Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet/ip_gre.c
Show All 39 Lines | |||||
#include "opt_inet.h" | #include "opt_inet.h" | ||||
#include "opt_inet6.h" | #include "opt_inet6.h" | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/mbuf.h> | #include <sys/mbuf.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/socketvar.h> | #include <sys/socketvar.h> | ||||
#include <sys/protosw.h> | |||||
#include <sys/errno.h> | #include <sys/errno.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/rmlock.h> | #include <sys/rmlock.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <net/ethernet.h> | #include <net/ethernet.h> | ||||
#include <net/if.h> | #include <net/if.h> | ||||
#include <net/if_var.h> | #include <net/if_var.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/ip.h> | #include <netinet/ip.h> | ||||
#include <netinet/ip_encap.h> | #include <netinet/ip_encap.h> | ||||
#include <netinet/ip_var.h> | #include <netinet/ip_var.h> | ||||
#ifdef INET6 | #ifdef INET6 | ||||
#include <netinet/ip6.h> | #include <netinet/ip6.h> | ||||
#endif | #endif | ||||
#include <net/if_gre.h> | #include <net/if_gre.h> | ||||
extern struct domain inetdomain; | |||||
static const struct protosw in_gre_protosw = { | |||||
.pr_type = SOCK_RAW, | |||||
.pr_domain = &inetdomain, | |||||
.pr_protocol = IPPROTO_GRE, | |||||
.pr_flags = PR_ATOMIC|PR_ADDR, | |||||
.pr_input = gre_input, | |||||
.pr_output = rip_output, | |||||
.pr_ctlinput = rip_ctlinput, | |||||
.pr_ctloutput = rip_ctloutput, | |||||
.pr_usrreqs = &rip_usrreqs | |||||
}; | |||||
#define GRE_TTL 30 | #define GRE_TTL 30 | ||||
VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL; | VNET_DEFINE(int, ip_gre_ttl) = GRE_TTL; | ||||
#define V_ip_gre_ttl VNET(ip_gre_ttl) | #define V_ip_gre_ttl VNET(ip_gre_ttl) | ||||
SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW, | SYSCTL_INT(_net_inet_ip, OID_AUTO, grettl, CTLFLAG_VNET | CTLFLAG_RW, | ||||
&VNET_NAME(ip_gre_ttl), 0, ""); | &VNET_NAME(ip_gre_ttl), 0, "Default TTL value for encapsulated packets"); | ||||
static int | static int | ||||
in_gre_encapcheck(const struct mbuf *m, int off, int proto, void *arg) | in_gre_encapcheck(const struct mbuf *m, int off, int proto, void *arg) | ||||
{ | { | ||||
GRE_RLOCK_TRACKER; | GRE_RLOCK_TRACKER; | ||||
struct gre_softc *sc; | struct gre_softc *sc; | ||||
struct ip *ip; | struct ip *ip; | ||||
sc = (struct gre_softc *)arg; | sc = (struct gre_softc *)arg; | ||||
if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0) | if ((GRE2IFP(sc)->if_flags & IFF_UP) == 0) | ||||
return (0); | return (0); | ||||
M_ASSERTPKTHDR(m); | M_ASSERTPKTHDR(m); | ||||
/* | |||||
* We expect that payload contains at least IPv4 | |||||
* or IPv6 packet. | |||||
*/ | |||||
if (m->m_pkthdr.len < sizeof(struct greip) + sizeof(struct ip)) | |||||
return (0); | |||||
GRE_RLOCK(sc); | GRE_RLOCK(sc); | ||||
if (sc->gre_family == 0) | if (sc->gre_family == 0) | ||||
goto bad; | goto bad; | ||||
KASSERT(sc->gre_family == AF_INET, | KASSERT(sc->gre_family == AF_INET, | ||||
("wrong gre_family: %d", sc->gre_family)); | ("wrong gre_family: %d", sc->gre_family)); | ||||
ip = mtod(m, struct ip *); | ip = mtod(m, struct ip *); | ||||
if (sc->gre_oip.ip_src.s_addr != ip->ip_dst.s_addr || | if (sc->gre_oip.ip_src.s_addr != ip->ip_dst.s_addr || | ||||
sc->gre_oip.ip_dst.s_addr != ip->ip_src.s_addr) | sc->gre_oip.ip_dst.s_addr != ip->ip_src.s_addr) | ||||
goto bad; | goto bad; | ||||
GRE_RUNLOCK(sc); | GRE_RUNLOCK(sc); | ||||
return (32 * 2); | return (32 * 3); /* src + dst + gre_hdr */ | ||||
bad: | bad: | ||||
GRE_RUNLOCK(sc); | GRE_RUNLOCK(sc); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
in_gre_output(struct mbuf *m, int af, int hlen) | in_gre_output(struct mbuf *m, int af, int hlen) | ||||
{ | { | ||||
Show All 19 Lines | case AF_INET6: | ||||
break; | break; | ||||
#endif | #endif | ||||
} | } | ||||
gi->gi_ip.ip_ttl = V_ip_gre_ttl; | gi->gi_ip.ip_ttl = V_ip_gre_ttl; | ||||
gi->gi_ip.ip_len = htons(m->m_pkthdr.len); | gi->gi_ip.ip_len = htons(m->m_pkthdr.len); | ||||
return (ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL)); | return (ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL)); | ||||
} | } | ||||
static const struct encap_config ipv4_encap_cfg = { | |||||
.proto = IPPROTO_GRE, | |||||
.min_length = sizeof(struct greip) + sizeof(struct ip), | |||||
.exact_match = (sizeof(in_addr_t) << 4) + 32, | |||||
.check = in_gre_encapcheck, | |||||
.input = gre_input | |||||
}; | |||||
int | int | ||||
in_gre_attach(struct gre_softc *sc) | in_gre_attach(struct gre_softc *sc) | ||||
{ | { | ||||
KASSERT(sc->gre_ecookie == NULL, ("gre_ecookie isn't NULL")); | KASSERT(sc->gre_ecookie == NULL, ("gre_ecookie isn't NULL")); | ||||
sc->gre_ecookie = encap_attach_func(AF_INET, IPPROTO_GRE, | sc->gre_ecookie = ip_encap_attach(&ipv4_encap_cfg, sc, M_WAITOK); | ||||
in_gre_encapcheck, &in_gre_protosw, sc); | |||||
if (sc->gre_ecookie == NULL) | |||||
return (EEXIST); | |||||
return (0); | return (0); | ||||
} | } |