Pull up following revision(s) (requested by rmind in ticket #702): sys/net/npf/npf_tableset.c: revision 1.15 usr.sbin/npf/npfctl/npfctl.h: revision 1.21 usr.sbin/npf/npftest/libnpftest/npf_table_test.c: revision 1.6 usr.sbin/npf/npfctl/npf_disassemble.c: revision 1.10 sys/net/npf/npf_state_tcp.c: revision 1.11 sys/net/npf/npf_impl.h: revision 1.24 sys/net/npf/npf.h: revision 1.22 sys/net/npf/npf_ctl.c: revision 1.19 sys/net/npf/npf.c: revision 1.14 usr.sbin/npf/npfctl/npfctl.8: revision 1.10 usr.sbin/npf/npfctl/npfctl.c: revision 1.21 npf_tcp_inwindow: inspect the sequence numbers even if the packet contains no data, fixing up only the RST to the initial SYN. This makes off-path attacks more difficult. For the reference, see "Reflection Scan: an Off-Path Attack on TCP" by Jan Wrobel. Implement NPF table listing and preservation of entries on reload. Bump the version. npfctl(8): mention table listing.diff -r1.7.2.5 -r1.7.2.6 src/sys/net/npf/npf.c
(riz)
--- src/sys/net/npf/npf.c 2012/11/19 09:44:42 1.7.2.5
+++ src/sys/net/npf/npf.c 2012/11/24 04:34:42 1.7.2.6
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf.c,v 1.7.2.5 2012/11/19 09:44:42 msaitoh Exp $ */ | 1 | /* $NetBSD: npf.c,v 1.7.2.6 2012/11/24 04:34:42 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -24,27 +24,27 @@ | @@ -24,27 +24,27 @@ | |||
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * NPF main: dynamic load/initialisation and unload routines. | 33 | * NPF main: dynamic load/initialisation and unload routines. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.7.2.5 2012/11/19 09:44:42 msaitoh Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.7.2.6 2012/11/24 04:34:42 riz Exp $"); | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/types.h> | 40 | #include <sys/types.h> | |
41 | 41 | |||
42 | #include <sys/atomic.h> | 42 | #include <sys/atomic.h> | |
43 | #include <sys/conf.h> | 43 | #include <sys/conf.h> | |
44 | #include <sys/kauth.h> | 44 | #include <sys/kauth.h> | |
45 | #include <sys/kmem.h> | 45 | #include <sys/kmem.h> | |
46 | #include <sys/lwp.h> | 46 | #include <sys/lwp.h> | |
47 | #include <sys/module.h> | 47 | #include <sys/module.h> | |
48 | #include <sys/percpu.h> | 48 | #include <sys/percpu.h> | |
49 | #include <sys/rwlock.h> | 49 | #include <sys/rwlock.h> | |
50 | #include <sys/socketvar.h> | 50 | #include <sys/socketvar.h> | |
@@ -293,27 +293,29 @@ npf_reload(prop_dictionary_t dict, npf_r | @@ -293,27 +293,29 @@ npf_reload(prop_dictionary_t dict, npf_r | |||
293 | 293 | |||
294 | /* Setup a new core structure. */ | 294 | /* Setup a new core structure. */ | |
295 | nc = kmem_zalloc(sizeof(npf_core_t), KM_SLEEP); | 295 | nc = kmem_zalloc(sizeof(npf_core_t), KM_SLEEP); | |
296 | nc->n_rules = rset; | 296 | nc->n_rules = rset; | |
297 | nc->n_tables = tset; | 297 | nc->n_tables = tset; | |
298 | nc->n_nat_rules = nset; | 298 | nc->n_nat_rules = nset; | |
299 | nc->n_dict = dict; | 299 | nc->n_dict = dict; | |
300 | nc->n_default_pass = flush; | 300 | nc->n_default_pass = flush; | |
301 | 301 | |||
302 | /* Lock and load the core structure. */ | 302 | /* Lock and load the core structure. */ | |
303 | rw_enter(&npf_lock, RW_WRITER); | 303 | rw_enter(&npf_lock, RW_WRITER); | |
304 | onc = atomic_swap_ptr(&npf_core, nc); | 304 | onc = atomic_swap_ptr(&npf_core, nc); | |
305 | if (onc) { | 305 | if (onc) { | |
306 | /* Reload only necessary NAT policies. */ | 306 | /* Reload only the static tables. */ | |
307 | npf_tableset_reload(tset, onc->n_tables); | |||
308 | /* Reload only the necessary NAT policies. */ | |||
307 | npf_ruleset_natreload(nset, onc->n_nat_rules); | 309 | npf_ruleset_natreload(nset, onc->n_nat_rules); | |
308 | } | 310 | } | |
309 | /* Unlock. Everything goes "live" now. */ | 311 | /* Unlock. Everything goes "live" now. */ | |
310 | rw_exit(&npf_lock); | 312 | rw_exit(&npf_lock); | |
311 | 313 | |||
312 | if (onc) { | 314 | if (onc) { | |
313 | /* Destroy unloaded structures. */ | 315 | /* Destroy unloaded structures. */ | |
314 | npf_core_destroy(onc); | 316 | npf_core_destroy(onc); | |
315 | } | 317 | } | |
316 | } | 318 | } | |
317 | 319 | |||
318 | void | 320 | void | |
319 | npf_core_enter(void) | 321 | npf_core_enter(void) |
--- src/sys/net/npf/npf.h 2012/11/18 22:38:26 1.14.2.7
+++ src/sys/net/npf/npf.h 2012/11/24 04:34:42 1.14.2.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf.h,v 1.14.2.7 2012/11/18 22:38:26 riz Exp $ */ | 1 | /* $NetBSD: npf.h,v 1.14.2.8 2012/11/24 04:34:42 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -35,27 +35,27 @@ | @@ -35,27 +35,27 @@ | |||
35 | 35 | |||
36 | #ifndef _NPF_NET_H_ | 36 | #ifndef _NPF_NET_H_ | |
37 | #define _NPF_NET_H_ | 37 | #define _NPF_NET_H_ | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/types.h> | 40 | #include <sys/types.h> | |
41 | 41 | |||
42 | #include <sys/ioctl.h> | 42 | #include <sys/ioctl.h> | |
43 | #include <prop/proplib.h> | 43 | #include <prop/proplib.h> | |
44 | 44 | |||
45 | #include <netinet/in_systm.h> | 45 | #include <netinet/in_systm.h> | |
46 | #include <netinet/in.h> | 46 | #include <netinet/in.h> | |
47 | 47 | |||
48 | #define NPF_VERSION 6 | 48 | #define NPF_VERSION 7 | |
49 | 49 | |||
50 | /* | 50 | /* | |
51 | * Public declarations and definitions. | 51 | * Public declarations and definitions. | |
52 | */ | 52 | */ | |
53 | 53 | |||
54 | /* Storage of address (both for IPv4 and IPv6) and netmask */ | 54 | /* Storage of address (both for IPv4 and IPv6) and netmask */ | |
55 | typedef struct in6_addr npf_addr_t; | 55 | typedef struct in6_addr npf_addr_t; | |
56 | typedef uint8_t npf_netmask_t; | 56 | typedef uint8_t npf_netmask_t; | |
57 | 57 | |||
58 | #define NPF_MAX_NETMASK (128) | 58 | #define NPF_MAX_NETMASK (128) | |
59 | #define NPF_NO_NETMASK ((npf_netmask_t)~0) | 59 | #define NPF_NO_NETMASK ((npf_netmask_t)~0) | |
60 | 60 | |||
61 | #if defined(_KERNEL) | 61 | #if defined(_KERNEL) | |
@@ -201,35 +201,49 @@ bool npf_autounload_p(void); | @@ -201,35 +201,49 @@ bool npf_autounload_p(void); | |||
201 | #define NPF_TABLE_TREE 2 | 201 | #define NPF_TABLE_TREE 2 | |
202 | 202 | |||
203 | /* Layers. */ | 203 | /* Layers. */ | |
204 | #define NPF_LAYER_2 2 | 204 | #define NPF_LAYER_2 2 | |
205 | #define NPF_LAYER_3 3 | 205 | #define NPF_LAYER_3 3 | |
206 | 206 | |||
207 | /* XXX mbuf.h: just for now. */ | 207 | /* XXX mbuf.h: just for now. */ | |
208 | #define PACKET_TAG_NPF 10 | 208 | #define PACKET_TAG_NPF 10 | |
209 | 209 | |||
210 | /* | 210 | /* | |
211 | * IOCTL structures. | 211 | * IOCTL structures. | |
212 | */ | 212 | */ | |
213 | 213 | |||
214 | #define NPF_IOCTL_TBLENT_LOOKUP 0 | |||
214 | #define NPF_IOCTL_TBLENT_ADD 1 | 215 | #define NPF_IOCTL_TBLENT_ADD 1 | |
215 | #define NPF_IOCTL_TBLENT_REM 2 | 216 | #define NPF_IOCTL_TBLENT_REM 2 | |
217 | #define NPF_IOCTL_TBLENT_LIST 3 | |||
218 | ||||
219 | typedef struct npf_ioctl_ent { | |||
220 | int alen; | |||
221 | npf_addr_t addr; | |||
222 | npf_netmask_t mask; | |||
223 | } npf_ioctl_ent_t; | |||
224 | ||||
225 | typedef struct npf_ioctl_buf { | |||
226 | void * buf; | |||
227 | size_t len; | |||
228 | } npf_ioctl_buf_t; | |||
216 | 229 | |||
217 | typedef struct npf_ioctl_table { | 230 | typedef struct npf_ioctl_table { | |
218 | int nct_action; | 231 | int nct_action; | |
219 | u_int nct_tid; | 232 | u_int nct_tid; | |
220 | int nct_alen; | 233 | union { | |
221 | npf_addr_t nct_addr; | 234 | npf_ioctl_ent_t ent; | |
222 | npf_netmask_t nct_mask; | 235 | npf_ioctl_buf_t buf; | |
236 | } nct_data; | |||
223 | } npf_ioctl_table_t; | 237 | } npf_ioctl_table_t; | |
224 | 238 | |||
225 | typedef enum { | 239 | typedef enum { | |
226 | /* Packets passed. */ | 240 | /* Packets passed. */ | |
227 | NPF_STAT_PASS_DEFAULT, | 241 | NPF_STAT_PASS_DEFAULT, | |
228 | NPF_STAT_PASS_RULESET, | 242 | NPF_STAT_PASS_RULESET, | |
229 | NPF_STAT_PASS_SESSION, | 243 | NPF_STAT_PASS_SESSION, | |
230 | /* Packets blocked. */ | 244 | /* Packets blocked. */ | |
231 | NPF_STAT_BLOCK_DEFAULT, | 245 | NPF_STAT_BLOCK_DEFAULT, | |
232 | NPF_STAT_BLOCK_RULESET, | 246 | NPF_STAT_BLOCK_RULESET, | |
233 | /* Session and NAT entries. */ | 247 | /* Session and NAT entries. */ | |
234 | NPF_STAT_SESSION_CREATE, | 248 | NPF_STAT_SESSION_CREATE, | |
235 | NPF_STAT_SESSION_DESTROY, | 249 | NPF_STAT_SESSION_DESTROY, |
--- src/sys/net/npf/npf_ctl.c 2012/11/18 22:38:26 1.12.2.5
+++ src/sys/net/npf/npf_ctl.c 2012/11/24 04:34:42 1.12.2.6
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf_ctl.c,v 1.12.2.5 2012/11/18 22:38:26 riz Exp $ */ | 1 | /* $NetBSD: npf_ctl.c,v 1.12.2.6 2012/11/24 04:34:42 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -27,27 +27,27 @@ | @@ -27,27 +27,27 @@ | |||
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * NPF device control. | 33 | * NPF device control. | |
34 | * | 34 | * | |
35 | * Implementation of (re)loading, construction of tables and rules. | 35 | * Implementation of (re)loading, construction of tables and rules. | |
36 | * NPF proplib(9) dictionary consumer. | 36 | * NPF proplib(9) dictionary consumer. | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | #include <sys/cdefs.h> | 39 | #include <sys/cdefs.h> | |
40 | __KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.12.2.5 2012/11/18 22:38:26 riz Exp $"); | 40 | __KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.12.2.6 2012/11/24 04:34:42 riz Exp $"); | |
41 | 41 | |||
42 | #include <sys/param.h> | 42 | #include <sys/param.h> | |
43 | #include <sys/conf.h> | 43 | #include <sys/conf.h> | |
44 | 44 | |||
45 | #include <prop/proplib.h> | 45 | #include <prop/proplib.h> | |
46 | 46 | |||
47 | #include "npf_ncode.h" | 47 | #include "npf_ncode.h" | |
48 | #include "npf_impl.h" | 48 | #include "npf_impl.h" | |
49 | 49 | |||
50 | #if defined(DEBUG) || defined(DIAGNOSTIC) | 50 | #if defined(DEBUG) || defined(DIAGNOSTIC) | |
51 | #define NPF_ERR_DEBUG(e) \ | 51 | #define NPF_ERR_DEBUG(e) \ | |
52 | prop_dictionary_set_cstring_nocopy((e), "source-file", __FILE__); \ | 52 | prop_dictionary_set_cstring_nocopy((e), "source-file", __FILE__); \ | |
53 | prop_dictionary_set_uint32((e), "source-line", __LINE__); | 53 | prop_dictionary_set_uint32((e), "source-line", __LINE__); | |
@@ -700,35 +700,44 @@ fail: | @@ -700,35 +700,44 @@ fail: | |||
700 | sess_htable_destroy(sehasht); | 700 | sess_htable_destroy(sehasht); | |
701 | } | 701 | } | |
702 | return error; | 702 | return error; | |
703 | } | 703 | } | |
704 | 704 | |||
705 | /* | 705 | /* | |
706 | * npfctl_table: add, remove or query entries in the specified table. | 706 | * npfctl_table: add, remove or query entries in the specified table. | |
707 | * | 707 | * | |
708 | * For maximum performance, interface is avoiding proplib(3)'s overhead. | 708 | * For maximum performance, interface is avoiding proplib(3)'s overhead. | |
709 | */ | 709 | */ | |
710 | int | 710 | int | |
711 | npfctl_table(void *data) | 711 | npfctl_table(void *data) | |
712 | { | 712 | { | |
713 | npf_ioctl_table_t *nct = data; | 713 | const npf_ioctl_table_t *nct = data; | |
714 | npf_tableset_t *tblset; | 714 | npf_tableset_t *tblset; | |
715 | int error; | 715 | int error; | |
716 | 716 | |||
717 | npf_core_enter(); /* XXXSMP */ | 717 | npf_core_enter(); /* XXXSMP */ | |
718 | tblset = npf_core_tableset(); | 718 | tblset = npf_core_tableset(); | |
719 | switch (nct->nct_action) { | 719 | switch (nct->nct_action) { | |
720 | case NPF_IOCTL_TBLENT_LOOKUP: | |||
721 | error = npf_table_lookup(tblset, nct->nct_tid, | |||
722 | nct->nct_data.ent.alen, &nct->nct_data.ent.addr); | |||
720 | case NPF_IOCTL_TBLENT_ADD: | 723 | case NPF_IOCTL_TBLENT_ADD: | |
721 | error = npf_table_insert(tblset, nct->nct_tid, | 724 | error = npf_table_insert(tblset, nct->nct_tid, | |
722 | nct->nct_alen, &nct->nct_addr, nct->nct_mask); | 725 | nct->nct_data.ent.alen, &nct->nct_data.ent.addr, | |
726 | nct->nct_data.ent.mask); | |||
723 | break; | 727 | break; | |
724 | case NPF_IOCTL_TBLENT_REM: | 728 | case NPF_IOCTL_TBLENT_REM: | |
725 | error = npf_table_remove(tblset, nct->nct_tid, | 729 | error = npf_table_remove(tblset, nct->nct_tid, | |
726 | nct->nct_alen, &nct->nct_addr, nct->nct_mask); | 730 | nct->nct_data.ent.alen, &nct->nct_data.ent.addr, | |
731 | nct->nct_data.ent.mask); | |||
732 | break; | |||
733 | case NPF_IOCTL_TBLENT_LIST: | |||
734 | error = npf_table_list(tblset, nct->nct_tid, | |||
735 | nct->nct_data.buf.buf, nct->nct_data.buf.len); | |||
727 | break; | 736 | break; | |
728 | default: | 737 | default: | |
729 | error = npf_table_lookup(tblset, nct->nct_tid, | 738 | error = EINVAL; | |
730 | nct->nct_alen, &nct->nct_addr); | 739 | break; | |
731 | } | 740 | } | |
732 | npf_core_exit(); /* XXXSMP */ | 741 | npf_core_exit(); /* XXXSMP */ | |
733 | return error; | 742 | return error; | |
734 | } | 743 | } |
--- src/sys/net/npf/npf_impl.h 2012/11/18 22:38:26 1.10.2.9
+++ src/sys/net/npf/npf_impl.h 2012/11/24 04:34:42 1.10.2.10
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf_impl.h,v 1.10.2.9 2012/11/18 22:38:26 riz Exp $ */ | 1 | /* $NetBSD: npf_impl.h,v 1.10.2.10 2012/11/24 04:34:42 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -71,31 +71,29 @@ | @@ -71,31 +71,29 @@ | |||
71 | struct npf_ruleset; | 71 | struct npf_ruleset; | |
72 | struct npf_rule; | 72 | struct npf_rule; | |
73 | struct npf_nat; | 73 | struct npf_nat; | |
74 | struct npf_session; | 74 | struct npf_session; | |
75 | 75 | |||
76 | typedef struct npf_ruleset npf_ruleset_t; | 76 | typedef struct npf_ruleset npf_ruleset_t; | |
77 | typedef struct npf_rule npf_rule_t; | 77 | typedef struct npf_rule npf_rule_t; | |
78 | typedef struct npf_nat npf_nat_t; | 78 | typedef struct npf_nat npf_nat_t; | |
79 | typedef struct npf_alg npf_alg_t; | 79 | typedef struct npf_alg npf_alg_t; | |
80 | typedef struct npf_natpolicy npf_natpolicy_t; | 80 | typedef struct npf_natpolicy npf_natpolicy_t; | |
81 | typedef struct npf_session npf_session_t; | 81 | typedef struct npf_session npf_session_t; | |
82 | 82 | |||
83 | struct npf_sehash; | 83 | struct npf_sehash; | |
84 | struct npf_tblent; | |||
85 | struct npf_table; | 84 | struct npf_table; | |
86 | 85 | |||
87 | typedef struct npf_sehash npf_sehash_t; | 86 | typedef struct npf_sehash npf_sehash_t; | |
88 | typedef struct npf_tblent npf_tblent_t; | |||
89 | typedef struct npf_table npf_table_t; | 87 | typedef struct npf_table npf_table_t; | |
90 | 88 | |||
91 | typedef npf_table_t * npf_tableset_t; | 89 | typedef npf_table_t * npf_tableset_t; | |
92 | 90 | |||
93 | /* | 91 | /* | |
94 | * DEFINITIONS. | 92 | * DEFINITIONS. | |
95 | */ | 93 | */ | |
96 | 94 | |||
97 | typedef bool (*npf_algfunc_t)(npf_cache_t *, nbuf_t *, void *); | 95 | typedef bool (*npf_algfunc_t)(npf_cache_t *, nbuf_t *, void *); | |
98 | 96 | |||
99 | #define NPF_NCODE_LIMIT 1024 | 97 | #define NPF_NCODE_LIMIT 1024 | |
100 | #define NPF_TABLE_SLOTS 32 | 98 | #define NPF_TABLE_SLOTS 32 | |
101 | 99 | |||
@@ -198,42 +196,39 @@ int npf_match_udp_ports(npf_cache_t *, | @@ -198,42 +196,39 @@ int npf_match_udp_ports(npf_cache_t *, | |||
198 | int npf_match_icmp4(npf_cache_t *, nbuf_t *, void *, uint32_t); | 196 | int npf_match_icmp4(npf_cache_t *, nbuf_t *, void *, uint32_t); | |
199 | int npf_match_icmp6(npf_cache_t *, nbuf_t *, void *, uint32_t); | 197 | int npf_match_icmp6(npf_cache_t *, nbuf_t *, void *, uint32_t); | |
200 | int npf_match_tcpfl(npf_cache_t *, nbuf_t *, void *, uint32_t); | 198 | int npf_match_tcpfl(npf_cache_t *, nbuf_t *, void *, uint32_t); | |
201 | 199 | |||
202 | /* Tableset interface. */ | 200 | /* Tableset interface. */ | |
203 | void npf_tableset_sysinit(void); | 201 | void npf_tableset_sysinit(void); | |
204 | void npf_tableset_sysfini(void); | 202 | void npf_tableset_sysfini(void); | |
205 | 203 | |||
206 | const pt_tree_ops_t npf_table_ptree_ops; | 204 | const pt_tree_ops_t npf_table_ptree_ops; | |
207 | 205 | |||
208 | npf_tableset_t *npf_tableset_create(void); | 206 | npf_tableset_t *npf_tableset_create(void); | |
209 | void npf_tableset_destroy(npf_tableset_t *); | 207 | void npf_tableset_destroy(npf_tableset_t *); | |
210 | int npf_tableset_insert(npf_tableset_t *, npf_table_t *); | 208 | int npf_tableset_insert(npf_tableset_t *, npf_table_t *); | |
211 | npf_tableset_t *npf_tableset_reload(npf_tableset_t *); | 209 | void npf_tableset_reload(npf_tableset_t *, npf_tableset_t *); | |
212 | 210 | |||
213 | npf_table_t * npf_table_create(u_int, int, size_t); | 211 | npf_table_t * npf_table_create(u_int, int, size_t); | |
214 | void npf_table_destroy(npf_table_t *); | 212 | void npf_table_destroy(npf_table_t *); | |
215 | void npf_table_ref(npf_table_t *); | |||
216 | void npf_table_unref(npf_table_t *); | |||
217 | 213 | |||
218 | npf_table_t * npf_table_get(npf_tableset_t *, u_int); | |||
219 | void npf_table_put(npf_table_t *); | |||
220 | int npf_table_check(const npf_tableset_t *, u_int, int); | 214 | int npf_table_check(const npf_tableset_t *, u_int, int); | |
221 | int npf_table_insert(npf_tableset_t *, u_int, | 215 | int npf_table_insert(npf_tableset_t *, u_int, | |
222 | const int, const npf_addr_t *, const npf_netmask_t); | 216 | const int, const npf_addr_t *, const npf_netmask_t); | |
223 | int npf_table_remove(npf_tableset_t *, u_int, | 217 | int npf_table_remove(npf_tableset_t *, u_int, | |
224 | const int, const npf_addr_t *, const npf_netmask_t); | 218 | const int, const npf_addr_t *, const npf_netmask_t); | |
225 | int npf_table_lookup(npf_tableset_t *, u_int, | 219 | int npf_table_lookup(npf_tableset_t *, u_int, | |
226 | const int, const npf_addr_t *); | 220 | const int, const npf_addr_t *); | |
221 | int npf_table_list(npf_tableset_t *, u_int, void *, size_t); | |||
227 | 222 | |||
228 | /* Ruleset interface. */ | 223 | /* Ruleset interface. */ | |
229 | npf_ruleset_t * npf_ruleset_create(void); | 224 | npf_ruleset_t * npf_ruleset_create(void); | |
230 | void npf_ruleset_destroy(npf_ruleset_t *); | 225 | void npf_ruleset_destroy(npf_ruleset_t *); | |
231 | void npf_ruleset_insert(npf_ruleset_t *, npf_rule_t *); | 226 | void npf_ruleset_insert(npf_ruleset_t *, npf_rule_t *); | |
232 | void npf_ruleset_natreload(npf_ruleset_t *, npf_ruleset_t *); | 227 | void npf_ruleset_natreload(npf_ruleset_t *, npf_ruleset_t *); | |
233 | npf_rule_t * npf_ruleset_matchnat(npf_ruleset_t *, npf_natpolicy_t *); | 228 | npf_rule_t * npf_ruleset_matchnat(npf_ruleset_t *, npf_natpolicy_t *); | |
234 | npf_rule_t * npf_ruleset_sharepm(npf_ruleset_t *, npf_natpolicy_t *); | 229 | npf_rule_t * npf_ruleset_sharepm(npf_ruleset_t *, npf_natpolicy_t *); | |
235 | npf_rule_t * npf_ruleset_replace(const char *, npf_ruleset_t *); | 230 | npf_rule_t * npf_ruleset_replace(const char *, npf_ruleset_t *); | |
236 | void npf_ruleset_freealg(npf_ruleset_t *, npf_alg_t *); | 231 | void npf_ruleset_freealg(npf_ruleset_t *, npf_alg_t *); | |
237 | 232 | |||
238 | npf_rule_t * npf_ruleset_inspect(npf_cache_t *, nbuf_t *, npf_ruleset_t *, | 233 | npf_rule_t * npf_ruleset_inspect(npf_cache_t *, nbuf_t *, npf_ruleset_t *, | |
239 | const ifnet_t *, const int, const int); | 234 | const ifnet_t *, const int, const int); |
--- src/sys/net/npf/npf_state_tcp.c 2012/07/25 20:45:24 1.3.2.5
+++ src/sys/net/npf/npf_state_tcp.c 2012/11/24 04:34:42 1.3.2.6
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf_state_tcp.c,v 1.3.2.5 2012/07/25 20:45:24 jdc Exp $ */ | 1 | /* $NetBSD: npf_state_tcp.c,v 1.3.2.6 2012/11/24 04:34:42 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2010-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2010-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -24,27 +24,27 @@ | @@ -24,27 +24,27 @@ | |||
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * NPF TCP state engine for connection tracking. | 33 | * NPF TCP state engine for connection tracking. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | __KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.3.2.5 2012/07/25 20:45:24 jdc Exp $"); | 37 | __KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.3.2.6 2012/11/24 04:34:42 riz Exp $"); | |
38 | 38 | |||
39 | #include <sys/param.h> | 39 | #include <sys/param.h> | |
40 | #include <sys/types.h> | 40 | #include <sys/types.h> | |
41 | 41 | |||
42 | #ifndef _KERNEL | 42 | #ifndef _KERNEL | |
43 | #include <stdio.h> | 43 | #include <stdio.h> | |
44 | #include <stdbool.h> | 44 | #include <stdbool.h> | |
45 | #include <inttypes.h> | 45 | #include <inttypes.h> | |
46 | #endif | 46 | #endif | |
47 | #include <netinet/in.h> | 47 | #include <netinet/in.h> | |
48 | #include <netinet/tcp.h> | 48 | #include <netinet/tcp.h> | |
49 | #include <netinet/tcp_seq.h> | 49 | #include <netinet/tcp_seq.h> | |
50 | 50 | |||
@@ -84,26 +84,28 @@ static u_int npf_tcp_timeouts[] __read_m | @@ -84,26 +84,28 @@ static u_int npf_tcp_timeouts[] __read_m | |||
84 | [NPF_TCPS_ESTABLISHED] = 60 * 60 * 24, | 84 | [NPF_TCPS_ESTABLISHED] = 60 * 60 * 24, | |
85 | /* FIN seen: 4 minutes (2 * MSL). */ | 85 | /* FIN seen: 4 minutes (2 * MSL). */ | |
86 | [NPF_TCPS_FIN_SENT] = 60 * 2 * 2, | 86 | [NPF_TCPS_FIN_SENT] = 60 * 2 * 2, | |
87 | [NPF_TCPS_FIN_RECEIVED] = 60 * 2 * 2, | 87 | [NPF_TCPS_FIN_RECEIVED] = 60 * 2 * 2, | |
88 | /* Half-closed cases: 6 hours. */ | 88 | /* Half-closed cases: 6 hours. */ | |
89 | [NPF_TCPS_CLOSE_WAIT] = 60 * 60 * 6, | 89 | [NPF_TCPS_CLOSE_WAIT] = 60 * 60 * 6, | |
90 | [NPF_TCPS_FIN_WAIT] = 60 * 60 * 6, | 90 | [NPF_TCPS_FIN_WAIT] = 60 * 60 * 6, | |
91 | /* Full close cases: 30 sec and 2 * MSL. */ | 91 | /* Full close cases: 30 sec and 2 * MSL. */ | |
92 | [NPF_TCPS_CLOSING] = 30, | 92 | [NPF_TCPS_CLOSING] = 30, | |
93 | [NPF_TCPS_LAST_ACK] = 30, | 93 | [NPF_TCPS_LAST_ACK] = 30, | |
94 | [NPF_TCPS_TIME_WAIT] = 60 * 2 * 2, | 94 | [NPF_TCPS_TIME_WAIT] = 60 * 2 * 2, | |
95 | }; | 95 | }; | |
96 | 96 | |||
97 | static bool npf_strict_order_rst __read_mostly = false; | |||
98 | ||||
97 | #define NPF_TCP_MAXACKWIN 66000 | 99 | #define NPF_TCP_MAXACKWIN 66000 | |
98 | 100 | |||
99 | /* | 101 | /* | |
100 | * List of TCP flag cases and conversion of flags to a case (index). | 102 | * List of TCP flag cases and conversion of flags to a case (index). | |
101 | */ | 103 | */ | |
102 | 104 | |||
103 | #define TCPFC_INVALID 0 | 105 | #define TCPFC_INVALID 0 | |
104 | #define TCPFC_SYN 1 | 106 | #define TCPFC_SYN 1 | |
105 | #define TCPFC_SYNACK 2 | 107 | #define TCPFC_SYNACK 2 | |
106 | #define TCPFC_ACK 3 | 108 | #define TCPFC_ACK 3 | |
107 | #define TCPFC_FIN 4 | 109 | #define TCPFC_FIN 4 | |
108 | #define TCPFC_COUNT 5 | 110 | #define TCPFC_COUNT 5 | |
109 | 111 | |||
@@ -381,37 +383,40 @@ npf_tcp_inwindow(const npf_cache_t *npc, | @@ -381,37 +383,40 @@ npf_tcp_inwindow(const npf_cache_t *npc, | |||
381 | if (tcpfl & TH_SYN) { | 383 | if (tcpfl & TH_SYN) { | |
382 | (void)npf_fetch_tcpopts(npc, nbuf, NULL, | 384 | (void)npf_fetch_tcpopts(npc, nbuf, NULL, | |
383 | &fstate->nst_wscale); | 385 | &fstate->nst_wscale); | |
384 | } | 386 | } | |
385 | } | 387 | } | |
386 | 388 | |||
387 | if ((tcpfl & TH_ACK) == 0) { | 389 | if ((tcpfl & TH_ACK) == 0) { | |
388 | /* Pretend that an ACK was sent. */ | 390 | /* Pretend that an ACK was sent. */ | |
389 | ack = tstate->nst_end; | 391 | ack = tstate->nst_end; | |
390 | } else if ((tcpfl & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST) && ack == 0) { | 392 | } else if ((tcpfl & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST) && ack == 0) { | |
391 | /* Workaround for some TCP stacks. */ | 393 | /* Workaround for some TCP stacks. */ | |
392 | ack = tstate->nst_end; | 394 | ack = tstate->nst_end; | |
393 | } | 395 | } | |
394 | if (seq == end) { | 396 | ||
395 | /* If packet contains no data - assume it is valid. */ | 397 | if (__predict_false(tcpfl & TH_RST)) { | |
396 | end = fstate->nst_end; | 398 | /* RST to the initial SYN may have zero SEQ - fix it up. */ | |
397 | seq = end; | 399 | if (seq == 0 && nst->nst_state == NPF_TCPS_SYN_SENT) { | |
398 | } | 400 | end = fstate->nst_end; | |
399 | #if 0 | 401 | seq = end; | |
400 | /* Strict in-order sequence for RST packets. */ | 402 | } | |
401 | if ((tcpfl & TH_RST) != 0 && (fstate->nst_end - seq) > 1) { | 403 | ||
402 | return false; | 404 | /* Strict in-order sequence for RST packets. */ | |
405 | if (npf_strict_order_rst && (fstate->nst_end - seq) > 1) { | |||
406 | return false; | |||
407 | } | |||
403 | } | 408 | } | |
404 | #endif | 409 | ||
405 | /* | 410 | /* | |
406 | * Determine whether the data is within previously noted window, | 411 | * Determine whether the data is within previously noted window, | |
407 | * that is, upper boundary for valid data (I). | 412 | * that is, upper boundary for valid data (I). | |
408 | */ | 413 | */ | |
409 | if (!SEQ_LEQ(end, fstate->nst_maxend)) { | 414 | if (!SEQ_LEQ(end, fstate->nst_maxend)) { | |
410 | npf_stats_inc(NPF_STAT_INVALID_STATE_TCP1); | 415 | npf_stats_inc(NPF_STAT_INVALID_STATE_TCP1); | |
411 | return false; | 416 | return false; | |
412 | } | 417 | } | |
413 | 418 | |||
414 | /* Lower boundary (II), which is no more than one window back. */ | 419 | /* Lower boundary (II), which is no more than one window back. */ | |
415 | if (!SEQ_GEQ(seq, fstate->nst_end - tstate->nst_maxwin)) { | 420 | if (!SEQ_GEQ(seq, fstate->nst_end - tstate->nst_maxwin)) { | |
416 | npf_stats_inc(NPF_STAT_INVALID_STATE_TCP2); | 421 | npf_stats_inc(NPF_STAT_INVALID_STATE_TCP2); | |
417 | return false; | 422 | return false; |
--- src/sys/net/npf/npf_tableset.c 2012/08/13 17:49:52 1.9.2.5
+++ src/sys/net/npf/npf_tableset.c 2012/11/24 04:34:41 1.9.2.6
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf_tableset.c,v 1.9.2.5 2012/08/13 17:49:52 riz Exp $ */ | 1 | /* $NetBSD: npf_tableset.c,v 1.9.2.6 2012/11/24 04:34:41 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -22,74 +22,80 @@ | @@ -22,74 +22,80 @@ | |||
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * NPF tableset module. | 33 | * NPF tableset module. | |
34 | * | 34 | * | |
35 | * TODO: | 35 | * Notes | |
36 | * - Dynamic hash growing/shrinking (i.e. re-hash functionality), maybe? | 36 | * | |
37 | * - Dynamic array resize. | 37 | * The tableset is an array of tables. After the creation, the array | |
38 | * is immutable. The caller is responsible to synchronise the access | |||
39 | * to the tableset. The table can either be a hash or a tree. Its | |||
40 | * entries are protected by a read-write lock. | |||
38 | */ | 41 | */ | |
39 | 42 | |||
40 | #include <sys/cdefs.h> | 43 | #include <sys/cdefs.h> | |
41 | __KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.9.2.5 2012/08/13 17:49:52 riz Exp $"); | 44 | __KERNEL_RCSID(0, "$NetBSD: npf_tableset.c,v 1.9.2.6 2012/11/24 04:34:41 riz Exp $"); | |
42 | 45 | |||
43 | #include <sys/param.h> | 46 | #include <sys/param.h> | |
44 | #include <sys/types.h> | 47 | #include <sys/types.h> | |
45 | 48 | |||
46 | #include <sys/atomic.h> | 49 | #include <sys/atomic.h> | |
47 | #include <sys/hash.h> | 50 | #include <sys/hash.h> | |
48 | #include <sys/kmem.h> | 51 | #include <sys/kmem.h> | |
49 | #include <sys/pool.h> | 52 | #include <sys/pool.h> | |
50 | #include <sys/queue.h> | 53 | #include <sys/queue.h> | |
51 | #include <sys/rwlock.h> | 54 | #include <sys/rwlock.h> | |
52 | #include <sys/systm.h> | 55 | #include <sys/systm.h> | |
53 | #include <sys/types.h> | 56 | #include <sys/types.h> | |
54 | 57 | |||
55 | #include "npf_impl.h" | 58 | #include "npf_impl.h" | |
56 | 59 | |||
57 | /* | 60 | /* | |
58 | * Table structures. | 61 | * Table structures. | |
59 | */ | 62 | */ | |
60 | 63 | |||
61 | struct npf_tblent { | 64 | typedef struct npf_tblent { | |
62 | union { | 65 | union { | |
63 | LIST_ENTRY(npf_tblent) hashq; | 66 | LIST_ENTRY(npf_tblent) hashq; | |
64 | pt_node_t node; | 67 | pt_node_t node; | |
65 | } te_entry; | 68 | } te_entry; | |
66 | int te_alen; | 69 | int te_alen; | |
67 | npf_addr_t te_addr; | 70 | npf_addr_t te_addr; | |
68 | }; | 71 | } npf_tblent_t; | |
69 | 72 | |||
70 | LIST_HEAD(npf_hashl, npf_tblent); | 73 | LIST_HEAD(npf_hashl, npf_tblent); | |
71 | 74 | |||
72 | struct npf_table { | 75 | struct npf_table { | |
73 | char t_name[16]; | 76 | char t_name[16]; | |
74 | /* Lock and reference count. */ | 77 | /* Lock and reference count. */ | |
75 | krwlock_t t_lock; | 78 | krwlock_t t_lock; | |
76 | u_int t_refcnt; | 79 | u_int t_refcnt; | |
80 | /* Total number of items. */ | |||
81 | u_int t_nitems; | |||
77 | /* Table ID. */ | 82 | /* Table ID. */ | |
78 | u_int t_id; | 83 | u_int t_id; | |
79 | /* The storage type can be: a) hash b) tree. */ | 84 | /* The storage type can be: a) hash b) tree. */ | |
80 | int t_type; | 85 | int t_type; | |
81 | struct npf_hashl * t_hashl; | 86 | struct npf_hashl * t_hashl; | |
82 | u_long t_hashmask; | 87 | u_long t_hashmask; | |
88 | /* Separate trees for IPv4 and IPv6. */ | |||
83 | pt_tree_t t_tree[2]; | 89 | pt_tree_t t_tree[2]; | |
84 | }; | 90 | }; | |
85 | 91 | |||
86 | #define NPF_ADDRLEN2TREE(alen) ((alen) >> 4) | 92 | #define NPF_ADDRLEN2TREE(alen) ((alen) >> 4) | |
87 | 93 | |||
88 | static pool_cache_t tblent_cache __read_mostly; | 94 | static pool_cache_t tblent_cache __read_mostly; | |
89 | 95 | |||
90 | /* | 96 | /* | |
91 | * npf_table_sysinit: initialise tableset structures. | 97 | * npf_table_sysinit: initialise tableset structures. | |
92 | */ | 98 | */ | |
93 | void | 99 | void | |
94 | npf_tableset_sysinit(void) | 100 | npf_tableset_sysinit(void) | |
95 | { | 101 | { | |
@@ -116,56 +122,81 @@ npf_tableset_create(void) | @@ -116,56 +122,81 @@ npf_tableset_create(void) | |||
116 | void | 122 | void | |
117 | npf_tableset_destroy(npf_tableset_t *tblset) | 123 | npf_tableset_destroy(npf_tableset_t *tblset) | |
118 | { | 124 | { | |
119 | const size_t sz = NPF_TABLE_SLOTS * sizeof(npf_table_t *); | 125 | const size_t sz = NPF_TABLE_SLOTS * sizeof(npf_table_t *); | |
120 | npf_table_t *t; | 126 | npf_table_t *t; | |
121 | u_int tid; | 127 | u_int tid; | |
122 | 128 | |||
123 | /* | 129 | /* | |
124 | * Destroy all tables (no references should be held, as ruleset | 130 | * Destroy all tables (no references should be held, as ruleset | |
125 | * should be destroyed before). | 131 | * should be destroyed before). | |
126 | */ | 132 | */ | |
127 | for (tid = 0; tid < NPF_TABLE_SLOTS; tid++) { | 133 | for (tid = 0; tid < NPF_TABLE_SLOTS; tid++) { | |
128 | t = tblset[tid]; | 134 | t = tblset[tid]; | |
129 | if (t != NULL) { | 135 | if (t && --t->t_refcnt == 0) { | |
130 | npf_table_destroy(t); | 136 | npf_table_destroy(t); | |
131 | } | 137 | } | |
132 | } | 138 | } | |
133 | kmem_free(tblset, sz); | 139 | kmem_free(tblset, sz); | |
134 | } | 140 | } | |
135 | 141 | |||
136 | /* | 142 | /* | |
137 | * npf_tableset_insert: insert the table into the specified tableset. | 143 | * npf_tableset_insert: insert the table into the specified tableset. | |
138 | * | 144 | * | |
139 | * => Returns 0 on success. Fails and returns error if ID is already used. | 145 | * => Returns 0 on success. Fails and returns error if ID is already used. | |
140 | */ | 146 | */ | |
141 | int | 147 | int | |
142 | npf_tableset_insert(npf_tableset_t *tblset, npf_table_t *t) | 148 | npf_tableset_insert(npf_tableset_t *tblset, npf_table_t *t) | |
143 | { | 149 | { | |
144 | const u_int tid = t->t_id; | 150 | const u_int tid = t->t_id; | |
145 | int error; | 151 | int error; | |
146 | 152 | |||
147 | KASSERT((u_int)tid < NPF_TABLE_SLOTS); | 153 | KASSERT((u_int)tid < NPF_TABLE_SLOTS); | |
148 | 154 | |||
149 | if (tblset[tid] == NULL) { | 155 | if (tblset[tid] == NULL) { | |
150 | tblset[tid] = t; | 156 | tblset[tid] = t; | |
157 | t->t_refcnt++; | |||
151 | error = 0; | 158 | error = 0; | |
152 | } else { | 159 | } else { | |
153 | error = EEXIST; | 160 | error = EEXIST; | |
154 | } | 161 | } | |
155 | return error; | 162 | return error; | |
156 | } | 163 | } | |
157 | 164 | |||
158 | /* | 165 | /* | |
166 | * npf_tableset_reload: iterate all tables and if the new table is of the | |||
167 | * same type and has no items, then we preserve the old one and its entries. | |||
168 | * | |||
169 | * => The caller is responsible for providing synchronisation. | |||
170 | */ | |||
171 | void | |||
172 | npf_tableset_reload(npf_tableset_t *ntset, npf_tableset_t *otset) | |||
173 | { | |||
174 | for (int i = 0; i < NPF_TABLE_SLOTS; i++) { | |||
175 | npf_table_t *t = ntset[i], *ot = otset[i]; | |||
176 | ||||
177 | if (t == NULL || ot == NULL) { | |||
178 | continue; | |||
179 | } | |||
180 | if (t->t_nitems || t->t_type != ot->t_type) { | |||
181 | continue; | |||
182 | } | |||
183 | ntset[i] = ot; | |||
184 | ot->t_refcnt++; | |||
185 | npf_table_destroy(t); | |||
186 | } | |||
187 | } | |||
188 | ||||
189 | /* | |||
159 | * Few helper routines. | 190 | * Few helper routines. | |
160 | */ | 191 | */ | |
161 | 192 | |||
162 | static npf_tblent_t * | 193 | static npf_tblent_t * | |
163 | table_hash_lookup(const npf_table_t *t, const npf_addr_t *addr, | 194 | table_hash_lookup(const npf_table_t *t, const npf_addr_t *addr, | |
164 | const int alen, struct npf_hashl **rhtbl) | 195 | const int alen, struct npf_hashl **rhtbl) | |
165 | { | 196 | { | |
166 | const uint32_t hidx = hash32_buf(addr, alen, HASH32_BUF_INIT); | 197 | const uint32_t hidx = hash32_buf(addr, alen, HASH32_BUF_INIT); | |
167 | struct npf_hashl *htbl = &t->t_hashl[hidx & t->t_hashmask]; | 198 | struct npf_hashl *htbl = &t->t_hashl[hidx & t->t_hashmask]; | |
168 | npf_tblent_t *ent; | 199 | npf_tblent_t *ent; | |
169 | 200 | |||
170 | /* | 201 | /* | |
171 | * Lookup the hash table and check for duplicates. | 202 | * Lookup the hash table and check for duplicates. | |
@@ -218,141 +249,82 @@ npf_table_create(u_int tid, int type, si | @@ -218,141 +249,82 @@ npf_table_create(u_int tid, int type, si | |||
218 | break; | 249 | break; | |
219 | case NPF_TABLE_HASH: | 250 | case NPF_TABLE_HASH: | |
220 | t->t_hashl = hashinit(hsize, HASH_LIST, true, &t->t_hashmask); | 251 | t->t_hashl = hashinit(hsize, HASH_LIST, true, &t->t_hashmask); | |
221 | if (t->t_hashl == NULL) { | 252 | if (t->t_hashl == NULL) { | |
222 | kmem_free(t, sizeof(npf_table_t)); | 253 | kmem_free(t, sizeof(npf_table_t)); | |
223 | return NULL; | 254 | return NULL; | |
224 | } | 255 | } | |
225 | break; | 256 | break; | |
226 | default: | 257 | default: | |
227 | KASSERT(false); | 258 | KASSERT(false); | |
228 | } | 259 | } | |
229 | rw_init(&t->t_lock); | 260 | rw_init(&t->t_lock); | |
230 | t->t_type = type; | 261 | t->t_type = type; | |
231 | t->t_refcnt = 1; | |||
232 | t->t_id = tid; | 262 | t->t_id = tid; | |
263 | ||||
233 | return t; | 264 | return t; | |
234 | } | 265 | } | |
235 | 266 | |||
236 | /* | 267 | /* | |
237 | * npf_table_destroy: free all table entries and table itself. | 268 | * npf_table_destroy: free all table entries and table itself. | |
238 | */ | 269 | */ | |
239 | void | 270 | void | |
240 | npf_table_destroy(npf_table_t *t) | 271 | npf_table_destroy(npf_table_t *t) | |
241 | { | 272 | { | |
242 | 273 | |||
243 | switch (t->t_type) { | 274 | switch (t->t_type) { | |
244 | case NPF_TABLE_HASH: { | 275 | case NPF_TABLE_HASH: | |
245 | for (unsigned n = 0; n <= t->t_hashmask; n++) { | 276 | for (unsigned n = 0; n <= t->t_hashmask; n++) { | |
246 | npf_tblent_t *ent; | 277 | npf_tblent_t *ent; | |
247 | 278 | |||
248 | while ((ent = LIST_FIRST(&t->t_hashl[n])) != NULL) { | 279 | while ((ent = LIST_FIRST(&t->t_hashl[n])) != NULL) { | |
249 | LIST_REMOVE(ent, te_entry.hashq); | 280 | LIST_REMOVE(ent, te_entry.hashq); | |
250 | pool_cache_put(tblent_cache, ent); | 281 | pool_cache_put(tblent_cache, ent); | |
251 | } | 282 | } | |
252 | } | 283 | } | |
253 | hashdone(t->t_hashl, HASH_LIST, t->t_hashmask); | 284 | hashdone(t->t_hashl, HASH_LIST, t->t_hashmask); | |
254 | break; | 285 | break; | |
255 | } | 286 | case NPF_TABLE_TREE: | |
256 | case NPF_TABLE_TREE: { | |||
257 | table_tree_destroy(&t->t_tree[0]); | 287 | table_tree_destroy(&t->t_tree[0]); | |
258 | table_tree_destroy(&t->t_tree[1]); | 288 | table_tree_destroy(&t->t_tree[1]); | |
259 | break; | 289 | break; | |
260 | } | |||
261 | default: | 290 | default: | |
262 | KASSERT(false); | 291 | KASSERT(false); | |
263 | } | 292 | } | |
264 | rw_destroy(&t->t_lock); | 293 | rw_destroy(&t->t_lock); | |
265 | kmem_free(t, sizeof(npf_table_t)); | 294 | kmem_free(t, sizeof(npf_table_t)); | |
266 | } | 295 | } | |
267 | 296 | |||
268 | /* | 297 | /* | |
269 | * npf_table_ref: holds the reference on table. | |||
270 | * | |||
271 | * => Table must be locked. | |||
272 | */ | |||
273 | void | |||
274 | npf_table_ref(npf_table_t *t) | |||
275 | { | |||
276 | ||||
277 | KASSERT(rw_lock_held(&t->t_lock)); | |||
278 | atomic_inc_uint(&t->t_refcnt); | |||
279 | } | |||
280 | ||||
281 | /* | |||
282 | * npf_table_unref: drop reference from the table and destroy the table if | |||
283 | * it is the last reference. | |||
284 | */ | |||
285 | void | |||
286 | npf_table_unref(npf_table_t *t) | |||
287 | { | |||
288 | ||||
289 | if (atomic_dec_uint_nv(&t->t_refcnt) != 0) { | |||
290 | return; | |||
291 | } | |||
292 | npf_table_destroy(t); | |||
293 | } | |||
294 | ||||
295 | /* | |||
296 | * npf_table_get: find the table according to ID and "get it" by locking it. | |||
297 | */ | |||
298 | npf_table_t * | |||
299 | npf_table_get(npf_tableset_t *tset, u_int tid) | |||
300 | { | |||
301 | npf_table_t *t; | |||
302 | ||||
303 | KASSERT(tset != NULL); | |||
304 | ||||
305 | if ((u_int)tid >= NPF_TABLE_SLOTS) { | |||
306 | return NULL; | |||
307 | } | |||
308 | t = tset[tid]; | |||
309 | if (t != NULL) { | |||
310 | rw_enter(&t->t_lock, RW_READER); | |||
311 | } | |||
312 | return t; | |||
313 | } | |||
314 | ||||
315 | /* | |||
316 | * npf_table_put: "put table back" by unlocking it. | |||
317 | */ | |||
318 | void | |||
319 | npf_table_put(npf_table_t *t) | |||
320 | { | |||
321 | ||||
322 | rw_exit(&t->t_lock); | |||
323 | } | |||
324 | ||||
325 | /* | |||
326 | * npf_table_check: validate ID and type. | 298 | * npf_table_check: validate ID and type. | |
327 | */ | 299 | */ | |
328 | int | 300 | int | |
329 | npf_table_check(const npf_tableset_t *tset, u_int tid, int type) | 301 | npf_table_check(const npf_tableset_t *tset, u_int tid, int type) | |
330 | { | 302 | { | |
331 | 303 | |||
332 | if ((u_int)tid >= NPF_TABLE_SLOTS) { | 304 | if ((u_int)tid >= NPF_TABLE_SLOTS) { | |
333 | return EINVAL; | 305 | return EINVAL; | |
334 | } | 306 | } | |
335 | if (tset[tid] != NULL) { | 307 | if (tset[tid] != NULL) { | |
336 | return EEXIST; | 308 | return EEXIST; | |
337 | } | 309 | } | |
338 | if (type != NPF_TABLE_TREE && type != NPF_TABLE_HASH) { | 310 | if (type != NPF_TABLE_TREE && type != NPF_TABLE_HASH) { | |
339 | return EINVAL; | 311 | return EINVAL; | |
340 | } | 312 | } | |
341 | return 0; | 313 | return 0; | |
342 | } | 314 | } | |
343 | 315 | |||
344 | static int | 316 | static int | |
345 | npf_table_validate_cidr(const u_int aidx, const npf_addr_t *addr, | 317 | table_cidr_check(const u_int aidx, const npf_addr_t *addr, | |
346 | const npf_netmask_t mask) | 318 | const npf_netmask_t mask) | |
347 | { | 319 | { | |
348 | 320 | |||
349 | if (mask > NPF_MAX_NETMASK && mask != NPF_NO_NETMASK) { | 321 | if (mask > NPF_MAX_NETMASK && mask != NPF_NO_NETMASK) { | |
350 | return EINVAL; | 322 | return EINVAL; | |
351 | } | 323 | } | |
352 | if (aidx > 1) { | 324 | if (aidx > 1) { | |
353 | return EINVAL; | 325 | return EINVAL; | |
354 | } | 326 | } | |
355 | 327 | |||
356 | /* | 328 | /* | |
357 | * For IPv4 (aidx = 0) - 32 and for IPv6 (aidx = 1) - 128. | 329 | * For IPv4 (aidx = 0) - 32 and for IPv6 (aidx = 1) - 128. | |
358 | * If it is a host - shall use NPF_NO_NETMASK. | 330 | * If it is a host - shall use NPF_NO_NETMASK. | |
@@ -365,166 +337,250 @@ npf_table_validate_cidr(const u_int aidx | @@ -365,166 +337,250 @@ npf_table_validate_cidr(const u_int aidx | |||
365 | 337 | |||
366 | /* | 338 | /* | |
367 | * npf_table_insert: add an IP CIDR entry into the table. | 339 | * npf_table_insert: add an IP CIDR entry into the table. | |
368 | */ | 340 | */ | |
369 | int | 341 | int | |
370 | npf_table_insert(npf_tableset_t *tset, u_int tid, const int alen, | 342 | npf_table_insert(npf_tableset_t *tset, u_int tid, const int alen, | |
371 | const npf_addr_t *addr, const npf_netmask_t mask) | 343 | const npf_addr_t *addr, const npf_netmask_t mask) | |
372 | { | 344 | { | |
373 | const u_int aidx = NPF_ADDRLEN2TREE(alen); | 345 | const u_int aidx = NPF_ADDRLEN2TREE(alen); | |
374 | npf_tblent_t *ent; | 346 | npf_tblent_t *ent; | |
375 | npf_table_t *t; | 347 | npf_table_t *t; | |
376 | int error; | 348 | int error; | |
377 | 349 | |||
378 | error = npf_table_validate_cidr(aidx, addr, mask); | 350 | if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { | |
351 | return EINVAL; | |||
352 | } | |||
353 | ||||
354 | error = table_cidr_check(aidx, addr, mask); | |||
379 | if (error) { | 355 | if (error) { | |
380 | return error; | 356 | return error; | |
381 | } | 357 | } | |
382 | ent = pool_cache_get(tblent_cache, PR_WAITOK); | 358 | ent = pool_cache_get(tblent_cache, PR_WAITOK); | |
383 | memcpy(&ent->te_addr, addr, alen); | 359 | memcpy(&ent->te_addr, addr, alen); | |
384 | ent->te_alen = alen; | 360 | ent->te_alen = alen; | |
385 | 361 | |||
386 | /* Get the table (acquire the lock). */ | |||
387 | t = npf_table_get(tset, tid); | |||
388 | if (t == NULL) { | |||
389 | pool_cache_put(tblent_cache, ent); | |||
390 | return EINVAL; | |||
391 | } | |||
392 | ||||
393 | /* | 362 | /* | |
394 | * Insert the entry. Return an error on duplicate. | 363 | * Insert the entry. Return an error on duplicate. | |
395 | */ | 364 | */ | |
365 | rw_enter(&t->t_lock, RW_WRITER); | |||
396 | switch (t->t_type) { | 366 | switch (t->t_type) { | |
397 | case NPF_TABLE_HASH: { | 367 | case NPF_TABLE_HASH: { | |
398 | struct npf_hashl *htbl; | 368 | struct npf_hashl *htbl; | |
399 | 369 | |||
400 | /* | 370 | /* | |
401 | * Hash tables by the concept support only IPs. | 371 | * Hash tables by the concept support only IPs. | |
402 | */ | 372 | */ | |
403 | if (mask != NPF_NO_NETMASK) { | 373 | if (mask != NPF_NO_NETMASK) { | |
404 | error = EINVAL; | 374 | error = EINVAL; | |
405 | break; | 375 | break; | |
406 | } | 376 | } | |
407 | if (!table_hash_lookup(t, addr, alen, &htbl)) { | 377 | if (!table_hash_lookup(t, addr, alen, &htbl)) { | |
408 | LIST_INSERT_HEAD(htbl, ent, te_entry.hashq); | 378 | LIST_INSERT_HEAD(htbl, ent, te_entry.hashq); | |
379 | t->t_nitems++; | |||
409 | } else { | 380 | } else { | |
410 | error = EEXIST; | 381 | error = EEXIST; | |
411 | } | 382 | } | |
412 | break; | 383 | break; | |
413 | } | 384 | } | |
414 | case NPF_TABLE_TREE: { | 385 | case NPF_TABLE_TREE: { | |
415 | pt_tree_t *tree = &t->t_tree[aidx]; | 386 | pt_tree_t *tree = &t->t_tree[aidx]; | |
416 | bool ok; | 387 | bool ok; | |
417 | 388 | |||
418 | /* | 389 | /* | |
419 | * If no mask specified, use maximum mask. | 390 | * If no mask specified, use maximum mask. | |
420 | */ | 391 | */ | |
421 | if (mask != NPF_NO_NETMASK) { | 392 | ok = (mask != NPF_NO_NETMASK) ? | |
422 | ok = ptree_insert_mask_node(tree, ent, mask); | 393 | ptree_insert_mask_node(tree, ent, mask) : | |
394 | ptree_insert_node(tree, ent); | |||
395 | if (ok) { | |||
396 | t->t_nitems++; | |||
397 | error = 0; | |||
423 | } else { | 398 | } else { | |
424 | ok = ptree_insert_node(tree, ent); | 399 | error = EEXIST; | |
425 | } | 400 | } | |
426 | error = ok ? 0 : EEXIST; | |||
427 | break; | 401 | break; | |
428 | } | 402 | } | |
429 | default: | 403 | default: | |
430 | KASSERT(false); | 404 | KASSERT(false); | |
431 | } | 405 | } | |
432 | npf_table_put(t); | 406 | rw_exit(&t->t_lock); | |
433 | 407 | |||
434 | if (error) { | 408 | if (error) { | |
435 | pool_cache_put(tblent_cache, ent); | 409 | pool_cache_put(tblent_cache, ent); | |
436 | } | 410 | } | |
437 | return error; | 411 | return error; | |
438 | } | 412 | } | |
439 | 413 | |||
440 | /* | 414 | /* | |
441 | * npf_table_remove: remove the IP CIDR entry from the table. | 415 | * npf_table_remove: remove the IP CIDR entry from the table. | |
442 | */ | 416 | */ | |
443 | int | 417 | int | |
444 | npf_table_remove(npf_tableset_t *tset, u_int tid, const int alen, | 418 | npf_table_remove(npf_tableset_t *tset, u_int tid, const int alen, | |
445 | const npf_addr_t *addr, const npf_netmask_t mask) | 419 | const npf_addr_t *addr, const npf_netmask_t mask) | |
446 | { | 420 | { | |
447 | const u_int aidx = NPF_ADDRLEN2TREE(alen); | 421 | const u_int aidx = NPF_ADDRLEN2TREE(alen); | |
448 | npf_tblent_t *ent; | 422 | npf_tblent_t *ent; | |
449 | npf_table_t *t; | 423 | npf_table_t *t; | |
450 | int error; | 424 | int error; | |
451 | 425 | |||
452 | error = npf_table_validate_cidr(aidx, addr, mask); | 426 | error = table_cidr_check(aidx, addr, mask); | |
453 | if (error) { | 427 | if (error) { | |
454 | return error; | 428 | return error; | |
455 | } | 429 | } | |
456 | t = npf_table_get(tset, tid); | 430 | ||
457 | if (t == NULL) { | 431 | if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { | |
458 | return EINVAL; | 432 | return EINVAL; | |
459 | } | 433 | } | |
460 | 434 | |||
435 | rw_enter(&t->t_lock, RW_WRITER); | |||
461 | switch (t->t_type) { | 436 | switch (t->t_type) { | |
462 | case NPF_TABLE_HASH: { | 437 | case NPF_TABLE_HASH: { | |
463 | struct npf_hashl *htbl; | 438 | struct npf_hashl *htbl; | |
464 | 439 | |||
465 | ent = table_hash_lookup(t, addr, alen, &htbl); | 440 | ent = table_hash_lookup(t, addr, alen, &htbl); | |
466 | if (__predict_true(ent != NULL)) { | 441 | if (__predict_true(ent != NULL)) { | |
467 | LIST_REMOVE(ent, te_entry.hashq); | 442 | LIST_REMOVE(ent, te_entry.hashq); | |
443 | t->t_nitems--; | |||
468 | } | 444 | } | |
469 | break; | 445 | break; | |
470 | } | 446 | } | |
471 | case NPF_TABLE_TREE: { | 447 | case NPF_TABLE_TREE: { | |
472 | pt_tree_t *tree = &t->t_tree[aidx]; | 448 | pt_tree_t *tree = &t->t_tree[aidx]; | |
473 | 449 | |||
474 | ent = ptree_find_node(tree, addr); | 450 | ent = ptree_find_node(tree, addr); | |
475 | if (__predict_true(ent != NULL)) { | 451 | if (__predict_true(ent != NULL)) { | |
476 | ptree_remove_node(tree, ent); | 452 | ptree_remove_node(tree, ent); | |
453 | t->t_nitems--; | |||
477 | } | 454 | } | |
478 | break; | 455 | break; | |
479 | } | 456 | } | |
480 | default: | 457 | default: | |
481 | KASSERT(false); | 458 | KASSERT(false); | |
482 | ent = NULL; | 459 | ent = NULL; | |
483 | } | 460 | } | |
484 | npf_table_put(t); | 461 | rw_exit(&t->t_lock); | |
485 | 462 | |||
486 | if (ent == NULL) { | 463 | if (ent == NULL) { | |
487 | return ENOENT; | 464 | return ENOENT; | |
488 | } | 465 | } | |
489 | pool_cache_put(tblent_cache, ent); | 466 | pool_cache_put(tblent_cache, ent); | |
490 | return 0; | 467 | return 0; | |
491 | } | 468 | } | |
492 | 469 | |||
493 | /* | 470 | /* | |
494 | * npf_table_lookup: find the table according to ID, lookup and match | 471 | * npf_table_lookup: find the table according to ID, lookup and match | |
495 | * the contents with the specified IP address. | 472 | * the contents with the specified IP address. | |
496 | */ | 473 | */ | |
497 | int | 474 | int | |
498 | npf_table_lookup(npf_tableset_t *tset, u_int tid, | 475 | npf_table_lookup(npf_tableset_t *tset, u_int tid, | |
499 | const int alen, const npf_addr_t *addr) | 476 | const int alen, const npf_addr_t *addr) | |
500 | { | 477 | { | |
501 | const u_int aidx = NPF_ADDRLEN2TREE(alen); | 478 | const u_int aidx = NPF_ADDRLEN2TREE(alen); | |
502 | npf_tblent_t *ent; | 479 | npf_tblent_t *ent; | |
503 | npf_table_t *t; | 480 | npf_table_t *t; | |
504 | 481 | |||
505 | if (__predict_false(aidx > 1)) { | 482 | if (__predict_false(aidx > 1)) { | |
506 | return EINVAL; | 483 | return EINVAL; | |
507 | } | 484 | } | |
508 | 485 | |||
509 | t = npf_table_get(tset, tid); | 486 | if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { | |
510 | if (__predict_false(t == NULL)) { | |||
511 | return EINVAL; | 487 | return EINVAL; | |
512 | } | 488 | } | |
489 | ||||
490 | rw_enter(&t->t_lock, RW_READER); | |||
513 | switch (t->t_type) { | 491 | switch (t->t_type) { | |
514 | case NPF_TABLE_HASH: { | 492 | case NPF_TABLE_HASH: { | |
515 | struct npf_hashl *htbl; | 493 | struct npf_hashl *htbl; | |
516 | ent = table_hash_lookup(t, addr, alen, &htbl); | 494 | ent = table_hash_lookup(t, addr, alen, &htbl); | |
517 | break; | 495 | break; | |
518 | } | 496 | } | |
519 | case NPF_TABLE_TREE: { | 497 | case NPF_TABLE_TREE: { | |
520 | ent = ptree_find_node(&t->t_tree[aidx], addr); | 498 | ent = ptree_find_node(&t->t_tree[aidx], addr); | |
521 | break; | 499 | break; | |
522 | } | 500 | } | |
523 | default: | 501 | default: | |
524 | KASSERT(false); | 502 | KASSERT(false); | |
525 | ent = NULL; | 503 | ent = NULL; | |
526 | } | 504 | } | |
527 | npf_table_put(t); | 505 | rw_exit(&t->t_lock); | |
528 | 506 | |||
529 | return ent ? 0 : ENOENT; | 507 | return ent ? 0 : ENOENT; | |
530 | } | 508 | } | |
509 | ||||
510 | static int | |||
511 | table_ent_copyout(npf_tblent_t *ent, npf_netmask_t mask, | |||
512 | void *ubuf, size_t len, size_t *off) | |||
513 | { | |||
514 | void *ubufp = (uint8_t *)ubuf + *off; | |||
515 | npf_ioctl_ent_t uent; | |||
516 | ||||
517 | if ((*off += sizeof(npf_ioctl_ent_t)) > len) { | |||
518 | return ENOMEM; | |||
519 | } | |||
520 | uent.alen = ent->te_alen; | |||
521 | memcpy(&uent.addr, &ent->te_addr, sizeof(npf_addr_t)); | |||
522 | uent.mask = mask; | |||
523 | ||||
524 | return copyout(&uent, ubufp, sizeof(npf_ioctl_ent_t)); | |||
525 | } | |||
526 | ||||
527 | static int | |||
528 | table_tree_list(pt_tree_t *tree, npf_netmask_t maxmask, void *ubuf, | |||
529 | size_t len, size_t *off) | |||
530 | { | |||
531 | npf_tblent_t *ent = NULL; | |||
532 | int error = 0; | |||
533 | ||||
534 | while ((ent = ptree_iterate(tree, ent, PT_ASCENDING)) != NULL) { | |||
535 | pt_bitlen_t blen; | |||
536 | ||||
537 | if (!ptree_mask_node_p(tree, ent, &blen)) { | |||
538 | blen = maxmask; | |||
539 | } | |||
540 | error = table_ent_copyout(ent, blen, ubuf, len, off); | |||
541 | if (error) | |||
542 | break; | |||
543 | } | |||
544 | return error; | |||
545 | } | |||
546 | ||||
547 | /* | |||
548 | * npf_table_list: copy a list of all table entries into a userspace buffer. | |||
549 | */ | |||
550 | int | |||
551 | npf_table_list(npf_tableset_t *tset, u_int tid, void *ubuf, size_t len) | |||
552 | { | |||
553 | npf_table_t *t; | |||
554 | size_t off = 0; | |||
555 | int error = 0; | |||
556 | ||||
557 | if ((u_int)tid >= NPF_TABLE_SLOTS || (t = tset[tid]) == NULL) { | |||
558 | return EINVAL; | |||
559 | } | |||
560 | ||||
561 | rw_enter(&t->t_lock, RW_READER); | |||
562 | switch (t->t_type) { | |||
563 | case NPF_TABLE_HASH: | |||
564 | for (unsigned n = 0; n <= t->t_hashmask; n++) { | |||
565 | npf_tblent_t *ent; | |||
566 | ||||
567 | LIST_FOREACH(ent, &t->t_hashl[n], te_entry.hashq) | |||
568 | if ((error = table_ent_copyout(ent, 0, ubuf, | |||
569 | len, &off)) != 0) | |||
570 | break; | |||
571 | } | |||
572 | break; | |||
573 | case NPF_TABLE_TREE: | |||
574 | error = table_tree_list(&t->t_tree[0], 32, ubuf, len, &off); | |||
575 | if (error) | |||
576 | break; | |||
577 | error = table_tree_list(&t->t_tree[1], 128, ubuf, len, &off); | |||
578 | if (error) | |||
579 | break; | |||
580 | default: | |||
581 | KASSERT(false); | |||
582 | } | |||
583 | rw_exit(&t->t_lock); | |||
584 | ||||
585 | return error; | |||
586 | } |
--- src/usr.sbin/npf/npfctl/Attic/npf_disassemble.c 2012/08/13 19:43:44 1.3.2.7
+++ src/usr.sbin/npf/npfctl/Attic/npf_disassemble.c 2012/11/24 04:34:43 1.3.2.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf_disassemble.c,v 1.3.2.7 2012/08/13 19:43:44 riz Exp $ */ | 1 | /* $NetBSD: npf_disassemble.c,v 1.3.2.8 2012/11/24 04:34:43 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Christos Zoulas. | 8 | * by Christos Zoulas. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * NPF n-code disassembler. | 33 | * NPF n-code disassembler. | |
34 | * | 34 | * | |
35 | * FIXME: config generation should be redesigned.. | 35 | * FIXME: config generation should be redesigned.. | |
36 | */ | 36 | */ | |
37 | #include <sys/cdefs.h> | 37 | #include <sys/cdefs.h> | |
38 | __RCSID("$NetBSD: npf_disassemble.c,v 1.3.2.7 2012/08/13 19:43:44 riz Exp $"); | 38 | __RCSID("$NetBSD: npf_disassemble.c,v 1.3.2.8 2012/11/24 04:34:43 riz Exp $"); | |
39 | 39 | |||
40 | #include <stdio.h> | 40 | #include <stdio.h> | |
41 | #include <stdlib.h> | 41 | #include <stdlib.h> | |
42 | #include <string.h> | 42 | #include <string.h> | |
43 | #include <unistd.h> | 43 | #include <unistd.h> | |
44 | #include <errno.h> | 44 | #include <errno.h> | |
45 | #include <err.h> | 45 | #include <err.h> | |
46 | #include <sys/socket.h> | 46 | #include <sys/socket.h> | |
47 | #include <netinet/in.h> | 47 | #include <netinet/in.h> | |
48 | #include <netinet/tcp.h> | 48 | #include <netinet/tcp.h> | |
49 | #include <net/if.h> | 49 | #include <net/if.h> | |
50 | 50 | |||
51 | #include <util.h> | 51 | #include <util.h> | |
@@ -654,70 +654,51 @@ npfctl_show_nat(nl_rule_t *nrl, unsigned | @@ -654,70 +654,51 @@ npfctl_show_nat(nl_rule_t *nrl, unsigned | |||
654 | int type; | 654 | int type; | |
655 | 655 | |||
656 | /* TODO: bi-NAT */ | 656 | /* TODO: bi-NAT */ | |
657 | 657 | |||
658 | _npf_rule_getinfo(nrl, &rg.rg_name, &rg.rg_attr, &rg.rg_ifnum); | 658 | _npf_rule_getinfo(nrl, &rg.rg_name, &rg.rg_attr, &rg.rg_ifnum); | |
659 | 659 | |||
660 | /* Get the interface, if any. */ | 660 | /* Get the interface, if any. */ | |
661 | char ifnamebuf[IFNAMSIZ], *ifname = NULL; | 661 | char ifnamebuf[IFNAMSIZ], *ifname = NULL; | |
662 | if (rg.rg_ifnum) { | 662 | if (rg.rg_ifnum) { | |
663 | ifname = if_indextoname(rg.rg_ifnum, ifnamebuf); | 663 | ifname = if_indextoname(rg.rg_ifnum, ifnamebuf); | |
664 | } | 664 | } | |
665 | _npf_nat_getinfo(nt, &type, &flags, &taddr, &alen, &port); | 665 | _npf_nat_getinfo(nt, &type, &flags, &taddr, &alen, &port); | |
666 | 666 | |||
667 | struct sockaddr_storage ss; | 667 | char *taddrbuf, tportbuf[16]; | |
668 | char taddrbuf[64], tportbuf[16]; | |||
669 | ||||
670 | if (alen == 4) { | |||
671 | struct sockaddr_in *sin = (void *)&ss; | |||
672 | sin->sin_len = sizeof(*sin); | |||
673 | sin->sin_family = AF_INET; | |||
674 | sin->sin_port = 0; | |||
675 | memcpy(&sin->sin_addr, &taddr, sizeof(sin->sin_addr)); | |||
676 | sockaddr_snprintf(taddrbuf, sizeof(taddrbuf), | |||
677 | "%a", (struct sockaddr *)sin); | |||
678 | } else { | |||
679 | assert(alen == 16); | |||
680 | struct sockaddr_in6 *sin6 = (void *)&ss; | |||
681 | sin6->sin6_len = sizeof(*sin6); | |||
682 | sin6->sin6_family = AF_INET6; | |||
683 | sin6->sin6_port = 0; | |||
684 | memcpy(&sin6->sin6_addr, &taddr, sizeof(sin6->sin6_addr)); | |||
685 | sockaddr_snprintf(taddrbuf, sizeof(taddrbuf), | |||
686 | "%a", (struct sockaddr *)sin6); | |||
687 | } | |||
688 | 668 | |||
669 | taddrbuf = npfctl_print_addrmask(alen, &taddr, 0); | |||
689 | if (port) { | 670 | if (port) { | |
690 | snprintf(tportbuf, sizeof(tportbuf), | 671 | snprintf(tportbuf, sizeof(tportbuf), " port %d", ntohs(port)); | |
691 | " port %d", ntohs(port)); | |||
692 | } | 672 | } | |
693 | 673 | |||
694 | const char *seg1 = "any", *seg2 = "any", *sp1 = "", *sp2 = "", *mt; | 674 | const char *seg1 = "any", *seg2 = "any", *sp1 = "", *sp2 = "", *mt; | |
695 | switch (type) { | 675 | switch (type) { | |
696 | case NPF_NATIN: | 676 | case NPF_NATIN: | |
697 | mt = "<-"; | 677 | mt = "<-"; | |
698 | seg1 = taddrbuf; | 678 | seg1 = taddrbuf; | |
699 | sp1 = port ? tportbuf : ""; | 679 | sp1 = port ? tportbuf : ""; | |
700 | break; | 680 | break; | |
701 | case NPF_NATOUT: | 681 | case NPF_NATOUT: | |
702 | mt = "->"; | 682 | mt = "->"; | |
703 | seg2 = taddrbuf; | 683 | seg2 = taddrbuf; | |
704 | sp2 = port ? tportbuf : ""; | 684 | sp2 = port ? tportbuf : ""; | |
705 | break; | 685 | break; | |
706 | default: | 686 | default: | |
707 | assert(false); | 687 | assert(false); | |
708 | } | 688 | } | |
709 | printf("map %s dynamic %s%s %s %s%s pass ", ifname, | 689 | printf("map %s dynamic %s%s %s %s%s pass ", ifname, | |
710 | seg1, sp1, mt, seg2, sp2); | 690 | seg1, sp1, mt, seg2, sp2); | |
691 | free(taddrbuf); | |||
711 | 692 | |||
712 | const void *nc; | 693 | const void *nc; | |
713 | size_t nclen; | 694 | size_t nclen; | |
714 | 695 | |||
715 | nc = _npf_rule_ncode(nrl, &nclen); | 696 | nc = _npf_rule_ncode(nrl, &nclen); | |
716 | printf("%s\n", (!nc || !npfctl_show_ncode(nc, nclen)) ? " any " : ""); | 697 | printf("%s\n", (!nc || !npfctl_show_ncode(nc, nclen)) ? " any " : ""); | |
717 | } | 698 | } | |
718 | 699 | |||
719 | int | 700 | int | |
720 | npfctl_config_show(int fd) | 701 | npfctl_config_show(int fd) | |
721 | { | 702 | { | |
722 | nl_config_t *ncf; | 703 | nl_config_t *ncf; | |
723 | bool active, loaded; | 704 | bool active, loaded; |
--- src/usr.sbin/npf/npfctl/npfctl.8 2012/08/13 19:43:44 1.6.6.2
+++ src/usr.sbin/npf/npfctl/npfctl.8 2012/11/24 04:34:43 1.6.6.3
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | .\" $NetBSD: npfctl.8,v 1.6.6.2 2012/08/13 19:43:44 riz Exp $ | 1 | .\" $NetBSD: npfctl.8,v 1.6.6.3 2012/11/24 04:34:43 riz Exp $ | |
2 | .\" | 2 | .\" | |
3 | .\" Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 3 | .\" Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
4 | .\" All rights reserved. | 4 | .\" All rights reserved. | |
5 | .\" | 5 | .\" | |
6 | .\" This material is based upon work partially supported by The | 6 | .\" This material is based upon work partially supported by The | |
7 | .\" NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 7 | .\" NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
8 | .\" | 8 | .\" | |
9 | .\" Redistribution and use in source and binary forms, with or without | 9 | .\" Redistribution and use in source and binary forms, with or without | |
10 | .\" modification, are permitted provided that the following conditions | 10 | .\" modification, are permitted provided that the following conditions | |
11 | .\" are met: | 11 | .\" are met: | |
12 | .\" 1. Redistributions of source code must retain the above copyright | 12 | .\" 1. Redistributions of source code must retain the above copyright | |
13 | .\" notice, this list of conditions and the following disclaimer. | 13 | .\" notice, this list of conditions and the following disclaimer. | |
14 | .\" 2. Redistributions in binary form must reproduce the above copyright | 14 | .\" 2. Redistributions in binary form must reproduce the above copyright | |
@@ -17,27 +17,27 @@ | @@ -17,27 +17,27 @@ | |||
17 | .\" | 17 | .\" | |
18 | .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 18 | .\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
19 | .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 19 | .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
20 | .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 20 | .\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
21 | .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 21 | .\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
22 | .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 22 | .\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
23 | .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 23 | .\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
24 | .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 24 | .\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
25 | .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 25 | .\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
26 | .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 26 | .\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
27 | .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 27 | .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
28 | .\" POSSIBILITY OF SUCH DAMAGE. | 28 | .\" POSSIBILITY OF SUCH DAMAGE. | |
29 | .\" | 29 | .\" | |
30 | .Dd August 12, 2012 | 30 | .Dd November 15, 2012 | |
31 | .Dt NPFCTL 8 | 31 | .Dt NPFCTL 8 | |
32 | .Os | 32 | .Os | |
33 | .Sh NAME | 33 | .Sh NAME | |
34 | .Nm npfctl | 34 | .Nm npfctl | |
35 | .Nd control NPF packet filter | 35 | .Nd control NPF packet filter | |
36 | .Sh SYNOPSIS | 36 | .Sh SYNOPSIS | |
37 | .Nm npfctl | 37 | .Nm npfctl | |
38 | .Ar command | 38 | .Ar command | |
39 | .Op Ar arguments | 39 | .Op Ar arguments | |
40 | .\" ----- | 40 | .\" ----- | |
41 | .Sh DESCRIPTION | 41 | .Sh DESCRIPTION | |
42 | The | 42 | The | |
43 | .Nm | 43 | .Nm | |
@@ -69,41 +69,48 @@ will lose NAT policy due to removal. | @@ -69,41 +69,48 @@ will lose NAT policy due to removal. | |||
69 | NAT policy is determined by the translation type and address. | 69 | NAT policy is determined by the translation type and address. | |
70 | Note that change of filter criteria will not expire associated sessions. | 70 | Note that change of filter criteria will not expire associated sessions. | |
71 | The reload operation (i.e., replacing the ruleset, NAT policies and tables) | 71 | The reload operation (i.e., replacing the ruleset, NAT policies and tables) | |
72 | is atomic. | 72 | is atomic. | |
73 | .It Ic flush | 73 | .It Ic flush | |
74 | Flush configuration. | 74 | Flush configuration. | |
75 | That is, remove all rules, tables and expire all sessions. | 75 | That is, remove all rules, tables and expire all sessions. | |
76 | This command does not disable packet inspection. | 76 | This command does not disable packet inspection. | |
77 | .It Ic show | 77 | .It Ic show | |
78 | Show the current state and configuration. | 78 | Show the current state and configuration. | |
79 | Syntax of printed configuration is for the user and may not match the | 79 | Syntax of printed configuration is for the user and may not match the | |
80 | .Xr npf.conf 5 | 80 | .Xr npf.conf 5 | |
81 | syntax. | 81 | syntax. | |
82 | .\".It Ic table Ar tid | 82 | .It Ic table Ar tid Ic add Aq Ar addr/mask | |
83 | .\"List all entries in the currently loaded table specified by | |||
84 | .\".Ar tid . | |||
85 | .It Ic table Ar tid Ic [ add | rem ] Aq Ar addr/mask | |||
86 | In table | 83 | In table | |
87 | .Ar tid , | 84 | .Ar tid , | |
88 | add or remove the IP address and optionally netmask, specified by | 85 | add the IP address and optionally netmask, specified by | |
86 | .Aq Ar addr/mask . | |||
87 | Only tree-type tables support masks. | |||
88 | .It Ic table Ar tid Ic rem Aq Ar addr/mask | |||
89 | In table | |||
90 | .Ar tid , | |||
91 | remove the IP address and optionally netmask, specified by | |||
89 | .Aq Ar addr/mask . | 92 | .Aq Ar addr/mask . | |
90 | Only tree-type tables support masks. | 93 | Only tree-type tables support masks. | |
91 | .It Ic table Ar tid Ic test Aq Ar addr | 94 | .It Ic table Ar tid Ic test Aq Ar addr | |
92 | Query the table | 95 | Query the table | |
93 | .Ar tid | 96 | .Ar tid | |
94 | for a specific IP address, specified by | 97 | for a specific IP address, specified by | |
95 | .Ar addr . | 98 | .Ar addr . | |
96 | If no mask is specified, a single host is assumed. | 99 | If no mask is specified, a single host is assumed. | |
100 | .It Ic table Ar tid Ic list | |||
101 | List all entries in the currently loaded table specified by | |||
102 | .Ar tid . | |||
103 | This operation is expensive and should be used with caution. | |||
97 | .It Ic sess-save | 104 | .It Ic sess-save | |
98 | Save all active sessions. | 105 | Save all active sessions. | |
99 | The data will be stored in the | 106 | The data will be stored in the | |
100 | .Pa /var/db/npf_sessions.db | 107 | .Pa /var/db/npf_sessions.db | |
101 | file. | 108 | file. | |
102 | Administrator may want to stop the packet inspection before the | 109 | Administrator may want to stop the packet inspection before the | |
103 | session saving. | 110 | session saving. | |
104 | .It Ic sess-load | 111 | .It Ic sess-load | |
105 | Load saved sessions from the file. | 112 | Load saved sessions from the file. | |
106 | Note that original configuration should be loaded before the session loading. | 113 | Note that original configuration should be loaded before the session loading. | |
107 | In a case of NAT policy changes, sessions which lose an associated policy | 114 | In a case of NAT policy changes, sessions which lose an associated policy | |
108 | will not be loaded. | 115 | will not be loaded. | |
109 | Any existing sessions during the load operation will be expired. | 116 | Any existing sessions during the load operation will be expired. |
--- src/usr.sbin/npf/npfctl/npfctl.c 2012/11/18 22:38:28 1.10.2.7
+++ src/usr.sbin/npf/npfctl/npfctl.c 2012/11/24 04:34:43 1.10.2.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npfctl.c,v 1.10.2.7 2012/11/18 22:38:28 riz Exp $ */ | 1 | /* $NetBSD: npfctl.c,v 1.10.2.8 2012/11/24 04:34:43 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This material is based upon work partially supported by The | 7 | * This material is based upon work partially supported by The | |
8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | 8 | * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,40 +20,42 @@ | @@ -20,40 +20,42 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __RCSID("$NetBSD: npfctl.c,v 1.10.2.7 2012/11/18 22:38:28 riz Exp $"); | 33 | __RCSID("$NetBSD: npfctl.c,v 1.10.2.8 2012/11/24 04:34:43 riz Exp $"); | |
34 | 34 | |||
35 | #include <sys/ioctl.h> | 35 | #include <sys/ioctl.h> | |
36 | #include <sys/stat.h> | 36 | #include <sys/stat.h> | |
37 | #include <sys/types.h> | 37 | #include <sys/types.h> | |
38 | 38 | |||
39 | #include <stdio.h> | 39 | #include <stdio.h> | |
40 | #include <stdlib.h> | 40 | #include <stdlib.h> | |
41 | #include <string.h> | 41 | #include <string.h> | |
42 | #include <err.h> | 42 | #include <err.h> | |
43 | #include <fcntl.h> | 43 | #include <fcntl.h> | |
44 | #include <unistd.h> | 44 | #include <unistd.h> | |
45 | #include <errno.h> | 45 | #include <errno.h> | |
46 | 46 | |||
47 | #include <util.h> | |||
48 | ||||
47 | #include "npfctl.h" | 49 | #include "npfctl.h" | |
48 | 50 | |||
49 | extern int yylineno, yycolumn; | 51 | extern int yylineno, yycolumn; | |
50 | extern const char * yyfilename; | 52 | extern const char * yyfilename; | |
51 | extern int yyparse(void); | 53 | extern int yyparse(void); | |
52 | extern void yyrestart(FILE *); | 54 | extern void yyrestart(FILE *); | |
53 | 55 | |||
54 | enum { | 56 | enum { | |
55 | NPFCTL_START, | 57 | NPFCTL_START, | |
56 | NPFCTL_STOP, | 58 | NPFCTL_STOP, | |
57 | NPFCTL_RELOAD, | 59 | NPFCTL_RELOAD, | |
58 | NPFCTL_SHOWCONF, | 60 | NPFCTL_SHOWCONF, | |
59 | NPFCTL_FLUSH, | 61 | NPFCTL_FLUSH, | |
@@ -132,30 +134,30 @@ xstrndup(const char *s, size_t len) | @@ -132,30 +134,30 @@ xstrndup(const char *s, size_t len) | |||
132 | 134 | |||
133 | __dead static void | 135 | __dead static void | |
134 | usage(void) | 136 | usage(void) | |
135 | { | 137 | { | |
136 | const char *progname = getprogname(); | 138 | const char *progname = getprogname(); | |
137 | 139 | |||
138 | fprintf(stderr, | 140 | fprintf(stderr, | |
139 | "usage:\t%s [ start | stop | reload | flush | show | stats ]\n", | 141 | "usage:\t%s [ start | stop | reload | flush | show | stats ]\n", | |
140 | progname); | 142 | progname); | |
141 | fprintf(stderr, | 143 | fprintf(stderr, | |
142 | "\t%s ( sess-save | sess-load )\n", | 144 | "\t%s ( sess-save | sess-load )\n", | |
143 | progname); | 145 | progname); | |
144 | fprintf(stderr, | 146 | fprintf(stderr, | |
145 | "\t%s table <tid> [ flush ]\n", | 147 | "\t%s table <tid> { add | rem | test } <address/mask>\n", | |
146 | progname); | 148 | progname); | |
147 | fprintf(stderr, | 149 | fprintf(stderr, | |
148 | "\t%s table <tid> { add | rem | test } <address/mask>\n", | 150 | "\t%s table <tid> { list | flush }\n", | |
149 | progname); | 151 | progname); | |
150 | 152 | |||
151 | exit(EXIT_FAILURE); | 153 | exit(EXIT_FAILURE); | |
152 | } | 154 | } | |
153 | 155 | |||
154 | static void | 156 | static void | |
155 | npfctl_parsecfg(const char *cfg) | 157 | npfctl_parsecfg(const char *cfg) | |
156 | { | 158 | { | |
157 | FILE *fp; | 159 | FILE *fp; | |
158 | 160 | |||
159 | fp = fopen(cfg, "r"); | 161 | fp = fopen(cfg, "r"); | |
160 | if (fp == NULL) { | 162 | if (fp == NULL) { | |
161 | err(EXIT_FAILURE, "open '%s'", cfg); | 163 | err(EXIT_FAILURE, "open '%s'", cfg); | |
@@ -245,82 +247,156 @@ npfctl_print_error(const nl_error_t *ne) | @@ -245,82 +247,156 @@ npfctl_print_error(const nl_error_t *ne) | |||
245 | 247 | |||
246 | if (srcfile) { | 248 | if (srcfile) { | |
247 | warnx("source %s line %d", srcfile, ne->ne_source_line); | 249 | warnx("source %s line %d", srcfile, ne->ne_source_line); | |
248 | } | 250 | } | |
249 | if (nc_err) { | 251 | if (nc_err) { | |
250 | warnx("n-code error (%d): %s at offset 0x%x", | 252 | warnx("n-code error (%d): %s at offset 0x%x", | |
251 | nc_err, ncode_errors[-nc_err], ne->ne_ncode_errat); | 253 | nc_err, ncode_errors[-nc_err], ne->ne_ncode_errat); | |
252 | } | 254 | } | |
253 | if (ne->ne_id) { | 255 | if (ne->ne_id) { | |
254 | warnx("object: %d", ne->ne_id); | 256 | warnx("object: %d", ne->ne_id); | |
255 | } | 257 | } | |
256 | } | 258 | } | |
257 | 259 | |||
260 | char * | |||
261 | npfctl_print_addrmask(int alen, npf_addr_t *addr, npf_netmask_t mask) | |||
262 | { | |||
263 | struct sockaddr_storage ss; | |||
264 | char *buf = zalloc(64); | |||
265 | int len; | |||
266 | ||||
267 | switch (alen) { | |||
268 | case 4: { | |||
269 | struct sockaddr_in *sin = (void *)&ss; | |||
270 | sin->sin_len = sizeof(*sin); | |||
271 | sin->sin_family = AF_INET; | |||
272 | sin->sin_port = 0; | |||
273 | memcpy(&sin->sin_addr, addr, sizeof(sin->sin_addr)); | |||
274 | break; | |||
275 | } | |||
276 | case 16: { | |||
277 | struct sockaddr_in6 *sin6 = (void *)&ss; | |||
278 | sin6->sin6_len = sizeof(*sin6); | |||
279 | sin6->sin6_family = AF_INET6; | |||
280 | sin6->sin6_port = 0; | |||
281 | memcpy(&sin6->sin6_addr, addr, sizeof(sin6->sin6_addr)); | |||
282 | break; | |||
283 | } | |||
284 | default: | |||
285 | assert(false); | |||
286 | } | |||
287 | len = sockaddr_snprintf(buf, 64, "%a", (struct sockaddr *)&ss); | |||
288 | if (mask) { | |||
289 | snprintf(&buf[len], 64 - len, "/%u", mask); | |||
290 | } | |||
291 | return buf; | |||
292 | } | |||
293 | ||||
258 | __dead static void | 294 | __dead static void | |
259 | npfctl_table(int fd, char **argv) | 295 | npfctl_table(int fd, int argc, char **argv) | |
260 | { | 296 | { | |
261 | static const struct tblops_s { | 297 | static const struct tblops_s { | |
262 | const char * cmd; | 298 | const char * cmd; | |
263 | int action; | 299 | int action; | |
264 | } tblops[] = { | 300 | } tblops[] = { | |
265 | { "add", NPF_IOCTL_TBLENT_ADD }, | 301 | { "add", NPF_IOCTL_TBLENT_ADD }, | |
266 | { "rem", NPF_IOCTL_TBLENT_REM }, | 302 | { "rem", NPF_IOCTL_TBLENT_REM }, | |
267 | { "test", 0 }, | 303 | { "test", NPF_IOCTL_TBLENT_LOOKUP }, | |
268 | { NULL, 0 } | 304 | { "list", NPF_IOCTL_TBLENT_LIST }, | |
305 | { NULL, 0 } | |||
269 | }; | 306 | }; | |
270 | npf_ioctl_table_t nct; | 307 | npf_ioctl_table_t nct; | |
271 | fam_addr_mask_t fam; | 308 | fam_addr_mask_t fam; | |
272 | char *cmd = argv[3]; | 309 | size_t buflen = 512; | |
273 | char *arg = argv[3]; | 310 | char *cmd, *arg; | |
274 | int n, alen; | 311 | int n, alen; | |
275 | 312 | |||
313 | /* Default action is list. */ | |||
276 | memset(&nct, 0, sizeof(npf_ioctl_table_t)); | 314 | memset(&nct, 0, sizeof(npf_ioctl_table_t)); | |
277 | nct.nct_tid = atoi(argv[2]); | 315 | nct.nct_tid = atoi(argv[0]); | |
316 | cmd = argv[1]; | |||
278 | 317 | |||
279 | for (n = 0; tblops[n].cmd != NULL; n++) { | 318 | for (n = 0; tblops[n].cmd != NULL; n++) { | |
280 | if (strcmp(cmd, tblops[n].cmd) == 0) { | 319 | if (strcmp(cmd, tblops[n].cmd) != 0) { | |
281 | nct.nct_action = tblops[n].action; | 320 | continue; | |
282 | arg = argv[4]; | 321 | } | |
283 | break; | 322 | nct.nct_action = tblops[n].action; | |
323 | break; | |||
324 | } | |||
325 | if (tblops[n].cmd == NULL) { | |||
326 | errx(EXIT_FAILURE, "invalid command '%s'", cmd); | |||
327 | } | |||
328 | if (nct.nct_action != NPF_IOCTL_TBLENT_LIST) { | |||
329 | if (argc < 3) { | |||
330 | usage(); | |||
284 | } | 331 | } | |
332 | arg = argv[2]; | |||
285 | } | 333 | } | |
286 | if (!npfctl_parse_cidr(arg, &fam, &alen)) { | 334 | again: | |
287 | errx(EXIT_FAILURE, "invalid CIDR '%s'", arg); | 335 | if (nct.nct_action == NPF_IOCTL_TBLENT_LIST) { | |
336 | nct.nct_data.buf.buf = zalloc(buflen); | |||
337 | nct.nct_data.buf.len = buflen; | |||
338 | } else { | |||
339 | if (!npfctl_parse_cidr(arg, &fam, &alen)) { | |||
340 | errx(EXIT_FAILURE, "invalid CIDR '%s'", arg); | |||
341 | } | |||
342 | nct.nct_data.ent.alen = alen; | |||
343 | memcpy(&nct.nct_data.ent.addr, &fam.fam_addr, sizeof(npf_addr_t)); | |||
344 | nct.nct_data.ent.mask = fam.fam_mask; | |||
288 | } | 345 | } | |
289 | memcpy(&nct.nct_addr, &fam.fam_addr, sizeof(npf_addr_t)); | |||
290 | nct.nct_mask = fam.fam_mask; | |||
291 | nct.nct_alen = alen; | |||
292 | 346 | |||
293 | if (ioctl(fd, IOC_NPF_TABLE, &nct) != -1) { | 347 | if (ioctl(fd, IOC_NPF_TABLE, &nct) != -1) { | |
294 | errno = 0; | 348 | errno = 0; | |
295 | } | 349 | } | |
296 | switch (errno) { | 350 | switch (errno) { | |
297 | case EEXIST: | 351 | case 0: | |
298 | warnx("entry already exists or is conflicting"); | |||
299 | break; | 352 | break; | |
353 | case EEXIST: | |||
354 | errx(EXIT_FAILURE, "entry already exists or is conflicting"); | |||
300 | case ENOENT: | 355 | case ENOENT: | |
301 | warnx("no matching entry was not found"); | 356 | errx(EXIT_FAILURE, "no matching entry was not found"); | |
302 | break; | |||
303 | case EINVAL: | 357 | case EINVAL: | |
304 | warnx("invalid address, mask or table ID"); | 358 | errx(EXIT_FAILURE, "invalid address, mask or table ID"); | |
305 | break; | 359 | case ENOMEM: | |
306 | case 0: | 360 | if (nct.nct_action == NPF_IOCTL_TBLENT_LIST) { | |
307 | printf("%s: %s\n", getprogname(), nct.nct_action == 0 ? | 361 | /* XXX */ | |
308 | "matching entry found" : "success"); | 362 | free(nct.nct_data.buf.buf); | |
309 | break; | 363 | buflen <<= 1; | |
364 | goto again; | |||
365 | } | |||
366 | /* FALLTHROUGH */ | |||
310 | default: | 367 | default: | |
311 | warn("error"); | 368 | err(EXIT_FAILURE, "ioctl"); | |
369 | } | |||
370 | ||||
371 | if (nct.nct_action == NPF_IOCTL_TBLENT_LIST) { | |||
372 | npf_ioctl_ent_t *ent = nct.nct_data.buf.buf; | |||
373 | char *buf; | |||
374 | ||||
375 | while (nct.nct_data.buf.len--) { | |||
376 | if (!ent->alen) | |||
377 | break; | |||
378 | buf = npfctl_print_addrmask(ent->alen, | |||
379 | &ent->addr, ent->mask); | |||
380 | puts(buf); | |||
381 | ent++; | |||
382 | } | |||
383 | free(nct.nct_data.buf.buf); | |||
384 | } else { | |||
385 | printf("%s: %s\n", getprogname(), | |||
386 | nct.nct_action == NPF_IOCTL_TBLENT_LOOKUP ? | |||
387 | "matching entry found" : "success"); | |||
312 | } | 388 | } | |
313 | exit(errno ? EXIT_FAILURE : EXIT_SUCCESS); | 389 | exit(EXIT_SUCCESS); | |
314 | } | 390 | } | |
315 | 391 | |||
316 | static void | 392 | static void | |
317 | npfctl(int action, int argc, char **argv) | 393 | npfctl(int action, int argc, char **argv) | |
318 | { | 394 | { | |
319 | int fd, ret, ver, boolval; | 395 | int fd, ret, ver, boolval; | |
320 | 396 | |||
321 | fd = open(NPF_DEV_PATH, O_RDONLY); | 397 | fd = open(NPF_DEV_PATH, O_RDONLY); | |
322 | if (fd == -1) { | 398 | if (fd == -1) { | |
323 | err(EXIT_FAILURE, "cannot open '%s'", NPF_DEV_PATH); | 399 | err(EXIT_FAILURE, "cannot open '%s'", NPF_DEV_PATH); | |
324 | } | 400 | } | |
325 | ret = ioctl(fd, IOC_NPF_VERSION, &ver); | 401 | ret = ioctl(fd, IOC_NPF_VERSION, &ver); | |
326 | if (ret == -1) { | 402 | if (ret == -1) { | |
@@ -345,30 +421,31 @@ npfctl(int action, int argc, char **argv | @@ -345,30 +421,31 @@ npfctl(int action, int argc, char **argv | |||
345 | npfctl_parsecfg(argc < 3 ? NPF_CONF_PATH : argv[2]); | 421 | npfctl_parsecfg(argc < 3 ? NPF_CONF_PATH : argv[2]); | |
346 | ret = npfctl_config_send(fd, NULL); | 422 | ret = npfctl_config_send(fd, NULL); | |
347 | if (ret) { | 423 | if (ret) { | |
348 | errx(EXIT_FAILURE, "ioctl: %s", strerror(ret)); | 424 | errx(EXIT_FAILURE, "ioctl: %s", strerror(ret)); | |
349 | } | 425 | } | |
350 | break; | 426 | break; | |
351 | case NPFCTL_SHOWCONF: | 427 | case NPFCTL_SHOWCONF: | |
352 | ret = npfctl_config_show(fd); | 428 | ret = npfctl_config_show(fd); | |
353 | break; | 429 | break; | |
354 | case NPFCTL_FLUSH: | 430 | case NPFCTL_FLUSH: | |
355 | ret = npf_config_flush(fd); | 431 | ret = npf_config_flush(fd); | |
356 | break; | 432 | break; | |
357 | case NPFCTL_TABLE: | 433 | case NPFCTL_TABLE: | |
358 | if (argc < 5) { | 434 | if ((argc -= 2) < 2) { | |
359 | usage(); | 435 | usage(); | |
360 | } | 436 | } | |
361 | npfctl_table(fd, argv); | 437 | argv += 2; | |
438 | npfctl_table(fd, argc, argv); | |||
362 | break; | 439 | break; | |
363 | case NPFCTL_STATS: | 440 | case NPFCTL_STATS: | |
364 | ret = npfctl_print_stats(fd); | 441 | ret = npfctl_print_stats(fd); | |
365 | break; | 442 | break; | |
366 | case NPFCTL_SESSIONS_SAVE: | 443 | case NPFCTL_SESSIONS_SAVE: | |
367 | if (npf_sessions_recv(fd, NPF_SESSDB_PATH) != 0) { | 444 | if (npf_sessions_recv(fd, NPF_SESSDB_PATH) != 0) { | |
368 | errx(EXIT_FAILURE, "could not save sessions to '%s'", | 445 | errx(EXIT_FAILURE, "could not save sessions to '%s'", | |
369 | NPF_SESSDB_PATH); | 446 | NPF_SESSDB_PATH); | |
370 | } | 447 | } | |
371 | break; | 448 | break; | |
372 | case NPFCTL_SESSIONS_LOAD: | 449 | case NPFCTL_SESSIONS_LOAD: | |
373 | if (npf_sessions_send(fd, NPF_SESSDB_PATH) != 0) { | 450 | if (npf_sessions_send(fd, NPF_SESSDB_PATH) != 0) { | |
374 | errx(EXIT_FAILURE, "no sessions loaded from '%s'", | 451 | errx(EXIT_FAILURE, "no sessions loaded from '%s'", |
--- src/usr.sbin/npf/npfctl/npfctl.h 2012/11/18 22:38:27 1.11.2.7
+++ src/usr.sbin/npf/npfctl/npfctl.h 2012/11/24 04:34:43 1.11.2.8
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npfctl.h,v 1.11.2.7 2012/11/18 22:38:27 riz Exp $ */ | 1 | /* $NetBSD: npfctl.h,v 1.11.2.8 2012/11/24 04:34:43 riz Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -86,26 +86,27 @@ typedef struct proc_call { | @@ -86,26 +86,27 @@ typedef struct proc_call { | |||
86 | 86 | |||
87 | typedef struct proc_param { | 87 | typedef struct proc_param { | |
88 | const char * pp_param; | 88 | const char * pp_param; | |
89 | const char * pp_value; | 89 | const char * pp_value; | |
90 | } proc_param_t; | 90 | } proc_param_t; | |
91 | 91 | |||
92 | void yyerror(const char *, ...) __printflike(1, 2) __dead; | 92 | void yyerror(const char *, ...) __printflike(1, 2) __dead; | |
93 | void * zalloc(size_t); | 93 | void * zalloc(size_t); | |
94 | void * xrealloc(void *, size_t); | 94 | void * xrealloc(void *, size_t); | |
95 | char * xstrdup(const char *); | 95 | char * xstrdup(const char *); | |
96 | char * xstrndup(const char *, size_t); | 96 | char * xstrndup(const char *, size_t); | |
97 | 97 | |||
98 | void npfctl_print_error(const nl_error_t *); | 98 | void npfctl_print_error(const nl_error_t *); | |
99 | char * npfctl_print_addrmask(int, npf_addr_t *, npf_netmask_t); | |||
99 | bool npfctl_table_exists_p(const char *); | 100 | bool npfctl_table_exists_p(const char *); | |
100 | int npfctl_protono(const char *); | 101 | int npfctl_protono(const char *); | |
101 | in_port_t npfctl_portno(const char *); | 102 | in_port_t npfctl_portno(const char *); | |
102 | uint8_t npfctl_icmpcode(int, uint8_t, const char *); | 103 | uint8_t npfctl_icmpcode(int, uint8_t, const char *); | |
103 | uint8_t npfctl_icmptype(int, const char *); | 104 | uint8_t npfctl_icmptype(int, const char *); | |
104 | unsigned long npfctl_find_ifindex(const char *); | 105 | unsigned long npfctl_find_ifindex(const char *); | |
105 | npfvar_t * npfctl_parse_tcpflag(const char *); | 106 | npfvar_t * npfctl_parse_tcpflag(const char *); | |
106 | npfvar_t * npfctl_parse_table_id(const char *); | 107 | npfvar_t * npfctl_parse_table_id(const char *); | |
107 | npfvar_t * npfctl_parse_icmp(int, int, int); | 108 | npfvar_t * npfctl_parse_icmp(int, int, int); | |
108 | npfvar_t * npfctl_parse_iface(const char *); | 109 | npfvar_t * npfctl_parse_iface(const char *); | |
109 | npfvar_t * npfctl_parse_port_range(in_port_t, in_port_t); | 110 | npfvar_t * npfctl_parse_port_range(in_port_t, in_port_t); | |
110 | npfvar_t * npfctl_parse_port_range_variable(const char *); | 111 | npfvar_t * npfctl_parse_port_range_variable(const char *); | |
111 | npfvar_t * npfctl_parse_fam_addr_mask(const char *, const char *, | 112 | npfvar_t * npfctl_parse_fam_addr_mask(const char *, const char *, |
--- src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c 2012/11/18 21:48:56 1.2.2.6
+++ src/usr.sbin/npf/npftest/libnpftest/npf_table_test.c 2012/11/24 04:34:44 1.2.2.7
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: npf_table_test.c,v 1.2.2.6 2012/11/18 21:48:56 riz Exp $ */ | 1 | /* $NetBSD: npf_table_test.c,v 1.2.2.7 2012/11/24 04:34:44 riz Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * NPF tableset test. | 4 | * NPF tableset test. | |
5 | * | 5 | * | |
6 | * Public Domain. | 6 | * Public Domain. | |
7 | */ | 7 | */ | |
8 | 8 | |||
9 | #include <sys/types.h> | 9 | #include <sys/types.h> | |
10 | 10 | |||
11 | #include "npf_impl.h" | 11 | #include "npf_impl.h" | |
12 | #include "npf_test.h" | 12 | #include "npf_test.h" | |
13 | 13 | |||
14 | static const char *ip_list[] = { | 14 | static const char *ip_list[] = { | |
@@ -34,39 +34,63 @@ static const uint16_t ip6_list[][8] = { | @@ -34,39 +34,63 @@ static const uint16_t ip6_list[][8] = { | |||
34 | { | 34 | { | |
35 | htons(0xfe80), 0x0, 0x0, 0x0, | 35 | htons(0xfe80), 0x0, 0x0, 0x0, | |
36 | 0x0, 0x0, 0x0, 0x0 | 36 | 0x0, 0x0, 0x0, 0x0 | |
37 | }, | 37 | }, | |
38 | { | 38 | { | |
39 | htons(0xfe80), 0x0, 0x0, 0x0, | 39 | htons(0xfe80), 0x0, 0x0, 0x0, | |
40 | htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1230) | 40 | htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1230) | |
41 | } | 41 | } | |
42 | }; | 42 | }; | |
43 | 43 | |||
44 | #define HASH_TID 1 | 44 | #define HASH_TID 1 | |
45 | #define TREE_TID 2 | 45 | #define TREE_TID 2 | |
46 | 46 | |||
47 | static bool | |||
48 | npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr) | |||
49 | { | |||
50 | const int alen = sizeof(struct in_addr); | |||
51 | const int nm = NPF_NO_NETMASK; | |||
52 | bool fail = false; | |||
53 | ||||
54 | /* Fill both tables with IP addresses. */ | |||
55 | for (unsigned i = 0; i < __arraycount(ip_list); i++) { | |||
56 | int error; | |||
57 | ||||
58 | addr->s6_addr32[0] = inet_addr(ip_list[i]); | |||
59 | ||||
60 | error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); | |||
61 | fail |= !(error == 0); | |||
62 | error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); | |||
63 | fail |= !(error != 0); | |||
64 | ||||
65 | error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); | |||
66 | fail |= !(error == 0); | |||
67 | error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); | |||
68 | fail |= !(error != 0); | |||
69 | } | |||
70 | return fail; | |||
71 | } | |||
72 | ||||
47 | bool | 73 | bool | |
48 | npf_table_test(bool verbose) | 74 | npf_table_test(bool verbose) | |
49 | { | 75 | { | |
50 | npf_addr_t addr_storage, *addr = &addr_storage; | 76 | npf_addr_t addr_storage, *addr = &addr_storage; | |
51 | const int nm = NPF_NO_NETMASK; | 77 | const int nm = NPF_NO_NETMASK; | |
52 | npf_tableset_t *tblset; | 78 | npf_tableset_t *tblset; | |
53 | npf_table_t *t1, *t2; | 79 | npf_table_t *t1, *t2; | |
54 | int error, alen; | 80 | int error, alen; | |
55 | bool fail = false; | 81 | bool fail = false; | |
56 | u_int i; | 82 | u_int i; | |
57 | 83 | |||
58 | npf_tableset_sysinit(); | |||
59 | ||||
60 | tblset = npf_tableset_create(); | 84 | tblset = npf_tableset_create(); | |
61 | fail |= !(tblset != NULL); | 85 | fail |= !(tblset != NULL); | |
62 | 86 | |||
63 | /* Table ID 1, using hash table with 256 lists. */ | 87 | /* Table ID 1, using hash table with 256 lists. */ | |
64 | t1 = npf_table_create(HASH_TID, NPF_TABLE_HASH, 256); | 88 | t1 = npf_table_create(HASH_TID, NPF_TABLE_HASH, 256); | |
65 | fail |= !(t1 != NULL); | 89 | fail |= !(t1 != NULL); | |
66 | error = npf_tableset_insert(tblset, t1); | 90 | error = npf_tableset_insert(tblset, t1); | |
67 | fail |= !(error == 0); | 91 | fail |= !(error == 0); | |
68 | 92 | |||
69 | /* Check for double-insert. */ | 93 | /* Check for double-insert. */ | |
70 | error = npf_tableset_insert(tblset, t1); | 94 | error = npf_tableset_insert(tblset, t1); | |
71 | fail |= !(error != 0); | 95 | fail |= !(error != 0); | |
72 | 96 | |||
@@ -77,59 +101,38 @@ npf_table_test(bool verbose) | @@ -77,59 +101,38 @@ npf_table_test(bool verbose) | |||
77 | fail |= !(error == 0); | 101 | fail |= !(error == 0); | |
78 | 102 | |||
79 | /* Attempt to match non-existing entries - should fail. */ | 103 | /* Attempt to match non-existing entries - should fail. */ | |
80 | addr->s6_addr32[0] = inet_addr(ip_list[0]); | 104 | addr->s6_addr32[0] = inet_addr(ip_list[0]); | |
81 | alen = sizeof(struct in_addr); | 105 | alen = sizeof(struct in_addr); | |
82 | 106 | |||
83 | error = npf_table_lookup(tblset, HASH_TID, alen, addr); | 107 | error = npf_table_lookup(tblset, HASH_TID, alen, addr); | |
84 | fail |= !(error != 0); | 108 | fail |= !(error != 0); | |
85 | 109 | |||
86 | error = npf_table_lookup(tblset, TREE_TID, alen, addr); | 110 | error = npf_table_lookup(tblset, TREE_TID, alen, addr); | |
87 | fail |= !(error != 0); | 111 | fail |= !(error != 0); | |
88 | 112 | |||
89 | /* Fill both tables with IP addresses. */ | 113 | /* Fill both tables with IP addresses. */ | |
90 | for (i = 0; i < __arraycount(ip_list); i++) { | 114 | fail |= npf_table_test_fill4(tblset, addr); | |
91 | addr->s6_addr32[0] = inet_addr(ip_list[i]); | |||
92 | ||||
93 | error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); | |||
94 | fail |= !(error == 0); | |||
95 | error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); | |||
96 | fail |= !(error != 0); | |||
97 | ||||
98 | error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); | |||
99 | fail |= !(error == 0); | |||
100 | error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); | |||
101 | fail |= !(error != 0); | |||
102 | } | |||
103 | 115 | |||
104 | /* Attempt to add duplicates - should fail. */ | 116 | /* Attempt to add duplicates - should fail. */ | |
105 | addr->s6_addr32[0] = inet_addr(ip_list[0]); | 117 | addr->s6_addr32[0] = inet_addr(ip_list[0]); | |
106 | alen = sizeof(struct in_addr); | 118 | alen = sizeof(struct in_addr); | |
107 | 119 | |||
108 | error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); | 120 | error = npf_table_insert(tblset, HASH_TID, alen, addr, nm); | |
109 | fail |= !(error != 0); | 121 | fail |= !(error != 0); | |
110 | 122 | |||
111 | error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); | 123 | error = npf_table_insert(tblset, TREE_TID, alen, addr, nm); | |
112 | fail |= !(error != 0); | 124 | fail |= !(error != 0); | |
113 | 125 | |||
114 | /* Reference checks. */ | |||
115 | t1 = npf_table_get(tblset, HASH_TID); | |||
116 | fail |= !(t1 != NULL); | |||
117 | npf_table_put(t1); | |||
118 | ||||
119 | t2 = npf_table_get(tblset, TREE_TID); | |||
120 | fail |= !(t2 != NULL); | |||
121 | npf_table_put(t2); | |||
122 | ||||
123 | /* Match (validate) each IP entry. */ | 126 | /* Match (validate) each IP entry. */ | |
124 | for (i = 0; i < __arraycount(ip_list); i++) { | 127 | for (i = 0; i < __arraycount(ip_list); i++) { | |
125 | addr->s6_addr32[0] = inet_addr(ip_list[i]); | 128 | addr->s6_addr32[0] = inet_addr(ip_list[i]); | |
126 | 129 | |||
127 | error = npf_table_lookup(tblset, HASH_TID, alen, addr); | 130 | error = npf_table_lookup(tblset, HASH_TID, alen, addr); | |
128 | fail |= !(error == 0); | 131 | fail |= !(error == 0); | |
129 | 132 | |||
130 | error = npf_table_lookup(tblset, TREE_TID, alen, addr); | 133 | error = npf_table_lookup(tblset, TREE_TID, alen, addr); | |
131 | fail |= !(error == 0); | 134 | fail |= !(error == 0); | |
132 | } | 135 | } | |
133 | 136 | |||
134 | /* IPv6 addresses. */ | 137 | /* IPv6 addresses. */ | |
135 | memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); | 138 | memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); | |
@@ -196,17 +199,16 @@ npf_table_test(bool verbose) | @@ -196,17 +199,16 @@ npf_table_test(bool verbose) | |||
196 | 199 | |||
197 | /* Remove all IPv4 entries. */ | 200 | /* Remove all IPv4 entries. */ | |
198 | for (i = 0; i < __arraycount(ip_list); i++) { | 201 | for (i = 0; i < __arraycount(ip_list); i++) { | |
199 | addr->s6_addr32[0] = inet_addr(ip_list[i]); | 202 | addr->s6_addr32[0] = inet_addr(ip_list[i]); | |
200 | 203 | |||
201 | error = npf_table_remove(tblset, HASH_TID, alen, addr, nm); | 204 | error = npf_table_remove(tblset, HASH_TID, alen, addr, nm); | |
202 | fail |= !(error == 0); | 205 | fail |= !(error == 0); | |
203 | 206 | |||
204 | error = npf_table_remove(tblset, TREE_TID, alen, addr, nm); | 207 | error = npf_table_remove(tblset, TREE_TID, alen, addr, nm); | |
205 | fail |= !(error == 0); | 208 | fail |= !(error == 0); | |
206 | } | 209 | } | |
207 | 210 | |||
208 | npf_tableset_destroy(tblset); | 211 | npf_tableset_destroy(tblset); | |
209 | npf_tableset_sysfini(); | |||
210 | 212 | |||
211 | return !fail; | 213 | return !fail; | |
212 | } | 214 | } |