summaryrefslogtreecommitdiffstats
path: root/iptables/nft.c
Commit message (Collapse)AuthorAgeFilesLines
* nft: Use ARRAY_SIZE() macro in nft_strerror()Phil Sutter2019-10-231-1/+1
| | | | | | | | Variable 'table' is an array of type struct table_struct, so this is a classical use-case for ARRAY_SIZE() macro. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Optimize flushing all chains of a tablePhil Sutter2019-10-171-14/+18
| | | | | | | | | | | | | | | | | | | | | | | | Leverage nftables' support for flushing all chains of a table by omitting NFTNL_RULE_CHAIN attribute in NFT_MSG_DELRULE payload. The only caveat is with verbose output, as that still requires to have a list of (existing) chains to iterate over. Apart from that, implementing this shortcut is pretty straightforward: Don't retrieve a chain list and just call __nft_rule_flush() directly which doesn't set above attribute if chain name pointer is NULL. A bigger deal is keeping rule cache consistent: Instead of just clearing rule list for each flushed chain, flush_rule_cache() is updated to iterate over all cached chains of the given table, clearing their rule lists if not called for a specific chain. While being at it, sort local variable declarations in nft_rule_flush() from longest to shortest and drop the loop-local 'chain_name' variable (but instead use 'chain' function parameter which is not used at that point). Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Support nft_is_table_compatible() per chainPhil Sutter2019-10-171-8/+24
| | | | | | | | | | | | | | When operating on a single chain only, compatibility checking causes unwanted overhead by checking all chains of the current table. Avoid this by accepting the current chain name as parameter and pass it along to nft_chain_list_get(). While being at it, introduce nft_assert_table_compatible() which calls xtables_error() in case compatibility check fails. If a chain name was given, include that in error message. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Reduce cache overhead of nft_chain_builtin_init()Phil Sutter2019-10-171-4/+5
| | | | | | | | There is no need for a full chain cache, fetch only the few builtin chains that might need to be created. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft-cache: Support partial rule cache per chainPhil Sutter2019-10-171-18/+17
| | | | | | | | | | | | | | | | | Accept an additional chain name pointer in __nft_build_cache() and pass it along to fetch only that specific chain and its rules. Enhance nft_build_cache() to take an optional nftnl_chain pointer to fetch rules for. Enhance nft_chain_list_get() to take an optional chain name. If cache level doesn't include chains already, it will fetch only the specified chain from kernel (if existing) and add that to table's chain list which is returned. This keeps operations for all chains of a table or a specific one within the same code path in nft.c. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft-cache: Fetch only chains in nft_chain_list_get()Phil Sutter2019-10-171-0/+20
| | | | | | | | | | The function is used to return the given table's chains, so fetching chain cache is enough. Add calls to nft_build_cache() in places where a rule cache is required. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Extract cache routines into nft-cache.cPhil Sutter2019-10-101-356/+4
| | | | | | | | The amount of code dealing with caching only is considerable and hence deserves an own source file. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Avoid nested cache fetchingPhil Sutter2019-10-101-2/+1
| | | | | | | | | Don't call fetch_table_cache() from within fetch_chain_cache() but instead from __nft_build_cache(). Since that is the only caller of fetch_chain_cache(), this change should not have any effect in practice. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Pass nft_handle to flush_cache()Phil Sutter2019-10-101-17/+11
| | | | | | | | | This allows to call nft_table_builtin_find() and hence removes the only real user of __nft_table_builtin_find(). Consequently remove the latter by integrating it into its sole caller. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables-restore: Minimize caching when flushingPhil Sutter2019-09-301-0/+17
| | | | | | | | | | | | | | Unless --noflush was given, xtables-restore merely needs the list of tables to decide whether to delete it or not. Introduce nft_fake_cache() function which populates table list, initializes chain lists (so nft_chain_list_get() returns an empty list instead of NULL) and sets 'have_cache' to turn any later calls to nft_build_cache() into nops. If --noflush was given, call nft_build_cache() just once instead of for each table line in input. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft: Make nftnl_table_list_get() fetch only tablesPhil Sutter2019-09-301-1/+2
| | | | | | | No need for a full cache to serve the list of tables. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft: Fix for add and delete of same rule in single batchPhil Sutter2019-09-301-0/+3
| | | | | | | | | | | | | | | Another corner-case found when extending restore ordering test: If a delete command in a dump referenced a rule added earlier within the same dump, kernel would reject the resulting NFT_MSG_DELRULE command. Catch this by assigning the rule to delete a RULE_ID value if it doesn't have a handle yet. Since __nft_rule_del() does not duplicate the nftnl_rule object when creating the NFT_COMPAT_RULE_DELETE command, this RULE_ID value is added to both NEWRULE and DELRULE commands - exactly what is needed to establish the reference. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft: Get rid of NFT_COMPAT_EXPR_MAX definePhil Sutter2019-09-261-4/+2
| | | | | | | | Instead simply use ARRAY_SIZE() macro to not overstep supported_exprs array. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables_error() does not returnPhil Sutter2019-09-251-6/+2
| | | | | | | | | It's a define which resolves into a callback which in turn is declared with noreturn attribute. It will never return, therefore drop all explicit exit() calls or other dead code immediately following it. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Florian Westphal <fw@strlen.de>
* nft Increase mnl_talk() receive buffer sizePhil Sutter2019-09-231-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | This improves cache population quite a bit and therefore helps when dealing with large rulesets. A simple hard to improve use-case is listing the last rule in a large chain. These are the average program run times depending on number of rules: rule count | legacy | nft old | nft new --------------------------------------------------------- 50,000 | .052s | .611s | .406s 100,000 | .115s | 2.12s | 1.24s 150,000 | .265s | 7.63s | 4.14s 200,000 | .411s | 21.0s | 10.6s So while legacy iptables is still magnitudes faster, this simple change doubles iptables-nft performance in ideal cases. Note that using a larger buffer than 32KB doesn't further improve performance since linux kernel won't transmit more data at once. This limit was set (actually extended from 16KB) in kernel commit d35c99ff77ecb ("netlink: do not enter direct reclaim from netlink_dump()"). Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Introduce nft_bridge_commit()Phil Sutter2019-09-231-2/+6
| | | | | | | | No need to check family value from nft_commit() if we can have a dedicated callback for bridge family. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Use nftnl_*_set_str() functionsPhil Sutter2019-09-231-14/+14
| | | | | | | | | | Although it doesn't make a difference in practice, they are the correct API functions to use when assigning string attributes. While doing so, also drop the needless casts to non-const. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Drop stale include directivePhil Sutter2019-08-011-1/+0
| | | | | | | | This is a leftover, the file does not exist in fresh clones. Fixes: 06fd5e46d46f7 ("xtables: Drop support for /etc/xtables.conf") Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Drop support for /etc/xtables.confPhil Sutter2019-07-291-154/+8
| | | | | | | | As decided upon at NFWS2019, drop support for configurable nftables base chains to use with iptables-nft. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Set errno in nft_rule_flush()Phil Sutter2019-07-291-1/+3
| | | | | | | | | | | When trying to flush a non-existent chain, errno gets set in nft_xtables_config_load(). That is an unintended side-effect and when support for xtables.conf is later removed, iptables-nft will emit the generic "Incompatible with this kernel." error message instead of "No chain/target/match by that name." as it should. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Make nft_for_each_table() more versatilePhil Sutter2019-07-231-3/+3
| | | | | | | Support passing arbitrary data (via void pointer) to the callback. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: exit in case we can't fetch current genidFlorian Westphal2019-07-151-2/+8
| | | | | | | | | | | When running iptables -nL as non-root user, iptables would loop indefinitely. With this change, it will fail with iptables v1.8.3 (nf_tables): Could not fetch rule set generation id: Permission denied (you must be root) Reported-by: Amish <anon.amish@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Move send/receive buffer sizes into nft_handlePhil Sutter2019-07-031-10/+7
| | | | | | | | | Store them next to the mnl_socket pointer. While being at it, add a comment to mnl_set_rcvbuffer() explaining why the buffer size is changed. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Pass nft_handle down to mnl_batch_talk()Phil Sutter2019-07-031-23/+18
| | | | | | | | | >From there, pass it along to mnl_nft_socket_sendmsg() and further down to mnl_set_{snd,rcv}buffer(). This prepares the code path for keeping stored socket buffer sizes in struct nft_handle. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Set socket receive bufferPhil Sutter2019-07-031-4/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When trying to delete user-defined chains in a large ruleset, iptables-nft aborts with "No buffer space available". This can be reproduced using the following script: | #! /bin/bash | iptables-nft-restore <( | | echo "*filter" | for i in $(seq 0 200000);do | printf ":chain_%06x - [0:0]\n" $i | done | for i in $(seq 0 200000);do | printf -- "-A INPUT -j chain_%06x\n" $i | printf -- "-A INPUT -j chain_%06x\n" $i | done | echo COMMIT | | ) | iptables-nft -X The problem seems to be the sheer amount of netlink error messages sent back to user space (one EBUSY for each chain). To solve this, set receive buffer size depending on number of commands sent to kernel. Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: reset netlink sender buffer size of socket restartPablo Neira Ayuso2019-05-201-0/+1
| | | | | | | | Otherwise, mnl_set_sndbuffer() skips the buffer update after socket restart. Then, sendmsg() fails with EMSGSIZE later on when sending the batch to the kernel. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: do not retry on EINTRPablo Neira Ayuso2019-05-201-21/+5
| | | | | | | Patch ab1cd3b510fa ("nft: ensure cache consistency") already handles consistency via generation ID. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: don't care about previous state in ERESTARTPablo Neira Ayuso2019-05-201-7/+10
| | | | | | | We need to re-evalute based on the existing cache generation. Fixes: 58d7de0181f6 ("xtables: handle concurrent ruleset modifications") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: don't skip table addition from ERESTARTPablo Neira Ayuso2019-05-201-9/+1
| | | | | | | I don't find a scenario that trigger this case. Fixes: 58d7de0181f6 ("xtables: handle concurrent ruleset modifications") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Fix for explicit rule flushesPhil Sutter2019-05-201-1/+1
| | | | | | | | | | | The commit this fixes added a new parameter to __nft_rule_flush() to mark a rule flush job as implicit or not. Yet the code added to that function ignores the parameter and instead always sets batch job's 'implicit' flag to 1. Fixes: 77e6a93d5c9dc ("xtables: add and set "implict" flag on transaction objects") Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: keep original cache in case of ERESTARTPablo Neira Ayuso2019-05-201-3/+20
| | | | | | | | | | | | | | | Phil Sutter says: "The problem is that data in h->obj_list potentially sits in cache, too. At least rules have to be there so insert with index works correctly. If the cache is flushed before regenerating the batch, use-after-free occurs which crashes the program." This patch keeps around the original cache until we have refreshed the batch. Fixes: 862818ac3a0de ("xtables: add and use nft_build_cache") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: ensure cache consistencyPablo Neira Ayuso2019-05-201-6/+16
| | | | | | | Check for generation ID before and after fetching the cache to ensure consistency. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: cache table listPablo Neira Ayuso2019-05-201-45/+57
| | | | | | | nft_table_find() uses the table list cache to look up for existing tables. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: add flush_cache()Pablo Neira Ayuso2019-05-191-11/+19
| | | | | | | | | This new function takes a struct nft_cache as parameter. This patch also introduces __nft_table_builtin_find() which is required to look up for built-in tables without the nft_handle structure. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: add __nft_table_builtin_find()Pablo Neira Ayuso2019-05-191-6/+12
| | | | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: statify nft_rebuild_cache()Pablo Neira Ayuso2019-05-191-1/+1
| | | | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: add struct nft_cachePablo Neira Ayuso2019-05-191-15/+16
| | | | | | Add new structure that encloses the cache and update the code to use it. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Don't leak iter in error path of __nft_chain_zero_counters()Phil Sutter2019-05-151-1/+3
| | | | | | | | | If batch_rule_add() fails, this function leaked the rule iterator object. Fixes: 4c54c892443c2 ("xtables: Catch errors when zeroing rule rounters") Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: handle concurrent ruleset modificationsFlorian Westphal2019-04-271-4/+127
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We currently race when several xtables-nft-restore processes attempt to handle rules in parallel. For instance, when no rules are present at all, then iptables-nft-restore < X & iptables-nft-restore < X ... can cause rules to be restored twice. Reason is that both processes might detect 'no rules exist', so neither issues a flush operation. We can't unconditionally issue the flush, because it would cause kernel to fail with -ENOENT unless the to-be-flushed table exists. This change passes the generation id that was used to build the transaction to the kernel. In case another process changed *any* rule somewhere, the transaction will now fail with -ERESTART. We then flush the cache, re-fetch the ruleset and refresh our transaction. For example, in the above 'parallel restore' case, the iptables-restore instance that lost the race would detect that the table has been created already, and would add the needed flush. In a similar vein, in case --noflush is used, we will add the flush op for user-defined chains that were created in the mean-time. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: add and set "implict" flag on transaction objectsFlorian Westphal2019-04-271-19/+24
| | | | | | | | | | | | | | | | | | | | | | Its used to flag the rule flushes that get added in user-defined-chains that get redefined with --noflush. IOW, those objects that are added not by explicit instruction but to keep semantics. With --noflush, iptables-legacy-restore will behave as if -F USERCHAIN was given, in case USERCHAIN exists and USERCHAIN gets redefined, i.e.: iptables-save v1.8.2 on Thu Apr 18 17:11:05 2019 *filter :USERCHAIN - [0:0] COMMIT ... will remove all existing rules from USERCHAIN. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: add and use nft_build_cacheFlorian Westphal2019-04-271-5/+23
| | | | | | | | | | | | Will be used with the "generation id" infrastructure. When we're told that the commit failed because someone else made changes, we can use this to re-initialize the cache and then revalidate the transaction list (e.g. to detect that we now have to flush the user-defined chain 'foo' that we wanted to create, but was added just now by someone else). Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: add skip flag to objectsFlorian Westphal2019-04-271-18/+31
| | | | | | | | | | | | This will be used to skip transaction objects when committing to kernel. This is needed for example when we restore a table that doesn't exist yet. In such a case we would already build a flush operation so we can just enable it when we hit problem with the generation id and we find that the table/chain was already created in the mean time. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: unify user chain add/flush for restore caseFlorian Westphal2019-04-271-43/+39
| | | | | | | | | | | | The idea here is to move the 'flush' decision into the core, rather than have the decision in the frontend. This will be required later when "generation id" is passed to kernel. In this case, we might have to add the flush when re-trying the transaction. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Fix error message for chain renamingPhil Sutter2019-02-131-1/+7
| | | | | | | | | If the new name already exists, legacy iptables prints "File exists.". This is a bit exotic, but more appropriate than "No chain/target/match by that name." printed by iptables-nft without this patch. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Fix error messages in commands with rule numberPhil Sutter2019-02-131-6/+6
| | | | | | | | | | | | Use E2BIG if rule identified by given number is not found. ENOENT is used if referenced chain is not found. Without this, a command specifying a non-existing chain in combination with a rule number like e.g.: 'iptables-nft -I nonexist 23 -j ACCEPT' returns "Index of insertion too big." instead of "No chain/target/match by that name." like legacy iptables does. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Move new chain check to where it belongsPhil Sutter2019-02-131-0/+5
| | | | | | | | Instead of checking chain existence in xtables.c, do it in nft_chain_user_add() and reuse predefined error message. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* xtables: Fix error message when zeroing a non-existent chainPhil Sutter2019-02-131-1/+3
| | | | | | | | | | | | | Previously, error message was a bit misleading: | # iptables-nft -Z noexist | iptables: Incompatible with this kernel. Set errno value so that the typical "No chain/target/match by that name." is printed instead. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nft: Eliminate dead code in __nft_rule_listPhil Sutter2019-02-111-12/+1
| | | | | | | | | | | If passed a rulenum > 0, the function uses nftnl_rule_lookup_byindex() and returns early. Negative rulenum values are not supposed to happen, so the remaining code which iterates over the full list of rules does not need to respect rulenum anymore. Fixes: 039b048965210 ("nft: Make use of nftnl_rule_lookup_byindex()") Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* ebtables-nft: Support user-defined chain policiesPhil Sutter2019-02-081-2/+226
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Legacy ebtables supports policies for user-defined chains - and what's worse, they default to ACCEPT unlike anywhere else. So lack of support for this braindead feature in ebtables-nft is actually a change of behaviour which very likely affects all ebtables users out there. The solution implemented here uses an implicit (and transparent) last rule in all user-defined ebtables-nft chains with policy other than RETURN. This rule is identified by an nft comment "XTABLES_EB_INTERNAL_POLICY_RULE" (since commit ccf154d7420c0 ("xtables: Don't use native nftables comments") nft comments are not used otherwise). To minimize interference with existing code, this policy rule is removed from chains during cache population and the policy is saved in NFTNL_CHAIN_POLICY attribute. When committing changes to the kernel, nft_commit() traverses through the list of chains and (re-)creates policy rules if required. In ebtables-nft-restore, table flushes are problematic. To avoid weird kernel error responses, introduce a custom 'table_flush' callback which removes any pending policy rule add/remove jobs prior to creating the NFT_COMPAT_TABLE_FLUSH one. I've hidden all this mess behind checks for h->family, so hopefully impact on {ip,ip6,arp}tables-nft should be negligible. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>
* nft: Introduce UDATA_TYPE_EBTABLES_POLICYPhil Sutter2019-02-081-0/+3
| | | | | | | | | This will be used later to identify ebtables user-defined chain policy rules. Signed-off-by: Phil Sutter <phil@nwl.cc> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fw@strlen.de>