aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorBruce M Simpson <bms@FreeBSD.org>2007-07-09 10:36:47 +0000
committerBruce M Simpson <bms@FreeBSD.org>2007-07-09 10:36:47 +0000
commitd90b8675c299e3931ad6534c76cb02760c3af273 (patch)
tree940a10664e03182d81af18435e890808935e19d4 /sys/netinet
parent2dc26b36c8759368bcb06d5870099082efd7dd5e (diff)
downloadsrc-d90b8675c299e3931ad6534c76cb02760c3af273.tar.gz
src-d90b8675c299e3931ad6534c76cb02760c3af273.zip
Fix a regression in IPv4 multicast join path (IP_ADD_MEMBERSHIP).
With the in_mcast.c code, if an interface for an IPv4 multicast join was not specified, and a route did not exist for the specified group in the unicast forwarding tables, the join would be rejected with the error EADDRNOTAVAIL. This change restores the old behaviour whereby if no interface is specified, and no route exists for the group destination, the IPv4 address list is walked to find a non-loopback, multicast-capable interface to satisfy the join request. This should resolve problems with starting multicast services during system boot or when a default forwarding entry does not exist. Approved by: re (rwatson)
Notes
Notes: svn path=/head/; revision=171317
Diffstat (limited to 'sys/netinet')
-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 0f0dc2d12a44..4995800c24bd 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) {