diff options
author | Renato Botelho <renato@netgate.com> | 2016-02-22 17:13:31 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2016-02-22 17:13:31 -0300 |
commit | f1832699781cbd404f0f9b60a41fe59c8cc4dd1a (patch) | |
tree | d49e1d5035507aac3542f1e5bbf425b0a97b9d61 /sys/netinet | |
parent | 0a3437aa52c010dc2ab10b9778a383fef436382c (diff) | |
parent | b899cad3faf3673f41a3fcf021164dcd7ee19a7e (diff) | |
download | FreeBSD-src-f1832699781cbd404f0f9b60a41fe59c8cc4dd1a.zip FreeBSD-src-f1832699781cbd404f0f9b60a41fe59c8cc4dd1a.tar.gz |
Merge remote-tracking branch 'origin/stable/10' into devel
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/in_var.h | 2 | ||||
-rw-r--r-- | sys/netinet/ip_fastfwd.c | 117 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 12 |
3 files changed, 113 insertions, 18 deletions
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 511ba26..8657dbb 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -452,7 +452,7 @@ int in_scrubprefix(struct in_ifaddr *, u_int); void ip_input(struct mbuf *); int in_ifadown(struct ifaddr *ifa, int); void in_ifscrub(struct ifnet *, struct in_ifaddr *, u_int); -struct mbuf *ip_tryforward(struct mbuf *); +struct mbuf *ip_fastforward(struct mbuf *); void *in_domifattach(struct ifnet *); void in_domifdetach(struct ifnet *, void *); diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 9c3ea66..3db6311 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -109,6 +109,12 @@ __FBSDID("$FreeBSD$"); #include <machine/in_cksum.h> +static VNET_DEFINE(int, ipfastforward_active); +#define V_ipfastforward_active VNET(ipfastforward_active) + +SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, fastforwarding, CTLFLAG_RW, + &VNET_NAME(ipfastforward_active), 0, "Enable fast IP forwarding"); + static struct sockaddr_in * ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) { @@ -153,7 +159,7 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) * to ip_input for full processing. */ struct mbuf * -ip_tryforward(struct mbuf *m) +ip_fastforward(struct mbuf *m) { struct ip *ip; struct mbuf *m0 = NULL; @@ -161,20 +167,119 @@ ip_tryforward(struct mbuf *m) struct sockaddr_in *dst = NULL; struct ifnet *ifp; struct in_addr odest, dest; - uint16_t ip_len, ip_off; + uint16_t sum, ip_len, ip_off; int error = 0; - int mtu; + int hlen, mtu; struct m_tag *fwd_tag = NULL; /* * Are we active and forwarding packets? */ + if (!V_ipfastforward_active || !V_ipforwarding) + return m; M_ASSERTVALID(m); M_ASSERTPKTHDR(m); bzero(&ro, sizeof(ro)); + /* + * Step 1: check for packet drop conditions (and sanity checks) + */ + + /* + * Is entire packet big enough? + */ + if (m->m_pkthdr.len < sizeof(struct ip)) { + IPSTAT_INC(ips_tooshort); + goto drop; + } + + /* + * Is first mbuf large enough for ip header and is header present? + */ + if (m->m_len < sizeof (struct ip) && + (m = m_pullup(m, sizeof (struct ip))) == NULL) { + IPSTAT_INC(ips_toosmall); + return NULL; /* mbuf already free'd */ + } + + ip = mtod(m, struct ip *); + + /* + * Is it IPv4? + */ + if (ip->ip_v != IPVERSION) { + IPSTAT_INC(ips_badvers); + goto drop; + } + + /* + * Is IP header length correct and is it in first mbuf? + */ + hlen = ip->ip_hl << 2; + if (hlen < sizeof(struct ip)) { /* minimum header length */ + IPSTAT_INC(ips_badhlen); + goto drop; + } + if (hlen > m->m_len) { + if ((m = m_pullup(m, hlen)) == NULL) { + IPSTAT_INC(ips_badhlen); + return NULL; /* mbuf already free'd */ + } + ip = mtod(m, struct ip *); + } + + /* + * Checksum correct? + */ + if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) + sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID); + else { + if (hlen == sizeof(struct ip)) + sum = in_cksum_hdr(ip); + else + sum = in_cksum(m, hlen); + } + if (sum) { + IPSTAT_INC(ips_badsum); + goto drop; + } + + /* + * Remember that we have checked the IP header and found it valid. + */ + m->m_pkthdr.csum_flags |= (CSUM_IP_CHECKED | CSUM_IP_VALID); + + ip_len = ntohs(ip->ip_len); + + /* + * Is IP length longer than packet we have got? + */ + if (m->m_pkthdr.len < ip_len) { + IPSTAT_INC(ips_tooshort); + goto drop; + } + + /* + * Is packet longer than IP header tells us? If yes, truncate packet. + */ + if (m->m_pkthdr.len > ip_len) { + if (m->m_len == m->m_pkthdr.len) { + m->m_len = ip_len; + m->m_pkthdr.len = ip_len; + } else + m_adj(m, ip_len - m->m_pkthdr.len); + } + + /* + * Is packet from or to 127/8? + */ + if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || + (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { + IPSTAT_INC(ips_badaddr); + goto drop; + } #ifdef ALTQ /* @@ -185,10 +290,12 @@ ip_tryforward(struct mbuf *m) #endif /* - * Only IP packets without options + * Step 2: fallback conditions to normal ip_input path processing */ - ip = mtod(m, struct ip *); + /* + * Only IP packets without options + */ if (ip->ip_hl != (sizeof(struct ip) >> 2)) { if (V_ip_doopts == 1) return m; diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 1eefadc..287417c 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -77,8 +77,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_carp.h> #ifdef IPSEC #include <netinet/ip_ipsec.h> -#include <netipsec/ipsec.h> -#include <netipsec/key.h> #endif /* IPSEC */ #include <sys/socketvar.h> @@ -469,22 +467,12 @@ tooshort: } else m_adj(m, ip_len - m->m_pkthdr.len); } - /* Try to forward the packet, but if we fail continue */ #ifdef IPSEC - /* For now we do not handle IPSEC in tryforward. */ - if (!key_havesp(IPSEC_DIR_INBOUND) && !key_havesp(IPSEC_DIR_OUTBOUND) && - (V_ipforwarding == 1)) - if (ip_tryforward(m) == NULL) - return; /* * Bypass packet filtering for packets previously handled by IPsec. */ if (ip_ipsec_filtertunnel(m)) goto passin; -#else - if (V_ipforwarding == 1) - if (ip_tryforward(m) == NULL) - return; #endif /* IPSEC */ /* |