Source-Changes-HG archive

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

[src/trunk]: src/sys/net/npf add functionality to lookup a nat entry from the...



details:   https://anonhg.NetBSD.org/src/rev/ecaab5b1e603
branches:  trunk
changeset: 819547:ecaab5b1e603
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Dec 10 05:41:10 2016 +0000

description:
add functionality to lookup a nat entry from the connection list.

diffstat:

 sys/net/npf/npf.c      |    7 +-
 sys/net/npf/npf.h      |    3 +-
 sys/net/npf/npf_conn.c |  176 ++++++++++++++++++++++++++++++++++++------------
 sys/net/npf/npf_conn.h |    3 +-
 sys/net/npf/npf_ctl.c  |   30 +++++++-
 sys/net/npf/npf_impl.h |    3 +-
 6 files changed, 170 insertions(+), 52 deletions(-)

diffs (truncated from 376 to 300 lines):

diff -r ca8dc5bc3a38 -r ecaab5b1e603 sys/net/npf/npf.c
--- a/sys/net/npf/npf.c Sat Dec 10 05:39:13 2016 +0000
+++ b/sys/net/npf/npf.c Sat Dec 10 05:41:10 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf.c,v 1.31 2015/10/29 15:19:43 christos Exp $        */
+/*     $NetBSD: npf.c,v 1.32 2016/12/10 05:41:10 christos Exp $        */
 
 /*-
  * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.31 2015/10/29 15:19:43 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.32 2016/12/10 05:41:10 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -244,6 +244,9 @@
        case IOC_NPF_LOAD:
                error = npfctl_load(cmd, data);
                break;
+       case IOC_NPF_CONN_LOOKUP:
+               error = npfctl_conn_lookup(cmd, data);
+               break;
        case IOC_NPF_VERSION:
                *(int *)data = NPF_VERSION;
                error = 0;
diff -r ca8dc5bc3a38 -r ecaab5b1e603 sys/net/npf/npf.h
--- a/sys/net/npf/npf.h Sat Dec 10 05:39:13 2016 +0000
+++ b/sys/net/npf/npf.h Sat Dec 10 05:41:10 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf.h,v 1.49 2016/12/09 02:26:36 christos Exp $        */
+/*     $NetBSD: npf.h,v 1.50 2016/12/10 05:41:10 christos Exp $        */
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -317,6 +317,7 @@
 #define        IOC_NPF_STATS           _IOW('N', 104, void *)
 #define        IOC_NPF_SAVE            _IOR('N', 105, struct plistref)
 #define        IOC_NPF_RULE            _IOWR('N', 107, struct plistref)
