Re: Multicast problems [PATCH]

From: Bruce M. Simpson <bms_at_incunabulum.net>
Date: Mon, 18 Jun 2007 19:39:36 +0100
Bruce M. Simpson wrote:
>
> The condition we've seen is a side-effect of ip_multicast_if() being 
> removed. Support for scoped addresses in the IPv4 stack will mean this 
> code has to change again.

Here is a patch which explicitly looks for an interface supporting 
multicast, if no default route exists. The KASSERT should only be 
triggered if the routing trie code is broken; it is still possible for 
the last-resort interface lookup to fail if no loopback interface 
exists, if none of the interfaces have IPv4 addresses, or if no 
interfaces in the system support multicast.

regards,
BMS

--- in_mcast.c.orig	Mon Jun 18 20:08:48 2007
+++ in_mcast.c	Mon Jun 18 20:36:33 2007
_at__at_ -996,8 +996,16 _at__at_
 
 		/*
 		 * Obtain ifp. If no interface address was provided,
-		 * use the interface of the route to the given multicast
-		 * address (usually this is the default route).
+		 * use the interface of the route in the unicast FIB for
+		 * the given multicast destination; usually, this is the
+		 * default route.
+		 * If this lookup fails, attempt to use the first non-loopback
+		 * interface with multicast capability in the system as a
+		 * last resort. The legacy IPv4 ASM API requires that we do
+		 * this in order to allow groups to be joined when the routing
+		 * table has not yet been populated during boot.
+		 * If all of these conditions fail, return EADDRNOTAVAIL, and
+		 * reject the IPv4 multicast join.
 		 */
 		if (mreqs.imr_interface.s_addr != INADDR_ANY) {
 			INADDR_TO_IFP(mreqs.imr_interface, ifp);
_at__at_ -1007,16 +1015,23 _at__at_
 			ro.ro_rt = NULL;
 			*(struct sockaddr_in *)&ro.ro_dst = gsa->sin;
 			rtalloc_ign(&ro, RTF_CLONING);
-			if (ro.ro_rt == NULL) {
-#ifdef DIAGNOSTIC
-				printf("%s: no route to %s\n", __func__,
-				    inet_ntoa(gsa->sin.sin_addr));
-#endif
-				return (EADDRNOTAVAIL);
+			if (ro.ro_rt != NULL) {
+				ifp = ro.ro_rt->rt_ifp;
+				KASSERT(ifp != NULL, ("%s: null ifp",
+				    __func__));
+				RTFREE(ro.ro_rt);
+			} else {
+				struct in_ifaddr *ia;
+				struct ifnet *mfp = NULL;
+				TAILQ_FOREACH(ia, &in_ifaddrhead, ia_link) {
+					mfp = ia->ia_ifp;
+					if (!(mfp->if_flags & IFF_LOOPBACK) &&
+					     (mfp->if_flags & IFF_MULTICAST)) {
+						ifp = mfp;
+						break;
+					}
+				}
 			}
-			ifp = ro.ro_rt->rt_ifp;
-			KASSERT(ifp != NULL, ("%s: null ifp", __func__));
-			RTFREE(ro.ro_rt);
 		}
 #ifdef DIAGNOSTIC
 		if (bootverbose) {
Received on Mon Jun 18 2007 - 16:39:46 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:12 UTC