Multicast packets sent to inappropriate sockets (patch)
William A.Carrel
william.a at carrel.org
Tue Oct 21 19:32:41 PDT 2003
Description:
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.
How-To-Repeat:
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.
Fix:
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)
continue;
#endif
- if (inp->inp_lport != uh->uh_dport)
+ if (inp->inp_lport != uh->uh_dport) {
+ docontinue:
continue;
+ }
+
if (inp->inp_laddr.s_addr != INADDR_ANY) {
if (inp->inp_laddr.s_addr !=
ip->ip_dst.s_addr)
@@ -291,6 +294,21 @@
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 (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 ==
inp->inp_moptions->imo_membership[mshipno]->inm_ifp)
+ break;
+ }
}
if (last != NULL) {
=== EOP ===
More information about the Bugs
mailing list