I've been working on a miniature multicast routing program and am
encountering some troubles with getting setsockopt(2) to create the
right behavior.
I pass in
setsockopt(the_sock, IP_ADD_MEMBERSHIP, &the_mreq);
with the_mreq having in_addr's for the link-local multicast channel I'm
interested in and the primary address of the interface I want the
socket to receive packets from. (Inside the setsockopt path the second
address is translated into an ifp for the interface that address is
on.)
I have two such sockets set up, one on each of the interfaces I'm
interested in. The problem is that a packet that comes in on one
interface winds up in the receive queue for both sockets. Both the
queue for the socket that has the membership on the interface I care
about, and the receive queue for the socket that has the membership on
the other interface.
My reading of UNP vol. 1 (pg. 496) and the ip(4) man page would imply
that this is not the correct behavior for a multicast membership that
was tied to a specific interface. This means that new processes that
add membership to the multicast address on a new interface can cause
older processes to receive packets on that interface that they did not
intend to read.
The code involved in the decision
(src/sys/netinet/udp_usrreq.c:268-332) has been around a while so I'm
loathe to change it willy-nilly.
To get the behavior I'm thinking of would involve checking to make sure
that the packet came in on the interface that the inp's multicast
membership is associated with. Essentially, checking
(ip->ip_dst.s_addr, m->m_pkthdr.rcvif) against the values
(inp->inp_moptions->imo_membership[]->inm_addr.s_addr,
inp->inp_moptions->imo_membership[]->inm_ifp)
The following code snippet illustrates what I'm thinking for
udp_usrreq.c...
/*
* Check multicast packets to make sure they are only sent to sockets
with
* multicast memberships on the same interface the packet arrived on
*/
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;
}
}
I think this would bring the operation of the IP_ADD_MEMBERSHIP sockopt
back into line with the documentation. Anyone have any thoughts on
this?
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"
- Re: setsockopt IP_ADD_MEMBERSHIP not honored William A . Carrel
- Re: setsockopt IP_ADD_MEMBERSHIP not honored Joshua Graessley
- Re: setsockopt IP_ADD_MEMBERSHIP not honored William A . Carrel
- Re: setsockopt IP_ADD_MEMBERSHIP not honor... Joshua Graessley
- kern/58359 (was: setsockopt IP_ADD_MEM... William A . Carrel
- setsockopt IP_ADD_MEMBERSHIP not honored sammy davis