summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authormartin <martin@NetBSD.org>2020-06-20 15:46:47 +0000
committermartin <martin@NetBSD.org>2020-06-20 15:46:47 +0000
commitb19d58aad73c1adb8001858747a19d45bc8be0f9 (patch)
tree9fe3f3431c7c5bed82411881629567d181b19097 /lib
parent7d79e88db64cfbb1537b720c0a32d0c76aafaaa6 (diff)
Pull up following revision(s) (requested by rmind in ticket #956):
usr.sbin/npf/npf-params.7: revision 1.4 sys/net/npf/npf_worker.c: revision 1.9 usr.sbin/npf/npftest/npftest.h: revision 1.17 usr.sbin/npf/npfctl/npf_bpf_comp.c: revision 1.16 usr.sbin/npf/npf-params.7: revision 1.5 sys/net/npf/npf_state_tcp.c: revision 1.21 usr.sbin/npf/npfctl/npf_build.c: revision 1.55 usr.sbin/npf/npf-params.7: revision 1.6 sys/net/npf/npfkern.h: revision 1.5 lib/libnpf/npf.c: revision 1.49 usr.sbin/npf/npf-params.7: revision 1.7 sys/net/npf/npf_impl.h: revision 1.81 sys/net/npf/npf_ext_log.c: revision 1.17 usr.sbin/npf/npfctl/npfctl.h: revision 1.53 usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c: revision 1.11 sys/net/npf/npf_nat.c: revision 1.50 sys/net/npf/npf_mbuf.c: revision 1.24 sys/net/npf/npf_alg.c: revision 1.22 usr.sbin/npf/npftest/libnpftest/npf_nat_test.c: revision 1.14 usr.sbin/npf/npftest/libnpftest/npf_conn_test.c: file removal usr.sbin/npf/npftest/libnpftest/npf_state_test.c: revision 1.10 sys/net/npf/npf.h: revision 1.63 usr.sbin/npf/npftest/libnpftest/npf_test.h: revision 1.21 usr.sbin/npf/npfctl/npf_var.c: revision 1.13 sys/net/npf/files.npf: revision 1.23 usr.sbin/npf/npfctl/npf_show.c: revision 1.32 usr.sbin/npf/npfctl/npf.conf.5: revision 1.91 sys/net/npf/npf_os.c: revision 1.18 sys/net/npf/npf_connkey.c: revision 1.2 sys/net/npf/npf_conf.c: revision 1.17 lib/libnpf/libnpf.3: revision 1.12 usr.sbin/npf/npftest/npftest.c: revision 1.25 usr.sbin/npf/npftest/libnpftest/npf_gc_test.c: revision 1.1 usr.sbin/npf/npfctl/npf_parse.y: revision 1.51 sys/net/npf/npf_tableset.c: revision 1.35 usr.sbin/npf/npftest/npftest.conf: revision 1.9 sys/net/npf/npf_sendpkt.c: revision 1.22 usr.sbin/npf/npfctl/npf_var.h: revision 1.10 sys/net/npf/npf_state.c: revision 1.23 sys/net/npf/npf_conn.h: revision 1.20 usr.sbin/npf/npfctl/npfctl.c: revision 1.64 usr.sbin/npf/npfctl/npf_cmd.c: revision 1.1 sys/net/npf/npf_portmap.c: revision 1.5 sys/net/npf/npf_params.c: revision 1.3 usr.sbin/npf/npfctl/npf_scan.l: revision 1.32 tests/net/npf/t_npf.sh: revision 1.4 sys/net/npf/npf_ext_rndblock.c: revision 1.9 lib/libnpf/npf.h: revision 1.39 sys/net/npf/npf_ruleset.c: revision 1.51 sys/net/npf/npf_alg_icmp.c: revision 1.33 sys/net/npf/npf.c: revision 1.43 usr.sbin/npf/npftest/libnpftest/npf_test_subr.c: revision 1.17 usr.sbin/npf/npfctl/npfctl.8: revision 1.25 sys/net/npf/npf_ctl.c: revision 1.60 usr.sbin/npf/npftest/libnpftest/npf_test_subr.c: revision 1.18 usr.sbin/npf/npftest/libnpftest/Makefile: revision 1.11 sys/net/npf/npf_handler.c: revision 1.49 sys/net/npf/npf_inet.c: revision 1.57 sys/net/npf/npf_ifaddr.c: revision 1.7 sys/net/npf/npf_conndb.c: revision 1.9 sys/net/npf/npf_if.c: revision 1.13 usr.sbin/npf/npfctl/Makefile: revision 1.15 sys/net/npf/npf_conn.c: revision 1.32 sys/net/npf/npf_ext_normalize.c: revision 1.10 sys/net/npf/npf_rproc.c: revision 1.20 sys/net/npf/npf_worker.c: revision 1.8 Major NPF improvements (merge from upstream): - Switch to the C11-style atomic primitives using atomic_loadstore(9). - npfkern: introduce the 'state.key.interface' and 'state.key.direction' settings. Users can now choose whether the connection state should be strictly per-interface or global at the configuration level. Keep NAT logic to be always per-interface, though. - npfkern: rewrite the G/C worker logic and make it self-tuning. - npfkern and libnpf: multiple bug fixes; add param exporting; introduce more parameters. Remove npf_nvlist_{copyin,copyout}() functions and refactor npfctl_load_nvlist() with others; add npfctl_run_op() to have a single entry point for operations. Introduce npf_flow_t and clean up some code. - npfctl: lots of fixes for the 'npfctl show' logic; make 'npfctl list' more informative; misc usability improvements and more user-friendly error messages. - Amend and improve the manual pages. npf_worker_sys{init,fini}: initialize/destroy the exit_cv condvar. npftest -- npf_test_init(): add a workaround for NetBSD. npf-params(7): fix the state.key defaults. npf-params.7: s/filer/filter/ Adjust to "npfctl debug" command line changes, from rmind@. Use more markup.
Diffstat (limited to 'lib')
-rw-r--r--lib/libnpf/libnpf.316
-rw-r--r--lib/libnpf/npf.c403
-rw-r--r--lib/libnpf/npf.h3
3 files changed, 292 insertions, 130 deletions
diff --git a/lib/libnpf/libnpf.3 b/lib/libnpf/libnpf.3
index f971604c083..029628c256f 100644
--- a/lib/libnpf/libnpf.3
+++ b/lib/libnpf/libnpf.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: libnpf.3,v 1.9.2.2 2019/10/04 08:06:35 martin Exp $
+.\" $NetBSD: libnpf.3,v 1.9.2.3 2020/06/20 15:46:48 martin Exp $
.\"
.\" Copyright (c) 2011-2019 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd August 25, 2019
+.Dd May 30, 2020
.Dt LIBNPF 3
.Os
.Sh NAME
@@ -187,13 +187,12 @@ be stopped and this rule should be applied instantly.
.It Dv NPF_RULE_STATEFUL
Create a state (session) on match, track the connection and pass the
backwards stream (the returning packets) without the ruleset inspection.
-The state is uniquely identified by a 5-tuple (source and destination
-IP addresses, port numbers and an interface identifier).
+The state is uniquely identified by an n-tuple key.
.It Dv NPF_RULE_GSTATEFUL
-Exclude the interface identifier from the state key i.e. use a 4-tuple.
+Exclude the interface identifier from the state key (n-tuple).
This makes the state global with respect to the network interfaces.
-The state is also picked for packets travelling different direction than
-originally.
+The state is also picked for packets travelling in different direction
+than originally.
.It Dv NPF_RULE_RETRST
Return TCP RST packet in a case of packet block.
.It Dv NPF_RULE_RETICMP
@@ -281,7 +280,8 @@ If the value of
is
.Dv NULL ,
then insert into the main ruleset.
-The rule must not be referenced after insertion.
+The rule will be consumed (the relevant resourced will be freed) and it
+must not be referenced after insertion.
.\" ---
.It Fn npf_rule_exists_p "ncf" "name"
Check whether the rule with a given name is already in the configuration.
diff --git a/lib/libnpf/npf.c b/lib/libnpf/npf.c
index 1f95d6f901a..9cc93093a8b 100644
--- a/lib/libnpf/npf.c
+++ b/lib/libnpf/npf.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2010-2019 The NetBSD Foundation, Inc.
+ * Copyright (c) 2010-2020 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -28,11 +28,14 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.46.2.2 2019/10/04 08:06:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.46.2.3 2020/06/20 15:46:48 martin Exp $");
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#if !defined(_NPF_STANDALONE)
+#include <sys/ioctl.h>
+#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <net/if.h>
@@ -227,6 +230,94 @@ _npf_extract_error(nvlist_t *resp, npf_error_t *errinfo)
}
/*
+ * npf_xfer_fd: transfer the given request and receive a response.
+ *
+ * => Sets the 'operation' key on the 'req' dictionary.
+ * => On success: returns 0 and valid nvlist in 'resp'.
+ * => On failure: returns an error number.
+ */
+static int
+_npf_xfer_fd(int fd, unsigned long cmd, nvlist_t *req, nvlist_t **resp)
+{
+ struct stat st;
+ int kernver;
+
+ /*
+ * Set the NPF version and operation.
+ */
+ if (!nvlist_exists(req, "version")) {
+ nvlist_add_number(req, "version", NPF_VERSION);
+ }
+ nvlist_add_number(req, "operation", cmd);
+
+ /*
+ * Determine the type of file descriptor:
+ * - If socket, then perform nvlist_send()/nvlist_recv().
+ * - If a character device, then use ioctl.
+ */
+ if (fstat(fd, &st) == -1) {
+ goto err;
+ }
+ switch (st.st_mode & S_IFMT) {
+#if !defined(__NetBSD__)
+ case S_IFSOCK:
+ if (nvlist_send(fd, req) == -1) {
+ goto err;
+ }
+ if (resp && (*resp = nvlist_recv(fd, 0)) == NULL) {
+ goto err;
+ }
+ break;
+#endif
+#if !defined(_NPF_STANDALONE)
+ case S_IFBLK:
+ case S_IFCHR:
+ if (ioctl(fd, IOC_NPF_VERSION, &kernver) == -1) {
+ goto err;
+ }
+ if (kernver != NPF_VERSION) {
+ errno = EPROGMISMATCH;
+ goto err;
+ }
+ if (nvlist_xfer_ioctl(fd, cmd, req, resp) == -1) {
+ goto err;
+ }
+ break;
+#else
+ (void)kernver;
+#endif
+ default:
+ errno = ENOTSUP;
+ goto err;
+ }
+ return 0;
+err:
+ return errno ? errno : EIO;
+}
+
+/*
+ * npf_xfer_fd_errno: same as npf_xfer_fd(), but:
+ *
+ * => After successful retrieval of the response, inspects it, extracts
+ * the 'errno' value (if any) and returns it.
+ * => Destroys the response.
+ */
+static int
+_npf_xfer_fd_errno(int fd, unsigned long cmd, nvlist_t *req)
+{
+ nvlist_t *resp;
+ int error;
+
+ error = _npf_xfer_fd(fd, cmd, req, &resp);
+ if (error) {
+ return error;
+ }
+ error = _npf_extract_error(resp, NULL);
+ nvlist_destroy(resp);
+ return error;
+}
+
+/*
* CONFIGURATION INTERFACE.
*/
@@ -247,18 +338,18 @@ npf_config_create(void)
int
npf_config_submit(nl_config_t *ncf, int fd, npf_error_t *errinfo)
{
- nvlist_t *errnv = NULL;
+ nvlist_t *resp = NULL;
int error;
/* Ensure the config is built. */
(void)npf_config_build(ncf);
- if (nvlist_xfer_ioctl(fd, IOC_NPF_LOAD, ncf->ncf_dict, &errnv) == -1) {
- assert(errnv == NULL);
- return errno;
+ error = _npf_xfer_fd(fd, IOC_NPF_LOAD, ncf->ncf_dict, &resp);
+ if (error) {
+ return error;
}
- error = _npf_extract_error(errnv, errinfo);
- nvlist_destroy(errnv);
+ error = _npf_extract_error(resp, errinfo);
+ nvlist_destroy(resp);
return error;
}
@@ -266,15 +357,24 @@ nl_config_t *
npf_config_retrieve(int fd)
{
nl_config_t *ncf;
+ nvlist_t *req, *resp = NULL;
+ int error;
ncf = calloc(1, sizeof(nl_config_t));
if (!ncf) {
return NULL;
}
- if (nvlist_recv_ioctl(fd, IOC_NPF_SAVE, &ncf->ncf_dict) == -1) {
+
+ req = nvlist_create(0);
+ error = _npf_xfer_fd(fd, IOC_NPF_SAVE, req, &resp);
+ nvlist_destroy(req);
+
+ if (error || _npf_extract_error(resp, NULL) != 0) {
+ nvlist_destroy(resp);
free(ncf);
return NULL;
}
+ ncf->ncf_dict = resp;
return ncf;
}
@@ -332,7 +432,7 @@ npf_config_loaded_p(nl_config_t *ncf)
return nvlist_exists_nvlist_array(ncf->ncf_dict, "rules");
}
-void *
+const void *
npf_config_build(nl_config_t *ncf)
{
_npf_rules_process(ncf, ncf->ncf_dict, "__rules");
@@ -397,6 +497,43 @@ npf_param_set(nl_config_t *ncf, const char *name, int val)
return 0;
}
+const char *
+npf_param_iterate(nl_config_t *ncf, nl_iter_t *iter, int *val, int *defval)
+{
+ void *cookie = (void *)(intptr_t)*iter;
+ const nvlist_t *params, *dparams;
+ const char *name;
+ int type;
+
+ assert(sizeof(nl_iter_t) >= sizeof(void *));
+
+ params = dnvlist_get_nvlist(ncf->ncf_dict, "params", NULL);
+ if (params == NULL) {
+ return NULL;
+ }
+skip:
+ if ((name = nvlist_next(params, &type, &cookie)) == NULL) {
+ *iter = NPF_ITER_BEGIN;
+ return NULL;
+ }
+ if (type != NV_TYPE_NUMBER) {
+ goto skip; // should never happen, though
+ }
+ if (defval) {
+ dparams = dnvlist_get_nvlist(ncf->ncf_dict,
+ "params-defaults", NULL);
+ if (dparams == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ *defval = (int)nvlist_get_number(dparams, name);
+ }
+
+ *val = (int)nvlist_get_number(params, name);
+ *iter = (intptr_t)cookie;
+ return name;
+}
+
/*
* DYNAMIC RULESET INTERFACE.
*/
@@ -412,24 +549,26 @@ int
npf_ruleset_add(int fd, const char *rname, nl_rule_t *rl, uint64_t *id)
{
const bool natset = _npf_nat_ruleset_p(rname);
- nvlist_t *rule_dict = rl->rule_dict;
- nvlist_t *ret_dict;
+ nvlist_t *rule_nvl = rl->rule_dict, *resp;
+ int error;
- nvlist_add_number(rule_dict, "attr",
- NPF_RULE_DYNAMIC | nvlist_take_number(rule_dict, "attr"));
+ nvlist_add_number(rule_nvl, "attr",
+ NPF_RULE_DYNAMIC | nvlist_take_number(rule_nvl, "attr"));
- if (natset && !dnvlist_get_bool(rule_dict, "nat-rule", false)) {
+ if (natset && !dnvlist_get_bool(rule_nvl, "nat-rule", false)) {
errno = EINVAL;
return errno;
}
- nvlist_add_string(rule_dict, "ruleset-name", rname);
- nvlist_add_bool(rule_dict, "nat-ruleset", natset);
- nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_ADD);
+ nvlist_add_string(rule_nvl, "ruleset-name", rname);
+ nvlist_add_bool(rule_nvl, "nat-ruleset", natset);
+ nvlist_add_number(rule_nvl, "command", NPF_CMD_RULE_ADD);
- if (nvlist_xfer_ioctl(fd, IOC_NPF_RULE, rule_dict, &ret_dict) == -1) {
- return errno;
+ error = _npf_xfer_fd(fd, IOC_NPF_RULE, rule_nvl, &resp);
+ if (error) {
+ return error;
}
- *id = nvlist_get_number(ret_dict, "id");
+ *id = nvlist_get_number(resp, "id");
+ nvlist_destroy(resp);
return 0;
}
@@ -437,50 +576,50 @@ int
npf_ruleset_remove(int fd, const char *rname, uint64_t id)
{
const bool natset = _npf_nat_ruleset_p(rname);
- nvlist_t *rule_dict = nvlist_create(0);
+ nvlist_t *rule_nvl = nvlist_create(0);
+ int error;
- nvlist_add_string(rule_dict, "ruleset-name", rname);
- nvlist_add_bool(rule_dict, "nat-ruleset", natset);
- nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_REMOVE);
- nvlist_add_number(rule_dict, "id", id);
+ nvlist_add_string(rule_nvl, "ruleset-name", rname);
+ nvlist_add_bool(rule_nvl, "nat-ruleset", natset);
+ nvlist_add_number(rule_nvl, "command", NPF_CMD_RULE_REMOVE);
+ nvlist_add_number(rule_nvl, "id", id);
- if (nvlist_send_ioctl(fd, IOC_NPF_RULE, rule_dict) == -1) {
- return errno;
- }
- return 0;
+ error = _npf_xfer_fd_errno(fd, IOC_NPF_RULE, rule_nvl);
+ nvlist_destroy(rule_nvl);
+ return error;
}
int
npf_ruleset_remkey(int fd, const char *rname, const void *key, size_t len)
{
const bool natset = _npf_nat_ruleset_p(rname);
- nvlist_t *rule_dict = nvlist_create(0);
+ nvlist_t *rule_nvl = nvlist_create(0);
+ int error;
- nvlist_add_string(rule_dict, "ruleset-name", rname);
- nvlist_add_bool(rule_dict, "nat-ruleset", natset);
- nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_REMKEY);
- nvlist_add_binary(rule_dict, "key", key, len);
+ nvlist_add_string(rule_nvl, "ruleset-name", rname);
+ nvlist_add_bool(rule_nvl, "nat-ruleset", natset);
+ nvlist_add_number(rule_nvl, "command", NPF_CMD_RULE_REMKEY);
+ nvlist_add_binary(rule_nvl, "key", key, len);
- if (nvlist_send_ioctl(fd, IOC_NPF_RULE, rule_dict) == -1) {
- return errno;
- }
- return 0;
+ error = _npf_xfer_fd_errno(fd, IOC_NPF_RULE, rule_nvl);
+ nvlist_destroy(rule_nvl);
+ return error;
}
int
npf_ruleset_flush(int fd, const char *rname)
{
const bool natset = _npf_nat_ruleset_p(rname);
- nvlist_t *rule_dict = nvlist_create(0);
+ nvlist_t *rule_nvl = nvlist_create(0);
+ int error;
- nvlist_add_string(rule_dict, "ruleset-name", rname);
- nvlist_add_bool(rule_dict, "nat-ruleset", natset);
- nvlist_add_number(rule_dict, "command", NPF_CMD_RULE_FLUSH);
+ nvlist_add_string(rule_nvl, "ruleset-name", rname);
+ nvlist_add_bool(rule_nvl, "nat-ruleset", natset);
+ nvlist_add_number(rule_nvl, "command", NPF_CMD_RULE_FLUSH);
- if (nvlist_send_ioctl(fd, IOC_NPF_RULE, rule_dict) == -1) {
- return errno;
- }
- return 0;
+ error = _npf_xfer_fd_errno(fd, IOC_NPF_RULE, rule_nvl);
+ nvlist_destroy(rule_nvl);
+ return error;
}
/*
@@ -591,7 +730,9 @@ npf_rule_export(nl_rule_t *rl, size_t *length)
bool
npf_rule_exists_p(nl_config_t *ncf, const char *name)
{
- return _npf_dataset_lookup(ncf->ncf_dict, "rules", "name", name);
+ const char *key = nvlist_exists_nvlist_array(ncf->ncf_dict,
+ "rules") ? "rules" : "__rules"; // config may not be built yet
+ return _npf_dataset_lookup(ncf->ncf_dict, key, "name", name);
}
int
@@ -705,24 +846,28 @@ int
_npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf)
{
const bool natset = _npf_nat_ruleset_p(rname);
- nvlist_t *req, *ret;
+ nvlist_t *req, *resp;
+ int error;
req = nvlist_create(0);
nvlist_add_string(req, "ruleset-name", rname);
nvlist_add_bool(req, "nat-ruleset", natset);
nvlist_add_number(req, "command", NPF_CMD_RULE_LIST);
- if (nvlist_xfer_ioctl(fd, IOC_NPF_RULE, req, &ret) == -1) {
- return errno;
+ error = _npf_xfer_fd(fd, IOC_NPF_RULE, req, &resp);
+ nvlist_destroy(req);
+ if (error) {
+ return error;
}
- if (nvlist_exists_nvlist_array(ret, "rules")) {
+
+ if (nvlist_exists_nvlist_array(resp, "rules")) {
nvlist_t **rules;
size_t n;
- rules = nvlist_take_nvlist_array(ret, "rules", &n);
+ rules = nvlist_take_nvlist_array(resp, "rules", &n);
nvlist_move_nvlist_array(ncf->ncf_dict, "rules", rules, n);
}
- nvlist_destroy(ret);
+ nvlist_destroy(resp);
return 0;
}
@@ -1108,21 +1253,20 @@ npf_table_insert(nl_config_t *ncf, nl_table_t *tl)
int
npf_table_replace(int fd, nl_table_t *tl, npf_error_t *errinfo)
{
- nvlist_t *errnv = NULL;
+ nvlist_t *resp = NULL;
int error;
/* Ensure const tables are built. */
if ((error = _npf_table_build_const(tl)) != 0) {
return error;
}
-
- if (nvlist_xfer_ioctl(fd, IOC_NPF_TABLE_REPLACE,
- tl->table_dict, &errnv) == -1) {
- assert(errnv == NULL);
+ error = _npf_xfer_fd(fd, IOC_NPF_TABLE_REPLACE, tl->table_dict, &resp);
+ if (error) {
+ assert(resp == NULL);
return errno;
}
- error = _npf_extract_error(errnv, errinfo);
- nvlist_destroy(errnv);
+ error = _npf_extract_error(resp, errinfo);
+ nvlist_destroy(resp);
return error;
}
@@ -1190,64 +1334,77 @@ npf_alg_load(nl_config_t *ncf, const char *name)
* CONNECTION / NAT ENTRY INTERFACE.
*/
-int
-npf_nat_lookup(int fd, int af, npf_addr_t *addr[2], in_port_t port[2],
- int proto, int dir)
+typedef struct {
+ unsigned alen;
+ unsigned proto;
+ npf_addr_t addr[3];
+ in_port_t port[3];
+} npf_connpoint_t;
+
+static int
+_npf_conn_lookup(int fd, const int af, npf_addr_t *addr[2], in_port_t port[2],
+ unsigned proto, const char *ifname, unsigned di)
{
- nvlist_t *req = NULL, *conn_res;
+ nvlist_t *req = NULL, *resp = NULL, *key_nv;
const nvlist_t *nat;
int error = EINVAL;
/*
* Setup the connection lookup key.
*/
- conn_res = nvlist_create(0);
- if (!conn_res) {
+ if ((key_nv = nvlist_create(0)) == NULL) {
return ENOMEM;
}
- if (!_npf_add_addr(conn_res, "saddr", af, addr[0]))
+ if (!_npf_add_addr(key_nv, "saddr", af, addr[0])) {
+ nvlist_destroy(key_nv);
goto out;
- if (!_npf_add_addr(conn_res, "daddr", af, addr[1]))
+ }
+ if (!_npf_add_addr(key_nv, "daddr", af, addr[1])) {
+ nvlist_destroy(key_nv);
goto out;
- nvlist_add_number(conn_res, "sport", port[0]);
- nvlist_add_number(conn_res, "dport", port[1]);
- nvlist_add_number(conn_res, "proto", proto);
+ }
+ nvlist_add_number(key_nv, "sport", htons(port[0]));
+ nvlist_add_number(key_nv, "dport", htons(port[1]));
+ nvlist_add_number(key_nv, "proto", proto);
+ if (ifname) {
+ nvlist_add_string(key_nv, "ifname", ifname);
+ }
+ if (di) {
+ nvlist_add_number(key_nv, "di", di);
+ }
/*
* Setup the request.
*/
- req = nvlist_create(0);
- if (!req) {
+ if ((req = nvlist_create(0)) == NULL) {
error = ENOMEM;
goto out;
}
- nvlist_add_number(req, "direction", dir);
- nvlist_move_nvlist(req, "key", conn_res);
- conn_res = NULL;
+ nvlist_move_nvlist(req, "key", key_nv);
/* Lookup: retrieve the connection entry. */
- if (nvlist_xfer_ioctl(fd, IOC_NPF_CONN_LOOKUP, req, &conn_res) == -1) {
- error = errno;
+ error = _npf_xfer_fd(fd, IOC_NPF_CONN_LOOKUP, req, &resp);
+ if (error) {
goto out;
}
/*
* Get the NAT entry and extract the translated pair.
*/
- nat = dnvlist_get_nvlist(conn_res, "nat", NULL);
- if (!nat) {
- errno = ENOENT;
+ if ((nat = dnvlist_get_nvlist(resp, "nat", NULL)) == NULL) {
+ error = ENOENT;
goto out;
}
- if (!_npf_get_addr(nat, "oaddr", addr[0])) {
+ if (_npf_get_addr(nat, "oaddr", addr[0]) == 0 ||
+ _npf_get_addr(nat, "taddr", addr[1]) == 0) {
error = EINVAL;
goto out;
}
- port[0] = nvlist_get_number(nat, "oport");
- port[1] = nvlist_get_number(nat, "tport");
+ port[0] = ntohs(nvlist_get_number(nat, "oport"));
+ port[1] = ntohs(nvlist_get_number(nat, "tport"));
out:
- if (conn_res) {
- nvlist_destroy(conn_res);
+ if (resp) {
+ nvlist_destroy(resp);
}
if (req) {
nvlist_destroy(req);
@@ -1255,57 +1412,60 @@ out:
return error;
}
-typedef struct {
- npf_addr_t addr[2];
- in_port_t port[2];
- uint16_t alen;
- uint16_t proto;
-} npf_endpoint_t;
+int
+npf_nat_lookup(int fd, int af, npf_addr_t *addr[2], in_port_t port[2],
+ int proto, int di __unused)
+{
+ int error;
+
+ port[0] = ntohs(port[0]); port[1] = ntohs(port[1]);
+ error = _npf_conn_lookup(fd, af, addr, port, proto, NULL, 0);
+ port[0] = htons(port[0]); port[1] = htons(port[1]);
+ return error;
+}
static bool
-npf_endpoint_load(const nvlist_t *conn, const char *name, npf_endpoint_t *ep)
+npf_connkey_handle(const nvlist_t *key_nv, npf_connpoint_t *ep)
{
- const nvlist_t *ed = dnvlist_get_nvlist(conn, name, NULL);
+ unsigned alen1, alen2;
- if (!ed)
- return false;
- if (!(ep->alen = _npf_get_addr(ed, "saddr", &ep->addr[0])))
+ alen1 = _npf_get_addr(key_nv, "saddr", &ep->addr[0]);
+ alen2 = _npf_get_addr(key_nv, "daddr", &ep->addr[1]);
+ if (alen1 == 0 || alen1 != alen2) {
return false;
- if (ep->alen != _npf_get_addr(ed, "daddr", &ep->addr[1]))
- return false;
- ep->port[0] = nvlist_get_number(ed, "sport");
- ep->port[1] = nvlist_get_number(ed, "dport");
- ep->proto = nvlist_get_number(ed, "proto");
+ }
+ ep->alen = alen1;
+ ep->port[0] = ntohs(nvlist_get_number(key_nv, "sport"));
+ ep->port[1] = ntohs(nvlist_get_number(key_nv, "dport"));
+ ep->proto = nvlist_get_number(key_nv, "proto");
return true;
}
static void
npf_conn_handle(const nvlist_t *conn, npf_conn_func_t func, void *arg)
{
- const nvlist_t *nat;
- npf_endpoint_t ep;
- uint16_t tport;
+ const nvlist_t *key_nv, *nat_nv;
const char *ifname;
+ npf_connpoint_t ep;
+
+ memset(&ep, 0, sizeof(npf_connpoint_t));
ifname = dnvlist_get_string(conn, "ifname", NULL);
- if (!ifname)
+ key_nv = dnvlist_get_nvlist(conn, "forw-key", NULL);
+ if (!npf_connkey_handle(key_nv, &ep)) {
goto err;
-
- if ((nat = dnvlist_get_nvlist(conn, "nat", NULL)) != NULL) {
- tport = nvlist_get_number(nat, "tport");
- } else {
- tport = 0;
}
- if (!npf_endpoint_load(conn, "forw-key", &ep)) {
- goto err;
+ if ((nat_nv = dnvlist_get_nvlist(conn, "nat", NULL)) != NULL) {
+ if (_npf_get_addr(nat_nv, "taddr", &ep.addr[2]) != ep.alen) {
+ goto err;
+ }
+ ep.port[2] = ntohs(nvlist_get_number(nat_nv, "tport"));
}
-
- in_port_t p[] = {
- ntohs(ep.port[0]),
- ntohs(ep.port[1]),
- ntohs(tport)
- };
- (*func)((unsigned)ep.alen, ep.addr, p, ifname, arg);
+ /*
+ * XXX: add 'proto' and 'flow'; perhaps expand and pass the
+ * whole to npf_connpoint_t?
+ */
+ (*func)((unsigned)ep.alen, ep.addr, ep.port, ifname, arg);
err:
return;
}
@@ -1329,6 +1489,7 @@ npf_conn_list(int fd, npf_conn_func_t func, void *arg)
const nvlist_t *conn = conns[i];
npf_conn_handle(conn, func, arg);
}
+ npf_config_destroy(ncf);
return 0;
}
diff --git a/lib/libnpf/npf.h b/lib/libnpf/npf.h
index 19624885536..aab769f0988 100644
--- a/lib/libnpf/npf.h
+++ b/lib/libnpf/npf.h
@@ -84,12 +84,13 @@ nl_config_t * npf_config_import(const void *, size_t);
void * npf_config_export(nl_config_t *, size_t *);
bool npf_config_active_p(nl_config_t *);
bool npf_config_loaded_p(nl_config_t *);
-void * npf_config_build(nl_config_t *);
+const void * npf_config_build(nl_config_t *);
int npf_alg_load(nl_config_t *, const char *);
int npf_param_get(nl_config_t *, const char *, int *);
int npf_param_set(nl_config_t *, const char *, int);
+const char * npf_param_iterate(nl_config_t *, nl_iter_t *, int *, int *);
int npf_ruleset_add(int, const char *, nl_rule_t *, uint64_t *);
int npf_ruleset_remove(int, const char *, uint64_t);