+#define        IOC_NPF_CONN_LOOKUP     _IOWR('N', 108, struct plistref)
 
 /*
  * Statistics counters.
diff -r ca8dc5bc3a38 -r ecaab5b1e603 sys/net/npf/npf_conn.c
--- a/sys/net/npf/npf_conn.c    Sat Dec 10 05:39:13 2016 +0000
+++ b/sys/net/npf/npf_conn.c    Sat Dec 10 05:41:10 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_conn.c,v 1.17 2016/12/08 23:07:11 rmind Exp $      */
+/*     $NetBSD: npf_conn.c,v 1.18 2016/12/10 05:41:10 christos Exp $   */
 
 /*-
  * Copyright (c) 2014-2015 Mindaugas Rasiukevicius <rmind at netbsd org>
@@ -99,7 +99,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_conn.c,v 1.17 2016/12/08 23:07:11 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_conn.c,v 1.18 2016/12/10 05:41:10 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -240,6 +240,45 @@
        return true;
 }
 
+static uint32_t
+connkey_setkey(npf_connkey_t *key, uint32_t proto, const void *ipv,
+    uint16_t *id, size_t alen, bool forw)
+{
+       uint32_t isrc, idst;
+       const npf_addr_t * const *ips = ipv;
+       if (__predict_true(forw)) {
+               isrc = NPF_SRC, idst = NPF_DST;
+       } else {
+               isrc = NPF_DST, idst = NPF_SRC;
+       }
+
+       /*
+        * Construct a key formed out of 32-bit integers.  The key layout:
+        *
+        * Field: | proto  |  alen  | src-id | dst-id | src-addr | dst-addr |
+        *        +--------+--------+--------+--------+----------+----------+
+        * Bits:  |   16   |   16   |   16   |   16   |  32-128  |  32-128  |
+        *
+        * The source and destination are inverted if they key is for the
+        * backwards stream (forw == false).  The address length depends
+        * on the 'alen' field; it is a length in bytes, either 4 or 16.
+        */
+
+       key->ck_key[0] = ((uint32_t)proto << 16) | (alen & 0xffff);
+       key->ck_key[1] = ((uint32_t)id[isrc] << 16) | id[idst];
+
+       if (__predict_true(alen == sizeof(in_addr_t))) {
+               key->ck_key[2] = ips[isrc]->s6_addr32[0];
+               key->ck_key[3] = ips[idst]->s6_addr32[0];
+               return 4 * sizeof(uint32_t);
+       } else {
+               const u_int nwords = alen >> 2;
+               memcpy(&key->ck_key[2], ips[isrc], alen);
+               memcpy(&key->ck_key[2 + nwords], ips[idst], alen);
+               return (2 + (nwords * 2)) * sizeof(uint32_t);
+       }
+}
+
 /*
  * npf_conn_conkey: construct a key for the connection lookup.
  *
@@ -251,7 +290,6 @@
        const u_int alen = npc->npc_alen;
        const struct tcphdr *th;
        const struct udphdr *uh;
-       u_int keylen, isrc, idst;
        uint16_t id[2];
 
        switch (npc->npc_proto) {
@@ -288,38 +326,8 @@
                return 0;
        }
 
-       if (__predict_true(forw)) {
-               isrc = NPF_SRC, idst = NPF_DST;
-       } else {
-               isrc = NPF_DST, idst = NPF_SRC;
-       }
-
-       /*
-        * Construct a key formed out of 32-bit integers.  The key layout:
-        *
-        * Field: | proto  |  alen  | src-id | dst-id | src-addr | dst-addr |
-        *        +--------+--------+--------+--------+----------+----------+
-        * Bits:  |   16   |   16   |   16   |   16   |  32-128  |  32-128  |
-        *
-        * The source and destination are inverted if they key is for the
-        * backwards stream (forw == false).  The address length depends
-        * on the 'alen' field; it is a length in bytes, either 4 or 16.
-        */
-
-       key->ck_key[0] = ((uint32_t)npc->npc_proto << 16) | (alen & 0xffff);
-       key->ck_key[1] = ((uint32_t)id[isrc] << 16) | id[idst];
-
-       if (__predict_true(alen == sizeof(in_addr_t))) {
-               key->ck_key[2] = npc->npc_ips[isrc]->s6_addr32[0];
-               key->ck_key[3] = npc->npc_ips[idst]->s6_addr32[0];
-               keylen = 4 * sizeof(uint32_t);
-       } else {
-               const u_int nwords = alen >> 2;
-               memcpy(&key->ck_key[2], npc->npc_ips[isrc], alen);
-               memcpy(&key->ck_key[2 + nwords], npc->npc_ips[idst], alen);
-               keylen = (2 + (nwords * 2)) * sizeof(uint32_t);
-       }
-       return keylen;
+       return connkey_setkey(key, npc->npc_proto, npc->npc_ips, id, alen,
+           forw);
 }
 
 static __inline void
