3

I could not find a working example for this, so I am going to post a question (and let's see if I can reduce this to an MVP code example). So, I need to do mdns queries, I can use two sockets (one for sending / second for receiving) but so far I have not been able to make it work with a single socket.

So the steps that I am performing are:

Enumerate all the interface addresses on the host. Then for each host:

  1. Create a non blocking UDP socket
  2. bind() to either the interface address:5353 or the multicast group address (either of these cause either read or write to fail)
  3. Set IP_MULTICAST_IF to the local interface
  4. IP_ADD_MEMBERSHIP to the multicast group
  5. Add the sockets for read/write in kqueue

So depending on what I do in step 2 either read or write fails:

  1. If I bind the socket to the multicast group I get read notifications from the kqueue and can read packets, but when I get a write notification from the kqueue and try to write it fails with errno 49
  2. If I bind the socket to the interface address I can send the packets but no read notifications ever arrive from the kqueue

So which address I need to bind to then? Also, since the IP_ADD_MEMBERSHIP parameter ip_mreq has the interface field, do I really need the IP_MULTICAST_IF?

dbush
  • 205,898
  • 23
  • 218
  • 273
Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71

1 Answers1

5

If you bind to a specific interface address (on Linux at least), you'll be unable to receive multicast. If you bind to a multicast address, you can't send.

What you need to do is bind to INADDR_ANY, then when you set the IP_ADD_MEMBERSHIP option, you set the interface address that you want to receive multicast packets on. If you have multiple interfaces, you can call this for each interface you want to bind to.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Will try this out right now. Just one clarification - when you say " you have multiple interfaces, you can call this for each interface you want to bind to" you still mean separate sockets, or can I actually do this with a single ocket and multiple IP_ADD_MEMBERSHIP calls on it ? – Rudolfs Bundulis Mar 26 '20 at 19:16
  • 1
    @RudolfsBundulis One socket, multiple `IP_ADD_MEMBERSHIP` calls, once for each interface. – dbush Mar 26 '20 at 19:37
  • thanks, doing as you suggested helped. Ok, one last thing - one of the ideas of using multiple sockets was the ability to know that a network interface has been brought down (i was expecting to get an epoll/kqueue error event in that case). Not sure if that happens, but if it does, how does bringing down an interface affect a socket that has joined multiple groups? – Rudolfs Bundulis Mar 26 '20 at 20:30
  • Ok just checked that bringing the interfaces up/down does not cause an error so I will have to handle that separately. – Rudolfs Bundulis Mar 26 '20 at 21:12