Skip to content
Advertisement

How to use the options to socket() for IPv6 multicast UDP?

I have a linux network interface that IPv6 multicast traffic is arriving on. There are both ICMPv6 packets and UDP packets arriving for the same multicast group.

I’m trying to receive the UDP traffic. The code below is in Python but I don’t believe this is important; the Python library here is a pretty thin wrapper around the BSD sockets API. This is what I’m doing:

JavaScript

With the code above, I appear to be receiving both the UDP and ICMPv6 packets. If I change the second parameter to socket.socket() from socket.SOCK_RAW to socket.SOCK_DGRAM then I receive no packets at all.

I’ve confirmed that both packet types are arriving on that interface, addressed to that multicast group, using wireshark.

There is something here that I’ve fundamentally not understood about socket(). Shouldn’t specifying IPPROTO_UDP mean that I only get UDP packets? Shouldn’t specifying SOCK_DGRAM still allow UDP packets through?

The Linux kernel is 4.9 on aarch64, in case that’s important.

Advertisement

Answer

Eventually figured this out. Here’s the correct way of doing this:

JavaScript

Important differences from the code in the question:

  • UDP (SOCK_DGRAM) sockets need to be bound to a port number. AFAICT this is why I was getting ICMP traffic as well as UDP with SOCK_RAW and no traffic at all with SOCK_DGRAM.
  • Instead of binding the socket to a unicast address on the interface of interest, bind it to the multicast group but use the interface index as the scope_id (the fourth in the address tuple passed to socket.bind()).
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement