I would like to receive all multicast IPv6 packets arriving on a certain interface, without resorting to operate on layer 2, if that is possible.
I open a socket for raw ICMPv6 packets, and receiving unicast packets dedicated for my machine works just fine. However many ICMPv6 packets are link-local multicast (e.g. neighbor solicitations). What’s the right way to listen for all multicast traffic, including solicited-node multicast? Currently I try to add a multicast group with IPV6_ADD_MEMBERSHIP, but this does not seem to work. Here’s my code:
/* open RAW socket to receive on */
if ((sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
perror("socket");
}
/* get device index */
memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, DEVNAME, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) {
perror("SIOCGIFINDEX");
}
/* configure to receive all multicast packets on this interface */
memset(&mreq, 0, sizeof(struct ipv6_mreq));
inet_pton(AF_INET6, "ff02::", &mreq.ipv6mr_multiaddr);
mreq.ipv6mr_interface = if_idx.ifr_ifindex;
if (setsockopt(sockfd, SOL_SOCKET, IPV6_ADD_MEMBERSHIP, &mreq,
sizeof(struct ipv6_mreq)) < 0) {
perror("setsockopt");
}
What am I doing wrong? What I want must be possible somehow. I tried ff02:: and ff02::1:ff00:0 as groups, and the latter even made setsockopt fail. What’s going on? Unfortunately there’s very little documentation on IPv6 multicast programming.
This appears to be impossible after all. I am now using Linux’s AF_PACKET socket type with “cooked” mode (SOCKET_DGRAM) to access the raw IPv6 packets with link-layer header and a BPF to filter out ICMPv6 ND packets – at least I won’t need to deal with parsing the ethernet header this way, and I can possibly support other link-layer types more easily.