Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet6/in6_gif.c
Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
#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/queue.h> | #include <sys/queue.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/protosw.h> | |||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.h> | ||||
#include <net/route.h> | #include <net/route.h> | ||||
#include <net/vnet.h> | #include <net/vnet.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
Show All 15 Lines | |||||
#include <net/if_gif.h> | #include <net/if_gif.h> | ||||
#define GIF_HLIM 30 | #define GIF_HLIM 30 | ||||
static VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM; | static VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM; | ||||
#define V_ip6_gif_hlim VNET(ip6_gif_hlim) | #define V_ip6_gif_hlim VNET(ip6_gif_hlim) | ||||
SYSCTL_DECL(_net_inet6_ip6); | SYSCTL_DECL(_net_inet6_ip6); | ||||
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, | ||||
&VNET_NAME(ip6_gif_hlim), 0, ""); | CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_gif_hlim), 0, | ||||
"Default hop limit for encapsulated packets"); | |||||
static int in6_gif_input(struct mbuf **, int *, int); | |||||
extern struct domain inet6domain; | |||||
static struct protosw in6_gif_protosw = { | |||||
.pr_type = SOCK_RAW, | |||||
.pr_domain = &inet6domain, | |||||
.pr_protocol = 0, /* IPPROTO_IPV[46] */ | |||||
.pr_flags = PR_ATOMIC|PR_ADDR, | |||||
.pr_input = in6_gif_input, | |||||
.pr_output = rip6_output, | |||||
.pr_ctloutput = rip6_ctloutput, | |||||
.pr_usrreqs = &rip6_usrreqs | |||||
}; | |||||
int | int | ||||
in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn) | in6_gif_output(struct ifnet *ifp, struct mbuf *m, int proto, uint8_t ecn) | ||||
{ | { | ||||
GIF_RLOCK_TRACKER; | GIF_RLOCK_TRACKER; | ||||
struct gif_softc *sc = ifp->if_softc; | struct gif_softc *sc = ifp->if_softc; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
int len; | int len; | ||||
Show All 33 Lines | #endif | ||||
* force fragmentation to minimum MTU, to avoid path MTU discovery. | * force fragmentation to minimum MTU, to avoid path MTU discovery. | ||||
* it is too painful to ask for resend of inner packet, to achieve | * it is too painful to ask for resend of inner packet, to achieve | ||||
* path MTU discovery for encapsulated packets. | * path MTU discovery for encapsulated packets. | ||||
*/ | */ | ||||
return (ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL, NULL)); | return (ip6_output(m, 0, NULL, IPV6_MINMTU, 0, NULL, NULL)); | ||||
} | } | ||||
static int | static int | ||||
in6_gif_input(struct mbuf **mp, int *offp, int proto) | in6_gif_input(struct mbuf *m, int off, int proto, void *arg) | ||||
{ | { | ||||
struct mbuf *m = *mp; | struct gif_softc *sc = arg; | ||||
struct ifnet *gifp; | struct ifnet *gifp; | ||||
struct gif_softc *sc; | |||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
uint8_t ecn; | uint8_t ecn; | ||||
sc = encap_getarg(m); | |||||
if (sc == NULL) { | if (sc == NULL) { | ||||
m_freem(m); | m_freem(m); | ||||
IP6STAT_INC(ip6s_nogif); | IP6STAT_INC(ip6s_nogif); | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
gifp = GIF2IFP(sc); | gifp = GIF2IFP(sc); | ||||
if ((gifp->if_flags & IFF_UP) != 0) { | if ((gifp->if_flags & IFF_UP) != 0) { | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
ecn = (ntohl(ip6->ip6_flow) >> 20) & 0xff; | ecn = (ntohl(ip6->ip6_flow) >> 20) & 0xff; | ||||
m_adj(m, *offp); | m_adj(m, off); | ||||
gif_input(m, gifp, proto, ecn); | gif_input(m, gifp, proto, ecn); | ||||
} else { | } else { | ||||
m_freem(m); | m_freem(m); | ||||
IP6STAT_INC(ip6s_nogif); | IP6STAT_INC(ip6s_nogif); | ||||
} | } | ||||
return (IPPROTO_DONE); | return (IPPROTO_DONE); | ||||
} | } | ||||
Show All 37 Lines | if (fib6_lookup_nh_basic(sc->gif_fibnum, &ip6->ip6_src, 0, 0, 0, | ||||
return (0); | return (0); | ||||
if (nh6.nh_ifp != m->m_pkthdr.rcvif) | if (nh6.nh_ifp != m->m_pkthdr.rcvif) | ||||
return (0); | return (0); | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static const struct encap_config ipv6_encap_cfg = { | |||||
.proto = -1, | |||||
.min_length = sizeof(struct ip6_hdr), | |||||
.exact_match = (sizeof(struct in6_addr) << 4) + 8, | |||||
.check = gif_encapcheck, | |||||
.input = in6_gif_input | |||||
}; | |||||
int | int | ||||
in6_gif_attach(struct gif_softc *sc) | in6_gif_attach(struct gif_softc *sc) | ||||
{ | { | ||||
KASSERT(sc->gif_ecookie == NULL, ("gif_ecookie isn't NULL")); | KASSERT(sc->gif_ecookie == NULL, ("gif_ecookie isn't NULL")); | ||||
sc->gif_ecookie = encap_attach_func(AF_INET6, -1, gif_encapcheck, | sc->gif_ecookie = ip6_encap_attach(&ipv6_encap_cfg, sc, M_WAITOK); | ||||
(void *)&in6_gif_protosw, sc); | |||||
if (sc->gif_ecookie == NULL) | |||||
return (EEXIST); | |||||
return (0); | return (0); | ||||
} | } |