diff options
author | Bruce M Simpson <bms@FreeBSD.org> | 2009-04-29 19:19:13 +0000 |
---|---|---|
committer | Bruce M Simpson <bms@FreeBSD.org> | 2009-04-29 19:19:13 +0000 |
commit | 33cde13046eaba762428c55bb5d5e07c1a7c5f33 (patch) | |
tree | 51d9a006ee48417962ce45f044b7e5603910fe13 /sys/netinet6/raw_ip6.c | |
parent | af7bd9a4f4fca52a1c9c48858b5e18d332ca03b9 (diff) |
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.
Notes
Notes:
svn path=/head/; revision=191672
Diffstat (limited to 'sys/netinet6/raw_ip6.c')
-rw-r--r-- | sys/netinet6/raw_ip6.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 2ac95e518a6c..c340ffdac0a9 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -128,9 +128,20 @@ extern u_long rip_sendspace; extern u_long rip_recvspace; /* - * Hooks for multicast forwarding. + * Hooks for multicast routing. They all default to NULL, so leave them not + * initialized and rely on BSS being set to 0. + */ + +/* + * The socket used to communicate with the multicast routing daemon. + */ +#ifdef VIMAGE_GLOBALS +struct socket *ip6_mrouter; +#endif + +/* + * The various mrouter functions. */ -struct socket *ip6_mrouter = NULL; int (*ip6_mrouter_set)(struct socket *, struct sockopt *); int (*ip6_mrouter_get)(struct socket *, struct sockopt *); int (*ip6_mrouter_done)(void); @@ -149,6 +160,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto) #ifdef IPSEC INIT_VNET_IPSEC(curvnet); #endif + struct ifnet *ifp; struct mbuf *m = *mp; register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); register struct inpcb *in6p; @@ -166,6 +178,8 @@ rip6_input(struct mbuf **mp, int *offp, int proto) init_sin6(&fromsa, m); /* general init */ + ifp = m->m_pkthdr.rcvif; + INP_INFO_RLOCK(&V_ripcbinfo); LIST_FOREACH(in6p, &V_ripcb, inp_list) { /* XXX inp locking */ @@ -180,9 +194,17 @@ rip6_input(struct mbuf **mp, int *offp, int proto) if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) && !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src)) continue; - if (prison_check_ip6(in6p->inp_cred, &ip6->ip6_dst) != 0) - continue; - INP_RLOCK(in6p); + if (jailed(in6p->inp_cred)) { + /* + * Allow raw socket in jail to receive multicast; + * assume process had PRIV_NETINET_RAW at attach, + * and fall through into normal filter path if so. + */ + if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && + prison_check_ip6(in6p->inp_cred, + &ip6->ip6_dst) != 0) + continue; + } if (in6p->in6p_cksum != -1) { V_rip6stat.rip6s_isum++; if (in6_cksum(m, proto, *offp, @@ -192,6 +214,31 @@ rip6_input(struct mbuf **mp, int *offp, int proto) continue; } } + INP_RLOCK(in6p); + /* + * If this raw socket has multicast state, and we + * have received a multicast, check if this socket + * should receive it, as multicast filtering is now + * the responsibility of the transport layer. + */ + if (in6p->in6p_moptions && + 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(in6p->in6p_moptions, ifp, + (struct sockaddr *)&mcaddr, + (struct sockaddr *)&fromsa); + if (blocked != MCAST_PASS) { + IP6STAT_INC(ip6s_notmember); + continue; + } + } if (last != NULL) { struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); @@ -604,13 +651,13 @@ rip6_attach(struct socket *so, int proto, struct thread *td) static void rip6_detach(struct socket *so) { - INIT_VNET_INET(so->so_vnet); + INIT_VNET_INET6(so->so_vnet); struct inpcb *inp; inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); - if (so == ip6_mrouter && ip6_mrouter_done) + if (so == V_ip6_mrouter && ip6_mrouter_done) ip6_mrouter_done(); /* xxx: RSVP */ INP_INFO_WLOCK(&V_ripcbinfo); |