Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 18 Jun 2007 19:39:36 +0100
From:      "Bruce M. Simpson" <bms@incunabulum.net>
To:        "Bruce M. Simpson" <bms@incunabulum.net>
Cc:        Daniel Eischen <deischen@freebsd.org>, Ian FREISLICH <ianf@clue.co.za>, current@freebsd.org
Subject:   Re: Multicast problems [PATCH]
Message-ID:  <4676D168.3050502@incunabulum.net>
In-Reply-To: <4676C952.5000607@incunabulum.net>
References:  <E1I0E3b-0000kk-Ky@clue.co.za> <46765CB9.9020105@incunabulum.net>	<Pine.GSO.4.64.0706180833080.23884@sea.ntplx.net>	<4676C30E.7040300@incunabulum.net>	<Pine.GSO.4.64.0706181344060.24865@sea.ntplx.net> <4676C952.5000607@incunabulum.net>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------020002060800060906070808
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

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

--------------020002060800060906070808
Content-Type: text/plain;
 name="xmcast.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="xmcast.diff"

--- in_mcast.c.orig	Mon Jun 18 20:08:48 2007
+++ in_mcast.c	Mon Jun 18 20:36:33 2007
@@ -996,8 +996,16 @@
 
 		/*
 		 * 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);
@@ -1007,16 +1015,23 @@
 			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) {

--------------020002060800060906070808--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4676D168.3050502>