Index: sys/net/npf/npf_alg.c =================================================================== RCS file: /cvsroot/src/sys/net/npf/npf_alg.c,v retrieving revision 1.7 diff -u -p -u -r1.7 npf_alg.c --- sys/net/npf/npf_alg.c 9 Feb 2013 03:35:31 -0000 1.7 +++ sys/net/npf/npf_alg.c 19 Mar 2013 21:17:47 -0000 @@ -43,12 +43,14 @@ __KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v #include #include #include +#include #include "npf_impl.h" /* NAT ALG structure for registration. */ struct npf_alg { LIST_ENTRY(npf_alg) na_entry; + const char * na_name; npf_alg_t * na_bptr; npf_alg_func_t na_match_func; npf_alg_func_t na_tr_func; @@ -77,22 +79,70 @@ npf_alg_sysfini(void) mutex_destroy(&nat_alg_lock); } +static const char npf_alg_prefix[] = "npf_alg_"; +#define NPF_EXT_PREFLEN (sizeof(npf_alg_prefix) - 1) + +static npf_alg_t * +npf_alg_lookup(const char *name, bool autoload) +{ + npf_alg_t *alg; + char modname[64 + NPF_EXT_PREFLEN]; + int error; + + KASSERT(mutex_owned(&nat_alg_lock)); + +again: + LIST_FOREACH(alg, &nat_alg_list, na_entry) + if (strcmp(alg->na_name, name) == 0) + break; + + if (alg != NULL || !autoload) + return alg; + + mutex_exit(&nat_alg_lock); + autoload = false; + snprintf(modname, sizeof(modname), "%s%s", npf_alg_prefix, name); + error = module_autoload(modname, MODULE_CLASS_MISC); + mutex_enter(&nat_alg_lock); + + if (error) + return NULL; + goto again; +} + +npf_alg_t * +npf_alg_construct(const char *name) +{ + npf_alg_t *alg; + + mutex_enter(&nat_alg_lock); + alg = npf_alg_lookup(name, true); + mutex_exit(&nat_alg_lock); + return alg; +} + /* * npf_alg_register: register application-level gateway. */ npf_alg_t * -npf_alg_register(npf_alg_func_t mfunc, npf_alg_func_t tfunc, +npf_alg_register(const char *name, npf_alg_func_t mfunc, npf_alg_func_t tfunc, npf_alg_sfunc_t sfunc) { npf_alg_t *alg; alg = kmem_zalloc(sizeof(npf_alg_t), KM_SLEEP); + alg->na_name = name; alg->na_bptr = alg; alg->na_match_func = mfunc; alg->na_tr_func = tfunc; alg->na_se_func = sfunc; mutex_enter(&nat_alg_lock); + if (npf_alg_lookup(name, false) != NULL) { + mutex_exit(&nat_alg_lock); + kmem_free(alg, sizeof(npf_alg_t)); + return NULL; + } LIST_INSERT_HEAD(&nat_alg_list, alg, na_entry); mutex_exit(&nat_alg_lock); Index: sys/net/npf/npf_alg_icmp.c =================================================================== RCS file: /cvsroot/src/sys/net/npf/npf_alg_icmp.c,v retrieving revision 1.15 diff -u -p -u -r1.15 npf_alg_icmp.c --- sys/net/npf/npf_alg_icmp.c 9 Feb 2013 03:35:31 -0000 1.15 +++ sys/net/npf/npf_alg_icmp.c 19 Mar 2013 21:17:47 -0000 @@ -79,7 +79,7 @@ static int npf_alg_icmp_init(void) { - alg_icmp = npf_alg_register(npfa_icmp_match, + alg_icmp = npf_alg_register("icmp", npfa_icmp_match, npfa_icmp_nat, npfa_icmp_session); KASSERT(alg_icmp != NULL); return 0; Index: sys/net/npf/npf_ctl.c =================================================================== RCS file: /cvsroot/src/sys/net/npf/npf_ctl.c,v retrieving revision 1.23 diff -u -p -u -r1.23 npf_ctl.c --- sys/net/npf/npf_ctl.c 16 Feb 2013 21:11:12 -0000 1.23 +++ sys/net/npf/npf_ctl.c 19 Mar 2013 21:17:47 -0000 @@ -216,6 +216,35 @@ npf_mk_rprocs(npf_rprocset_t *rpset, pro return error; } +static npf_alg_t * +npf_mk_singlealg(prop_dictionary_t aldict) +{ + const char *name; + + if (!prop_dictionary_get_cstring_nocopy(aldict, "name", &name)) + return NULL; + return npf_alg_construct(name); +} + +static int __noinline +npf_mk_algs(prop_array_t alglist, prop_dictionary_t errdict) +{ + prop_object_iterator_t it; + prop_dictionary_t nadict; + int error = 0; + + it = prop_array_iterator(alglist); + while ((nadict = prop_object_iterator_next(it)) != NULL) { + if (npf_mk_singlealg(nadict) == NULL) { + NPF_ERR_DEBUG(errdict); + error = EINVAL; + break; + } + } + prop_object_iterator_release(it); + return error; +} + static int __noinline npf_mk_code(prop_object_t obj, int type, void **code, size_t *csize, prop_dictionary_t errdict) @@ -419,7 +448,7 @@ npfctl_reload(u_long cmd, void *data) { struct plistref *pref = data; prop_dictionary_t npf_dict, errdict; - prop_array_t natlist, tables, rprocs, rules; + prop_array_t alglist, natlist, tables, rprocs, rules; npf_tableset_t *tblset = NULL; npf_rprocset_t *rpset = NULL; npf_ruleset_t *rlset = NULL; @@ -446,6 +475,13 @@ npfctl_reload(u_long cmd, void *data) goto fail; } + /* ALGs. */ + alglist = prop_dictionary_get(npf_dict, "algs"); + error = npf_mk_algs(alglist, errdict); + if (error) { + goto fail; + } + /* NAT policies. */ natlist = prop_dictionary_get(npf_dict, "translation"); nitems = prop_array_count(natlist); Index: sys/net/npf/npf_impl.h =================================================================== RCS file: /cvsroot/src/sys/net/npf/npf_impl.h,v retrieving revision 1.28 diff -u -p -u -r1.28 npf_impl.h --- sys/net/npf/npf_impl.h 16 Feb 2013 21:11:12 -0000 1.28 +++ sys/net/npf/npf_impl.h 19 Mar 2013 21:17:47 -0000 @@ -324,9 +324,10 @@ npf_nat_t * npf_nat_restore(prop_diction /* ALG interface. */ void npf_alg_sysinit(void); void npf_alg_sysfini(void); -npf_alg_t * npf_alg_register(npf_alg_func_t, npf_alg_func_t, +npf_alg_t * npf_alg_register(const char *, npf_alg_func_t, npf_alg_func_t, npf_alg_sfunc_t); int npf_alg_unregister(npf_alg_t *); +npf_alg_t * npf_alg_construct(const char *); bool npf_alg_match(npf_cache_t *, nbuf_t *, npf_nat_t *, int); void npf_alg_exec(npf_cache_t *, nbuf_t *, npf_nat_t *, int); npf_session_t * npf_alg_session(npf_cache_t *, nbuf_t *, int); Index: usr.sbin/npf/npfctl/npf_build.c =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npfctl/npf_build.c,v retrieving revision 1.22 diff -u -p -u -r1.22 npf_build.c --- usr.sbin/npf/npfctl/npf_build.c 18 Mar 2013 02:17:49 -0000 1.22 +++ usr.sbin/npf/npfctl/npf_build.c 19 Mar 2013 21:17:48 -0000 @@ -443,7 +443,7 @@ npfctl_build_rproc(const char *name, npf rp = npf_rproc_create(name); if (rp == NULL) { - errx(EXIT_FAILURE, "npf_rproc_create failed"); + errx(EXIT_FAILURE, "%s failed", __func__); } npf_rproc_insert(npf_conf, rp); @@ -710,3 +710,15 @@ npfctl_build_table(const char *tid, u_in npfctl_fill_table(tl, type, fname); } } + +/* + * npfctl_build_alg: create an NPF application level gatewayl and add it + * to the configuration. + */ +void +npfctl_build_alg(const char *al_name) +{ + if (_npf_alg_load(npf_conf, al_name)) { + errx(EXIT_FAILURE, "alg '%s' is already defined\n", al_name); + } +} Index: usr.sbin/npf/npfctl/npf_parse.y =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npfctl/npf_parse.y,v retrieving revision 1.21 diff -u -p -u -r1.21 npf_parse.y --- usr.sbin/npf/npfctl/npf_parse.y 18 Mar 2013 02:17:49 -0000 1.21 +++ usr.sbin/npf/npfctl/npf_parse.y 19 Mar 2013 21:17:48 -0000 @@ -86,6 +86,7 @@ yyerror(const char *fmt, ...) %} +%token ALG %token ALL %token ANY %token APPLY @@ -196,6 +197,7 @@ line | map | group | rproc + | alg | ; @@ -324,6 +326,12 @@ rproc } ; +alg + : ALG STRING + { + npfctl_build_alg($2); + } + ; procs : proc_call SEPLINE procs { Index: usr.sbin/npf/npfctl/npf_scan.l =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npfctl/npf_scan.l,v retrieving revision 1.11 diff -u -p -u -r1.11 npf_scan.l --- usr.sbin/npf/npfctl/npf_scan.l 18 Mar 2013 02:17:49 -0000 1.11 +++ usr.sbin/npf/npfctl/npf_scan.l 19 Mar 2013 21:17:48 -0000 @@ -86,6 +86,7 @@ NID [a-zA-Z_0-9]+ NUMBER [0-9]+ %% +alg return ALG; table return TABLE; type return TYPE; hash return HASH; Index: usr.sbin/npf/npfctl/npfctl.h =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npfctl/npfctl.h,v retrieving revision 1.28 diff -u -p -u -r1.28 npfctl.h --- usr.sbin/npf/npfctl/npfctl.h 18 Mar 2013 02:17:49 -0000 1.28 +++ usr.sbin/npf/npfctl/npfctl.h 19 Mar 2013 21:17:48 -0000 @@ -192,6 +192,7 @@ int npfctl_ruleset_show(int, const char nl_rule_t * npfctl_rule_ref(void); unsigned long npfctl_debug_addif(const char *); +void npfctl_build_alg(const char *); void npfctl_build_rproc(const char *, npfvar_t *); void npfctl_build_group(const char *, int, u_int, bool); void npfctl_build_group_end(void); Index: lib/libnpf/npf.c =================================================================== RCS file: /cvsroot/src/lib/libnpf/npf.c,v retrieving revision 1.18 diff -u -p -u -r1.18 npf.c --- lib/libnpf/npf.c 16 Feb 2013 21:11:16 -0000 1.18 +++ lib/libnpf/npf.c 19 Mar 2013 21:17:50 -0000 @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.18 struct nl_config { /* Rules, translations, tables, procedures. */ prop_dictionary_t ncf_dict; + prop_array_t ncf_alg_list; prop_array_t ncf_rules_list; prop_array_t ncf_rproc_list; prop_array_t ncf_table_list; @@ -75,6 +76,10 @@ struct nl_table { prop_dictionary_t ntl_dict; }; +struct nl_alg { + prop_dictionary_t nal_dict; +}; + struct nl_ext { const char * nxt_name; prop_dictionary_t nxt_dict; @@ -95,6 +100,7 @@ npf_config_create(void) if (ncf == NULL) { return NULL; } + ncf->ncf_alg_list = prop_array_create(); ncf->ncf_rules_list = prop_array_create(); ncf->ncf_rproc_list = prop_array_create(); ncf->ncf_table_list = prop_array_create(); @@ -128,6 +134,7 @@ npf_config_submit(nl_config_t *ncf, int prop_dictionary_set(npf_dict, "rules", rlset); prop_object_release(rlset); + prop_dictionary_set(npf_dict, "algs", ncf->ncf_alg_list); prop_dictionary_set(npf_dict, "rprocs", ncf->ncf_rproc_list); prop_dictionary_set(npf_dict, "tables", ncf->ncf_table_list); prop_dictionary_set(npf_dict, "translation", ncf->ncf_nat_list); @@ -174,6 +181,7 @@ npf_config_retrieve(int fd, bool *active return NULL; } ncf->ncf_dict = npf_dict; + ncf->ncf_alg_list = prop_dictionary_get(npf_dict, "algs"); ncf->ncf_rules_list = prop_dictionary_get(npf_dict, "rules"); ncf->ncf_rproc_list = prop_dictionary_get(npf_dict, "rprocs"); ncf->ncf_table_list = prop_dictionary_get(npf_dict, "tables"); @@ -220,6 +228,7 @@ npf_config_destroy(nl_config_t *ncf) { if (!ncf->ncf_dict) { + prop_object_release(ncf->ncf_alg_list); prop_object_release(ncf->ncf_rules_list); prop_object_release(ncf->ncf_rproc_list); prop_object_release(ncf->ncf_table_list); @@ -773,7 +782,7 @@ npf_nat_create(int type, u_int flags, u_ } int -npf_nat_insert(nl_config_t *ncf, nl_nat_t *nt, pri_t pri) +npf_nat_insert(nl_config_t *ncf, nl_nat_t *nt, pri_t pri __unused) { prop_dictionary_t rldict = nt->nrl_dict; @@ -936,6 +945,36 @@ _npf_table_foreach(nl_config_t *ncf, nl_ } /* + * ALG INTERFACE. + */ + +bool +_npf_alg_load(nl_config_t *ncf, const char *name) +{ + prop_dictionary_t al_dict; + + if (_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name)) + return false; + + al_dict = prop_dictionary_create(); + prop_dictionary_set_cstring(al_dict, "name", name); + prop_array_add(ncf->ncf_alg_list, al_dict); + prop_object_release(al_dict); + return true; +} + +bool +_npf_alg_unload(nl_config_t *ncf, const char *name) +{ + + if (_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name)) + return false; + + // Not yet: prop_array_add(ncf->ncf_alg_list, al_dict); + return true; +} + +/* * MISC. */ Index: lib/libnpf/npf.h =================================================================== RCS file: /cvsroot/src/lib/libnpf/npf.h,v retrieving revision 1.15 diff -u -p -u -r1.15 npf.h --- lib/libnpf/npf.h 16 Feb 2013 21:11:17 -0000 1.15 +++ lib/libnpf/npf.h 19 Mar 2013 21:17:51 -0000 @@ -134,6 +134,11 @@ void _npf_nat_getinfo(nl_nat_t *, int * void _npf_table_foreach(nl_config_t *, nl_table_callback_t); void _npf_debug_addif(nl_config_t *, struct ifaddrs *, u_int); + +/* The ALG interface is experimental */ +bool _npf_alg_load(nl_config_t *, const char *); +bool _npf_alg_unload(nl_config_t *, const char *); + #endif __END_DECLS