我创建了一个网络设备,可以多播dev->flags = IFF_MULTICAST。
我发送了 UDP 消息,但是当我收到数据包时,我没有收到 udp 消息,系统跟踪是
ipv6_rcv()
|--> ip6_route_input()
|-->ip6_mc_input()
函数 ip6_mc_input() 中 ipv6_chk_mcast_addr() 返回的值为 0。我想我需要在mc_list中添加多播地址 ff02::2。
这是真的吗?
我该怎么做?
谢谢。
您需要加入多播组才能在其上接收流量。 IFF_MULTICAST
标志表示您的设备(驱动程序)支持多播。 当系统想要加入或离开多播组时,驱动程序应配置硬件(通常只是一个筛选器)。
由于您正在将数据包传递到堆栈中,因此默认情况下您的硬件非常混杂,或者您以某种方式配置了硬件过滤器,而系统尚未加入多播组。
无论情况如何,为了使ipv6_chk_mcast_addr()
成功,您必须加入目标多播组。 在用户空间中,您将通过IP_ADD_MEMBERSHIP
setsockopt()
调用执行此操作。 由于您对全路由器组播组 (ff02::2) 感兴趣,我相信(但不确定)当您配置转发时,内核将自动加入它。
我终于解决了我的问题。我需要做一个这样的插座。
if ((sockEnvio = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP))){
printf("socket() failed");
}
// Bind the socket to the interface we're interested in
int err=0;
memset(&server, 0, sizeof(server));
server.sin6_family = AF_INET6;
server.sin6_scope_id = if_nametoindex("eth2");
server.sin6_port = htons(15118);
err = bind(sockEnvio, (struct sockaddr *)&server, sizeof(server));
if (err < 0) {
perror("packet socket bind return failed:");
close(sockEnvio);
}
printf("ICMPv6 socket bind to interface %d OK", if_nametoindex("eth2")); //if_nametoindex(lan));
int optval = 1;
if (setsockopt(sockEnvio, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval, sizeof(optval)) < 0) {
perror("Error! setsockopt(IPV6_RECVPKTINFO)");
close(sockEnvio);
}
optval = 0;
if (setsockopt(sockEnvio, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &optval, sizeof(optval)) <0 ) {
perror("Error! setsockopt(IPV6_MULTICAST_LOOP)");
close(sockEnvio);
}
struct ipv6_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.ipv6mr_interface = if_nametoindex("eth2");
mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xff;
mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
mreq.ipv6mr_multiaddr.s6_addr[15] = 0x02;
if (setsockopt(sockEnvio, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
perror("Error! setsockopt(IPV6_ADD_MEMBERSHIP, ff02::02)");
close(sockEnvio);
}