From 23e9c6dc1ecc5660dbf815858ca2291f550c0951 Mon Sep 17 00:00:00 2001 From: Gleb Smirnoff Date: Mon, 8 Oct 2012 08:03:58 +0000 Subject: [PATCH] After r241245 it appeared that in_delayed_cksum(), which still expects host byte order, was sometimes called with net byte order. Since we are moving towards net byte order throughout the stack, the function was converted to expect net byte order, and its consumers fixed appropriately: - ip_output(), ipfilter(4) not changed, since already call in_delayed_cksum() with header in net byte order. - divert(4), ng_nat(4), ipfw_nat(4) now don't need to swap byte order there and back. - mrouting code and IPv6 ipsec now need to switch byte order there and back, but I hope, this is temporary solution. - In ipsec(4) shifted switch to net byte order prior to in_delayed_cksum(). - pf_route() catches up on r241245 changes to ip_output(). --- sys/netgraph/ng_nat.c | 6 +++--- sys/netinet/ip_divert.c | 2 -- sys/netinet/ip_ipsec.c | 5 +++-- sys/netinet/ip_mroute.c | 3 +++ sys/netinet/ip_output.c | 5 +++-- sys/netinet6/ip6_ipsec.c | 6 ++++++ sys/netpfil/ipfw/ip_fw_nat.c | 7 +++---- sys/netpfil/pf/pf.c | 15 ++++++--------- 8 files changed, 27 insertions(+), 22 deletions(-) diff --git a/sys/netgraph/ng_nat.c b/sys/netgraph/ng_nat.c index 59818d9ced8..fc39e3e0799 100644 --- a/sys/netgraph/ng_nat.c +++ b/sys/netgraph/ng_nat.c @@ -756,18 +756,18 @@ ng_nat_rcvdata(hook_p hook, item_p item ) */ if (th->th_x2) { + uint16_t ip_len = ntohs(ip->ip_len); + th->th_x2 = 0; - ip->ip_len = ntohs(ip->ip_len); th->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, htons(IPPROTO_TCP + - ip->ip_len - (ip->ip_hl << 2))); + ip_len - (ip->ip_hl << 2))); if ((m->m_pkthdr.csum_flags & CSUM_TCP) == 0) { m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); in_delayed_cksum(m); } - ip->ip_len = htons(ip->ip_len); } } diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 99d598cc1ee..4f5f1b35e37 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -208,10 +208,8 @@ divert_packet(struct mbuf *m, int incoming) /* Delayed checksums are currently not compatible with divert. */ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { - ip->ip_len = ntohs(ip->ip_len); in_delayed_cksum(m); m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; - ip->ip_len = htons(ip->ip_len); } #ifdef SCTP if (m->m_pkthdr.csum_flags & CSUM_SCTP) { diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c index 389b74eea3c..7fc4c3f5e50 100644 --- a/sys/netinet/ip_ipsec.c +++ b/sys/netinet/ip_ipsec.c @@ -332,6 +332,9 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error) } } + ip->ip_len = htons(ip->ip_len); + ip->ip_off = htons(ip->ip_off); + /* * Do delayed checksums now because we send before * this is done in the normal processing path. @@ -346,8 +349,6 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error) (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP; } #endif - ip->ip_len = htons(ip->ip_len); - ip->ip_off = htons(ip->ip_off); /* NB: callee frees mbuf */ *error = ipsec4_process_packet(*m, sp->req, *flags, 0); diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c index 9250be5fc00..c52332df987 100644 --- a/sys/netinet/ip_mroute.c +++ b/sys/netinet/ip_mroute.c @@ -2376,7 +2376,10 @@ pim_register_prepare(struct ip *ip, struct mbuf *m) /* Take care of delayed checksums */ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + /* XXX: in_delayed_cksum() expects net byte order */ + ip->ip_len = htons(ip->ip_len); in_delayed_cksum(m); + ip->ip_len = ntohs(ip->ip_len); m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 6ea9827c758..e82a0acb875 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -882,11 +882,12 @@ void in_delayed_cksum(struct mbuf *m) { struct ip *ip; - u_short csum, offset; + uint16_t csum, offset, ip_len; ip = mtod(m, struct ip *); offset = ip->ip_hl << 2 ; - csum = in_cksum_skip(m, ip->ip_len, offset); + ip_len = ntohs(ip->ip_len); + csum = in_cksum_skip(m, ip_len, offset); if (m->m_pkthdr.csum_flags & CSUM_UDP && csum == 0) csum = 0xffff; offset += m->m_pkthdr.csum_data; /* checksum offset */ diff --git a/sys/netinet6/ip6_ipsec.c b/sys/netinet6/ip6_ipsec.c index 911ea8d3bd8..5d214dea0a1 100644 --- a/sys/netinet6/ip6_ipsec.c +++ b/sys/netinet6/ip6_ipsec.c @@ -295,9 +295,15 @@ ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error, */ #ifdef INET if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + struct ip *ip; + ipseclog((LOG_DEBUG, "%s: we do not support IPv4 over IPv6", __func__)); + /* XXX: in_delayed_cksum() expects net byte order */ + ip = mtod(m, struct ip *); + ip->ip_len = htons(ip->ip_len); in_delayed_cksum(*m); + ip->ip_len = ntohs(ip->ip_len); (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } #endif diff --git a/sys/netpfil/ipfw/ip_fw_nat.c b/sys/netpfil/ipfw/ip_fw_nat.c index 6318633195f..94861b34877 100644 --- a/sys/netpfil/ipfw/ip_fw_nat.c +++ b/sys/netpfil/ipfw/ip_fw_nat.c @@ -336,11 +336,11 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) if (ldt) { struct tcphdr *th; struct udphdr *uh; - u_short cksum; + uint16_t ip_len, cksum; - ip->ip_len = ntohs(ip->ip_len); + ip_len = ntohs(ip->ip_len); cksum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, - htons(ip->ip_p + ip->ip_len - (ip->ip_hl << 2))); + htons(ip->ip_p + ip_len - (ip->ip_hl << 2))); switch (ip->ip_p) { case IPPROTO_TCP: @@ -366,7 +366,6 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m) in_delayed_cksum(mcl); mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; } - ip->ip_len = htons(ip->ip_len); } args->m = mcl; return (IP_FW_NAT); diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 00150f3e127..4c126fd69e7 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -5149,7 +5149,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, struct pf_addr naddr; struct pf_src_node *sn = NULL; int error = 0; - int sw_csum; + uint16_t ip_len, ip_off, sw_csum; KASSERT(m && *m && r && oifp, ("%s: invalid parameters", __func__)); KASSERT(dir == PF_IN || dir == PF_OUT, ("%s: invalid direction", @@ -5244,9 +5244,8 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, if (ifp->if_flags & IFF_LOOPBACK) m0->m_flags |= M_SKIP_FIREWALL; - /* Back to host byte order. */ - ip->ip_len = ntohs(ip->ip_len); - ip->ip_off = ntohs(ip->ip_off); + ip_len = ntohs(ip->ip_len); + ip_off = ntohs(ip->ip_off); /* Copied from FreeBSD 10.0-CURRENT ip_output. */ m0->m_pkthdr.csum_flags |= CSUM_IP; @@ -5267,11 +5266,9 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, * 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 <= ifp->if_mtu || + if (ip_len <= ifp->if_mtu || (m0->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(m0, ip->ip_hl << 2); @@ -5281,7 +5278,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp, } /* Balk when DF bit is set or the interface didn't support TSO. */ - if ((ip->ip_off & IP_DF) || (m0->m_pkthdr.csum_flags & CSUM_TSO)) { + if ((ip_off & IP_DF) || (m0->m_pkthdr.csum_flags & CSUM_TSO)) { error = EMSGSIZE; KMOD_IPSTAT_INC(ips_cantfrag); if (r->rt != PF_DUPTO) {