Multicast packets sent to inappropriate sockets (patch)

William A.Carrel william.a at
Tue Oct 21 19:32:41 PDT 2003

	udp_input() in src/sys/netinet/udp_usrreq.c does not properly check
	inbound multicast packets to make sure they conform with memberships
	on a given socket before sending packets along to that socket.
	This can result in UDP multicast packets being erroneously delivered
	to sockets that should not be seeing them. Programs wishing to
	guarantee that a socket is only seeing packets on one interface must
	read in information about the interface configuration to try and
	determine whether the packet was legitimately delivered to it.
	This bug has been present since at least 4.4BSD-Lite and is present
	in all known BSD derivatives.  Problem reports are simultaneously
	being filed to FreeBSD, NetBSD, Darwin, DragonflyBSD and OpenBSD.
	I'll follow up to this PR with cross-references.
	A brief discussion of this issue and more details about it can be
	found in the freebsd-net mailing list under the subject
	"setsockopt IP_ADD_MEMBERSHIP not honored" around the date of this
	problem report.
	On a machine with two multicast interfaces, open two sockets and
	add them to the same multicast address but on different interfaces
	using setsockopt([sock], IP_ADD_MEMBERSHIP, sizeof(the_mreq),
	&the_mreq);  Inbound multicast packets to the requested multicast
	address on either interface will appear in both sockets, not just
	the requested one.
	See mailing list discussion for more information.
	Programs must either use sysctl or ioctl to gather information about
	the interface they want to be exclusively receiving multicast packets
	from or the kernel must be patched.  Patches follow for
	FreeBSD-STABLE.  (The new code may not be fully
	style(9) compliant, my apologies in advance.)
	The docontinue goto present in the stable patch is consistent with
	treatment for FreeBSD-CURRENT and reduces diffs to that code base.
=== FreeBSD RELENG_4 patch ===
--- udp_usrreq.c.orig	Tue Oct 21 17:22:09 2003
+++ udp_usrreq.c	Tue Oct 21 18:21:15 2003
@@ -279,8 +279,11 @@
 			if ((inp->inp_vflag & INP_IPV4) == 0)
-			if (inp->inp_lport != uh->uh_dport)
+			if (inp->inp_lport != uh->uh_dport) {
+		docontinue:
+			}
 			if (inp->inp_laddr.s_addr != INADDR_ANY) {
 				if (inp->inp_laddr.s_addr !=
@@ -291,6 +294,21 @@
 				    ip->ip_src.s_addr ||
 				    inp->inp_fport != uh->uh_sport)
+			}
+			/*
+			 * 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 (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+				int mshipno;
+				for (mshipno = 0; mshipno <= 
inp->inp_moptions->imo_num_memberships; ++mshipno) {
+					if (mshipno == inp->inp_moptions->imo_num_memberships)
+						goto docontinue;
+					if (ip->ip_dst.s_addr == 
inp->inp_moptions->imo_membership[mshipno]->inm_addr.s_addr && 
m->m_pkthdr.rcvif == 
+						break;
+				}

 			if (last != NULL) {
=== EOP ===

More information about the Bugs mailing list