Module Name: src
Committed By: rmind
Date: Fri Jun 22 13:43:17 UTC 2012
Modified Files:
src/sys/net/npf: npf.c npf.h npf_alg.c npf_impl.h npf_inet.c
npf_instr.c npf_log.c npf_nat.c npf_sendpkt.c npf_session.c
npf_state.c npf_state_tcp.c npf_tableset.c
src/usr.sbin/npf/npftest/libnpftest: npf_table_test.c
Log Message:
NPF:
- Rename some functions for consistency and de-inline them.
- Fix few invalid asserts (add regressoin test).
- Use pserialize(9) for ALG interface.
- Minor fixes, sprinkle many comments.
To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 src/sys/net/npf/npf.c src/sys/net/npf/npf_instr.c \
src/sys/net/npf/npf_sendpkt.c src/sys/net/npf/npf_tableset.c
cvs rdiff -u -r1.16 -r1.17 src/sys/net/npf/npf.h
cvs rdiff -u -r1.3 -r1.4 src/sys/net/npf/npf_alg.c src/sys/net/npf/npf_log.c
cvs rdiff -u -r1.15 -r1.16 src/sys/net/npf/npf_impl.h
cvs rdiff -u -r1.11 -r1.12 src/sys/net/npf/npf_inet.c
cvs rdiff -u -r1.12 -r1.13 src/sys/net/npf/npf_nat.c \
src/sys/net/npf/npf_session.c
cvs rdiff -u -r1.7 -r1.8 src/sys/net/npf/npf_state.c
cvs rdiff -u -r1.6 -r1.7 src/sys/net/npf/npf_state_tcp.c
cvs rdiff -u -r1.1 -r1.2 src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c
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.10 src/sys/net/npf/npf.c:1.11
--- src/sys/net/npf/npf.c:1.10 Tue Mar 13 18:40:59 2012
+++ src/sys/net/npf/npf.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf.c,v 1.10 2012/03/13 18:40:59 elad Exp $ */
+/* $NetBSD: npf.c,v 1.11 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.10 2012/03/13 18:40:59 elad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.11 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -48,6 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.10
#include <sys/percpu.h>
#include <sys/rwlock.h>
#include <sys/socketvar.h>
+#include <sys/sysctl.h>
#include <sys/uio.h>
#include "npf_impl.h"
@@ -80,6 +81,7 @@ static int npfctl_stats(void *);
static krwlock_t npf_lock __cacheline_aligned;
static npf_core_t * npf_core __cacheline_aligned;
static percpu_t * npf_stats_percpu __read_mostly;
+static struct sysctllog * npf_sysctl __read_mostly;
const struct cdevsw npf_cdevsw = {
npf_dev_open, npf_dev_close, npf_dev_read, nowrite, npf_dev_ioctl,
@@ -99,6 +101,8 @@ npf_init(void)
rw_init(&npf_lock);
npf_stats_percpu = percpu_alloc(NPF_STATS_SIZE);
+ npf_sysctl = NULL;
+
npf_tableset_sysinit();
npf_session_sysinit();
npf_nat_sysinit();
@@ -144,6 +148,10 @@ npf_fini(void)
npf_nat_sysfini();
npf_session_sysfini();
npf_tableset_sysfini();
+
+ if (npf_sysctl) {
+ sysctl_teardown(&npf_sysctl);
+ }
percpu_free(npf_stats_percpu, NPF_STATS_SIZE);
rw_destroy(&npf_lock);
Index: src/sys/net/npf/npf_instr.c
diff -u src/sys/net/npf/npf_instr.c:1.10 src/sys/net/npf/npf_instr.c:1.11
--- src/sys/net/npf/npf_instr.c:1.10 Mon Feb 20 00:18:20 2012
+++ src/sys/net/npf/npf_instr.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_instr.c,v 1.10 2012/02/20 00:18:20 rmind Exp $ */
+/* $NetBSD: npf_instr.c,v 1.11 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2009-2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.10 2012/02/20 00:18:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_instr.c,v 1.11 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -129,7 +129,7 @@ npf_match_ipmask(npf_cache_t *npc, nbuf_
}
addr = sd ? npc->npc_srcip : npc->npc_dstip;
if (mask != NPF_NO_NETMASK) {
- npf_calculate_masked_addr(&cmpaddr, addr, mask);
+ npf_addr_mask(addr, mask, &cmpaddr);
addr = &cmpaddr;
}
return memcmp(netaddr, addr, npc->npc_ipsz) ? -1 : 0;
Index: src/sys/net/npf/npf_sendpkt.c
diff -u src/sys/net/npf/npf_sendpkt.c:1.10 src/sys/net/npf/npf_sendpkt.c:1.11
--- src/sys/net/npf/npf_sendpkt.c:1.10 Sun May 6 02:45:25 2012
+++ src/sys/net/npf/npf_sendpkt.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_sendpkt.c,v 1.10 2012/05/06 02:45:25 rmind Exp $ */
+/* $NetBSD: npf_sendpkt.c,v 1.11 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_sendpkt.c,v 1.10 2012/05/06 02:45:25 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_sendpkt.c,v 1.11 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -108,7 +108,7 @@ npf_return_tcp(npf_cache_t *npc)
memset(ip, 0, len);
/*
- * First fill of IPv4 header, for TCP checksum.
+ * First, partially fill IPv4 header for TCP checksum.
* Note: IP length contains TCP header length.
*/
ip->ip_p = IPPROTO_TCP;
@@ -134,7 +134,9 @@ npf_return_tcp(npf_cache_t *npc)
th = (struct tcphdr *)(ip6 + 1);
}
- /* Construct TCP header and compute the checksum. */
+ /*
+ * Construct TCP header and compute the checksum.
+ */
th->th_sport = oth->th_dport;
th->th_dport = oth->th_sport;
th->th_seq = htonl(ack);
@@ -148,7 +150,9 @@ npf_return_tcp(npf_cache_t *npc)
if (npf_iscached(npc, NPC_IP4)) {
th->th_sum = in_cksum(m, len);
- /* Second fill of IPv4 header, fill correct IP length. */
+ /*
+ * Second, fill the rest of IPv4 header and correct IP length.
+ */
ip->ip_v = IPVERSION;
ip->ip_hl = sizeof(struct ip) >> 2;
ip->ip_tos = IPTOS_LOWDELAY;
Index: src/sys/net/npf/npf_tableset.c
diff -u src/sys/net/npf/npf_tableset.c:1.10 src/sys/net/npf/npf_tableset.c:1.11
--- src/sys/net/npf/npf_tableset.c:1.10 Mon Feb 20 00:18:20 2012
+++ src/sys/net/npf/npf_tableset.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_tableset.c,v 1.10 2012/02/20 00:18:20 rmind Exp $ */
+/* $NetBSD: npf_tableset.c,v 1.11 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.10 2012/02/20 00:18:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.11 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -164,7 +164,7 @@ table_rbtree_cmp_nodes(void *ctx, const
const npf_tblent_t * const te1 = n1;
const npf_tblent_t * const te2 = n2;
- return npf_compare_cidr(&te1->te_addr, te1->te_mask,
+ return npf_addr_cmp(&te1->te_addr, te1->te_mask,
&te2->te_addr, te2->te_mask);
}
@@ -174,7 +174,7 @@ table_rbtree_cmp_key(void *ctx, const vo
const npf_tblent_t * const te = n1;
const npf_addr_t *t2 = key;
- return npf_compare_cidr(&te->te_addr, te->te_mask, t2, NPF_NO_NETMASK);
+ return npf_addr_cmp(&te->te_addr, te->te_mask, t2, NPF_NO_NETMASK);
}
static const rb_tree_ops_t table_rbtree_ops = {
@@ -366,7 +366,7 @@ npf_table_add_cidr(npf_tableset_t *tset,
switch (t->t_type) {
case NPF_TABLE_HASH:
/* Generate hash value from: address & mask. */
- npf_calculate_masked_addr(&val, addr, mask);
+ npf_addr_mask(addr, mask, &val);
htbl = table_hash_bucket(t, &val, sizeof(npf_addr_t));
/* Lookup to check for duplicates. */
LIST_FOREACH(it, htbl, te_entry.hashq) {
@@ -428,7 +428,7 @@ npf_table_rem_cidr(npf_tableset_t *tset,
switch (t->t_type) {
case NPF_TABLE_HASH:
/* Generate hash value from: (address & mask). */
- npf_calculate_masked_addr(&val, addr, mask);
+ npf_addr_mask(addr, mask, &val);
htbl = table_hash_bucket(t, &val, sizeof(npf_addr_t));
LIST_FOREACH(e, htbl, te_entry.hashq) {
if (e->te_mask != mask) {
@@ -446,7 +446,7 @@ npf_table_rem_cidr(npf_tableset_t *tset,
break;
case NPF_TABLE_TREE:
/* Key: (address & mask). */
- npf_calculate_masked_addr(&val, addr, mask);
+ npf_addr_mask(addr, mask, &val);
e = rb_tree_find_node(&t->t_rbtree, &val);
if (__predict_true(e != NULL)) {
rb_tree_remove_node(&t->t_rbtree, e);
@@ -486,20 +486,23 @@ npf_table_match_addr(npf_tableset_t *tse
case NPF_TABLE_HASH:
htbl = table_hash_bucket(t, addr, sizeof(npf_addr_t));
LIST_FOREACH(e, htbl, te_entry.hashq) {
- if (npf_compare_cidr(addr, e->te_mask, &e->te_addr,
+ if (npf_addr_cmp(addr, e->te_mask, &e->te_addr,
NPF_NO_NETMASK) == 0)
break;
}
break;
case NPF_TABLE_TREE:
e = rb_tree_find_node(&t->t_rbtree, addr);
- KASSERT(e && npf_compare_cidr(addr, e->te_mask, &e->te_addr,
- NPF_NO_NETMASK) == 0);
break;
default:
KASSERT(false);
}
npf_table_put(t);
- return e ? 0 : ENOENT;
+ if (e == NULL) {
+ return ENOENT;
+ }
+ KASSERT(npf_addr_cmp(addr, e->te_mask, &e->te_addr,
+ NPF_NO_NETMASK) == 0);
+ return 0;
}
Index: src/sys/net/npf/npf.h
diff -u src/sys/net/npf/npf.h:1.16 src/sys/net/npf/npf.h:1.17
--- src/sys/net/npf/npf.h:1.16 Sat Apr 14 19:01:21 2012
+++ src/sys/net/npf/npf.h Fri Jun 22 13:43:17 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: npf.h,v 1.16 2012/04/14 19:01:21 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.17 2012/06/22 13:43:17 rmind Exp $ */
/*-
- * Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -110,72 +110,6 @@ typedef struct {
} npc_l4;
} npf_cache_t;
-static inline void
-npf_generate_mask(npf_addr_t *dst, const npf_netmask_t omask)
-{
- uint_fast8_t length = omask;
-
- /* Note: maximum length is 32 for IPv4 and 128 for IPv6. */
- KASSERT(length <= NPF_MAX_NETMASK);
-
- for (int i = 0; i < 4; i++) {
- if (length >= 32) {
- dst->s6_addr32[i] = htonl(0xffffffff);
- length -= 32;
- } else {
- dst->s6_addr32[i] = htonl(0xffffffff << (32 - length));
- length = 0;
- }
- }
-}
-
-static inline void
-npf_calculate_masked_addr(npf_addr_t *dst, const npf_addr_t *src,
- const npf_netmask_t omask)
-{
- npf_addr_t mask;
-
- npf_generate_mask(&mask, omask);
- for (int i = 0; i < 4; i++) {
- dst->s6_addr32[i] = src->s6_addr32[i] & mask.s6_addr32[i];
- }
-}
-
-/*
- * npf_compare_cidr: compare two addresses, either IPv4 or IPv6.
- *
- * => If the mask is NULL, ignore it.
- */
-static inline int
-npf_compare_cidr(const npf_addr_t *addr1, const npf_netmask_t mask1,
- const npf_addr_t *addr2, const npf_netmask_t mask2)
-{
- npf_addr_t realmask1, realmask2;
-
- if (mask1 != NPF_NO_NETMASK) {
- npf_generate_mask(&realmask1, mask1);
- }
- if (mask2 != NPF_NO_NETMASK) {
- npf_generate_mask(&realmask2, mask2);
- }
- for (int i = 0; i < 4; i++) {
- const uint32_t x = mask1 != NPF_NO_NETMASK ?
- addr1->s6_addr32[i] & realmask1.s6_addr32[i] :
- addr1->s6_addr32[i];
- const uint32_t y = mask2 != NPF_NO_NETMASK ?
- addr2->s6_addr32[i] & realmask2.s6_addr32[i] :
- addr2->s6_addr32[i];
- if (x < y) {
- return -1;
- }
- if (x > y) {
- return 1;
- }
- }
-
- return 0;
-}
-
static inline bool
npf_iscached(const npf_cache_t *npc, const int inf)
{
Index: src/sys/net/npf/npf_alg.c
diff -u src/sys/net/npf/npf_alg.c:1.3 src/sys/net/npf/npf_alg.c:1.4
--- src/sys/net/npf/npf_alg.c:1.3 Mon Feb 20 00:18:19 2012
+++ src/sys/net/npf/npf_alg.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_alg.c,v 1.3 2012/02/20 00:18:19 rmind Exp $ */
+/* $NetBSD: npf_alg.c,v 1.4 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -31,16 +31,17 @@
/*
* NPF interface for application level gateways (ALGs).
- *
- * XXX: locking
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v 1.3 2012/02/20 00:18:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v 1.4 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
+#include <sys/types.h>
+
#include <sys/kmem.h>
-#include <sys/pool.h>
+#include <sys/pserialize.h>
+#include <sys/mutex.h>
#include <net/pfil.h>
#include "npf_impl.h"
@@ -55,12 +56,16 @@ struct npf_alg {
npf_algfunc_t na_seid_func;
};
-static LIST_HEAD(, npf_alg) nat_alg_list __read_mostly;
+static LIST_HEAD(, npf_alg) nat_alg_list __cacheline_aligned;
+static kmutex_t nat_alg_lock __cacheline_aligned;
+static pserialize_t nat_alg_psz __cacheline_aligned;
void
npf_alg_sysinit(void)
{
+ mutex_init(&nat_alg_lock, MUTEX_DEFAULT, IPL_NONE);
+ nat_alg_psz = pserialize_create();
LIST_INIT(&nat_alg_list);
}
@@ -69,6 +74,8 @@ npf_alg_sysfini(void)
{
KASSERT(LIST_EMPTY(&nat_alg_list));
+ pserialize_destroy(nat_alg_psz);
+ mutex_destroy(&nat_alg_lock);
}
/*
@@ -88,7 +95,11 @@ npf_alg_register(npf_algfunc_t match, np
alg->na_out_func = out;
alg->na_in_func = in;
alg->na_seid_func = seid;
+
+ mutex_enter(&nat_alg_lock);
LIST_INSERT_HEAD(&nat_alg_list, alg, na_entry);
+ mutex_exit(&nat_alg_lock);
+
return alg;
}
@@ -98,17 +109,15 @@ npf_alg_register(npf_algfunc_t match, np
int
npf_alg_unregister(npf_alg_t *alg)
{
- npf_alg_t *it;
- LIST_FOREACH(it, &nat_alg_list, na_entry) {
- if (alg == it)
- break;
- }
- if (it != NULL) {
- LIST_REMOVE(alg, na_entry);
- }
- /* TODO: Flush relevant sessions. */
+ mutex_enter(&nat_alg_lock);
+ LIST_REMOVE(alg, na_entry);
+ pserialize_perform(nat_alg_psz);
+ mutex_exit(&nat_alg_lock);
+
+ npf_nat_freealg(alg);
kmem_free(alg, sizeof(npf_alg_t));
+
return 0;
}
@@ -119,15 +128,20 @@ bool
npf_alg_match(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt)
{
npf_alg_t *alg;
- npf_algfunc_t func;
+ bool match = false;
+ int s;
+ s = pserialize_read_enter();
LIST_FOREACH(alg, &nat_alg_list, na_entry) {
- func = alg->na_match_func;
+ npf_algfunc_t func = alg->na_match_func;
+
if (func && func(npc, nbuf, nt)) {
- return true;
+ match = true;
+ break;
}
}
- return false;
+ pserialize_read_exit(s);
+ return match;
}
/*
@@ -137,7 +151,9 @@ void
npf_alg_exec(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, const int di)
{
npf_alg_t *alg;
+ int s;
+ s = pserialize_read_enter();
LIST_FOREACH(alg, &nat_alg_list, na_entry) {
if ((di & PFIL_OUT) != 0 && alg->na_out_func != NULL) {
(alg->na_out_func)(npc, nbuf, nt);
@@ -148,19 +164,25 @@ npf_alg_exec(npf_cache_t *npc, nbuf_t *n
continue;
}
}
+ pserialize_read_exit(s);
}
bool
npf_alg_sessionid(npf_cache_t *npc, nbuf_t *nbuf, npf_cache_t *key)
{
npf_alg_t *alg;
- npf_algfunc_t func;
+ bool nkey = false;
+ int s;
+ s = pserialize_read_enter();
LIST_FOREACH(alg, &nat_alg_list, na_entry) {
- func = alg->na_seid_func;
+ npf_algfunc_t func = alg->na_seid_func;
+
if (func && func(npc, nbuf, (npf_nat_t *)key)) {
- return true;
+ nkey = true;
+ break;
}
}
- return false;
+ pserialize_read_exit(s);
+ return nkey;
}
Index: src/sys/net/npf/npf_log.c
diff -u src/sys/net/npf/npf_log.c:1.3 src/sys/net/npf/npf_log.c:1.4
--- src/sys/net/npf/npf_log.c:1.3 Mon Feb 20 00:18:20 2012
+++ src/sys/net/npf/npf_log.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_log.c,v 1.3 2012/02/20 00:18:20 rmind Exp $ */
+/* $NetBSD: npf_log.c,v 1.4 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_log.c,v 1.3 2012/02/20 00:18:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_log.c,v 1.4 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -58,7 +58,7 @@ typedef struct npflog_softc {
int sc_unit;
} npflog_softc_t;
-static int npflog_clone_create(struct if_clone *, int );
+static int npflog_clone_create(struct if_clone *, int);
static int npflog_clone_destroy(ifnet_t *);
static LIST_HEAD(, npflog_softc) npflog_if_list __cacheline_aligned;
@@ -120,11 +120,13 @@ npflog_clone_create(struct if_clone *ifc
ifp->if_dlt = DLT_NULL;
ifp->if_ioctl = npflog_ioctl;
+ KERNEL_LOCK(1, NULL);
if_attach(ifp);
if_alloc_sadl(ifp);
bpf_attach(ifp, DLT_NULL, 0);
-
LIST_INSERT_HEAD(&npflog_if_list, sc, sc_entry);
+ KERNEL_UNLOCK_ONE(NULL);
+
return 0;
}
@@ -133,9 +135,12 @@ npflog_clone_destroy(ifnet_t *ifp)
{
npflog_softc_t *sc = ifp->if_softc;
+ KERNEL_LOCK(1, NULL);
LIST_REMOVE(sc, sc_entry);
bpf_detach(ifp);
if_detach(ifp);
+ KERNEL_UNLOCK_ONE(NULL);
+
mutex_destroy(&sc->sc_lock);
kmem_free(sc, sizeof(npflog_softc_t));
return 0;
@@ -148,13 +153,6 @@ npf_log_packet(npf_cache_t *npc, nbuf_t
ifnet_t *ifp;
int family;
- /* Find a pseudo-interface to log. */
- ifp = if_byindex(if_idx);
- if (ifp == NULL) {
- /* No interface. */
- return;
- }
-
/* Set the address family. */
if (npf_iscached(npc, NPC_IP4)) {
family = AF_INET;
@@ -164,8 +162,17 @@ npf_log_packet(npf_cache_t *npc, nbuf_t
family = AF_UNSPEC;
}
- /* Pass through BPF. */
KERNEL_LOCK(1, NULL);
+
+ /* Find a pseudo-interface to log. */
+ ifp = if_byindex(if_idx);
+ if (ifp == NULL) {
+ /* No interface. */
+ KERNEL_UNLOCK_ONE(NULL);
+ return;
+ }
+
+ /* Pass through BPF. */
ifp->if_opackets++;
ifp->if_obytes += m->m_pkthdr.len;
bpf_mtap_af(ifp, family, m);
Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.15 src/sys/net/npf/npf_impl.h:1.16
--- src/sys/net/npf/npf_impl.h:1.15 Wed May 30 21:38:03 2012
+++ src/sys/net/npf/npf_impl.h Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_impl.h,v 1.15 2012/05/30 21:38:03 rmind Exp $ */
+/* $NetBSD: npf_impl.h,v 1.16 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -177,7 +177,13 @@ uint16_t npf_fixup16_cksum(uint16_t, uin
uint16_t npf_fixup32_cksum(uint16_t, uint32_t, uint32_t);
uint16_t npf_addr_cksum(uint16_t, int, npf_addr_t *, npf_addr_t *);
uint32_t npf_addr_sum(const int, const npf_addr_t *, const npf_addr_t *);
-int npf_tcpsaw(npf_cache_t *, tcp_seq *, tcp_seq *, uint32_t *);
+int npf_addr_cmp(const npf_addr_t *, const npf_netmask_t,
+ const npf_addr_t *, const npf_netmask_t);
+void npf_addr_mask(const npf_addr_t *, const npf_netmask_t,
+ npf_addr_t *);
+
+int npf_tcpsaw(const npf_cache_t *, tcp_seq *, tcp_seq *,
+ uint32_t *);
bool npf_fetch_tcpopts(const npf_cache_t *, nbuf_t *,
uint16_t *, int *);
bool npf_normalize(npf_cache_t *, nbuf_t *, bool, bool, u_int, u_int);
@@ -291,6 +297,7 @@ void npf_nat_expire(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 *);
void npf_nat_setalg(npf_nat_t *, npf_alg_t *, uintptr_t);
+void npf_nat_freealg(npf_alg_t *);
int npf_nat_save(prop_dictionary_t, prop_array_t, npf_nat_t *);
npf_nat_t * npf_nat_restore(prop_dictionary_t, npf_session_t *);
Index: src/sys/net/npf/npf_inet.c
diff -u src/sys/net/npf/npf_inet.c:1.11 src/sys/net/npf/npf_inet.c:1.12
--- src/sys/net/npf/npf_inet.c:1.11 Mon Feb 20 00:18:19 2012
+++ src/sys/net/npf/npf_inet.c Fri Jun 22 13:43:17 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_inet.c,v 1.11 2012/02/20 00:18:19 rmind Exp $ */
+/* $NetBSD: npf_inet.c,v 1.12 2012/06/22 13:43:17 rmind Exp $ */
/*-
- * Copyright (c) 2009-2011 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -31,10 +31,15 @@
/*
* Various procotol related helper routines.
+ *
+ * This layer manipulates npf_cache_t structure i.e. caches requested headers
+ * and stores which information was cached in the information bit field.
+ * It is also responsibility of this layer to update or invalidate the cache
+ * on rewrites (e.g. by translation routines).
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.11 2012/02/20 00:18:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.12 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -121,14 +126,86 @@ npf_addr_sum(const int sz, const npf_add
return mix;
}
+static inline void
+npf_generate_mask(npf_addr_t *out, const npf_netmask_t mask)
+{
+ uint_fast8_t length = mask;
+
+ /* Note: maximum length is 32 for IPv4 and 128 for IPv6. */
+ KASSERT(length <= NPF_MAX_NETMASK);
+
+ for (int i = 0; i < 4; i++) {
+ if (length >= 32) {
+ out->s6_addr32[i] = htonl(0xffffffff);
+ length -= 32;
+ } else {
+ out->s6_addr32[i] = htonl(0xffffffff << (32 - length));
+ length = 0;
+ }
+ }
+}
+
+/*
+ * npf_addr_mask: apply the mask to a given address and store the result.
+ */
+void
+npf_addr_mask(const npf_addr_t *addr, const npf_netmask_t mask, npf_addr_t *out)
+{
+ npf_addr_t realmask;
+
+ npf_generate_mask(&realmask, mask);
+
+ for (int i = 0; i < 4; i++) {
+ out->s6_addr32[i] = addr->s6_addr32[i] & realmask.s6_addr32[i];
+ }
+}
+
+/*
+ * npf_addr_cmp: compare two addresses, either IPv4 or IPv6.
+ *
+ * => Ignore the mask, if NPF_NO_NETMASK is specified.
+ * => Return 0 if equal and -1 or 1 if less or greater accordingly.
+ */
+int
+npf_addr_cmp(const npf_addr_t *addr1, const npf_netmask_t mask1,
+ const npf_addr_t *addr2, const npf_netmask_t mask2)
+{
+ npf_addr_t realmask1, realmask2;
+
+ if (mask1 != NPF_NO_NETMASK) {
+ npf_generate_mask(&realmask1, mask1);
+ }
+ if (mask2 != NPF_NO_NETMASK) {
+ npf_generate_mask(&realmask2, mask2);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ const uint32_t x = mask1 != NPF_NO_NETMASK ?
+ addr1->s6_addr32[i] & realmask1.s6_addr32[i] :
+ addr1->s6_addr32[i];
+ const uint32_t y = mask2 != NPF_NO_NETMASK ?
+ addr2->s6_addr32[i] & realmask2.s6_addr32[i] :
+ addr2->s6_addr32[i];
+ if (x < y) {
+ return -1;
+ }
+ if (x > y) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/*
* npf_tcpsaw: helper to fetch SEQ, ACK, WIN and return TCP data length.
- * Returns all values in host byte-order.
+ *
+ * => Returns all values in host byte-order.
*/
int
-npf_tcpsaw(npf_cache_t *npc, tcp_seq *seq, tcp_seq *ack, uint32_t *win)
+npf_tcpsaw(const npf_cache_t *npc, tcp_seq *seq, tcp_seq *ack, uint32_t *win)
{
- struct tcphdr *th = &npc->npc_l4.tcp;
+ const struct tcphdr *th = &npc->npc_l4.tcp;
u_int thlen;
KASSERT(npf_iscached(npc, NPC_TCP));
@@ -139,11 +216,10 @@ npf_tcpsaw(npf_cache_t *npc, tcp_seq *se
thlen = th->th_off << 2;
if (npf_iscached(npc, NPC_IP4)) {
- struct ip *ip = &npc->npc_ip.v4;
+ const struct ip *ip = &npc->npc_ip.v4;
return ntohs(ip->ip_len) - npf_cache_hlen(npc) - thlen;
- } else {
- KASSERT(npf_iscached(npc, NPC_IP6));
- struct ip6_hdr *ip6 = &npc->npc_ip.v6;
+ } else if (npf_iscached(npc, NPC_IP6)) {
+ const struct ip6_hdr *ip6 = &npc->npc_ip.v6;
return ntohs(ip6->ip6_plen) - thlen;
}
return 0;
@@ -179,6 +255,7 @@ next:
if (nbuf_advfetch(&nbuf, &n_ptr, step, sizeof(val), &val)) {
return false;
}
+
switch (val) {
case TCPOPT_EOL:
/* Done. */
@@ -225,6 +302,7 @@ next:
topts_len -= val;
step = val - 1;
}
+
/* Any options left? */
if (__predict_true(topts_len > 0)) {
goto next;
@@ -238,21 +316,21 @@ next:
bool
npf_fetch_ip(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
{
- struct ip *ip;
- struct ip6_hdr *ip6;
uint8_t ver;
if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(uint8_t), &ver)) {
return false;
}
+
switch (ver >> 4) {
- case IPVERSION:
- /* IPv4 */
- ip = &npc->npc_ip.v4;
- /* Fetch the header. */
+ case IPVERSION: {
+ struct ip *ip = &npc->npc_ip.v4;
+
+ /* Fetch IPv4 header. */
if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(struct ip), ip)) {
return false;
}
+
/* Check header length and fragment offset. */
if ((u_int)(ip->ip_hl << 2) < sizeof(struct ip)) {
return false;
@@ -261,6 +339,7 @@ npf_fetch_ip(npf_cache_t *npc, nbuf_t *n
/* Note fragmentation. */
npc->npc_info |= NPC_IPFRAG;
}
+
/* Cache: layer 3 - IPv4. */
npc->npc_ipsz = sizeof(struct in_addr);
npc->npc_srcip = (npf_addr_t *)&ip->ip_src;
@@ -269,31 +348,31 @@ npf_fetch_ip(npf_cache_t *npc, nbuf_t *n
npc->npc_hlen = ip->ip_hl << 2;
npc->npc_next_proto = npc->npc_ip.v4.ip_p;
break;
+ }
- case (IPV6_VERSION >> 4):
- ip6 = &npc->npc_ip.v6;
+ case (IPV6_VERSION >> 4): {
+ struct ip6_hdr *ip6 = &npc->npc_ip.v6;
+ size_t toskip;
+ bool done;
+
+ /* Fetch IPv6 header. */
if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(struct ip6_hdr), ip6)) {
return false;
}
- bool done = false;
- uint_fast8_t next_proto;
- size_t toskip;
-
/* Initial next-protocol value. */
- next_proto = ip6->ip6_nxt;
+ npc->npc_next_proto = ip6->ip6_nxt;
toskip = sizeof(struct ip6_hdr);
npc->npc_hlen = 0;
+ done = false;
+ /*
+ * Advance by the length of the previous known header and
+ * fetch by the lengh of next extension header.
+ */
do {
struct ip6_ext ip6e;
- npc->npc_next_proto = next_proto;
-
- /*
- * Advance by the length of the previous known header
- * and fetch the next extension header's length.
- */
if (nbuf_advfetch(&nbuf, &n_ptr, toskip,
sizeof(struct ip6_ext), &ip6e)) {
return false;
@@ -315,21 +394,28 @@ npf_fetch_ip(npf_cache_t *npc, nbuf_t *n
break;
}
npc->npc_hlen += toskip;
- next_proto = ip6e.ip6e_nxt;
+ npc->npc_next_proto = ip6e.ip6e_nxt;
} while (!done);
+ /* Cache: layer 3 - IPv6. */
npc->npc_ipsz = sizeof(struct in6_addr);
npc->npc_srcip = (npf_addr_t *)&ip6->ip6_src;
npc->npc_dstip = (npf_addr_t *)&ip6->ip6_dst;
npc->npc_info |= NPC_IP6;
break;
+ }
default:
return false;
}
+
return true;
}
+/*
+ * npf_fetch_tcp: fetch, check and cache TCP header. If necessary,
+ * fetch and cache layer 3 as well.
+ */
bool
npf_fetch_tcp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
{
@@ -355,6 +441,10 @@ npf_fetch_tcp(npf_cache_t *npc, nbuf_t *
return true;
}
+/*
+ * npf_fetch_udp: fetch, check and cache UDP header. If necessary,
+ * fetch and cache layer 3 as well.
+ */
bool
npf_fetch_udp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
{
@@ -372,7 +462,7 @@ npf_fetch_udp(npf_cache_t *npc, nbuf_t *
uh = &npc->npc_l4.udp;
hlen = npf_cache_hlen(npc);
- /* Fetch ICMP header. */
+ /* Fetch UDP header. */
if (nbuf_advfetch(&nbuf, &n_ptr, hlen, sizeof(struct udphdr), uh)) {
return false;
}
@@ -384,8 +474,6 @@ npf_fetch_udp(npf_cache_t *npc, nbuf_t *
/*
* npf_fetch_icmp: fetch ICMP code, type and possible query ID.
- *
- * => Stores both all fetched items into the cache.
*/
bool
npf_fetch_icmp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
@@ -417,7 +505,7 @@ npf_fetch_icmp(npf_cache_t *npc, nbuf_t
/*
* npf_cache_all: general routine to cache all relevant IP (v4 or v6)
- * and TCP, UDP or ICMP data.
+ * and TCP, UDP or ICMP headers.
*/
int
npf_cache_all(npf_cache_t *npc, nbuf_t *nbuf)
Index: src/sys/net/npf/npf_nat.c
diff -u src/sys/net/npf/npf_nat.c:1.12 src/sys/net/npf/npf_nat.c:1.13
--- src/sys/net/npf/npf_nat.c:1.12 Sun Mar 11 18:27:59 2012
+++ src/sys/net/npf/npf_nat.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_nat.c,v 1.12 2012/03/11 18:27:59 rmind Exp $ */
+/* $NetBSD: npf_nat.c,v 1.13 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.12 2012/03/11 18:27:59 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.13 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -267,6 +267,12 @@ npf_nat_freepolicy(npf_natpolicy_t *np)
kmem_free(np, sizeof(npf_natpolicy_t));
}
+void
+npf_nat_freealg(npf_alg_t *alg)
+{
+ (void)alg; /* TODO */
+}
+
/*
* npf_nat_matchpolicy: compare two NAT policies.
*
Index: src/sys/net/npf/npf_session.c
diff -u src/sys/net/npf/npf_session.c:1.12 src/sys/net/npf/npf_session.c:1.13
--- src/sys/net/npf/npf_session.c:1.12 Sun Mar 11 18:27:59 2012
+++ src/sys/net/npf/npf_session.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_session.c,v 1.12 2012/03/11 18:27:59 rmind Exp $ */
+/* $NetBSD: npf_session.c,v 1.13 2012/06/22 13:43:17 rmind Exp $ */
/*-
* Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.12 2012/03/11 18:27:59 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.13 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -483,6 +483,7 @@ npf_session_inspect(npf_cache_t *npc, nb
atomic_inc_uint(&se->s_refcnt);
} else {
/* Silently block invalid packets. */
+ npf_stats_inc(NPF_STAT_INVALID_STATE);
*error = ENETUNREACH;
se = NULL;
}
Index: src/sys/net/npf/npf_state.c
diff -u src/sys/net/npf/npf_state.c:1.7 src/sys/net/npf/npf_state.c:1.8
--- src/sys/net/npf/npf_state.c:1.7 Wed May 30 21:38:03 2012
+++ src/sys/net/npf/npf_state.c Fri Jun 22 13:43:17 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_state.c,v 1.7 2012/05/30 21:38:03 rmind Exp $ */
+/* $NetBSD: npf_state.c,v 1.8 2012/06/22 13:43:17 rmind Exp $ */
/*-
- * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
+ * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.7 2012/05/30 21:38:03 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state.c,v 1.8 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -54,7 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: npf_state.c,
#define NPF_ANY_SESSION_ESTABLISHED 2
#define NPF_ANY_SESSION_NSTATES 3
-static const int npf_generic_fsm[NPF_ANY_SESSION_NSTATES][2] __read_mostly = {
+static const int npf_generic_fsm[NPF_ANY_SESSION_NSTATES][2] = {
[NPF_ANY_SESSION_CLOSED] = {
[NPF_FLOW_FORW] = NPF_ANY_SESSION_NEW,
},
@@ -68,12 +68,19 @@ static const int npf_generic_fsm[NPF_ANY
},
};
-static const u_int npf_generic_timeout[] __read_mostly = {
+static u_int npf_generic_timeout[] __read_mostly = {
[NPF_ANY_SESSION_CLOSED] = 0,
[NPF_ANY_SESSION_NEW] = 30,
[NPF_ANY_SESSION_ESTABLISHED] = 60,
};
+/*
+ * npf_state_init: initialise the state structure.
+ *
+ * Should normally be called on a first packet, which also determines the
+ * direction in a case of connection-orientated protocol. Returns true on
+ * success and false otherwise (e.g. if protocol is not supported).
+ */
bool
npf_state_init(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst)
{
@@ -111,6 +118,12 @@ npf_state_destroy(npf_state_t *nst)
mutex_destroy(&nst->nst_lock);
}
+/*
+ * npf_state_inspect: inspect the packet according to the protocol state.
+ *
+ * Return true if packet is considered to match the state (e.g. for TCP,
+ * the packet belongs to the tracked connection) and false otherwise.
+ */
bool
npf_state_inspect(const npf_cache_t *npc, nbuf_t *nbuf,
npf_state_t *nst, const bool forw)
@@ -137,9 +150,6 @@ npf_state_inspect(const npf_cache_t *npc
NPF_TCP_STATE_SAMPLE(nst, ret);
mutex_exit(&nst->nst_lock);
- if (__predict_false(!ret)) {
- npf_stats_inc(NPF_STAT_INVALID_STATE);
- }
return ret;
}
Index: src/sys/net/npf/npf_state_tcp.c
diff -u src/sys/net/npf/npf_state_tcp.c:1.6 src/sys/net/npf/npf_state_tcp.c:1.7
--- src/sys/net/npf/npf_state_tcp.c:1.6 Tue Jun 5 22:46:54 2012
+++ src/sys/net/npf/npf_state_tcp.c Fri Jun 22 13:43:17 2012
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_state_tcp.c,v 1.6 2012/06/05 22:46:54 rmind Exp $ */
+/* $NetBSD: npf_state_tcp.c,v 1.7 2012/06/22 13:43:17 rmind Exp $ */
/*-
- * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
+ * Copyright (c) 2010-2012 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.6 2012/06/05 22:46:54 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.7 2012/06/22 13:43:17 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -440,6 +440,10 @@ npf_tcp_inwindow(const npf_cache_t *npc,
return true;
}
+/*
+ * npf_state_tcp: inspect TCP segment, determine whether it belongs to
+ * the connection and track its state.
+ */
bool
npf_state_tcp(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, int di)
{
@@ -447,7 +451,7 @@ npf_state_tcp(const npf_cache_t *npc, nb
const int tcpfl = th->th_flags, state = nst->nst_state;
int nstate;
- KASSERT(mutex_owned(&nst->nst_lock));
+ KASSERT(nst->nst_state == 0 || mutex_owned(&nst->nst_lock));
/* Look for a transition to a new state. */
if (__predict_true((tcpfl & TH_RST) == 0)) {
Index: src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c:1.1 src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c:1.2
--- src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c:1.1 Sat Apr 14 21:57:29 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c Fri Jun 22 13:43:17 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_table_test.c,v 1.1 2012/04/14 21:57:29 rmind Exp $ */
+/* $NetBSD: npf_table_test.c,v 1.2 2012/06/22 13:43:17 rmind Exp $ */
/*
* NPF tableset test.
@@ -55,6 +55,15 @@ npf_table_test(bool verbose)
error = npf_tableset_insert(tblset, t2);
assert(error == 0);
+ /* Attempt to match non-existing entries - should fail. */
+ addr->s6_addr32[0] = inet_addr(ip_list[0]);
+
+ error = npf_table_match_addr(tblset, HASH_TID, addr);
+ assert(error != 0);
+
+ error = npf_table_match_addr(tblset, TREE_TID, addr);
+ assert(error != 0);
+
/* Fill both tables with IP addresses. */
for (i = 0; i < __arraycount(ip_list); i++) {
addr->s6_addr32[0] = inet_addr(ip_list[i]);