Source-Changes-HG archive

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

[src/trunk]: src NPF: add support for static (stateless) NAT.



details:   https://anonhg.NetBSD.org/src/rev/4dd033f1f88e
branches:  trunk
changeset: 793367:4dd033f1f88e
user:      rmind <rmind%NetBSD.org@localhost>
date:      Fri Feb 07 23:45:22 2014 +0000

description:
NPF: add support for static (stateless) NAT.

diffstat:

 lib/libnpf/npf.c                               |   14 ++-
 lib/libnpf/npf.h                               |    3 +-
 sys/net/npf/npf.h                              |    5 +-
 sys/net/npf/npf_nat.c                          |  113 ++++++++++++++----------
 usr.sbin/npf/npfctl/npf_build.c                |   68 ++++++--------
 usr.sbin/npf/npfctl/npf_show.c                 |   13 +-
 usr.sbin/npf/npftest/libnpftest/npf_nat_test.c |   19 +++-
 usr.sbin/npf/npftest/libnpftest/npf_test.h     |    7 +-
 usr.sbin/npf/npftest/npftest.conf              |    7 +-
 9 files changed, 150 insertions(+), 99 deletions(-)

diffs (truncated from 512 to 300 lines):

diff -r 8cef2516912e -r 4dd033f1f88e lib/libnpf/npf.c
--- a/lib/libnpf/npf.c  Fri Feb 07 23:18:04 2014 +0000
+++ b/lib/libnpf/npf.c  Fri Feb 07 23:45:22 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf.c,v 1.26 2014/02/06 02:51:28 rmind Exp $   */
+/*     $NetBSD: npf.c,v 1.27 2014/02/07 23:45:22 rmind Exp $   */
 
 /*-
  * Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.26 2014/02/06 02:51:28 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.27 2014/02/07 23:45:22 rmind Exp $");
 
 #include <sys/types.h>
 #include <netinet/in_systm.h>
@@ -874,6 +874,16 @@
        return type;
 }
 
+u_int
+npf_nat_getflags(nl_nat_t *nt)
+{
+       prop_dictionary_t rldict = nt->nrl_dict;
+       unsigned flags = 0;
+
+       prop_dictionary_get_uint32(rldict, "flags", &flags);
+       return flags;
+}
+
 void
 npf_nat_getmap(nl_nat_t *nt, npf_addr_t *addr, size_t *alen, in_port_t *port)
 {
diff -r 8cef2516912e -r 4dd033f1f88e lib/libnpf/npf.h
--- a/lib/libnpf/npf.h  Fri Feb 07 23:18:04 2014 +0000
+++ b/lib/libnpf/npf.h  Fri Feb 07 23:45:22 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf.h,v 1.23 2014/02/06 02:51:28 rmind Exp $   */
+/*     $NetBSD: npf.h,v 1.24 2014/02/07 23:45:22 rmind Exp $   */
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -136,6 +136,7 @@
 
 nl_nat_t *     npf_nat_iterate(nl_config_t *);
 int            npf_nat_gettype(nl_nat_t *);
+unsigned       npf_nat_getflags(nl_nat_t *);
 void           npf_nat_getmap(nl_nat_t *, npf_addr_t *, size_t *, in_port_t *);
 
 nl_rproc_t *   npf_rproc_iterate(nl_config_t *);
diff -r 8cef2516912e -r 4dd033f1f88e sys/net/npf/npf.h
--- a/sys/net/npf/npf.h Fri Feb 07 23:18:04 2014 +0000
+++ b/sys/net/npf/npf.h Fri Feb 07 23:45:22 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf.h,v 1.35 2014/02/06 02:51:28 rmind Exp $   */
+/*     $NetBSD: npf.h,v 1.36 2014/02/07 23:45:22 rmind Exp $   */
 
 /*-
  * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -87,7 +87,7 @@
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp6.h>
 
-#define        NPC_IP4         0x01    /* Indicates fetched IPv4 header. */
+#define        NPC_IP4         0x01    /* Indicates IPv4 header. */
 #define        NPC_IP6         0x02    /* Indicates IPv6 header. */
 #define        NPC_IPFRAG      0x04    /* IPv4/IPv6 fragment. */
 #define        NPC_LAYER4      0x08    /* Layer 4 has been fetched. */
@@ -235,6 +235,7 @@
 
 #define        NPF_NAT_PORTS                   0x01
 #define        NPF_NAT_PORTMAP                 0x02
+#define        NPF_NAT_STATIC                  0x04
 
 /* Table types. */
 #define        NPF_TABLE_HASH                  1
