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--