在Linux上接收所有组播ICMPv6数据包

时间:2012-09-27 19:46:10

标签: linux network-programming ipv6 multicast

我希望收到所有到达特定接口的多播IPv6数据包,如果可能的话,不要求助于在第2层上运行。

我为原始ICMPv6数据包打开一个套接字,并且接收专用于我的机器的单播数据包工作正常。然而,许多ICMPv6分组是链路本地多播(例如,邻居请求)。监听所有组播流量的正确方法是什么,包括请求节点组播?目前我尝试使用IPV6_ADD_MEMBERSHIP添加多播组,但这似乎不起作用。这是我的代码:

/* 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");
}

我做错了什么?我想要的东西必须以某种方式。我尝试将ff02 ::和ff02 :: 1:ff00:0作为组,后者甚至使setsockopt失败。这是怎么回事?遗憾的是,关于IPv6多播编程的文档很少。

2 个答案:

答案 0 :(得分:0)

使用SOL_IPV6代替SOL_SOCKET

测试订阅ff80::1并使用ping6 -I eth0 ff08::1生成流量。

答案 1 :(得分:0)

毕竟这似乎是不可能的。我现在使用Linux的AF_PACKET套接字类型和“熟”模式(SOCKET_DGRAM)来访问带有链路层报头的原始IPv6数据包和BPF来过滤掉ICMPv6 ND数据包 - 至少我不需要处理解析以太网以这种方式标题,我可以更容易地支持其他链接层类型。