Subject: kern/23221: setsockopt IP_ADD_MEMBERSHIP arguments not honored
To: None <tech-net@netbsd.org>
From: William A. Carrel <william.a@carrel.org>
List: tech-net
Date: 10/23/2003 19:23:26
I'm posting here to try and drive some action to a PR I have filed
regarding the handling of IPv4 multicast traffic in BSD4.4-Lite based
operating systems.
There is an error in handling incoming packets in udp4_realinput()
(src/sys/netinet/udp_usrreq.c at line 582). Inbound multicast packets
on any interface listening to a given multicast address are passed to
every socket listening to that address. This behavior is inconsistent
with the documentation in ip(4)s manpage and with the description given
in UNP Vol. 1 (Stevens) at page 496.
To back up and demonstrate the problem, programs wishing to recieve
traffic to a multicast address on some socket need to make a call to
setsockopt(2) to IP_ADD_MEMBERSHIP to a multicast address. That
membership request contains both the multicast address they want
membership to and, more importantly to the issue at hand, an IPv4
address on the interface they want get the multicast traffic from.
(Using INADDR_ANY will give them some default interface chosen by the
kernel, generally the interface with the route for the multicast
address.)
That socket should only ever be seeing multicast traffic from the
interface they have asked for. But, unfortunately, with the current
coding, if another socket is opened and has membership for the same
multicast address but on a different interface, both sockets will get a
copy of the multicast addresses traffic from both interfaces. Worse
yet, the second socket doesn't even need to be opened by the same
process for this effect to occur.
To make that description more concise here is a scenario:
if0 is 1.2.3.4, if1 is 5.6.7.8
pid20 opens a socket and adds membership to 224.0.0.50 on if0
pid30 opens a socket and adds membership to 224.0.0.50 on if1
A packet to 224.0.0.50 arrives on if1, it is delivered to both pid20 and
pid30 socket.
A packet to 224.0.0.50 arrives on if0, it also is delivered to both
processes.
The patch I've provided forces a check on multicast traffic to make sure
that it arrived on the interface for which a socket holds a membership
before it is delivered to the socket. It should completely resolve this
issue.
Further dicussion on this issue is welcome. A brief discussion of this
issue occurred on the freebsd-net list recently, it is referenced in the
PR. This error in delivery occurs in all BSD 4.4-Lite derived code and
also in Linux and quite possibly in any number of commercial operating
systems that have borrowed from the 4.4-Lite IPv4 stack.
Thanks for reading!