diff options
| author | rmind <rmind@NetBSD.org> | 2019-01-19 21:19:31 +0000 |
|---|---|---|
| committer | rmind <rmind@NetBSD.org> | 2019-01-19 21:19:31 +0000 |
| commit | 6f4ca96c603ba8a29c8749b17c19d8e0a899433a (patch) | |
| tree | 3e7e337922d24af7a508ba78a7555f37b7bb26d0 /lib/libnpf | |
| parent | 88499cef2cf91e79802cf52cba2f90b3160bcf92 (diff) | |
Major NPF improvements:
- Convert NPF connection table to thmap. State lookup is now lock-free.
- Improve connection state G/C: it is now incremental and tunable.
- Add support for dynamic NAT address. Translation addresses can now be
selected from a pool of addresses. There are two selection algorithms,
"ip-hash" and "round-robin" (see the man page).
- Translation address can be specified as e.g. ifaddrs(wm0) in npf.conf
to dynamically choose an IP from the interface address(es).
- Add support for the NETMAP algorithm with static NAT for net-to-net
translation (it is equivalent to iptables NETMAP logic).
- Convert 'ipset' tables to use thmap; the table lookup is now lock-free.
- Misc improvements, bug fixes and more unit tests.
- Bump NPF_VERSION (will also bump libnpf).
Diffstat (limited to 'lib/libnpf')
| -rw-r--r-- | lib/libnpf/libnpf.3 | 121 | ||||
| -rw-r--r-- | lib/libnpf/npf.c | 80 | ||||
| -rw-r--r-- | lib/libnpf/npf.h | 20 |
3 files changed, 155 insertions, 66 deletions
diff --git a/lib/libnpf/libnpf.3 b/lib/libnpf/libnpf.3 index 06ae974ada2..cfb2562050c 100644 --- a/lib/libnpf/libnpf.3 +++ b/lib/libnpf/libnpf.3 @@ -1,6 +1,6 @@ -.\" $NetBSD: libnpf.3,v 1.6 2018/09/29 14:41:36 rmind Exp $ +.\" $NetBSD: libnpf.3,v 1.7 2019/01/19 21:19:31 rmind Exp $ .\" -.\" Copyright (c) 2011-2017 The NetBSD Foundation, Inc. +.\" Copyright (c) 2011-2018 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This material is based upon work partially supported by The @@ -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 June 10, 2018 +.Dd December 29, 2018 .Dt LIBNPF 3 .Os .Sh NAME @@ -43,49 +43,57 @@ .Ft int .Fn npf_config_submit "nl_config_t *ncf" "int fd" "nl_error_t *errinfo" .Ft nl_config_t * -.Fn npf_config_retrieve "int fd" "bool *active" "bool *loaded" +.Fn npf_config_retrieve "int fd" .Ft int .Fn npf_config_flush "int fd" .Ft void -.Fn npf_config_export "const nl_config_t *ncf" "size_t *len" +.Fn npf_config_export "nl_config_t *ncf" "size_t *len" .Ft nl_config_t * .Fn npf_config_import "const void *blob" "size_t len" .Ft bool .Fn npf_config_active_p "nl_config_t *ncf" +.Ft bool +.Fn npf_config_loaded_p "nl_config_t *ncf" .Ft void .Fn npf_config_destroy "nl_config_t *ncf" .\" --- .Ft nl_rule_t * -.Fn npf_rule_create "char *name" "uint32_t attr" "const char *ifname" +.Fn npf_rule_create "const char *name" "uint32_t attr" "const char *ifname" .Ft int .Fn npf_rule_setcode "nl_rule_t *rl" "int type" "const void *code" "size_t len" .Ft int -.Fn npf_rule_setkey "nl_rule_t *rl" "int type" "const void *code" "size_t len" +.Fn npf_rule_setkey "nl_rule_t *rl" "const void *key" "size_t len" .Ft int .Fn npf_rule_setinfo "nl_rule_t *rl" "const void *info" "size_t len" -.Ft bool -.Fn npf_rule_exists_p "nl_config_t *ncf" "const char *name" .Ft int .Fn npf_rule_setprio "nl_rule_t *rl" "int pri" .Ft int -.Fn npf_rule_setproc "nl_config_t *ncf" "nl_rule_t *rl" "const char *name" +.Fn npf_rule_setproc "nl_rule_t *rl" "const char *name" .Ft int .Fn npf_rule_insert "nl_config_t *ncf" "nl_rule_t *parent" "nl_rule_t *rl" +.Ft bool +.Fn npf_rule_exists_p "nl_config_t *ncf" "const char *name" .Ft void * .Fn npf_rule_export "nl_rule_t *rl" "size_t *length" .Ft void .Fn npf_rule_destroy "nl_rule_t *rl" .\" --- .Ft nl_rproc_t * -.Fn npf_rproc_create "char *name" +.Fn npf_rproc_create "const char *name" +.Ft int +.Fn npf_rproc_extcall "nl_rproc_t *rp" "nl_ext_t *ext" .Ft bool .Fn npf_rproc_exists_p "nl_config_t *ncf" "const char *name" .Ft int .Fn npf_rproc_insert "nl_config_t *ncf" "nl_rproc_t *rp" .\" --- .Ft nl_nat_t * -.Fn npf_nat_create "int type" "u_int flags" "const char *ifname" \ -"npf_addr_t *addr" "int af" "in_port_t port" +.Fn npf_nat_create "int type" "unsigned flags" "const char *ifname" +.Ft int +.Fn npf_nat_setaddr "nl_nat_t *nt" "int af" "npf_addr_t *addr" \ +"npf_netmask_t mask" +.Ft int +.Fn npf_nat_setport "nl_nat_t *nt" "in_port_t port" .Ft int .Fn npf_nat_insert "nl_config_t *ncf" "nl_nat_t *nt" "pri_t pri" .\" --- @@ -93,7 +101,7 @@ .Fn npf_table_create "const char *name" "u_int id" "int type" .Ft int .Fn npf_table_add_entry "nl_table_t *tl" "int af" \ -"in_addr_t addr" "in_addr_t mask" +"const npf_addr_t *addr" "const npf_netmask_t mask" .Ft int .Fn npf_table_insert "nl_config_t *ncf" "nl_table_t *tl" .Ft void @@ -118,8 +126,8 @@ to the kernel. On failure, the error information is written into the structure specified by .Fa errinfo . -.It Fn npf_config_export "fd" "len" -Serialize the current configuration and return the binary object as +.It Fn npf_config_export "ncf" "len" +Serialize the given configuration and return the binary object as well as its length in .Fa len parameter. @@ -130,11 +138,14 @@ Read the configuration from a binary object of the specified length, unserialize, and return the configuration object. .It Fn npf_config_flush "fd" Flush the current configuration. -.It Fn npf_config_retrieve "fd" "active" "loaded" +.It Fn npf_config_retrieve "fd" Retrieve and return the loaded configuration from the kernel. .It Fn npf_config_active_p "ncf" -Indicate whether the retrieved configuration is active (true if yes -and false otherwise). +Indicate whether the retrieved configuration is active i.e. packet +filtering is enabled (true if yes and false otherwise). +.It Fn npf_config_loaded_p "ncf" +Indicate whether the retrieved configuration is loaded i.e. has any +rules (true if yes and false otherwise). .It Fn npf_config_destroy "ncf" Destroy the configuration object, specified by .Fa ncf . @@ -143,7 +154,7 @@ Destroy the configuration object, specified by .Ss Rule interface .Bl -tag -width 4n .It Fn npf_rule_create "name" "attr" "ifname" -Create a rule with a given name, attribute and priorty. +Create a rule with a given name, attributes and priority. If the name is specified, then it should be unique within the configuration object. Otherwise, the name can be @@ -208,7 +219,7 @@ Currently, only the BPF byte-code is supported and the .Dv NPF_CODE_BPF constant should be passed. .\" --- -.It Fn npf_rule_setkey "rl" "type" "key" "len" +.It Fn npf_rule_setkey "rl" "key" "len" Assign a key for the rule specified by .Fa rl . The binary key is specified by @@ -245,7 +256,7 @@ beginning or the end of the priority level 0 in the ruleset. All rules inserted using these constants will have the priority 0 assigned and will share this level in the ordered way. .\" --- -.It Fn npf_rule_setproc "ncf" "rl" "name" +.It Fn npf_rule_setproc "rl" "name" Set a procedure for the specified rule. .\" --- .It Fn npf_rule_insert "ncf" "parent" "rl" @@ -258,6 +269,9 @@ is then insert into the main ruleset. The rule 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. +.\" --- .It Fn npf_rule_export "rl" "length" Serialize the rule (including the byte-code), return a binary object and set its @@ -282,7 +296,7 @@ The rule procedure must not be referenced after insertion. .\" ----- .Ss Translation interface .Bl -tag -width 4n -.It Fn npf_nat_create "type" "flags" "ifname" "addr" "af" "port" +.It Fn npf_nat_create "type" "flags" "ifname" Create a NAT policy of a specified type. There are two types: .Bl -tag -width "NPF_NAT_PORTMAP " @@ -315,7 +329,11 @@ This flag is effective only if the flag is set. .El .Pp -The translation address is specified by +The network interface on which the policy will be applicable is specified by +.Fa ifname . +.\" --- +.It Fn npf_nat_setaddr "nt" "af" "addr" "mask" +Set the translation address, as specified by .Fa addr , and its family by .Fa af . @@ -324,12 +342,36 @@ The family must be either for IPv4 or .Dv AF_INET6 for IPv6 address. +Additionally, +.Fa mask +may be specified to indicate the translation network. +In such case, a custom algorithm may need to be specified using the +.Fn npf_nat_setalgo +function. +.\" --- +.It Fn npf_nat_setport "nt" "port" +Set the translation port, specified by +.Fa port . .\" --- .It Fn npf_nat_setalgo "nt" "algo" Set a particular NAT algorithm. -Currently, only -.Dv NPF_ALGO_NPT66 -algorithm is supported for NPTv6 (RFC 6296). +Currently, the following algorithms are supported with dynamic NAT: +.Bl -tag -width "NPF_ALGO_IPHASH" +.It Dv NPF_ALGO_IPHASH +Hash of the source and destination addresses. +.It Dv NPF_ALGO_RR +Round-robin for the translation addresses. +.El +.Pp +The following are support with static NAT: +.Bl -tag -width "NPF_ALGO_NETMAP" +.It Dv NPF_ALGO_NETMAP +Network-to-network map where the translation network prefix (address +after applying the mask) is bitwise OR-ed with the host part of the +original address (zero bits of the mask). +.It Dv NPF_ALGO_NPT66 +IPv6-to-IPv6 Network Prefix Translation (NPTv6, defined in RFC 6296). +.El .\" --- .It Fn npf_nat_insert "ncf" "nt" "pri" Insert NAT policy, its rule, into the specified configuration. @@ -348,17 +390,20 @@ which should be in the range between 1 and .Dv NPF_MAX_TABLES . .Pp The following types are supported: -.Bl -tag -width "NPF_TABLE_HASH" -.It Dv NPF_TABLE_HASH -Indicates to use a hash table for storage. -.It Dv NPF_TABLE_TREE -Indicates to use a tree for storage, supporting the longest -prefix match. -.It Dv NPF_TABLE_CDB -Indicates to use constant database for storage, typically using -a perfect hash table, which will be generated on table insertion -into the configuration. -Such table will be immutable. +.Bl -tag -width "NPF_TABLE_IPSET" +.It Dv NPF_TABLE_IPSET +Indicates to use a regular associative array for storage of IP sets. +Currently implemented as a hashmap. +.It Dv NPF_TABLE_LPM +Indicates to the table can contain networks (as well as hosts) and the +longest prefix match should be performed on lookup. +.It Dv NPF_TABLE_CONST +Indicates that the table contents will be constant and the table can be +considered immutable (no inserts/removes after load). +If such constraint is acceptable, this table type will provide the best +performance. +It is currently implemented as a perfect hash table, generated on table +insertion into the configuration. .El .\" --- .It Fn npf_table_add_entry "tl" "af" "addr" "mask" diff --git a/lib/libnpf/npf.c b/lib/libnpf/npf.c index 3f07608e342..1dde754c160 100644 --- a/lib/libnpf/npf.c +++ b/lib/libnpf/npf.c @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.44 2018/09/29 14:41:36 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.45 2019/01/19 21:19:31 rmind Exp $"); #include <sys/types.h> #include <sys/mman.h> @@ -736,8 +736,7 @@ npf_rproc_getname(nl_rproc_t *rp) */ nl_nat_t * -npf_nat_create(int type, unsigned flags, const char *ifname, - int af, npf_addr_t *addr, npf_netmask_t mask, in_port_t port) +npf_nat_create(int type, unsigned flags, const char *ifname) { nl_rule_t *rl; nvlist_t *rule_dict; @@ -756,17 +755,6 @@ npf_nat_create(int type, unsigned flags, const char *ifname, /* Translation type and flags. */ nvlist_add_number(rule_dict, "type", type); nvlist_add_number(rule_dict, "flags", flags); - - /* Translation IP and mask. */ - if (!_npf_add_addr(rule_dict, "nat-ip", af, addr)) { - npf_rule_destroy(rl); - return NULL; - } - nvlist_add_number(rule_dict, "nat-mask", (uint32_t)mask); - - /* Translation port (for redirect case). */ - nvlist_add_number(rule_dict, "nat-port", port); - return (nl_nat_t *)rl; } @@ -788,6 +776,32 @@ npf_nat_iterate(nl_config_t *ncf) } int +npf_nat_setaddr(nl_nat_t *nt, int af, npf_addr_t *addr, npf_netmask_t mask) +{ + /* Translation IP and mask. */ + if (!_npf_add_addr(nt->rule_dict, "nat-ip", af, addr)) { + return nvlist_error(nt->rule_dict); + } + nvlist_add_number(nt->rule_dict, "nat-mask", (uint32_t)mask); + return nvlist_error(nt->rule_dict); +} + +int +npf_nat_setport(nl_nat_t *nt, in_port_t port) +{ + /* Translation port (for redirect case). */ + nvlist_add_number(nt->rule_dict, "nat-port", port); + return nvlist_error(nt->rule_dict); +} + +int +npf_nat_settable(nl_nat_t *nt, unsigned tid) +{ + nvlist_add_number(nt->rule_dict, "nat-table-id", tid); + return nvlist_error(nt->rule_dict); +} + +int npf_nat_setalgo(nl_nat_t *nt, unsigned algo) { nvlist_add_number(nt->rule_dict, "nat-algo", algo); @@ -818,12 +832,38 @@ npf_nat_getflags(nl_nat_t *nt) return dnvlist_get_number(nt->rule_dict, "flags", 0); } -void -npf_nat_getmap(nl_nat_t *nt, npf_addr_t *addr, size_t *alen, in_port_t *port) +unsigned +npf_nat_getalgo(nl_nat_t *nt) +{ + return dnvlist_get_number(nt->rule_dict, "nat-algo", 0); +} + +const npf_addr_t * +npf_nat_getaddr(nl_nat_t *nt, size_t *alen, npf_netmask_t *mask) +{ + const void *data; + + if (nvlist_exists(nt->rule_dict, "nat-ip")) { + data = nvlist_get_binary(nt->rule_dict, "nat-ip", alen); + *mask = nvlist_get_number(nt->rule_dict, "nat-mask"); + } else { + data = NULL; + *alen = 0; + *mask = NPF_NO_NETMASK; + } + return data; +} + +in_port_t +npf_nat_getport(nl_nat_t *nt) +{ + return (uint16_t)dnvlist_get_number(nt->rule_dict, "nat-port", 0); +} + +unsigned +npf_nat_gettable(nl_nat_t *nt) { - const void *data = nvlist_get_binary(nt->rule_dict, "nat-ip", alen); - memcpy(addr, data, *alen); - *port = (uint16_t)dnvlist_get_number(nt->rule_dict, "nat-port", 0); + return dnvlist_get_number(nt->rule_dict, "nat-table-id", 0); } /* @@ -969,7 +1009,7 @@ npf_table_insert(nl_config_t *ncf, nl_table_t *tl) if (_npf_dataset_lookup(ncf->ncf_dict, "tables", "name", name)) { return EEXIST; } - if (dnvlist_get_number(tl->table_dict, "type", 0) == NPF_TABLE_CDB) { + if (dnvlist_get_number(tl->table_dict, "type", 0) == NPF_TABLE_CONST) { if ((error = _npf_table_build(tl)) != 0) { return error; } diff --git a/lib/libnpf/npf.h b/lib/libnpf/npf.h index 6c62c58dbae..77f8b9e38cc 100644 --- a/lib/libnpf/npf.h +++ b/lib/libnpf/npf.h @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011-2014 The NetBSD Foundation, Inc. + * Copyright (c) 2011-2018 The NetBSD Foundation, Inc. * All rights reserved. * * This material is based upon work partially supported by The @@ -77,7 +77,7 @@ int npf_ruleset_remove(int, const char *, uint64_t); int npf_ruleset_remkey(int, const char *, const void *, size_t); int npf_ruleset_flush(int, const char *); -nl_ext_t * npf_ext_construct(const char *name); +nl_ext_t * npf_ext_construct(const char *); void npf_ext_param_u32(nl_ext_t *, const char *, uint32_t); void npf_ext_param_bool(nl_ext_t *, const char *, bool); void npf_ext_param_string(nl_ext_t *, const char *, const char *); @@ -98,10 +98,14 @@ int npf_rproc_extcall(nl_rproc_t *, nl_ext_t *); bool npf_rproc_exists_p(nl_config_t *, const char *); int npf_rproc_insert(nl_config_t *, nl_rproc_t *); -nl_nat_t * npf_nat_create(int, unsigned, const char *, - int, npf_addr_t *, npf_netmask_t, in_port_t); +nl_nat_t * npf_nat_create(int, unsigned, const char *); int npf_nat_insert(nl_config_t *, nl_nat_t *, int); int npf_nat_lookup(int, int, npf_addr_t *[2], in_port_t [2], int, int); +int npf_nat_setaddr(nl_nat_t *, int, npf_addr_t *, npf_netmask_t); +int npf_nat_setport(nl_nat_t *, in_port_t); +int npf_nat_settable(nl_nat_t *, unsigned); +int npf_nat_setalgo(nl_nat_t *, unsigned); +int npf_nat_setnpt66(nl_nat_t *, uint16_t); nl_table_t * npf_table_create(const char *, unsigned, int); int npf_table_add_entry(nl_table_t *, int, @@ -130,10 +134,10 @@ int npf_table_gettype(nl_table_t *); nl_nat_t * npf_nat_iterate(nl_config_t *); int npf_nat_gettype(nl_nat_t *); unsigned npf_nat_getflags(nl_nat_t *); -void npf_nat_getmap(nl_nat_t *, npf_addr_t *, size_t *, in_port_t *); - -int npf_nat_setalgo(nl_nat_t *, unsigned); -int npf_nat_setnpt66(nl_nat_t *, uint16_t); +const npf_addr_t *npf_nat_getaddr(nl_nat_t *, size_t *, npf_netmask_t *); +in_port_t npf_nat_getport(nl_nat_t *); +unsigned npf_nat_gettable(nl_nat_t *); +unsigned npf_nat_getalgo(nl_nat_t *); nl_rproc_t * npf_rproc_iterate(nl_config_t *); const char * npf_rproc_getname(nl_rproc_t *); |
