summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/udp6_usrreq.c
diff options
context:
space:
mode:
authorbms <bms@FreeBSD.org>2009-04-29 19:19:13 +0000
committerbms <bms@FreeBSD.org>2009-04-29 19:19:13 +0000
commit32a71137f08bc028578417de36a241d7e6011f58 (patch)
tree51d9a006ee48417962ce45f044b7e5603910fe13 /sys/netinet6/udp6_usrreq.c
parent51a4d1c4a3d279a3638c0b40f351aa93f965c7df (diff)
downloadFreeBSD-src-32a71137f08bc028578417de36a241d7e6011f58.zip
FreeBSD-src-32a71137f08bc028578417de36a241d7e6011f58.tar.gz
Bite the bullet, and make the IPv6 SSM and MLDv2 mega-commit:
import from p4 bms_netdev. Summary of changes: * Connect netinet6/in6_mcast.c to build. The legacy KAME KPIs are mostly preserved. * Eliminate now dead code from ip6_output.c. Don't do mbuf bingo, we are not going to do RFC 2292 style CMSG tricks for multicast options as they are not required by any current IPv6 normative reference. * Refactor transports (UDP, raw_ip6) to do own mcast filtering. SCTP, TCP unaffected by this change. * Add ip6_msource, in6_msource structs to in6_var.h. * Hookup mld_ifinfo state to in6_ifextra, allocate from domifattach path. * Eliminate IN6_LOOKUP_MULTI(), it is no longer referenced. Kernel consumers which need this should use in6m_lookup(). * Refactor IPv6 socket group memberships to use a vector (like IPv4). * Update ifmcstat(8) for IPv6 SSM. * Add witness lock order for IN6_MULTI_LOCK. * Move IN6_MULTI_LOCK out of lower ip6_output()/ip6_input() paths. * Introduce IP6STAT_ADD/SUB/INC/DEC as per rwatson's IPv4 cleanup. * Update carp(4) for new IPv6 SSM KPIs. * Virtualize ip6_mrouter socket. Changes mostly localized to IPv6 MROUTING. * Don't do a local group lookup in MROUTING. * Kill unused KAME prototypes in6_purgemkludge(), in6_restoremkludge(). * Preserve KAME DAD timer jitter behaviour in MLDv1 compatibility mode. * Bump __FreeBSD_version to 800084. * Update UPDATING. NOTE WELL: * This code hasn't been tested against real MLDv2 queriers (yet), although the on-wire protocol has been verified in Wireshark. * There are a few unresolved issues in the socket layer APIs to do with scope ID propagation. * There is a LOR present in ip6_output()'s use of in6_setscope() which needs to be resolved. See comments in mld6.c. This is believed to be benign and can't be avoided for the moment without re-introducing an indirect netisr. This work was mostly derived from the IGMPv3 implementation, and has been sponsored by a third party.
Diffstat (limited to 'sys/netinet6/udp6_usrreq.c')
-rw-r--r--sys/netinet6/udp6_usrreq.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 566cf92..5393740 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -177,6 +177,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
INIT_VNET_INET(curvnet);
INIT_VNET_INET6(curvnet);
struct mbuf *m = *mp;
+ struct ifnet *ifp;
struct ip6_hdr *ip6;
struct udphdr *uh;
struct inpcb *inp;
@@ -184,6 +185,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
int plen, ulen;
struct sockaddr_in6 fromsa;
+ ifp = m->m_pkthdr.rcvif;
ip6 = mtod(m, struct ip6_hdr *);
if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
@@ -239,6 +241,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
INP_INFO_RLOCK(&V_udbinfo);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
struct inpcb *last;
+ struct ip6_moptions *imo;
/*
* In the event that laddr should be set to the link-local
@@ -261,12 +264,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
continue;
if (inp->inp_lport != uh->uh_dport)
continue;
- /*
- * XXX: Do not check source port of incoming datagram
- * unless inp_connect() has been called to bind the
- * fport part of the 4-tuple; the source could be
- * trying to talk to us with an ephemeral port.
- */
if (inp->inp_fport != 0 &&
inp->inp_fport != uh->uh_sport)
continue;
@@ -282,6 +279,35 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
continue;
}
+ INP_RLOCK(inp);
+
+ /*
+ * Handle socket delivery policy for any-source
+ * and source-specific multicast. [RFC3678]
+ */
+ imo = inp->in6p_moptions;
+ if (imo && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
+ struct sockaddr_in6 mcaddr;
+ int blocked;
+
+ bzero(&mcaddr, sizeof(struct sockaddr_in6));
+ mcaddr.sin6_len = sizeof(struct sockaddr_in6);
+ mcaddr.sin6_family = AF_INET6;
+ mcaddr.sin6_addr = ip6->ip6_dst;
+
+ blocked = im6o_mc_filter(imo, ifp,
+ (struct sockaddr *)&mcaddr,
+ (struct sockaddr *)&fromsa);
+ if (blocked != MCAST_PASS) {
+ if (blocked == MCAST_NOTGMEMBER)
+ IP6STAT_INC(ip6s_notmember);
+ if (blocked == MCAST_NOTSMEMBER ||
+ blocked == MCAST_MUTED)
+ UDPSTAT_INC(udps_filtermcast);
+ INP_RUNLOCK(inp);
+ continue;
+ }
+ }
if (last != NULL) {
struct mbuf *n;
@@ -397,6 +423,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
return (IPPROTO_DONE);
badheadlocked:
+ if (inp)
+ INP_RUNLOCK(inp);
INP_INFO_RUNLOCK(&V_udbinfo);
badunlocked:
if (m)
OpenPOWER on IntegriCloud