diff -r 8cef2516912e -r 4dd033f1f88e sys/net/npf/npf_nat.c
--- a/sys/net/npf/npf_nat.c     Fri Feb 07 23:18:04 2014 +0000
+++ b/sys/net/npf/npf_nat.c     Fri Feb 07 23:45:22 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_nat.c,v 1.23 2013/12/06 01:33:37 rmind Exp $       */
+/*     $NetBSD: npf_nat.c,v 1.24 2014/02/07 23:45:22 rmind Exp $       */
 
 /*-
  * Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.23 2013/12/06 01:33:37 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.24 2014/02/07 23:45:22 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -423,8 +423,8 @@
 {
        /*
         * Outbound NAT rewrites:
-        * - Source on "forwards" stream.
-        * - Destination on "backwards" stream.
+        * - Source (NPF_SRC) on "forwards" stream.
+        * - Destination (NPF_DST) on "backwards" stream.
         * Inbound NAT is other way round.
         */
        if (type == NPF_NATOUT) {
@@ -433,7 +433,7 @@
                KASSERT(type == NPF_NATIN);
        }
        CTASSERT(NPF_SRC == 0 && NPF_DST == 1);
-       KASSERT(forw == 0 || forw == 1);
+       KASSERT(forw == NPF_SRC || forw == NPF_DST);
        return (u_int)forw;
 }
 
@@ -528,14 +528,56 @@
 }
 
 /*
- * npf_nat_translate: perform address and/or port translation.
+ * 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
 npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
 {
-       const int proto = npc->npc_proto;
        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;
 
@@ -560,39 +602,8 @@
                npf_alg_exec(npc, nbuf, nt, 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;
+       /* Finally, perform the translation. */
+       return npf_nat_rwr(npc, np, addr, port, forw);
 }
 
 /*
@@ -640,6 +651,16 @@
        }
        forw = true;
 
+       /* Static NAT - just perform the translation. */
+       if (np->n_flags & NPF_NAT_STATIC) {
+               if (nbuf_cksum_barrier(nbuf, di)) {
+                       npf_recache(npc, nbuf);
+               }
+               error = npf_nat_rwr(npc, np, &np->n_taddr, np->n_tport, forw);
+               atomic_dec_uint(&np->n_refcnt);
+               return error;
+       }
+
        /*
         * If there is no local session (no "stateful" rule - unusual, but
         * possible configuration), establish one before translation.  Note
@@ -688,11 +709,11 @@
        /* Perform the translation. */
        error = npf_nat_translate(npc, nbuf, nt, forw);
 out:
-       if (error && nse) {
-               /* It created for NAT - just expire. */
-               npf_session_expire(nse);
-       }
-       if (nse) {
+       if (__predict_false(nse)) {
+               if (error) {
+                       /* It created for NAT - just expire. */
+                       npf_session_expire(nse);
+               }
                npf_session_release(nse);
        }
        return error;
diff -r 8cef2516912e -r 4dd033f1f88e usr.sbin/npf/npfctl/npf_build.c
--- a/usr.sbin/npf/npfctl/npf_build.c   Fri Feb 07 23:18:04 2014 +0000
+++ b/usr.sbin/npf/npfctl/npf_build.c   Fri Feb 07 23:45:22 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_build.c,v 1.34 2014/02/06 18:48:09 christos Exp $  */
+/*     $NetBSD: npf_build.c,v 1.35 2014/02/07 23:45:22 rmind Exp $     */
 
 /*-
  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.34 2014/02/06 18:48:09 christos Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.35 2014/02/07 23:45:22 rmind Exp $");
 
 #include <sys/types.h>
 #include <sys/mman.h>
@@ -535,7 +535,7 @@
  */
 static void
 npfctl_build_nat(int type, const char *ifname, sa_family_t family,
-    const addr_port_t *ap, const filt_opts_t *fopts, bool binat)
+    const addr_port_t *ap, const filt_opts_t *fopts, u_int flags)
 {
        const opt_proto_t op = { .op_proto = -1, .op_opts = NULL };
        fam_addr_mask_t *am;
@@ -551,36 +551,16 @@
                yyerror("IPv6 NAT is not supported");
        }
 
-       switch (type) {
-       case NPF_NATOUT:
-               /*
-                * Outbound NAT (or source NAT) policy, usually used for the
-                * traditional NAPT.  If it is a half for bi-directional NAT,
-                * then no port translation with mapping.
-                */
-               nat = npf_nat_create(NPF_NATOUT, !binat ?
-                   (NPF_NAT_PORTS | NPF_NAT_PORTMAP) : 0,
-                   ifname, &am->fam_addr, am->fam_family, 0);
-               break;
-       case NPF_NATIN:
-               /*
-                * Inbound NAT (or destination NAT).  Unless bi-NAT, a port
-                * must be specified, since it has to be redirection.
-                */
+       if (ap->ap_portrange) {



Home | Main Index | Thread Index | Old Index