@@ -343,6 +351,28 @@
 }
 
 /*
+ * npf_conn_ok: check if the connection is active, and has the right direction.
+ */
+static bool
+npf_conn_ok(npf_conn_t *con, const int di, bool forw)
+{
+       uint32_t flags = con->c_flags;
+
+       /* Check if connection is active and not expired. */
+       bool ok = (flags & (CONN_ACTIVE | CONN_EXPIRE)) == CONN_ACTIVE;
+       if (__predict_false(!ok)) {
+               return false;
+       }
+
+       /* Check if the direction is consistent */
+       bool pforw = (flags & PFIL_ALL) == di;
+       if (__predict_false(forw != pforw)) {
+               return false;
+       }
+       return true;
+}
+
+/*
  * npf_conn_lookup: lookup if there is an established connection.
  *
  * => If found, we will hold a reference for the caller.
@@ -353,8 +383,7 @@
        const nbuf_t *nbuf = npc->npc_nbuf;
        npf_conn_t *con;
        npf_connkey_t key;
-       u_int flags, cifid;
-       bool ok, pforw;
+       u_int cifid;
 
        /* Construct a key and lookup for a connection in the store. */
        if (!npf_conn_conkey(npc, &key, true)) {
@@ -367,9 +396,7 @@
        KASSERT(npc->npc_proto == con->c_proto);
 
        /* Check if connection is active and not expired. */
-       flags = con->c_flags;
-       ok = (flags & (CONN_ACTIVE | CONN_EXPIRE)) == CONN_ACTIVE;
-       if (__predict_false(!ok)) {
+       if (!npf_conn_ok(con, di, *forw)) {
                atomic_dec_uint(&con->c_refcnt);
                return NULL;
        }
@@ -383,11 +410,6 @@
                atomic_dec_uint(&con->c_refcnt);
                return NULL;
        }
-       pforw = (flags & PFIL_ALL) == di;
-       if (__predict_false(*forw != pforw)) {
-               atomic_dec_uint(&con->c_refcnt);
-               return NULL;
-       }
 
        /* Update the last activity time. */
        getnanouptime(&con->c_atime);
@@ -917,6 +939,70 @@
        return cdict;
 }
 
+static uint32_t
+npf_connkey_import(prop_dictionary_t idict, npf_connkey_t *key, uint16_t *dir)
+{
+       uint16_t proto;
+       prop_object_t sobj, dobj;
+       uint16_t id[2];
+       npf_addr_t const * ips[2];
+
+       prop_dictionary_get_uint16(idict, "proto", &proto);
+       prop_dictionary_get_uint16(idict, "direction", dir);
+
+       prop_dictionary_get_uint16(idict, "sport", &id[NPF_SRC]);
+       prop_dictionary_get_uint16(idict, "dport", &id[NPF_DST]);
+
+       sobj = prop_dictionary_get(idict, "saddr");
+       if ((ips[NPF_SRC] = prop_data_data_nocopy(sobj)) == NULL)
+               return 0;
+
+       dobj = prop_dictionary_get(idict, "daddr");
+       if ((ips[NPF_DST] = prop_data_data_nocopy(dobj)) == NULL)
+               return 0;
+
+       size_t alen = prop_data_size(sobj);
+       if (alen != prop_data_size(dobj))
+               return 0;
+       *(const int *)ips[NPF_SRC], id[NPF_SRC],
+       *(const int *)ips[NPF_DST], id[NPF_DST], alen, proto, *dir);
+       
+       return connkey_setkey(key, proto, ips, id, alen, true);
+}
+
+int
+npf_conn_find(prop_dictionary_t idict, prop_dictionary_t *odict)
+{
+       npf_connkey_t key;
+       npf_conn_t *con;
+       uint16_t dir;
+       bool forw;
+
+       if (!npf_connkey_import(idict, &key, &dir)) {
+               return EINVAL;
+       }
+
+       con = npf_conndb_lookup(conn_db, &key, &forw);
+       if (con == NULL) {
+               return ESRCH;
+       }
+
+       dir = dir == PFIL_IN ? PFIL_OUT : PFIL_IN;
+       if (!npf_conn_ok(con, dir, true)) {
+               atomic_dec_uint(&con->c_refcnt);
+               return ESRCH;
+       }
+
+       *odict = npf_conn_export(con);
+       if (*odict == NULL) {
+               atomic_dec_uint(&con->c_refcnt);
+               return ENOSPC;
+       }
+       atomic_dec_uint(&con->c_refcnt);
+
+       return 0;
+}
+
 /*
  * npf_conn_import: fully reconstruct a single connection from a
  * directory and insert into the given database.
diff -r ca8dc5bc3a38 -r ecaab5b1e603 sys/net/npf/npf_conn.h
--- a/sys/net/npf/npf_conn.h    Sat Dec 10 05:39:13 2016 +0000
+++ b/sys/net/npf/npf_conn.h    Sat Dec 10 05:41:10 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: npf_conn.h,v 1.8 2014/12/20 16:19:43 rmind Exp $       */
+/*     $NetBSD: npf_conn.h,v 1.9 2016/12/10 05:41:10 christos Exp $    */
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.



Home | Main Index | Thread Index | Old Index