46#include <sys/socket.h>
47#include <sys/socketvar.h>
48#include <sys/sockio.h>
51#include <sys/kernel.h>
52#include <sys/sysctl.h>
53#include <sys/malloc.h>
57#include <net/if_var.h>
73#include <net/if_gre.h>
74#include <machine/in_cksum.h>
78#define V_ip_gre_ttl VNET(ip_gre_ttl)
79SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW,
80 &VNET_NAME(ip_gre_ttl), 0,
"Default TTL value for encapsulated packets");
89#define V_ipv4_sockets VNET(ipv4_sockets)
90#define V_ipv4_hashtbl VNET(ipv4_hashtbl)
91#define V_ipv4_srchashtbl VNET(ipv4_srchashtbl)
92#define GRE_HASH(src, dst) (V_ipv4_hashtbl[\
93 in_gre_hashval((src), (dst)) & (GRE_HASH_SIZE - 1)])
94#define GRE_SRCHASH(src) (V_ipv4_srchashtbl[\
95 fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)])
96#define GRE_SOCKHASH(src) (V_ipv4_sockets[\
97 fnv_32_buf(&(src), sizeof(src), FNV1_32_INIT) & (GRE_HASH_SIZE - 1)])
98#define GRE_HASH_SC(sc) GRE_HASH((sc)->gre_oip.ip_src.s_addr,\
99 (sc)->gre_oip.ip_dst.s_addr)
106 ret = fnv_32_buf(&src,
sizeof(src), FNV1_32_INIT);
107 return (fnv_32_buf(&dst,
sizeof(dst), ret));
110static struct gre_socket*
113 struct gre_socket *gs;
128 struct gre_list *head;
129 struct gre_softc *tmp;
130 struct gre_socket *gs;
132 if (sc->gre_family == AF_INET &&
133 sc->gre_oip.ip_src.s_addr == src &&
134 sc->gre_oip.ip_dst.s_addr == dst &&
135 (sc->gre_options & GRE_UDPENCAP) == (opts & GRE_UDPENCAP))
138 if (opts & GRE_UDPENCAP) {
146 CK_LIST_FOREACH(tmp, head, chain) {
149 if (tmp->gre_oip.ip_src.s_addr == src &&
150 tmp->gre_oip.ip_dst.s_addr == dst)
151 return (EADDRNOTAVAIL);
160 struct gre_softc *sc;
166 ip = mtod(m,
const struct ip *);
168 ip->ip_src.s_addr), chain) {
174 sc->gre_oip.ip_dst.s_addr ==
ip->ip_src.s_addr) {
175 if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0)
192 GRE2IFP(sc)->if_drv_flags |= IFF_DRV_RUNNING;
194 GRE2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
207 struct gre_softc *sc;
224 const struct sockaddr *sa,
void *ctx)
226 struct gre_socket *gs;
227 struct gre_softc *sc;
232 gs = (
struct gre_socket *)ctx;
233 dst = ((
const struct sockaddr_in *)sa)->sin_addr.s_addr;
234 CK_LIST_FOREACH(sc, &gs->list, chain) {
235 if (sc->gre_oip.ip_dst.s_addr == dst)
238 if (sc != NULL && (GRE2IFP(sc)->if_flags & IFF_UP) != 0){
251 struct gre_socket *gs;
263 addr = sc->gre_oip.ip_src.s_addr;
267 if (s->
addr != addr) {
268 if (CK_LIST_EMPTY(&gs->list)) {
269 CK_LIST_REMOVE(gs, chain);
271 NET_EPOCH_CALL(gre_sofree, &gs->epoch_ctx);
273 gs = sc->gre_so = NULL;
284 s = malloc(
sizeof(*s), M_GRE, M_WAITOK | M_ZERO);
288 error = socreate(sc->gre_family, &gs->so,
292 if_printf(GRE2IFP(sc),
293 "cannot create socket: %d\n", error);
301 if_printf(GRE2IFP(sc),
302 "cannot set UDP tunneling: %d\n", error);
306 memset(&sopt, 0,
sizeof(sopt));
307 sopt.sopt_dir = SOPT_SET;
309 sopt.sopt_name = IP_BINDANY;
310 sopt.sopt_val = &value;
311 sopt.sopt_valsize =
sizeof(value);
313 error = sosetopt(gs->so, &sopt);
315 if_printf(GRE2IFP(sc),
316 "cannot set IP_BINDANY opt: %d\n", error);
320 memset(&sin, 0,
sizeof(sin));
325 error = sobind(gs->so, (
struct sockaddr *)&sin,
328 if_printf(GRE2IFP(sc),
329 "cannot bind socket: %d\n", error);
338 CK_LIST_INSERT_HEAD(&gs->list, sc, chain);
350 struct epoch_tracker et;
354 if (sc->gre_options & GRE_UDPENCAP) {
355 sc->gre_csumflags = CSUM_UDP;
356 sc->gre_hlen =
sizeof(
struct greudp);
358 gh = &sc->gre_udphdr->gi_gre;
359 gre_update_udphdr(sc, &sc->gre_udp,
361 sc->gre_oip.ip_dst.s_addr, 0));
363 sc->gre_hlen =
sizeof(
struct greip);
364 sc->gre_oip.ip_p = IPPROTO_GRE;
365 gh = &sc->gre_iphdr->gi_gre;
368 sc->gre_oip.ip_hl =
sizeof(
struct ip) >> 2;
369 gre_update_hdr(sc, gh);
375 if (sc->gre_options & GRE_UDPENCAP) {
381 CK_LIST_INSERT_HEAD(&
GRE_SRCHASH(sc->gre_oip.ip_src.s_addr),
397 MPASS(cmd == GRESKEY || cmd == GRESOPTS || cmd == GRESPORT);
398 MPASS(sc->gre_family == AF_INET);
405 if (cmd == GRESOPTS &&
406 (sc->gre_options & GRE_UDPENCAP) != (value & GRE_UDPENCAP) &&
408 sc->gre_oip.ip_dst.s_addr, value) == EADDRNOTAVAIL)
411 CK_LIST_REMOVE(sc, chain);
412 CK_LIST_REMOVE(sc, srchash);
419 sc->gre_options = value;
422 sc->gre_port = value;
428 free(sc->gre_hdr, M_GRE);
436 struct ifreq *ifr = (
struct ifreq *)data;
456 error = EADDRNOTAVAIL;
466 if (error == EADDRNOTAVAIL)
468 if (error == EEXIST) {
473 ip = malloc(
sizeof(
struct greudp) + 3 *
sizeof(
uint32_t),
474 M_GRE, M_WAITOK | M_ZERO);
477 if (sc->gre_family != 0) {
479 CK_LIST_REMOVE(sc, chain);
480 CK_LIST_REMOVE(sc, srchash);
482 free(sc->gre_hdr, M_GRE);
485 sc->gre_family = AF_INET;
488 sc->gre_iseq = UINT32_MAX;
492 free(sc->gre_hdr, M_GRE);
495 case SIOCGIFPSRCADDR:
496 case SIOCGIFPDSTADDR:
497 if (sc->gre_family != AF_INET) {
498 error = EADDRNOTAVAIL;
502 memset(src, 0,
sizeof(*src));
505 src->
sin_addr = (cmd == SIOCGIFPSRCADDR) ?
506 sc->gre_oip.ip_src: sc->gre_oip.ip_dst;
507 error = prison_if(curthread->td_ucred, (
struct sockaddr *)src);
509 memset(src, 0,
sizeof(*src));
520 gi = mtod(m,
struct greip *);
528 m_copydata(m, hlen + offsetof(
struct ip,
ip_tos),
529 sizeof(u_char), &gi->gi_ip.ip_tos);
530 m_copydata(m, hlen + offsetof(
struct ip,
ip_id),
531 sizeof(u_short), (caddr_t)&gi->gi_ip.ip_id);
535 gi->gi_ip.ip_tos = 0;
541 gi->gi_ip.ip_len = htons(m->m_pkthdr.len);
548 .
proto = IPPROTO_GRE,
549 .min_length =
sizeof(
struct greip) + sizeof(struct
ip),
559 if (!IS_DEFAULT_VNET(curvnet))
570 if (IS_DEFAULT_VNET(curvnet)) {
bool in_localip(struct in_addr in)
u_short in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
int ip_encap_detach(const struct encaptab *)
int ip_encap_unregister_srcaddr(const struct srcaddrtab *)
const struct encaptab * ip_encap_attach(const struct encap_config *, void *arg, int mflags)
const struct srcaddrtab * ip_encap_register_srcaddr(encap_srcaddr_t, void *arg, int mflags)
static void in_gre_srcaddr(void *arg __unused, const struct sockaddr *sa, int event __unused)
int in_gre_setopts(struct gre_softc *sc, u_long cmd, uint32_t value)
static const struct encap_config ipv4_encap_cfg
VNET_DEFINE(int, ip_gre_ttl)
SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets")
int in_gre_output(struct mbuf *m, int af, int hlen)
static void in_gre_udp_input(struct mbuf *m, int off, struct inpcb *inp, const struct sockaddr *sa, void *ctx)
static uint32_t in_gre_hashval(in_addr_t src, in_addr_t dst)
static int in_gre_setup_socket(struct gre_softc *sc)
int in_gre_ioctl(struct gre_softc *sc, u_long cmd, caddr_t data)
static int in_gre_lookup(const struct mbuf *m, int off, int proto, void **arg)
static int in_gre_attach(struct gre_softc *sc)
#define GRE_SOCKHASH(src)
static int in_gre_checkdup(const struct gre_softc *sc, in_addr_t src, in_addr_t dst, uint32_t opts)
#define GRE_HASH(src, dst)
#define V_ipv4_srchashtbl
VNET_DEFINE_STATIC(struct gre_sockets *, ipv4_sockets)
static const struct encaptab * ecookie
static void in_gre_set_running(struct gre_softc *sc)
static struct gre_socket * in_gre_lookup_socket(in_addr_t addr)
static const struct srcaddrtab * ipv4_srcaddrtab
void ip_fillid(struct ip *ip)
int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp)
struct in_addr ip_src ip_dst
int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, udp_tun_icmp_t i, void *ctx)