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!