Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet6/in6_gif.c
Show First 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | |||||
#include <netinet/ip_encap.h> | #include <netinet/ip_encap.h> | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
#include <netinet6/ip6_var.h> | #include <netinet6/ip6_var.h> | ||||
#include <netinet6/in6_var.h> | #include <netinet6/in6_var.h> | ||||
#include <netinet6/scope6_var.h> | #include <netinet6/scope6_var.h> | ||||
#include <netinet6/ip6_ecn.h> | #include <netinet6/ip6_ecn.h> | ||||
#include <netinet6/in6_fib.h> | #include <netinet6/in6_fib.h> | ||||
#include <net/route/route_cache.h> | |||||
#include <net/if_gif.h> | #include <net/if_gif.h> | ||||
#define GIF_HLIM 30 | #define GIF_HLIM 30 | ||||
VNET_DEFINE_STATIC(int, ip6_gif_hlim) = GIF_HLIM; | VNET_DEFINE_STATIC(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, | SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, | ||||
▲ Show 20 Lines • Show All 164 Lines • ▼ Show 20 Lines | if (error == EEXIST) { | ||||
error = 0; | error = 0; | ||||
break; | break; | ||||
} | } | ||||
ip6 = malloc(sizeof(*ip6), M_GIF, M_WAITOK | M_ZERO); | ip6 = malloc(sizeof(*ip6), M_GIF, M_WAITOK | M_ZERO); | ||||
ip6->ip6_src = src->sin6_addr; | ip6->ip6_src = src->sin6_addr; | ||||
ip6->ip6_dst = dst->sin6_addr; | ip6->ip6_dst = dst->sin6_addr; | ||||
ip6->ip6_vfc = IPV6_VERSION; | ip6->ip6_vfc = IPV6_VERSION; | ||||
if (sc->gif_family != 0) { | if (sc->gif_family != 0) { | ||||
route_cache_unsubscribe_rib_event(&sc->gif_rc); | |||||
/* Detach existing tunnel first */ | /* Detach existing tunnel first */ | ||||
CK_LIST_REMOVE(sc, srchash); | CK_LIST_REMOVE(sc, srchash); | ||||
CK_LIST_REMOVE(sc, chain); | CK_LIST_REMOVE(sc, chain); | ||||
GIF_WAIT(); | GIF_WAIT(); | ||||
free(sc->gif_hdr, M_GIF); | free(sc->gif_hdr, M_GIF); | ||||
route_cache_uninit(&sc->gif_rc, sc->gif_family); | |||||
/* XXX: should we notify about link state change? */ | /* XXX: should we notify about link state change? */ | ||||
} | } | ||||
sc->gif_family = AF_INET6; | sc->gif_family = AF_INET6; | ||||
sc->gif_ip6hdr = ip6; | sc->gif_ip6hdr = ip6; | ||||
in6_gif_attach(sc); | in6_gif_attach(sc); | ||||
route_cache_init(&sc->gif_rc, sc->gif_family); | |||||
in6_gif_set_running(sc); | in6_gif_set_running(sc); | ||||
route_cache_subscribe_rib_event(&sc->gif_rc, sc->gif_family, | |||||
sc->gif_fibnum); | |||||
break; | break; | ||||
case SIOCGIFPSRCADDR_IN6: | case SIOCGIFPSRCADDR_IN6: | ||||
case SIOCGIFPDSTADDR_IN6: | case SIOCGIFPDSTADDR_IN6: | ||||
if (sc->gif_family != AF_INET6) { | if (sc->gif_family != AF_INET6) { | ||||
error = EADDRNOTAVAIL; | error = EADDRNOTAVAIL; | ||||
break; | break; | ||||
} | } | ||||
src = (struct sockaddr_in6 *)&ifr->ifr_addr; | src = (struct sockaddr_in6 *)&ifr->ifr_addr; | ||||
Show All 12 Lines | in6_gif_ioctl(struct gif_softc *sc, u_long cmd, caddr_t data) | ||||
return (error); | return (error); | ||||
} | } | ||||
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) | ||||
{ | { | ||||
struct gif_softc *sc = ifp->if_softc; | struct gif_softc *sc = ifp->if_softc; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
struct route_in6 *ro; | |||||
int len; | int len; | ||||
int error; | |||||
/* prepend new IP header */ | /* prepend new IP header */ | ||||
NET_EPOCH_ASSERT(); | NET_EPOCH_ASSERT(); | ||||
len = sizeof(struct ip6_hdr); | len = sizeof(struct ip6_hdr); | ||||
#ifndef __NO_STRICT_ALIGNMENT | #ifndef __NO_STRICT_ALIGNMENT | ||||
if (proto == IPPROTO_ETHERIP) | if (proto == IPPROTO_ETHERIP) | ||||
len += ETHERIP_ALIGN; | len += ETHERIP_ALIGN; | ||||
#endif | #endif | ||||
Show All 12 Lines | #endif | ||||
ip6 = mtod(m, struct ip6_hdr *); | ip6 = mtod(m, struct ip6_hdr *); | ||||
MPASS(sc->gif_family == AF_INET6); | MPASS(sc->gif_family == AF_INET6); | ||||
bcopy(sc->gif_ip6hdr, ip6, sizeof(struct ip6_hdr)); | bcopy(sc->gif_ip6hdr, ip6, sizeof(struct ip6_hdr)); | ||||
ip6->ip6_flow |= htonl((uint32_t)ecn << 20); | ip6->ip6_flow |= htonl((uint32_t)ecn << 20); | ||||
ip6->ip6_nxt = proto; | ip6->ip6_nxt = proto; | ||||
ip6->ip6_hlim = V_ip6_gif_hlim; | ip6->ip6_hlim = V_ip6_gif_hlim; | ||||
ro = route_cache_acquire6(&sc->gif_rc); | |||||
/* | /* | ||||
* 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)); | error = ip6_output(m, 0, ro, IPV6_MINMTU, 0, NULL, NULL); | ||||
route_cache_release6(ro); | |||||
return (error); | |||||
} | } | ||||
static int | static int | ||||
in6_gif_input(struct mbuf *m, int off, int proto, void *arg) | in6_gif_input(struct mbuf *m, int off, int proto, void *arg) | ||||
{ | { | ||||
struct gif_softc *sc = arg; | struct gif_softc *sc = arg; | ||||
struct ifnet *gifp; | struct ifnet *gifp; | ||||
struct ip6_hdr *ip6; | struct ip6_hdr *ip6; | ||||
▲ Show 20 Lines • Show All 149 Lines • Show Last 20 Lines |