]> git.ipfire.org Git - thirdparty/nftables.git/log
thirdparty/nftables.git
9 months agobuild: Bump version to 1.0.8 v1.0.8
Pablo Neira Ayuso [Thu, 13 Jul 2023 08:57:04 +0000 (10:57 +0200)] 
build: Bump version to 1.0.8

Update dependency on libnftnl >= 1.2.6 which contains support for
meta broute.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9 months agoinclude: missing dccpopt.h breaks make distcheck
Pablo Neira Ayuso [Fri, 14 Jul 2023 09:34:43 +0000 (11:34 +0200)] 
include: missing dccpopt.h breaks make distcheck

Add it to Makefile.am.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9 months agoImplement 'reset {set,map,element}' commands
Phil Sutter [Thu, 15 Jun 2023 13:24:28 +0000 (15:24 +0200)] 
Implement 'reset {set,map,element}' commands

All these are used to reset state in set/map elements, i.e. reset the
timeout or zero quota and counter values.

While 'reset element' expects a (list of) elements to be specified which
should be reset, 'reset set/map' will reset all elements in the given
set/map.

Signed-off-by: Phil Sutter <phil@nwl.cc>
9 months agoevaluate: Cache looked up set for list commands
Phil Sutter [Wed, 14 Jun 2023 15:40:02 +0000 (17:40 +0200)] 
evaluate: Cache looked up set for list commands

Evaluation phase checks the given table and set exist in cache. Relieve
execution phase from having to perform the lookup again by storing the
set reference in cmd->set. Just have to increase the ref counter so
cmd_free() does the right thing (which lacked handling of MAP and METER
objects for some reason).

Signed-off-by: Phil Sutter <phil@nwl.cc>
9 months agoevaluate: Merge some cases in cmd_evaluate_list()
Phil Sutter [Wed, 14 Jun 2023 13:32:04 +0000 (15:32 +0200)] 
evaluate: Merge some cases in cmd_evaluate_list()

The code for set, map and meter were almost identical apart from the
specific last check. Fold them together and make the distinction in that
spot only.

Signed-off-by: Phil Sutter <phil@nwl.cc>
9 months agotests: shell: cover old scanner bug
Pablo Neira Ayuso [Tue, 11 Jul 2023 15:00:51 +0000 (17:00 +0200)] 
tests: shell: cover old scanner bug

