diff options
Diffstat (limited to 'freebsd/sys/netinet/ip_fastfwd.c')
-rw-r--r-- | freebsd/sys/netinet/ip_fastfwd.c | 181 |
1 files changed, 27 insertions, 154 deletions
diff --git a/freebsd/sys/netinet/ip_fastfwd.c b/freebsd/sys/netinet/ip_fastfwd.c index 863b9a16..19dfb1ab 100644 --- a/freebsd/sys/netinet/ip_fastfwd.c +++ b/freebsd/sys/netinet/ip_fastfwd.c @@ -78,7 +78,6 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <rtems/bsd/local/opt_ipfw.h> #include <rtems/bsd/local/opt_ipstealth.h> #include <rtems/bsd/sys/param.h> @@ -87,6 +86,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/protosw.h> +#include <sys/sdt.h> #include <sys/socket.h> #include <sys/sysctl.h> @@ -99,6 +99,7 @@ __FBSDID("$FreeBSD$"); #include <net/vnet.h> #include <netinet/in.h> +#include <netinet/in_kdtrace.h> #include <netinet/in_systm.h> #include <netinet/in_var.h> #include <netinet/ip.h> @@ -108,12 +109,6 @@ __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) { @@ -158,7 +153,7 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m) * to ip_input for full processing. */ struct mbuf * -ip_fastforward(struct mbuf *m) +ip_tryforward(struct mbuf *m) { struct ip *ip; struct mbuf *m0 = NULL; @@ -166,119 +161,20 @@ ip_fastforward(struct mbuf *m) struct sockaddr_in *dst = NULL; struct ifnet *ifp; struct in_addr odest, dest; - u_short sum, ip_len; + uint16_t ip_len, ip_off; int error = 0; - int hlen, mtu; + int 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 /* @@ -289,16 +185,14 @@ ip_fastforward(struct mbuf *m) #endif /* - * Step 2: fallback conditions to normal ip_input path processing - */ - - /* * Only IP packets without options */ + ip = mtod(m, struct ip *); + if (ip->ip_hl != (sizeof(struct ip) >> 2)) { - if (ip_doopts == 1) + if (V_ip_doopts == 1) return m; - else if (ip_doopts == 2) { + else if (V_ip_doopts == 2) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB, 0, 0); return NULL; /* mbuf already free'd */ @@ -312,7 +206,7 @@ ip_fastforward(struct mbuf *m) * * XXX: Probably some of these checks could be direct drop * conditions. However it is not clear whether there are some - * hacks or obscure behaviours which make it neccessary to + * hacks or obscure behaviours which make it necessary to * let ip_input handle it. We play safe here and let ip_input * deal with it until it is proven that we can directly drop it. */ @@ -340,12 +234,6 @@ ip_fastforward(struct mbuf *m) * Step 3: incoming packet firewall processing */ - /* - * Convert to host representation - */ - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); - odest.s_addr = dest.s_addr = ip->ip_dst.s_addr; /* @@ -464,8 +352,6 @@ passin: forwardlocal: /* * Return packet for processing by ip_input(). - * Keep host byte order as expected at ip_input's - * "ours"-label. */ m->m_flags |= M_FASTFWD_OURS; if (ro.ro_rt) @@ -491,29 +377,18 @@ passout: /* * Step 6: send off the packet */ + ip_len = ntohs(ip->ip_len); + ip_off = ntohs(ip->ip_off); /* * Check if route is dampned (when ARP is unable to resolve) */ if ((ro.ro_rt->rt_flags & RTF_REJECT) && - (ro.ro_rt->rt_rmx.rmx_expire == 0 || - time_uptime < ro.ro_rt->rt_rmx.rmx_expire)) { + (ro.ro_rt->rt_expire == 0 || time_uptime < ro.ro_rt->rt_expire)) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); goto consumed; } -#ifndef ALTQ - /* - * Check if there is enough space in the interface queue - */ - if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >= - ifp->if_snd.ifq_maxlen) { - IPSTAT_INC(ips_odropped); - /* would send source quench here but that is depreciated */ - goto drop; - } -#endif - /* * Check if media link state of interface is not down */ @@ -525,28 +400,27 @@ passout: /* * Check if packet fits MTU or if hardware will fragment for us */ - if (ro.ro_rt->rt_rmx.rmx_mtu) - mtu = min(ro.ro_rt->rt_rmx.rmx_mtu, ifp->if_mtu); + if (ro.ro_rt->rt_mtu) + mtu = min(ro.ro_rt->rt_mtu, ifp->if_mtu); else mtu = ifp->if_mtu; - if (ip->ip_len <= mtu || - (ifp->if_hwassist & CSUM_FRAGMENT && (ip->ip_off & IP_DF) == 0)) { + if (ip_len <= mtu) { /* - * Restore packet header fields to original values + * Avoid confusing lower layers. */ - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + m_clrprotoflags(m); /* * Send off the packet via outgoing interface */ + IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, &ro); } else { /* * Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery */ - if (ip->ip_off & IP_DF) { + if (ip_off & IP_DF) { IPSTAT_INC(ips_cantfrag); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0, mtu); @@ -556,14 +430,8 @@ passout: * We have to fragment the packet */ m->m_pkthdr.csum_flags |= CSUM_IP; - /* - * ip_fragment expects ip_len and ip_off in host byte - * order but returns all packets in network byte order - */ - if (ip_fragment(ip, &m, mtu, ifp->if_hwassist, - (~ifp->if_hwassist & CSUM_DELAY_IP))) { + if (ip_fragment(ip, &m, mtu, ifp->if_hwassist)) goto drop; - } KASSERT(m != NULL, ("null mbuf and no error")); /* * Send off the fragments via outgoing interface @@ -572,7 +440,12 @@ passout: do { m0 = m->m_nextpkt; m->m_nextpkt = NULL; + /* + * Avoid confusing lower layers. + */ + m_clrprotoflags(m); + IP_PROBE(send, NULL, NULL, ip, ifp, ip, NULL); error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, &ro); if (error) @@ -592,7 +465,7 @@ passout: if (error != 0) IPSTAT_INC(ips_odropped); else { - ro.ro_rt->rt_rmx.rmx_pksent++; + counter_u64_add(ro.ro_rt->rt_pksent, 1); IPSTAT_INC(ips_forward); IPSTAT_INC(ips_fastforward); } |