EADDRNOTAVAIL when resetting IPv6 multicast interface
EADDRNOTAVAIL when resetting IPv6 multicast interface
- Subject: EADDRNOTAVAIL when resetting IPv6 multicast interface
- From: Saúl Ibarra Corretgé <email@hidden>
- Date: Wed, 26 Mar 2014 22:13:25 +0100
Hi,
(Disclaimer: it's my first post to the list. I found no previous reports
of this problem, apologies in advance if I managed to miss them.)
While working on a platform abstraction library I've ran into what looks
like a bug in the XNU kernel when setting the IPv6 multicast interface
to the default value using the IPV6_MULTICAST_IF option with setsockopt.
>From the manual page:
"IPV6_MULTICAST_IF u_int *
Get or set the interface from which multicast packets will be sent.
For hosts with multiple interfaces, each multicast transmission is sent
from the primary network interface. The interface is specified as its
index as provided by if_nametoindex(3). A value of zero specifies the
default interface."
However, when passing 0 in order to reset to the default value,
EADDRNOTAVAIL happens.
The attached file (test-multicast-if.c) demonstrates the problem. I
tested it on OSX 10.6.8 and 10.9.3 with the same result.
I had a look at the XNU source for version 2422.1.72 and made a small
(untested) patch (see ipv6-multicast-if.diff) which I think would solve
the issue.
The same problem manifests when trying to join a multicast group using
IPV6_JOIN_GROUP when the ipv6mr_interface field of struct ipv6_mreq is
set to 0.
Kind regards,
--
Saúl Ibarra Corretgé
bettercallsaghul.com
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#define IFACE "lo0"
int set_multicast_if(int fd, int index)
{
int opt;
int optlen;
opt = index;
optlen = sizeof(opt);
return setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &opt, optlen);
}
int get_multicast_if(int fd)
{
int opt;
int optlen;
optlen = sizeof(opt);
if (getsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &opt, &optlen) == 0)
return opt;
return -1;
}
int main(int argc, const char *argv[])
{
int index;
int fd;
int r;
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd == -1) {
perror("creating socket");
abort();
}
/* get default index value */
r = get_multicast_if(fd);
if (r < 0) {
perror("getting default interface");
abort();
}
assert(r == 0);
index = if_nametoindex(IFACE);
assert(index > 0);
/* set new interface index value */
r = set_multicast_if(fd, index);
if (r < 0) {
perror("setting interface");
abort();
}
/* get current index value */
r = get_multicast_if(fd);
if (r < 0) {
perror("getting interface");
abort();
}
assert(r == index);
/* set index value back to default */
r = set_multicast_if(fd, 0);
if (r < 0) {
perror("setting interface");
abort();
}
/* get current index value */
r = get_multicast_if(fd);
if (r < 0) {
perror("getting interface");
abort();
}
assert(r == 0);
return 0;
}
--- bsd/netinet6/in6_mcast.c.orig 2014-03-26 21:48:29.847976899 +0100
+++ bsd/netinet6/in6_mcast.c 2014-03-26 21:52:04.823969044 +0100
@@ -2616,7 +2616,7 @@
ifp = ifindex2ifnet[ifindex];
ifnet_head_done();
- if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
+ if (ifp != NULL && (ifp->if_flags & IFF_MULTICAST) == 0)
return (EADDRNOTAVAIL);
imo = in6p_findmoptions(inp);
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden