diff options
author | glebius <glebius@FreeBSD.org> | 2012-10-06 10:02:11 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2012-10-06 10:02:11 +0000 |
commit | f3a0231bff618f3752bf9f6827708edc3063f57d (patch) | |
tree | 889546ddb486b4afbf10cf3344d3d84a4620dcb4 /sys/netinet | |
parent | 30f3c300d8d28e84a49c574e8bd0db454de92910 (diff) | |
download | FreeBSD-src-f3a0231bff618f3752bf9f6827708edc3063f57d.zip FreeBSD-src-f3a0231bff618f3752bf9f6827708edc3063f57d.tar.gz |
A step in resolving mess with byte ordering for AF_INET. After this change:
- All packets in NETISR_IP queue are in net byte order.
- ip_input() is entered in net byte order and converts packet
to host byte order right _after_ processing pfil(9) hooks.
- ip_output() is entered in host byte order and converts packet
to net byte order right _before_ processing pfil(9) hooks.
- ip_fragment() accepts and emits packet in net byte order.
- ip_forward(), ip_mloopback() use host byte order (untouched actually).
- ip_fastforward() no longer modifies packet at all (except ip_ttl).
- Swapping of byte order there and back removed from the following modules:
pf(4), ipfw(4), enc(4), if_bridge(4).
- Swapping of byte order added to ipfilter(4), based on __FreeBSD_version
- __FreeBSD_version bumped.
- pfil(9) manual page updated.
Reviewed by: ray, luigi, eri, melifaro
Tested by: glebius (LE), ray (BE)
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_fastfwd.c | 29 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 39 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 47 |
3 files changed, 62 insertions, 53 deletions
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index a1adb85..0eaaafe 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -164,7 +164,7 @@ 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 sum, ip_len, ip_off; int error = 0; int hlen, mtu; #ifdef IPFIREWALL_FORWARD @@ -340,12 +340,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; /* @@ -472,8 +466,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) @@ -500,6 +492,8 @@ 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) @@ -515,7 +509,7 @@ passout: /* * Check if there is enough space in the interface queue */ - if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >= + if ((ifp->if_snd.ifq_len + ip_len / ifp->if_mtu + 1) >= ifp->if_snd.ifq_maxlen) { IPSTAT_INC(ips_odropped); /* would send source quench here but that is depreciated */ @@ -539,13 +533,8 @@ passout: else mtu = ifp->if_mtu; - if (ip->ip_len <= mtu || - (ifp->if_hwassist & CSUM_FRAGMENT && (ip->ip_off & IP_DF) == 0)) { - /* - * Restore packet header fields to original values - */ - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + if (ip_len <= mtu || + (ifp->if_hwassist & CSUM_FRAGMENT && (ip_off & IP_DF) == 0)) { /* * Send off the packet via outgoing interface */ @@ -555,7 +544,7 @@ passout: /* * 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); @@ -565,10 +554,6 @@ 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))) { goto drop; diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index e9388a0..c2ff860 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -380,20 +380,18 @@ ip_input(struct mbuf *m) struct ifaddr *ifa; struct ifnet *ifp; int checkif, hlen = 0; - u_short sum; + uint16_t sum, ip_len; int dchg = 0; /* dest changed after fw */ struct in_addr odst; /* original dst address */ M_ASSERTPKTHDR(m); if (m->m_flags & M_FASTFWD_OURS) { - /* - * Firewall or NAT changed destination to local. - * We expect ip_len and ip_off to be in host byte order. - */ m->m_flags &= ~M_FASTFWD_OURS; /* Set up some basics that will be used later. */ ip = mtod(m, struct ip *); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); hlen = ip->ip_hl << 2; goto ours; } @@ -458,15 +456,11 @@ ip_input(struct mbuf *m) return; #endif - /* - * Convert fields to host representation. - */ - ip->ip_len = ntohs(ip->ip_len); - if (ip->ip_len < hlen) { + ip_len = ntohs(ip->ip_len); + if (ip_len < hlen) { IPSTAT_INC(ips_badlen); goto bad; } - ip->ip_off = ntohs(ip->ip_off); /* * Check that the amount of data in the buffers @@ -474,17 +468,17 @@ ip_input(struct mbuf *m) * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ - if (m->m_pkthdr.len < ip->ip_len) { + if (m->m_pkthdr.len < ip_len) { tooshort: IPSTAT_INC(ips_tooshort); goto bad; } - if (m->m_pkthdr.len > ip->ip_len) { + if (m->m_pkthdr.len > ip_len) { if (m->m_len == m->m_pkthdr.len) { - m->m_len = ip->ip_len; - m->m_pkthdr.len = ip->ip_len; + m->m_len = ip_len; + m->m_pkthdr.len = ip_len; } else - m_adj(m, ip->ip_len - m->m_pkthdr.len); + m_adj(m, ip_len - m->m_pkthdr.len); } #ifdef IPSEC /* @@ -519,6 +513,8 @@ tooshort: #ifdef IPFIREWALL_FORWARD if (m->m_flags & M_FASTFWD_OURS) { m->m_flags &= ~M_FASTFWD_OURS; + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); goto ours; } if ((dchg = (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL)) != 0) { @@ -527,6 +523,8 @@ tooshort: * packets originally destined to us to some other directly * connected host. */ + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); ip_forward(m, dchg); return; } @@ -534,6 +532,13 @@ tooshort: passin: /* + * From now and up to output pfil(9) processing in ip_output() + * the header is in host byte order. + */ + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); + + /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message @@ -1360,6 +1365,8 @@ u_char inetctlerrmap[PRC_NCMDS] = { * * The srcrt parameter indicates whether the packet is being forwarded * via a source route. + * + * IP header in host byte order. */ void ip_forward(struct mbuf *m, int srcrt) diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index eeea58c..6ea9827 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -125,7 +125,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, int error = 0; struct sockaddr_in *dst; struct in_ifaddr *ia; - int isbroadcast, sw_csum; + int isbroadcast; + uint16_t ip_len, ip_off, sw_csum; struct route iproute; struct rtentry *rte; /* cache for ro->ro_rt */ struct in_addr odst; @@ -501,6 +502,12 @@ sendit: hlen = ip->ip_hl << 2; #endif /* IPSEC */ + /* + * To network byte order. pfil(9) hooks and ip_fragment() expect this. + */ + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + /* Jump over all PFIL processing if hooks are not active. */ if (!PFIL_HOOKED(&V_inet_pfil_hook)) goto passout; @@ -537,6 +544,8 @@ sendit: } else { if (ia != NULL) ifa_free(&ia->ia_ifa); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); goto again; /* Redo the routing table lookup. */ } } @@ -570,11 +579,16 @@ sendit: m_tag_delete(m, fwd_tag); if (ia != NULL) ifa_free(&ia->ia_ifa); + ip->ip_len = ntohs(ip->ip_len); + ip->ip_off = ntohs(ip->ip_off); goto again; } #endif /* IPFIREWALL_FORWARD */ passout: + ip_len = ntohs(ip->ip_len); + ip_off = ntohs(ip->ip_off); + /* 127/8 must not appear on wire - RFC1122. */ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { @@ -603,11 +617,9 @@ passout: * If small enough for interface, or the interface will take * care of the fragmentation for us, we can just send directly. */ - if (ip->ip_len <= mtu || + if (ip_len <= mtu || (m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 || - ((ip->ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) { - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); + ((ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) { ip->ip_sum = 0; if (sw_csum & CSUM_DELAY_IP) ip->ip_sum = in_cksum(m, hlen); @@ -641,7 +653,7 @@ passout: } /* Balk when DF bit is set or the interface didn't support TSO. */ - if ((ip->ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_TSO)) { + if ((ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_TSO)) { error = EMSGSIZE; IPSTAT_INC(ips_cantfrag); goto bad; @@ -710,8 +722,12 @@ ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, int firstlen; struct mbuf **mnext; int nfrags; + uint16_t ip_len, ip_off; + + ip_len = ntohs(ip->ip_len); + ip_off = ntohs(ip->ip_off); - if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */ + if (ip_off & IP_DF) { /* Fragmentation not allowed */ IPSTAT_INC(ips_cantfrag); return EMSGSIZE; } @@ -785,7 +801,7 @@ smart_frag_failure: * The fragments are linked off the m_nextpkt of the original * packet, which after processing serves as the first fragment. */ - for (nfrags = 1; off < ip->ip_len; off += len, nfrags++) { + for (nfrags = 1; off < ip_len; off += len, nfrags++) { struct ip *mhip; /* ip header on the fragment */ struct mbuf *m; int mhlen = sizeof (struct ip); @@ -811,10 +827,10 @@ smart_frag_failure: mhip->ip_hl = mhlen >> 2; } m->m_len = mhlen; - /* XXX do we need to add ip->ip_off below ? */ - mhip->ip_off = ((off - hlen) >> 3) + ip->ip_off; - if (off + len >= ip->ip_len) { /* last fragment */ - len = ip->ip_len - off; + /* XXX do we need to add ip_off below ? */ + mhip->ip_off = ((off - hlen) >> 3) + ip_off; + if (off + len >= ip_len) { /* last fragment */ + len = ip_len - off; m->m_flags |= M_LASTFRAG; } else mhip->ip_off |= IP_MF; @@ -849,11 +865,10 @@ smart_frag_failure: * Update first fragment by trimming what's been copied out * and updating header. */ - m_adj(m0, hlen + firstlen - ip->ip_len); + m_adj(m0, hlen + firstlen - ip_len); m0->m_pkthdr.len = hlen + firstlen; ip->ip_len = htons((u_short)m0->m_pkthdr.len); - ip->ip_off |= IP_MF; - ip->ip_off = htons(ip->ip_off); + ip->ip_off = htons(ip_off | IP_MF); ip->ip_sum = 0; if (sw_csum & CSUM_DELAY_IP) ip->ip_sum = in_cksum(m0, hlen); @@ -1279,6 +1294,8 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) * calls the output routine of the loopback "driver", but with an interface * pointer that might NOT be a loopback interface -- evil, but easier than * replicating that code here. + * + * IP header in host byte order. */ static void ip_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in *dst, |