summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in_mcast.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/in_mcast.c')
-rw-r--r--sys/netinet/in_mcast.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index 0f0dc2d..4995800 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -996,8 +996,16 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
/*
* 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 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
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) {
OpenPOWER on IntegriCloud