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

在Linux上接收所有多播ICMPv6数据包,linux,network-programming,ipv6,multicast,Linux,Network Programming,Ipv6,Multicast,我想接收到达某个接口的所有多播IPv6数据包,如果可能的话,无需在第2层上操作 我为原始ICMPv6数据包打开一个套接字,然后接收专用于我的机器的单播数据包就可以了。然而,许多ICMPv6数据包是链路本地多播,例如邻居请求。侦听所有多播流量(包括请求的节点多播)的正确方法是什么?目前,我尝试添加一个具有IPV6_add_成员身份的多播组,但这似乎不起作用。这是我的密码: /* open RAW socket to receive on */ if ((sockfd = socket(AF_INE

我想接收到达某个接口的所有多播IPv6数据包,如果可能的话,无需在第2层上操作

我为原始ICMPv6数据包打开一个套接字,然后接收专用于我的机器的单播数据包就可以了。然而,许多ICMPv6数据包是链路本地多播,例如邻居请求。侦听所有多播流量(包括请求的节点多播)的正确方法是什么?目前,我尝试添加一个具有IPV6_add_成员身份的多播组,但这似乎不起作用。这是我的密码:

/* 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多播编程的文档很少。

使用SOL_IPv6而不是SOL_SOCKET


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

这似乎毕竟是不可能的。我现在使用Linux的AF_数据包套接字类型和熟模式套接字(Cook mode socket_DGRAM)访问带有链路层头的原始IPv6数据包,并使用BPF过滤掉ICMPv6 ND数据包-至少我不需要以这种方式解析以太网头,而且我可能更容易支持其他链路层类型。

Yes,这是我指定的多播地址的一部分。对不起,我不明白你在说什么。范围ID在此不相关;它们的作用是发送数据包,而不是接收数据包。这里重要的只是接口,而且设置正确。UDP?!我想接收ICMPv6数据包。那根本不是UDP!我必须使用原始套接字来处理ICMPv6。为什么IPv6多播不能与原始套接字一起工作?这在哪里有记录?相反,我的消息来源说它只适用于DGRAM和原始套接字。顺便说一句:如果你想知道上面的断章取义的评论,我回复了一个现在决定删除他或她的评论的人。叹气。这适用于特定的多播组,但我需要从所有请求的节点多播组接收流量。这是2^24个组,要将它们全部添加到一起肯定不太实际。我甚至试过这么做,因为这就是多播的工作原理:网络基础设施需要IGMP订阅才能转发流量。对于本地链路流量,您可以尝试使用PF_数据包,但您可能仍然需要一些交换机重新配置或基本上使用集线器。好的,我只对实际到达机器上的多播流量感兴趣,一般来说,这至少是所有链路本地多播。事实上,我在最初的帖子中写过。根本不涉及IGMP或IPv6等效协议。