summaryrefslogtreecommitdiffstats
path: root/iptables/nft-shared.c
Commit message (Collapse)AuthorAgeFilesLines
* nft: Make rule parsing errors fatalPhil Sutter2022-12-201-1/+3
| | | | | | | Finish parsing the rule, thereby printing all potential problems and abort the program. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Increase rule parser strictnessPhil Sutter2022-12-201-10/+25
| | | | | | Catch more unexpected conditions. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Parse icmp header matchesPhil Sutter2022-12-201-0/+74
| | | | | | These were previously ignored. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Recognize INVAL/D interface namePhil Sutter2022-12-021-0/+19
| | | | | | | | It is just a hack to translate '! -i +' into a never matching nft rule, but recognize it anyway for completeness' sake and to make xlate replay test pass. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix match generator for '! -i +'Phil Sutter2022-12-021-0/+6
| | | | | | | | | | | | | It's actually nonsense since it will never match, but iptables accepts it and the resulting nftables rule must behave identically. Reuse the solution implemented into xtables-translate (by commit e179e87a1179e) and turn the above match into 'iifname INVAL/D'. The commit this fixes merely ignored the fact that "any interface" match might be inverted. Fixes: 0a8635183edd0 ("xtables-compat: ignore '+' interface name") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix for comparing ifname matches against nft-generated onesPhil Sutter2022-12-021-1/+1
| | | | | | | | | Since nft adds the interface name as fixed-size string of 16 bytes, filling a mask based on the length value will not match the mask nft set. Fixes: 652b98e793711 ("xtables-compat: fix wildcard detection") Signed-off-by: Phil Sutter <phil@nwl.cc>
* xtables: Introduce xtables_clear_iptables_command_state()Phil Sutter2022-12-021-14/+0
| | | | | | | | | | This is nft_clear_iptables_command_state() but in a location reachable by legacy iptables, too. Changes callers in non-family-specific code to use clear_cs callback instead of directly calling it - ebtables still has a custom variant. Signed-off-by: Phil Sutter <phil@nwl.cc>
* iptables-nft: exit nonzero when iptables-save cannot decode all expressionsFlorian Westphal2022-11-231-3/+7
| | | | | | | | | | | | We always return 0, even if we printed some error message half-way. Increment an error counter whenever an error message was printed so that the chain-loop can exit with an error if this counter is nonzero. Another effect is that iptables-save will no longer print the COMMIT line anmore. Reported-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Phil Sutter <phil@nwl.cc>
* nft-shared: replace nftnl_expr_get_data() by nftnl_expr_get()Pablo Neira Ayuso2022-11-151-1/+1
| | | | | | | Replace nftnl_expr_get_data() alias by real function call. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft-shared: Introduce port_match_single_to_range()Phil Sutter2022-11-151-93/+37
| | | | | | | The same algorithm was present four times, outsource it. Also use max()/min() macros for a more readable boundary notation. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix meta statement parsingPhil Sutter2022-09-281-5/+9
| | | | | | | | | | | | The function nft_meta_set_to_target() would always bail since nothing sets 'sreg->meta_sreg.set' to true. This is obvious, as the immediate expression "filling" the source register does not indicate its purpose. The whole source register purpose storing in meta_sreg seems to be pointless, so drop it altogether. Fixes: f315af1cf8871 ("nft: track each register individually") Signed-off-by: Phil Sutter <phil@nwl.cc>
* ebtables: Fix among matchPhil Sutter2022-09-281-0/+16
| | | | | | | | | | | | | | | | | | Fixed commit broke among match in two ways: 1) The two lookup sizes are 12 and 6, not 12 and 4 - among supports either ether+IP or ether only, not IP only. 2) Adding two to sreg_count to get the second register is too simple: It works only for four byte regs, not the 16 byte ones. The first register is always a 16 byte one, though. Fixing (1) is trivial, fix (2) by introduction of nft_get_next_reg() doing the right thing. For consistency, use it for among match creation, too. Fixes: f315af1cf8871 ("nft: track each register individually") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft-shared: Introduce __get_cmp_data()Phil Sutter2022-09-281-7/+10
| | | | | | | This is an inner function to get_cmp_data() returning the op value as-is for caller examination. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: track each register individuallyFlorian Westphal2022-09-281-61/+144
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of assuming only one register is used, track all 16 regs individually. This avoids need for the 'PREV_PAYLOAD' hack and also avoids the need to clear out old flags: When we see that register 'x' will be written to, that register state is reset automatically. Existing dissector decodes ip saddr 1.2.3.4 meta l4proto tcp ... as -s 6.0.0.0 -p tcp iptables-nft -s 1.2.3.4 -p tcp is decoded correctly because the expressions are ordered like: meta l4proto tcp ip saddr 1.2.3.4 | ... and 'meta l4proto' did clear the PAYLOAD flag. The simpler fix is: ctx->flags &= ~NFT_XT_CTX_PAYLOAD; in nft_parse_cmp(), but that breaks dissection of '1-42', because the second compare ('cmp lte 42') will not find the payload expression anymore. Link: https://lore.kernel.org/netfilter-devel/20220922143544.GA22541@breakpoint.cc/T/#t Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Phil Sutter <phil@nwl.cc>
* nft: support ttl/hoplimit dissectionFlorian Westphal2022-09-131-0/+68
| | | | | | | xlate raw "nft ... ttl eq 1" and so on to the ttl/hl matches. Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Phil Sutter <phil@nwl.cc>
* nft: support dissection of meta pkktype modeFlorian Westphal2022-09-081-0/+25
| | | | | | | Makes iptables-nft-save dump 'nft meta pkttype' rules. Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Phil Sutter <phil@nwl.cc>
* nft: Exit if nftnl_alloc_expr failsPhil Sutter2022-06-211-15/+16
| | | | | | | | | | In some code-paths, 'reg' pointer remaining uninitialized is used later so at least minimal error checking is necessary. Given that a call to nftnl_alloc_expr() with sane argument should never fail, complain and exit if it happens. Fixes: 7e38890c6b4fb ("nft: prepare for dynamic register allocation") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: prepare for dynamic register allocationPablo Neira Ayuso2022-05-021-38/+61
| | | | | | | | | Store the register that has been allocated and pass it on to the next expression. NFT_REG_1 is still used. No functional changes are expected. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: pass handle to helper functions to build netlink payloadPablo Neira Ayuso2022-05-021-13/+18
| | | | | | | Pass struct nft_handle to helper functions in preparation for the dynamic register allocation. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: native mark matching supportPablo Neira Ayuso2022-05-021-0/+36
| | | | | | Use meta mark + bitwise + cmp instead of nft_compat mark match. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: pass struct nft_xt_ctx to parse_meta()Pablo Neira Ayuso2022-05-021-3/+3
| | | | | | In preparation for native mark match support. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft-shared: update context register for bitwise expressionPablo Neira Ayuso2022-05-021-0/+2
| | | | | | | | Update the destination register, otherwise nft_parse_cmp() gives up on interpreting the cmp expression when bitwise sreg != dreg. Fixes: 2c4a34c30cb4 ("iptables-compat: fix address prefix") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Don't pass command state opaque to family ops callbacksPhil Sutter2022-03-101-13/+10
| | | | | | | | | | | There are no family-specific versions of struct iptables_command_state anymore, so no need to hide it behind void pointer. Pass the type as-is and save a few casts. While at it, drop unused callbacks parse_bitwise and parse_cmp. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft: Speed up immediate parsingPhil Sutter2022-03-101-19/+18
| | | | | | | | | | | | | | | | | | | | | | | | | Parsing of rules which jump to a chain pointlessly causes a call to xtables_find_target() despite the code already knowing the outcome. Avoid the significant delay for rulesets with many chain jumps by performing the (standard) target lookup only for accept/drop/return verdicts. From a biased test-case on my VM: | # iptables-nft-save | grep -c -- '-j' | 133943 | # time ./old/iptables-nft-save >/dev/null | real 0m45.566s | user 0m1.308s | sys 0m8.430s | # time ./new/iptables-nft-save >/dev/null | real 0m3.547s | user 0m0.762s | sys 0m2.476s Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft: Simplify immediate parsingPhil Sutter2022-03-101-10/+7
| | | | | | | | | | Implementations of parse_immediate callback are mostly trivial, the only relevant part is access to family-specific parts of struct iptables_command_state when setting goto flag for iptables and ip6tables. Refactor them into simple set_goto_flag callbacks. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft-shared: add tcp flag dissectionFlorian Westphal2022-01-291-0/+26
| | | | | | | Detect payload load of th->flags and convert it to xt tcp match structure. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft-shared: support native udp port delinearizeFlorian Westphal2022-01-291-4/+121
| | | | | | same as previous patch, but for udp. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft-shared: support native tcp port range delinearizeFlorian Westphal2022-01-291-1/+114
| | | | | | | adds support for nft ... tcp dport != min-max Signed-off-by: Florian Westphal <fw@strlen.de>
* nft-shared: support native tcp port delinearizeFlorian Westphal2022-01-291-2/+176
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This extends iptables-nft dissector to decode native tcp port matching. nft ruleset: table ip filter { chain INPUT { type filter hook input priority filter; policy accept; tcp sport 12345 tcp sport 12345 tcp dport 6789 tcp sport < 1024 tcp dport >= 1024 } } $ iptables-nft-save -A INPUT -p tcp -m tcp --sport 12345 -A INPUT -p tcp -m tcp --sport 12345 --dport 6789 -A INPUT -p tcp -m tcp --sport 0:1023 -A INPUT -p tcp -m tcp --dport 1024:65535 This would allow to extend iptables-nft to prefer native payload expressions for --sport,dport in the future. Also, parse_cmp must not clear the "payload" flag, this is because cmp-based range expressions will contain following sequence: payload => reg1 cmp reg1 > minv cmp reg1 < maxv ... so second cmp would work. Signed-off-by: Florian Westphal <fw@strlen.de>
* extensions: libxt_NFLOG: don't truncate log prefix on print/saveKyle Bowman2022-01-181-0/+52
| | | | | | | | | | | | | | | | | | | | | | | | When parsing the rule, use a struct with a layout compatible to that of struct xt_nflog_info, but with a buffer large enough to contain the whole 128-character nft prefix. We always send the nflog-group to the kernel since, for nft, log and nflog targets are handled by the same kernel module, and are distinguished by whether they define an nflog-group. Therefore, we must send the group even if it is zero, or the kernel will configure the target as a log, not an nflog. Changes to nft_is_expr_compatible were made since only targets which have an `nflog-group` are compatible. Since nflog targets are distinguished by having an nflog-group, we ignore targets without one. We also set the copy-len flag if the snap-len is set since without this, iptables will mistake `nflog-size` for `nflog-range`. Signed-off-by: Kyle Bowman <kbowman@cloudflare.com> Signed-off-by: Alex Forster <aforster@cloudflare.com> Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Florian Westphal <fw@strlen.de>
* nft-shared: set correct register valueFlorian Westphal2021-12-231-1/+1
| | | | | | | | | | | NFTNL_EXPR_META_DREG equals NFTNL_EXPR_PAYLOAD_BASE, so we set dreg to the payload base instead. It "works" because the simple nft rules currently generated via ipables-nft have base == register-number but this is a coincidence. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft-shared: Drop unused function print_proto()Phil Sutter2021-11-231-15/+0
| | | | | | | | | The last users vanished back in 2013. There is identical code in save_rule_details(), but with only a single user there's not much point in keeping the function. Fixes: cdc78b1d6bd7b ("nft: convert rule into a command state structure") Signed-off-by: Phil Sutter <phil@nwl.cc>
* xshared: Share print_header() with legacy iptablesPhil Sutter2021-11-231-44/+0
| | | | | | | | | | | | | | | Legacy iptables fetches the relevant data via libiptc before calling the shared routine which merely prints data as requested. Drop the 'basechain' parameter, instead make sure a policy name is passed only with base chains. Since the function is not shared with ebtables (which uses a very rudimental header instead), this is safe. In order to support legacy iptables' checking of iptc_get_references() return code (printing an error message instead of the reference count), make refs parameter signed and print the error message if it's negative. Signed-off-by: Phil Sutter <phil@nwl.cc>
* xshared: Share print_rule_details() with legacyPhil Sutter2021-11-231-27/+0
| | | | | | | | | | Have to pass pointer to counters directly since different fields are being used for some reason. Since proto_to_name() is not used outside of xshared.c anymore, make it static. Signed-off-by: Phil Sutter <phil@nwl.cc>
* xshared: Share save_rule_details() with legacyPhil Sutter2021-11-231-29/+0
| | | | | | | | | | The function combines printing of input and output interfaces and protocol parameter, all being IP family independent. Extend the function to print fragment option ('-f'), too if requested. While being at it, drop unused iptables_command_state parameter and reorder the remaining ones a bit. Signed-off-by: Phil Sutter <phil@nwl.cc>
* xshared: Share print_iface() functionPhil Sutter2021-11-231-24/+2
| | | | | | | | | | | Merge the three identical copies into one and name it 'save_iface' (as the printed syntax is for "save"-format). Leave arptables alone for now, its rather complicated whitespace printing doesn't allow for use of the shared function. Also keep ebtables' custom implementation, it is used for the --logical-in/--logical-out long-options, too. Apart from that, ebtables-nft does not use a mask, at all. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Change whitespace printing in save_rule callbackPhil Sutter2021-11-231-14/+12
| | | | | | | This aligns whitespace printing with legacy iptables' print_rule4() in order to prepare for further code-sharing. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft-shared: Make nft_check_xt_legacy() family agnosticPhil Sutter2021-10-201-0/+5
| | | | | | | Of course there is no such thing as *_tables_names for ebtables, so no legacy tables checking for ebtables-nft. Signed-off-by: Phil Sutter <phil@nwl.cc>
* Use proto_to_name() from xshared in more placesPhil Sutter2021-05-171-3/+3
| | | | | | | | | | Share the common proto name lookup code. While being at it, make proto number variable 16bit, values may exceed 256. This aligns iptables-nft '-p' argument printing with legacy iptables. In practice, this should make a difference only in corner cases. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix bitwise expression avoidance detectionPhil Sutter2021-03-091-1/+3
| | | | | | | | | Byte-boundary prefix detection was too sloppy: Any data following the first zero-byte was ignored. Add a follow-up loop making sure there are no stray bits in the designated host part. Fixes: 323259001d617 ("nft: Optimize class-based IP prefix matches") Signed-off-by: Phil Sutter <phil@nwl.cc>
* ebtables: Optimize masked MAC address matchesPhil Sutter2020-11-041-3/+2
| | | | | | | | | | Just like with class-based prefix matches in iptables-nft, optimize masked MAC address matches if the mask is on a byte-boundary. To reuse the logic in add_addr(), extend it to accept the payload base value via parameter. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Optimize class-based IP prefix matchesPhil Sutter2020-11-041-4/+10
| | | | | | | Payload expression works on byte-boundaries, leverage this with suitable prefix lengths. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix for broken address mask match detectionPhil Sutter2020-09-301-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Trying to decide whether a bitwise expression is needed to match parts of a source or destination address only, add_addr() checks if all bytes in 'mask' are 0xff or not. The check is apparently broken though as each byte in 'mask' is cast to a signed char before comparing against 0xff, therefore the bitwise is always added: | # ./bad/iptables-nft -A foo -s 10.0.0.1 -j ACCEPT | # ./good/iptables-nft -A foo -s 10.0.0.2 -j ACCEPT | # nft --debug=netlink list chain ip filter foo | ip filter foo 5 | [ payload load 4b @ network header + 12 => reg 1 ] | [ bitwise reg 1 = (reg=1 & 0xffffffff ) ^ 0x00000000 ] | [ cmp eq reg 1 0x0100000a ] | [ counter pkts 0 bytes 0 ] | [ immediate reg 0 accept ] | | ip filter foo 6 5 | [ payload load 4b @ network header + 12 => reg 1 ] | [ cmp eq reg 1 0x0200000a ] | [ counter pkts 0 bytes 0 ] | [ immediate reg 0 accept ] | | table ip filter { | chain foo { | ip saddr 10.0.0.1 counter packets 0 bytes 0 accept | ip saddr 10.0.0.2 counter packets 0 bytes 0 accept | } | } Fix the cast, safe an extra op and gain 100% performance in ideal cases. Fixes: 56859380eb328 ("xtables-compat: avoid unneeded bitwise ops") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Drop save_counters callback from family_opsPhil Sutter2020-05-181-8/+0
| | | | | | | All families use the same callback function, just fold it into the sole place it's called. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Merge nft_*_rule_find() functionsPhil Sutter2020-05-181-39/+0
| | | | | | | | | Both ebtables and arptables are fine with using nft_ipv46_rule_find() instead of their own implementations. Take the chance and move the former into nft.c as a static helper since it is used in a single place, only. Then get rid of the callback from family_ops. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: split parsing from netlink commandsPablo Neira Ayuso2020-05-111-2/+5
| | | | | | | | | | | | | | This patch updates the parser to generate a list of command objects. This list of commands is then transformed to a list of netlink jobs. This new command object stores the rule using the nftnl representation via nft_rule_new(). To reduce the number of updates in this patch, the nft_*_rule_find() functions have been updated to restore the native representation to skip the update of the rule comparison code. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft-shared: skip check for jumpto if cs->target is unsetPablo Neira Ayuso2020-04-151-1/+2
| | | | | | | | | The command_jump() function leaves cs->target unset if the target is not found. Let's check if the jumpto string mismatches only in this case. https://bugzilla.netfilter.org/show_bug.cgi?id=1422 Tested-by: Etienne Champetier <etienne.champetier@anevia.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* Fix DEBUG buildPhil Sutter2019-12-041-1/+1
| | | | | | | | | Fixed commit missed to update this conditional call to nft_rule_print_save(). Fixes: 1e8ef6a584754 ("nft: family_ops: Pass nft_handle to 'rule_to_cs' callback") Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Support parsing lookup expressionPhil Sutter2019-11-251-0/+9
| | | | | | | | Add required glue code to support family specific lookup expression parsers implemented as family_ops callback. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Embed rule's table name in nft_xt_ctxPhil Sutter2019-11-251-0/+1
| | | | | | | | Down to the point where expression parsing happens, the rule's table is not known anymore but relevant if set lookups are required. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>