summaryrefslogtreecommitdiffstats
path: root/iptables/nft-shared.c
Commit message (Collapse)AuthorAgeFilesLines
* 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>
* nft: Bore up nft_parse_payload()Phil Sutter2019-11-251-0/+8
| | | | | | | | | Allow for closer inspection by storing payload expression's base and length values. Also facilitate for two consecutive payload expressions as LHS of a (cmp/lookup) statement as used with concatenations. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Keep nft_handle pointer in nft_xt_ctxPhil Sutter2019-11-251-26/+14
| | | | | | | | | Instead of carrying the family value, carry the handle (which contains the family value) and relieve expression parsers from having to call nft_family_ops_lookup(). Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: family_ops: Pass nft_handle to 'rule_to_cs' callbackPhil Sutter2019-11-251-2/+3
| | | | | | | | | | | This is the actual callback used to parse nftables rules. Pass nft_handle to it so it can access the cache (and possible sets therein). Having to pass nft_handle to nft_rule_print_save() allows to simplify it a bit since no family ops lookup has to be done anymore. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: family_ops: Pass nft_handle to 'rule_find' callbackPhil Sutter2019-11-251-4/+3
| | | | | | | | | In order to prepare for rules containing set references, nft handle has to be passed to nft_rule_to_iptables_command_state() in order to let it access the set in cache. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Fix typo in nft_parse_limit() error messagePhil Sutter2019-09-261-1/+1
| | | | | | | Seems like a trivial copy'n'paste bug. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Fix add_bitwise_u16() on Big EndianPhil Sutter2019-09-231-1/+1
| | | | | | | | | | | | | | | | | | | | | Type used for 'mask' and 'xor' parameters was wrong, 'int' is four bytes on 32 or 64 bit architectures. After casting a uint16_t to int, on Big Endian the first two bytes of data are (the leading) zero which libnftnl then copies instead of the actual value. This problem was noticed when using '--fragment' option: | # iptables-nft -A FORWARD --fragment -j ACCEPT | # nft list ruleset | grep frag-off | ip frag-off & 0 != 0 counter packets 0 bytes 0 accept With this fix in place, the resulting nft rule is correct: | ip frag-off & 8191 != 0 counter packets 0 bytes 0 accept Fixes: 2f1fbab671576 ("iptables: nft: add -f support") Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Don't assume NFTNL_RULE_USERDATA holds a commentPhil Sutter2019-02-081-17/+22
| | | | | | | | | If this rule attribute is present but does not contain a comment, get_comment() returns NULL which is then fed into strncpy() causing a crash. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* xtables: Fix for false-positive rule matchingPhil Sutter2019-02-051-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | When comparing two rules with non-standard targets, differences in targets' payloads wasn't respected. The cause is a rather hideous one: Unlike xtables_find_match(), xtables_find_target() did not care whether the found target was already in use or not, so the same target instance was assigned to both rules and therefore payload comparison happened over the same memory location. With legacy iptables it is not possible to reuse a target: The only case where two rules (i.e., iptables_command_state instances) could exist at the same time is when comparing rules, but that's handled using libiptc. The above change clashes with ebtables-nft's reuse of target objects: While input parsing still just assigns the object from xtables_targets list, rule conversion from nftnl to iptables_command_state allocates new data. To fix this, make ebtables-nft input parsing use the common command_jump() routine instead of its own simplified copy. In turn, this also eliminates the ebtables-nft-specific variants of parse_target(), though with a slight change of behaviour: Names of user-defined chains are no longer allowed to contain up to 31 but merely 28 characters. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* xtables: Fix for crash when comparing rules with standard targetPhil Sutter2019-02-011-4/+19
| | | | | | | | | | When parsing an nftnl_rule with a standard verdict, nft_rule_to_iptables_command_state() initialized cs->target but didn't care about cs->target->t. When later comparing that rule to another, compare_targets() crashed due to unconditional access to t's fields. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* nft: Fix potential memleaks in nft_*_rule_find()Phil Sutter2019-02-011-5/+9
| | | | | | | | | These functions parse an nftnl_rule into a local instance of iptables_command_state which potentially allocates memory (for matches or target), so call ops->clear_cs() before returning to caller. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* xtables: make all nft_parse_ helpers staticFlorian Westphal2018-11-191-8/+8
| | | | | | no more external callers. Signed-off-by: Florian Westphal <fw@strlen.de>
* xtables: Fix for matching rules with wildcard interfacesPhil Sutter2018-11-011-1/+1
| | | | | | | | | | | | | | Due to xtables_parse_interface() and parse_ifname() being misaligned regarding interface mask setting, rules containing a wildcard interface added with iptables-nft could neither be checked nor deleted. As suggested, introduce extensions/iptables.t to hold checks for built-in selectors. This file is picked up by iptables-test.py as-is. The only limitation is that iptables is being used for it, so no ip6tables-specific things can be tested with it (for now). Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft-shared: Use xtables_calloc()Phil Sutter2018-09-251-11/+2
| | | | | | | | This simplifies code a bit since it takes care of checking for out-of-memory conditions. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* iptables: Use print_ifaces() from xtablesPhil Sutter2018-09-241-39/+0
| | | | | | | | | | Move the function to xshared.c for common use between legacy and xtables sources. While being at it, silence a covscan warning triggered by that function as it couldn't verify input buffers won't exceed IFNAMSIZ. Therefore use snprintf() when writing to the local buffer. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* Mark fall through cases in switch() statementsPhil Sutter2018-09-241-0/+1
| | | | | | | | | | | | Typical covscan complaint, non-empty fall throughs should be marked as such. There was but a single case which should break instead, namely in libebt_log.c: It is not critical, since the next case merely asserts 'invert' being zero (which can't be as it was checked before). But while being at it, introduce log_chk_inv() to consolidate the semantically equal cases for the various log types. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* xtables: Fix for deleting rules with commentPhil Sutter2018-08-291-9/+6
| | | | | | | | | | | | | | | | | | | | | | Comment match allocation in command_match() and nft_rule_to_iptables_command_state() were misaligned in that the latter set match_size to just what is required instead of what the match needs at maximum like the further. This led to failure when comparing them later and therefore a rule with a comment could not be deleted. For comments of a specific length, the udata buffer is padded by libnftnl so nftnl_rule_get_data() returns a length value which is larger than the string (including NULL-byte). The trailing data is supposed to be ignored, but compare_matches() can't not know about that detail and therefore returns a false-negative if trailing data contains junk. To overcome this, use strncpy() when populating match data in nft_rule_to_iptables_command_state(). While being at it, make sure comment match allocation in that function is identical to what command_match() does with regards to data allocation size. Also use xtables_calloc() which does the required error checking. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* xtables: Add missing deinitializationPhil Sutter2018-08-241-0/+2
| | | | | | | | | | These fix reports for definitely lost blocks in valgrind. Not really memleaks, but due to nft_handle going out of scope they're counted as lost. Still worth fixing though since it reduces noise when auditing code for real issues. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>