diff options
author | bms <bms@FreeBSD.org> | 2007-02-24 11:38:47 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2007-02-24 11:38:47 +0000 |
commit | 3e83ac665326a6a015b2179fc28157d9fb7433e2 (patch) | |
tree | 6230b66dd7bf83f11724dee78961a7c0020c9d31 | |
parent | c553ec0508d385c07a87aed036312de1e3a64b03 (diff) | |
download | FreeBSD-src-3e83ac665326a6a015b2179fc28157d9fb7433e2.zip FreeBSD-src-3e83ac665326a6a015b2179fc28157d9fb7433e2.tar.gz |
Make IPv6 multicast forwarding dynamically loadable from a GENERIC kernel.
It is built in the same module as IPv4 multicast forwarding, i.e. ip_mroute.ko,
if and only if IPv6 support is enabled for loadable modules.
Export IPv6 forwarding structs to userland netstat(1) via sysctl(9).
-rw-r--r-- | sys/conf/files | 4 | ||||
-rw-r--r-- | sys/modules/ip_mroute_mod/Makefile | 19 | ||||
-rw-r--r-- | sys/netinet/ip_mroute.c | 79 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 2 | ||||
-rw-r--r-- | sys/netinet6/in6_proto.c | 2 | ||||
-rw-r--r-- | sys/netinet6/ip6_input.c | 3 | ||||
-rw-r--r-- | sys/netinet6/ip6_mroute.c | 63 | ||||
-rw-r--r-- | sys/netinet6/ip6_mroute.h | 8 | ||||
-rw-r--r-- | sys/netinet6/ip6_var.h | 4 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 22 |
10 files changed, 171 insertions, 35 deletions
diff --git a/sys/conf/files b/sys/conf/files index 802e9a1..de6f263 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1760,7 +1760,7 @@ netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_ipsec.c optional ipsec netinet/ip_ipsec.c optional fast_ipsec -netinet/ip_mroute.c optional mrouting +netinet/ip_mroute.c optional mrouting inet | mrouting inet6 netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet @@ -1815,7 +1815,7 @@ netinet6/in6_src.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_id.c optional inet6 netinet6/ip6_input.c optional inet6 -netinet6/ip6_mroute.c optional inet6 +netinet6/ip6_mroute.c optional mrouting inet6 netinet6/ip6_output.c optional inet6 netinet6/ipcomp_core.c optional ipsec netinet6/ipcomp_input.c optional ipsec diff --git a/sys/modules/ip_mroute_mod/Makefile b/sys/modules/ip_mroute_mod/Makefile index 3a419a0..99eaf60 100644 --- a/sys/modules/ip_mroute_mod/Makefile +++ b/sys/modules/ip_mroute_mod/Makefile @@ -1,13 +1,26 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../netinet +.PATH: ${.CURDIR}/../../netinet ${.CURDIR}/../../netinet6 KMOD= ip_mroute -SRCS= ip_mroute.c opt_mac.h opt_mrouting.h + +SRCS= ip_mroute.c +SRCS+= opt_inet.h opt_mac.h opt_mrouting.h +SRCS+= opt_inet6.h + +.if !defined(MK_INET6_SUPPORT) || ${MK_INET6_SUPPORT} != "no" +SRCS+= ip6_mroute.c +.endif .if !defined(KERNBUILDDIR) +opt_inet.h: + echo "#define INET 1" > ${.TARGET} opt_mrouting.h: - echo "#define MROUTING 1" > ${.TARGET} + echo "#define MROUTING 1" > ${.TARGET} +.if !defined(MK_INET6_SUPPORT) || ${MK_INET6_SUPPORT} != "no" +opt_inet6.h: + echo "#define INET6 1" > ${.TARGET} +.endif .endif .include <bsd.kmod.mk> diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 90720e8..e889b7d 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -55,6 +55,8 @@ * $FreeBSD$ */ +#include "opt_inet.h" +#include "opt_inet6.h" #include "opt_mac.h" #include "opt_mrouting.h" @@ -92,6 +94,12 @@ #include <netinet/pim.h> #include <netinet/pim_var.h> #include <netinet/udp.h> +#ifdef INET6 +#include <netinet/ip6.h> +#include <netinet6/in6_var.h> +#include <netinet6/ip6_mroute.h> +#include <netinet6/ip6_var.h> +#endif #include <machine/in_cksum.h> #include <security/mac/mac_framework.h> @@ -217,6 +225,19 @@ struct protosw in_pim_protosw = { .pr_usrreqs = &rip_usrreqs }; static const struct encaptab *pim_encap_cookie; + +#ifdef INET6 +/* ip6_mroute.c glue */ +extern struct in6_protosw in6_pim_protosw; +static const struct encaptab *pim6_encap_cookie; + +extern int X_ip6_mrouter_set(struct socket *, struct sockopt *); +extern int X_ip6_mrouter_get(struct socket *, struct sockopt *); +extern int X_ip6_mrouter_done(void); +extern int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *); +extern int X_mrt6_ioctl(int, caddr_t); +#endif + static int pim_encapcheck(const struct mbuf *, int, int, void *); /* @@ -2737,7 +2758,7 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, } /* - * pim_encapcheck() is called by the encap4_input() path at runtime to + * pim_encapcheck() is called by the encap[46]_input() path at runtime to * determine if a packet is for PIM; allowing PIM to be dynamically loaded * into the kernel. */ @@ -2995,6 +3016,10 @@ pim_input_to_daemon: return; } +/* + * XXX: This is common code for dealing with initialization for both + * the IPv4 and IPv6 multicast forwarding paths. It could do with cleanup. + */ static int ip_mroute_modevent(module_t mod, int type, void *unused) { @@ -3006,6 +3031,7 @@ ip_mroute_modevent(module_t mod, int type, void *unused) ip_mrouter_reset(); TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt", &pim_squelch_wholepkt); + pim_encap_cookie = encap_attach_func(AF_INET, IPPROTO_PIM, pim_encapcheck, &in_pim_protosw, NULL); if (pim_encap_cookie == NULL) { @@ -3015,13 +3041,40 @@ ip_mroute_modevent(module_t mod, int type, void *unused) mtx_destroy(&mrouter_mtx); return (EINVAL); } + +#ifdef INET6 + pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM, + pim_encapcheck, (struct protosw *)&in6_pim_protosw, NULL); + if (pim6_encap_cookie == NULL) { + printf("ip_mroute: unable to attach pim6 encap\n"); + if (pim_encap_cookie) { + encap_detach(pim_encap_cookie); + pim_encap_cookie = NULL; + } + VIF_LOCK_DESTROY(); + MFC_LOCK_DESTROY(); + mtx_destroy(&mrouter_mtx); + return (EINVAL); + } +#endif + ip_mcast_src = X_ip_mcast_src; ip_mforward = X_ip_mforward; ip_mrouter_done = X_ip_mrouter_done; ip_mrouter_get = X_ip_mrouter_get; ip_mrouter_set = X_ip_mrouter_set; + +#ifdef INET6 + ip6_mforward = X_ip6_mforward; + ip6_mrouter_done = X_ip6_mrouter_done; + ip6_mrouter_get = X_ip6_mrouter_get; + ip6_mrouter_set = X_ip6_mrouter_set; + mrt6_ioctl = X_mrt6_ioctl; +#endif + ip_rsvp_force_done = X_ip_rsvp_force_done; ip_rsvp_vif = X_ip_rsvp_vif; + legal_vif_num = X_legal_vif_num; mrt_ioctl = X_mrt_ioctl; rsvp_input_p = X_rsvp_input; @@ -3036,29 +3089,49 @@ ip_mroute_modevent(module_t mod, int type, void *unused) * just loaded and then unloaded w/o starting up a user * process we still need to cleanup. */ - if (ip_mrouter) + if (ip_mrouter +#ifdef INET6 + || ip6_mrouter +#endif + ) return EINVAL; +#ifdef INET6 + if (pim6_encap_cookie) { + encap_detach(pim6_encap_cookie); + pim6_encap_cookie = NULL; + } + X_ip6_mrouter_done(); + ip6_mforward = NULL; + ip6_mrouter_done = NULL; + ip6_mrouter_get = NULL; + ip6_mrouter_set = NULL; + mrt6_ioctl = NULL; +#endif + if (pim_encap_cookie) { encap_detach(pim_encap_cookie); pim_encap_cookie = NULL; } - X_ip_mrouter_done(); ip_mcast_src = NULL; ip_mforward = NULL; ip_mrouter_done = NULL; ip_mrouter_get = NULL; ip_mrouter_set = NULL; + ip_rsvp_force_done = NULL; ip_rsvp_vif = NULL; + legal_vif_num = NULL; mrt_ioctl = NULL; rsvp_input_p = NULL; + VIF_LOCK_DESTROY(); MFC_LOCK_DESTROY(); mtx_destroy(&mrouter_mtx); break; + default: return EOPNOTSUPP; } diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 230f932..6aa0f9c 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -334,7 +334,7 @@ in6_control(so, cmd, data, ifp, td) switch (cmd) { case SIOCGETSGCNT_IN6: case SIOCGETMIFCNT_IN6: - return (mrt6_ioctl(cmd, data)); + return (mrt6_ioctl ? mrt6_ioctl(cmd, data) : EOPNOTSUPP); } switch(cmd) { diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 6765102..6b2a92a 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -335,7 +335,7 @@ struct ip6protosw inet6sw[] = { .pr_domain = &inet6domain, .pr_protocol = IPPROTO_PIM, .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, - .pr_input = pim6_input, + .pr_input = encap6_input, .pr_output = rip6_output, .pr_ctloutput = rip6_ctloutput, .pr_usrreqs = &rip6_usrreqs diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index 981c43a..099bdc7 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -696,7 +696,8 @@ passin: * ip6_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. */ - if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { + if (ip6_mrouter && ip6_mforward && + ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { ip6stat.ip6s_cantforward++; m_freem(m); return; diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index 1f86754..a6c238a 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -96,6 +96,7 @@ #include <sys/socketvar.h> #include <sys/sockio.h> #include <sys/sx.h> +#include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/systm.h> #include <sys/time.h> @@ -114,6 +115,7 @@ #include <netinet6/scope6_var.h> #include <netinet6/nd6.h> #include <netinet6/ip6_mroute.h> +#include <netinet6/ip6protosw.h> #include <netinet6/pim6.h> #include <netinet6/pim6_var.h> @@ -130,6 +132,18 @@ static int socket_send __P((struct socket *, struct mbuf *, static int register_send __P((struct ip6_hdr *, struct mif6 *, struct mbuf *)); +extern struct domain inet6domain; +struct ip6protosw in6_pim_protosw = { + .pr_type = SOCK_RAW, + .pr_domain = &inet6domain, + .pr_protocol = IPPROTO_PIM, + .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, + .pr_input = pim6_input, + .pr_output = rip6_output, + .pr_ctloutput = rip6_ctloutput, + .pr_usrreqs = &rip6_usrreqs +}; + /* * Globals. All but ip6_mrouter, ip6_mrtproto and mrt6stat could be static, * except for netstat or debugging purposes. @@ -137,14 +151,32 @@ static int register_send __P((struct ip6_hdr *, struct mif6 *, struct socket *ip6_mrouter = NULL; int ip6_mrouter_ver = 0; int ip6_mrtproto = IPPROTO_PIM; /* for netstat only */ + +SYSCTL_DECL(_net_inet6); +SYSCTL_DECL(_net_inet6_ip6); +SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); + struct mrt6stat mrt6stat; +SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW, + &mrt6stat, mrt6stat, + "Multicast Routing Statistics (struct mrt6stat, netinet6/ip6_mroute.h)"); #define NO_RTE_FOUND 0x1 #define RTE_FOUND 0x2 struct mf6c *mf6ctable[MF6CTBLSIZ]; +SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD, + &mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]", + "Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], " + "netinet6/ip6_mroute.h)"); + u_char n6expire[MF6CTBLSIZ]; + static struct mif6 mif6table[MAXMIFS]; +SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD, + &mif6table, sizeof(mif6table), "S,vif[MAXMIFS]", + "Multicast Interfaces (struct mif[MAXMIFS], netinet6/ip6_mroute.h)"); + #ifdef MRT6DEBUG u_int mrt6debug = 0; /* debug level */ #define DEBUG_MFC 0x02 @@ -187,6 +219,10 @@ static mifi_t nummifs = 0; static mifi_t reg_mif_num = (mifi_t)-1; static struct pim6stat pim6stat; +SYSCTL_STRUCT(_net_inet6_pim, PIM6CTL_STATS, stats, CTLFLAG_RD, + &pim6stat, pim6stat, + "PIM Statistics (struct pim6stat, netinet6/pim_var.h)"); + static int pim6; /* @@ -261,13 +297,17 @@ static int del_m6fc __P((struct mf6cctl *)); static struct callout expire_upcalls_ch; +int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m); +int X_ip6_mrouter_done(void); +int X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt); +int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt); +int X_mrt6_ioctl(int cmd, caddr_t data); + /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ int -ip6_mrouter_set(so, sopt) - struct socket *so; - struct sockopt *sopt; +X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt) { int error = 0; int optval; @@ -290,7 +330,7 @@ ip6_mrouter_set(so, sopt) error = ip6_mrouter_init(so, optval, sopt->sopt_name); break; case MRT6_DONE: - error = ip6_mrouter_done(); + error = X_ip6_mrouter_done(); break; case MRT6_ADD_MIF: error = sooptcopyin(sopt, &mifc, sizeof(mifc), sizeof(mifc)); @@ -335,9 +375,7 @@ ip6_mrouter_set(so, sopt) * Handle MRT getsockopt commands */ int -ip6_mrouter_get(so, sopt) - struct socket *so; - struct sockopt *sopt; +X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt) { int error = 0; @@ -356,9 +394,7 @@ ip6_mrouter_get(so, sopt) * Handle ioctl commands to obtain information from the cache */ int -mrt6_ioctl(cmd, data) - int cmd; - caddr_t data; +X_mrt6_ioctl(int cmd, caddr_t data) { switch (cmd) { case SIOCGETSGCNT_IN6: @@ -478,7 +514,7 @@ ip6_mrouter_init(so, v, cmd) * Disable multicast routing */ int -ip6_mrouter_done() +X_ip6_mrouter_done(void) { mifi_t mifi; int i; @@ -993,10 +1029,7 @@ socket_send(s, mm, src) */ int -ip6_mforward(ip6, ifp, m) - struct ip6_hdr *ip6; - struct ifnet *ifp; - struct mbuf *m; +X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m) { struct mf6c *rt; struct mif6 *mifp; diff --git a/sys/netinet6/ip6_mroute.h b/sys/netinet6/ip6_mroute.h index b1de70b..fdff76d 100644 --- a/sys/netinet6/ip6_mroute.h +++ b/sys/netinet6/ip6_mroute.h @@ -268,10 +268,10 @@ struct rtdetq { /* XXX: rtdetq is also defined in ip_mroute.h */ #define MAX_UPQ6 4 /* max. no of pkts in upcall Q */ -int ip6_mrouter_set __P((struct socket *so, struct sockopt *sopt)); -int ip6_mrouter_get __P((struct socket *so, struct sockopt *sopt)); -int ip6_mrouter_done __P((void)); -int mrt6_ioctl __P((int, caddr_t)); +extern int (*ip6_mrouter_set)(struct socket *so, struct sockopt *sopt); +extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt); +extern int (*ip6_mrouter_done)(void); +extern int (*mrt6_ioctl)(int, caddr_t); #endif /* _KERNEL */ #endif /* !_NETINET6_IP6_MROUTE_H_ */ diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index a0dfec3..91b444b 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -353,7 +353,9 @@ struct ip6aux *ip6_addaux __P((struct mbuf *)); struct ip6aux *ip6_findaux __P((struct mbuf *)); void ip6_delaux __P((struct mbuf *)); -int ip6_mforward __P((struct ip6_hdr *, struct ifnet *, struct mbuf *)); +extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, + struct mbuf *); + int ip6_process_hopopts __P((struct mbuf *, u_int8_t *, int, u_int32_t *, u_int32_t *)); void ip6_savecontrol __P((struct inpcb *, struct mbuf *, struct mbuf **)); diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index cab78eb..643c694 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -122,6 +122,18 @@ extern u_long rip_recvspace; struct rip6stat rip6stat; /* + * Hooks for multicast forwarding. + */ + +struct socket *ip6_mrouter; + +int (*ip6_mrouter_set)(struct socket *, struct sockopt *); +int (*ip6_mrouter_get)(struct socket *, struct sockopt *); +int (*ip6_mrouter_done)(void); +int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *); +int (*mrt6_ioctl)(int, caddr_t); + +/* * Setup generic address and protocol structures * for raw_input routine, then pass them along with * mbuf chain. @@ -507,7 +519,8 @@ rip6_ctloutput(so, sopt) case MRT6_ADD_MFC: case MRT6_DEL_MFC: case MRT6_PIM: - error = ip6_mrouter_get(so, sopt); + error = ip6_mrouter_get ? ip6_mrouter_get(so, sopt) : + EOPNOTSUPP; break; case IPV6_CHECKSUM: error = ip6_raw_ctloutput(so, sopt); @@ -527,7 +540,8 @@ rip6_ctloutput(so, sopt) case MRT6_ADD_MFC: case MRT6_DEL_MFC: case MRT6_PIM: - error = ip6_mrouter_set(so, sopt); + error = ip6_mrouter_set ? ip6_mrouter_set(so, sopt) : + EOPNOTSUPP; break; case IPV6_CHECKSUM: error = ip6_raw_ctloutput(so, sopt); @@ -587,9 +601,9 @@ rip6_detach(struct socket *so) inp = sotoinpcb(so); KASSERT(inp != NULL, ("rip6_detach: inp == NULL")); - /* xxx: RSVP */ - if (so == ip6_mrouter) + if (so == ip6_mrouter && ip6_mrouter_done) ip6_mrouter_done(); + /* xxx: RSVP */ INP_INFO_WLOCK(&ripcbinfo); INP_LOCK(inp); if (inp->in6p_icmp6filt) { |