Changeset View
Changeset View
Standalone View
Standalone View
head/sys/net/if_stf.c
Show First 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/sockio.h> | #include <sys/sockio.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/errno.h> | #include <sys/errno.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/protosw.h> | |||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/rmlock.h> | #include <sys/rmlock.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
#define STF2IFP(sc) ((sc)->sc_ifp) | #define STF2IFP(sc) ((sc)->sc_ifp) | ||||
static const char stfname[] = "stf"; | static const char stfname[] = "stf"; | ||||
static MALLOC_DEFINE(M_STF, stfname, "6to4 Tunnel Interface"); | static MALLOC_DEFINE(M_STF, stfname, "6to4 Tunnel Interface"); | ||||
static const int ip_stf_ttl = 40; | static const int ip_stf_ttl = 40; | ||||
extern struct domain inetdomain; | static int in_stf_input(struct mbuf *, int, int, void *); | ||||
static int in_stf_input(struct mbuf **, int *, int); | |||||
static struct protosw in_stf_protosw = { | |||||
.pr_type = SOCK_RAW, | |||||
.pr_domain = &inetdomain, | |||||
.pr_protocol = IPPROTO_IPV6, | |||||
.pr_flags = PR_ATOMIC|PR_ADDR, | |||||
.pr_input = in_stf_input, | |||||
.pr_output = rip_output, | |||||
.pr_ctloutput = rip_ctloutput, | |||||
.pr_usrreqs = &rip_usrreqs | |||||
}; | |||||
static char *stfnames[] = {"stf0", "stf", "6to4", NULL}; | static char *stfnames[] = {"stf0", "stf", "6to4", NULL}; | ||||
static int stfmodevent(module_t, int, void *); | static int stfmodevent(module_t, int, void *); | ||||
static int stf_encapcheck(const struct mbuf *, int, int, void *); | static int stf_encapcheck(const struct mbuf *, int, int, void *); | ||||
static int stf_getsrcifa6(struct ifnet *, struct in6_addr *, struct in6_addr *); | static int stf_getsrcifa6(struct ifnet *, struct in6_addr *, struct in6_addr *); | ||||
static int stf_output(struct ifnet *, struct mbuf *, const struct sockaddr *, | static int stf_output(struct ifnet *, struct mbuf *, const struct sockaddr *, | ||||
struct route *); | struct route *); | ||||
static int isrfc1918addr(struct in_addr *); | static int isrfc1918addr(struct in_addr *); | ||||
static int stf_checkaddr4(struct stf_softc *, struct in_addr *, | static int stf_checkaddr4(struct stf_softc *, struct in_addr *, | ||||
struct ifnet *); | struct ifnet *); | ||||
static int stf_checkaddr6(struct stf_softc *, struct in6_addr *, | static int stf_checkaddr6(struct stf_softc *, struct in6_addr *, | ||||
struct ifnet *); | struct ifnet *); | ||||
static int stf_ioctl(struct ifnet *, u_long, caddr_t); | static int stf_ioctl(struct ifnet *, u_long, caddr_t); | ||||
static int stf_clone_match(struct if_clone *, const char *); | static int stf_clone_match(struct if_clone *, const char *); | ||||
static int stf_clone_create(struct if_clone *, char *, size_t, caddr_t); | static int stf_clone_create(struct if_clone *, char *, size_t, caddr_t); | ||||
static int stf_clone_destroy(struct if_clone *, struct ifnet *); | static int stf_clone_destroy(struct if_clone *, struct ifnet *); | ||||
static struct if_clone *stf_cloner; | static struct if_clone *stf_cloner; | ||||
static const struct encap_config ipv4_encap_cfg = { | |||||
.proto = IPPROTO_IPV6, | |||||
.min_length = sizeof(struct ip), | |||||
.exact_match = (sizeof(in_addr_t) << 3) + 8, | |||||
.check = stf_encapcheck, | |||||
.input = in_stf_input | |||||
}; | |||||
static int | static int | ||||
stf_clone_match(struct if_clone *ifc, const char *name) | stf_clone_match(struct if_clone *ifc, const char *name) | ||||
{ | { | ||||
int i; | int i; | ||||
for(i = 0; stfnames[i] != NULL; i++) { | for(i = 0; stfnames[i] != NULL; i++) { | ||||
if (strcmp(stfnames[i], name) == 0) | if (strcmp(stfnames[i], name) == 0) | ||||
return (1); | return (1); | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | if (snprintf(dp, len - (dp-name), "%d", unit) > | ||||
*/ | */ | ||||
panic("if_clone_create(): interface name too long"); | panic("if_clone_create(): interface name too long"); | ||||
} | } | ||||
} | } | ||||
strlcpy(ifp->if_xname, name, IFNAMSIZ); | strlcpy(ifp->if_xname, name, IFNAMSIZ); | ||||
ifp->if_dname = stfname; | ifp->if_dname = stfname; | ||||
ifp->if_dunit = IF_DUNIT_NONE; | ifp->if_dunit = IF_DUNIT_NONE; | ||||
sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6, | sc->encap_cookie = ip_encap_attach(&ipv4_encap_cfg, sc, M_WAITOK); | ||||
stf_encapcheck, &in_stf_protosw, sc); | |||||
if (sc->encap_cookie == NULL) { | if (sc->encap_cookie == NULL) { | ||||
if_printf(ifp, "attach failed\n"); | if_printf(ifp, "attach failed\n"); | ||||
free(sc, M_STF); | free(sc, M_STF); | ||||
ifc_free_unit(ifc, unit); | ifc_free_unit(ifc, unit); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
ifp->if_mtu = IPV6_MMTU; | ifp->if_mtu = IPV6_MMTU; | ||||
ifp->if_ioctl = stf_ioctl; | ifp->if_ioctl = stf_ioctl; | ||||
ifp->if_output = stf_output; | ifp->if_output = stf_output; | ||||
ifp->if_snd.ifq_maxlen = ifqmaxlen; | ifp->if_snd.ifq_maxlen = ifqmaxlen; | ||||
if_attach(ifp); | if_attach(ifp); | ||||
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); | bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) | stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) | ||||
{ | { | ||||
struct stf_softc *sc = ifp->if_softc; | struct stf_softc *sc = ifp->if_softc; | ||||
int err __unused; | int err __unused; | ||||
err = encap_detach(sc->encap_cookie); | err = ip_encap_detach(sc->encap_cookie); | ||||
KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); | KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); | ||||
bpfdetach(ifp); | bpfdetach(ifp); | ||||
if_detach(ifp); | if_detach(ifp); | ||||
if_free(ifp); | if_free(ifp); | ||||
free(sc, M_STF); | free(sc, M_STF); | ||||
ifc_free_unit(ifc, STFUNIT); | ifc_free_unit(ifc, STFUNIT); | ||||
▲ Show 20 Lines • Show All 317 Lines • ▼ Show 20 Lines | stf_checkaddr6(struct stf_softc *sc, struct in6_addr *in6, struct ifnet *inifp) | ||||
*/ | */ | ||||
if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6)) | if (IN6_IS_ADDR_V4COMPAT(in6) || IN6_IS_ADDR_V4MAPPED(in6)) | ||||
return -1; | return -1; | ||||
return 0; | return 0; | ||||
} | } | ||||
static int | static int | ||||
in_stf_input(struct mbuf **mp, int *offp, int proto) | in_stf_input(struct mbuf *m, int off, int proto, void *arg) | ||||
{ | { | ||||
struct stf_softc *sc; | struct stf_softc *sc = arg; | ||||
struct ip *ip; | struct ip *ip; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct mbuf *m; | |||||
u_int8_t otos, itos; | u_int8_t otos, itos; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
int off; | |||||
m = *mp; | |||||
off = *offp; | |||||
if (proto != IPPROTO_IPV6) { | if (proto != IPPROTO_IPV6) { | ||||
m_freem(m); | m_freem(m); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
sc = (struct stf_softc *)encap_getarg(m); | |||||
if (sc == NULL || (STF2IFP(sc)->if_flags & IFF_UP) == 0) { | if (sc == NULL || (STF2IFP(sc)->if_flags & IFF_UP) == 0) { | ||||
m_freem(m); | m_freem(m); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
ifp = STF2IFP(sc); | ifp = STF2IFP(sc); | ||||
#ifdef MAC | #ifdef MAC | ||||
Show All 34 Lines | #endif | ||||
if ((ifp->if_flags & IFF_LINK1) != 0) | if ((ifp->if_flags & IFF_LINK1) != 0) | ||||
ip_ecn_egress(ECN_ALLOWED, &otos, &itos); | ip_ecn_egress(ECN_ALLOWED, &otos, &itos); | ||||
else | else | ||||
ip_ecn_egress(ECN_NOCARE, &otos, &itos); | ip_ecn_egress(ECN_NOCARE, &otos, &itos); | ||||
ip6->ip6_flow &= ~htonl(0xff << 20); | ip6->ip6_flow &= ~htonl(0xff << 20); | ||||
ip6->ip6_flow |= htonl((u_int32_t)itos << 20); | ip6->ip6_flow |= htonl((u_int32_t)itos << 20); | ||||
m->m_pkthdr.rcvif = ifp; | m->m_pkthdr.rcvif = ifp; | ||||
if (bpf_peers_present(ifp->if_bpf)) { | if (bpf_peers_present(ifp->if_bpf)) { | ||||
/* | /* | ||||
* We need to prepend the address family as | * We need to prepend the address family as | ||||
* a four byte field. Cons up a dummy header | * a four byte field. Cons up a dummy header | ||||
* to pacify bpf. This is safe because bpf | * to pacify bpf. This is safe because bpf | ||||
* will only read from the mbuf (i.e., it won't | * will only read from the mbuf (i.e., it won't | ||||
* try to free it or keep a pointer a to it). | * try to free it or keep a pointer a to it). | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 76 Lines • Show Last 20 Lines |