Module Name:    src
Committed By:   christos
Date:           Sat Dec 10 05:41:10 UTC 2016

Modified Files:
        src/sys/net/npf: npf.c npf.h npf_conn.c npf_conn.h npf_ctl.c npf_impl.h

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


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 src/sys/net/npf/npf.c
cvs rdiff -u -r1.49 -r1.50 src/sys/net/npf/npf.h
cvs rdiff -u -r1.17 -r1.18 src/sys/net/npf/npf_conn.c
cvs rdiff -u -r1.8 -r1.9 src/sys/net/npf/npf_conn.h
cvs rdiff -u -r1.43 -r1.44 src/sys/net/npf/npf_ctl.c
cvs rdiff -u -r1.62 -r1.63 src/sys/net/npf/npf_impl.h

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.c
diff -u src/sys/net/npf/npf.c:1.31 src/sys/net/npf/npf.c:1.32
--- src/sys/net/npf/npf.c:1.31	Thu Oct 29 11:19:43 2015
+++ src/sys/net/npf/npf.c	Sat Dec 10 00:41:10 2016
@@ -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 @@ npf_dev_ioctl(dev_t dev, u_long cmd, voi
 	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;

Index: src/sys/net/npf/npf.h
diff -u src/sys/net/npf/npf.h:1.49 src/sys/net/npf/npf.h:1.50
--- src/sys/net/npf/npf.h:1.49	Thu Dec  8 21:26:36 2016
+++ src/sys/net/npf/npf.h	Sat Dec 10 00:41:10 2016
@@ -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 @@ typedef struct npf_ioctl_table {
 #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.

Index: src/sys/net/npf/npf_conn.c
diff -u src/sys/net/npf/npf_conn.c:1.17 src/sys/net/npf/npf_conn.c:1.18
--- src/sys/net/npf/npf_conn.c:1.17	Thu Dec  8 18:07:11 2016
+++ src/sys/net/npf/npf_conn.c	Sat Dec 10 00:41:10 2016
@@ -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 @@ npf_conn_trackable_p(const npf_cache_t *
 	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 @@ npf_conn_conkey(const npf_cache_t *npc, 
 	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 @@ npf_conn_conkey(const npf_cache_t *npc, 
 		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 @@ connkey_set_id(npf_connkey_t *key, const
 }
 
 /*
+ * 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 @@ npf_conn_lookup(const npf_cache_t *npc, 
 	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 @@ npf_conn_lookup(const npf_cache_t *npc, 
 	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 @@ npf_conn_lookup(const npf_cache_t *npc, 
 		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 @@ npf_conn_export(const npf_conn_t *con)
 	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.

Index: src/sys/net/npf/npf_conn.h
diff -u src/sys/net/npf/npf_conn.h:1.8 src/sys/net/npf/npf_conn.h:1.9
--- src/sys/net/npf/npf_conn.h:1.8	Sat Dec 20 11:19:43 2014
+++ src/sys/net/npf/npf_conn.h	Sat Dec 10 00:41:10 2016
@@ -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.
@@ -117,6 +117,7 @@ npf_nat_t *	npf_conn_getnat(npf_conn_t *
 void		npf_conn_gc(npf_conndb_t *, bool, bool);
 int		npf_conn_import(npf_conndb_t *, prop_dictionary_t,
 		    npf_ruleset_t *);
+int		npf_conn_find(prop_dictionary_t, prop_dictionary_t *);
 prop_dictionary_t npf_conn_export(const npf_conn_t *);
 void		npf_conn_print(const npf_conn_t *);
 

Index: src/sys/net/npf/npf_ctl.c
diff -u src/sys/net/npf/npf_ctl.c:1.43 src/sys/net/npf/npf_ctl.c:1.44
--- src/sys/net/npf/npf_ctl.c:1.43	Tue Oct 27 21:54:10 2015
+++ src/sys/net/npf/npf_ctl.c	Sat Dec 10 00:41:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ctl.c,v 1.43 2015/10/28 01:54:10 christos Exp $	*/
+/*	$NetBSD: npf_ctl.c,v 1.44 2016/12/10 05:41:10 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.43 2015/10/28 01:54:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.44 2016/12/10 05:41:10 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -704,6 +704,32 @@ out:
 }
 
 /*
+ * npfctl_conn_lookup: lookup a connection in the list of connections
+ */
+int
+npfctl_conn_lookup(u_long cmd, void *data)
+{
+	struct plistref *pref = data;
+	prop_dictionary_t conn_data, conn_result;
+	int error;
+
+	error = prop_dictionary_copyin_ioctl(pref, cmd, &conn_data);
+	if (error) {
+		return error;
+	}
+
+	error = npf_conn_find(conn_data, &conn_result);
+	if (error) {
+		goto out;
+	}
+	prop_dictionary_copyout_ioctl(pref, cmd, conn_result);
+	prop_object_release(conn_result);
+out:
+	prop_object_release(conn_data);
+	return error;
+}
+
+/*
  * npfctl_rule: add or remove dynamic rules in the specified ruleset.
  */
 int

Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.62 src/sys/net/npf/npf_impl.h:1.63
--- src/sys/net/npf/npf_impl.h:1.62	Thu Dec  8 21:40:38 2016
+++ src/sys/net/npf/npf_impl.h	Sat Dec 10 00:41:10 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_impl.h,v 1.62 2016/12/09 02:40:38 christos Exp $	*/
+/*	$NetBSD: npf_impl.h,v 1.63 2016/12/10 05:41:10 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
@@ -169,6 +169,7 @@ int		npfctl_reload(u_long, void *);
 int		npfctl_save(u_long, void *);
 int		npfctl_load(u_long, void *);
 int		npfctl_rule(u_long, void *);
+int		npfctl_conn_lookup(u_long, void *);
 int		npfctl_table(void *);
 
 void		npf_stats_inc(npf_stats_t);

Reply via email to