Add a new sysctl knob, net.inet.udp.strict_mcast_mship, to the udp_input path.

This switch toggles between strict multicast delivery, and traditional
multicast delivery.

The traditional (default) behaviour is to deliver multicast datagrams to all
sockets which are members of that group, regardless of the network interface
where the datagrams were received.

The strict behaviour is to deliver multicast datagrams received on a
particular interface only to sockets whose membership is bound to that
interface.

Note that as a matter of course, multicast consumers specifying INADDR_ANY
for their interface get joined on the interface where the default route
happens to be bound. This switch has no effect if the interface which the
consumer specifies for IP_ADD_MEMBERSHIP is not UP and RUNNING.

The original patch has been cleaned up somewhat from that submitted. It has
been tested on a multihomed machine with multiple QuickTime RTP streams
running over the local switch, which doesn't do IGMP snooping.

PR:		kern/58359
Submitted by:	William A. Carrel
Reviewed by:	rwatson
MFC after:	1 week
This commit is contained in:
Bruce M Simpson 2003-11-12 20:17:11 +00:00
parent 5645e50570
commit 83453a06de

View File

@ -108,6 +108,10 @@ static int blackhole = 0;
SYSCTL_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW,
&blackhole, 0, "Do not send port unreachables for refused connects");
static int strict_mcast_mship = 0;
SYSCTL_INT(_net_inet_udp, OID_AUTO, strict_mcast_mship, CTLFLAG_RW,
&strict_mcast_mship, 0, "Only send multicast to member sockets");
struct inpcbhead udb; /* from udp_var.h */
#define udb6 udb /* for KAME src sync over BSD*'s */
struct inpcbinfo udbinfo;
@ -308,6 +312,30 @@ udp_input(m, off)
goto docontinue;
}
/*
* Check multicast packets to make sure they are only
* sent to sockets with multicast memberships for the
* packet's destination address and arrival interface
*/
#define MSHIP(_inp, n) ((_inp)->inp_moptions->imo_membership[(n)])
#define NMSHIPS(_inp) ((_inp)->inp_moptions->imo_num_memberships)
if (strict_mcast_mship && inp->inp_moptions != NULL) {
int mship, foundmship = 0;
for (mship = 0; mship < NMSHIPS(inp); mship++) {
if (MSHIP(inp, mship)->inm_addr.s_addr
== ip->ip_dst.s_addr &&
MSHIP(inp, mship)->inm_ifp
== m->m_pkthdr.rcvif) {
foundmship = 1;
break;
}
}
if (foundmship == 0)
goto docontinue;
}
#undef NMSHIPS
#undef MSHIP
if (last != NULL) {
struct mbuf *n;