I am dealing with an old codebase, in which ipv6 multicast does not seem to work. When I try to bind() the socket to ff01::1, it fails. The socket is being created in my ethernet interface.
Binding the socket to in6addr_any, which is "::", results in a successful bind, but no packet is ever received, except for the ones being send by the application itself, using the given socket (IPV6_MULTICAST_LOOP is set). These packets never seem to leave the application either. They are not visible in wireshark when trying to capture packets in the ethernet interface. Only the incoming outside multicast packets are visible. None of them reach my application.
System is Ubuntu 16.04 with Linux 4.4.0.
A sample of the setup code:
#define MCASTADDRC "ff01::1"
int mcast::bind_mcast(const char *interface) {
this->net = socket(AF_INET6, SOCK_DGRAM, 0);
inet_pton(AF_INET6,MCASTADDRC,&this->multicast.ipv6mr_multiaddr);
this->ifaceaddr.sin6_family = AF_INET6;
this->ifaceaddr.sin6_port = htons(SRVPORT);
this->ifaceaddr.sin6_addr = in6addr_any;
// interface for multicast
this->mcastaddr.sin6_family = AF_INET6;
this->mcastaddr.sin6_port = htons(SRVPORT);
this->mcastaddr.sin6_addr = this->multicast.ipv6mr_multiaddr;
int opcoes = fcntl(this->net, F_GETFL, 0);
if ( fcntl(this->net, F_SETFL, opcoes | O_NONBLOCK) == -1 ) {
// fail
return(false);
}
if (bind(net, (struct sockaddr *) &this->ifaceaddr, sizeof(this->ifaceaddr)) == -1 ) {
// fail
return(false);
}
this->ifaceindex = if_nametoindex(interface);
this->multicast.ipv6mr_interface = this->ifaceindex;
this->ifaceaddr.sin6_scope_id = this->ifaceindex;
int mcast_loop = 1;
if (setsockopt(this->net, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &mcast_loop, sizeof(mcast_loop))) {
//fail
return(false);
}
if (setsockopt(this->net, IPPROTO_IPV6, IPV6_MULTICAST_IF, &this->ifaceindex, sizeof(this->ifaceindex))) {
//fail
return(false);
}
if (setsockopt(this->net, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &this->multicast, sizeof(this->multicast))) {
//fail
return(false);
}
int optval = 6000000;
int optlen = sizeof(optval);
if (setsockopt(this->net, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))) {
exit(0);
}
if (getsockopt(this->net, SOL_SOCKET, SO_RCVBUF, &optval, (socklen_t *)&optlen)) {
// fail
exit(0);
}
if(optval < 262142) {
// buffer is too small, we failed
exit(0);
}
return(true); // success
}
Bits 12-15 (starting at 0) in an IPv6 multicast address specifies the multicast scope.
A multicast address of the the form ff01::/16
has a scope of 1 which means interface local. Such packets may not be sent over any network link. That's why you can't receive any packets with an address like this from other hosts.
You need to use an address with a different scope value. A scope of 2
may be sent over the local network but not across routers, while a scope of e
(15) is globally routeable.
Also, run netstat -ng
when your program is running to ensure that you've joined the proper multicast group on the proper interface.
See the Wikipedia page for multicast addresses for more details.