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/92ddee77d7e5
branches: trunk
changeset: 349405:92ddee77d7e5
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 21fbc0c007a9 -r 92ddee77d7e5 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 21fbc0c007a9 -r 92ddee77d7e5 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 21fbc0c007a9 -r 92ddee77d7e5 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 21fbc0c007a9 -r 92ddee77d7e5 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