Subject: various IPv6 multicast sockopts broken
To: None <tech-net@netbsd.org>
From: Matthias Drochner <M.Drochner@fz-juelich.de>
List: tech-net
Date: 12/18/2004 13:48:16
This is a multipart MIME message.
--==_Exmh_5287332431240
Content-Type: text/plain; charset=us-ascii
Hi -
tracking down why some ntp configurations involving
IPv6 multicasts don't work anymore I found that some
changes to setsockopt argument checking broke it.
The immediate reason for the NTP failure is that a
IPV6_JOIN_GROUP with a zero ipv6mr_interface doesn't
work anymore. (zero is a legal value meaning that
"the default multicast interface" is used; in practice
this means that the routing code picks one)
Code inspection shows that IPV6_LEAVE_GROUP and
IPV6_MULTICAST_IF are broken in similar ways.
The appended patch should fix it. (I've only
verified the JOIN_GROUP with ntpd.)
Would someone please have a look at it, just to be sure?
Wouldn't it be better to put all accesses to
the index2ifnet[] array into a function?
best regards
Matthias
--==_Exmh_5287332431240
Content-Type: text/plain ; name="ip6mc.txt"; charset=us-ascii
Content-Description: ip6mc.txt
Content-Disposition: attachment; filename="ip6mc.txt"
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.86
diff -u -r1.86 ip6_output.c
--- netinet6/ip6_output.c 4 Dec 2004 16:10:25 -0000 1.86
+++ netinet6/ip6_output.c 17 Dec 2004 12:31:59 -0000
@@ -1809,16 +1809,19 @@
break;
}
bcopy(mtod(m, u_int *), &ifindex, sizeof(ifindex));
- if (ifindex < 0 || if_indexlim <= ifindex ||
- !ifindex2ifnet[ifindex]) {
- error = ENXIO; /* XXX EINVAL? */
- break;
- }
- ifp = ifindex2ifnet[ifindex];
- if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
- error = EADDRNOTAVAIL;
- break;
- }
+ if (ifindex != 0) {
+ if (ifindex < 0 || if_indexlim <= ifindex ||
+ !ifindex2ifnet[ifindex]) {
+ error = ENXIO; /* XXX EINVAL? */
+ break;
+ }
+ ifp = ifindex2ifnet[ifindex];
+ if ((ifp->if_flags & IFF_MULTICAST) == 0) {
+ error = EADDRNOTAVAIL;
+ break;
+ }
+ } else
+ ifp = NULL;
im6o->im6o_multicast_ifp = ifp;
break;
@@ -1887,18 +1890,18 @@
/*
* If the interface is specified, validate it.
- */
- if (mreq->ipv6mr_interface < 0 ||
- if_indexlim <= mreq->ipv6mr_interface ||
- !ifindex2ifnet[mreq->ipv6mr_interface]) {
- error = ENXIO; /* XXX EINVAL? */
- break;
- }
- /*
* If no interface was explicitly specified, choose an
* appropriate one according to the given multicast address.
*/
- if (mreq->ipv6mr_interface == 0) {
+ if (mreq->ipv6mr_interface != 0) {
+ if (mreq->ipv6mr_interface < 0 ||
+ if_indexlim <= mreq->ipv6mr_interface ||
+ !ifindex2ifnet[mreq->ipv6mr_interface]) {
+ error = ENXIO; /* XXX EINVAL? */
+ break;
+ }
+ ifp = ifindex2ifnet[mreq->ipv6mr_interface];
+ } else {
/*
* If the multicast address is in node-local scope,
* the interface should be a loopback interface.
@@ -1923,8 +1926,7 @@
ifp = ro.ro_rt->rt_ifp;
rtfree(ro.ro_rt);
}
- } else
- ifp = ifindex2ifnet[mreq->ipv6mr_interface];
+ }
/*
* See if we found an interface, and confirm that it
@@ -1989,13 +1991,16 @@
* If an interface address was specified, get a pointer
* to its ifnet structure.
*/
- if (mreq->ipv6mr_interface < 0 ||
- if_indexlim <= mreq->ipv6mr_interface ||
- !ifindex2ifnet[mreq->ipv6mr_interface]) {
- error = ENXIO; /* XXX EINVAL? */
- break;
- }
- ifp = ifindex2ifnet[mreq->ipv6mr_interface];
+ if (mreq->ipv6mr_interface != 0) {
+ if (mreq->ipv6mr_interface < 0 ||
+ if_indexlim <= mreq->ipv6mr_interface ||
+ !ifindex2ifnet[mreq->ipv6mr_interface]) {
+ error = ENXIO; /* XXX EINVAL? */
+ break;
+ }
+ ifp = ifindex2ifnet[mreq->ipv6mr_interface];
+ } else
+ ifp = NULL;
/*
* Put interface index into the multicast address,
* if the address has link-local scope.
--==_Exmh_5287332431240--