aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet6/raw_ip6.c
diff options
context:
space:
mode:
authorBruce M Simpson <bms@FreeBSD.org>2009-04-29 19:19:13 +0000
committerBruce M Simpson <bms@FreeBSD.org>2009-04-29 19:19:13 +0000
commit33cde13046eaba762428c55bb5d5e07c1a7c5f33 (patch)
tree51d9a006ee48417962ce45f044b7e5603910fe13 /sys/netinet6/raw_ip6.c
parentaf7bd9a4f4fca52a1c9c48858b5e18d332ca03b9 (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.c61
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);