summaryrefslogtreecommitdiffstats
path: root/iptables/nft.c
Commit message (Collapse)AuthorAgeFilesLines
* nft: Fix EPERM handling for extensions without rev 0Phil Sutter2022-05-111-4/+7
| | | | | | | | | | Treating revision 0 as compatible in EPERM case works fine as long as there is a revision 0 of that extension defined in DSO. Fix the code for others: Extend the EPERM handling to all revisions and keep the existing warning for revision 0. Fixes: 17534cb18ed0a ("Improve error messages for unsupported extensions") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: split gen_payload() to allocate register and initialize expressionPablo Neira Ayuso2022-05-021-4/+14
| | | | | | Add __gen_payload(), in preparation for the dynamic register allocation. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: prepare for dynamic register allocationPablo Neira Ayuso2022-05-021-31/+39
| | | | | | | | | 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/+13
| | | | | | | 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/+23
| | | | | | Use meta mark + bitwise + cmp instead of nft_compat mark match. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Don't pass command state opaque to family ops callbacksPhil Sutter2022-03-101-2/+2
| | | | | | | | | | | 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>
* Improve error messages for unsupported extensionsPhil Sutter2022-03-021-3/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If a given extension was not supported by the kernel, iptables would print a rather confusing error message if extension parameters were given: | # rm /lib/modules/$(uname -r)/kernel/net/netfilter/xt_LOG.ko | # iptables -A FORWARD -j LOG --log-prefix foo | iptables v1.8.7 (legacy): unknown option "--log-prefix" Avoid this by pretending extension revision 0 is always supported. It is the same hack as used to successfully print extension help texts as unprivileged user, extended to all error codes to serve privileged ones as well. In addition, print a warning if kernel rejected revision 0 and it's not a permissions problem. This helps users find out which extension in a rule the kernel didn't like. Finally, the above commands result in these messages: | Warning: Extension LOG revision 0 not supported, missing kernel module? | iptables: No chain/target/match by that name. Or, for iptables-nft: | Warning: Extension LOG revision 0 not supported, missing kernel module? | iptables v1.8.7 (nf_tables): RULE_APPEND failed (No such file or directory): rule in chain FORWARD Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Add debug output to table creationPhil Sutter2022-02-081-0/+15
| | | | | | | This at least allows to inspect how tables are created on demand. Also requires setting NFTNL_TABLE_FAMILY for clean output. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Set NFTNL_CHAIN_FAMILY in new chainsPhil Sutter2022-02-081-4/+8
| | | | | | | | | | | | | | | | | | | | | | Kernel doesn't need it, but debug output improves significantly. Before this patch: | # iptables-nft -vv -A INPUT | [...] | unknown filter INPUT use 0 type filter hook unknown prio 0 policy accept packets 0 bytes 0 | [...] and after: | # iptables-nft -vv -A INPUT | [...] | ip filter INPUT use 0 type filter hook input prio 0 policy accept packets 0 bytes 0 | [...] While being at it, make nft_chain_builtin_alloc() take only the builtin table's name as parameter - it's the only field it accesses. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Use verbose flag to toggle debug outputPhil Sutter2022-02-041-18/+20
| | | | | | | | | | | Copy legacy iptables' behaviour, printing debug output if verbose flag is given more than once. Since nft debug output applies to netlink messages which are not created until nft_action() phase, carrying verbose value is non-trivial - introduce a field in struct nft_handle for that. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: add support for native tcp flag matchingFlorian Westphal2022-01-291-2/+29
| | | | | | prefer payload + bitwise + cmp to nft_compat match. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft: prefer native expressions instead of tcp matchFlorian Westphal2022-01-291-0/+32
| | | | | | | | | | | | | | Instead of using nft_compat+xtables tcp match, prefer to emit payload+cmp or payload+range expression. Unlike udp, tcp has flag bits that can be matched too but we have to fall back to the xt expression for now. We also don't support tcp option match, but thats a rarely used feature anyway. Delinearization support for ports was added in previous patches. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft: prefer native expressions instead of udp matchFlorian Westphal2022-01-291-0/+122
| | | | | | | | | Instead of using nft_compat+xtables udp match, prefer to emit payload+cmp or payload+range expression. Delinearization support was added in previous patches. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft-shared: support native tcp port range delinearizeFlorian Westphal2022-01-291-0/+1
| | | | | | | adds support for nft ... tcp dport != min-max Signed-off-by: Florian Westphal <fw@strlen.de>
* xshared: Fix response to unprivileged usersPhil Sutter2022-01-201-0/+5
| | | | | | | | | | | | | | | | | | | | | Expected behaviour in both variants is: * Print help without error, append extension help if -m and/or -j options are present * Indicate lack of permissions in an error message for anything else With iptables-nft, this was broken basically from day 1. Shared use of do_parse() then somewhat broke legacy: it started complaining about inability to create a lock file. Fix this by making iptables-nft assume extension revision 0 is present if permissions don't allow to verify. This is consistent with legacy. Second part is to exit directly after printing help - this avoids having to make the following code "nop-aware" to prevent privileged actions. Signed-off-by: Phil Sutter <phil@nwl.cc> Reviewed-by: Florian Westphal <fw@strlen.de>
* extensions: libxt_NFLOG: don't truncate log prefix on print/saveKyle Bowman2022-01-181-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | 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>
* extensions: libxt_NFLOG: use nft built-in logging instead of xt_NFLOGKyle Bowman2022-01-181-0/+28
| | | | | | | | | | | | | | | Replaces the use of xt_NFLOG with the nft built-in log statement. This additionally adds support for using longer log prefixes of 128 characters in size. Until now NFLOG has truncated the log-prefix to the 64-character limit supported by iptables-legacy. We now use the struct xtables_target's udata member to store the longer 128-character prefix supported by iptables-nft. 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: fix indentation error.Jeremy Sowden2022-01-151-21/+21
| | | | | | | `add_action` was indented with 7 spaces. Signed-off-by: Jeremy Sowden <jeremy@azazel.net> Signed-off-by: Florian Westphal <fw@strlen.de>
* xshared: Share print_header() with legacy iptablesPhil Sutter2021-11-231-3/+3
| | | | | | | | | | | | | | | 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>
* nft: Change whitespace printing in save_rule callbackPhil Sutter2021-11-231-2/+2
| | | | | | | 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: Introduce builtin_tables_lookup()Phil Sutter2021-10-201-2/+17
| | | | | | | The set of builtin tables to use is fully determined by the given family so just look it up instead of having callers pass it explicitly. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Delete builtin chains compatiblyPhil Sutter2021-09-271-8/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | Attempting to delete all chains if --delete-chain is called without argument has unwanted side-effects especially legacy iptables users are not aware of and won't expect: * Non-default policies are ignored, a previously dropping firewall may start accepting traffic. * The kernel refuses to remove non-empty chains, causing program abort even if no user-defined chain exists. Fix this by requiring a rule cache in that situation and make builtin chain deletion depend on its policy and number of rules. Since this may change concurrently, check again when having to refresh the transaction. Also, hide builtin chains from verbose output - their creation is implicit, so treat their removal as implicit, too. When deleting a specific chain, do not allow to skip the job though. Otherwise deleting a builtin chain which is still in use will succeed although not executed. Fixes: 61e85e3192dea ("iptables-nft: allow removal of empty builtin chains") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft-chain: Introduce base_slot fieldPhil Sutter2021-09-271-27/+1
| | | | | | | | For builtin chains, record the base_chains array slot they are assigned to. This simplifies removing that reference if they are being deleted later. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Check base-chain compatibility when adding to cachePhil Sutter2021-09-271-32/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | With introduction of dedicated base-chain slots, a selection process was established as no longer all base-chains ended in the same chain list for later searching/checking but only the first one found for each hook matching criteria is kept and the rest discarded. A side-effect of the above is that table compatibility checking started to omit consecutive base-chains, making iptables-nft less restrictive as long as the expected base-chains were returned first from kernel when populating the cache. Make behaviour consistent and warn users about the possibly disturbing chains found by: * Run all base-chain checks from nft_is_chain_compatible() before allowing a base-chain to occupy its slot. * If an unfit base-chain was found (and discarded), flag the table's cache as tainted and warn about it if the remaining ruleset is otherwise compatible. Since base-chains that remain in cache would pass nft_is_chain_compatible() checking, remove that and reduce it to rule inspection. Signed-off-by: Phil Sutter <phil@nwl.cc>
* iptables-nft: allow removal of empty builtin chainsFlorian Westphal2021-09-071-27/+51
| | | | | | | | | | | | The only reason why this is prohibited is that you cannot do it in iptables-legacy. This removes the artifical limitation. "iptables-nft -X" will leave the builtin chains alone; Also, deletion is only permitted if the chain is empty. Signed-off-by: Florian Westphal <fw@strlen.de>
* nft: Use xtables_{m,c}alloc() everywherePhil Sutter2021-08-311-12/+3
| | | | | | | | | | Make use of libxtables allocators where sensible to have implicit error checking. Leave library-internal calls in place to not create unexpected program exit points for users, apart from xt_xlate_alloc() as that function called xtables_error() in error case which exits by itself already. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Use xtables_malloc() in mnl_err_list_node_add()Phil Sutter2021-08-311-1/+1
| | | | | | | | The function called malloc() without checking for memory allocation failure. Simply replace the call by xtables_malloc() to fix that. Fixes: 4e2020952d6f9 ("xtables: use libnftnl batch API") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix for non-verbose check commandPhil Sutter2021-08-031-1/+1
| | | | | | | | Check command was unconditionally verbose since v1.8.5. Make it respect --verbose option again. Fixes: a7f1e208cdf9c ("nft: split parsing from netlink commands") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Increase BATCH_PAGE_SIZE to support huge rulesetsPhil Sutter2021-04-101-5/+7
| | | | | | | | | | | | | | In order to support the same ruleset sizes as legacy iptables, the kernel's limit of 1024 iovecs has to be overcome. Therefore increase each iovec's size from 128KB to 2MB. While being at it, add a log message for failing sendmsg() call. This is not supposed to happen, even if the transaction fails. Yet if it does, users are left with only a "line XXX failed" message (with line number being the COMMIT line). Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* nft: cache: Sort chains on demand onlyPhil Sutter2021-04-061-0/+12
| | | | | | | | | Mandatory sorted insert of chains into cache significantly slows down restoring of large rulesets. Since the sorted list of user-defined chains is needed for listing and verbose output only, introduce nft_cache_sort_chains() and call it where needed. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Avoid pointless table/chain creationPhil Sutter2020-12-211-18/+80
| | | | | | | | | | | | | | | | | Accept a chain name in nft_xt_builtin_init() to limit the base chain creation to that specific chain only. Introduce nft_xt_builtin_table_init() to create just the table for situations where no builtin chains are needed but the command may still succeed in an empty ruleset, particularly when creating a custom chain, restoring base chains or adding a set for ebtables among match. Introduce nft_xt_fake_builtin_chains(), a function to call after cache has been populated to fill empty base chain slots. This keeps ruleset listing output intact if some base chains do not exist (or even the whole ruleset is completely empty). Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Introduce a dedicated base chain arrayPhil Sutter2020-12-211-1/+11
| | | | | | | | | Preparing for sorted chain output, introduce a per-table array holding base chains indexed by nf_inet_hooks value. Since the latter is ordered correctly, iterating over the array will return base chains in expected order. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Introduce struct nft_chainPhil Sutter2020-12-211-44/+71
| | | | | | | | | Preparing for ordered output of user-defined chains, introduce a local datatype wrapping nftnl_chain. In order to maintain the chain name hash table, introduce nft_chain_list as well and use it instead of nftnl_chain_list. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: cache: Move nft_chain_find() overPhil Sutter2020-12-211-17/+0
| | | | | | It is basically just a cache lookup, hence fits better in here. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Implement nft_chain_foreach()Phil Sutter2020-12-211-55/+33
| | | | | | | | | | | | | | This is just a fancy wrapper around nftnl_chain_list_foreach() with the added benefit of detecting invalid table names or uninitialized chain lists. This in turn allows to drop the checks in flush_rule_cache() and ignore the return code of nft_chain_foreach() as it fails only if the dropped checks had failed, too. Since this wrapper does the chain list lookup by itself, use of nft_chain_list_get() shrinks down to a single place, namely inside nft_chain_find(). Therefore fold it into the latter. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: cache: Introduce nft_cache_add_chain()Phil Sutter2020-12-211-9/+7
| | | | | | | This is a convenience function for adding a chain to cache, for now just a simple wrapper around nftnl_chain_list_add_tail(). Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix selective chain compatibility checksPhil Sutter2020-12-211-0/+6
| | | | | | | | | | | | | | Since commit 80251bc2a56ed ("nft: remove cache build calls"), 'chain' parameter passed to nft_chain_list_get() is no longer effective. Before, it was used to fetch only that single chain from kernel when populating the cache. So the returned list of chains for which compatibility checks are done would contain only that single chain. Re-establish the single chain compat checking by introducing a dedicated code path to nft_is_chain_compatible() doing so. Fixes: 80251bc2a56ed ("nft: remove cache build calls") Signed-off-by: Phil Sutter <phil@nwl.cc>
* ebtables: Fix for broken chain renamingPhil Sutter2020-11-171-3/+0
| | | | | | | | | | Loading extensions pollutes 'errno' value, hence before using it to indicate failure it should be sanitized. This was done by the called function before the parsing/netlink split and not migrated by accident. Move it into calling code to clarify the connection. Fixes: a7f1e208cdf9c ("nft: split parsing from netlink commands") Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix for concurrent noflush restore callsPhil Sutter2020-10-131-28/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Transaction refresh was broken with regards to nft_chain_restore(): It created a rule flush batch object only if the chain was found in cache and a chain add object only if the chain was not found. Yet with concurrent ruleset updates, one has to expect both situations: * If a chain vanishes, the rule flush job must be skipped and instead the chain add job become active. * If a chain appears, the chain add job must be skipped and instead rules flushed. Change the code accordingly: Create both batch objects and set their 'skip' field depending on the situation in cache and adjust both in nft_refresh_transaction(). As a side-effect, the implicit rule flush becomes explicit and all handling of implicit batch jobs is dropped along with the related field indicating such. Reuse the 'implicit' parameter of __nft_rule_flush() to control the initial 'skip' field value instead. A subtle caveat is vanishing of existing chains: Creating the chain add job based on the chain in cache causes a netlink message containing that chain's handle which the kernel dislikes. Therefore unset the chain's handle in that case. Fixes: 58d7de0181f61 ("xtables: handle concurrent ruleset modifications") Signed-off-by: Phil Sutter <phil@nwl.cc>
* iptables-nft: fix basechain policy configurationPablo Neira Ayuso2020-10-081-1/+5
| | | | | | | | | | Previous to this patch, the basechain policy could not be properly configured if it wasn't explictly set when loading the ruleset, leading to iptables-nft-restore (and ip6tables-nft-restore) trying to send an invalid ruleset to the kernel. Signed-off-by: Arturo Borrero Gonzalez <arturo@netfilter.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Fix error reporting for refreshed transactionsPhil Sutter2020-10-071-2/+3
| | | | | | | | | | | | | | When preparing a batch from the list of batch objects in nft_action(), the sequence number used for each object is stored within that object for later matching against returned error messages. Though if the transaction has to be refreshed, some of those objects may be skipped, other objects take over their sequence number and errors are matched to skipped objects. Avoid this by resetting the skipped object's sequence number to zero. Fixes: 58d7de0181f61 ("xtables: handle concurrent ruleset modifications") Signed-off-by: Phil Sutter <phil@nwl.cc> Reviewed-by: Florian Westphal <fw@strlen.de>
* nft: Make batch_add_chain() return the added batch objectPhil Sutter2020-10-071-18/+17
| | | | | | | | | | Do this so in a later patch the 'skip' field can be adjusted. While being at it, simplify a few callers and eliminate the need for a 'ret' variable. Signed-off-by: Phil Sutter <phil@nwl.cc> Reviewed-by: Florian Westphal <fw@strlen.de>
* nft: Use nft_chain_find() in nft_chain_builtin_init()Phil Sutter2020-08-211-12/+4
| | | | | | The replaced code is basically identical to nft_chain_find()'s body. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fold nftnl_rule_list_chain_save() into callerPhil Sutter2020-08-211-24/+7
| | | | | | | | | | | Existence of this function was mostly code-duplication: Caller already branches depending on whether 'chain' is NULL or not and even does the chain list lookup. While being at it, simplify __nftnl_rule_list_chain_save function name a bit now that the non-prefixed name is gone. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Extend use of nftnl_chain_list_foreach()Phil Sutter2020-08-211-77/+86
| | | | | | | | | | | | | Make use of the callback-based iterator in nft_rule_list(), nft_rule_list_save(), nft_rule_flush() and nft_rule_save(). Callback code for nft_rule_list() and nft_rule_list_save is pretty similar, so introduce and use a common callback function. For nft_rule_save(), turn nft_chain_save_rules() into a callback - it is not used anywhere else, anyway. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Fix for ruleset flush while restoringPhil Sutter2020-08-141-13/+2
| | | | | | | | | | | | | | | | | | If ruleset is flushed while an instance of iptables-nft-restore is running and has seen a COMMIT line once, it doesn't notice the disappeared table while handling the next COMMIT. This is due to table existence being tracked via 'initialized' boolean which is only reset by nft_table_flush(). To fix this, drop the dedicated 'initialized' boolean and switch users to the recently introduced 'exists' one. As a side-effect, this causes base chain existence being checked for each command calling nft_xt_builtin_init() as the old 'initialized' bit was used to track if that function has been called before or not. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Eliminate table list from cachePhil Sutter2020-07-311-40/+15
| | | | | | | | | | | | | | The full list of tables in kernel is not relevant, only those used by iptables-nft and for those, knowing if they exist or not is sufficient. For holding that information, the already existing 'table' array in nft_cache suits well. Consequently, nft_table_find() merely checks if the new 'exists' boolean is true or not and nft_for_each_table() iterates over the builtin_table array in nft_handle, additionally checking the boolean in cache for whether to skip the entry or not. Signed-off-by: Phil Sutter <phil@nwl.cc>
* iptables: replace libnftnl table list by linux listPablo Neira Ayuso2020-07-271-56/+18
| | | | | | | | This patch removes the libnftnl table list by linux list. This comes with an extra memory allocation to store the nft_table object. Probably, there is no need to cache the entire nftnl_table in the near future. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Use nft_chain_find() in two more placesPhil Sutter2020-07-241-15/+14
| | | | | | | This doesn't really increase functions' readability but prepares for later changes. Signed-off-by: Phil Sutter <phil@nwl.cc>
* nft: Turn nft_chain_save() into a foreach-callbackPhil Sutter2020-07-241-35/+12
| | | | | | | | Let nftnl_chain_list_foreach() do the chain list iterating instead of open-coding it. While being at it, simplify the policy value selection code as well. Signed-off-by: Phil Sutter <phil@nwl.cc>