Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net/npf NPF: fix the recent breakage of the traceroute A...



details:   https://anonhg.NetBSD.org/src/rev/93bb53b1b0d3
branches:  trunk
changeset: 326810:93bb53b1b0d3
user:      rmind <rmind%NetBSD.org@localhost>
date:      Wed Feb 19 03:51:31 2014 +0000

description:
NPF: fix the recent breakage of the traceroute ALG.  Also, simplify and
refactor a little bit.

diffstat:

 sys/net/npf/npf_alg_icmp.c |  37 ++++++++++++++++----------
 sys/net/npf/npf_impl.h     |   5 ++-
 sys/net/npf/npf_inet.c     |  50 ++++++++++++++++++++++++++++++++++--
 sys/net/npf/npf_nat.c      |  63 +++++++--------------------------------------
 4 files changed, 82 insertions(+), 73 deletions(-)

diffs (truncated from 317 to 300 lines):

diff -r f1b3ffcfa35d -r 93bb53b1b0d3 sys/net/npf/npf_alg_icmp.c
--- a/sys/net/npf/npf_alg_icmp.c        Wed Feb 19 01:43:16 2014 +0000
+++ b/sys/net/npf/npf_alg_icmp.c        Wed Feb 19 03:51:31 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_alg_icmp.c,v 1.19 2014/02/16 22:10:40 rmind Exp $  */
+/*     $NetBSD: npf_alg_icmp.c,v 1.20 2014/02/19 03:51:31 rmind Exp $  */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.19 2014/02/16 22:10:40 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.20 2014/02/19 03:51:31 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/module.h>
@@ -305,6 +305,7 @@
 static bool
 npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
 {
+       const u_int which = NPF_SRC;
        npf_cache_t enpc;
 
        if (forw || !npf_iscached(npc, NPC_ICMP))
@@ -315,6 +316,9 @@
        KASSERT(npf_iscached(&enpc, NPC_IP46));
        KASSERT(npf_iscached(&enpc, NPC_LAYER4));
 
+       /*
+        * ICMP: fetch the current checksum we are going to fixup.
+        */
        struct icmp *ic = npc->npc_l4.icmp;
        uint16_t cksum = ic->icmp_cksum;
 
@@ -322,12 +326,9 @@
            offsetof(struct icmp6_hdr, icmp6_cksum));
 
        /*
-        * Retrieve the original address and port, then calculate ICMP
-        * checksum for these changes in the embedded packet.  While data
-        * is not rewritten in the cache, save IP and TCP/UDP checksums.
-        *
-        * XXX: Assumes NPF_NATOUT (source address/port).  Currently,
-        * npfa_icmp_match() matches only for the PFIL_OUT traffic.
+        * Fetch the IP and port in the _embedded_ packet.  Also, fetch
+        * the IPv4 and TCP/UDP checksums before they are rewritten.
+        * Calculate the part of the ICMP checksum fixup.
         */
        const int proto = enpc.npc_proto;
        uint16_t ipcksum = 0, l4cksum = 0;
@@ -340,7 +341,7 @@
                const struct ip *eip = enpc.npc_ip.v4;
                ipcksum = eip->ip_sum;
        }
