Module Name: src Committed By: rmind Date: Mon Feb 6 23:30:15 UTC 2012
Modified Files: src/sys/modules/npf: Makefile src/sys/net/npf: files.npf npf.h npf_handler.c npf_impl.h npf_ruleset.c Added Files: src/sys/net/npf: npf_rproc.c Log Message: - Split NPF rule procedure code into a separate module (no functional changes). - Simplify some code, add more comments, some asserts. - G/C unused rule hook code. To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/modules/npf/Makefile cvs rdiff -u -r1.5 -r1.6 src/sys/net/npf/files.npf cvs rdiff -u -r1.13 -r1.14 src/sys/net/npf/npf.h cvs rdiff -u -r1.12 -r1.13 src/sys/net/npf/npf_handler.c cvs rdiff -u -r1.9 -r1.10 src/sys/net/npf/npf_impl.h \ src/sys/net/npf/npf_ruleset.c cvs rdiff -u -r0 -r1.1 src/sys/net/npf/npf_rproc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/modules/npf/Makefile diff -u src/sys/modules/npf/Makefile:1.8 src/sys/modules/npf/Makefile:1.9 --- src/sys/modules/npf/Makefile:1.8 Tue Nov 29 20:05:30 2011 +++ src/sys/modules/npf/Makefile Mon Feb 6 23:30:14 2012 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.8 2011/11/29 20:05:30 rmind Exp $ +# $NetBSD: Makefile,v 1.9 2012/02/06 23:30:14 rmind Exp $ .include "../Makefile.inc" @@ -8,8 +8,8 @@ KMOD= npf SRCS= npf.c npf_alg.c npf_ctl.c npf_handler.c SRCS+= npf_inet.c npf_instr.c npf_log.c npf_mbuf.c npf_nat.c -SRCS+= npf_processor.c npf_ruleset.c npf_sendpkt.c npf_session.c -SRCS+= npf_state.c npf_state_tcp.c npf_tableset.c +SRCS+= npf_processor.c npf_ruleset.c npf_rproc.c npf_sendpkt.c +SRCS+= npf_session.c npf_state.c npf_state_tcp.c npf_tableset.c CPPFLAGS+= -DINET6 Index: src/sys/net/npf/files.npf diff -u src/sys/net/npf/files.npf:1.5 src/sys/net/npf/files.npf:1.6 --- src/sys/net/npf/files.npf:1.5 Tue Nov 29 20:05:30 2011 +++ src/sys/net/npf/files.npf Mon Feb 6 23:30:14 2012 @@ -1,4 +1,4 @@ -# $NetBSD: files.npf,v 1.5 2011/11/29 20:05:30 rmind Exp $ +# $NetBSD: files.npf,v 1.6 2012/02/06 23:30:14 rmind Exp $ # # Public Domain. # @@ -17,6 +17,7 @@ file net/npf/npf_instr.c npf file net/npf/npf_mbuf.c npf file net/npf/npf_processor.c npf file net/npf/npf_ruleset.c npf +file net/npf/npf_rproc.c npf file net/npf/npf_tableset.c npf file net/npf/npf_inet.c npf file net/npf/npf_session.c npf Index: src/sys/net/npf/npf.h diff -u src/sys/net/npf/npf.h:1.13 src/sys/net/npf/npf.h:1.14 --- src/sys/net/npf/npf.h:1.13 Sun Feb 5 00:37:13 2012 +++ src/sys/net/npf/npf.h Mon Feb 6 23:30:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf.h,v 1.13 2012/02/05 00:37:13 rmind Exp $ */ +/* $NetBSD: npf.h,v 1.14 2012/02/06 23:30:14 rmind Exp $ */ /*- * Copyright (c) 2009-2011 The NetBSD Foundation, Inc. @@ -68,10 +68,7 @@ typedef uint8_t npf_netmask_t; typedef void nbuf_t; struct npf_rproc; -struct npf_hook; - typedef struct npf_rproc npf_rproc_t; -typedef struct npf_hook npf_hook_t; /* * Packet information cache. @@ -215,12 +212,6 @@ int nbuf_store_datum(nbuf_t *, void *, int nbuf_add_tag(nbuf_t *, uint32_t, uint32_t); int nbuf_find_tag(nbuf_t *, uint32_t, void **); -#if 0 -npf_hook_t * npf_hook_register(npf_rule_t *, - void (*)(npf_cache_t *, nbuf_t *, void *), void *); -void npf_hook_unregister(npf_rule_t *, npf_hook_t *); -#endif - #endif /* _KERNEL */ /* Rule attributes. */ Index: src/sys/net/npf/npf_handler.c diff -u src/sys/net/npf/npf_handler.c:1.12 src/sys/net/npf/npf_handler.c:1.13 --- src/sys/net/npf/npf_handler.c:1.12 Sun Jan 15 00:49:48 2012 +++ src/sys/net/npf/npf_handler.c Mon Feb 6 23:30:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_handler.c,v 1.12 2012/01/15 00:49:48 rmind Exp $ */ +/* $NetBSD: npf_handler.c,v 1.13 2012/02/06 23:30:14 rmind Exp $ */ /*- * Copyright (c) 2009-2010 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.12 2012/01/15 00:49:48 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_handler.c,v 1.13 2012/02/06 23:30:14 rmind Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -166,9 +166,12 @@ npf_packet_handler(void *arg, struct mbu goto block; } - /* Get rule procedure for assocation and/or execution. */ + /* + * Get the rule procedure (acquires a reference) for assocation + * with a session (if any) and execution. + */ KASSERT(rp == NULL); - rp = npf_rproc_return(rl); + rp = npf_rule_getrproc(rl); /* Apply the rule, release the lock. */ error = npf_rule_apply(&npc, nbuf, rl, &retfl); @@ -185,6 +188,10 @@ npf_packet_handler(void *arg, struct mbu error = ENOMEM; goto out; } + /* + * Note: the reference to the rule procedure is transfered to + * the session. It will be released on session destruction. + */ npf_session_setpass(se, rp); } pass: @@ -195,44 +202,47 @@ pass: error = npf_do_nat(&npc, se, nbuf, ifp, di); block: /* - * Perform rule procedure, if any. + * Execute rule procedure, if any. */ if (rp) { npf_rproc_run(&npc, nbuf, rp, error); } out: - /* Release the reference on session, or rule procedure. */ + /* + * Release the reference on a session. Release the reference on a + * rule procedure only if there was no association. + */ if (se) { npf_session_release(se); } else if (rp) { - npf_rproc_release(rp); /* XXXkmem */ + npf_rproc_release(rp); } - /* - * If error is set - drop the packet. - * Normally, ENETUNREACH is used for "block". - */ - if (error) { - /* - * Depending on flags and protocol, return TCP reset (RST) - * or ICMP destination unreachable - */ - if (retfl) { - npf_return_block(&npc, nbuf, retfl); - } - if (error != ENETUNREACH) { - NPF_PRINTF(("NPF: error in handler '%d'\n", error)); - npf_stats_inc(NPF_STAT_ERROR); - } - m_freem(*mp); - *mp = NULL; - } else { + /* Pass the packet, if no error. */ + if (!error) { /* * XXX: Disable for now, it will be set accordingly later, * for optimisations (to reduce inspection). */ (*mp)->m_flags &= ~M_CANFASTFWD; + return 0; } + + /* + * Block the packet. ENETUNREACH is used to indicate blocking. + * Depending on the flags and protocol, return TCP reset (RST) or + * ICMP destination unreachable. + */ + if (retfl) { + npf_return_block(&npc, nbuf, retfl); + } + if (error != ENETUNREACH) { + NPF_PRINTF(("NPF: error in handler '%d'\n", error)); + npf_stats_inc(NPF_STAT_ERROR); + } + m_freem(*mp); + *mp = NULL; + return error; } Index: src/sys/net/npf/npf_impl.h diff -u src/sys/net/npf/npf_impl.h:1.9 src/sys/net/npf/npf_impl.h:1.10 --- src/sys/net/npf/npf_impl.h:1.9 Tue Nov 29 20:05:30 2011 +++ src/sys/net/npf/npf_impl.h Mon Feb 6 23:30:14 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: npf_impl.h,v 1.9 2011/11/29 20:05:30 rmind Exp $ */ +/* $NetBSD: npf_impl.h,v 1.10 2012/02/06 23:30:14 rmind Exp $ */ /*- * Copyright (c) 2009-2011 The NetBSD Foundation, Inc. @@ -226,9 +226,10 @@ void npf_rule_free(npf_rule_t *); npf_ruleset_t * npf_rule_subset(npf_rule_t *); npf_natpolicy_t *npf_rule_getnat(const npf_rule_t *); void npf_rule_setnat(npf_rule_t *, npf_natpolicy_t *); +npf_rproc_t * npf_rule_getrproc(npf_rule_t *); npf_rproc_t * npf_rproc_create(prop_dictionary_t); -npf_rproc_t * npf_rproc_return(npf_rule_t *); +void npf_rproc_acquire(npf_rproc_t *); void npf_rproc_release(npf_rproc_t *); void npf_rproc_run(npf_cache_t *, nbuf_t *, npf_rproc_t *, int); Index: src/sys/net/npf/npf_ruleset.c diff -u src/sys/net/npf/npf_ruleset.c:1.9 src/sys/net/npf/npf_ruleset.c:1.10 --- src/sys/net/npf/npf_ruleset.c:1.9 Sun Jan 15 00:49:49 2012 +++ src/sys/net/npf/npf_ruleset.c Mon Feb 6 23:30:14 2012 @@ -1,7 +1,7 @@ -/* $NetBSD: npf_ruleset.c,v 1.9 2012/01/15 00:49:49 rmind Exp $ */ +/* $NetBSD: npf_ruleset.c,v 1.10 2012/02/06 23:30:14 rmind Exp $ */ /*- - * Copyright (c) 2009-2011 The NetBSD Foundation, Inc. + * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. * All rights reserved. * * This material is based upon work partially supported by The @@ -34,14 +34,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.9 2012/01/15 00:49:49 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.10 2012/02/06 23:30:14 rmind Exp $"); #include <sys/param.h> #include <sys/kernel.h> -#include <sys/atomic.h> #include <sys/kmem.h> -#include <sys/pool.h> #include <sys/queue.h> #include <sys/types.h> @@ -57,31 +55,8 @@ struct npf_ruleset { npf_rule_t * rs_default; }; -/* Rule hook entry. */ -struct npf_hook { - void (*hk_fn)(npf_cache_t *, nbuf_t *, void *); - void * hk_arg; - LIST_ENTRY(npf_hook) hk_entry; -}; - #define NPF_RNAME_LEN 16 -/* Rule procedure structure. */ -struct npf_rproc { - /* Name. */ - char rp_name[NPF_RNAME_LEN]; - /* Reference count. */ - u_int rp_refcnt; - uint32_t rp_flags; - /* Normalization options. */ - bool rp_rnd_ipid; - bool rp_no_df; - u_int rp_minttl; - u_int rp_maxmss; - /* Logging interface. */ - u_int rp_log_ifid; -}; - /* Rule structure. */ struct npf_rule { /* Rule name (optional) and list entry. */ @@ -101,9 +76,6 @@ struct npf_rule { u_int r_ifid; /* Rule procedure data. */ npf_rproc_t * r_rproc; - /* List of hooks to process on match. */ - kmutex_t r_hooks_lock; - LIST_HEAD(, npf_hook) r_hooks; }; npf_ruleset_t * @@ -222,79 +194,6 @@ npf_ruleset_natreload(npf_ruleset_t *nrl } } -npf_rproc_t * -npf_rproc_create(prop_dictionary_t rpdict) -{ - npf_rproc_t *rp; - const char *rname; - - rp = kmem_zalloc(sizeof(npf_rproc_t), KM_SLEEP); - rp->rp_refcnt = 1; - - /* Name and flags. */ - prop_dictionary_get_cstring_nocopy(rpdict, "name", &rname); - strlcpy(rp->rp_name, rname, NPF_RNAME_LEN); - prop_dictionary_get_uint32(rpdict, "flags", &rp->rp_flags); - - /* Logging interface ID (integer). */ - prop_dictionary_get_uint32(rpdict, "log-interface", &rp->rp_log_ifid); - - /* IP ID randomization and IP_DF flag cleansing. */ - prop_dictionary_get_bool(rpdict, "randomize-id", &rp->rp_rnd_ipid); - prop_dictionary_get_bool(rpdict, "no-df", &rp->rp_no_df); - - /* Minimum IP TTL and maximum TCP MSS. */ - prop_dictionary_get_uint32(rpdict, "min-ttl", &rp->rp_minttl); - prop_dictionary_get_uint32(rpdict, "max-mss", &rp->rp_maxmss); - - return rp; -} - -npf_rproc_t * -npf_rproc_return(npf_rule_t *rl) -{ - npf_rproc_t *rp = rl->r_rproc; - - KASSERT(npf_core_locked()); - if (rp) { - atomic_inc_uint(&rp->rp_refcnt); - } - return rp; -} - -void -npf_rproc_release(npf_rproc_t *rp) -{ - - /* Destroy on last reference. */ - if (atomic_dec_uint_nv(&rp->rp_refcnt) != 0) { - return; - } - kmem_free(rp, sizeof(npf_rproc_t)); -} - -void -npf_rproc_run(npf_cache_t *npc, nbuf_t *nbuf, npf_rproc_t *rp, int error) -{ - const uint32_t flags = rp->rp_flags; - - KASSERT(rp->rp_refcnt > 0); - - /* Normalize the packet, if required. */ - if ((flags & NPF_RPROC_NORMALIZE) != 0 && !error) { - (void)npf_normalize(npc, nbuf, - rp->rp_rnd_ipid, rp->rp_no_df, - rp->rp_minttl, rp->rp_maxmss); - npf_stats_inc(NPF_STAT_RPROC_NORM); - } - - /* Log packet, if required. */ - if ((flags & NPF_RPROC_LOG) != 0) { - npf_log_packet(npc, nbuf, rp->rp_log_ifid); - npf_stats_inc(NPF_STAT_RPROC_LOG); - } -} - /* * npf_rule_alloc: allocate a rule and copy n-code from user-space. * @@ -311,8 +210,6 @@ npf_rule_alloc(prop_dictionary_t rldict, /* Allocate a rule structure. */ rl = kmem_alloc(sizeof(npf_rule_t), KM_SLEEP); TAILQ_INIT(&rl->r_subset.rs_queue); - mutex_init(&rl->r_hooks_lock, MUTEX_DEFAULT, IPL_SOFTNET); - LIST_INIT(&rl->r_hooks); rl->r_natp = NULL; /* N-code. */ @@ -334,7 +231,7 @@ npf_rule_alloc(prop_dictionary_t rldict, /* Rule procedure. */ if (rp) { - atomic_inc_uint(&rp->rp_refcnt); + npf_rproc_acquire(rp); } rl->r_rproc = rp; @@ -362,12 +259,12 @@ npf_rule_free(npf_rule_t *rl) /* Free n-code. */ npf_ncode_free(rl->r_ncode, rl->r_nc_size); } - mutex_destroy(&rl->r_hooks_lock); kmem_free(rl, sizeof(npf_rule_t)); } /* * npf_rule_subset: return sub-ruleset, if any. + * npf_rule_getrproc: acquire a reference and return rule procedure, if any. * npf_rule_getnat: get NAT policy assigned to the rule. */ @@ -377,6 +274,18 @@ npf_rule_subset(npf_rule_t *rl) return &rl->r_subset; } +npf_rproc_t * +npf_rule_getrproc(npf_rule_t *rl) +{ + npf_rproc_t *rp = rl->r_rproc; + + KASSERT(npf_core_locked()); + if (rp) { + npf_rproc_acquire(rp); + } + return rp; +} + npf_natpolicy_t * npf_rule_getnat(const npf_rule_t *rl) { @@ -395,43 +304,6 @@ npf_rule_setnat(npf_rule_t *rl, npf_natp rl->r_natp = np; } -#if 0 -/* - * npf_hook_register: register action hook in the rule. - */ -npf_hook_t * -npf_hook_register(npf_rule_t *rl, - void (*fn)(npf_cache_t *, nbuf_t *, void *), void *arg) -{ - npf_hook_t *hk; - - hk = kmem_alloc(sizeof(npf_hook_t), KM_SLEEP); - if (hk != NULL) { - hk->hk_fn = fn; - hk->hk_arg = arg; - mutex_enter(&rl->r_hooks_lock); - LIST_INSERT_HEAD(&rl->r_hooks, hk, hk_entry); - mutex_exit(&rl->r_hooks_lock); - } - return hk; -} - -/* - * npf_hook_unregister: unregister a specified hook. - * - * => Hook should have been registered in the rule. - */ -void -npf_hook_unregister(npf_rule_t *rl, npf_hook_t *hk) -{ - - mutex_enter(&rl->r_hooks_lock); - LIST_REMOVE(hk, hk_entry); - mutex_exit(&rl->r_hooks_lock); - kmem_free(hk, sizeof(npf_hook_t)); -} -#endif - npf_rule_t * npf_ruleset_replace(const char *name, npf_ruleset_t *rlset) { @@ -511,7 +383,7 @@ again: } /* - * npf_rule_apply: apply the rule i.e. run hooks and return appropriate value. + * npf_rule_apply: apply the rule and return appropriate value. * * => Returns ENETUNREACH if "block" and 0 if "pass". * => Releases the ruleset lock. @@ -519,26 +391,16 @@ again: int npf_rule_apply(npf_cache_t *npc, nbuf_t *nbuf, npf_rule_t *rl, int *retfl) { - npf_hook_t *hk; int error; KASSERT(npf_core_locked()); /* If not passing - drop the packet. */ - if ((rl->r_attr & NPF_RULE_PASS) == 0) { - error = ENETUNREACH; - goto done; - } - error = 0; - - /* Passing. Run the hooks. */ - LIST_FOREACH(hk, &rl->r_hooks, hk_entry) { - KASSERT(hk->hk_fn != NULL); - (*hk->hk_fn)(npc, nbuf, hk->hk_arg); - } -done: + error = (rl->r_attr & NPF_RULE_PASS) ? 0 : ENETUNREACH; + *retfl = rl->r_attr; npf_core_exit(); + return error; } Added files: Index: src/sys/net/npf/npf_rproc.c diff -u /dev/null src/sys/net/npf/npf_rproc.c:1.1 --- /dev/null Mon Feb 6 23:30:15 2012 +++ src/sys/net/npf/npf_rproc.c Mon Feb 6 23:30:14 2012 @@ -0,0 +1,133 @@ +/* $NetBSD: npf_rproc.c,v 1.1 2012/02/06 23:30:14 rmind Exp $ */ + +/*- + * Copyright (c) 2009-2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This material is based upon work partially supported by The + * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * NPF rule procedure interface. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD"); + +#include <sys/param.h> +#include <sys/kernel.h> + +#include <sys/atomic.h> +#include <sys/kmem.h> +#include <sys/types.h> + +#include "npf_impl.h" + +#define NPF_RNAME_LEN 16 + +/* Rule procedure structure. */ +struct npf_rproc { + /* Name. */ + char rp_name[NPF_RNAME_LEN]; + /* Reference count. */ + u_int rp_refcnt; + uint32_t rp_flags; + /* Normalisation options. */ + bool rp_rnd_ipid; + bool rp_no_df; + u_int rp_minttl; + u_int rp_maxmss; + /* Logging interface. */ + u_int rp_log_ifid; +}; + +npf_rproc_t * +npf_rproc_create(prop_dictionary_t rpdict) +{ + npf_rproc_t *rp; + const char *rname; + + rp = kmem_zalloc(sizeof(npf_rproc_t), KM_SLEEP); + rp->rp_refcnt = 1; + + /* Name and flags. */ + prop_dictionary_get_cstring_nocopy(rpdict, "name", &rname); + strlcpy(rp->rp_name, rname, NPF_RNAME_LEN); + prop_dictionary_get_uint32(rpdict, "flags", &rp->rp_flags); + + /* Logging interface ID (integer). */ + prop_dictionary_get_uint32(rpdict, "log-interface", &rp->rp_log_ifid); + + /* IP ID randomisation and IP_DF flag cleansing. */ + prop_dictionary_get_bool(rpdict, "randomize-id", &rp->rp_rnd_ipid); + prop_dictionary_get_bool(rpdict, "no-df", &rp->rp_no_df); + + /* Minimum IP TTL and maximum TCP MSS. */ + prop_dictionary_get_uint32(rpdict, "min-ttl", &rp->rp_minttl); + prop_dictionary_get_uint32(rpdict, "max-mss", &rp->rp_maxmss); + + return rp; +} + +void +npf_rproc_acquire(npf_rproc_t *rp) +{ + + atomic_inc_uint(&rp->rp_refcnt); +} + +void +npf_rproc_release(npf_rproc_t *rp) +{ + + /* Destroy on last reference. */ + KASSERT(rp->rp_refcnt > 0); + if (atomic_dec_uint_nv(&rp->rp_refcnt) != 0) { + return; + } + kmem_free(rp, sizeof(npf_rproc_t)); +} + +void +npf_rproc_run(npf_cache_t *npc, nbuf_t *nbuf, npf_rproc_t *rp, int error) +{ + const uint32_t flags = rp->rp_flags; + + KASSERT(rp->rp_refcnt > 0); + + /* Normalise the packet, if required. */ + if ((flags & NPF_RPROC_NORMALIZE) != 0 && !error) { + (void)npf_normalize(npc, nbuf, + rp->rp_rnd_ipid, rp->rp_no_df, + rp->rp_minttl, rp->rp_maxmss); + npf_stats_inc(NPF_STAT_RPROC_NORM); + } + + /* Log packet, if required. */ + if ((flags & NPF_RPROC_LOG) != 0) { + npf_log_packet(npc, nbuf, rp->rp_log_ifid); + npf_stats_inc(NPF_STAT_RPROC_LOG); + } +}