Make ALG's autoloadable by providing in the config file: trunk
authorchristos <christos@NetBSD.org>
Wed, 20 Mar 2013 00:29:46 +0000
branchtrunk
changeset 217379 fb5e74f02c59
parent 217378 19f5185c8fc7
child 217380 5700117a9358
Make ALG's autoloadable by providing in the config file: alg "algname"
lib/libnpf/npf.c
lib/libnpf/npf.h
sys/net/npf/npf_alg.c
sys/net/npf/npf_alg_icmp.c
sys/net/npf/npf_ctl.c
sys/net/npf/npf_impl.h
usr.sbin/npf/npfctl/npf_build.c
usr.sbin/npf/npfctl/npf_parse.y
usr.sbin/npf/npfctl/npf_scan.l
usr.sbin/npf/npfctl/npfctl.h
--- a/lib/libnpf/npf.c	Tue Mar 19 22:16:52 2013 +0000
+++ b/lib/libnpf/npf.c	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.c,v 1.18 2013/02/16 21:11:16 rmind Exp $	*/
+/*	$NetBSD: npf.c,v 1.19 2013/03/20 00:29:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.18 2013/02/16 21:11:16 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.19 2013/03/20 00:29:46 christos Exp $");
 
 #include <sys/types.h>
 #include <netinet/in_systm.h>
@@ -50,6 +50,7 @@
 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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 {
 
 	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 @@
 }
 
 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 @@
 }
 
 /*
+ * ALG INTERFACE.
+ */
+
+int
+_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 EEXIST;
+
+	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 0;
+}
+
+int
+_npf_alg_unload(nl_config_t *ncf, const char *name)
+{
+
+	if (!_npf_prop_array_lookup(ncf->ncf_alg_list, "name", name))
+		return ENOENT;
+
+	// Not yet: prop_array_add(ncf->ncf_alg_list, al_dict);
+	return ENOTSUP;
+}
+
+/*
  * MISC.
  */
 
--- a/lib/libnpf/npf.h	Tue Mar 19 22:16:52 2013 +0000
+++ b/lib/libnpf/npf.h	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf.h,v 1.15 2013/02/16 21:11:17 rmind Exp $	*/
+/*	$NetBSD: npf.h,v 1.16 2013/03/20 00:29:46 christos Exp $	*/
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -134,6 +134,11 @@
 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 */
+int 		_npf_alg_load(nl_config_t *, const char *);
+int		_npf_alg_unload(nl_config_t *, const char *);
+
 #endif
 
 __END_DECLS
--- a/sys/net/npf/npf_alg.c	Tue Mar 19 22:16:52 2013 +0000
+++ b/sys/net/npf/npf_alg.c	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_alg.c,v 1.7 2013/02/09 03:35:31 rmind Exp $	*/
+/*	$NetBSD: npf_alg.c,v 1.8 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v 1.7 2013/02/09 03:35:31 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v 1.8 2013/03/20 00:29:47 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -43,12 +43,14 @@
 #include <sys/pserialize.h>
 #include <sys/mutex.h>
 #include <net/pfil.h>
+#include <sys/module.h>
 
 #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 @@
 	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);
 
--- a/sys/net/npf/npf_alg_icmp.c	Tue Mar 19 22:16:52 2013 +0000
+++ b/sys/net/npf/npf_alg_icmp.c	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_alg_icmp.c,v 1.15 2013/02/09 03:35:31 rmind Exp $	*/
+/*	$NetBSD: npf_alg_icmp.c,v 1.16 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.15 2013/02/09 03:35:31 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.16 2013/03/20 00:29:47 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/module.h>
@@ -79,7 +79,7 @@
 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;
--- a/sys/net/npf/npf_ctl.c	Tue Mar 19 22:16:52 2013 +0000
+++ b/sys/net/npf/npf_ctl.c	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_ctl.c,v 1.23 2013/02/16 21:11:12 rmind Exp $	*/
+/*	$NetBSD: npf_ctl.c,v 1.24 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.23 2013/02/16 21:11:12 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.24 2013/03/20 00:29:47 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -216,6 +216,35 @@
 	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 @@
 {
 	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 @@
 		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);
--- a/sys/net/npf/npf_impl.h	Tue Mar 19 22:16:52 2013 +0000
+++ b/sys/net/npf/npf_impl.h	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_impl.h,v 1.28 2013/02/16 21:11:12 rmind Exp $	*/
+/*	$NetBSD: npf_impl.h,v 1.29 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -324,9 +324,10 @@
 /* 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);
--- a/usr.sbin/npf/npfctl/npf_build.c	Tue Mar 19 22:16:52 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_build.c	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_build.c,v 1.22 2013/03/18 02:17:49 rmind Exp $	*/
+/*	$NetBSD: npf_build.c,v 1.23 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_build.c,v 1.22 2013/03/18 02:17:49 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.23 2013/03/20 00:29:47 christos Exp $");
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
@@ -443,7 +443,7 @@
 
 	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_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) != 0) {
+		errx(EXIT_FAILURE, "ALG '%s' already loaded", al_name);
+	}
+}
--- a/usr.sbin/npf/npfctl/npf_parse.y	Tue Mar 19 22:16:52 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_parse.y	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_parse.y,v 1.21 2013/03/18 02:17:49 rmind Exp $	*/
+/*	$NetBSD: npf_parse.y,v 1.22 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -86,6 +86,7 @@
 
 %}
 
+%token			ALG
 %token			ALL
 %token			ANY
 %token			APPLY
@@ -196,6 +197,7 @@
 	| map
 	| group
 	| rproc
+	| alg
 	|
 	;
 
@@ -324,6 +326,12 @@
 	}
 	;
 
+alg	
+	: ALG STRING
+	{
+		npfctl_build_alg($2);
+	}
+	;
 procs
 	: proc_call SEPLINE procs
 	{
--- a/usr.sbin/npf/npfctl/npf_scan.l	Tue Mar 19 22:16:52 2013 +0000
+++ b/usr.sbin/npf/npfctl/npf_scan.l	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npf_scan.l,v 1.11 2013/03/18 02:17:49 rmind Exp $	*/
+/*	$NetBSD: npf_scan.l,v 1.12 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -86,6 +86,7 @@
 NUMBER	[0-9]+
 
 %%
+alg			return ALG;
 table			return TABLE;
 type			return TYPE;
 hash			return HASH;
--- a/usr.sbin/npf/npfctl/npfctl.h	Tue Mar 19 22:16:52 2013 +0000
+++ b/usr.sbin/npf/npfctl/npfctl.h	Wed Mar 20 00:29:46 2013 +0000
@@ -1,4 +1,4 @@
-/*	$NetBSD: npfctl.h,v 1.28 2013/03/18 02:17:49 rmind Exp $	*/
+/*	$NetBSD: npfctl.h,v 1.29 2013/03/20 00:29:47 christos Exp $	*/
 
 /*-
  * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -192,6 +192,7 @@
 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);