Multicast packets sent to inappropriate sockets (patch)
William A. Carrel
william.a at carrel.org
Sat Oct 25 10:24:59 PDT 2003
The FreeBSD folks have apparently had a some amount of trepidation
surrounding the patch I presented on this issue. The old behavior dates
back to BSD4.3. Tradition.
Anyway, I've made a new patch which I hope you'll consider.
(a) provides a sysctl to toggle between the traditional BSD4.3 handling
and the Solaris-style strict membership handling implied by man ip(4)
and UNPv1.
(b) solves a kernel panic in the first patch
And with the new behavior enabled with the sysctl this will prevent
unicast listeners from getting multicast traffic delivered to them if
they are not multicast-aware (i.e. if they don't actually have any mcast
memberships). This means that if some socket on your system is
listening to a multicast address, this patch (when enabled) will prevent
your nfsd from seeing traffic to multicast-address:2049, which it would
otherwise receive.
The patch follows. Be sure to let me know if you have any concerns or
questions. Thanks for reading.
--- freebsd_stable_udp_usrreq.c.orig Fri Oct 24 12:35:46 2003
+++ freebsd_stable_udp_usrreq.c Fri Oct 24 23:22:01 2003
@@ -102,6 +102,10 @@
SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
&blackhole, 0, "Do not send port unreachables for refused connects");
+static int strict_mcast_mship = 0;
+SYSCTL_INT(_net_inet_udp, OID_AUTO, strict_mcast_mship, CTLFLAG_RW,
+ &strict_mcast_mship, 0, "Only send multicast to member sockets");
+
struct inpcbhead udb; /* from udp_var.h */
#define udb6 udb /* for KAME src sync over BSD*'s */
struct inpcbinfo udbinfo;
@@ -290,6 +294,27 @@
if (inp->inp_faddr.s_addr !=
ip->ip_src.s_addr ||
inp->inp_fport != uh->uh_sport)
+ continue;
+ }
+ /*
+ * Check multicast packets to make sure they are only
+ * sent to sockets with multicast memberships for the
+ * packet's destination address and arrival interface
+ */
+ if (strict_mcast_mship &&
+ IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) &&
+ inp->inp_moptions != NULL) {
+ int mshipno;
+
+ for (mshipno = 0;
+ mshipno <=
+ inp->inp_moptions->imo_num_memberships;
+ ++mshipno) {
+ if (ip->ip_dst.s_addr ==
inp->inp_moptions->imo_membership[mshipno]->inm_addr.s_addr &&
m->m_pkthdr.rcvif == inp->inp_moptions->imo_membership[mshipno]->inm_ifp)
+ break;
+ }
+ if (mshipno ==
+ inp->inp_moptions->imo_num_memberships)
continue;
}
More information about the Bugs
mailing list