summaryrefslogtreecommitdiff
path: root/lib/libnpf
diff options
context:
space:
mode:
authorrmind <rmind@NetBSD.org>2019-01-19 21:19:31 +0000
committerrmind <rmind@NetBSD.org>2019-01-19 21:19:31 +0000
commit6f4ca96c603ba8a29c8749b17c19d8e0a899433a (patch)
tree3e7e337922d24af7a508ba78a7555f37b7bb26d0 /lib/libnpf
parent88499cef2cf91e79802cf52cba2f90b3160bcf92 (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.3121
-rw-r--r--lib/libnpf/npf.c80
-rw-r--r--lib/libnpf/npf.h20
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 *);