Add a test to cover 423abaa40ec4 ("scanner: don't rely on fseek for
input stream repositioning") that fixes the bug described in
https://bugs.gentoo.org/675188.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9 months agolibnftables: drop check for nf_sock in nft_ctx_free()
Thomas Haller [Mon, 10 Jul 2023 08:45:19 +0000 (10:45 +0200)] 
libnftables: drop check for nf_sock in nft_ctx_free()

The "nft_ctx" API does not provide a way to change or reconnect the
netlink socket. And none of the users would rely on that.

Also note that nft_ctx_new() initializes nf_sock via
nft_mnl_socket_open(), which panics of the socket could not be
initialized.

This means, the check is unnecessary and needlessly confusing. Drop it.

Signed-off-by: Thomas Haller <thaller@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9 months agolibnftables: inline creation of nf_sock in nft_ctx_new()
Thomas Haller [Mon, 10 Jul 2023 08:45:18 +0000 (10:45 +0200)] 
libnftables: inline creation of nf_sock in nft_ctx_new()

The function only has one caller. It's not clear how to extend this in a
useful way, so that it makes sense to keep the initialization in a
separate function.

Simplify the code, by inlining and dropping the static function
nft_ctx_netlink_init(). There was only one caller.

Signed-off-by: Thomas Haller <thaller@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9 months agolibnftables: drop unused argument nf_sock from nft_netlink()
Thomas Haller [Mon, 10 Jul 2023 08:45:17 +0000 (10:45 +0200)] 
libnftables: drop unused argument nf_sock from nft_netlink()

Signed-off-by: Thomas Haller <thaller@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
9 months agolibnftables: always initialize netlink socket in nft_ctx_new()
Thomas Haller [Mon, 10 Jul 2023 08:45:16 +0000 (10:45 +0200)] 
libnftables: always initialize netlink socket in nft_ctx_new()

nft_ctx_new() has a flags argument, but currently no flags are
supported. The documentation suggests to pass 0 (NFT_CTX_DEFAULT).

Initializing the netlink socket happens by default already, we should do
it for all flags. Also because  nft_ctx_netlink_init() is not public
API so it's not clear how the user gets a functioning context instance
otherwise.

If we ever want to not initialize the netlink socket for a context
instance, then there should be a dedicated flag for doing that (and
additional API for making that mode of operation usable).

Signed-off-by: Thomas Haller <thaller@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agoevaluate: place byteorder conversion before rshift in payload statement
Pablo Neira Ayuso [Fri, 7 Jul 2023 21:40:19 +0000 (23:40 +0200)] 
evaluate: place byteorder conversion before rshift in payload statement

For bitfield that spans more than one byte, such as ip6 dscp, byteorder
conversion needs to be done before rshift. Add unary expression for this
conversion only in the case of meta and ct statements.

Before this patch:

 # nft --debug=netlink add rule ip6 x y 'meta mark set ip6 dscp'
 ip6 x y
  [ payload load 2b @ network header + 0 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
  [ byteorder reg 1 = ntoh(reg 1, 2, 2) ] <--------- incorrect
  [ meta set mark with reg 1 ]

After this patch:

 # nft --debug=netlink add rule ip6 x y 'meta mark set ip6 dscp'
 ip6 x y
  [ payload load 2b @ network header + 0 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
  [ byteorder reg 1 = ntoh(reg 1, 2, 2) ] <-------- correct
  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
  [ meta set mark with reg 1 ]

For the matching case, binary transfer already deals with the rshift to
adjust left and right hand side of the expression, the unary conversion
is not needed in such case.

Fixes: 8221d86e616b ("tests: py: add test-cases for ct and packet mark payload expressions")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agonetlink_linearize: use div_round_up in byteorder length
Pablo Neira Ayuso [Thu, 6 Jul 2023 08:26:39 +0000 (10:26 +0200)] 
netlink_linearize: use div_round_up in byteorder length

Use div_round_up() to calculate the byteorder length, otherwise fields
that take % BITS_PER_BYTE != 0 are not considered by the byteorder
expression.

Reported-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agotests: shell: Introduce valgrind mode
Phil Sutter [Wed, 14 Jun 2023 18:01:46 +0000 (20:01 +0200)] 
tests: shell: Introduce valgrind mode

Pass flag '-V' to run-tests.sh to run all 'nft' invocations in valgrind
leak checking environment. Code copied from iptables' shell-testsuite
where it proved to be useful already.

Signed-off-by: Phil Sutter <phil@nwl.cc>
10 months agocli: Make cli_init() return to caller
Phil Sutter [Wed, 21 Jun 2023 23:10:59 +0000 (01:10 +0200)] 
cli: Make cli_init() return to caller

Avoid direct exit() calls as that leaves the caller-allocated nft_ctx
object in place. Making sure it is freed helps with valgrind-analyses at
least.

To signal desired exit from CLI, introduce global cli_quit boolean and
make all cli_exit() implementations also set cli_rc variable to the
appropriate return code.

The logic is to finish CLI only if cli_quit is true which asserts proper
cleanup as it is set only by the respective cli_exit() function.

Signed-off-by: Phil Sutter <phil@nwl.cc>
10 months agomain: Call nft_ctx_free() before exiting
Phil Sutter [Wed, 21 Jun 2023 22:51:40 +0000 (00:51 +0200)] 
main: Call nft_ctx_free() before exiting

Introduce labels for failure and regular exit so all direct exit() calls
after nft_ctx allocation may be replaced by a single goto statement.

Simply drop that return call in interactive branch, code will continue
at 'out' label naturally.

Signed-off-by: Phil Sutter <phil@nwl.cc>
10 months agomain: Make 'buf' variable branch-local
Phil Sutter [Wed, 21 Jun 2023 22:46:53 +0000 (00:46 +0200)] 
main: Make 'buf' variable branch-local

It is used only to linearize non-option argv for passing to
nft_run_cmd_from_buffer(), reduce its scope. Allows to safely move the
free() call there, too.

Signed-off-by: Phil Sutter <phil@nwl.cc>
10 months agotests: shell: refcount memleak in map rhs with timeouts
Pablo Neira Ayuso [Mon, 3 Jul 2023 22:50:34 +0000 (00:50 +0200)] 
tests: shell: refcount memleak in map rhs with timeouts

Extend coverage for refcount leaks on map element expiration.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agoexpression: define .clone for catchall set element
Pablo Neira Ayuso [Fri, 30 Jun 2023 07:42:11 +0000 (09:42 +0200)] 
expression: define .clone for catchall set element

Otherwise reuse of catchall set element expression in variable triggers
a null-pointer dereference.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agotests: py: Document JSON mode in README
Phil Sutter [Tue, 27 Jun 2023 15:50:07 +0000 (17:50 +0200)] 
tests: py: Document JSON mode in README

Mostly identify the various files that (may) appear or exist already and
how to deal with them.

Signed-off-by: Phil Sutter <phil@nwl.cc>
10 months agotests: shell: cover refcount leak of mapping rhs
Pablo Neira Ayuso [Tue, 27 Jun 2023 12:12:53 +0000 (14:12 +0200)] 
tests: shell: cover refcount leak of mapping rhs

Add a test to cover reference count leak in maps by adding twice
same element, then flush.

Reported-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agotests: shell: coverage for simple port knocking ruleset
Pablo Neira Ayuso [Mon, 26 Jun 2023 06:15:29 +0000 (08:15 +0200)] 
tests: shell: coverage for simple port knocking ruleset

Add a test to cover port knocking simple ruleset.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agotests: json: add missing/expected json output
Florian Westphal [Sat, 24 Jun 2023 17:14:35 +0000 (19:14 +0200)] 
tests: json: add missing/expected json output

nft-test.py generates following warning:
any/last.t: WARNING: line 12: '{"nftables": [{"add": {"rule": {"family": "ip", "table": "test-ip4", "chain": "input", "expr": [{"last": {"used": 300000}}]}}}]}': '[{"last": {"used": 300000}}]' mismatches '[{"last": null}]'

This is because "last" expression is stateful; but nft-test.py
explicitly asks for stateless output.

Thus we need to provide a json.output file, without it,
nft-test.py uses last.json as the expected output file.

Fixes: ae8786756b0c ("src: add json support for last statement")
Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agosrc: avoid IPPROTO_MAX for array definitions
Florian Westphal [Tue, 20 Jun 2023 19:52:13 +0000 (21:52 +0200)] 
src: avoid IPPROTO_MAX for array definitions

ip header can only accomodate 8but value, but IPPROTO_MAX has been bumped
due to uapi reasons to support MPTCP (262, which is used to toggle on
multipath support in tcp).

This results in:
exthdr.c:349:11: warning: result of comparison of constant 263 with expression of type 'uint8_t' (aka 'unsigned char') is always true [-Wtautological-constant-out-of-range-compare]
if (type < array_size(exthdr_protocols))
            ~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

redude array sizes back to what can be used on-wire.

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agoct timeout: fix 'list object x' vs. 'list objects in table' confusion
Florian Westphal [Mon, 19 Jun 2023 20:43:06 +0000 (22:43 +0200)] 
ct timeout: fix 'list object x' vs. 'list objects in table' confusion

<empty ruleset>
$ nft list ct timeout table t
Error: No such file or directory
list ct timeout table t
                      ^
This is expected to list all 'ct timeout' objects.
The failure is correct, the table 't' does not exist.

But now lets add one:
$ nft add table t
$ nft list ct timeout  table t
Segmentation fault (core dumped)

... and thats not expected, nothing should be shown
and nft should exit normally.

Because of missing TIMEOUTS command enum, the backend thinks
it should do an object lookup, but as frontend asked for
'list of objects' rather than 'show this object',
handle.obj.name is NULL, which then results in this crash.

Update the command enums so that backend knows what the
frontend asked for.

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agoparser: reject zero-length interface names in flowtables
Florian Westphal [Mon, 19 Jun 2023 20:43:05 +0000 (22:43 +0200)] 
parser: reject zero-length interface names in flowtables

Previous patch wasn't enough, also disable this for flowtable device lists.

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agoparser: reject zero-length interface names
Florian Westphal [Mon, 19 Jun 2023 20:43:04 +0000 (22:43 +0200)] 
parser: reject zero-length interface names

device "" results in an assertion during evaluation.
Before:
nft: expression.c:426: constant_expr_alloc: Assertion `(((len) + (8) - 1) / (8)) > 0' failed.
After:
zero_length_devicename_assert:3:42-49: Error: you cannot set an empty interface name
type filter hook ingress device""lo" priority -1
                         ^^^^^^^^
Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agoparser: don't assert on scope underflows
Florian Westphal [Mon, 19 Jun 2023 20:43:03 +0000 (22:43 +0200)] 
parser: don't assert on scope underflows

close_scope() gets called from the object destructors;
imbalance can cause us to hit assert().

Before:
nft: parser_bison.y:88: close_scope: Assertion `state->scope > 0' failed.
After:
assertion3:4:7-7: Error: too many levels of nesting jump {
assertion3:5:8-8: Error: too many levels of nesting jump
assertion3:5:9-9: Error: syntax error, unexpected newline, expecting '{'
assertion3:7:1-1: Error: syntax error, unexpected end of file

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agoevaluate: do not abort when prefix map has non-map element
Florian Westphal [Mon, 19 Jun 2023 20:43:02 +0000 (22:43 +0200)] 
evaluate: do not abort when prefix map has non-map element

Before:
nft: evaluate.c:1849: __mapping_expr_expand: Assertion `i->etype == EXPR_MAPPING' failed.

after:
Error: expected mapping, not set element
   snat ip prefix to ip saddr map { 10.141.11.0/24 : 192.168.2.0/24, 10.141.12.1 }

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agojson: dccp: remove erroneous const qualifier
Florian Westphal [Mon, 19 Jun 2023 20:43:01 +0000 (22:43 +0200)] 
json: dccp: remove erroneous const qualifier

This causes a clang warning:

parser_json.c:767:6: warning: variable 'opt_type' is uninitialized when used here [-Wuninitialized]
if (opt_type < DCCPOPT_TYPE_MIN || opt_type > DCCPOPT_TYPE_MAX) {
            ^~~~~~~~
... because it deduces the object is readonly.

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agojson: add inner payload support
Pablo Neira Ayuso [Tue, 20 Jun 2023 10:57:56 +0000 (12:57 +0200)] 
json: add inner payload support

Add support for vxlan, geneve, gre and gretap.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agosrc: add json support for last statement
Pablo Neira Ayuso [Tue, 20 Jun 2023 09:45:53 +0000 (11:45 +0200)] 
src: add json support for last statement

This patch adds json support for the last statement, it works for me here.

However, tests/py still displays a warning:

any/last.t: WARNING: line 12: '{"nftables": [{"add": {"rule": {"family": "ip", "table": "test-ip4", "chain": "input", "expr": [{"last": {"used": 300000}}]}}}]}': '[{"last": {"used": 300000}}]' mismatches '[{"last": null}]'

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agocache: include set elements in "nft set list"
Florian Westphal [Sun, 18 Jun 2023 16:39:45 +0000 (18:39 +0200)] 
cache: include set elements in "nft set list"

Make "nft list sets" include set elements in listing by default.
In nftables 1.0.0, "nft list sets" did not include the set elements,
but with "--json" they were included.

1.0.1 and newer never include them.
This causes a problem for people updating from 1.0.0 and relying
on the presence of the set elements.

Change nftables to always include the set elements.
The "--terse" option is honored to get the "no elements" behaviour.

Fixes: a1a6b0a5c3c4 ("cache: finer grain cache population for list commands")
Link: https://marc.info/?l=netfilter&m=168704941828372&w=2
Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agotests: shell: bogus EBUSY errors in transactions
Pablo Neira Ayuso [Wed, 14 Jun 2023 08:38:08 +0000 (10:38 +0200)] 
tests: shell: bogus EBUSY errors in transactions

Make sure reference tracking during transaction update is correct by
checking for bogus EBUSY error. For example, when deleting map with
chain reference X, followed by a delete chain X command.

This test is covering the following paths:

- prepare + abort (via -c/--check option)
- prepare + commit
- release (when netns is destroyed)

Reported-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
10 months agotests: shell: add test case for chain-in-use-splat
Florian Westphal [Mon, 12 Jun 2023 10:33:43 +0000 (12:33 +0200)] 
tests: shell: add test case for chain-in-use-splat

WARNING [.]: at net/netfilter/nf_tables_api.c:1885
6.3.4-201.fc38.x86_64 #1
nft_immediate_destroy+0xc1/0xd0 [nf_tables]
__nf_tables_abort+0x4b9/0xb20 [nf_tables]
nf_tables_abort+0x39/0x50 [nf_tables]
nfnetlink_rcv_batch+0x47c/0x8e0 [nfnetlink]
nfnetlink_rcv+0x179/0x1a0 [nfnetlink]
netlink_unicast+0x19e/0x290

This is because of chain->use underflow, at time destroy
function is called, ->use has wrapped back to -1.

Fixed via
"netfilter: nf_tables: fix chain binding transaction logic".

Signed-off-by: Florian Westphal <fw@strlen.de>
10 months agotests: shell: fix spurious errors in terse listing in json
Pablo Neira Ayuso [Sun, 11 Jun 2023 19:13:38 +0000 (21:13 +0200)] 
tests: shell: fix spurious errors in terse listing in json

Sometimes table handle becomes 192, which makes this test fail. Check
for 192.168 instead to make sure terse listing works fine instead.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agoexthdr: add boolean DCCP option matching
Jeremy Sowden [Tue, 11 Apr 2023 20:45:34 +0000 (21:45 +0100)] 
exthdr: add boolean DCCP option matching

Iptables supports the matching of DCCP packets based on the presence
or absence of DCCP options.  Extend exthdr expressions to add this
functionality to nftables.

Link: https://bugzilla.netfilter.org/show_bug.cgi?id=930
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agotests: extend tests for destroy command
Fernando Fernandez Mancera [Sat, 27 May 2023 16:24:24 +0000 (18:24 +0200)] 
tests: extend tests for destroy command

Extend tests to cover destroy command for chains, flowtables, sets,
maps. In addition rename a destroy command test for rules with a
duplicated number.

Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agosrc: permit use of constant values in set lookup keys
Florian Westphal [Wed, 24 May 2023 11:25:22 +0000 (13:25 +0200)] 
src: permit use of constant values in set lookup keys

Something like:

Given: set s { type ipv4_addr . ipv4_addr . inet_service .. } something
like
   add rule ip saddr . 1.2.3.4 . 80 @s goto c1

fails with: "Error: Can't parse symbolic invalid expressions".

This fails because the relational expression first evaluates
the left hand side, so when concat evaluation sees '1.2.3.4'
no key context is available.

Check if the RHS is a set reference, and, if so, evaluate
the right hand side.

This sets a pointer to the set key in the evaluation context
structure which then makes the concat evaluation step parse
1.2.3.4 and 80 as ipv4 address and 16bit port number.

On delinearization, extend relop postprocessing to
copy the datatype from the rhs (set reference, has
proper datatype according to set->key) to the lhs (concat
expression).

Signed-off-by: Florian Westphal <fw@strlen.de>
11 months agomnl: support bpf id decode in nft list hooks
Florian Westphal [Tue, 16 May 2023 16:24:29 +0000 (18:24 +0200)] 
mnl: support bpf id decode in nft list hooks

This allows 'nft list hooks' to also display the bpf program id
attached.  Example:

hook input {
  -0000000128 nf_hook_run_bpf id 6
  ..

Signed-off-by: Florian Westphal <fw@strlen.de>
11 months agoevaluate: set NFT_SET_EVAL flag if dynamic set already exists
Pablo Neira Ayuso [Thu, 18 May 2023 12:40:38 +0000 (14:40 +0200)] 
evaluate: set NFT_SET_EVAL flag if dynamic set already exists

nft reports EEXIST when reading an existing set whose NFT_SET_EVAL has
been previously inferred from the ruleset.

 # cat test.nft
 table ip test {
        set dlist {
                type ipv4_addr
                size 65535
        }

        chain output {
                type filter hook output priority filter; policy accept;
                udp dport 1234 update @dlist { ip daddr } counter packets 0 bytes 0
        }
 }
 # nft -f test.nft
 # nft -f test.nft
 test.nft:2:6-10: Error: Could not process rule: File exists
         set dlist {
             ^^^^^

Phil Sutter says:

In the first call, the set lacking 'dynamic' flag does not exist
and is therefore added to the cache. Consequently, both the 'add set'
command and the set statement point at the same set object. In the
second call, a set with same name exists already, so the object created
for 'add set' command is not added to cache and consequently not updated
with the missing flag. The kernel thus rejects the NEWSET request as the
existing set differs from the new one.

Set on the NFT_SET_EVAL flag if the existing set sets it on.

Fixes: 8d443adfcc8c1 ("evaluate: attempt to set_eval flag if dynamic updates requested")
Tested-by: Eric Garver <eric@garver.life>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agodatatype: add hint error handler
Pablo Neira Ayuso [Tue, 9 May 2023 15:46:54 +0000 (17:46 +0200)] 
datatype: add hint error handler

If user provides a symbol that cannot be parsed and the datatype provides
an error handler, provide a hint through the misspell infrastructure.

For instance:

 # cat test.nft
 table ip x {
        map y {
                typeof ip saddr : verdict
                elements = { 1.2.3.4 : filter_server1 }
        }
 }
 # nft -f test.nft
 test.nft:4:26-39: Error: Could not parse netfilter verdict; did you mean `jump filter_server1'?
                 elements = { 1.2.3.4 : filter_server1 }
                                        ^^^^^^^^^^^^^^

While at it, normalize error to "Could not parse symbolic %s expression".

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agodatatype: misspell support with symbol table parser for error reporting
Pablo Neira Ayuso [Tue, 9 May 2023 15:46:52 +0000 (17:46 +0200)] 
datatype: misspell support with symbol table parser for error reporting

Some datatypes provide a symbol table that is parsed as an integer.
Improve error reporting by using the misspell infrastructure, to provide
a hint to the user, whenever possible.

If base datatype, usually the integer datatype, fails to parse the
symbol, then try a fuzzy match on the symbol table to provide a hint
in case the user has mistype it.

For instance:

 test.nft:3:11-14: Error: Could not parse Differentiated Services Code Point expression; did you you mean `cs0`?
                 ip dscp ccs0
                         ^^^^

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agooptimize: do not remove counter in verdict maps
Pablo Neira Ayuso [Sun, 7 May 2023 17:54:30 +0000 (19:54 +0200)] 
optimize: do not remove counter in verdict maps

Add counter to set element instead of dropping it:

 # nft -c -o -f test.nft
 Merging:
 test.nft:6:3-50:              ip saddr 1.1.1.1 ip daddr 2.2.2.2 counter accept
 test.nft:7:3-48:              ip saddr 1.1.1.2 ip daddr 3.3.3.3 counter drop
 into:
       ip daddr . ip saddr vmap { 2.2.2.2 . 1.1.1.1 counter : accept, 3.3.3.3 . 1.1.1.2 counter : drop }

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agoevaluate: skip optimization if anonymous set uses stateful statement
Pablo Neira Ayuso [Sun, 7 May 2023 17:34:19 +0000 (19:34 +0200)] 
evaluate: skip optimization if anonymous set uses stateful statement

fee6bda06403 ("evaluate: remove anon sets with exactly one element")
introduces an optimization to remove use of sets with single element.
Skip this optimization if set element contains stateful statements.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
11 months agoevaluate: allow stateful statements with anonymous verdict maps
Pablo Neira Ayuso [Sun, 7 May 2023 17:30:46 +0000 (19:30 +0200)] 
evaluate: allow stateful statements with anonymous verdict maps

Evaluation fails to accept stateful statements in verdict maps, relax
the following check for anonymous sets:

test.nft:4:29-35: Error: missing statement in map declaration
                ip saddr vmap { 127.0.0.1 counter : drop, * counter : accept }
                                          ^^^^^^^

The existing code generates correctly the counter in the anonymous
verdict map.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agonetlink: restore typeof interval map data type
Florian Westphal [Mon, 1 May 2023 16:51:19 +0000 (18:51 +0200)] 
netlink: restore typeof interval map data type

When "typeof ... : interval ..." gets used, existing logic
failed to validate the expressions.

"interval" means that kernel reserves twice the size,
so consider this when validating and restoring.

Also fix up the dump file of the existing test
case to be symmetrical.

Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agodoc: add nat examples
Florian Westphal [Mon, 1 May 2023 10:10:09 +0000 (12:10 +0200)] 
doc: add nat examples

nftables nat is much more capable than what the existing
documentation describes.

In particular, nftables can fully emulate iptables
NETMAP target and can perform n:m address mapping.

Add a new example section extracted from commit log
messages when those features got added.

Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agodoc: list set/map flag keywords in a table
Florian Westphal [Mon, 1 May 2023 10:09:44 +0000 (12:09 +0200)] 
doc: list set/map flag keywords in a table

add descriptions of the set/map flags.

Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agometa: introduce meta broute support
Sriram Yagnaraman [Sun, 26 Feb 2023 09:52:04 +0000 (10:52 +0100)] 
meta: introduce meta broute support

Can be used in bridge prerouting hook to divert a packet
to the ip stack for routing.

This is a replacement for "ebtables -t broute" functionality.

Link: https://patchwork.ozlabs.org/project/netfilter-devel/patch/20230224095251.11249-1-sriram.yagnaraman@est.tech/
Signed-off-by: Sriram Yagnaraman <sriram.yagnaraman@est.tech>
Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agodoc: correct NAT statement description
Jeremy Sowden [Sun, 5 Mar 2023 10:14:16 +0000 (10:14 +0000)] 
doc: correct NAT statement description

Specifying a port specifies that a port, not an address, should be
modified.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agojson: formatting fixes
Jeremy Sowden [Sun, 5 Mar 2023 10:14:14 +0000 (10:14 +0000)] 
json: formatting fixes

A few indentation tweaks for the JSON parser.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agosrc: fix enum/integer mismatches
Florian Westphal [Sat, 29 Apr 2023 13:48:09 +0000 (15:48 +0200)] 
src: fix enum/integer mismatches

gcc 13 complains about type confusion:
cache.c:1178:5: warning: conflicting types for 'nft_cache_update' due to enum/integer mismatch;
have 'int(struct nft_ctx *, unsigned int,  struct list_head *, const struct nft_cache_filter *)' [-Wenum-int-mismatch]
cache.h:74:5: note: previous declaration of 'nft_cache_update' with type 'int(struct nft_ctx *, enum cmd_ops,  struct list_head *, const struct nft_cache_filter *)'

Same for:
rule.c:1915:13: warning: conflicting types for 'obj_type_name' due to enum/integer mismatch; have 'const char *(enum stmt_types)' [-Wenum-int-mismatch]
 1915 | const char *obj_type_name(enum stmt_types type)
      |             ^~~~~~~~~~~~~
expression.c:1543:24: warning: conflicting types for 'expr_ops_by_type' due to enum/integer mismatch; have 'const struct expr_ops *(uint32_t)' {aka 'const struct expr_ops *(unsigned int)'} [-Wenum-int-mismatch]
 1543 | const struct expr_ops *expr_ops_by_type(uint32_t value)
      |                        ^~~~~~~~~~~~~~~~

Convert to the stricter type (enum) where possible.

Signed-off-by: Florian Westphal <fw@strlen.de>
12 months agotests: py: missing json updates on ct and meta mark payload expression
Pablo Neira Ayuso [Tue, 25 Apr 2023 16:14:07 +0000 (18:14 +0200)] 
tests: py: missing json updates on ct and meta mark payload expression

Add json output, it is missing in the original tests/py update.

Fixes: 8221d86e616b ("tests: py: add test-cases for ct and packet mark payload expressions")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agomnl: incomplete extended error reporting for singleton device in chain
Pablo Neira Ayuso [Tue, 25 Apr 2023 10:37:15 +0000 (12:37 +0200)] 
mnl: incomplete extended error reporting for singleton device in chain

Fix error reporting when single device is specifies in chain:

 # nft add chain netdev filter ingress '{ devices = { x }; }'
 add chain netdev filter ingress { devices = { x }; }
                                               ^

Fixes: a66b5ad9540d ("src: allow for updating devices on existing netdev chain")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agomnl: handle singleton element in netdevice set
Pablo Neira Ayuso [Tue, 25 Apr 2023 09:48:52 +0000 (11:48 +0200)] 
mnl: handle singleton element in netdevice set

expr_evaluate_set() turns sets with singleton element into value,
nft_dev_add() expects a list of expression, so it crashes.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1676
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agojson: allow to specify comment on chain
Pablo Neira Ayuso [Tue, 25 Apr 2023 08:33:22 +0000 (10:33 +0200)] 
json: allow to specify comment on chain

Allow users to add a comment when declaring a chain.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agojson: allow to specify comment on table
Pablo Neira Ayuso [Mon, 24 Apr 2023 21:17:50 +0000 (23:17 +0200)] 
json: allow to specify comment on table

Allow users to add a comment when declaring a table:

 # sudo nft add table inet test3 '{comment "this is a comment";}'
 # nft list ruleset
 table inet test3 {
        comment "this is a comment"
 }
 # nft -j list ruleset
 {"nftables": [{"metainfo": {"version": "1.0.7", "release_name": "Old Doc Yak", "json_schema_version": 1}}, {"table": {"family": "inet", "name": "test3", "handle": 3, "comment": "this is a comment"}}]}
 # nft -j list ruleset > test.json
 # nft flush ruleset
 # nft -j -f test.json
 # nft -j list ruleset
 {"nftables": [{"metainfo": {"version": "1.0.7", "release_name": "Old Doc Yak", "json_schema_version": 1}}, {"table": {"family": "inet", "name": "test3", "handle": 4, "comment": "this is a comment"}}]}

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1670
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agometa: skip protocol context update for nfproto with same table family
Pablo Neira Ayuso [Mon, 24 Apr 2023 20:07:44 +0000 (22:07 +0200)] 
meta: skip protocol context update for nfproto with same table family

Inefficient bytecode crashes ruleset listing:

[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ] <-- this specifies NFPROTO_IPV4 but table family is IPv4!
[ payload load 4b @ network header + 12 => reg 1 ]
[ cmp gte reg 1 0x1000000a ]
[ cmp lte reg 1 0x1f00000a ]
[ masq ]

This IPv4 table obviously only see IPv4 traffic, but bytecode specifies
a redundant match on NFPROTO_IPV4.

After this patch, listing works:

 # nft list ruleset
 table ip crash {
        chain crash {
                type nat hook postrouting priority srcnat; policy accept;
                ip saddr 10.0.0.16-10.0.0.31 masquerade
        }
 }

Skip protocol context update in case that this information is redundant.

Fixes: https://bugzilla.netfilter.org/show_bug.cgi?id=1562
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agoevaluate: bail out if new flowtable does not specify hook and priority
Pablo Neira Ayuso [Thu, 20 Apr 2023 22:37:07 +0000 (00:37 +0200)] 
evaluate: bail out if new flowtable does not specify hook and priority

If user forgets to specify the hook and priority and the flowtable does
not exist, then bail out:

 # cat flowtable-incomplete.nft
 table t {
  flowtable f {
   devices = { lo }
  }
 }
 # nft -f /tmp/k
 flowtable-incomplete.nft:2:12-12: Error: missing hook and priority in flowtable declaration
 flowtable f {
           ^

Update one existing tests/shell to specify a hook and priority.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agosrc: allow for updating devices on existing netdev chain
Pablo Neira Ayuso [Wed, 19 Apr 2023 09:50:01 +0000 (11:50 +0200)] 
src: allow for updating devices on existing netdev chain

This patch allows you to add/remove devices to an existing chain:

 # cat ruleset.nft
 table netdev x {
chain y {
type filter hook ingress devices = { eth0 } priority 0; policy accept;
}
 }
 # nft -f ruleset.nft
 # nft add chain netdev x y '{ devices = { eth1 };  }'
 # nft list ruleset
 table netdev x {
chain y {
type filter hook ingress devices = { eth0, eth1 } priority 0; policy accept;
}
 }
 # nft delete chain netdev x y '{ devices = { eth0 }; }'
 # nft list ruleset
 table netdev x {
chain y {
type filter hook ingress devices = { eth1 } priority 0; policy accept;
}
 }

This feature allows for creating an empty netdev chain, with no devices.
In such case, no packets are seen until a device is registered.

This patch includes extended netlink error reporting:

 # nft add chain netdev x y '{ devices = { x } ; }'
 Error: Could not process rule: No such file or directory
 add chain netdev x y { devices = { x } ; }
                                    ^

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agomnl: flowtable support for extended netlink error reporting
Pablo Neira Ayuso [Wed, 19 Apr 2023 13:38:04 +0000 (15:38 +0200)] 
mnl: flowtable support for extended netlink error reporting

This patch extends existing flowtable support to improve error
reporting:

 # nft add flowtable inet x y '{ devices = { x } ; }'
 Error: Could not process rule: No such file or directory
 add flowtable inet x y { devices = { x } ; }
                                      ^
 # nft delete flowtable inet x y '{ devices = { x } ; }'
 Error: Could not process rule: No such file or directory
 delete flowtable inet x y { devices = { x } ; }
                                         ^
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agomnl: set SO_SNDBUF before SO_SNDBUFFORCE
Pablo Neira Ayuso [Fri, 7 Apr 2023 22:21:57 +0000 (16:21 -0600)] 
mnl: set SO_SNDBUF before SO_SNDBUFFORCE

Set SO_SNDBUF before SO_SNDBUFFORCE: Unpriviledged user namespace does
not have CAP_NET_ADMIN on the host (user_init_ns) namespace.

SO_SNDBUF always succeeds in Linux, always try SO_SNDBUFFORCE after it.

Moreover, suggest the user to bump socket limits if EMSGSIZE after
having see EPERM previously, when calling SO_SNDBUFFORCE.

Provide a hint to the user too:

 # nft -f test.nft
 netlink: Error: Could not process rule: Message too long
 Please, rise /proc/sys/net/core/wmem_max on the host namespace. Hint: 4194304 bytes

Dave Pfike says:

 Prior to this patch, nft inside a systemd-nspawn container was failing
 to install my ruleset (which includes a large-ish map), with the error

 netlink: Error: Could not process rule: Message too long

 strace reveals:

 setsockopt(3, SOL_SOCKET, SO_SNDBUFFORCE, [524288], 4) = -1 EPERM (Operation not permitted)

 This is despite the nspawn process supposedly having CAP_NET_ADMIN.

 A web search reveals at least one other user having the same issue:

 https://old.reddit.com/r/Proxmox/comments/scnoav/lxc_container_debian_11_nftables_geoblocking/

Reported-by: Dave Pifke <dave@pifke.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 months agotests: shell: Fix for unstable sets/0043concatenated_ranges_0
Phil Sutter [Thu, 20 Apr 2023 15:39:27 +0000 (17:39 +0200)] 
tests: shell: Fix for unstable sets/0043concatenated_ranges_0

On my (slow?) testing VM, The test tends to fail when doing a full run
(i.e., calling run-test.sh without arguments) and tends to pass when run
individually.

The problem seems to be the 1s element timeout which in some cases may
pass before element deletion occurs. Simply fix this by doubling the
timeout. It has to pass just once, so shouldn't hurt too much.

Fixes: 618393c6b3f25 ("tests: Introduce test for set with concatenated ranges")
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
12 months agomain: Error out when combining -i/--interactive and -f/--file
Pablo Neira Ayuso [Sat, 8 Apr 2023 18:16:07 +0000 (20:16 +0200)] 
main: Error out when combining -i/--interactive and -f/--file

These two options are mutually exclusive, display error in that case:

 # nft -i -f test.nft
 Error: -i/--interactive and -f/--file options cannot be combined

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agooptimize: support for redirect and masquerade
Pablo Neira Ayuso [Tue, 4 Apr 2023 13:30:21 +0000 (15:30 +0200)] 
optimize: support for redirect and masquerade

The redirect and masquerade statements can be handled as verdicts:

- if redirect statement specifies no ports.
- masquerade statement, in any case.

Exceptions to the rule: If redirect statement specifies ports, then nat
map transformation can be used iif both statements specify ports.

Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1668
Fixes: 0a6dbfce6dc3 ("optimize: merge nat rules with same selectors into map")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agonetlink_delinearize: do not reset protocol context for nat protocol expression
Pablo Neira Ayuso [Tue, 4 Apr 2023 13:34:05 +0000 (15:34 +0200)] 
netlink_delinearize: do not reset protocol context for nat protocol expression

This patch reverts 403b46ada490 ("netlink_delinearize: kill dependency
before eval of 'redirect' stmt"). Since ("evaluate: bogus missing
transport protocol"), this workaround is not required anymore.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: bogus missing transport protocol
Pablo Neira Ayuso [Tue, 4 Apr 2023 13:30:20 +0000 (15:30 +0200)] 
evaluate: bogus missing transport protocol

Users have to specify a transport protocol match such as

meta l4proto tcp

before the redirect statement, even if the redirect statement already
implicitly refers to the transport protocol, for instance:

test.nft:3:16-53: Error: transport protocol mapping is only valid after transport protocol match
                redirect to :tcp dport map { 83 : 8083, 84 : 8084 }
                ~~~~~~~~     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Evaluate the redirect expression before the mandatory check for the
transport protocol match, so protocol context already provides a
transport protocol.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agooptimize: assert nat type on nat statement helper
Pablo Neira Ayuso [Tue, 4 Apr 2023 13:30:16 +0000 (15:30 +0200)] 
optimize: assert nat type on nat statement helper

Add assert() to helper function to expression from NAT statement.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoxt: Fix translation error path
Phil Sutter [Tue, 28 Mar 2023 11:46:10 +0000 (13:46 +0200)] 
xt: Fix translation error path

If xtables support was compiled in but the required libxtables DSO is
not found, nft prints an error message and leaks memory:

| counter packets 0 bytes 0 XT target MASQUERADE not found

This is not as bad as it seems, the output combines stdout and stderr.
Dropping stderr produces an incomplete ruleset listing, though. While
this seemingly inline output can't easily be avoided, fix a few things:

* Respect octx->error_fp, libnftables might have been configured to
  redirect stderr somewhere else.
* Align error message formatting with others.
* Don't return immediately, but free allocated memory and fall back to
  printing the expression in "untranslated" form.

Fixes: 5c30feeee5cfe ("xt: Delay libxtables access until translation")
Signed-off-by: Phil Sutter <phil@nwl.cc>
13 months agonetlink_delinearize: correct type and byte-order of shifts
Jeremy Sowden [Thu, 23 Mar 2023 16:58:44 +0000 (17:58 +0100)] 
netlink_delinearize: correct type and byte-order of shifts

Downgrade to base type integer instead of the specific type from the
expression that is used in the shift operation.

Without this, listing a rule like:

  ct mark set ip dscp lshift 2 or 0x10

will return:

  ct mark set ip dscp << 2 | cs2

because the type of the OR's right operand will be transitively derived
from `ip dscp`.  However, this is not valid syntax:

  # nft add rule t c ct mark set ip dscp '<<' 2 '|' cs2
  Error: Could not parse integer
  add rule t c ct mark set ip dscp << 2 | cs2
                                          ^^^

Use xinteger_type to print the output in hexadecimal.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agointervals: use expression location when translating to intervals
Pablo Neira Ayuso [Mon, 27 Mar 2023 14:36:31 +0000 (16:36 +0200)] 
intervals: use expression location when translating to intervals

Otherwise, internal location reports:

 # nft -f ruleset.nft
 internal:0:0-0: Error: Could not process rule: File exists

after this patch:

 # nft -f ruleset.nft
 ruleset.nft:402:1-16: Error: Could not process rule: File exists
 1.2.3.0/30,
 ^^^^^^^^^^^

Fixes: 81e36530fcac ("src: replace interval segment tree overlap and automerge")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agopayload: set byteorder when completing expression
Pablo Neira Ayuso [Thu, 23 Mar 2023 09:42:58 +0000 (10:42 +0100)] 
payload: set byteorder when completing expression

Otherwise payload expression remains in invalid byteorder which is
handled as network byteorder for historical reason.

No functional change is intended.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agotests: py: extend test-cases for mark statements with bitwise expressions
Pablo Neira Ayuso [Thu, 23 Mar 2023 12:50:35 +0000 (13:50 +0100)] 
tests: py: extend test-cases for mark statements with bitwise expressions

Add more tests to cover bitwise operation. Shift operations are used on
constant value which are reduced at evaluation time.

Shift takes precendence over AND and OR operations, otherwise use parens
to override this.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agotests: shell: add test-cases for ct and packet mark payload expressions
Jeremy Sowden [Fri, 17 Mar 2023 09:16:54 +0000 (10:16 +0100)] 
tests: shell: add test-cases for ct and packet mark payload expressions

Add new test-cases to verify that defining a rule that sets the ct or
packet mark to a value derived from a payload works correctly.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agotests: shell: rename and move bitwise test-cases
Jeremy Sowden [Fri, 17 Mar 2023 09:16:50 +0000 (10:16 +0100)] 
tests: shell: rename and move bitwise test-cases

The `0040mark_shift_?` tests are testing not just shifts, but binops
more generally, so name them accordingly.

Move them to a new folder specifically for bitwise operations.

Change the priorities of the chains to match the type.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agotests: py: add test-cases for ct and packet mark payload expressions
Jeremy Sowden [Fri, 17 Mar 2023 09:16:48 +0000 (10:16 +0100)] 
tests: py: add test-cases for ct and packet mark payload expressions

Add new test-cases to verify that defining a rule that sets the ct or
packet mark to a value derived from a payload works correctly.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agonetlink_delinerize: incorrect byteorder in mark statement listing
Pablo Neira Ayuso [Thu, 23 Mar 2023 12:23:34 +0000 (13:23 +0100)] 
netlink_delinerize: incorrect byteorder in mark statement listing

When using ip dscp in combination with bitwise operation:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp | 0x4'
 ip x y
   [ payload load 1b @ network header + 1 => reg 1 ]
   [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
   [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
   [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ]
   [ ct set mark with reg 1 ]

the listing is showing in the incorrect byteorder:

 # nft list ruleset
 table ip x {
        chain y {
ct mark set ip dscp | 0x4000000
}
 }

handle and and or operations in host byteorder.

The following command:

 # nft --debug=netlink add rule ip6 x y 'ct mark set ip6 dscp | 0x4'
 ip6 x y
   [ payload load 2b @ network header + 0 => reg 1 ]
   [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
   [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
   [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
   [ bitwise reg 1 = ( reg 1 & 0xfffffffb ) ^ 0x00000004 ]
   [ ct set mark with reg 1 ]

works fine (without requiring this patch) because there is an explicit
byteorder expression.

However, ip dscp takes only 1-byte, so it does not require the byteorder
expression. Use host byteorder if the rhs of bitwise AND OR is larger
than lhs payload expression and such expression is equal or less than
1-byte.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: honor statement length in bitwise evaluation
Pablo Neira Ayuso [Fri, 17 Mar 2023 09:16:45 +0000 (10:16 +0100)] 
evaluate: honor statement length in bitwise evaluation

Get length from statement, instead infering it from the expression that
is used to set the value. In the particular case of {ct|meta} mark, this
is 32 bits.

Otherwise, bytecode generation is not correct:

 # nft -c --debug=netlink 'add rule ip6 x y ct mark set ip6 dscp << 2 | 0x10'
  [ payload load 2b @ network header + 0 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]
  [ bitwise reg 1 = ( reg 1 << 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x00000fef ) ^ 0x00000010 ]    <--- incorrect!
  [ ct set mark with reg 1 ]

the previous bitwise shift already upgraded to 32-bits (not visible from
the netlink debug output above).

After this patch, the last | 0x10 uses 32-bits:

 [ bitwise reg 1 = ( reg 1 & 0xffffffef ) ^ 0x00000010 ]

note that mask 0xffffffef is used instead of 0x00000fef.

Patch ("evaluate: support shifts larger than the width of the left operand")
provides the statement length through eval context. Use it to evaluate the
bitwise expression accordingly, otherwise bytecode is incorrect:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1 | 0xff000000'
 ip x y
  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x1e000000 ) ^ 0x000000ff ]  <-- incorrect byteorder for OR
  [ byteorder reg 1 = ntoh(reg 1, 4, 4) ]    <-- no needed for single ip dscp byte
  [ ct set mark with reg 1 ]

Correct bytecode:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1 | 0xff000000
 ip x y
  [ payload load 1b @ network header + 1 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x000000fc ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000002 ) ]
  [ bitwise reg 1 = ( reg 1 & 0x0000001e ) ^ 0xff000000 ]
  [ ct set mark with reg 1 ]

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: honor statement length in integer evaluation
Pablo Neira Ayuso [Thu, 23 Mar 2023 11:52:39 +0000 (12:52 +0100)] 
evaluate: honor statement length in integer evaluation

Otherwise, bogus error is reported:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1 | 0xff000000'
 Error: Value 4278190080 exceeds valid range 0-63
 add rule ip x y ct mark set ip dscp & 0x0f << 1 | 0xff000000
                                                   ^^^^^^^^^^

Use the statement length as the maximum value in the mark statement
expression.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: set up integer type to shift expression
Pablo Neira Ayuso [Thu, 23 Mar 2023 11:36:08 +0000 (12:36 +0100)] 
evaluate: set up integer type to shift expression

Otherwise expr_evaluate_value() fails with invalid datatype:

 # nft --debug=netlink add rule ip x y 'ct mark set ip dscp & 0x0f << 1'
 BUG: invalid basetype invalid
 nft: evaluate.c:440: expr_evaluate_value: Assertion `0' failed.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: relax type-checking for integer arguments in mark statements
Pablo Neira Ayuso [Fri, 17 Mar 2023 09:16:46 +0000 (10:16 +0100)] 
evaluate: relax type-checking for integer arguments in mark statements

In order to be able to set ct and meta marks to values derived from
payload expressions, we need to relax the requirement that the type of
the statement argument must match that of the statement key.  Instead,
we require that the base-type of the argument is integer and that the
argument is small enough to fit.

Moreover, swap expression byteorder before to make it compatible with
the statement byteorder, to ensure rulesets are portable.

 # nft --debug=netlink add rule ip t c 'meta mark set ip saddr'
 ip t c
  [ payload load 4b @ network header + 12 => reg 1 ]
  [ byteorder reg 1 = ntoh(reg 1, 4, 4) ] <----------- byteorder swap
  [ meta set mark with reg 1 ]

Based on original work from Jeremy Sowden.

The following patches are required for this to work:

evaluate: get length from statement instead of lhs expression
evaluate: don't eval unary arguments
evaluate: support shifts larger than the width of the left operand
netlink_delinearize: correct type and byte-order of shifts
evaluate: insert byte-order conversions for expressions between 9 and 15 bits

Add one testcase for tests/py.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: don't eval unary arguments
Jeremy Sowden [Fri, 17 Mar 2023 09:16:43 +0000 (10:16 +0100)] 
evaluate: don't eval unary arguments

When a unary expression is inserted to implement a byte-order
conversion, the expression being converted has already been evaluated
and so `expr_evaluate_unary` doesn't need to do so.

This is required by {ct|meta} statements with bitwise operations, which
might result in byteorder conversion of the expression.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoevaluate: support shifts larger than the width of the left operand
Pablo Neira Ayuso [Fri, 17 Mar 2023 09:16:40 +0000 (10:16 +0100)] 
evaluate: support shifts larger than the width of the left operand

If we want to left-shift a value of narrower type and assign the result
to a variable of a wider type, we are constrained to only shifting up to
the width of the narrower type.  Thus:

  add rule t c meta mark set ip dscp << 2

works, but:

  add rule t c meta mark set ip dscp << 8

does not, even though the lvalue is large enough to accommodate the
result.

Upgrade the maximum length based on the statement datatype length, which
is provided via context, if it is larger than expression lvalue.

Update netlink_delinearize.c to handle the case where the length of a
shift expression does not match that of its left-hand operand.

Based on patch from Jeremy Sowden.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agometa: don't crash if meta key isn't known
Florian Westphal [Wed, 15 Mar 2023 12:57:38 +0000 (13:57 +0100)] 
meta: don't crash if meta key isn't known

If older nft version is used for dumping, 'key' might be
outside of the range of known templates.

Signed-off-by: Florian Westphal <fw@strlen.de>
13 months agoevaluate: insert byte-order conversions for expressions between 9 and 15 bits
Jeremy Sowden [Fri, 17 Mar 2023 09:16:36 +0000 (10:16 +0100)] 
evaluate: insert byte-order conversions for expressions between 9 and 15 bits

Round up expression lengths when determining whether to insert a
byte-order conversion.  For example, if one is masking a network header
which spans a byte boundary, the mask will span two bytes and so it will
need to be in NBO.

Fixes: bb03cbcd18a1 ("evaluate: no need to swap byte-order for values of fewer than 16 bits.")
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoAvoid a memleak with 'reset rules' command
Phil Sutter [Mon, 20 Mar 2023 09:03:13 +0000 (10:03 +0100)] 
Avoid a memleak with 'reset rules' command

Like other 'reset' commands, 'reset rules' also lists the (part of the)
ruleset which was affected to give users a chance to store the zeroed
values. Therefore do_command_reset() calls do_command_list(). This in
turn calls do_list_ruleset() for CMD_OBJ_RULES which wasn't prepared for
values stored in cmd->handle other than a possible family value and thus
freely reused the pointers as scratch area for the do_list_table() call
whiich in the past fetched each table's data directly from kernel.

Meanwhile ruleset listing code has been integrated into the common
caching logic, the 'cmd' pointer became unused by do_list_table(). The
temporary cmd->handle manipulation is not needed anymore, dropping it
prevents a memleak caused by overwriting of allocated table name
pointer.

Fixes: 1694df2de79f3 ("Implement 'reset rule' and 'reset rules' commands")
Signed-off-by: Phil Sutter <phil@nwl.cc>
13 months agoReduce signature of do_list_table()
Phil Sutter [Mon, 20 Mar 2023 08:58:29 +0000 (09:58 +0100)] 
Reduce signature of do_list_table()

Since commit 16fac7d11bdf5 ("src: use cache infrastructure for rule
objects"), the function does not use the passed 'cmd' object anymore.
Remove it to affirm correctness of a follow-up fix and simplification in
do_list_ruleset().

Signed-off-by: Phil Sutter <phil@nwl.cc>
13 months agopy: replace distutils with setuptools
Jose M. Guisado Gomez [Wed, 22 Feb 2023 10:20:55 +0000 (11:20 +0100)] 
py: replace distutils with setuptools

Removes a deprecation warning when using distutils and python >=3.10.

Python distutils module is formally marked as deprecated since python
3.10 and will be removed from the standard library from Python 3.12.
(https://peps.python.org/pep-0632/)

From https://setuptools.pypa.io/en/latest/setuptools.html

"""
Packages built and distributed using setuptools look to the user like
ordinary Python packages based on the distutils.
"""

Signed-off-by: Jose M. Guisado Gomez <guigom@riseup.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
13 months agoparser_bison: simplify reset syntax
Pablo Neira Ayuso [Tue, 14 Mar 2023 13:56:18 +0000 (14:56 +0100)] 
parser_bison: simplify reset syntax

Simplify:

*reset rules* *chain* ['family'] 'table' ['chain]'
to
*reset rules* ['family'] 'table' 'chain'

*reset rules* *table* ['family'] 'table'
to
*reset rules* ['family'] 'table'

*reset counters* ['family'] *table* 'table'
to
*reset counters* ['family'] 'table'

*reset quotas* ['family'] *table* 'table'
to
*reset quotas* ['family'] 'table'

Previous syntax remains in place for backward compatibility.

Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoRevert "evaluate: relax type-checking for integer arguments in mark statements"
Pablo Neira Ayuso [Tue, 14 Mar 2023 09:29:59 +0000 (10:29 +0100)] 
Revert "evaluate: relax type-checking for integer arguments in mark statements"

This patch reverts eab3eb7f146c ("evaluate: relax type-checking for
integer arguments in mark statements") since it might cause ruleset
portability issues when moving a ruleset from little to big endian
host (and vice-versa).

Let's revert this until we agree on what to do in this case.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agobuild: Bump version to 1.0.7 v1.0.7
Pablo Neira Ayuso [Mon, 13 Mar 2023 13:58:58 +0000 (14:58 +0100)] 
build: Bump version to 1.0.7

Update dependency on libnftnl >= 1.2.5 which contains support for inner
header matching.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agosrc: fix a couple of typo's in comments
Jeremy Sowden [Sun, 12 Mar 2023 20:27:10 +0000 (20:27 +0000)] 
src: fix a couple of typo's in comments

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
13 months agocmd: move command functions to src/cmd.c
Pablo Neira Ayuso [Fri, 10 Mar 2023 18:40:34 +0000 (19:40 +0100)] 
cmd: move command functions to src/cmd.c

Move several command functions to src/cmd.c to debloat src/rule.c

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agosrc: improve error reporting for unsupported chain type
Pablo Neira Ayuso [Fri, 10 Mar 2023 18:20:50 +0000 (19:20 +0100)] 
src: improve error reporting for unsupported chain type

8c75d3a16960 ("Reject invalid chain priority values in user space")
provides error reporting from the evaluation phase. Instead, this patch
infers the error after the kernel reports EOPNOTSUPP.

test.nft:3:28-40: Error: Chains of type "nat" must have a priority value above -200
                type nat hook prerouting priority -300;
                                         ^^^^^^^^^^^^^

This patch also adds another common issue for users compiling their own
kernels if they forget to enable CONFIG_NFT_NAT in their .config file.

Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
13 months agoReject invalid chain priority values in user space
Phil Sutter [Thu, 9 Mar 2023 23:52:15 +0000 (00:52 +0100)] 
Reject invalid chain priority values in user space

The kernel doesn't accept nat type chains with a priority of -200 or
below. Catch this and provide a better error message than the kernel's
EOPNOTSUPP.

Signed-off-by: Phil Sutter <phil@nwl.cc>
13 months agoxt: Fix fallback printing for extensions matching keywords
Phil Sutter [Thu, 9 Mar 2023 13:31:31 +0000 (14:31 +0100)] 
xt: Fix fallback printing for extensions matching keywords

Yet another Bison workaround: Instead of the fancy error message, an
incomprehensible syntax error is emitted:

| # iptables-nft -A FORWARD -p tcp -m osf --genre linux
| # nft list ruleset | nft -f -
| # Warning: table ip filter is managed by iptables-nft, do not touch!
| /dev/stdin:4:29-31: Error: syntax error, unexpected osf, expecting string
|  meta l4proto tcp xt match osf counter packets 0 bytes 0
|                            ^^^

Avoid this by quoting the extension name when printing:

| # nft list ruleset | sudo ./src/nft -f -
| # Warning: table ip filter is managed by iptables-nft, do not touch!
| /dev/stdin:4:20-33: Error: unsupported xtables compat expression, use iptables-nft with this ruleset
|  meta l4proto tcp xt match "osf" counter packets 0 bytes 0
|                   ^^^^^^^^^^^^^^

Fixes: 79195a8cc9e9d ("xt: Rewrite unsupported compat expression dumping")
Fixes: e41c53ca5b043 ("xt: Fall back to generic printing from translation")
Signed-off-by: Phil Sutter <phil@nwl.cc>
13 months agodoc: nft.8: Document lower priority limit for nat type chains
Phil Sutter [Thu, 9 Mar 2023 13:44:21 +0000 (14:44 +0100)] 
doc: nft.8: Document lower priority limit for nat type chains

Users can't know the magic limit.

Signed-off-by: Phil Sutter <phil@nwl.cc>
14 months agotests: shell: use bash in 0011reset_0
Pablo Neira Ayuso [Wed, 1 Mar 2023 10:59:32 +0000 (11:59 +0100)] 
tests: shell: use bash in 0011reset_0

One of my boxes does not use bash as /bin/sh, update this test to
explicitly use bash, otherwise I hit:

  testcases/rule_management/0011reset_0: 71: Syntax error: "(" unexpected

Fixes: 1694df2de79f ("Implement 'reset rule' and 'reset rules' commands")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
14 months agocache: fetch more objects when resetting rule
Pablo Neira Ayuso [Wed, 1 Mar 2023 10:58:22 +0000 (11:58 +0100)] 
cache: fetch more objects when resetting rule

If the ruleset contains a reference to object, listing fails. The
existing test for the new reset command displays the following error:

 # ./run-tests.sh testcases/rule_management/0011reset_0
 I: using nft command: ./../../src/nft

 W: [FAILED]     testcases/rule_management/0011reset_0: got 2
 loading ruleset
 resetting specific rule
 netlink: Error: Unknown set 's' in dynset statement

Fixes: 1694df2de79f ("Implement 'reset rule' and 'reset rules' commands")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
14 months agoparser_bison: allow to use quota in sets
Pablo Neira Ayuso [Wed, 1 Mar 2023 10:12:20 +0000 (11:12 +0100)] 
parser_bison: allow to use quota in sets

src: support for restoring element quota

This patch allows you to restore quota in dynamic sets.

 table ip x {
        set y {
                type ipv4_addr
                size 65535
                flags dynamic,timeout
                counter quota 500 bytes
                timeout 1h
                elements = { 8.8.8.8 counter packets 9 bytes 756 quota 500 bytes used 500 bytes timeout 1h expires 56m57s47ms }
        }

        chain z {
                type filter hook output priority filter; policy accept;
                update @y { ip daddr } counter packets 6 bytes 507
        }
 }

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>