0

The problem is the following: I want to identify a set of network services in my LAN. I know that all capable devices respond to an UDP broadcast message on port 60128. In order to identify them I wrote the following first test:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#define BUFLEN 256
int main(int argc, const char *argv[]){
  struct sockaddr_in myaddr, remaddr;
  int fd, i, slen=sizeof(remaddr);
  char buf[BUFLEN]; /* message buffer */
  int recvlen;      /* # bytes in acknowledgement message */
  /* create a socket */
  if ((fd=socket(AF_INET, SOCK_DGRAM, 0))==-1)
    printf("socket created\n");
  int broadcast=1;
  if (setsockopt(fd,SOL_SOCKET,SO_BROADCAST, &broadcast,sizeof(broadcast))==-1) {
    printf("%s",strerror(errno));
    return -1;
  } 
  unsigned char v2 = 0;
  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &v2,   sizeof(v2)) == -1){
    printf("%s",strerror(errno));
    return -1;
  }
  /* bind it to all local addresses*/
  memset((char *)&myaddr, 0, sizeof(myaddr));
  myaddr.sin_family = AF_INET;
  myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  myaddr.sin_port = htons(60128);

  if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
    perror("bind failed");
    return 0;
  }        

  /* Prepare Broadcast */
  memset((char *) &remaddr, 0, sizeof(remaddr));
  remaddr.sin_family = AF_INET;
  remaddr.sin_port = htons(60128);
  remaddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);

  char *packet = "Test";
  size_t plen = strlen(packet);

  /* now let's broadcast the messages */
  if (sendto(fd, packet, plen, 0, (struct sockaddr *)&remaddr, slen)==-1) {
    perror("sendto");
    exit(1);
  }
  while(1) {
    fd_set fdset;
    FD_ZERO( &fdset );
    FD_SET( fd, &fdset );
    struct timeval tv_timeout = { 5 , 0 };
    int select_retval = select( fd+1, &fdset, NULL, NULL, &tv_timeout );
    printf("select: %d\n", select_retval);
    if ( select_retval < 0 ) {
        printf("Error\n");
        break;  
    }
    if ( select_retval == 0) {
        printf("No additional response\n");
        break;
    }
    if ( FD_ISSET( fd, &fdset ) ) {
        recvlen = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&remaddr, &slen);
        if (recvlen >= 0) {
                        buf[recvlen] = 0;   
                        printf("received message(%s): \"%s\"\n",inet_ntoa(remaddr.sin_addr),buf);
                }
    }
  }
  close(fd);
  return 0;
}

When I now start the program I get the following: All answers from the enabled devices and an answer from the program itself. Assume that my computer has the IP "192.168.0.102" then the following is included in the output (although the necessary daemon for the service is not running on my PC):

received message(192.168.0.102): "Test"

Is there a way to filter out the sender of the broadcast without checking each answer separately to see if the sender's IP is my own one?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
M.K. aka Grisu
  • 2,338
  • 5
  • 17
  • 32
  • possible duplicate: https://stackoverflow.com/questions/1762101/how-to-ignore-your-own-broadcast-udp-packets – Michael Sep 08 '17 at 20:31

1 Answers1

0

This is called 'loopback', and there is a setsockopt() option to disable it.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    I added `unsigned char v2 = 0; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &v2, sizeof(v2)) == -1){ printf("%s",strerror(errno)); return -1; }´ directly after I set the broadcast flag and I still get the same result, so nothing changed and the program still receives its own packet. – M.K. aka Grisu Nov 29 '14 at 12:01