-       cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[NPF_SRC], addr);
+       cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[which], addr);
 
        switch (proto) {
        case IPPROTO_TCP: {
@@ -363,17 +364,23 @@
        }
 
        /*
-        * Rewrite the source IP address and port of the embedded IP header,
-        * which represents the original packet.  This updates the checksums
-        * in the embedded packet.
+        * Translate the embedded packet.  The following changes will
+        * be performed by npf_napt_rwr():
+        *
+        *      1) Rewrite the IP address and, if not ICMP, port.
+        *      2) Rewrite the TCP/UDP checksum (if not ICMP).
+        *      3) Rewrite the IPv4 checksum for (1) and (2).
+        *
+        * XXX: Assumes NPF_NATOUT (source address/port).  Currently,
+        * npfa_icmp_match() matches only for the PFIL_OUT traffic.
         */
-       if (npf_nat_translate(&enpc, nbuf, nt, forw)) {
+       if (npf_napt_rwr(&enpc, which, addr, port)) {
                return false;
        }
 
        /*
-        * Finish calculation of the ICMP checksum: include the checksum
-        * change in the embedded packet.
+        * Finally, finish the ICMP checksum fixup: include the checksum
+        * changes in the embedded packet.
         */
        if (npf_iscached(&enpc, NPC_IP4)) {
                const struct ip *eip = enpc.npc_ip.v4;
diff -r f1b3ffcfa35d -r 93bb53b1b0d3 sys/net/npf/npf_impl.h
--- a/sys/net/npf/npf_impl.h    Wed Feb 19 01:43:16 2014 +0000
+++ b/sys/net/npf/npf_impl.h    Wed Feb 19 03:51:31 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_impl.h,v 1.48 2014/02/16 22:10:40 rmind Exp $      */
+/*     $NetBSD: npf_impl.h,v 1.49 2014/02/19 03:51:31 rmind Exp $      */
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -200,6 +200,8 @@
 bool           npf_rwrport(const npf_cache_t *, u_int, const in_port_t);
 bool           npf_rwrcksum(const npf_cache_t *, u_int,
                    const npf_addr_t *, const in_port_t);
+int            npf_napt_rwr(const npf_cache_t *, u_int, const npf_addr_t *,
+                   const in_addr_t);
 int            npf_npt66_rwr(const npf_cache_t *, u_int, const npf_addr_t *,
                    npf_netmask_t, uint16_t);
 
@@ -341,7 +343,6 @@
 void           npf_nat_freealg(npf_natpolicy_t *, npf_alg_t *);
 
 int            npf_do_nat(npf_cache_t *, npf_session_t *, nbuf_t *, const int);
-int            npf_nat_translate(npf_cache_t *, nbuf_t *, npf_nat_t *, bool);
 void           npf_nat_destroy(npf_nat_t *);
 void           npf_nat_getorig(npf_nat_t *, npf_addr_t **, in_port_t *);
 void           npf_nat_gettrans(npf_nat_t *, npf_addr_t **, in_port_t *);
diff -r f1b3ffcfa35d -r 93bb53b1b0d3 sys/net/npf/npf_inet.c
--- a/sys/net/npf/npf_inet.c    Wed Feb 19 01:43:16 2014 +0000
+++ b/sys/net/npf/npf_inet.c    Wed Feb 19 03:51:31 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $      */
+/*     $NetBSD: npf_inet.c,v 1.30 2014/02/19 03:51:31 rmind Exp $      */
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.30 2014/02/19 03:51:31 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -578,7 +578,7 @@
        }
 
        /* Nothing else to do for ICMP. */
-       if (proto == IPPROTO_ICMP) {
+       if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
                return true;
        }
        KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
@@ -617,6 +617,50 @@
 }
 
 /*
+ * npf_napt_rwr: perform address and/or port translation.
+ */
+int
+npf_napt_rwr(const npf_cache_t *npc, u_int which,
+    const npf_addr_t *addr, const in_addr_t port)
+{
+       const unsigned proto = npc->npc_proto;
+
+       /*
+        * Rewrite IP and/or TCP/UDP checksums first, since we need the
+        * current (old) address/port for the calculations.  Then perform
+        * the address translation i.e. rewrite source or destination.
+        */
+       if (!npf_rwrcksum(npc, which, addr, port)) {
+               return EINVAL;
+       }
+       if (!npf_rwrip(npc, which, addr)) {
+               return EINVAL;
+       }
+       if (port == 0) {
+               /* Done. */
+               return 0;
+       }
+
+       switch (proto) {
+       case IPPROTO_TCP:
+       case IPPROTO_UDP:
+               /* Rewrite source/destination port. */
+               if (!npf_rwrport(npc, which, port)) {
+                       return EINVAL;
+               }
+               break;
+       case IPPROTO_ICMP:
+       case IPPROTO_ICMPV6:
+               KASSERT(npf_iscached(npc, NPC_ICMP));
+               /* Nothing. */
+               break;
+       default:
+               return ENOTSUP;
+       }
+       return 0;
+}
+
+/*
  * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296.
  */
 
diff -r f1b3ffcfa35d -r 93bb53b1b0d3 sys/net/npf/npf_nat.c
--- a/sys/net/npf/npf_nat.c     Wed Feb 19 01:43:16 2014 +0000
+++ b/sys/net/npf/npf_nat.c     Wed Feb 19 03:51:31 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $       */
+/*     $NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $       */
 
 /*-
  * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org>
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -549,62 +549,18 @@
 }
 
 /*
- * npf_nat_rwr: perform address and/or port translation.
- */
-static int
-npf_nat_rwr(npf_cache_t *npc, const npf_natpolicy_t *np,
-    const npf_addr_t *addr, const in_addr_t port, bool forw)
-{
-       const unsigned proto = npc->npc_proto;
-       const u_int which = npf_nat_which(np->n_type, forw);
-
-       /*
-        * Rewrite IP and/or TCP/UDP checksums first, since we need the
-        * current (old) address/port for the calculations.  Then perform
-        * the address translation i.e. rewrite source or destination.
-        */
-       if (!npf_rwrcksum(npc, which, addr, port)) {
-               return EINVAL;
-       }
-       if (!npf_rwrip(npc, which, addr)) {
-               return EINVAL;
-       }
-       if ((np->n_flags & NPF_NAT_PORTS) == 0) {
-               /* Done. */
-               return 0;
-       }
-
-       switch (proto) {
-       case IPPROTO_TCP:
-       case IPPROTO_UDP:
-               /* Rewrite source/destination port. */
-               if (!npf_rwrport(npc, which, port)) {
-                       return EINVAL;
-               }
-               break;
-       case IPPROTO_ICMP:
-               KASSERT(npf_iscached(npc, NPC_ICMP));
-               /* Nothing. */
-               break;
-       default:
-               return ENOTSUP;
-       }
-       return 0;
-}
-
-/*
  * npf_nat_translate: perform translation given the state data.
  */
-int
+static inline int
 npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
 {
        const npf_natpolicy_t *np = nt->nt_natpolicy;
+       const u_int which = npf_nat_which(np->n_type, forw);
        const npf_addr_t *addr;
        in_port_t port;
 
        KASSERT(npf_iscached(npc, NPC_IP46));
        KASSERT(npf_iscached(npc, NPC_LAYER4));
-       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
 
        if (forw) {
                /* "Forwards" stream: use translation address/port. */
@@ -617,14 +573,16 @@
        }
        KASSERT((np->n_flags & NPF_NAT_PORTS) != 0 || port == 0);
 
-       /* Execute ALG hook first. */
+       /* Execute ALG translation first. */
        if ((npc->npc_info & NPC_ALG_EXEC) == 0) {
                npc->npc_info |= NPC_ALG_EXEC;
                npf_alg_exec(npc, nbuf, nt, forw);
+               npf_recache(npc, nbuf);
        }
+       KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
 
        /* Finally, perform the translation. */
-       return npf_nat_rwr(npc, np, addr, port, forw);
+       return npf_napt_rwr(npc, which, addr, port);
 }
 
 /*
@@ -633,17 +591,16 @@
 static inline int 
 npf_nat_algo(npf_cache_t *npc, const npf_natpolicy_t *np, bool forw)



Home | Main Index | Thread Index | Old Index