Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet6/ip6_mroute.c
Show First 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | |||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/if_types.h> | #include <net/if_types.h> | ||||
#include <net/raw_cb.h> | |||||
#include <net/vnet.h> | #include <net/vnet.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/in_var.h> | #include <netinet/in_var.h> | ||||
#include <netinet/icmp6.h> | #include <netinet/icmp6.h> | ||||
#include <netinet/ip_encap.h> | #include <netinet/ip_encap.h> | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
Show All 13 Lines | |||||
static int set_pim6(int *); | static int set_pim6(int *); | ||||
static int socket_send(struct socket *, struct mbuf *, | static int socket_send(struct socket *, struct mbuf *, | ||||
struct sockaddr_in6 *); | struct sockaddr_in6 *); | ||||
extern int in6_mcast_loop; | extern int in6_mcast_loop; | ||||
extern struct domain inet6domain; | extern struct domain inet6domain; | ||||
static const struct encaptab *pim6_encap_cookie; | static const struct encaptab *pim6_encap_cookie; | ||||
static const struct protosw 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 | |||||
}; | |||||
static int pim6_encapcheck(const struct mbuf *, int, int, void *); | static int pim6_encapcheck(const struct mbuf *, int, int, void *); | ||||
static int pim6_input(struct mbuf *, int, int, void *); | |||||
static const struct encap_config ipv6_encap_cfg = { | |||||
.proto = IPPROTO_PIM, | |||||
.min_length = sizeof(struct ip6_hdr) + PIM_MINLEN, | |||||
.exact_match = 8, | |||||
.check = pim6_encapcheck, | |||||
.input = pim6_input | |||||
}; | |||||
static VNET_DEFINE(int, ip6_mrouter_ver) = 0; | static VNET_DEFINE(int, ip6_mrouter_ver) = 0; | ||||
#define V_ip6_mrouter_ver VNET(ip6_mrouter_ver) | #define V_ip6_mrouter_ver VNET(ip6_mrouter_ver) | ||||
SYSCTL_DECL(_net_inet6); | SYSCTL_DECL(_net_inet6); | ||||
SYSCTL_DECL(_net_inet6_ip6); | SYSCTL_DECL(_net_inet6_ip6); | ||||
static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); | static SYSCTL_NODE(_net_inet6, IPPROTO_PIM, pim, CTLFLAG_RW, 0, "PIM"); | ||||
static struct mrt6stat mrt6stat; | static struct mrt6stat mrt6stat; | ||||
▲ Show 20 Lines • Show All 1,528 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/* | /* | ||||
* pim6_encapcheck() is called by the encap6_input() path at runtime to | * pim6_encapcheck() is called by the encap6_input() path at runtime to | ||||
* determine if a packet is for PIM; allowing PIM to be dynamically loaded | * determine if a packet is for PIM; allowing PIM to be dynamically loaded | ||||
* into the kernel. | * into the kernel. | ||||
*/ | */ | ||||
static int | static int | ||||
pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg) | pim6_encapcheck(const struct mbuf *m __unused, int off __unused, | ||||
int proto __unused, void *arg __unused) | |||||
{ | { | ||||
#ifdef DIAGNOSTIC | |||||
KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM")); | KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM")); | ||||
#endif | return (8); /* claim the datagram. */ | ||||
if (proto != IPPROTO_PIM) | |||||
return 0; /* not for us; reject the datagram. */ | |||||
return 64; /* claim the datagram. */ | |||||
} | } | ||||
/* | /* | ||||
* PIM sparse mode hook | * PIM sparse mode hook | ||||
* Receives the pim control messages, and passes them up to the listening | * Receives the pim control messages, and passes them up to the listening | ||||
* socket, using rip6_input. | * socket, using rip6_input. | ||||
* The only message processed is the REGISTER pim message; the pim header | * The only message processed is the REGISTER pim message; the pim header | ||||
* is stripped off, and the inner packet is passed to register_mforward. | * is stripped off, and the inner packet is passed to register_mforward. | ||||
*/ | */ | ||||
int | static int | ||||
pim6_input(struct mbuf **mp, int *offp, int proto) | pim6_input(struct mbuf *m, int off, int proto, void *arg __unused) | ||||
{ | { | ||||
struct pim *pim; /* pointer to a pim struct */ | struct pim *pim; /* pointer to a pim struct */ | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
int pimlen; | int pimlen; | ||||
struct mbuf *m = *mp; | |||||
int minlen; | int minlen; | ||||
int off = *offp; | |||||
PIM6STAT_INC(pim6s_rcv_total); | PIM6STAT_INC(pim6s_rcv_total); | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
pimlen = m->m_pkthdr.len - *offp; | pimlen = m->m_pkthdr.len - off; | ||||
/* | /* | ||||
* Validate lengths | * Validate lengths | ||||
*/ | */ | ||||
if (pimlen < PIM_MINLEN) { | if (pimlen < PIM_MINLEN) { | ||||
PIM6STAT_INC(pim6s_rcv_tooshort); | PIM6STAT_INC(pim6s_rcv_tooshort); | ||||
MRT6_DLOG(DEBUG_PIM, "PIM packet too short"); | MRT6_DLOG(DEBUG_PIM, "PIM packet too short"); | ||||
m_freem(m); | m_freem(m); | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Pass the PIM message up to the daemon; if it is a register message | * Pass the PIM message up to the daemon; if it is a register message | ||||
* pass the 'head' only up to the daemon. This includes the | * pass the 'head' only up to the daemon. This includes the | ||||
* encapsulator ip6 header, pim header, register header and the | * encapsulator ip6 header, pim header, register header and the | ||||
* encapsulated ip6 header. | * encapsulated ip6 header. | ||||
*/ | */ | ||||
pim6_input_to_daemon: | pim6_input_to_daemon: | ||||
rip6_input(&m, offp, proto); | return (rip6_input(&m, &off, proto)); | ||||
return (IPPROTO_DONE); | |||||
} | } | ||||
static int | static int | ||||
ip6_mroute_modevent(module_t mod, int type, void *unused) | ip6_mroute_modevent(module_t mod, int type, void *unused) | ||||
{ | { | ||||
switch (type) { | switch (type) { | ||||
case MOD_LOAD: | case MOD_LOAD: | ||||
MROUTER6_LOCK_INIT(); | MROUTER6_LOCK_INIT(); | ||||
MFC6_LOCK_INIT(); | MFC6_LOCK_INIT(); | ||||
MIF6_LOCK_INIT(); | MIF6_LOCK_INIT(); | ||||
pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM, | pim6_encap_cookie = ip6_encap_attach(&ipv6_encap_cfg, | ||||
pim6_encapcheck, | NULL, M_WAITOK); | ||||
(const struct protosw *)&in6_pim_protosw, NULL); | |||||
if (pim6_encap_cookie == NULL) { | if (pim6_encap_cookie == NULL) { | ||||
printf("ip6_mroute: unable to attach pim6 encap\n"); | printf("ip6_mroute: unable to attach pim6 encap\n"); | ||||
MIF6_LOCK_DESTROY(); | MIF6_LOCK_DESTROY(); | ||||
MFC6_LOCK_DESTROY(); | MFC6_LOCK_DESTROY(); | ||||
MROUTER6_LOCK_DESTROY(); | MROUTER6_LOCK_DESTROY(); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
ip6_mforward = X_ip6_mforward; | ip6_mforward = X_ip6_mforward; | ||||
ip6_mrouter_done = X_ip6_mrouter_done; | ip6_mrouter_done = X_ip6_mrouter_done; | ||||
ip6_mrouter_get = X_ip6_mrouter_get; | ip6_mrouter_get = X_ip6_mrouter_get; | ||||
ip6_mrouter_set = X_ip6_mrouter_set; | ip6_mrouter_set = X_ip6_mrouter_set; | ||||
mrt6_ioctl = X_mrt6_ioctl; | mrt6_ioctl = X_mrt6_ioctl; | ||||
break; | break; | ||||
case MOD_UNLOAD: | case MOD_UNLOAD: | ||||
if (V_ip6_mrouter != NULL) | if (V_ip6_mrouter != NULL) | ||||
return EINVAL; | return EINVAL; | ||||
if (pim6_encap_cookie) { | if (pim6_encap_cookie) { | ||||
encap_detach(pim6_encap_cookie); | ip6_encap_detach(pim6_encap_cookie); | ||||
pim6_encap_cookie = NULL; | pim6_encap_cookie = NULL; | ||||
} | } | ||||
X_ip6_mrouter_done(); | X_ip6_mrouter_done(); | ||||
ip6_mforward = NULL; | ip6_mforward = NULL; | ||||
ip6_mrouter_done = NULL; | ip6_mrouter_done = NULL; | ||||
ip6_mrouter_get = NULL; | ip6_mrouter_get = NULL; | ||||
ip6_mrouter_set = NULL; | ip6_mrouter_set = NULL; | ||||
mrt6_ioctl = NULL; | mrt6_ioctl = NULL; | ||||
Show All 20 Lines |