1

I am trying to implement some discovery mechanism for a network device. The goal is for my application to discover a device on the network independent of the network configuration (IPv4).

My device is waiting for a UDP broadcast (255.255.255.255) on a fixed port and with fixed content. If the content matches, the device sends a broadcast (again to 255.255.255.255), which should be received by the PC.

Now my issue is on the PC side: The PC should send a broadcast on a specific network interface. For that, I bind the socket to a network address. On Windows this solution would work perfectly. But on Linux it seems to be more difficult. When I bind the socket to a network address, I couldn't receive any broadcast on it.

int ret;
this->port = port;

socketfd = socket(AF_INET, SOCK_DGRAM, 0);
if (socketfd < 0) {
    this->port = 0;
    return;
}

struct sockaddr_in bindAddr;
memset(&bindAddr, 0, sizeof(bindAddr));
bindAddr.sin_family = AF_INET;
bindAddr.sin_addr.s_addr = inet_addr("192.168.2.104");//ipV4;
bindAddr.sin_port = htons(port);
ret = bind(socketfd, (struct sockaddr *)&bindAddr, sizeof(bindAddr));

if (ret < 0) {
    int error = errno;
    this->port = 0;
    return;
}

int broadcastOpt = 1;
ret = setsockopt(socketfd, SOL_SOCKET, SO_BROADCAST, &broadcastOpt, sizeof(broadcastOpt));

if (ret < 0) {
    //int error = errno;
    this->port = 0;
    return;
}

I also found the sockopt SO_BINDTODEVICE, which is fine when I execute the application as root. But in the end this is not a solution for my application. Does anyone have an idea on how to bind the UDP Broadcast to a single network interface while also being able to receive any broadcasts on this interface?

tink
  • 14,342
  • 4
  • 46
  • 50
moudi
  • 478
  • 4
  • 17
  • Have you considered using a directed broadcast address as your destination? – Ben Voigt Jan 24 '19 at 14:54
  • Where `192.168.2.104` is coming from? – SergeyA Jan 24 '19 at 15:07
  • 1
    Have a look here: https://stackoverflow.com/a/1215424/5636775 – Ctx Jan 24 '19 at 15:09
  • Use two different sockets. One socket for listening for broadcast, bind to `IPADDR_ANY`. Second socket for sending broadcast, bind to specific interface. – Barmar Jan 24 '19 at 15:14
  • @Cid But the sockets API is the same. – Barmar Jan 24 '19 at 15:15
  • @SergeyA The IP `192.168.2.104`is just an example. I get them over `getifaddrs(..)` – moudi Jan 24 '19 at 18:19
  • @Ctx Thanks for the link. But it seems, that I can't select the interface on which the broadcast would be sent... At least on my current test, the message was just written to one interface, independent of the IP_PKTINFO settings. – moudi Jan 24 '19 at 18:44
  • @Barmar Really good idea! Is it possible to use two different sockets on the same port in UDP Broadcast? I would check out this solution. If them not sou, I would use two sockets on different ports and define two fix port number for read and write. – moudi Jan 24 '19 at 18:48
  • Take a look at the `SO_REUSEPORT` socket option, it might be useful. – Barmar Jan 24 '19 at 18:50
  • Do you need to use a specific source port when you send the broadcast? Usually only the destination port is important. – Barmar Jan 24 '19 at 18:51
  • So, I got it. Just for those which are interested on the solution: I did it with two socket. The device listen on a fix port for a discovery message. If one is received, the device send a response back to the computer. The convention which i use, is that the device response was sent to the source port from the computer, incremented by one. In this solution just the dedicated messages are received by the computer... Anyway: On the linux host side, I got also in touch with the 'rp_filter'. Set this to zero would pass all broadcast messages to the socket in the application... – moudi Feb 06 '19 at 15:01

0 Answers0