summaryrefslogtreecommitdiffstats
path: root/src/netlink_delinearize.c
Commit message (Collapse)AuthorAgeFilesLines
* netlink_delinearize: fix wrong conversion to "list" in ct markFernando Fernandez Mancera2019-09-101-1/+2
| | | | | | | | | | | We only prefer "list" representation in "ct event". For any other type of "ct" use the "or" representation so nft prints "ct mark set ct mark | 0x00000001" instead of "ct mark set ct mark,0x00000001". Link: https://bugzilla.netfilter.org/show_bug.cgi?id=1364 Fixes: cb8f81ac3079 ("netlink_delinearize: prefer ct event set foo,bar over 'set foo|bar'") Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: introduce SYNPROXY matchingFernando Fernandez Mancera2019-07-171-0/+17
| | | | | | | | | | | | | | | | | | | | Add support for "synproxy" statement. For example (for TCP port 8888): table ip x { chain y { type filter hook prerouting priority raw; policy accept; tcp dport 8888 tcp flags syn notrack } chain z { type filter hook input priority filter; policy accept; tcp dport 8888 ct state invalid,untracked synproxy mss 1460 wscale 7 timestamp sack-perm ct state invalid drop } } Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* ct: support for NFT_CT_{SRC,DST}_{IP,IP6}Pablo Neira Ayuso2019-06-211-1/+1
| | | | | | | | | | | | | | | | | These keys are available since kernel >= 4.17. You can still use NFT_CT_{SRC,DST}, however, you need to specify 'meta protocol' in first place to provide layer 3 context. Note that NFT_CT_{SRC,DST} are broken with set, maps and concatenations. This patch is implicitly fixing these cases. If your kernel is < 4.17, you can still use address matching via explicit meta nfproto: meta nfproto ipv4 ct original saddr 1.2.3.4 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: statement: disable reject statement type omission for bridgeFlorian Westphal2019-06-191-0/+6
| | | | | | | | | | | | | add rule bridge test-bridge input reject with icmp type port-unreachable ... will be printed as 'reject', which is fine on ip family, but not on bridge -- 'with icmp type' adds an ipv4 dependency, but simple reject does not (it will use icmpx to also reject ipv6 packets with an icmpv6 error). Add a toggle to supress short-hand versions in this case. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinerize: remove network header dep for reject statement also in ↵Florian Westphal2019-06-191-0/+4
| | | | | | | | | | | | | | | | | | | | | bridge family add rule bridge test-bridge input reject with icmp type ... is shown as ether type ip reject type ... i.e., the dependency is not removed. Allow dependency removal -- this adds a problem where some icmp types will be shortened to 'reject', losing the icmp ipv4 dependency. Next patch resolves this problem by disabling short-hand abbreviations for bridge reject statements. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: use-after-free in expr_postprocess_string()Pablo Neira Ayuso2019-06-131-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | escaped_string_wildcard_expr_alloc() may reallocate the expression. valgrind reports errors like this one: ==29945== Invalid write of size 4 ==29945== at 0x72EE944: __expr_postprocess_string (netlink_delinearize.c:2006) ==29945== by 0x72EE944: expr_postprocess_string (netlink_delinearize.c:2016) ==29945== by 0x72EE944: expr_postprocess (netlink_delinearize.c:2120) ==29945== by 0x72EE5A7: expr_postprocess (netlink_delinearize.c:2094) ==29945== by 0x72EF23B: stmt_expr_postprocess (netlink_delinearize.c:2289) ==29945== by 0x72EF23B: rule_parse_postprocess (netlink_delinearize.c:2510) ==29945== by 0x72EF23B: netlink_delinearize_rule (netlink_delinearize.c:2650) ==29945== by 0x72E6F63: list_rule_cb (netlink.c:330) ==29945== by 0x7770BD3: nftnl_rule_list_foreach (rule.c:810) ==29945== by 0x72E739E: netlink_list_rules (netlink.c:349) ==29945== by 0x72E739E: netlink_list_table (netlink.c:490) ==29945== by 0x72D4A89: cache_init_objects (rule.c:194) ==29945== by 0x72D4A89: cache_init (rule.c:216) ==29945== by 0x72D4A89: cache_update (rule.c:266) ==29945== by 0x72F829E: nft_evaluate (libnftables.c:388) ==29945== by 0x72F8A5B: nft_run_cmd_from_buffer (libnftables.c:428) Remove expr->len, not needed and it triggers use-after-free errors. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add reference counter for dynamic datatypesPablo Neira Ayuso2019-06-131-10/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There are two datatypes are using runtime datatype allocation: * Concatenations. * Integer, that require byteorder adjustment. From the evaluation / postprocess step, transformations are common, hence expressions may end up fetching (infering) datatypes from an existing one. This patch adds a reference counter to release the dynamic datatype object when it is shared. The API includes the following helper functions: * datatype_set(expr, datatype), to assign a datatype to an expression. This helper already deals with reference counting for dynamic datatypes. This also drops the reference counter of any previous datatype (to deal with the datatype replacement case). * datatype_get(datatype) bumps the reference counter. This function also deals with nul-pointers, that occurs when the datatype is unset. * datatype_free() drops the reference counter, and it also releases the datatype if there are not more clients of it. Rule of thumb is: The reference counter of any newly allocated datatype is set to zero. This patch also updates every spot to use datatype_set() for non-dynamic datatypes, for consistency. In this case, the helper just makes an simple assignment. Note that expr_alloc() has been updated to call datatype_get() on the datatype that is assigned to this new expression. Moreover, expr_free() calls datatype_free(). This fixes valgrind reports like this one: ==28352== 1,350 (440 direct, 910 indirect) bytes in 5 blocks are definitely lost in loss recor 3 of 3 ==28352== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==28352== by 0x4E79558: xmalloc (utils.c:36) ==28352== by 0x4E7963D: xzalloc (utils.c:65) ==28352== by 0x4E6029B: dtype_alloc (datatype.c:1073) ==28352== by 0x4E6029B: concat_type_alloc (datatype.c:1127) ==28352== by 0x4E6D3B3: netlink_delinearize_set (netlink.c:578) ==28352== by 0x4E6D68E: list_set_cb (netlink.c:648) ==28352== by 0x5D74023: nftnl_set_list_foreach (set.c:780) ==28352== by 0x4E6D6F3: netlink_list_sets (netlink.c:669) ==28352== by 0x4E5A7A3: cache_init_objects (rule.c:159) ==28352== by 0x4E5A7A3: cache_init (rule.c:216) ==28352== by 0x4E5A7A3: cache_update (rule.c:266) ==28352== by 0x4E7E0EE: nft_evaluate (libnftables.c:388) ==28352== by 0x4E7EADD: nft_run_cmd_from_filename (libnftables.c:479) ==28352== by 0x109A53: main (main.c:310) This patch also removes the DTYPE_F_CLONE flag which is broken and not needed anymore since proper reference counting is in place. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: release expression before calling ↵Pablo Neira Ayuso2019-06-101-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | netlink_parse_concat_expr() netlink_get_register() clones the expression in the register. Release this expression before calling netlink_parse_concat_expr() to deconstruct the concatenation. ==15069== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==15069== by 0x4E79508: xmalloc (utils.c:36) ==15069== by 0x4E795ED: xzalloc (utils.c:65) ==15069== by 0x4E6029B: dtype_alloc (datatype.c:1073) ==15069== by 0x4E6029B: concat_type_alloc (datatype.c:1127) ==15069== by 0x4E6D3B3: netlink_delinearize_set (netlink.c:578) ==15069== by 0x4E6D68E: list_set_cb (netlink.c:648) ==15069== by 0x5F34023: nftnl_set_list_foreach (set.c:780) ==15069== by 0x4E6D6F3: netlink_list_sets (netlink.c:669) ==15069== by 0x4E5A7A3: cache_init_objects (rule.c:159) ==15069== by 0x4E5A7A3: cache_init (rule.c:216) ==15069== by 0x4E5A7A3: cache_update (rule.c:266) ==15069== by 0x4E7E09E: nft_evaluate (libnftables.c:388) ==15069== by 0x4E7E85B: nft_run_cmd_from_buffer (libnftables.c:428) Reported-by: Václav Zindulka <vaclav.zindulka@tlapnet.cz> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: release expressions in context registersPablo Neira Ayuso2019-06-101-3/+3
| | | | | | | | | netlink_release_registers() needs to go a bit further to release the expressions in the register array. This should be safe since netlink_get_register() clones expressions in the context registers. Reported-by: Václav Zindulka <vaclav.zindulka@tlapnet.cz> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink: Fix printing of zero-length prefixesPhil Sutter2019-05-091-1/+3
| | | | | | | | | | | | | | | | | | | When delinearizing, an all-zero mask didn't qualify as prefix. Therefore a statement: | ip daddr 0.0.0.0/0 would be printed as: | ip daddr & 0.0.0.0 == 0.0.0.0 To fix this, expr_mask_is_prefix() must return true if the initial 1-bit search fails (the given value must be zero in this case). Additionally, a shortcut is needed in conversion algorithm of expr_mask_to_prefix() to not turn the zero prefix into a 1 by accident. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: use UDATA defines from libnftnlPhil Sutter2019-05-031-14/+15
| | | | | | | | | | | | | Userdata attribute names have been added to libnftnl, use them instead of the local copy. While being at it, rename udata_get_comment() in netlink_delinearize.c and the callback it uses since the function is specific to rules. Also integrate the existence check for NFTNL_RULE_USERDATA into it along with the call to nftnl_rule_get_data(). Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add nat support for the inet familyFlorian Westphal2019-04-091-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | consider a simple ip6 nat table: table ip6 nat { chain output { type nat hook output priority 0; policy accept; dnat to dead:2::99 } Now consider same ruleset, but using 'table inet nat': nft now lacks context to determine address family to parse 'to $address'. This adds code to make the following work: table inet nat { [ .. ] # detect af from network protocol context: ip6 daddr dead::2::1 dnat to dead:2::99 # use new dnat ip6 keyword: dnat ip6 to dead:2::99 } On list side, the keyword is only shown in the inet family, else the short version (dnat to ...) is used as the family is redundant when the table already mandates the ip protocol version supported. Address mismatches such as table ip6 { .. dnat ip to 1.2.3.4 are detected/handled during the evaluation phase. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* osf: add version fingerprint supportFernando Fernandez Mancera2019-04-081-1/+3
| | | | | | | | | | | | | | | Add support for version fingerprint in "osf" expression. Example: table ip foo { chain bar { type filter hook input priority filter; policy accept; osf ttl skip name "Linux" osf ttl skip version "Linux:4.20" } } Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: expr: add expression etypeFlorian Westphal2019-02-081-37/+36
| | | | | | | | Temporary kludge to remove all the expr->ops->type == ... patterns. Followup patch will remove expr->ops, and make expr_ops() lookup the correct expr_ops struct instead to reduce struct expr size. Signed-off-by: Florian Westphal <fw@strlen.de>
* src: payload: export and use payload_expr_cmpFlorian Westphal2019-02-081-1/+1
| | | | | | | expr->ops is going away, so export payload cmp and use it directly. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: expr: add and use expr_name helperFlorian Westphal2019-02-081-4/+4
| | | | | | | | Currently callers use expr->ops->name, but follouwp patch will remove the ops pointer from struct expr. So add this helper and use it everywhere. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
* osf: add ttl option supportFernando Fernandez Mancera2018-10-231-1/+4
| | | | | | | | | | | | | | Add support for ttl option in "osf" expression. Example: table ip foo { chain bar { type filter hook input priority filter; policy accept; osf ttl skip name "Linux" } } Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: pass struct nft_ctx through struct netlink_ctxPablo Neira Ayuso2018-10-221-2/+2
| | | | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* Fix memleak in netlink_parse_fwd() error pathPhil Sutter2018-10-151-5/+8
| | | | | | | | Make sure allocated 'stmt' is freed before returning to caller. Fixes: 30d45266bf38b ("expr: extend fwd statement to support address and family") Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add ipsec (xfrm) expressionMáté Eckl2018-09-211-0/+21
| | | | | | | | | | | | | | | | This allows matching on ipsec tunnel/beet addresses in xfrm state associated with a packet, ipsec request id and the SPI. Examples: ipsec in ip saddr 192.168.1.0/24 ipsec out ip6 daddr @endpoints ipsec in spi 1-65536 Joint work with Florian Westphal. Cc: Máté Eckl <ecklm94@gmail.com> Signed-off-by: Florian Westphal <fw@strlen.de>
* src: integrate stateful expressions into sets and mapsPablo Neira Ayuso2018-08-241-11/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The following example shows how to populate a set from the packet path using the destination IP address, for each entry there is a counter. The entry expires after the 1 hour timeout if no packets matching this entry are seen. table ip x { set xyz { type ipv4_addr size 65535 flags dynamic,timeout timeout 1h } chain y { type filter hook output priority filter; policy accept; update @xyz { ip daddr counter } counter } } Similar example, that creates a mapping better IP address and mark, where the mark is assigned using an incremental sequence generator from 0 to 1 inclusive. table ip x { map xyz { type ipv4_addr : mark size 65535 flags dynamic,timeout timeout 1h } chain y { type filter hook input priority filter; policy accept; update @xyz { ip saddr counter : numgen inc mod 2 } } } Supported stateful statements are: limit, quota, counter and connlimit. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: simplify map statementPablo Neira Ayuso2018-08-241-1/+6
| | | | | | | Instead of using the map expression, store dynamic key and data separately since they need special handling than constant maps. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: introduce passive OS fingerprint matchingFernando Fernandez Mancera2018-08-041-0/+14
| | | | | | | | | | | | | | Add support for "osf" expression. Example: table ip foo { chain bar { type filter hook input priority 0; policy accept; osf name "Linux" counter packets 3 bytes 132 } } Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: Add tproxy supportMáté Eckl2018-08-031-0/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This patch adds support for transparent proxy functionality which is supported in ip, ip6 and inet tables. The syntax is the following: tproxy [{|ip|ip6}] to {<ip address>|:<port>|<ip address>:<port>} It looks for a socket listening on the specified address or port and assigns it to the matching packet. In an inet table, a packet matches for both families until address is specified. Network protocol family has to be specified **only** in inet tables if address is specified. As transparent proxy support is implemented for sockets with layer 4 information, a transport protocol header criterion has to be set in the same rule. eg. 'meta l4proto tcp' or 'udp dport 4444' Example ruleset: table ip x { chain y { type filter hook prerouting priority -150; policy accept; tcp dport ntp tproxy to 1.1.1.1 udp dport ssh tproxy to :2222 } } table ip6 x { chain y { type filter hook prerouting priority -150; policy accept; tcp dport ntp tproxy to [dead::beef] udp dport ssh tproxy to :2222 } } table inet x { chain y { type filter hook prerouting priority -150; policy accept; tcp dport 321 tproxy to :ssh tcp dport 99 tproxy ip to 1.1.1.1:999 udp dport 155 tproxy ip6 to [dead::beef]:smux } } Signed-off-by: Máté Eckl <ecklm94@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: Refactor meta_may_dependency_kill()Phil Sutter2018-06-261-40/+43
| | | | | | | | | | | | | | | | The original intent was to fix a bug: The following rule in inet table: | meta nfproto ipv4 icmpv6 type echo-reply Was added correctly but when printing the meta match was falsely removed. The fix is to deny dependency killing if RHS family of nfproto match doesn't match RHS family of l4proto match. Adding this to the already large conditional led to even more unreadable code, therefore this patch tries to clean that up (and also removes the partial code duplication. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* src: netlink_delinarize: don't stop when encountering unsupported expressionFlorian Westphal2018-06-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | The error message is still shown, but try to make sense of further expressions (if any). I tried to replace the expression by a textual representation. Two variants I tested are: 1. append as comment: ip saddr 127.0.0.2 drop comment "unknown expression 'foo'" This allows nft -f, but it adds/alters a comment. 2. substitute in-place (i.e., add a constant expression with the error message instead of 'unkown' message: unknown expression "foo" ip saddr 127.0.0.2 drop This won't allow 'nft -f' however. I'm not sure this is a problem, in any case we lose information if we can't find an expression (e.g. added by newer version). Signed-off-by: Florian Westphal <fw@strlen.de>
* src: Introduce socket matchingMáté Eckl2018-06-061-0/+17
| | | | | | | | | | | | | | | | For now it can only match sockets with IP(V6)_TRANSPARENT socket option set. Example: table inet sockin { chain sockchain { type filter hook prerouting priority -150; policy accept; socket transparent 1 mark set 0x00000001 nftrace set 1 counter packets 9 bytes 504 accept } } Signed-off-by: Máté Eckl <ecklm94@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* expr: extend fwd statement to support address and familyPablo Neira Ayuso2018-06-061-5/+36
| | | | | | | | Allow to forward packets through to explicit destination and interface. nft add rule netdev x y fwd ip to 192.168.2.200 device eth0 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: connlimit supportPablo Neira Ayuso2018-06-061-0/+16
| | | | | | | | | | | | | | This patch adds support for the new connlimit stateful expression, that provides a mapping with the connlimit iptables extension through meters. eg. nft add rule filter input tcp dport 22 \ meter test { ip saddr ct count over 2 } counter reject This limits the maximum amount incoming of SSH connections per source address up to 2 simultaneous connections. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* nat: Eliminate misuse of AF_*Máté Eckl2018-06-061-2/+2
| | | | | | | | | Although the value of AF_INET and NFPROTO_IPV4 is the same, the use of AF_INET was misleading when checking the proto family. Same with AF_INET6. Signed-off-by: Máté Eckl <ecklm94@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* fix printing of "tcp flags syn" and "tcp flags == syn" expressionsSabrina Dubroca2018-05-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | Commit 6979625686ec ("relational: Eliminate meta OPs") introduced some bugs when printing bitmask types. First, during the post-processing phase of delinearization, the expression for "tcp flags syn" (PAYLOAD & flag != 0) gets converted to PAYLOAD == flag, which is not equivalent. This should be PAYLOAD (IMPL) flag. Then, during output, the "==" sign from "tcp flags == syn" is dropped, because the bitmask condition in must_print_eq_op() was removed. Let's restore it, so that "tcp flags == syn" doesn't get printed as "tcp flags syn". An extra check for value types is added, so that we don't start printing "==" for sets such as "tcp flags {syn,ack}" Finally, add a regression test for this particular case. Fixes: 6979625686ec ("relational: Eliminate meta OPs") Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: Florian Westphal <fw@strlen.de>
* src: add chain_specPablo Neira Ayuso2018-05-061-2/+2
| | | | | | Store location object in handle to improve error reporting. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add table_specPablo Neira Ayuso2018-05-061-1/+1
| | | | | | Store location object in handle to improve error reporting. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* meter: enforce presence of a max sizeFlorian Westphal2018-05-021-0/+1
| | | | | | | | | | meters are updated dynamically, so we don't know in advance how large this structure can be. Add a 'size' keyword to specifiy an upper limit and update the old syntax to assume a default max value of 65535. Signed-off-by: Florian Westphal <fw@strlen.de>
* netlink_delinearize: kill dependency before eval of 'redirect' stmtFlorian Westphal2018-04-011-1/+3
| | | | | | | | | | | | | ip protocol 6 redirect to :tcp dport map { 22 : 8000, 80 : 8080} is printed as redirect to :tcp dport map { 22 : 8000, 80 : 8080} but that input yields: Error: transport protocol mapping is only valid after transport protocol match so kill dependencies beforehand so nft won't remove it. Signed-off-by: Florian Westphal <fw@strlen.de>
* Combine redir and masq statements into natPhil Sutter2018-03-171-18/+14
| | | | | | | | | | | | | | | | | | | All these statements are very similar, handling them with the same code is obvious. The only thing required here is a custom extension of enum nft_nat_types which is used in nat_stmt to distinguish between snat and dnat already. Though since enum nft_nat_types is part of kernel uAPI, create a local extended version containing the additional fields. Note that nat statement printing got a bit more complicated to get the number of spaces right for every possible combination of attributes. Note also that there wasn't a case for STMT_MASQ in rule_parse_postprocess(), which seems like a bug. Since STMT_MASQ became just a variant of STMT_NAT, postprocessing will take place for it now anyway. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: netlink_delinearize: don't assume element contains a valueFlorian Westphal2018-03-171-1/+1
| | | | | | | | | | | We cannot assume i->key->key is EXPR_VALUE, we could look e.g. at a range, which will trigger an assertion failure in binop_adjust_one(). We should call __binop_adjust recursively again in the EXPR_SET_ELEM case, using key as new input. Fixes: b8b8e7b6ae10 ("evaluate: transfer right shifts to set reference side") Signed-off-by: Florian Westphal <fw@strlen.de>
* relational: Eliminate meta OPsPhil Sutter2018-03-161-12/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | With a bit of code reorganization, relational meta OPs OP_RANGE, OP_FLAGCMP and OP_LOOKUP become unused and can be removed. The only meta OP left is OP_IMPLICIT which is usually treated as alias to OP_EQ. Though it needs to stay in place for one reason: When matching against a bitmask (e.g. TCP flags or conntrack states), it has a different meaning: | nft --debug=netlink add rule ip t c tcp flags syn | ip t c | [ meta load l4proto => reg 1 ] | [ cmp eq reg 1 0x00000006 ] | [ payload load 1b @ transport header + 13 => reg 1 ] | [ bitwise reg 1 = (reg=1 & 0x00000002 ) ^ 0x00000000 ] | [ cmp neq reg 1 0x00000000 ] | nft --debug=netlink add rule ip t c tcp flags == syn | ip t c | [ meta load l4proto => reg 1 ] | [ cmp eq reg 1 0x00000006 ] | [ payload load 1b @ transport header + 13 => reg 1 ] | [ cmp eq reg 1 0x00000002 ] OP_IMPLICIT creates a match which just checks the given flag is present, while OP_EQ creates a match which ensures the given flag and no other is present. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: support of dynamic map addition and update of elementsLaura Garcia Liebana2018-03-151-2/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The support of dynamic adds and updates are only available for sets and meters. This patch gives such abilities to maps as well. This patch is useful in cases where dynamic population of maps are required, for example, to maintain a persistence during some period of time. Example: table ip nftlb { map persistencia { type ipv4_addr : mark timeout 1h elements = { 192.168.1.132 expires 59m55s : 0x00000064, 192.168.56.101 expires 59m24s : 0x00000065 } } chain pre { type nat hook prerouting priority 0; policy accept; map update \ { @nh,96,32 : numgen inc mod 2 offset 100 } @persistencia } } An example of the netlink generated sequence: nft --debug=netlink add rule ip nftlb pre map add \ { ip saddr : numgen inc mod 2 offset 100 } @persistencia ip nftlb pre [ payload load 4b @ network header + 12 => reg 1 ] [ numgen reg 2 = inc mod 2 offset 100 ] [ dynset add reg_key 1 set persistencia sreg_data 2 ] Signed-off-by: Laura Garcia Liebana <nevola@gmail.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: flow offload supportPablo Neira Ayuso2018-03-051-0/+11
| | | | | | | | | | | | This patch allows us to refer to existing flowtables: # nft add rule x x flow offload @m Packets matching this rule create an entry in the flow table 'm', hence, follow up packets that get to the flowtable at ingress bypass the classic forwarding path. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: Fix resource leaksPhil Sutter2018-03-021-52/+92
| | | | | | | | | | | | | | | | | | Most of the cases are basically the same: Error path fails to free the previously allocated statement or expression. A few cases received special treatment though: - In netlink_parse_payload_stmt(), the leak is easily avoided by code reordering. - In netlink_parse_exthdr(), there's no point in introducing a goto label since there is but a single affected error check. - In netlink_parse_hash() non-error path leaked as well if sreg contained a concatenated expression. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* Review switch statements for unmarked fall through casesPhil Sutter2018-02-281-0/+1
| | | | | | | | | | | | | | While revisiting all of them, clear a few oddities as well: - There's no point in marking empty fall through cases: They are easy to spot and a common concept when using switch(). - Fix indenting of break statement in one occasion. - Drop needless braces around one case which doesn't declare variables. Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>
* meta: introduce datatype ifname_typeArturo Borrero Gonzalez2018-02-251-7/+6
| | | | | | | | | | | | | | | | | | | | | | | | This new datatype is a string subtype. It will allow us to build named maps/sets using meta keys like 'iifname', 'oifname', 'ibriport' or 'obriport'. Example: table inet t { set s { type ifname elements = { "eth0", "eth1" } } chain c { iifname @s accept oifname @s accept } } Signed-off-by: Arturo Borrero Gonzalez <arturo@netfilter.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: Spelling fixesVille Skyttä2018-02-151-1/+1
| | | | | Signed-off-by: Ville Skyttä <ville.skytta@iki.fi> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: add meta_may_dependency_kill()Pablo Neira Ayuso2018-02-151-1/+71
| | | | | | | | | | | | | Do not exercise dependency removal for protocol key network payload expressions in bridge, netdev and inet families from meta expressions, more specifically: * inet: nfproto and ether type. * netdev and bridge: meta protocol and ether type. need to be left in place. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: get rid of __payload_dependency_kill()Pablo Neira Ayuso2018-02-151-6/+3
| | | | | | Use payload_dependency_release() instead. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: add payload_dependency_exists()Pablo Neira Ayuso2018-02-151-6/+9
| | | | | | | | | | | | | | | This helper function tells us if there is already a protocol key payload expression, ie. those with EXPR_F_PROTOCOL flag set on, that we might want to remove since we can infer from another expression in the upper protocol base, eg. ip protocol tcp tcp dport 22 'ip protocol tcp' can be removed in the ip family since it is redundant, but not in the netdev, bridge and inet families, where we cannot make assumptions on the layer 3 protocol. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: pass family to payload_dependency_kill()Pablo Neira Ayuso2018-02-151-7/+11
| | | | | | | | | This context information is very relevant when deciding if a redundant dependency needs to be removed or not, specifically for the inet, bridge and netdev families. This new parameter is used by follow up patch entitled ("payload: add payload_may_dependency_kill()"). Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* netlink_delinearize: add assertion to prevent infinite loopPablo Neira Ayuso2018-02-021-1/+4
| | | | | | | | | | | | | | | | | | | | | | | The following configuration: table inet filter { chain input { ct original ip daddr {1.2.3.4} accept } } is triggering an infinite loop. This problem also exists with concatenations and ct ip {s,d}addr. Until we have a solution for this, let's just prevent infinite loops. Now we hit this: # nft list ruleset nft: netlink_delinearize.c:124: netlink_parse_concat_expr: Assertion `consumed > 0' failed. Abort Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
* src: fix protocol context update on big-endian systemsPhil Sutter2017-12-121-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | There is an obscure bug on big-endian systems when trying to list a rule containing the expression 'ct helper tftp' which triggers the assert() call in mpz_get_type(). Florian identified the cause: ct_expr_pctx_update() is called for the relational expression which calls mpz_get_uint32() to get RHS value (assuming it is a protocol number). On big-endian systems, the misinterpreted value exceeds UINT_MAX. Expressions' pctx_update() callback should only be called for protocol matches, so ct_meta_common_postprocess() lacked a check for 'left->flags & EXPR_F_PROTOCOL' like the one already present in payload_expr_pctx_update(). In order to fix this in a clean way, this patch introduces a wrapper relational_expr_pctx_update() to be used instead of directly calling LHS's pctx_update() callback which unifies the necessary checks (and adds one more assert): - assert(expr->ops->type == EXPR_RELATIONAL) -> This is new, just to ensure the wrapper is called properly. - assert(expr->op == OP_EQ) -> This was moved from {ct,meta,payload}_expr_pctx_update(). - left->ops->pctx_update != NULL -> This was taken from expr_evaluate_relational(), a necessary requirement for the introduced wrapper to function at all. - (left->flags & EXPR_F_PROTOCOL) != 0 -> The crucial missing check which led to the problem. Suggested-by: Florian Westphal <fw@strlen.de> Signed-off-by: Phil Sutter <phil@nwl.cc> Signed-off-by: Florian Westphal <fw@strlen.de>