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>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
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
[-- Attachment #2 --]
--- 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) {
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4676D168.3050502>
