diff options
| author | martin <martin@NetBSD.org> | 2020-06-20 15:46:47 +0000 |
|---|---|---|
| committer | martin <martin@NetBSD.org> | 2020-06-20 15:46:47 +0000 |
| commit | b19d58aad73c1adb8001858747a19d45bc8be0f9 (patch) | |
| tree | 9fe3f3431c7c5bed82411881629567d181b19097 /lib | |
| parent | 7d79e88db64cfbb1537b720c0a32d0c76aafaaa6 (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.3 | 16 | ||||
| -rw-r--r-- | lib/libnpf/npf.c | 403 | ||||
| -rw-r--r-- | lib/libnpf/npf.h | 3 |
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); |
