summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files4
-rw-r--r--sys/modules/ip_mroute_mod/Makefile19
-rw-r--r--sys/netinet/ip_mroute.c79
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/in6_proto.c2
-rw-r--r--sys/netinet6/ip6_input.c3
-rw-r--r--sys/netinet6/ip6_mroute.c63
-rw-r--r--sys/netinet6/ip6_mroute.h8
-rw-r--r--sys/netinet6/ip6_var.h4
-rw-r--r--sys/netinet6/raw_ip6.c22
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) {
OpenPOWER on IntegriCloud