Module Name: src Committed By: riz Date: Sun Dec 16 18:19:53 UTC 2012
Modified Files: src/sys/net/npf [netbsd-6]: npf.h npf_inet.c npf_mbuf.c Log Message: Pull up following revision(s) (requested by rmind in ticket #746): sys/net/npf/npf_inet.c: revision 1.18 sys/net/npf/npf_mbuf.c: revision 1.8 sys/net/npf/npf.h: revision 1.23 npf_rwrcksum: handle delayed checksums in the network stack; also fix non-NPF_NAT_PORTS case and add some comments. PR/47235. To generate a diff of this commit: cvs rdiff -u -r1.14.2.8 -r1.14.2.9 src/sys/net/npf/npf.h cvs rdiff -u -r1.10.4.6 -r1.10.4.7 src/sys/net/npf/npf_inet.c cvs rdiff -u -r1.6.14.1 -r1.6.14.2 src/sys/net/npf/npf_mbuf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/npf/npf.h diff -u src/sys/net/npf/npf.h:1.14.2.8 src/sys/net/npf/npf.h:1.14.2.9 --- src/sys/net/npf/npf.h:1.14.2.8 Sat Nov 24 04:34:42 2012 +++ src/sys/net/npf/npf.h Sun Dec 16 18:19:52 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.14.2.8 2012/11/24 04:34:42 riz Exp $ */ +/* $NetBSD: npf.h,v 1.14.2.9 2012/12/16 18:19:52 riz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -146,6 +146,7 @@ int nbuf_advstore(nbuf_t **, void **, u int nbuf_fetch_datum(nbuf_t *, void *, size_t, void *); int nbuf_store_datum(nbuf_t *, void *, size_t, void *); +void nbuf_cksum_barrier(nbuf_t *); int nbuf_add_tag(nbuf_t *, uint32_t, uint32_t); int nbuf_find_tag(nbuf_t *, uint32_t, void **); Index: src/sys/net/npf/npf_inet.c diff -u src/sys/net/npf/npf_inet.c:1.10.4.6 src/sys/net/npf/npf_inet.c:1.10.4.7 --- src/sys/net/npf/npf_inet.c:1.10.4.6 Sun Nov 18 22:38:25 2012 +++ src/sys/net/npf/npf_inet.c Sun Dec 16 18:19:52 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_inet.c,v 1.10.4.6 2012/11/18 22:38:25 riz Exp $ */ +/* $NetBSD: npf_inet.c,v 1.10.4.7 2012/12/16 18:19:52 riz Exp $ */ /*- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.10.4.6 2012/11/18 22:38:25 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.10.4.7 2012/12/16 18:19:52 riz Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -597,65 +597,80 @@ npf_rwrcksum(npf_cache_t *npc, nbuf_t *n { const int proto = npf_cache_ipproto(npc); npf_addr_t *oaddr; - in_port_t *oport; - uint16_t *cksum; + uint16_t *ocksum; + in_port_t oport; u_int offby; - /* Checksum update for IPv4 header. */ + /* XXX: NetBSD - process delayed checksums. */ + if (di == PFIL_OUT && proto != IPPROTO_ICMP) { + nbuf_cksum_barrier(nbuf); + npc->npc_info &= ~(NPC_LAYER4 | NPC_TCP | NPC_UDP); + if (!npf_cache_all(npc, nbuf)) { + return false; + } + } + + oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip; + if (npf_iscached(npc, NPC_IP4)) { struct ip *ip = &npc->npc_ip.v4; uint16_t ipsum; - oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip; + /* Recalculate IPv4 checksum, advance to it and rewrite. */ ipsum = npf_addr_cksum(ip->ip_sum, npc->npc_alen, oaddr, addr); - - /* Advance to the IPv4 checksum and rewrite it. */ offby = offsetof(struct ip, ip_sum); if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(ipsum), &ipsum)) return false; - ip->ip_sum = ipsum; - offby = npf_cache_hlen(npc) - offby; } else { /* No checksum for IPv6. */ KASSERT(npf_iscached(npc, NPC_IP6)); - oaddr = NULL; offby = 0; - return false; /* XXX: Not yet supported. */ } - /* Determine whether TCP/UDP checksum update is needed. */ - if (proto == IPPROTO_ICMP || port == 0) { + /* Nothing else to do for ICMP. */ + if (proto == IPPROTO_ICMP) { return true; } KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP)); + offby = npf_cache_hlen(npc) - offby; - /* Calculate TCP/UDP checksum. */ + /* + * Calculate TCP/UDP checksum: + * - Skip if UDP and the current checksum is zero. + * - Fixup the IP address change. + * - Fixup the port change, if required (non-zero). + */ if (proto == IPPROTO_TCP) { struct tcphdr *th = &npc->npc_l4.tcp; - cksum = &th->th_sum; + ocksum = &th->th_sum; offby += offsetof(struct tcphdr, th_sum); - oport = (di == PFIL_OUT) ? &th->th_sport : &th->th_dport; + oport = (di == PFIL_OUT) ? th->th_sport : th->th_dport; } else { struct udphdr *uh = &npc->npc_l4.udp; KASSERT(proto == IPPROTO_UDP); - cksum = &uh->uh_sum; - if (*cksum == 0) { + ocksum = &uh->uh_sum; + if (*ocksum == 0) { /* No need to update. */ return true; } offby += offsetof(struct udphdr, uh_sum); - oport = (di == PFIL_OUT) ? &uh->uh_sport : &uh->uh_dport; + oport = (di == PFIL_OUT) ? uh->uh_sport : uh->uh_dport; + } + + uint16_t cksum = *ocksum; + cksum = npf_addr_cksum(cksum, npc->npc_alen, oaddr, addr); + if (port) { + cksum = npf_fixup16_cksum(cksum, oport, port); } - *cksum = npf_addr_cksum(*cksum, npc->npc_alen, oaddr, addr); - *cksum = npf_fixup16_cksum(*cksum, *oport, port); /* Advance to TCP/UDP checksum and rewrite it. */ - if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(uint16_t), cksum)) { + if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(cksum), &cksum)) { return false; } + *ocksum = cksum; return true; } Index: src/sys/net/npf/npf_mbuf.c diff -u src/sys/net/npf/npf_mbuf.c:1.6.14.1 src/sys/net/npf/npf_mbuf.c:1.6.14.2 --- src/sys/net/npf/npf_mbuf.c:1.6.14.1 Tue Jun 26 00:07:16 2012 +++ src/sys/net/npf/npf_mbuf.c Sun Dec 16 18:19:52 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_mbuf.c,v 1.6.14.1 2012/06/26 00:07:16 riz Exp $ */ +/* $NetBSD: npf_mbuf.c,v 1.6.14.2 2012/12/16 18:19:52 riz Exp $ */ /*- * Copyright (c) 2009-2011 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.6.14.1 2012/06/26 00:07:16 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_mbuf.c,v 1.6.14.2 2012/12/16 18:19:52 riz Exp $"); #include <sys/param.h> #include <sys/mbuf.h> @@ -233,6 +233,17 @@ nbuf_advstore(nbuf_t **nbuf, void **n_pt return error; } +void +nbuf_cksum_barrier(nbuf_t *nbuf) +{ + struct mbuf *m = nbuf; + + if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4 | M_CSUM_UDPv4)) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4 | M_CSUM_UDPv4); + } +} + /* * nbuf_add_tag: add a tag to specified network buffer. *