diff --git a/SOURCES/0001-evaluate-reject-Allow-icmpx-in-inet-bridge-families.patch b/SOURCES/0001-evaluate-reject-Allow-icmpx-in-inet-bridge-families.patch index d6a76ed..4aafcba 100644 --- a/SOURCES/0001-evaluate-reject-Allow-icmpx-in-inet-bridge-families.patch +++ b/SOURCES/0001-evaluate-reject-Allow-icmpx-in-inet-bridge-families.patch @@ -223,5 +223,5 @@ index 7a6468e81f9e7..ee1aae02f1e1d 100644 + [ reject type 2 code 3 ] + -- -2.19.0 +2.21.0 diff --git a/SOURCES/0002-monitor-Drop-fake-XML-support.patch b/SOURCES/0002-monitor-Drop-fake-XML-support.patch index aad6e58..08e6467 100644 --- a/SOURCES/0002-monitor-Drop-fake-XML-support.patch +++ b/SOURCES/0002-monitor-Drop-fake-XML-support.patch @@ -67,5 +67,5 @@ index 4310c3b8dc434..d75410888e3d0 100644 nftnl_rule_fprintf(monh->ctx->octx->output_fp, nlr, monh->format, netlink_msg2nftnl_of(type)); -- -2.19.0 +2.21.0 diff --git a/SOURCES/0003-monitor-Drop-update-table-and-update-chain-cases.patch b/SOURCES/0003-monitor-Drop-update-table-and-update-chain-cases.patch index 447cb12..8c23bb4 100644 --- a/SOURCES/0003-monitor-Drop-update-table-and-update-chain-cases.patch +++ b/SOURCES/0003-monitor-Drop-update-table-and-update-chain-cases.patch @@ -44,5 +44,5 @@ index d75410888e3d0..3e70b89f0b2ab 100644 c = netlink_delinearize_chain(monh->ctx, nlc); chain_print_plain(c, monh->ctx->octx); -- -2.19.0 +2.21.0 diff --git a/SOURCES/0004-monitor-Fix-printing-of-ct-objects.patch b/SOURCES/0004-monitor-Fix-printing-of-ct-objects.patch index f54e6f5..ca630d7 100644 --- a/SOURCES/0004-monitor-Fix-printing-of-ct-objects.patch +++ b/SOURCES/0004-monitor-Fix-printing-of-ct-objects.patch @@ -160,5 +160,5 @@ index 0000000000000..7b88409775796 +I delete ct helper ip t cth +O - -- -2.19.0 +2.21.0 diff --git a/SOURCES/0005-monitor-Use-libnftables-JSON-output.patch b/SOURCES/0005-monitor-Use-libnftables-JSON-output.patch index e6e47dd..2523ce9 100644 --- a/SOURCES/0005-monitor-Use-libnftables-JSON-output.patch +++ b/SOURCES/0005-monitor-Use-libnftables-JSON-output.patch @@ -648,5 +648,5 @@ index eb06302d4f223..3065cc5474bbf 100644 struct table *table_alloc(void) -- -2.19.0 +2.21.0 diff --git a/SOURCES/0006-tests-monitor-Test-JSON-output-as-well.patch b/SOURCES/0006-tests-monitor-Test-JSON-output-as-well.patch index 9fa9726..b2ca0ca 100644 --- a/SOURCES/0006-tests-monitor-Test-JSON-output-as-well.patch +++ b/SOURCES/0006-tests-monitor-Test-JSON-output-as-well.patch @@ -364,5 +364,5 @@ index e4dc073e14b65..78d8f8b04bd36 100644 O add counter ip t cnt { packets 0 bytes 0 } +J {"add": {"counter": {"family": "ip", "name": "cnt", "table": "t", "handle": 0, "packets": 0, "bytes": 0}}} -- -2.19.0 +2.21.0 diff --git a/SOURCES/0007-segtree-bogus-range-via-get-set-element-on-existing-.patch b/SOURCES/0007-segtree-bogus-range-via-get-set-element-on-existing-.patch index ab5d9fe..2b0e0e9 100644 --- a/SOURCES/0007-segtree-bogus-range-via-get-set-element-on-existing-.patch +++ b/SOURCES/0007-segtree-bogus-range-via-get-set-element-on-existing-.patch @@ -144,5 +144,5 @@ index 8a8aa71e8a6e2..288b01f420a48 100644 static bool range_is_prefix(const mpz_t range) -- -2.19.0 +2.21.0 diff --git a/SOURCES/0008-segtree-disantangle-get_set_interval_end.patch b/SOURCES/0008-segtree-disantangle-get_set_interval_end.patch index e9a5c04..5b84089 100644 --- a/SOURCES/0008-segtree-disantangle-get_set_interval_end.patch +++ b/SOURCES/0008-segtree-disantangle-get_set_interval_end.patch @@ -105,5 +105,5 @@ index 288b01f420a48..0d53c83fd837e 100644 set->init = new_init; -- -2.19.0 +2.21.0 diff --git a/SOURCES/0009-segtree-memleak-in-get_set_decompose.patch b/SOURCES/0009-segtree-memleak-in-get_set_decompose.patch index 2f72aed..0a2eac0 100644 --- a/SOURCES/0009-segtree-memleak-in-get_set_decompose.patch +++ b/SOURCES/0009-segtree-memleak-in-get_set_decompose.patch @@ -34,5 +34,5 @@ index 0d53c83fd837e..dc2554b72acf3 100644 return 0; -- -2.19.0 +2.21.0 diff --git a/SOURCES/0010-segtree-stop-iteration-on-existing-elements-in-case-.patch b/SOURCES/0010-segtree-stop-iteration-on-existing-elements-in-case-.patch index 79bc36d..5ba7493 100644 --- a/SOURCES/0010-segtree-stop-iteration-on-existing-elements-in-case-.patch +++ b/SOURCES/0010-segtree-stop-iteration-on-existing-elements-in-case-.patch @@ -56,5 +56,5 @@ index dc2554b72acf3..dc457d6bc1b7d 100644 mpz_clear(high); -- -2.19.0 +2.21.0 diff --git a/SOURCES/0011-segtree-incorrect-handling-of-last-element-in-get_se.patch b/SOURCES/0011-segtree-incorrect-handling-of-last-element-in-get_se.patch index dd39952..f64907a 100644 --- a/SOURCES/0011-segtree-incorrect-handling-of-last-element-in-get_se.patch +++ b/SOURCES/0011-segtree-incorrect-handling-of-last-element-in-get_se.patch @@ -28,5 +28,5 @@ index dc457d6bc1b7d..4ee09884cbde6 100644 compound_expr_add(new_init, expr_clone(left)); } -- -2.19.0 +2.21.0 diff --git a/SOURCES/0012-segtree-set-proper-error-cause-on-existing-elements.patch b/SOURCES/0012-segtree-set-proper-error-cause-on-existing-elements.patch index 86fbda6..d7d852d 100644 --- a/SOURCES/0012-segtree-set-proper-error-cause-on-existing-elements.patch +++ b/SOURCES/0012-segtree-set-proper-error-cause-on-existing-elements.patch @@ -45,5 +45,5 @@ index 4ee09884cbde6..5685618b3724a 100644 goto out; } -- -2.19.0 +2.21.0 diff --git a/SOURCES/0013-rule-fix-memleak-in-do_get_setelems.patch b/SOURCES/0013-rule-fix-memleak-in-do_get_setelems.patch index 5ccda60..f203c0a 100644 --- a/SOURCES/0013-rule-fix-memleak-in-do_get_setelems.patch +++ b/SOURCES/0013-rule-fix-memleak-in-do_get_setelems.patch @@ -38,5 +38,5 @@ index 3065cc5474bbf..a157ac91683cc 100644 static int do_command_get(struct netlink_ctx *ctx, struct cmd *cmd) -- -2.19.0 +2.21.0 diff --git a/SOURCES/0014-Fix-memleak-in-netlink_parse_fwd-error-path.patch b/SOURCES/0014-Fix-memleak-in-netlink_parse_fwd-error-path.patch index 9e88ef5..56190df 100644 --- a/SOURCES/0014-Fix-memleak-in-netlink_parse_fwd-error-path.patch +++ b/SOURCES/0014-Fix-memleak-in-netlink_parse_fwd-error-path.patch @@ -46,5 +46,5 @@ index 31d62420d41c8..ae84512c56f3a 100644 stmt->fwd.addr = addr; } -- -2.19.0 +2.21.0 diff --git a/SOURCES/0015-libnftables-Fix-memleak-in-nft_parse_bison_filename.patch b/SOURCES/0015-libnftables-Fix-memleak-in-nft_parse_bison_filename.patch index 9ecfeba..581bf53 100644 --- a/SOURCES/0015-libnftables-Fix-memleak-in-nft_parse_bison_filename.patch +++ b/SOURCES/0015-libnftables-Fix-memleak-in-nft_parse_bison_filename.patch @@ -39,5 +39,5 @@ index 5bc7ba0d210ab..91af169ca7190 100644 return -1; -- -2.19.0 +2.21.0 diff --git a/SOURCES/0016-src-pass-struct-nft_ctx-through-struct-eval_ctx.patch b/SOURCES/0016-src-pass-struct-nft_ctx-through-struct-eval_ctx.patch index 315511c..9b95b2b 100644 --- a/SOURCES/0016-src-pass-struct-nft_ctx-through-struct-eval_ctx.patch +++ b/SOURCES/0016-src-pass-struct-nft_ctx-through-struct-eval_ctx.patch @@ -437,5 +437,5 @@ index 33915ed8702a6..d75cd50fa29b9 100644 static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner, -- -2.19.0 +2.21.0 diff --git a/SOURCES/0017-src-trace-fix-policy-printing.patch b/SOURCES/0017-src-trace-fix-policy-printing.patch index 3a28bd2..9455910 100644 --- a/SOURCES/0017-src-trace-fix-policy-printing.patch +++ b/SOURCES/0017-src-trace-fix-policy-printing.patch @@ -76,5 +76,5 @@ index ca5e9b4a0f8a6..4fd3f2dfefced 100644 trace_print_hdr(nlt, monh->ctx->octx); -- -2.19.0 +2.21.0 diff --git a/SOURCES/0018-rule-list-only-the-table-containing-object.patch b/SOURCES/0018-rule-list-only-the-table-containing-object.patch index 937b57d..ba17c37 100644 --- a/SOURCES/0018-rule-list-only-the-table-containing-object.patch +++ b/SOURCES/0018-rule-list-only-the-table-containing-object.patch @@ -51,5 +51,5 @@ index a157ac91683cc..3b5468d00e79c 100644 list_for_each_entry(obj, &table->objs, list) { if (obj->type != type || -- -2.19.0 +2.21.0 diff --git a/SOURCES/0019-src-pass-struct-nft_ctx-through-struct-netlink_ctx.patch b/SOURCES/0019-src-pass-struct-nft_ctx-through-struct-netlink_ctx.patch index b2d401f..9f2cac8 100644 --- a/SOURCES/0019-src-pass-struct-nft_ctx-through-struct-netlink_ctx.patch +++ b/SOURCES/0019-src-pass-struct-nft_ctx-through-struct-netlink_ctx.patch @@ -1135,5 +1135,5 @@ index 3b5468d00e79c..6acfa3ac1695c 100644 BUG("invalid command object type %u\n", cmd->obj); } -- -2.19.0 +2.21.0 diff --git a/SOURCES/0020-netlink-reset-mnl_socket-field-in-struct-nft_ctx-on-.patch b/SOURCES/0020-netlink-reset-mnl_socket-field-in-struct-nft_ctx-on-.patch index b28e35e..688c3c8 100644 --- a/SOURCES/0020-netlink-reset-mnl_socket-field-in-struct-nft_ctx-on-.patch +++ b/SOURCES/0020-netlink-reset-mnl_socket-field-in-struct-nft_ctx-on-.patch @@ -71,5 +71,5 @@ index 6acfa3ac1695c..47b0d30cbed18 100644 } return -1; -- -2.19.0 +2.21.0 diff --git a/SOURCES/0021-src-remove-opts-field-from-struct-xt_stmt.patch b/SOURCES/0021-src-remove-opts-field-from-struct-xt_stmt.patch index 3856c57..774c912 100644 --- a/SOURCES/0021-src-remove-opts-field-from-struct-xt_stmt.patch +++ b/SOURCES/0021-src-remove-opts-field-from-struct-xt_stmt.patch @@ -67,5 +67,5 @@ index 95d0c5f24c07e..74763d58cafd7 100644 .ip = stmt->xt.entry, .target = stmt->xt.target->t, -- -2.19.0 +2.21.0 diff --git a/SOURCES/0022-JSON-Support-latest-enhancements-of-fwd-statement.patch b/SOURCES/0022-JSON-Support-latest-enhancements-of-fwd-statement.patch index 6815854..e2cec35 100644 --- a/SOURCES/0022-JSON-Support-latest-enhancements-of-fwd-statement.patch +++ b/SOURCES/0022-JSON-Support-latest-enhancements-of-fwd-statement.patch @@ -236,5 +236,5 @@ index 696b55efe8207..966c08b0959c3 100644 + [ fwd sreg_dev 1 sreg_addr 2 nfproto 2 ] + -- -2.19.0 +2.21.0 diff --git a/SOURCES/0023-parser_json-Fix-for-ineffective-family-value-checks.patch b/SOURCES/0023-parser_json-Fix-for-ineffective-family-value-checks.patch index fbb1e2e..68225c7 100644 --- a/SOURCES/0023-parser_json-Fix-for-ineffective-family-value-checks.patch +++ b/SOURCES/0023-parser_json-Fix-for-ineffective-family-value-checks.patch @@ -306,5 +306,5 @@ index af57b3025a104..30de17f8a1e26 100644 return NULL; } -- -2.19.0 +2.21.0 diff --git a/SOURCES/0024-json-Fix-memleak-in-dup_stmt_json.patch b/SOURCES/0024-json-Fix-memleak-in-dup_stmt_json.patch index 0528644..aa20e45 100644 --- a/SOURCES/0024-json-Fix-memleak-in-dup_stmt_json.patch +++ b/SOURCES/0024-json-Fix-memleak-in-dup_stmt_json.patch @@ -29,5 +29,5 @@ index eeba90e266f75..66b02a934a24b 100644 if (stmt->dup.to) { root = json_pack("{s:o}", "addr", expr_print_json(stmt->dup.to, octx)); -- -2.19.0 +2.21.0 diff --git a/SOURCES/0025-json-Fix-for-recent-changes-to-context-structs.patch b/SOURCES/0025-json-Fix-for-recent-changes-to-context-structs.patch index 97c5f9b..5f405e2 100644 --- a/SOURCES/0025-json-Fix-for-recent-changes-to-context-structs.patch +++ b/SOURCES/0025-json-Fix-for-recent-changes-to-context-structs.patch @@ -283,5 +283,5 @@ index 30de17f8a1e26..817415c15fb89 100644 json_t *tmp, *value; size_t index; -- -2.19.0 +2.21.0 diff --git a/SOURCES/0026-parser_bison-Fix-for-ECN-keyword-in-LHS-of-relationa.patch b/SOURCES/0026-parser_bison-Fix-for-ECN-keyword-in-LHS-of-relationa.patch index 5d164fa..3b502b4 100644 --- a/SOURCES/0026-parser_bison-Fix-for-ECN-keyword-in-LHS-of-relationa.patch +++ b/SOURCES/0026-parser_bison-Fix-for-ECN-keyword-in-LHS-of-relationa.patch @@ -181,5 +181,5 @@ index 09538aed746c9..2390a24ead15c 100644 inet test-inet input [ meta load l4proto => reg 1 ] -- -2.19.0 +2.21.0 diff --git a/SOURCES/0027-nft.8-Update-meta-pkt_type-value-description.patch b/SOURCES/0027-nft.8-Update-meta-pkt_type-value-description.patch index 1cb85ff..8aaabdc 100644 --- a/SOURCES/0027-nft.8-Update-meta-pkt_type-value-description.patch +++ b/SOURCES/0027-nft.8-Update-meta-pkt_type-value-description.patch @@ -43,5 +43,5 @@ index 3a5571b0da57a..0df42810c5e68 100644 -- -2.19.0 +2.21.0 diff --git a/SOURCES/0028-json-Work-around-segfault-when-encountering-xt-stmt.patch b/SOURCES/0028-json-Work-around-segfault-when-encountering-xt-stmt.patch index bf1a703..a8d5c1f 100644 --- a/SOURCES/0028-json-Work-around-segfault-when-encountering-xt-stmt.patch +++ b/SOURCES/0028-json-Work-around-segfault-when-encountering-xt-stmt.patch @@ -45,5 +45,5 @@ index 98581a3c2a3e4..f74afd5a7292e 100644 return stmt->ops->json(stmt, octx); -- -2.19.0 +2.21.0 diff --git a/SOURCES/0029-nft.8-Document-log-level-audit.patch b/SOURCES/0029-nft.8-Document-log-level-audit.patch index 9c9a44f..0562634 100644 --- a/SOURCES/0029-nft.8-Document-log-level-audit.patch +++ b/SOURCES/0029-nft.8-Document-log-level-audit.patch @@ -47,5 +47,5 @@ index 0df42810c5e68..22d57ac630037 100644 -- -2.19.0 +2.21.0 diff --git a/SOURCES/0030-nft.8-Clarify-index-option-of-add-rule-command.patch b/SOURCES/0030-nft.8-Clarify-index-option-of-add-rule-command.patch index 3d6dad0..e01dc5b 100644 --- a/SOURCES/0030-nft.8-Clarify-index-option-of-add-rule-command.patch +++ b/SOURCES/0030-nft.8-Clarify-index-option-of-add-rule-command.patch @@ -64,5 +64,5 @@ index 22d57ac630037..512724ed8f9a7 100644 -- -2.19.0 +2.21.0 diff --git a/SOURCES/0031-src-Reject-export-vm-json-command.patch b/SOURCES/0031-src-Reject-export-vm-json-command.patch index e1853dd..4347d85 100644 --- a/SOURCES/0031-src-Reject-export-vm-json-command.patch +++ b/SOURCES/0031-src-Reject-export-vm-json-command.patch @@ -148,5 +148,5 @@ index 817415c15fb89..1e3688b2dc1cd 100644 static int __json_parse(struct json_ctx *ctx, json_t *root) -- -2.19.0 +2.21.0 diff --git a/SOURCES/0032-datatype-add-stolen-verdict.patch b/SOURCES/0032-datatype-add-stolen-verdict.patch new file mode 100644 index 0000000..56e8553 --- /dev/null +++ b/SOURCES/0032-datatype-add-stolen-verdict.patch @@ -0,0 +1,44 @@ +From 14c526641e1fdec01f345c8d9f22fff809e59790 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Tue, 12 Jun 2018 18:39:13 +0200 +Subject: [PATCH] datatype: add stolen verdict + +using fwd statement causes crash when using nft trace: + + trace id ddbbaae2 netdev vpn ingress_out packet: iif "enp2s0" ether saddr 78:54:00:29:bb:aa ether daddr 52:54:00:01:53:9f ip saddr 85.14.236.41 ip daddr 17.25.63.98 ip dscp cs0 ip ecn not-ect ip ttl 64 ip id 49036 ip length 84 icmp type echo-reply icmp code 0 icmp id 16947 icmp sequence 4 + trace id ddbbaae2 netdev vpn ingress_out rule ip saddr 85.14.236.41 nftrace set 1 (verdict continue) + trace id ddbbaae2 netdev vpn ingress_out rule ip saddr 85.14.236.41 ether saddr set aa:bb:00:18:cc:dd ether daddr set 00:00:5e:00:00:11 fwd to "enp1s0" + BUG: invalid verdict value 2 + nft: datatype.c:282: verdict_type_print: Assertion `0' failed. + +ADd stolen verdict (2) and remove the BUG statement. + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1261 +Signed-off-by: Florian Westphal +(cherry picked from commit bbbed9f3175c5260332ae7e6800b3a6791418fd2) +Signed-off-by: Phil Sutter +--- + src/datatype.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/datatype.c b/src/datatype.c +index c77d228e95a1e..209044539bb84 100644 +--- a/src/datatype.c ++++ b/src/datatype.c +@@ -280,8 +280,12 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) + case NF_QUEUE: + nft_print(octx, "queue"); + break; ++ case NF_STOLEN: ++ nft_print(octx, "stolen"); ++ break; + default: +- BUG("invalid verdict value %u\n", expr->verdict); ++ nft_print(octx, "unknown verdict value %u", expr->verdict); ++ break; + } + } + } +-- +2.21.0 + diff --git a/SOURCES/0033-libnftables-Fix-exit_cookie.patch b/SOURCES/0033-libnftables-Fix-exit_cookie.patch new file mode 100644 index 0000000..f4347b4 --- /dev/null +++ b/SOURCES/0033-libnftables-Fix-exit_cookie.patch @@ -0,0 +1,49 @@ +From 742f52eeb2bf587abb89dbd81ea0f6f58a9d7309 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 13 Jun 2018 19:18:24 +0200 +Subject: [PATCH] libnftables: Fix exit_cookie() + +The output and error buffer feature depends on cookie->orig_fp to +indicate the current status of buffering: If it is set, a prior call to +init_cookie() is assumed. Though exit_cookie() missed to reset that +pointer to NULL. causing weird behaviour in applications if they do: + +| nft = nft_ctx_new(0); +| nft_ctx_buffer_output(nft); +| nft_ctx_unbuffer_output(nft); +| nft_ctx_buffer_output(nft); + +While being at it, apply the same fix to error path in init_cookie() as +well. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 5ca7ad252366865225d5c59d297e71215b68f027) +Signed-off-by: Phil Sutter +--- + src/libnftables.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/libnftables.c b/src/libnftables.c +index 848c9cba65657..640693df93755 100644 +--- a/src/libnftables.c ++++ b/src/libnftables.c +@@ -195,6 +195,7 @@ static int init_cookie(struct cookie *cookie) + cookie->fp = fopencookie(cookie, "w", cookie_fops); + if (!cookie->fp) { + cookie->fp = cookie->orig_fp; ++ cookie->orig_fp = NULL; + return 1; + } + +@@ -208,6 +209,7 @@ static int exit_cookie(struct cookie *cookie) + + fclose(cookie->fp); + cookie->fp = cookie->orig_fp; ++ cookie->orig_fp = NULL; + free(cookie->buf); + cookie->buf = NULL; + cookie->buflen = 0; +-- +2.21.0 + diff --git a/SOURCES/0034-scanner-Do-not-convert-tabs-into-spaces.patch b/SOURCES/0034-scanner-Do-not-convert-tabs-into-spaces.patch new file mode 100644 index 0000000..b21c130 --- /dev/null +++ b/SOURCES/0034-scanner-Do-not-convert-tabs-into-spaces.patch @@ -0,0 +1,59 @@ +From b652c8a14c3cda433cd8d3ebe8290ee7907e4815 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 18 Jun 2018 10:23:22 +0200 +Subject: [PATCH] scanner: Do not convert tabs into spaces + +Commit 2f86dd5a43baf ("erec: Review erec_print()") changed erec_print() +function to expect tabs in input by replacing the whitespace character +in the marker line at the same offset with a tab character so that the +marker aligns with the offending part of input. + +The need for that came from JSON input not having its tabs converted to +spaces, which erec_print() didn't expect. + +Above change though has a shortcoming: When reading standard syntax +input from a file, Flex code converts tabs into spaces. Location +information is taken from this converted input, but when printing an +error message, the offending input line is read from the input file +directly (which still contains tabs). + +The solution is to simply drop said tab conversion from scanner.l. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 7f8d28105c8caeae7af5bccbe4a6d79f1f73e205) +Signed-off-by: Phil Sutter +--- + src/scanner.l | 16 +--------------- + 1 file changed, 1 insertion(+), 15 deletions(-) + +diff --git a/src/scanner.l b/src/scanner.l +index 416bd27af1427..3551fbf80df6e 100644 +--- a/src/scanner.l ++++ b/src/scanner.l +@@ -613,21 +613,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) + return NEWLINE; + } + +-{tab} { +- /* +- * Compensate difference between visible length +- * and real length. +- */ +- struct parser_state *state = yyget_extra(yyscanner); +- unsigned int diff; +- +- diff = TABSIZE - strlen("\t"); +- diff -= (state->indesc->column - +- strlen("\t") - 1) % TABSIZE; +- +- update_pos(state, yylloc, diff); +- } +- ++{tab}+ + {space}+ + {comment} + +-- +2.21.0 + diff --git a/SOURCES/0035-netlink_delinearize-Refactor-meta_may_dependency_kil.patch b/SOURCES/0035-netlink_delinearize-Refactor-meta_may_dependency_kil.patch new file mode 100644 index 0000000..43869fc --- /dev/null +++ b/SOURCES/0035-netlink_delinearize-Refactor-meta_may_dependency_kil.patch @@ -0,0 +1,384 @@ +From 0709a45a89405ad4c564b3a8071fffb79da58612 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 21 Jun 2018 14:01:13 +0200 +Subject: [PATCH] netlink_delinearize: Refactor meta_may_dependency_kill() + +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 +Signed-off-by: Florian Westphal +(cherry picked from commit 056aaa3e6dc65aced5e552233ac3e7f89fb81f86) +Signed-off-by: Phil Sutter +--- + src/netlink_delinearize.c | 83 +++++++++++----------- + tests/py/inet/icmp.t | 18 +++++ + tests/py/inet/icmp.t.json | 114 +++++++++++++++++++++++++++++++ + tests/py/inet/icmp.t.json.output | 30 ++++++++ + tests/py/inet/icmp.t.payload | 54 +++++++++++++++ + 5 files changed, 259 insertions(+), 40 deletions(-) + create mode 100644 tests/py/inet/icmp.t + create mode 100644 tests/py/inet/icmp.t.json + create mode 100644 tests/py/inet/icmp.t.json.output + create mode 100644 tests/py/inet/icmp.t.payload + +diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c +index bf990e9e979d5..0f4f62f34256c 100644 +--- a/src/netlink_delinearize.c ++++ b/src/netlink_delinearize.c +@@ -1525,61 +1525,64 @@ static bool meta_may_dependency_kill(struct payload_dep_ctx *ctx, + const struct expr *expr) + { + struct expr *dep = ctx->pdep->expr; ++ uint16_t l3proto; ++ uint8_t l4proto; + + if (ctx->pbase != PROTO_BASE_NETWORK_HDR) + return true; + + switch (family) { + case NFPROTO_INET: +- switch (dep->left->ops->type) { +- case EXPR_META: +- if (dep->left->meta.key == NFT_META_NFPROTO && +- (mpz_get_uint16(dep->right->value) == NFPROTO_IPV4 || +- mpz_get_uint16(dep->right->value) == NFPROTO_IPV6) && +- expr->left->meta.key == NFT_META_L4PROTO && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6) +- return false; +- break; +- case EXPR_PAYLOAD: +- if (dep->left->payload.base == PROTO_BASE_LL_HDR && +- (mpz_get_uint16(dep->right->value) == ETH_P_IP || +- mpz_get_uint16(dep->right->value) == ETH_P_IPV6) && +- expr->left->meta.key == NFT_META_L4PROTO && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6) +- return false; +- break; +- default: +- break; +- } +- break; + case NFPROTO_NETDEV: + case NFPROTO_BRIDGE: +- switch (dep->left->ops->type) { +- case EXPR_META: +- if (dep->left->meta.key == NFT_META_PROTOCOL && +- (mpz_get_uint16(dep->right->value) == ETH_P_IP || +- mpz_get_uint16(dep->right->value) == ETH_P_IPV6) && +- expr->left->meta.key == NFT_META_L4PROTO && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6) +- return false; ++ break; ++ default: ++ return true; ++ } ++ ++ if (expr->left->meta.key != NFT_META_L4PROTO) ++ return true; ++ ++ l3proto = mpz_get_uint16(dep->right->value); ++ ++ switch (dep->left->ops->type) { ++ case EXPR_META: ++ if (dep->left->meta.key != NFT_META_NFPROTO) ++ return true; ++ break; ++ case EXPR_PAYLOAD: ++ if (dep->left->payload.base != PROTO_BASE_LL_HDR) ++ return true; ++ ++ switch(l3proto) { ++ case ETH_P_IP: ++ l3proto = NFPROTO_IPV4; + break; +- case EXPR_PAYLOAD: +- if (dep->left->payload.base == PROTO_BASE_LL_HDR && +- (mpz_get_uint16(dep->right->value) == ETH_P_IP || +- mpz_get_uint16(dep->right->value) == ETH_P_IPV6) && +- expr->left->meta.key == NFT_META_L4PROTO && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMP && +- mpz_get_uint8(expr->right->value) != IPPROTO_ICMPV6) +- return false; ++ case ETH_P_IPV6: ++ l3proto = NFPROTO_IPV6; + break; + default: + break; + } + break; ++ default: ++ break; ++ } ++ ++ l4proto = mpz_get_uint8(expr->right->value); ++ ++ switch (l4proto) { ++ case IPPROTO_ICMP: ++ case IPPROTO_ICMPV6: ++ break; ++ default: ++ return false; + } ++ ++ if ((l3proto == NFPROTO_IPV4 && l4proto == IPPROTO_ICMPV6) || ++ (l3proto == NFPROTO_IPV6 && l4proto == IPPROTO_ICMP)) ++ return false; ++ + return true; + } + +diff --git a/tests/py/inet/icmp.t b/tests/py/inet/icmp.t +new file mode 100644 +index 0000000000000..9014f846729c7 +--- /dev/null ++++ b/tests/py/inet/icmp.t +@@ -0,0 +1,18 @@ ++:output;type filter hook output priority 0 ++ ++*inet;test-inet;output ++ ++# without nfproto specified, these should add an implicit dependency on ++# the likely l3 proto (i.e., IPv6 for icmpv6 and IPv4 for icmp) ++ ++icmp type echo-request;ok ++icmpv6 type echo-request;ok ++ ++# make sure only those nfproto matches are dropped if ++# the next statement would add it as a dependency anyway ++ ++meta nfproto ipv4 icmp type echo-request;ok;icmp type echo-request ++meta nfproto ipv4 icmpv6 type echo-request;ok ++ ++meta nfproto ipv6 icmp type echo-request;ok ++meta nfproto ipv6 icmpv6 type echo-request;ok;icmpv6 type echo-request +diff --git a/tests/py/inet/icmp.t.json b/tests/py/inet/icmp.t.json +new file mode 100644 +index 0000000000000..c4517605a7186 +--- /dev/null ++++ b/tests/py/inet/icmp.t.json +@@ -0,0 +1,114 @@ ++# icmp type echo-request ++[ ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmp" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ ++# icmpv6 type echo-request ++[ ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmpv6" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ ++# meta nfproto ipv4 icmp type echo-request ++[ ++ { ++ "match": { ++ "left": { "meta": "nfproto" }, ++ "right": "ipv4" ++ } ++ }, ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmp" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ ++# meta nfproto ipv4 icmpv6 type echo-request ++[ ++ { ++ "match": { ++ "left": { "meta": "nfproto" }, ++ "right": "ipv4" ++ } ++ }, ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmpv6" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ ++# meta nfproto ipv6 icmp type echo-request ++[ ++ { ++ "match": { ++ "left": { "meta": "nfproto" }, ++ "right": "ipv6" ++ } ++ }, ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmp" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ ++# meta nfproto ipv6 icmpv6 type echo-request ++[ ++ { ++ "match": { ++ "left": { "meta": "nfproto" }, ++ "right": "ipv6" ++ } ++ }, ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmpv6" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ +diff --git a/tests/py/inet/icmp.t.json.output b/tests/py/inet/icmp.t.json.output +new file mode 100644 +index 0000000000000..2282900d58e98 +--- /dev/null ++++ b/tests/py/inet/icmp.t.json.output +@@ -0,0 +1,30 @@ ++# meta nfproto ipv4 icmp type echo-request ++[ ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmp" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ ++# meta nfproto ipv6 icmpv6 type echo-request ++[ ++ { ++ "match": { ++ "left": { ++ "payload": { ++ "field": "type", ++ "name": "icmpv6" ++ } ++ }, ++ "right": "echo-request" ++ } ++ } ++] ++ +diff --git a/tests/py/inet/icmp.t.payload b/tests/py/inet/icmp.t.payload +new file mode 100644 +index 0000000000000..f98cfc39abed4 +--- /dev/null ++++ b/tests/py/inet/icmp.t.payload +@@ -0,0 +1,54 @@ ++# icmp type echo-request ++inet test-inet output ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x00000002 ] ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x00000001 ] ++ [ payload load 1b @ transport header + 0 => reg 1 ] ++ [ cmp eq reg 1 0x00000008 ] ++ ++# icmpv6 type echo-request ++inet test-inet output ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x0000000a ] ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x0000003a ] ++ [ payload load 1b @ transport header + 0 => reg 1 ] ++ [ cmp eq reg 1 0x00000080 ] ++ ++# meta nfproto ipv4 icmp type echo-request ++inet test-inet output ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x00000002 ] ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x00000001 ] ++ [ payload load 1b @ transport header + 0 => reg 1 ] ++ [ cmp eq reg 1 0x00000008 ] ++ ++# meta nfproto ipv4 icmpv6 type echo-request ++inet test-inet output ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x00000002 ] ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x0000003a ] ++ [ payload load 1b @ transport header + 0 => reg 1 ] ++ [ cmp eq reg 1 0x00000080 ] ++ ++# meta nfproto ipv6 icmp type echo-request ++inet test-inet output ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x0000000a ] ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x00000001 ] ++ [ payload load 1b @ transport header + 0 => reg 1 ] ++ [ cmp eq reg 1 0x00000008 ] ++ ++# meta nfproto ipv6 icmpv6 type echo-request ++inet test-inet output ++ [ meta load nfproto => reg 1 ] ++ [ cmp eq reg 1 0x0000000a ] ++ [ meta load l4proto => reg 1 ] ++ [ cmp eq reg 1 0x0000003a ] ++ [ payload load 1b @ transport header + 0 => reg 1 ] ++ [ cmp eq reg 1 0x00000080 ] ++ +-- +2.21.0 + diff --git a/SOURCES/0036-evaluate-skip-evaluation-of-datatype-concatenations.patch b/SOURCES/0036-evaluate-skip-evaluation-of-datatype-concatenations.patch new file mode 100644 index 0000000..bc4527e --- /dev/null +++ b/SOURCES/0036-evaluate-skip-evaluation-of-datatype-concatenations.patch @@ -0,0 +1,61 @@ +From 1c690d0992d3ef1dbb872b1cd65c10161628e9fd Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Fri, 6 Jul 2018 20:07:54 +0200 +Subject: [PATCH] evaluate: skip evaluation of datatype concatenations + +These are not really expressions, so there is not value in place. The +expr_evaluate_concat() is called from set_evaluate() to calculate the +total length of the tuple. + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1265 +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 6b00b9537e181eaf630ecaf0d4e56905eb29d87c) +Signed-off-by: Phil Sutter +--- + src/evaluate.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/evaluate.c b/src/evaluate.c +index 4656c7566db39..6ab4a3309ad77 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -1090,7 +1090,8 @@ static int list_member_evaluate(struct eval_ctx *ctx, struct expr **expr) + return err; + } + +-static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr) ++static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr, ++ bool eval) + { + const struct datatype *dtype = ctx->ectx.dtype, *tmp; + uint32_t type = dtype ? dtype->type : 0, ntype = 0; +@@ -1111,7 +1112,7 @@ static int expr_evaluate_concat(struct eval_ctx *ctx, struct expr **expr) + tmp = concat_subtype_lookup(type, --off); + expr_set_context(&ctx->ectx, tmp, tmp->size); + +- if (list_member_evaluate(ctx, &i) < 0) ++ if (eval && list_member_evaluate(ctx, &i) < 0) + return -1; + flags &= i->flags; + +@@ -1776,7 +1777,7 @@ static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr) + case EXPR_BINOP: + return expr_evaluate_binop(ctx, expr); + case EXPR_CONCAT: +- return expr_evaluate_concat(ctx, expr); ++ return expr_evaluate_concat(ctx, expr, true); + case EXPR_LIST: + return expr_evaluate_list(ctx, expr); + case EXPR_SET: +@@ -2820,7 +2821,7 @@ static int set_evaluate(struct eval_ctx *ctx, struct set *set) + + if (set->key->len == 0) { + if (set->key->ops->type == EXPR_CONCAT && +- expr_evaluate_concat(ctx, &set->key) < 0) ++ expr_evaluate_concat(ctx, &set->key, false) < 0) + return -1; + + if (set->key->len == 0) +-- +2.21.0 + diff --git a/SOURCES/0037-tests-shell-add-tests-for-listing-objects.patch b/SOURCES/0037-tests-shell-add-tests-for-listing-objects.patch new file mode 100644 index 0000000..68601dd --- /dev/null +++ b/SOURCES/0037-tests-shell-add-tests-for-listing-objects.patch @@ -0,0 +1,96 @@ +From c4bc472abe9f92ca2fcb9696e8e84083dcc29269 Mon Sep 17 00:00:00 2001 +From: Harsha Sharma +Date: Tue, 10 Jul 2018 22:00:21 +0200 +Subject: [PATCH] tests: shell: add tests for listing objects + +Add tests for listing specific object for a given table name and all +objects of a table. + +Signed-off-by: Harsha Sharma +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit bf91cfd9a619484fa3fde325ac092d69738ecf47) + +Conflicts: +-> adjust expected output in 0013objects_0 to old code base. + +Signed-off-by: Phil Sutter +--- + tests/shell/testcases/listing/0013objects_0 | 34 +++++++++++++++++++++ + tests/shell/testcases/listing/0014objects_0 | 24 +++++++++++++++ + 2 files changed, 58 insertions(+) + create mode 100755 tests/shell/testcases/listing/0013objects_0 + create mode 100755 tests/shell/testcases/listing/0014objects_0 + +diff --git a/tests/shell/testcases/listing/0013objects_0 b/tests/shell/testcases/listing/0013objects_0 +new file mode 100755 +index 0000000000000..c237e932a4483 +--- /dev/null ++++ b/tests/shell/testcases/listing/0013objects_0 +@@ -0,0 +1,34 @@ ++#!/bin/bash ++ ++# list table with all objects and chains ++ ++EXPECTED="table ip test { ++ quota https-quota { ++ 25 mbytes ++ } ++ ++ ct helper cthelp { ++ type \"sip\" protocol tcp ++ ++ l3proto ip ++ } ++ ++ chain input { ++ } ++}" ++ ++set -e ++ ++$NFT add table test ++$NFT add chain test input ++$NFT add quota test https-quota 25 mbytes ++$NFT add ct helper test cthelp { type \"sip\" protocol tcp \; } ++$NFT add table test-ip ++ ++GET="$($NFT list table test)" ++if [ "$EXPECTED" != "$GET" ] ; then ++ DIFF="$(which diff)" ++ [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ exit 1 ++fi ++ +diff --git a/tests/shell/testcases/listing/0014objects_0 b/tests/shell/testcases/listing/0014objects_0 +new file mode 100755 +index 0000000000000..dcfe2e6f80947 +--- /dev/null ++++ b/tests/shell/testcases/listing/0014objects_0 +@@ -0,0 +1,24 @@ ++#!/bin/bash ++ ++# list only the object asked for with table ++ ++EXPECTED="table ip test { ++ quota https-quota { ++ 25 mbytes ++ } ++}" ++ ++set -e ++ ++$NFT add table test ++$NFT add quota test https-quota 25 mbytes ++$NFT add ct helper test cthelp { type \"sip\" protocol tcp \; } ++$NFT add table test-ip ++ ++GET="$($NFT list quota test https-quota)" ++if [ "$EXPECTED" != "$GET" ] ; then ++ DIFF="$(which diff)" ++ [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ exit 1 ++fi ++ +-- +2.21.0 + diff --git a/SOURCES/0038-rule-fix-object-listing-when-no-table-is-given.patch b/SOURCES/0038-rule-fix-object-listing-when-no-table-is-given.patch new file mode 100644 index 0000000..92facd9 --- /dev/null +++ b/SOURCES/0038-rule-fix-object-listing-when-no-table-is-given.patch @@ -0,0 +1,63 @@ +From 3e28756a6f0730abac937d9fb10b7ee9c3569a15 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Wed, 2 Jan 2019 17:10:36 +0100 +Subject: [PATCH] rule: fix object listing when no table is given + +'nft list quotas' would not print anything at all anymore. + +Fixes: 88456a7ef01172 ("rule: list only the table containing object") +Signed-off-by: Florian Westphal +(cherry picked from commit dafac7d528de0890b82f943fc818ccb7a82fca7d) +Signed-off-by: Phil Sutter +--- + src/rule.c | 13 ++++++++----- + tests/shell/testcases/listing/0014objects_0 | 7 +++++++ + 2 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/src/rule.c b/src/rule.c +index 47b0d30cbed18..c3a2e7cc464bb 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -1585,13 +1585,16 @@ static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type) + continue; + + if (cmd->handle.table.name != NULL && +- !strcmp(cmd->handle.table.name, table->handle.table.name)) { +- nft_print(&ctx->nft->output, "table %s %s {\n", +- family2str(table->handle.family), +- cmd->handle.table.name); +- } else ++ strcmp(cmd->handle.table.name, table->handle.table.name)) + continue; + ++ if (list_empty(&table->objs)) ++ continue; ++ ++ nft_print(&ctx->nft->output, "table %s %s {\n", ++ family2str(table->handle.family), ++ table->handle.table.name); ++ + list_for_each_entry(obj, &table->objs, list) { + if (obj->type != type || + (cmd->handle.obj.name != NULL && +diff --git a/tests/shell/testcases/listing/0014objects_0 b/tests/shell/testcases/listing/0014objects_0 +index dcfe2e6f80947..20f68406e58fa 100755 +--- a/tests/shell/testcases/listing/0014objects_0 ++++ b/tests/shell/testcases/listing/0014objects_0 +@@ -15,6 +15,13 @@ $NFT add quota test https-quota 25 mbytes + $NFT add ct helper test cthelp { type \"sip\" protocol tcp \; } + $NFT add table test-ip + ++GET="$($NFT list quotas)" ++if [ "$EXPECTED" != "$GET" ] ; then ++ DIFF="$(which diff)" ++ [ -x $DIFF ] && $DIFF -u <(echo "$EXPECTED") <(echo "$GET") ++ exit 1 ++fi ++ + GET="$($NFT list quota test https-quota)" + if [ "$EXPECTED" != "$GET" ] ; then + DIFF="$(which diff)" +-- +2.21.0 + diff --git a/SOURCES/0039-proto-fix-icmp-icmpv6-code-datatype.patch b/SOURCES/0039-proto-fix-icmp-icmpv6-code-datatype.patch new file mode 100644 index 0000000..4f03b5a --- /dev/null +++ b/SOURCES/0039-proto-fix-icmp-icmpv6-code-datatype.patch @@ -0,0 +1,122 @@ +From f314ae8d3cc29d473ff5ce67ad4aa3776283e3d6 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Tue, 4 Sep 2018 13:53:59 +0200 +Subject: [PATCH] proto: fix icmp/icmpv6 code datatype + +Andrew A. Sabitov says: + I'd like to use a set (concatenation) of icmpv6 type and icmpv6 code + and check incoming icmpv6 traffic against it: + + add set inet fw in_icmpv6_types { type icmpv6_type . icmpv6_code; } + add element inet fw in_icmpv6_types { 1 . 0 } # no route to destination + add element inet fw in_icmpv6_types { 1 . 1 } # communication with destination administratively prohibited + # ... + + add rule inet fw in_icmpv6 icmpv6 type . icmpv6 code @in_icmpv6_types \ + limit rate 15/minute accept + +yields: +Error: can not use variable sized data types (integer) in concat expressions + icmpv6 type . icmpv6 code @in_icmpv6_types + ~~~~~~~~~~~~~~^^^^^^^^^^^ + +Change 'code' type to the icmp/icmpv6 code type. +Needs minor change to test suite as nft will now display +human-readable names instead of numeric codes. + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1276 +Signed-off-by: Florian Westphal +(cherry picked from commit 0f44d4f62753535d39d95d83778348bee4e88053) +Signed-off-by: Phil Sutter +--- + src/proto.c | 4 ++-- + tests/py/ip/icmp.t | 4 ++-- + tests/py/ip/icmp.t.payload.ip | 2 +- + tests/py/ip6/icmpv6.t | 6 +++--- + tests/py/ip6/icmpv6.t.payload.ip6 | 2 +- + 5 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/src/proto.c b/src/proto.c +index ed011efab2229..d178bf39ea907 100644 +--- a/src/proto.c ++++ b/src/proto.c +@@ -347,7 +347,7 @@ const struct proto_desc proto_icmp = { + .checksum_key = ICMPHDR_CHECKSUM, + .templates = { + [ICMPHDR_TYPE] = ICMPHDR_TYPE("type", &icmp_type_type, type), +- [ICMPHDR_CODE] = ICMPHDR_FIELD("code", code), ++ [ICMPHDR_CODE] = ICMPHDR_TYPE("code", &icmp_code_type, code), + [ICMPHDR_CHECKSUM] = ICMPHDR_FIELD("checksum", checksum), + [ICMPHDR_ID] = ICMPHDR_FIELD("id", un.echo.id), + [ICMPHDR_SEQ] = ICMPHDR_FIELD("sequence", un.echo.sequence), +@@ -686,7 +686,7 @@ const struct proto_desc proto_icmp6 = { + .checksum_key = ICMP6HDR_CHECKSUM, + .templates = { + [ICMP6HDR_TYPE] = ICMP6HDR_TYPE("type", &icmp6_type_type, icmp6_type), +- [ICMP6HDR_CODE] = ICMP6HDR_FIELD("code", icmp6_code), ++ [ICMP6HDR_CODE] = ICMP6HDR_TYPE("code", &icmpv6_code_type, icmp6_code), + [ICMP6HDR_CHECKSUM] = ICMP6HDR_FIELD("checksum", icmp6_cksum), + [ICMP6HDR_PPTR] = ICMP6HDR_FIELD("parameter-problem", icmp6_pptr), + [ICMP6HDR_MTU] = ICMP6HDR_FIELD("mtu", icmp6_mtu), +diff --git a/tests/py/ip/icmp.t b/tests/py/ip/icmp.t +index 5a7ce7e08bac0..6c05fb9d0fbca 100644 +--- a/tests/py/ip/icmp.t ++++ b/tests/py/ip/icmp.t +@@ -28,8 +28,8 @@ icmp code 33-55;ok + icmp code != 33-55;ok + icmp code { 33-55};ok + icmp code != { 33-55};ok +-icmp code { 2, 4, 54, 33, 56};ok +-icmp code != { 2, 4, 54, 33, 56};ok ++icmp code { 2, 4, 54, 33, 56};ok;icmp code { prot-unreachable, 4, 33, 54, 56} ++icmp code != { prot-unreachable, 4, 33, 54, 56};ok + + icmp checksum 12343 accept;ok + icmp checksum != 12343 accept;ok +diff --git a/tests/py/ip/icmp.t.payload.ip b/tests/py/ip/icmp.t.payload.ip +index f959cf338295c..27f222072d5dc 100644 +--- a/tests/py/ip/icmp.t.payload.ip ++++ b/tests/py/ip/icmp.t.payload.ip +@@ -184,7 +184,7 @@ ip test-ip4 input + [ payload load 1b @ transport header + 1 => reg 1 ] + [ lookup reg 1 set __set%d ] + +-# icmp code != { 2, 4, 54, 33, 56} ++# icmp code != { prot-unreachable, 4, 33, 54, 56} + __set%d test-ip4 3 + __set%d test-ip4 0 + element 00000002 : 0 [end] element 00000004 : 0 [end] element 00000036 : 0 [end] element 00000021 : 0 [end] element 00000038 : 0 [end] +diff --git a/tests/py/ip6/icmpv6.t b/tests/py/ip6/icmpv6.t +index a898fe30c24c7..8d794115d51e9 100644 +--- a/tests/py/ip6/icmpv6.t ++++ b/tests/py/ip6/icmpv6.t +@@ -28,10 +28,10 @@ icmpv6 type {router-renumbering, mld-listener-done, time-exceeded, nd-router-sol + icmpv6 type {mld-listener-query, time-exceeded, nd-router-advert} accept;ok + icmpv6 type != {mld-listener-query, time-exceeded, nd-router-advert} accept;ok + +-icmpv6 code 4;ok ++icmpv6 code 4;ok;icmpv6 code port-unreachable + icmpv6 code 3-66;ok +-icmpv6 code {5, 6, 7} accept;ok +-icmpv6 code != {5, 6, 7} accept;ok ++icmpv6 code {5, 6, 7} accept;ok;icmpv6 code {policy-fail, reject-route, 7} accept ++icmpv6 code != {policy-fail, reject-route, 7} accept;ok + icmpv6 code { 3-66};ok + icmpv6 code != { 3-66};ok + +diff --git a/tests/py/ip6/icmpv6.t.payload.ip6 b/tests/py/ip6/icmpv6.t.payload.ip6 +index 7a630f9f8b097..51d71f4149b56 100644 +--- a/tests/py/ip6/icmpv6.t.payload.ip6 ++++ b/tests/py/ip6/icmpv6.t.payload.ip6 +@@ -220,7 +220,7 @@ ip6 test-ip6 input + [ lookup reg 1 set __set%d ] + [ immediate reg 0 accept ] + +-# icmpv6 code != {5, 6, 7} accept ++# icmpv6 code != {policy-fail, reject-route, 7} accept + __set%d test-ip6 3 + __set%d test-ip6 0 + element 00000005 : 0 [end] element 00000006 : 0 [end] element 00000007 : 0 [end] +-- +2.21.0 + diff --git a/SOURCES/0040-evaluate-throw-distinct-error-if-map-exists-but-cont.patch b/SOURCES/0040-evaluate-throw-distinct-error-if-map-exists-but-cont.patch new file mode 100644 index 0000000..32d28b4 --- /dev/null +++ b/SOURCES/0040-evaluate-throw-distinct-error-if-map-exists-but-cont.patch @@ -0,0 +1,55 @@ +From f50e0290b648f00fb76655b23d48d0729500c76a Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Thu, 20 Sep 2018 17:21:45 +0200 +Subject: [PATCH] evaluate: throw distinct error if map exists but contains no + objects +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +nft would throw misleading error in case map exists but doesn't contain +expected objects. + +nft add rule filter in ct helper set tcp dport map @foo +Error: Expression is not a map +add rule filter in ct helper set tcp dport map @foo + ^^^^ +nft list table filter +table ip filter { + map foo { + type inet_service : ifname + } +... + +clarify this. + +Reported-by: Christian Göttsche +Signed-off-by: Florian Westphal +(cherry picked from commit 5b35fb3132b1fa4348266139661ffa21a5a5ae0d) +Signed-off-by: Phil Sutter +--- + src/evaluate.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/evaluate.c b/src/evaluate.c +index 6ab4a3309ad77..88fa44dd34ef5 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -2671,10 +2671,12 @@ static int stmt_evaluate_objref_map(struct eval_ctx *ctx, struct stmt *stmt) + case EXPR_SYMBOL: + if (expr_evaluate(ctx, &map->mappings) < 0) + return -1; +- if (map->mappings->ops->type != EXPR_SET_REF || +- !(map->mappings->set->flags & NFT_SET_OBJECT)) ++ if (map->mappings->ops->type != EXPR_SET_REF) + return expr_error(ctx->msgs, map->mappings, + "Expression is not a map"); ++ if (!(map->mappings->set->flags & NFT_SET_OBJECT)) ++ return expr_error(ctx->msgs, map->mappings, ++ "Expression is not a map with objects"); + break; + default: + BUG("invalid mapping expression %s\n", +-- +2.21.0 + diff --git a/SOURCES/0041-parser-bail-out-on-incorrect-burst-unit.patch b/SOURCES/0041-parser-bail-out-on-incorrect-burst-unit.patch new file mode 100644 index 0000000..69d44ac --- /dev/null +++ b/SOURCES/0041-parser-bail-out-on-incorrect-burst-unit.patch @@ -0,0 +1,106 @@ +From bd7a8291c1e00c3625dd348dbb7246b4a7aa357d Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 3 Dec 2018 17:06:21 +0100 +Subject: [PATCH] parser: bail out on incorrect burst unit + +Burst can be either bytes or packets, depending on the rate limit unit. + + # nft add rule x y iif eth0 limit rate 512 kbytes/second burst 5 packets + Error: syntax error, unexpected packets, expecting string or bytes + add rule x y iif eth0 limit rate 512 kbytes/second burst 5 packets + ^^^^^^^ + +Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1306 +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 1018eae77176cffd39bad0e499010923642c2cba) +Signed-off-by: Phil Sutter +--- + src/parser_bison.y | 15 +++++++++------ + tests/py/any/limit.t | 2 ++ + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index a6b6fc1745a72..aabf16316ff8b 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -562,7 +562,7 @@ int nft_lex(void *, void *, void *); + %type level_type log_flags log_flags_tcp log_flag_tcp + %type limit_stmt quota_stmt connlimit_stmt + %destructor { stmt_free($$); } limit_stmt quota_stmt connlimit_stmt +-%type limit_burst limit_mode time_unit quota_mode ++%type limit_burst_pkts limit_burst_bytes limit_mode time_unit quota_mode + %type reject_stmt reject_stmt_alloc + %destructor { stmt_free($$); } reject_stmt reject_stmt_alloc + %type nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc +@@ -2298,7 +2298,7 @@ log_flag_tcp : SEQUENCE + } + ; + +-limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst ++limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst_pkts + { + $$ = limit_stmt_alloc(&@$); + $$->limit.rate = $4; +@@ -2307,7 +2307,7 @@ limit_stmt : LIMIT RATE limit_mode NUM SLASH time_unit limit_burst + $$->limit.type = NFT_LIMIT_PKTS; + $$->limit.flags = $3; + } +- | LIMIT RATE limit_mode NUM STRING limit_burst ++ | LIMIT RATE limit_mode NUM STRING limit_burst_bytes + { + struct error_record *erec; + uint64_t rate, unit; +@@ -2388,8 +2388,11 @@ limit_mode : OVER { $$ = NFT_LIMIT_F_INV; } + | /* empty */ { $$ = 0; } + ; + +-limit_burst : /* empty */ { $$ = 0; } ++limit_burst_pkts : /* empty */ { $$ = 0; } + | BURST NUM PACKETS { $$ = $2; } ++ ; ++ ++limit_burst_bytes : /* empty */ { $$ = 0; } + | BURST NUM BYTES { $$ = $2; } + | BURST NUM STRING + { +@@ -3199,7 +3202,7 @@ ct_obj_alloc : + } + ; + +-limit_config : RATE limit_mode NUM SLASH time_unit limit_burst ++limit_config : RATE limit_mode NUM SLASH time_unit limit_burst_pkts + { + struct limit *limit; + limit = xzalloc(sizeof(*limit)); +@@ -3210,7 +3213,7 @@ limit_config : RATE limit_mode NUM SLASH time_unit limit_burst + limit->flags = $2; + $$ = limit; + } +- | RATE limit_mode NUM STRING limit_burst ++ | RATE limit_mode NUM STRING limit_burst_bytes + { + struct limit *limit; + struct error_record *erec; +diff --git a/tests/py/any/limit.t b/tests/py/any/limit.t +index 8180bea3ddae6..ef7f93133297f 100644 +--- a/tests/py/any/limit.t ++++ b/tests/py/any/limit.t +@@ -14,6 +14,7 @@ limit rate 400/hour;ok + limit rate 40/day;ok + limit rate 400/week;ok + limit rate 1023/second burst 10 packets;ok ++limit rate 1023/second burst 10 bytes;fail + + limit rate 1 kbytes/second;ok + limit rate 2 kbytes/second;ok +@@ -21,6 +22,7 @@ limit rate 1025 kbytes/second;ok + limit rate 1023 mbytes/second;ok + limit rate 10230 mbytes/second;ok + limit rate 1023000 mbytes/second;ok ++limit rate 512 kbytes/second burst 5 packets;fail + + limit rate 1025 bytes/second burst 512 bytes;ok + limit rate 1025 kbytes/second burst 1023 kbytes;ok +-- +2.21.0 + diff --git a/SOURCES/0042-src-fix-netdev-family-device-name-parsing.patch b/SOURCES/0042-src-fix-netdev-family-device-name-parsing.patch new file mode 100644 index 0000000..6af5875 --- /dev/null +++ b/SOURCES/0042-src-fix-netdev-family-device-name-parsing.patch @@ -0,0 +1,53 @@ +From b4a5b3b3b0a46d9155d0e07e5ab226cf5697cd13 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Wed, 9 Jan 2019 23:26:05 +0100 +Subject: [PATCH] src: fix netdev family device name parsing + +Should use accept/use quotes, else you can't use this with a device name +that is shared with a key word, e.g. 'device vm'. + +Signed-off-by: Florian Westphal +Acked-by: Pablo Neira Ayuso +(cherry picked from commit b338244abc7f018d79a95657fff88eadee7e9f6b) + +Conflicts: + src/rule.c + tests/shell/testcases/chains/dumps/0021prio_0.nft +-> Context change due to missing commit c8a0e8c90e2d1 + ("src: Set/print standard chain prios with textual names") + +Signed-off-by: Phil Sutter +--- + src/parser_bison.y | 2 +- + src/rule.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index aabf16316ff8b..f86a754deea8e 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -1793,7 +1793,7 @@ prio_spec : NUM { $$ = $1; } + | DASH NUM { $$ = -$2; } + ; + +-dev_spec : DEVICE STRING { $$ = $2; } ++dev_spec : DEVICE string { $$ = $2; } + | /* empty */ { $$ = NULL; } + ; + +diff --git a/src/rule.c b/src/rule.c +index c3a2e7cc464bb..0b494e4326be6 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -773,7 +773,7 @@ static void chain_print_declaration(const struct chain *chain, + nft_print(octx, "\t\ttype %s hook %s", chain->type, + hooknum2str(chain->handle.family, chain->hooknum)); + if (chain->dev != NULL) +- nft_print(octx, " device %s", chain->dev); ++ nft_print(octx, " device \"%s\"", chain->dev); + nft_print(octx, " priority %d; policy %s;\n", + chain->priority, chain_policy2str(chain->policy)); + } +-- +2.21.0 + diff --git a/SOURCES/0043-libnftables-Print-errors-before-freeing-commands.patch b/SOURCES/0043-libnftables-Print-errors-before-freeing-commands.patch new file mode 100644 index 0000000..ab7f593 --- /dev/null +++ b/SOURCES/0043-libnftables-Print-errors-before-freeing-commands.patch @@ -0,0 +1,50 @@ +From 25d8f60537cd6a700b15941032a2b93066938af3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 26 Feb 2019 22:13:38 +0100 +Subject: [PATCH] libnftables: Print errors before freeing commands + +Commands may contain data printed by an error record, so make sure +cmd_free() is not called before erec_print_list() has returned. + +Fixes: 778de37d82e7b ("libnftables: Keep cmds list outside of parser_state") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit a0da4c5bbf0d741fb815a977c945afe1b9a0739f) +Signed-off-by: Phil Sutter +--- + src/libnftables.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libnftables.c b/src/libnftables.c +index 640693df93755..5ca8236d8ba03 100644 +--- a/src/libnftables.c ++++ b/src/libnftables.c +@@ -457,11 +457,11 @@ int nft_run_cmd_from_buffer(struct nft_ctx *nft, char *buf, size_t buflen) + if (nft_netlink(nft, &cmds, &msgs, nft->nf_sock) != 0) + rc = -1; + err: ++ erec_print_list(&nft->output, &msgs, nft->debug_mask); + list_for_each_entry_safe(cmd, next, &cmds, list) { + list_del(&cmd->list); + cmd_free(cmd); + } +- erec_print_list(&nft->output, &msgs, nft->debug_mask); + iface_cache_release(); + if (nft->scanner) { + scanner_destroy(nft->scanner); +@@ -497,11 +497,11 @@ int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename) + if (nft_netlink(nft, &cmds, &msgs, nft->nf_sock) != 0) + rc = -1; + err: ++ erec_print_list(&nft->output, &msgs, nft->debug_mask); + list_for_each_entry_safe(cmd, next, &cmds, list) { + list_del(&cmd->list); + cmd_free(cmd); + } +- erec_print_list(&nft->output, &msgs, nft->debug_mask); + iface_cache_release(); + if (nft->scanner) { + scanner_destroy(nft->scanner); +-- +2.21.0 + diff --git a/SOURCES/0044-segtree-fix-crash-when-debug-mode-is-active.patch b/SOURCES/0044-segtree-fix-crash-when-debug-mode-is-active.patch new file mode 100644 index 0000000..e40cda4 --- /dev/null +++ b/SOURCES/0044-segtree-fix-crash-when-debug-mode-is-active.patch @@ -0,0 +1,60 @@ +From 9c9034a8cb88de406c64553d27f6471f99b9e06a Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Mon, 4 Mar 2019 01:06:05 +0100 +Subject: [PATCH] segtree: fix crash when debug mode is active +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +We must set output_fp to sensible filep, else crash. + +Reported-by: Václav Zindulka +Signed-off-by: Florian Westphal +(cherry picked from commit afd1ad6f68680c0f0a4afad7c67ddc8652948732) +Signed-off-by: Phil Sutter +--- + src/segtree.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/src/segtree.c b/src/segtree.c +index 5685618b3724a..5a5a728912db7 100644 +--- a/src/segtree.c ++++ b/src/segtree.c +@@ -9,6 +9,7 @@ + */ + + #include ++#include + #include + #include + +@@ -67,8 +68,6 @@ struct elementary_interval { + struct expr *expr; + }; + +-static struct output_ctx debug_octx = {}; +- + static void seg_tree_init(struct seg_tree *tree, const struct set *set, + struct expr *init, unsigned int debug_mask) + { +@@ -570,6 +569,7 @@ int set_to_intervals(struct list_head *errs, struct set *set, + bool merge) + { + struct elementary_interval *ei, *next; ++ struct output_ctx debug_octx; + struct seg_tree tree; + LIST_HEAD(list); + +@@ -590,6 +590,9 @@ int set_to_intervals(struct list_head *errs, struct set *set, + } + + if (segtree_debug(tree.debug_mask)) { ++ memset(&debug_octx, 0, sizeof(debug_octx)); ++ debug_octx.output_fp = stderr; ++ debug_octx.error_fp = stderr; + expr_print(init, &debug_octx); + pr_gmp_debug("\n"); + } +-- +2.21.0 + diff --git a/SOURCES/0045-parser_bison-no-need-for-statement-separator-for-ct-.patch b/SOURCES/0045-parser_bison-no-need-for-statement-separator-for-ct-.patch new file mode 100644 index 0000000..db0621f --- /dev/null +++ b/SOURCES/0045-parser_bison-no-need-for-statement-separator-for-ct-.patch @@ -0,0 +1,53 @@ +From 156f738087525eeb35e1225d8fb1e23da71dc58b Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Thu, 14 Mar 2019 11:04:37 +0100 +Subject: [PATCH] parser_bison: no need for statement separator for ct object + commands + +Otherwise, this forces user to place a double semi-colon to skip a +parser error in a multi-line commands: + + # nft add "ct helper ip filter test { type \"ftp\" protocol tcp; };add rule filter test ct helper set \"ftp\"" + Error: syntax error, unexpected add, expecting end of file or newline or semicolon + add ct helper ip filter test { type "ftp" protocol tcp; };add rule filter test ct helper set "ftp" + ^^^ + +Reported-by: Laura Garcia +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit d3cace26609253a8e3f20aeb8693f37d63897a7e) + +Conflicts: + src/parser_bison.y +-> Some chunks dropped for missing commit c7c94802679cd + ("src: add ct timeout support") + +Signed-off-by: Phil Sutter +--- + src/parser_bison.y | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index f86a754deea8e..99d60822790dc 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -941,7 +941,7 @@ add_cmd : TABLE table_spec + { + $$ = cmd_alloc(CMD_ADD, CMD_OBJ_QUOTA, &$2, &@$, $3); + } +- | CT HELPER obj_spec ct_obj_alloc '{' ct_helper_block '}' stmt_separator ++ | CT HELPER obj_spec ct_obj_alloc '{' ct_helper_block '}' + { + + $$ = cmd_alloc_obj_ct(CMD_ADD, NFT_OBJECT_CT_HELPER, &$3, &@$, $4); +@@ -1023,7 +1023,7 @@ create_cmd : TABLE table_spec + { + $$ = cmd_alloc(CMD_CREATE, CMD_OBJ_QUOTA, &$2, &@$, $3); + } +- | CT HELPER obj_spec ct_obj_alloc '{' ct_helper_block '}' stmt_separator ++ | CT HELPER obj_spec ct_obj_alloc '{' ct_helper_block '}' + { + $$ = cmd_alloc_obj_ct(CMD_CREATE, NFT_OBJECT_CT_HELPER, &$3, &@$, $4); + } +-- +2.21.0 + diff --git a/SOURCES/0046-ct-use-nft_print-instead-of-printf.patch b/SOURCES/0046-ct-use-nft_print-instead-of-printf.patch new file mode 100644 index 0000000..cd17e21 --- /dev/null +++ b/SOURCES/0046-ct-use-nft_print-instead-of-printf.patch @@ -0,0 +1,33 @@ +From 5d255c91b90a3480d084c50c6c61bb3dcd380ab7 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Fri, 5 Apr 2019 15:36:48 +0200 +Subject: [PATCH] ct: use nft_print() instead of printf() + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit e07be57df3f5191d23b05c4fb06a94f3961beb13) + +Conflicts: +-> Change applied manually due to missing commit 4795a994e2810 + ("src: use 'flow add' syntax") + +Signed-off-by: Phil Sutter +--- + src/ct.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ct.c b/src/ct.c +index 1d50382bab8b1..f019f5af3e182 100644 +--- a/src/ct.c ++++ b/src/ct.c +@@ -481,7 +481,7 @@ struct stmt *notrack_stmt_alloc(const struct location *loc) + static void flow_offload_stmt_print(const struct stmt *stmt, + struct output_ctx *octx) + { +- printf("flow offload @%s", stmt->flow.table_name); ++ nft_print(octx, "flow offload @%s", stmt->flow.table_name); + } + + static const struct stmt_ops flow_offload_stmt_ops = { +-- +2.21.0 + diff --git a/SOURCES/0047-parser_bison-type_identifier-string-memleak.patch b/SOURCES/0047-parser_bison-type_identifier-string-memleak.patch new file mode 100644 index 0000000..51687b4 --- /dev/null +++ b/SOURCES/0047-parser_bison-type_identifier-string-memleak.patch @@ -0,0 +1,41 @@ +From 539029b8aee913dd391da66ecd0ac9ff2adb12ff Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Fri, 5 Apr 2019 14:09:56 +0200 +Subject: [PATCH] parser_bison: type_identifier string memleak + +==6297== 24 bytes in 3 blocks are definitely lost in loss record 2 of 13 +==6297== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) +==6297== by 0x56193B9: strdup (strdup.c:42) +==6297== by 0x4E758BD: xstrdup (utils.c:75) +==6297== by 0x4E7F9D3: nft_parse (parser_bison.y:1895) +==6297== by 0x4E7AAE1: nft_parse_bison_filename (libnftables.c:370) +==6297== by 0x4E7AAE1: nft_run_cmd_from_filename (libnftables.c:438) +==6297== by 0x109A33: main (main.c:310) + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 4d97f0a4eebd25d1639cd7c7ac2452445205a819) +Signed-off-by: Phil Sutter +--- + src/parser_bison.y | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 99d60822790dc..1dc83953ea858 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -1681,11 +1681,11 @@ data_type_atom_expr : type_identifier + if (dtype == NULL) { + erec_queue(error(&@1, "unknown datatype %s", $1), + state->msgs); +- xfree($1); + YYERROR; + } + $$ = constant_expr_alloc(&@1, dtype, dtype->byteorder, + dtype->size, NULL); ++ xfree($1); + } + ; + +-- +2.21.0 + diff --git a/SOURCES/0048-src-missing-destroy-function-in-statement-definition.patch b/SOURCES/0048-src-missing-destroy-function-in-statement-definition.patch new file mode 100644 index 0000000..7b7ea9f --- /dev/null +++ b/SOURCES/0048-src-missing-destroy-function-in-statement-definition.patch @@ -0,0 +1,211 @@ +From 61e3dab3169af7add5fa131bb7414adf586d2997 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Fri, 5 Apr 2019 15:35:36 +0200 +Subject: [PATCH] src: missing destroy function in statement definitions + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 4ac11b890fe870d1c066783bccc235e1922dd431) + +Conflicts: +-> Dropped changes to set_stmt_destroy() and map_stmt_destroy() due to + missing commit a55ca1a24b7b2 ("src: integrate stateful expressions + into sets and maps") + +Signed-off-by: Phil Sutter +--- + src/ct.c | 12 ++++++++++++ + src/exthdr.c | 7 +++++++ + src/meta.c | 6 ++++++ + src/payload.c | 7 +++++++ + src/statement.c | 19 +++++++++++++++++++ + src/xt.c | 1 + + 6 files changed, 52 insertions(+) + +diff --git a/src/ct.c b/src/ct.c +index f019f5af3e182..c2ca51494af60 100644 +--- a/src/ct.c ++++ b/src/ct.c +@@ -440,11 +440,17 @@ static void ct_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + expr_print(stmt->ct.expr, octx); + } + ++static void ct_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->ct.expr); ++} ++ + static const struct stmt_ops ct_stmt_ops = { + .type = STMT_CT, + .name = "ct", + .print = ct_stmt_print, + .json = ct_stmt_json, ++ .destroy = ct_stmt_destroy, + }; + + struct stmt *ct_stmt_alloc(const struct location *loc, enum nft_ct_keys key, +@@ -484,10 +490,16 @@ static void flow_offload_stmt_print(const struct stmt *stmt, + nft_print(octx, "flow offload @%s", stmt->flow.table_name); + } + ++static void flow_offload_stmt_destroy(struct stmt *stmt) ++{ ++ xfree(stmt->flow.table_name); ++} ++ + static const struct stmt_ops flow_offload_stmt_ops = { + .type = STMT_FLOW_OFFLOAD, + .name = "flow_offload", + .print = flow_offload_stmt_print, ++ .destroy = flow_offload_stmt_destroy, + }; + + struct stmt *flow_offload_stmt_alloc(const struct location *loc, +diff --git a/src/exthdr.c b/src/exthdr.c +index cb0a58e8526a5..8602016f66477 100644 +--- a/src/exthdr.c ++++ b/src/exthdr.c +@@ -104,11 +104,18 @@ static void exthdr_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + expr_print(stmt->exthdr.val, octx); + } + ++static void exthdr_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->exthdr.expr); ++ expr_free(stmt->exthdr.val); ++} ++ + static const struct stmt_ops exthdr_stmt_ops = { + .type = STMT_EXTHDR, + .name = "exthdr", + .print = exthdr_stmt_print, + .json = exthdr_stmt_json, ++ .destroy = exthdr_stmt_destroy, + }; + + struct stmt *exthdr_stmt_alloc(const struct location *loc, +diff --git a/src/meta.c b/src/meta.c +index ff0cb122d7dfa..c1021febdefd4 100644 +--- a/src/meta.c ++++ b/src/meta.c +@@ -604,11 +604,17 @@ static void meta_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + expr_print(stmt->meta.expr, octx); + } + ++static void meta_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->meta.expr); ++} ++ + static const struct stmt_ops meta_stmt_ops = { + .type = STMT_META, + .name = "meta", + .print = meta_stmt_print, + .json = meta_stmt_json, ++ .destroy = meta_stmt_destroy, + }; + + struct stmt *meta_stmt_alloc(const struct location *loc, enum nft_meta_keys key, +diff --git a/src/payload.c b/src/payload.c +index 6517686cbfba5..42b055360848d 100644 +--- a/src/payload.c ++++ b/src/payload.c +@@ -189,11 +189,18 @@ static void payload_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + expr_print(stmt->payload.val, octx); + } + ++static void payload_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->payload.expr); ++ expr_free(stmt->payload.val); ++} ++ + static const struct stmt_ops payload_stmt_ops = { + .type = STMT_PAYLOAD, + .name = "payload", + .print = payload_stmt_print, + .json = payload_stmt_json, ++ .destroy = payload_stmt_destroy, + }; + + struct stmt *payload_stmt_alloc(const struct location *loc, +diff --git a/src/statement.c b/src/statement.c +index e9c9d648b0092..1b889e77cca20 100644 +--- a/src/statement.c ++++ b/src/statement.c +@@ -134,6 +134,7 @@ static void meter_stmt_destroy(struct stmt *stmt) + expr_free(stmt->meter.key); + expr_free(stmt->meter.set); + stmt_free(stmt->meter.stmt); ++ xfree(stmt->meter.name); + } + + static const struct stmt_ops meter_stmt_ops = { +@@ -226,11 +227,17 @@ static void objref_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + expr_print(stmt->objref.expr, octx); + } + ++static void objref_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->objref.expr); ++} ++ + static const struct stmt_ops objref_stmt_ops = { + .type = STMT_OBJREF, + .name = "objref", + .print = objref_stmt_print, + .json = objref_stmt_json, ++ .destroy = objref_stmt_destroy, + }; + + struct stmt *objref_stmt_alloc(const struct location *loc) +@@ -435,11 +442,17 @@ static void queue_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + + } + ++static void queue_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->queue.queue); ++} ++ + static const struct stmt_ops queue_stmt_ops = { + .type = STMT_QUEUE, + .name = "queue", + .print = queue_stmt_print, + .json = queue_stmt_json, ++ .destroy = queue_stmt_destroy, + }; + + struct stmt *queue_stmt_alloc(const struct location *loc) +@@ -511,11 +524,17 @@ static void reject_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + } + } + ++static void reject_stmt_destroy(struct stmt *stmt) ++{ ++ expr_free(stmt->reject.expr); ++} ++ + static const struct stmt_ops reject_stmt_ops = { + .type = STMT_REJECT, + .name = "reject", + .print = reject_stmt_print, + .json = reject_stmt_json, ++ .destroy = reject_stmt_destroy, + }; + + struct stmt *reject_stmt_alloc(const struct location *loc) +diff --git a/src/xt.c b/src/xt.c +index 74763d58cafd7..298a94d51e8a0 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -92,6 +92,7 @@ void xt_stmt_release(const struct stmt *stmt) + break; + } + xfree(stmt->xt.entry); ++ xfree(stmt->xt.name); + } + + static void *xt_entry_alloc(struct xt_stmt *xt, uint32_t af) +-- +2.21.0 + diff --git a/SOURCES/0049-tests-shell-validate-too-deep-jumpstack-from-basecha.patch b/SOURCES/0049-tests-shell-validate-too-deep-jumpstack-from-basecha.patch new file mode 100644 index 0000000..67a76b3 --- /dev/null +++ b/SOURCES/0049-tests-shell-validate-too-deep-jumpstack-from-basecha.patch @@ -0,0 +1,37 @@ +From 62e3a8f9d4246bc491d0b4aa11b250ed8ad06ecc Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Wed, 8 Aug 2018 21:52:50 +0200 +Subject: [PATCH] tests: shell: validate too deep jumpstack from basechain + +If there is no basechain, the validation is never exercised. + +Too deep nested chains are fine as long as they are not connected to a +basechain. + +Update test to add a basechain so we exercise validation. + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 760a8bab07ade570e589bc8da36935776d225d95) +Signed-off-by: Phil Sutter +--- + tests/shell/testcases/chains/0002jumps_1 | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tests/shell/testcases/chains/0002jumps_1 b/tests/shell/testcases/chains/0002jumps_1 +index 0cc89288670ed..4d163b05fe1b9 100755 +--- a/tests/shell/testcases/chains/0002jumps_1 ++++ b/tests/shell/testcases/chains/0002jumps_1 +@@ -6,7 +6,9 @@ MAX_JUMPS=16 + + $NFT add table t + +-for i in $(seq 1 $MAX_JUMPS) ++$NFT add chain t c1 { type filter hook input priority 0\; } ++ ++for i in $(seq 2 $MAX_JUMPS) + do + $NFT add chain t c${i} + done +-- +2.21.0 + diff --git a/SOURCES/0050-netlink-remove-markup-json-parsing-code.patch b/SOURCES/0050-netlink-remove-markup-json-parsing-code.patch new file mode 100644 index 0000000..fdeb584 --- /dev/null +++ b/SOURCES/0050-netlink-remove-markup-json-parsing-code.patch @@ -0,0 +1,367 @@ +From fbccf77429c4f1fccd48a201369402e33bea91c6 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Wed, 26 Sep 2018 16:23:19 +0200 +Subject: [PATCH] netlink: remove markup json parsing code + +We have better json support these days, remove libnftnl json support. + +While at it, remove test file for this too. + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 276c452e47c5e22b3af06a051aa2908521aeba66) +Signed-off-by: Phil Sutter +--- + src/netlink.c | 276 +----------------- + tests/shell/testcases/import/vm_json_import_0 | 53 ---- + 2 files changed, 2 insertions(+), 327 deletions(-) + delete mode 100755 tests/shell/testcases/import/vm_json_import_0 + +diff --git a/src/netlink.c b/src/netlink.c +index c178be3c9ee26..0509a06b3d2b3 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -1970,280 +1970,8 @@ int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type, + return MNL_CB_OK; + } + +-static int netlink_markup_setelems(const struct nftnl_parse_ctx *ctx) +-{ +- const struct ruleset_parse *rp; +- struct nftnl_set *set; +- uint32_t cmd; +- int ret = -1; +- +- set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET); +- rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); +- +- cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); +- switch (cmd) { +- case NFTNL_CMD_ADD: +- ret = mnl_nft_setelem_batch_add(set, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_DELETE: +- ret = mnl_nft_setelem_batch_del(set, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- default: +- errno = EOPNOTSUPP; +- break; +- } +- +- return ret; +-} +- +-static int netlink_markup_set(const struct nftnl_parse_ctx *ctx) +-{ +- const struct ruleset_parse *rp; +- struct nftnl_set *set; +- uint32_t cmd; +- int ret = -1; +- +- set = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_SET); +- rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); +- +- cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); +- switch (cmd) { +- case NFTNL_CMD_ADD: +- ret = mnl_nft_set_batch_add(set, rp->nl_ctx->batch, NLM_F_EXCL, +- rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_DELETE: +- ret = mnl_nft_set_batch_del(set, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- default: +- errno = EOPNOTSUPP; +- break; +- } +- +- if (ret < 0) +- return ret; +- +- return netlink_markup_setelems(ctx); +-} +- +-static int netlink_markup_build_rule(const struct nftnl_parse_ctx *ctx, +- uint32_t cmd, struct nftnl_rule *rule) +-{ +- const struct ruleset_parse *rp; +- uint32_t nl_flags; +- int ret = -1; +- +- rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); +- +- switch (cmd) { +- case NFTNL_CMD_ADD: +- nl_flags = NLM_F_APPEND | NLM_F_CREATE; +- nftnl_rule_unset(rule, NFTNL_RULE_HANDLE); +- ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags, +- rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_DELETE: +- ret = mnl_nft_rule_batch_del(rule, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_REPLACE: +- nl_flags = NLM_F_REPLACE; +- ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags, +- rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_INSERT: +- nl_flags = NLM_F_CREATE; +- nftnl_rule_unset(rule, NFTNL_RULE_HANDLE); +- ret = mnl_nft_rule_batch_add(rule, rp->nl_ctx->batch, nl_flags, +- rp->nl_ctx->seqnum); +- break; +- default: +- errno = EOPNOTSUPP; +- break; +- } +- +- return ret; +- +-} +- +-static int netlink_markup_rule(const struct nftnl_parse_ctx *ctx) +-{ +- struct nftnl_rule *rule; +- uint32_t cmd; +- +- cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); +- rule = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_RULE); +- +- return netlink_markup_build_rule(ctx, cmd, rule); +-} +- +-static int netlink_markup_build_flush(const struct nftnl_parse_ctx *ctx) +-{ +- struct nftnl_rule *rule; +- struct nftnl_table *table; +- struct nftnl_chain *chain; +- const char *table_get_name, *table_get_family; +- const char *chain_get_table, *chain_get_name, *chain_get_family; +- uint32_t type; +- int ret = -1; +- +- rule = nftnl_rule_alloc(); +- if (rule == NULL) +- return -1; +- +- type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE); +- switch (type) { +- case NFTNL_RULESET_TABLE: +- table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE); +- table_get_name = nftnl_table_get(table, NFTNL_TABLE_NAME); +- table_get_family = nftnl_table_get(table, NFTNL_TABLE_FAMILY); +- +- nftnl_rule_set(rule, NFTNL_RULE_TABLE, table_get_name); +- nftnl_rule_set(rule, NFTNL_RULE_FAMILY, table_get_family); +- break; +- case NFTNL_RULESET_CHAIN: +- chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN); +- chain_get_table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE); +- chain_get_name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME); +- chain_get_family = nftnl_chain_get(chain, NFTNL_TABLE_FAMILY); +- +- nftnl_rule_set(rule, NFTNL_RULE_TABLE, chain_get_table); +- nftnl_rule_set(rule, NFTNL_RULE_CHAIN, chain_get_name); +- nftnl_rule_set(rule, NFTNL_RULE_FAMILY, chain_get_family); +- break; +- default: +- errno = EOPNOTSUPP; +- goto err; +- } +- +- ret = netlink_markup_build_rule(ctx, NFTNL_CMD_DELETE, rule); +-err: +- nftnl_rule_free(rule); +- return ret; +-} +- +-static int netlink_markup_chain(const struct nftnl_parse_ctx *ctx) +-{ +- const struct ruleset_parse *rp; +- struct nftnl_chain *chain; +- uint32_t cmd; +- int ret = -1; +- +- chain = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_CHAIN); +- rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); +- +- nftnl_chain_unset(chain, NFTNL_CHAIN_HANDLE); +- +- cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); +- switch (cmd) { +- case NFTNL_CMD_ADD: +- ret = mnl_nft_chain_batch_add(chain, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_DELETE: +- ret = mnl_nft_chain_batch_del(chain, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_FLUSH: +- ret = netlink_markup_build_flush(ctx); +- break; +- default: +- errno = EOPNOTSUPP; +- break; +- } +- +- return ret; +-} +- +- +-static int netlink_markup_build_table(const struct nftnl_parse_ctx *ctx, +- uint32_t cmd, struct nftnl_table *table) +-{ +- struct ruleset_parse *rp; +- int ret = -1; +- +- rp = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_DATA); +- +- switch (cmd) { +- case NFTNL_CMD_ADD: +- ret = mnl_nft_table_batch_add(table, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_DELETE: +- ret = mnl_nft_table_batch_del(table, rp->nl_ctx->batch, +- 0, rp->nl_ctx->seqnum); +- break; +- case NFTNL_CMD_FLUSH: +- ret = netlink_markup_build_flush(ctx); +- break; +- default: +- errno = EOPNOTSUPP; +- break; +- } +- +- return ret; +-} +- +-static int netlink_markup_table(const struct nftnl_parse_ctx *ctx) +-{ +- struct nftnl_table *table; +- uint32_t cmd; +- +- cmd = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_CMD); +- table = nftnl_ruleset_ctx_get(ctx, NFTNL_RULESET_CTX_TABLE); +- +- return netlink_markup_build_table(ctx, cmd, table); +-} +- +-static int netlink_markup_flush(const struct nftnl_parse_ctx *ctx) +-{ +- struct nftnl_table *table; +- int ret; +- +- table = nftnl_table_alloc(); +- if (table == NULL) +- return -1; +- +- ret = netlink_markup_build_table(ctx, NFTNL_CMD_DELETE, table); +- nftnl_table_free(table); +- +- return ret; +-} +- + int netlink_markup_parse_cb(const struct nftnl_parse_ctx *ctx) + { +- uint32_t type; +- int ret = -1; +- +- type = nftnl_ruleset_ctx_get_u32(ctx, NFTNL_RULESET_CTX_TYPE); +- switch (type) { +- case NFTNL_RULESET_TABLE: +- ret = netlink_markup_table(ctx); +- break; +- case NFTNL_RULESET_CHAIN: +- ret = netlink_markup_chain(ctx); +- break; +- case NFTNL_RULESET_RULE: +- ret = netlink_markup_rule(ctx); +- break; +- case NFTNL_RULESET_SET: +- ret = netlink_markup_set(ctx); +- break; +- case NFTNL_RULESET_SET_ELEMS: +- ret = netlink_markup_setelems(ctx); +- break; +- case NFTNL_RULESET_RULESET: +- ret = netlink_markup_flush(ctx); +- break; +- default: +- errno = EOPNOTSUPP; +- break; +- } +- +- nftnl_ruleset_ctx_free(ctx); +- +- return ret; ++ errno = EOPNOTSUPP; ++ return -1; + } +diff --git a/tests/shell/testcases/import/vm_json_import_0 b/tests/shell/testcases/import/vm_json_import_0 +deleted file mode 100755 +index 546ccf7ab490f..0000000000000 +--- a/tests/shell/testcases/import/vm_json_import_0 ++++ /dev/null +@@ -1,53 +0,0 @@ +-#!/bin/bash +- +-RULESET="table ip mangle { +- set blackhole { +- type ipv4_addr +- elements = { 192.168.1.4, 192.168.1.5 } +- } +- +- chain prerouting { +- type filter hook prerouting priority 0; policy accept; +- tcp dport { ssh, http } accept +- ip saddr @blackhole drop +- icmp type echo-request accept +- iifname \"lo\" accept +- icmp type echo-request counter packets 0 bytes 0 +- ct state established,related accept +- tcp flags != syn counter packets 7 bytes 841 +- ip saddr 192.168.1.100 ip daddr 192.168.1.1 counter packets 0 bytes 0 +- } +-} +-table arp x { +- chain y { +- arp htype 22 +- arp ptype ip +- arp operation != rrequest +- arp operation { request, reply, rrequest, rreply, inrequest, inreply, nak } +- arp hlen 33-45 +- } +-} +-table bridge x { +- chain y { +- type filter hook input priority 0; policy accept; +- vlan id 4094 +- vlan id 4094 vlan cfi 0 +- vlan id 1 ip saddr 10.0.0.0/23 udp dport domain +- } +-} +-table ip6 x { +- chain y { +- type nat hook postrouting priority 0; policy accept; +- icmpv6 id 33-45 +- ip6 daddr fe00::1-fe00::200 udp dport domain counter packets 0 bytes 0 +- meta l4proto tcp masquerade to :1024 +- iifname \"wlan0\" ct state established,new tcp dport vmap { ssh : drop, 222 : drop } masquerade +- tcp dport ssh ip6 daddr 1::2 ether saddr 00:0f:54:0c:11:04 accept +- ip6 daddr fe00::1-fe00::200 udp dport domain counter packets 0 bytes 0 masquerade +- } +-}" +- +-$NFT -f - <<< "$RULESET" +-RULESET_JSON=$($NFT export vm json) +-$NFT flush ruleset +-$NFT import vm json <<< "$RULESET_JSON" +-- +2.21.0 + diff --git a/SOURCES/0051-rule-limit-don-t-print-default-burst-value.patch b/SOURCES/0051-rule-limit-don-t-print-default-burst-value.patch new file mode 100644 index 0000000..4a51b2e --- /dev/null +++ b/SOURCES/0051-rule-limit-don-t-print-default-burst-value.patch @@ -0,0 +1,36 @@ +From a06d879ceba6b1ae7b541c223701435a4d1394e1 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Wed, 4 Jul 2018 15:10:12 +0200 +Subject: [PATCH] rule: limit: don't print default burst value + +limit http-traffic { rate 1/second } gets printed as +limit http-traffic { rate 1/second burst 5 packets } + +caused tests/shell/run-tests.sh tests/shell/testcases/sets/0026named_limit_0 + +to return 'DUMP FAIL'. + +Signed-off-by: Florian Westphal +Acked-by: Pablo Neira Ayuso +(cherry picked from commit 1dc9be8445265498a2db534ae254260b6e7dd75b) +Signed-off-by: Phil Sutter +--- + src/rule.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/rule.c b/src/rule.c +index 0b494e4326be6..850b00cfc9874 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -1472,7 +1472,7 @@ static void obj_print_data(const struct obj *obj, + nft_print(octx, "rate %s%" PRIu64 "/%s", + inv ? "over " : "", obj->limit.rate, + get_unit(obj->limit.unit)); +- if (obj->limit.burst > 0) ++ if (obj->limit.burst > 0 && obj->limit.burst != 5) + nft_print(octx, " burst %u packets", + obj->limit.burst); + break; +-- +2.21.0 + diff --git a/SOURCES/0052-JSON-Review-verdict-statement-and-expression.patch b/SOURCES/0052-JSON-Review-verdict-statement-and-expression.patch new file mode 100644 index 0000000..b0dce22 --- /dev/null +++ b/SOURCES/0052-JSON-Review-verdict-statement-and-expression.patch @@ -0,0 +1,97 @@ +From 9eb22ba5e195c97ca7a1e2baac7fec68b3f3b310 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 29 Aug 2018 16:23:23 +0200 +Subject: [PATCH] JSON: Review verdict statement and expression + +Change jump and goto verdicts to become extensible by dedicating an +object for the target parameter. + +While being at it, drop break and queue verdict expressions since they +don't seem to exist, no idea where I got those from in the first place. +For queue, there is a dedicated expression at least. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 8125785d5c5d35ec275e508166091d5472748bc1) + +Conflicts: + doc/libnftables-json.adoc +-> Dropped changes to non-existent libnftables JSON API documentation. + +Signed-off-by: Phil Sutter +--- + src/json.c | 5 ++++- + src/parser_json.c | 10 ++++------ + tests/py/nft-test.py | 4 +++- + 3 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/src/json.c b/src/json.c +index f74afd5a7292e..fad2a83624062 100644 +--- a/src/json.c ++++ b/src/json.c +@@ -651,7 +651,10 @@ json_t *verdict_expr_json(const struct expr *expr, struct output_ctx *octx) + BUG("Unknown verdict %d.", expr->verdict); + return NULL; + } +- return json_pack("{s:o}", name, chain ? json_string(chain) : json_null()); ++ if (chain) ++ return json_pack("{s:{s:s}}", name, "target", chain); ++ else ++ return json_pack("{s:n}", name); + } + + json_t *rt_expr_json(const struct expr *expr, struct output_ctx *octx) +diff --git a/src/parser_json.c b/src/parser_json.c +index 1e3688b2dc1cd..e3f20ae51c764 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -1008,27 +1008,25 @@ static struct expr *json_parse_verdict_expr(struct json_ctx *ctx, + bool chain; + } verdict_tbl[] = { + { NFT_CONTINUE, "continue", false }, +- { NFT_BREAK, "break", false }, + { NFT_JUMP, "jump", true }, + { NFT_GOTO, "goto", true }, + { NFT_RETURN, "return", false }, + { NF_ACCEPT, "accept", false }, + { NF_DROP, "drop", false }, +- { NF_QUEUE, "queue", false }, + }; + const char *chain = NULL; + unsigned int i; + +- json_unpack(root, "s", &chain); ++ json_unpack(root, "{s:s}", "target", &chain); + + for (i = 0; i < array_size(verdict_tbl); i++) { + if (strcmp(type, verdict_tbl[i].name)) + continue; + +- if (verdict_tbl[i].chain && !chain) { +- json_error(ctx, "Verdict %s needs chain argument.", type); ++ if (verdict_tbl[i].chain && ++ json_unpack_err(ctx, root, "{s:s}", "target", &chain)) + return NULL; +- } ++ + return verdict_expr_alloc(int_loc, + verdict_tbl[i].verdict, chain); + } +diff --git a/tests/py/nft-test.py b/tests/py/nft-test.py +index c02294ac54562..08569fbe0de44 100755 +--- a/tests/py/nft-test.py ++++ b/tests/py/nft-test.py +@@ -277,7 +277,9 @@ def chain_create(chain, table, filename): + print_error(reason, filename, chain.lineno) + return -1 + +- cmd = "add chain %s %s { %s; }" % (table, chain, chain.config) ++ cmd = "add chain %s %s" % (table, chain) ++ if chain.config: ++ cmd += " { %s; }" % chain.config + + ret = execute_cmd(cmd, filename, chain.lineno) + if ret != 0: +-- +2.21.0 + diff --git a/SOURCES/0053-parser_json-Duplicate-chain-name-when-parsing-jump-v.patch b/SOURCES/0053-parser_json-Duplicate-chain-name-when-parsing-jump-v.patch new file mode 100644 index 0000000..362a141 --- /dev/null +++ b/SOURCES/0053-parser_json-Duplicate-chain-name-when-parsing-jump-v.patch @@ -0,0 +1,35 @@ +From 5a6bcfe9e3d323e9503383601234fde3f3cf4a0b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 26 Feb 2019 22:13:39 +0100 +Subject: [PATCH] parser_json: Duplicate chain name when parsing jump verdict + +Since verdict expression frees the chain name, pass a newly allocated +string to it. Otherwise double free happens because json_decref() frees +the string property value as well. + +Fixes: d1057a5feb5fd ("JSON: Simplify verdict statement parsing") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit dc6a6e83b47fc7078a061350cd2b111cb2adec14) +Signed-off-by: Phil Sutter +--- + src/parser_json.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index e3f20ae51c764..688fac1bddde2 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -1028,7 +1028,8 @@ static struct expr *json_parse_verdict_expr(struct json_ctx *ctx, + return NULL; + + return verdict_expr_alloc(int_loc, +- verdict_tbl[i].verdict, chain); ++ verdict_tbl[i].verdict, ++ chain ? xstrdup(chain) : NULL); + } + json_error(ctx, "Unknown verdict '%s'.", type); + return NULL; +-- +2.21.0 + diff --git a/SOURCES/0054-src-Introduce-chain_expr-in-jump-and-goto-statements.patch b/SOURCES/0054-src-Introduce-chain_expr-in-jump-and-goto-statements.patch new file mode 100644 index 0000000..7a3fded --- /dev/null +++ b/SOURCES/0054-src-Introduce-chain_expr-in-jump-and-goto-statements.patch @@ -0,0 +1,324 @@ +From b5852ee30b4ee854c81bf93c1c7b4ec5b0dd7e3f Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Fri, 24 May 2019 15:06:47 +0200 +Subject: [PATCH] src: Introduce chain_expr in jump and goto statements + +Introduce expressions as a chain in jump and goto statements. +This is going to be used to support variables as a chain in the +following patches. + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit f1e8a129ee428419a0d5a45a2f410e8e4008d109) + +Conflicts: +-> Adjust for missing commit 72931553828af + ("src: expr: add expression etype") + +Signed-off-by: Phil Sutter +--- + include/expression.h | 4 ++-- + src/datatype.c | 22 ++++++++++++++++++++-- + src/evaluate.c | 4 ++++ + src/expression.c | 12 ++++++------ + src/json.c | 6 +++--- + src/netlink.c | 26 +++++++++++++++++++++----- + src/parser_bison.y | 17 +++++++++++++---- + src/parser_json.c | 9 +++++++-- + 8 files changed, 76 insertions(+), 24 deletions(-) + +diff --git a/include/expression.h b/include/expression.h +index 885e9c43bb77f..5f814fdb065fe 100644 +--- a/include/expression.h ++++ b/include/expression.h +@@ -233,7 +233,7 @@ struct expr { + struct { + /* EXPR_VERDICT */ + int verdict; +- const char *chain; ++ struct expr *chain; + }; + struct { + /* EXPR_VALUE */ +@@ -385,7 +385,7 @@ extern void relational_expr_pctx_update(struct proto_ctx *ctx, + const struct expr *expr); + + extern struct expr *verdict_expr_alloc(const struct location *loc, +- int verdict, const char *chain); ++ int verdict, struct expr *chain); + + extern struct expr *symbol_expr_alloc(const struct location *loc, + enum symbol_types type, struct scope *scope, +diff --git a/src/datatype.c b/src/datatype.c +index 209044539bb84..f7defa37ff196 100644 +--- a/src/datatype.c ++++ b/src/datatype.c +@@ -253,6 +253,8 @@ const struct datatype invalid_type = { + + static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) + { ++ char chain[NFT_CHAIN_MAXNAMELEN]; ++ + switch (expr->verdict) { + case NFT_CONTINUE: + nft_print(octx, "continue"); +@@ -261,10 +263,26 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) + nft_print(octx, "break"); + break; + case NFT_JUMP: +- nft_print(octx, "jump %s", expr->chain); ++ if (expr->chain->ops->type == EXPR_VALUE) { ++ mpz_export_data(chain, expr->chain->value, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN); ++ nft_print(octx, "jump %s", chain); ++ } else { ++ nft_print(octx, "jump "); ++ expr_print(expr->chain, octx); ++ } + break; + case NFT_GOTO: +- nft_print(octx, "goto %s", expr->chain); ++ if (expr->chain->ops->type == EXPR_VALUE) { ++ mpz_export_data(chain, expr->chain->value, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN); ++ nft_print(octx, "goto %s", chain); ++ } else { ++ nft_print(octx, "goto "); ++ expr_print(expr->chain, octx); ++ } + break; + case NFT_RETURN: + nft_print(octx, "return"); +diff --git a/src/evaluate.c b/src/evaluate.c +index 88fa44dd34ef5..5f0f3b36fd99f 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -1847,6 +1847,10 @@ static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt) + case EXPR_VERDICT: + if (stmt->expr->verdict != NFT_CONTINUE) + stmt->flags |= STMT_F_TERMINAL; ++ if (stmt->expr->chain != NULL) { ++ if (expr_evaluate(ctx, &stmt->expr->chain) < 0) ++ return -1; ++ } + break; + case EXPR_MAP: + break; +diff --git a/src/expression.c b/src/expression.c +index bea0f4c8d9bc1..411047cb9341d 100644 +--- a/src/expression.c ++++ b/src/expression.c +@@ -174,22 +174,22 @@ static bool verdict_expr_cmp(const struct expr *e1, const struct expr *e2) + + if ((e1->verdict == NFT_JUMP || + e1->verdict == NFT_GOTO) && +- strcmp(e1->chain, e2->chain)) +- return false; ++ expr_cmp(e1->chain, e2->chain)) ++ return true; + +- return true; ++ return false; + } + + static void verdict_expr_clone(struct expr *new, const struct expr *expr) + { + new->verdict = expr->verdict; + if (expr->chain != NULL) +- new->chain = xstrdup(expr->chain); ++ mpz_init_set(new->chain->value, expr->chain->value); + } + + static void verdict_expr_destroy(struct expr *expr) + { +- xfree(expr->chain); ++ expr_free(expr->chain); + } + + static const struct expr_ops verdict_expr_ops = { +@@ -203,7 +203,7 @@ static const struct expr_ops verdict_expr_ops = { + }; + + struct expr *verdict_expr_alloc(const struct location *loc, +- int verdict, const char *chain) ++ int verdict, struct expr *chain) + { + struct expr *expr; + +diff --git a/src/json.c b/src/json.c +index fad2a83624062..6ecebc477146f 100644 +--- a/src/json.c ++++ b/src/json.c +@@ -636,14 +636,14 @@ json_t *verdict_expr_json(const struct expr *expr, struct output_ctx *octx) + { NF_QUEUE, "queue", false }, + }; + const char *name = NULL; +- const char *chain = NULL; ++ json_t *chain = NULL; + unsigned int i; + + for (i = 0; i < array_size(verdict_tbl); i++) { + if (expr->verdict == verdict_tbl[i].verdict) { + name = verdict_tbl[i].name; + if (verdict_tbl[i].chain && expr->chain) +- chain = expr->chain; ++ chain = expr_print_json(expr->chain, octx); + break; + } + } +@@ -652,7 +652,7 @@ json_t *verdict_expr_json(const struct expr *expr, struct output_ctx *octx) + return NULL; + } + if (chain) +- return json_pack("{s:{s:s}}", name, "target", chain); ++ return json_pack("{s:{s:o}}", name, "target", chain); + else + return json_pack("{s:n}", name); + } +diff --git a/src/netlink.c b/src/netlink.c +index 0509a06b3d2b3..fcd05b73f4c0e 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -391,12 +391,17 @@ static void netlink_gen_constant_data(const struct expr *expr, + static void netlink_gen_verdict(const struct expr *expr, + struct nft_data_linearize *data) + { ++ char chain[NFT_CHAIN_MAXNAMELEN]; ++ + data->verdict = expr->verdict; + + switch (expr->verdict) { + case NFT_JUMP: + case NFT_GOTO: +- snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", expr->chain); ++ mpz_export_data(chain, expr->chain->value, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN); ++ snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain); + data->chain[NFT_CHAIN_MAXNAMELEN-1] = '\0'; + break; + } +@@ -426,12 +431,15 @@ struct expr *netlink_alloc_value(const struct location *loc, + static struct expr *netlink_alloc_verdict(const struct location *loc, + const struct nft_data_delinearize *nld) + { +- char *chain; ++ struct expr *chain; + + switch (nld->verdict) { + case NFT_JUMP: + case NFT_GOTO: +- chain = xstrdup(nld->chain); ++ chain = constant_expr_alloc(loc, &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN * ++ BITS_PER_BYTE, nld->chain); + break; + default: + chain = NULL; +@@ -1694,14 +1702,22 @@ static void trace_print_expr(const struct nftnl_trace *nlt, unsigned int attr, + static void trace_print_verdict(const struct nftnl_trace *nlt, + struct output_ctx *octx) + { ++ struct expr *chain_expr = NULL; + const char *chain = NULL; + unsigned int verdict; + struct expr *expr; + + verdict = nftnl_trace_get_u32(nlt, NFTNL_TRACE_VERDICT); +- if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) ++ if (nftnl_trace_is_set(nlt, NFTNL_TRACE_JUMP_TARGET)) { + chain = xstrdup(nftnl_trace_get_str(nlt, NFTNL_TRACE_JUMP_TARGET)); +- expr = verdict_expr_alloc(&netlink_location, verdict, chain); ++ chain_expr = constant_expr_alloc(&netlink_location, ++ &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN ++ * BITS_PER_BYTE, ++ chain); ++ } ++ expr = verdict_expr_alloc(&netlink_location, verdict, chain_expr); + + nft_print(octx, "verdict "); + expr_print(expr, octx); +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 1dc83953ea858..08dce52cebd1e 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -583,8 +583,8 @@ int nft_lex(void *, void *, void *); + %type meter_stmt meter_stmt_alloc flow_stmt_legacy_alloc + %destructor { stmt_free($$); } meter_stmt meter_stmt_alloc flow_stmt_legacy_alloc + +-%type symbol_expr verdict_expr integer_expr variable_expr +-%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr ++%type symbol_expr verdict_expr integer_expr variable_expr chain_expr ++%destructor { expr_free($$); } symbol_expr verdict_expr integer_expr variable_expr chain_expr + %type primary_expr shift_expr and_expr + %destructor { expr_free($$); } primary_expr shift_expr and_expr + %type exclusive_or_expr inclusive_or_expr +@@ -3461,11 +3461,11 @@ verdict_expr : ACCEPT + { + $$ = verdict_expr_alloc(&@$, NFT_CONTINUE, NULL); + } +- | JUMP identifier ++ | JUMP chain_expr + { + $$ = verdict_expr_alloc(&@$, NFT_JUMP, $2); + } +- | GOTO identifier ++ | GOTO chain_expr + { + $$ = verdict_expr_alloc(&@$, NFT_GOTO, $2); + } +@@ -3475,6 +3475,15 @@ verdict_expr : ACCEPT + } + ; + ++chain_expr : identifier ++ { ++ $$ = constant_expr_alloc(&@$, &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN * ++ BITS_PER_BYTE, $1); ++ } ++ ; ++ + meta_expr : META meta_key + { + $$ = meta_expr_alloc(&@$, $2); +diff --git a/src/parser_json.c b/src/parser_json.c +index 688fac1bddde2..b62c4125a0144 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -1014,10 +1014,16 @@ static struct expr *json_parse_verdict_expr(struct json_ctx *ctx, + { NF_ACCEPT, "accept", false }, + { NF_DROP, "drop", false }, + }; ++ struct expr *chain_expr = NULL; + const char *chain = NULL; + unsigned int i; + + json_unpack(root, "{s:s}", "target", &chain); ++ if (!chain) ++ chain_expr = constant_expr_alloc(int_loc, &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN * ++ BITS_PER_BYTE, chain); + + for (i = 0; i < array_size(verdict_tbl); i++) { + if (strcmp(type, verdict_tbl[i].name)) +@@ -1028,8 +1034,7 @@ static struct expr *json_parse_verdict_expr(struct json_ctx *ctx, + return NULL; + + return verdict_expr_alloc(int_loc, +- verdict_tbl[i].verdict, +- chain ? xstrdup(chain) : NULL); ++ verdict_tbl[i].verdict, chain_expr); + } + json_error(ctx, "Unknown verdict '%s'.", type); + return NULL; +-- +2.21.0 + diff --git a/SOURCES/0055-src-Allow-goto-and-jump-to-a-variable.patch b/SOURCES/0055-src-Allow-goto-and-jump-to-a-variable.patch new file mode 100644 index 0000000..7928c06 --- /dev/null +++ b/SOURCES/0055-src-Allow-goto-and-jump-to-a-variable.patch @@ -0,0 +1,204 @@ +From 0100e69baee2e3a7e4bf5f0fb5c824d5c3e81286 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Fri, 24 May 2019 15:06:50 +0200 +Subject: [PATCH] src: Allow goto and jump to a variable + +This patch introduces the use of nft input files variables in 'jump' and 'goto' +statements, e.g. + +define dest = ber + +add table ip foo +add chain ip foo bar {type filter hook input priority 0;} +add chain ip foo ber +add rule ip foo ber counter +add rule ip foo bar jump $dest + +table ip foo { + chain bar { + type filter hook input priority filter; policy accept; + jump ber + } + + chain ber { + counter packets 71 bytes 6664 + } +} + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit c64457cff9673fbb41f613a67e158b4d62235c09) + +Conflicts: +-> Adjust for missing commits 72931553828af + ("src: expr: add expression etype") and 68e76238749fb + ("src: expr: add and use expr_name helper"). + +Signed-off-by: Phil Sutter +--- + src/datatype.c | 11 ++++++++++ + src/evaluate.c | 7 +++++++ + src/parser_bison.y | 3 ++- + .../shell/testcases/nft-f/0018jump_variable_0 | 19 ++++++++++++++++++ + .../shell/testcases/nft-f/0019jump_variable_1 | 20 +++++++++++++++++++ + .../shell/testcases/nft-f/0020jump_variable_1 | 20 +++++++++++++++++++ + .../nft-f/dumps/0018jump_variable_0.nft | 8 ++++++++ + 7 files changed, 87 insertions(+), 1 deletion(-) + create mode 100755 tests/shell/testcases/nft-f/0018jump_variable_0 + create mode 100755 tests/shell/testcases/nft-f/0019jump_variable_1 + create mode 100755 tests/shell/testcases/nft-f/0020jump_variable_1 + create mode 100644 tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft + +diff --git a/src/datatype.c b/src/datatype.c +index f7defa37ff196..5791a6a41599e 100644 +--- a/src/datatype.c ++++ b/src/datatype.c +@@ -308,11 +308,22 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) + } + } + ++static struct error_record *verdict_type_parse(const struct expr *sym, ++ struct expr **res) ++{ ++ *res = constant_expr_alloc(&sym->location, &string_type, ++ BYTEORDER_HOST_ENDIAN, ++ (strlen(sym->identifier) + 1) * BITS_PER_BYTE, ++ sym->identifier); ++ return NULL; ++} ++ + const struct datatype verdict_type = { + .type = TYPE_VERDICT, + .name = "verdict", + .desc = "netfilter verdict", + .print = verdict_type_print, ++ .parse = verdict_type_parse, + }; + + static const struct symbol_table nfproto_tbl = { +diff --git a/src/evaluate.c b/src/evaluate.c +index 5f0f3b36fd99f..8e15e71d8a33b 100644 +--- a/src/evaluate.c ++++ b/src/evaluate.c +@@ -1850,6 +1850,13 @@ static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt) + if (stmt->expr->chain != NULL) { + if (expr_evaluate(ctx, &stmt->expr->chain) < 0) + return -1; ++ if ((stmt->expr->chain->ops->type != EXPR_SYMBOL && ++ stmt->expr->chain->ops->type != EXPR_VALUE) || ++ stmt->expr->chain->symtype != SYMBOL_VALUE) { ++ return stmt_error(ctx, stmt, ++ "invalid verdict chain expression %s\n", ++ stmt->expr->chain->ops->name); ++ } + } + break; + case EXPR_MAP: +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 08dce52cebd1e..2e8ebde34eee6 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -3475,7 +3475,8 @@ verdict_expr : ACCEPT + } + ; + +-chain_expr : identifier ++chain_expr : variable_expr ++ | identifier + { + $$ = constant_expr_alloc(&@$, &string_type, + BYTEORDER_HOST_ENDIAN, +diff --git a/tests/shell/testcases/nft-f/0018jump_variable_0 b/tests/shell/testcases/nft-f/0018jump_variable_0 +new file mode 100755 +index 0000000000000..003a1bdf701f1 +--- /dev/null ++++ b/tests/shell/testcases/nft-f/0018jump_variable_0 +@@ -0,0 +1,19 @@ ++#!/bin/bash ++ ++# Tests use of variables in jump statements ++ ++set -e ++ ++RULESET=" ++define dest = ber ++ ++table ip foo { ++ chain bar { ++ jump \$dest ++ } ++ ++ chain ber { ++ } ++}" ++ ++$NFT -f - <<< "$RULESET" +diff --git a/tests/shell/testcases/nft-f/0019jump_variable_1 b/tests/shell/testcases/nft-f/0019jump_variable_1 +new file mode 100755 +index 0000000000000..bda861c91df31 +--- /dev/null ++++ b/tests/shell/testcases/nft-f/0019jump_variable_1 +@@ -0,0 +1,20 @@ ++#!/bin/bash ++ ++# Tests use of variables in jump statements ++ ++set -e ++ ++RULESET=" ++define dest = { 1024 } ++ ++table ip foo { ++ chain bar { ++ jump \$dest ++ } ++ ++ chain ber { ++ } ++}" ++ ++$NFT -f - <<< "$RULESET" && exit 1 ++exit 0 +diff --git a/tests/shell/testcases/nft-f/0020jump_variable_1 b/tests/shell/testcases/nft-f/0020jump_variable_1 +new file mode 100755 +index 0000000000000..f753058f24f64 +--- /dev/null ++++ b/tests/shell/testcases/nft-f/0020jump_variable_1 +@@ -0,0 +1,20 @@ ++#!/bin/bash ++ ++# Tests use of variables in jump statements ++ ++set -e ++ ++RULESET=" ++define dest = * ++ ++table ip foo { ++ chain bar { ++ jump \$dest ++ } ++ ++ chain ber { ++ } ++}" ++ ++$NFT -f - <<< "$RULESET" && exit 1 ++exit 0 +diff --git a/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft +new file mode 100644 +index 0000000000000..0ddaf07f0ea3b +--- /dev/null ++++ b/tests/shell/testcases/nft-f/dumps/0018jump_variable_0.nft +@@ -0,0 +1,8 @@ ++table ip foo { ++ chain bar { ++ jump ber ++ } ++ ++ chain ber { ++ } ++} +-- +2.21.0 + diff --git a/SOURCES/0056-parser_json-Fix-and-simplify-verdict-expression-pars.patch b/SOURCES/0056-parser_json-Fix-and-simplify-verdict-expression-pars.patch new file mode 100644 index 0000000..c12a61e --- /dev/null +++ b/SOURCES/0056-parser_json-Fix-and-simplify-verdict-expression-pars.patch @@ -0,0 +1,82 @@ +From cc4fa3ebfd8bbb18e17711f8ec122043340a1680 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 27 May 2019 13:37:00 +0200 +Subject: [PATCH] parser_json: Fix and simplify verdict expression parsing + +Parsing of the "target" property was flawed in two ways: + +* The value was extracted twice. Drop the first unconditional one. +* Expression allocation required since commit f1e8a129ee428 was broken, + The expression was allocated only if the property was not present. + +Fixes: f1e8a129ee428 ("src: Introduce chain_expr in jump and goto statements") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit c34ad1653ff98db5d1ddceab663401055ac7ae4c) +Signed-off-by: Phil Sutter +--- + src/parser_json.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index b62c4125a0144..7e4da4838e40b 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -999,13 +999,22 @@ static struct expr *json_parse_range_expr(struct json_ctx *ctx, + return range_expr_alloc(int_loc, expr_low, expr_high); + } + ++static struct expr *json_alloc_chain_expr(const char *chain) ++{ ++ if (!chain) ++ return NULL; ++ ++ return constant_expr_alloc(int_loc, &string_type, BYTEORDER_HOST_ENDIAN, ++ NFT_CHAIN_MAXNAMELEN * BITS_PER_BYTE, chain); ++} ++ + static struct expr *json_parse_verdict_expr(struct json_ctx *ctx, + const char *type, json_t *root) + { + const struct { + int verdict; + const char *name; +- bool chain; ++ bool need_chain; + } verdict_tbl[] = { + { NFT_CONTINUE, "continue", false }, + { NFT_JUMP, "jump", true }, +@@ -1014,27 +1023,19 @@ static struct expr *json_parse_verdict_expr(struct json_ctx *ctx, + { NF_ACCEPT, "accept", false }, + { NF_DROP, "drop", false }, + }; +- struct expr *chain_expr = NULL; + const char *chain = NULL; + unsigned int i; + +- json_unpack(root, "{s:s}", "target", &chain); +- if (!chain) +- chain_expr = constant_expr_alloc(int_loc, &string_type, +- BYTEORDER_HOST_ENDIAN, +- NFT_CHAIN_MAXNAMELEN * +- BITS_PER_BYTE, chain); +- + for (i = 0; i < array_size(verdict_tbl); i++) { + if (strcmp(type, verdict_tbl[i].name)) + continue; + +- if (verdict_tbl[i].chain && ++ if (verdict_tbl[i].need_chain && + json_unpack_err(ctx, root, "{s:s}", "target", &chain)) + return NULL; + +- return verdict_expr_alloc(int_loc, +- verdict_tbl[i].verdict, chain_expr); ++ return verdict_expr_alloc(int_loc, verdict_tbl[i].verdict, ++ json_alloc_chain_expr(chain)); + } + json_error(ctx, "Unknown verdict '%s'.", type); + return NULL; +-- +2.21.0 + diff --git a/SOURCES/0057-src-invalid-read-when-importing-chain-name.patch b/SOURCES/0057-src-invalid-read-when-importing-chain-name.patch new file mode 100644 index 0000000..ab5df69 --- /dev/null +++ b/SOURCES/0057-src-invalid-read-when-importing-chain-name.patch @@ -0,0 +1,67 @@ +From 2b491f62a6a2d34f747ccf083eb016a8d0dcdba9 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 10 Jun 2019 13:12:20 +0200 +Subject: [PATCH] src: invalid read when importing chain name + +Use strlen(), otherwise mpz_import_data() reads too much beyond the real +chain string. Valgrind reports the following error: + +==2759== Invalid read of size 1 +==2759== at 0x67D68D6: __gmpz_import (in /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2) +==2759== by 0x4E79467: mpz_import_data (gmputil.c:133) +==2759== by 0x4E60A12: constant_expr_alloc (expression.c:375) +==2759== by 0x4E8ED65: nft_parse (parser_bison.y:3825) +==2759== by 0x4E7E850: nft_parse_bison_buffer (libnftables.c:357) +==2759== by 0x4E7E850: nft_run_cmd_from_buffer (libnftables.c:424) +==2759== by 0x1095D4: main (in /tmp/a.out) +==2759== Address 0x6ee1b4a is 0 bytes after a block of size 10 alloc'd +==2759== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) +==2759== by 0x59FD3B9: strdup (strdup.c:42) +==2759== by 0x4E7963D: xstrdup (utils.c:75) +==2759== by 0x4E9C233: nft_lex (scanner.l:626) +==2759== by 0x4E8E382: nft_parse (parser_bison.c:5297) +==2759== by 0x4E7E850: nft_parse_bison_buffer (libnftables.c:357) +==2759== by 0x4E7E850: nft_run_cmd_from_buffer (libnftables.c:424) + +Fixes: f1e8a129ee42 ("src: Introduce chain_expr in jump and goto statements") +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 142350f154c78a1aeccebc6115440162986dc906) +Signed-off-by: Phil Sutter +--- + src/netlink.c | 4 ++-- + src/parser_bison.y | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/netlink.c b/src/netlink.c +index fcd05b73f4c0e..fc310fd293d64 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -438,8 +438,8 @@ static struct expr *netlink_alloc_verdict(const struct location *loc, + case NFT_GOTO: + chain = constant_expr_alloc(loc, &string_type, + BYTEORDER_HOST_ENDIAN, +- NFT_CHAIN_MAXNAMELEN * +- BITS_PER_BYTE, nld->chain); ++ strlen(nld->chain) * BITS_PER_BYTE, ++ nld->chain); + break; + default: + chain = NULL; +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 2e8ebde34eee6..4bd1ae1e39855 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -3480,8 +3480,8 @@ chain_expr : variable_expr + { + $$ = constant_expr_alloc(&@$, &string_type, + BYTEORDER_HOST_ENDIAN, +- NFT_CHAIN_MAXNAMELEN * +- BITS_PER_BYTE, $1); ++ strlen($1) * BITS_PER_BYTE, ++ $1); + } + ; + +-- +2.21.0 + diff --git a/SOURCES/0058-expression-use-expr_clone-from-verdict_expr_clone.patch b/SOURCES/0058-expression-use-expr_clone-from-verdict_expr_clone.patch new file mode 100644 index 0000000..a8ffd48 --- /dev/null +++ b/SOURCES/0058-expression-use-expr_clone-from-verdict_expr_clone.patch @@ -0,0 +1,43 @@ +From b9422bf04c66ac4c6fd5fec1f539e8ff270f83f1 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 10 Jun 2019 13:51:20 +0200 +Subject: [PATCH] expression: use expr_clone() from verdict_expr_clone() + +Chains are now expressions, do not assume a constant value is used. + +==26302== Process terminating with default action of signal 11 (SIGSEGV) +==26302== Access not within mapped region at address 0x50 +==26302== at 0x67D7EE7: __gmpz_init_set (in /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2) +==26302== by 0x4E61224: expr_clone (expression.c:65) +==26302== by 0x4E7898B: interval_map_decompose (segtree.c:943) +==26302== by 0x4E6DDA0: netlink_list_setelems (netlink.c:882) +==26302== by 0x4E5A806: cache_init_objects (rule.c:166) +==26302== by 0x4E5A806: cache_init (rule.c:216) +==26302== by 0x4E5A806: cache_update (rule.c:266) +==26302== by 0x4E7E0EE: nft_evaluate (libnftables.c:388) +==26302== by 0x4E7E8AB: nft_run_cmd_from_buffer (libnftables.c:428) + +Fixes: f1e8a129ee42 ("src: Introduce chain_expr in jump and goto statements") +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit aaf0167f2615372c1baaff327d1fb89d4297a52a) +Signed-off-by: Phil Sutter +--- + src/expression.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/expression.c b/src/expression.c +index 411047cb9341d..a339c6f30bce5 100644 +--- a/src/expression.c ++++ b/src/expression.c +@@ -184,7 +184,7 @@ static void verdict_expr_clone(struct expr *new, const struct expr *expr) + { + new->verdict = expr->verdict; + if (expr->chain != NULL) +- mpz_init_set(new->chain->value, expr->chain->value); ++ new->chain = expr_clone(expr->chain); + } + + static void verdict_expr_destroy(struct expr *expr) +-- +2.21.0 + diff --git a/SOURCES/0059-parser_bison-free-chain-name-after-creating-constant.patch b/SOURCES/0059-parser_bison-free-chain-name-after-creating-constant.patch new file mode 100644 index 0000000..f01ea16 --- /dev/null +++ b/SOURCES/0059-parser_bison-free-chain-name-after-creating-constant.patch @@ -0,0 +1,39 @@ +From 8bd95db6d02b8ed268f2bfb7ec62b4d0cfbf82ad Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 10 Jun 2019 19:23:40 +0200 +Subject: [PATCH] parser_bison: free chain name after creating constant + expression + +==2330== 2 bytes in 1 blocks are definitely lost in loss record 1 of 1 +==2330== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) +==2330== by 0x583D3B9: strdup (strdup.c:42) +==2330== by 0x4E7966D: xstrdup (utils.c:75) +==2330== by 0x4E9C283: nft_lex (scanner.l:626) +==2330== by 0x4E8E3C2: nft_parse (parser_bison.c:5297) +==2330== by 0x4E7EAB2: nft_parse_bison_filename (libnftables.c:374) +==2330== by 0x4E7EAB2: nft_run_cmd_from_filename (libnftables.c:475) +==2330== by 0x109A53: main (main.c:310) + +Fixes: f1e8a129ee42 ("src: Introduce chain_expr in jump and goto statements") +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 29d0b6b0526ed9b661db9f1c8dbd2abbff11483a) +Signed-off-by: Phil Sutter +--- + src/parser_bison.y | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/parser_bison.y b/src/parser_bison.y +index 4bd1ae1e39855..cea5d7660ba4c 100644 +--- a/src/parser_bison.y ++++ b/src/parser_bison.y +@@ -3482,6 +3482,7 @@ chain_expr : variable_expr + BYTEORDER_HOST_ENDIAN, + strlen($1) * BITS_PER_BYTE, + $1); ++ xfree($1); + } + ; + +-- +2.21.0 + diff --git a/SOURCES/0060-doc-update-nft-list-plural-form-parameters.patch b/SOURCES/0060-doc-update-nft-list-plural-form-parameters.patch new file mode 100644 index 0000000..363ef4e --- /dev/null +++ b/SOURCES/0060-doc-update-nft-list-plural-form-parameters.patch @@ -0,0 +1,84 @@ +From dafcd4c03c7d05ba8613c9fffb78aefaf87b31b7 Mon Sep 17 00:00:00 2001 +From: Fernando Fernandez Mancera +Date: Fri, 5 Apr 2019 17:36:55 +0200 +Subject: [PATCH] doc: update nft list plural form parameters + +Signed-off-by: Fernando Fernandez Mancera +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 067ac215e93f6cb912c3f99ca9e6689397bfba2f) + +Conflicts: + doc/nft.txt +-> Changes applied manually to doc/nft.xml + +Signed-off-by: Phil Sutter +--- + doc/nft.xml | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/doc/nft.xml b/doc/nft.xml +index 1a97d7a169776..ea3973e1b8f1a 100644 +--- a/doc/nft.xml ++++ b/doc/nft.xml +@@ -560,6 +560,10 @@ filter input iif $int_ifs accept + family + table + ++ ++ list ++ tables ++ + + delete + table +@@ -705,6 +709,10 @@ add table inet mytable + table + chain + ++ ++ list ++ chains ++ + + delete + chain +@@ -1036,6 +1044,10 @@ table inet filter { + table + set + ++ ++ list ++ sets ++ + + delete + set +@@ -1187,6 +1199,10 @@ table inet filter { + policy policy ; + } + ++ ++ list ++ maps ++ + + + delete +@@ -1418,6 +1434,14 @@ table inet filter { + table + handle handle + ++ ++ list ++ counters ++ ++ ++ list ++ quotas ++ + + + Stateful objects are attached to tables and are identified by an unique name. They group stateful information from rules, to reference them in rules the keywords "type name" are used e.g. "counter name". +-- +2.21.0 + diff --git a/SOURCES/0061-doc-Add-minimal-description-of-v-map-statements.patch b/SOURCES/0061-doc-Add-minimal-description-of-v-map-statements.patch new file mode 100644 index 0000000..c34cd0e --- /dev/null +++ b/SOURCES/0061-doc-Add-minimal-description-of-v-map-statements.patch @@ -0,0 +1,100 @@ +From 1ac8084be4f5a66f078fb346c7dee618ce2d217e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 4 Apr 2019 13:02:55 +0200 +Subject: [PATCH] doc: Add minimal description of (v)map statements + +Although quite useful, these were missing in man page. Content loosely +based on wiki documentation. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 3b29acc8f29944c5cf34259f2e2b5b40b4d0ccdd) + +Conflicts: +-> Changes applied manually, upstream merged to asciidoc. + +Signed-off-by: Phil Sutter +--- + doc/nft.xml | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 66 insertions(+) + +diff --git a/doc/nft.xml b/doc/nft.xml +index ea3973e1b8f1a..9acff09e30619 100644 +--- a/doc/nft.xml ++++ b/doc/nft.xml +@@ -5535,6 +5535,72 @@ dup to ip daddr map { 192.168.7.1 : "eth0", 192.168.7.2 : "eth1" } + + + ++ ++ ++ Map statement ++ ++ The map statement is used to lookup data based on some specific input key. ++ ++ ++ ++ expression ++ map { ++ key ++ : ++ value ++ ++ , ++ key ++ : ++ value ++ ++ } ++ ++ ++ ++ using the map statement ++ ++# select DNAT target based on TCP dport: ++# connections to port 80 are redirected to 192.168.1.100, ++# connections to port 8888 are redirected to 192.168.1.101 ++nft add rule ip nat prerouting dnat tcp dport map { 80 : 192.168.1.100, 8888 : 192.168.1.101 } ++ ++# source address based SNAT: ++# packets from net 192.168.1.0/24 will appear as originating from 10.0.0.1, ++# packets from net 192.168.2.0/24 will appear as originating from 10.0.0.2 ++nft add rule ip nat postrouting snat to ip saddr map { 192.168.1.0/24 : 10.0.0.1, 192.168.2.0/24 : 10.0.0.2 } ++ ++ ++ ++ ++ Vmap statement ++ ++ The verdict map (vmap) statement works analogous to the map statement, but contains verdicts as values. ++ ++ ++ ++ expression ++ vmap { ++ key ++ : ++ value ++ ++ , ++ key ++ : ++ value ++ ++ } ++ ++ ++ ++ using the vmap statement ++ ++# jump to different chains depending on layer 4 protocol type: ++nft add rule ip filter input ip protocol vmap { tcp : jump tcp-chain, udp : jump udp-chain , icmp : jump icmp-chain } ++ ++ ++ + + + +-- +2.21.0 + diff --git a/SOURCES/0062-xt-pass-octx-to-translate-function.patch b/SOURCES/0062-xt-pass-octx-to-translate-function.patch new file mode 100644 index 0000000..95088bb --- /dev/null +++ b/SOURCES/0062-xt-pass-octx-to-translate-function.patch @@ -0,0 +1,89 @@ +From 68c1ca177513a94f41ea974de9a48259e8ca5866 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Tue, 6 Nov 2018 16:06:26 +0100 +Subject: [PATCH] xt: pass octx to translate function + +We can't use it when no translation is available as libxtables will +use plain printf(), but when translation is available we can. + +Signed-off-by: Florian Westphal +(cherry picked from commit c15c2869168d71d07aca0221e1b37f0c5da54547) +Signed-off-by: Phil Sutter +--- + include/xt.h | 5 +++-- + src/statement.c | 2 +- + src/xt.c | 6 +++--- + 3 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/include/xt.h b/include/xt.h +index 753511e635080..549eb9fe41531 100644 +--- a/include/xt.h ++++ b/include/xt.h +@@ -6,9 +6,10 @@ struct netlink_parse_ctx; + struct nftnl_expr; + struct rule_pp_ctx; + struct rule; ++struct output_ctx; + + #ifdef HAVE_LIBXTABLES +-void xt_stmt_xlate(const struct stmt *stmt); ++void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx); + void xt_stmt_release(const struct stmt *stmt); + + void netlink_parse_target(struct netlink_parse_ctx *ctx, +@@ -20,7 +21,7 @@ void netlink_parse_match(struct netlink_parse_ctx *ctx, + void stmt_xt_postprocess(struct rule_pp_ctx *rctx, struct stmt *stmt, + struct rule *rule); + #else +-static inline void xt_stmt_xlate(const struct stmt *stmt) {} ++static inline void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) {} + static inline void xt_stmt_release(const struct stmt *stmt) {} + + #include +diff --git a/src/statement.c b/src/statement.c +index 1b889e77cca20..29b73f9fba4ae 100644 +--- a/src/statement.c ++++ b/src/statement.c +@@ -780,7 +780,7 @@ struct stmt *fwd_stmt_alloc(const struct location *loc) + + static void xt_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + { +- xt_stmt_xlate(stmt); ++ xt_stmt_xlate(stmt, octx); + } + + static void xt_stmt_destroy(struct stmt *stmt) +diff --git a/src/xt.c b/src/xt.c +index 298a94d51e8a0..9b7d4c29194aa 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -26,7 +26,7 @@ + #include + #include + +-void xt_stmt_xlate(const struct stmt *stmt) ++void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + { + struct xt_xlate *xl = xt_xlate_alloc(10240); + +@@ -40,7 +40,7 @@ void xt_stmt_xlate(const struct stmt *stmt) + }; + + stmt->xt.match->xlate(xl, ¶ms); +- printf("%s", xt_xlate_get(xl)); ++ nft_print(octx, "%s", xt_xlate_get(xl)); + } else if (stmt->xt.match->print) { + printf("#"); + stmt->xt.match->print(&stmt->xt.entry, +@@ -57,7 +57,7 @@ void xt_stmt_xlate(const struct stmt *stmt) + }; + + stmt->xt.target->xlate(xl, ¶ms); +- printf("%s", xt_xlate_get(xl)); ++ nft_print(octx, "%s", xt_xlate_get(xl)); + } else if (stmt->xt.target->print) { + printf("#"); + stmt->xt.target->print(NULL, stmt->xt.target->t, 0); +-- +2.21.0 + diff --git a/SOURCES/0063-xt-always-build-with-a-minimal-support-for-xt-match-.patch b/SOURCES/0063-xt-always-build-with-a-minimal-support-for-xt-match-.patch new file mode 100644 index 0000000..c226edd --- /dev/null +++ b/SOURCES/0063-xt-always-build-with-a-minimal-support-for-xt-match-.patch @@ -0,0 +1,163 @@ +From 4a4acdac14e0ec770589534aa4a5ea469a76e2a5 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Tue, 6 Nov 2018 16:06:27 +0100 +Subject: [PATCH] xt: always build with a minimal support for xt match/target + decode + +When building without libxtables, nft would just silently omit any presence +of nft_compat in the output. + +This adds ifdef-ry to at least print name of target/match involved when +libxtables isn't available for decoding. + +Signed-off-by: Florian Westphal +(cherry picked from commit b3c8de9c5aecde38eec964f31120df82b9704c8c) +Signed-off-by: Phil Sutter +--- + include/xt.h | 13 +------------ + src/Makefile.am | 2 +- + src/xt.c | 22 ++++++++++++++++++++++ + 3 files changed, 24 insertions(+), 13 deletions(-) + +diff --git a/include/xt.h b/include/xt.h +index 549eb9fe41531..ab59bb3d45a41 100644 +--- a/include/xt.h ++++ b/include/xt.h +@@ -8,7 +8,6 @@ struct rule_pp_ctx; + struct rule; + struct output_ctx; + +-#ifdef HAVE_LIBXTABLES + void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx); + void xt_stmt_release(const struct stmt *stmt); + +@@ -18,20 +17,10 @@ void netlink_parse_target(struct netlink_parse_ctx *ctx, + void netlink_parse_match(struct netlink_parse_ctx *ctx, + const struct location *loc, + const struct nftnl_expr *nle); ++#ifdef HAVE_LIBXTABLES + void stmt_xt_postprocess(struct rule_pp_ctx *rctx, struct stmt *stmt, + struct rule *rule); + #else +-static inline void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) {} +-static inline void xt_stmt_release(const struct stmt *stmt) {} +- +-#include +- +-static inline void netlink_parse_target(struct netlink_parse_ctx *ctx, +- const struct location *loc, +- const struct nftnl_expr *nle) {} +-static inline void netlink_parse_match(struct netlink_parse_ctx *ctx, +- const struct location *loc, +- const struct nftnl_expr *nle) {} + static inline void stmt_xt_postprocess(struct rule_pp_ctx *rctx, + struct stmt *stmt, struct rule *rule) {} + +diff --git a/src/Makefile.am b/src/Makefile.am +index a4ad8cb31236b..495511803b686 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -78,8 +78,8 @@ libminigmp_la_CFLAGS = ${AM_CFLAGS} -Wno-sign-compare + libnftables_la_LIBADD += libminigmp.la + endif + +-if BUILD_XTABLES + libnftables_la_SOURCES += xt.c ++if BUILD_XTABLES + libnftables_la_LIBADD += ${XTABLES_LIBS} + endif + +diff --git a/src/xt.c b/src/xt.c +index 9b7d4c29194aa..c35c84edca0e6 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -28,6 +28,7 @@ + + void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + { ++#ifdef HAVE_LIBXTABLES + struct xt_xlate *xl = xt_xlate_alloc(10240); + + switch (stmt->xt.type) { +@@ -68,6 +69,9 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + } + + xt_xlate_free(xl); ++#else ++ nft_print(octx, "# xt_%s", stmt->xt.name); ++#endif + } + + void xt_stmt_release(const struct stmt *stmt) +@@ -95,6 +99,7 @@ void xt_stmt_release(const struct stmt *stmt) + xfree(stmt->xt.name); + } + ++#ifdef HAVE_LIBXTABLES + static void *xt_entry_alloc(struct xt_stmt *xt, uint32_t af) + { + union nft_entry { +@@ -180,6 +185,7 @@ static struct xtables_match *xt_match_clone(struct xtables_match *m) + memcpy(clone, m, sizeof(struct xtables_match)); + return clone; + } ++#endif + + /* + * Delinearization +@@ -191,6 +197,7 @@ void netlink_parse_match(struct netlink_parse_ctx *ctx, + { + struct stmt *stmt; + const char *name; ++#ifdef HAVE_LIBXTABLES + struct xtables_match *mt; + const char *mtinfo; + struct xt_entry_match *m; +@@ -218,7 +225,13 @@ void netlink_parse_match(struct netlink_parse_ctx *ctx, + stmt->xt.type = NFT_XT_MATCH; + stmt->xt.match = xt_match_clone(mt); + stmt->xt.match->m = m; ++#else ++ name = nftnl_expr_get_str(nle, NFTNL_EXPR_MT_NAME); + ++ stmt = xt_stmt_alloc(loc); ++ stmt->xt.name = strdup(name); ++ stmt->xt.type = NFT_XT_MATCH; ++#endif + list_add_tail(&stmt->list, &ctx->rule->stmts); + } + +@@ -228,6 +241,7 @@ void netlink_parse_target(struct netlink_parse_ctx *ctx, + { + struct stmt *stmt; + const char *name; ++#ifdef HAVE_LIBXTABLES + struct xtables_target *tg; + const void *tginfo; + struct xt_entry_target *t; +@@ -256,10 +270,17 @@ void netlink_parse_target(struct netlink_parse_ctx *ctx, + stmt->xt.type = NFT_XT_TARGET; + stmt->xt.target = xt_target_clone(tg); + stmt->xt.target->t = t; ++#else ++ name = nftnl_expr_get_str(nle, NFTNL_EXPR_TG_NAME); + ++ stmt = xt_stmt_alloc(loc); ++ stmt->xt.name = strdup(name); ++ stmt->xt.type = NFT_XT_TARGET; ++#endif + list_add_tail(&stmt->list, &ctx->rule->stmts); + } + ++#ifdef HAVE_LIBXTABLES + static bool is_watcher(uint32_t family, struct stmt *stmt) + { + if (family != NFPROTO_BRIDGE || +@@ -371,3 +392,4 @@ void xt_init(void) + /* Default to IPv4, but this changes in runtime */ + xtables_init_all(&xt_nft_globals, NFPROTO_IPV4); + } ++#endif +-- +2.21.0 + diff --git a/SOURCES/0064-src-fix-double-free-on-xt-stmt-destruction.patch b/SOURCES/0064-src-fix-double-free-on-xt-stmt-destruction.patch new file mode 100644 index 0000000..c21de02 --- /dev/null +++ b/SOURCES/0064-src-fix-double-free-on-xt-stmt-destruction.patch @@ -0,0 +1,68 @@ +From b8d39d718360e1b46be846dbedd94a6b099a9e31 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Tue, 23 Apr 2019 13:18:05 +0200 +Subject: [PATCH] src: fix double free on xt stmt destruction + +'nft monitor' dies with: +*** Error in `/sbin/nft': double free or corruption (fasttop): 0x000055f8ba57b750 *** + +... when the iptables-nft test suite is running in parallel, because +xfree(stmt->xt.name) gets called twice. + +Fixes: 4ac11b890fe870 ("src: missing destroy function in statement definitions") +Signed-off-by: Florian Westphal +Acked-by: Pablo Neira Ayuso +(cherry picked from commit 99afd62d48f4c510bdb4076eb9d811c001ad1cac) +Signed-off-by: Phil Sutter +--- + include/xt.h | 2 +- + src/statement.c | 6 ------ + src/xt.c | 2 +- + 3 files changed, 2 insertions(+), 8 deletions(-) + +diff --git a/include/xt.h b/include/xt.h +index ab59bb3d45a41..9fc515084d597 100644 +--- a/include/xt.h ++++ b/include/xt.h +@@ -9,7 +9,7 @@ struct rule; + struct output_ctx; + + void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx); +-void xt_stmt_release(const struct stmt *stmt); ++void xt_stmt_destroy(struct stmt *stmt); + + void netlink_parse_target(struct netlink_parse_ctx *ctx, + const struct location *loc, +diff --git a/src/statement.c b/src/statement.c +index 29b73f9fba4ae..c261540b92ebd 100644 +--- a/src/statement.c ++++ b/src/statement.c +@@ -783,12 +783,6 @@ static void xt_stmt_print(const struct stmt *stmt, struct output_ctx *octx) + xt_stmt_xlate(stmt, octx); + } + +-static void xt_stmt_destroy(struct stmt *stmt) +-{ +- xfree(stmt->xt.name); +- xt_stmt_release(stmt); +-} +- + static const struct stmt_ops xt_stmt_ops = { + .type = STMT_XT, + .name = "xt", +diff --git a/src/xt.c b/src/xt.c +index c35c84edca0e6..ef371720fbcfa 100644 +--- a/src/xt.c ++++ b/src/xt.c +@@ -74,7 +74,7 @@ void xt_stmt_xlate(const struct stmt *stmt, struct output_ctx *octx) + #endif + } + +-void xt_stmt_release(const struct stmt *stmt) ++void xt_stmt_destroy(struct stmt *stmt) + { + switch (stmt->xt.type) { + case NFT_XT_MATCH: +-- +2.21.0 + diff --git a/SOURCES/0065-tests-shell-Add-testcase-for-cache-update-problems.patch b/SOURCES/0065-tests-shell-Add-testcase-for-cache-update-problems.patch new file mode 100644 index 0000000..b4bfab1 --- /dev/null +++ b/SOURCES/0065-tests-shell-Add-testcase-for-cache-update-problems.patch @@ -0,0 +1,56 @@ +From 802c96c0b2061dbab20694184bebbeba5eda4a03 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 26 Oct 2018 11:42:05 +0200 +Subject: [PATCH] tests/shell: Add testcase for cache update problems + +The first test in there shows how the current cache update strategy +causes trouble. The second test shows that proposed "locking" of cache +when local entries are added is flawed, too. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 21d678639b28b99c301262c163128fdf67397ca6) +Signed-off-by: Phil Sutter +--- + .../shell/testcases/cache/0003_cache_update_0 | 29 +++++++++++++++++++ + 1 file changed, 29 insertions(+) + create mode 100755 tests/shell/testcases/cache/0003_cache_update_0 + +diff --git a/tests/shell/testcases/cache/0003_cache_update_0 b/tests/shell/testcases/cache/0003_cache_update_0 +new file mode 100755 +index 0000000000000..deb45db2c43be +--- /dev/null ++++ b/tests/shell/testcases/cache/0003_cache_update_0 +@@ -0,0 +1,29 @@ ++#!/bin/bash ++ ++set -e ++ ++# Expose how naive cache update logic (i.e., drop cache and repopulate from ++# kernel ruleset) may mess things up. The following input does: ++# ++# list ruleset -> populate the cache, cache->genid is non-zero ++# add table ip t -> make kernel's genid increment (cache->genid remains ++# unchanged) ++# add table ip t2; -> first command of batch, new table t2 is added to the cache ++# add chain ip t2 c -> second command of batch, triggers cache_update() which ++# removes table t2 from it ++ ++$NFT -i >/dev/null < cache would be locked without previous update ++# add chain ip t c -> table t is not found due to no cache update happening ++ ++$NFT -i >/dev/null < +Date: Wed, 22 May 2019 21:44:04 +0200 +Subject: [PATCH] src: update cache if cmd is more specific + +If we've done a partial fetch of the cache and the genid is the same the +cache update will be skipped without fetching the needed items. This +change flushes the cache if the new request is more specific than the +current cache - forcing a cache update which includes the needed items. + +Introduces a simple scoring system which reflects how +cache_init_objects() looks at the current command to decide if it is +finished already or not. Then use that in cache_needs_more(): If current +command's score is higher than old command's, cache needs an update. + +Fixes: 816d8c7659c1 ("Support 'add/insert rule index '") +Signed-off-by: Eric Garver +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit eeda228c2d1719f5b6276b40ad14a5b3c3e88536) + +Conflicts: + src/rule.c +-> Context change due to missing commit 0562beb6544d3 + ("src: get rid of netlink_genid_get()"). + +Signed-off-by: Phil Sutter +--- + include/nftables.h | 1 + + src/rule.c | 20 +++++++++++++++++++ + .../shell/testcases/cache/0003_cache_update_0 | 14 +++++++++++++ + 3 files changed, 35 insertions(+) + +diff --git a/include/nftables.h b/include/nftables.h +index 5e209b417d5a5..e9425d1fc8fb3 100644 +--- a/include/nftables.h ++++ b/include/nftables.h +@@ -36,6 +36,7 @@ struct nft_cache { + uint16_t genid; + struct list_head list; + uint32_t seqnum; ++ uint32_t cmd; + }; + + struct mnl_socket; +diff --git a/src/rule.c b/src/rule.c +index 850b00cfc9874..a03abe1bf0c47 100644 +--- a/src/rule.c ++++ b/src/rule.c +@@ -151,6 +151,23 @@ static int cache_init(struct netlink_ctx *ctx, enum cmd_ops cmd) + return 0; + } + ++/* Return a "score" of how complete local cache will be if ++ * cache_init_objects() ran for given cmd. Higher value ++ * means more complete. */ ++static int cache_completeness(enum cmd_ops cmd) ++{ ++ if (cmd == CMD_LIST) ++ return 3; ++ if (cmd != CMD_RESET) ++ return 2; ++ return 1; ++} ++ ++static bool cache_needs_more(enum cmd_ops old_cmd, enum cmd_ops cmd) ++{ ++ return cache_completeness(old_cmd) < cache_completeness(cmd); ++} ++ + int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs) + { + uint16_t genid; +@@ -166,6 +183,8 @@ int cache_update(struct nft_ctx *nft, enum cmd_ops cmd, struct list_head *msgs) + replay: + ctx.seqnum = cache->seqnum++; + genid = netlink_genid_get(&ctx); ++ if (cache->genid && cache_needs_more(cache->cmd, cmd)) ++ cache_release(cache); + if (genid && genid == cache->genid) + return 0; + if (cache->genid) +@@ -181,6 +200,7 @@ replay: + return -1; + } + cache->genid = genid; ++ cache->cmd = cmd; + return 0; + } + +diff --git a/tests/shell/testcases/cache/0003_cache_update_0 b/tests/shell/testcases/cache/0003_cache_update_0 +index deb45db2c43be..fa9b5df380a41 100755 +--- a/tests/shell/testcases/cache/0003_cache_update_0 ++++ b/tests/shell/testcases/cache/0003_cache_update_0 +@@ -27,3 +27,17 @@ EOF + $NFT -i >/dev/null < rule to reference in next step ++# add rule ip t4 c index 0 drop -> index 0 is not found due to rule cache not ++# being updated ++$NFT -i >/dev/null </dev/null < +Date: Tue, 13 Aug 2019 22:12:44 +0200 +Subject: [PATCH] src: fix jumps on bigendian arches + +table bla { + chain foo { } + chain bar { jump foo } + } +} + +Fails to restore on big-endian platforms: +jump.nft:5:2-9: Error: Could not process rule: No such file or directory + jump foo + +nft passes a 0-length name to the kernel. + +This is because when we export the value (the string), we provide +the size of the destination buffer. + +In earlier versions, the parser allocated the name with the same +fixed size and all was fine. + +After the fix, the export places the name in the wrong location +in the destination buffer. + +This makes tests/shell/testcases/chains/0001jumps_0 work on s390x. + +v2: convert one error check to a BUG(), it should not happen unless + kernel abi is broken. + +Fixes: 142350f154c78 ("src: invalid read when importing chain name") +Signed-off-by: Florian Westphal +Acked-by: Pablo Neira Ayuso +(cherry picked from commit fb6d826afb1fa346bdf61c43cd6f7551caee27ba) + +Conflicts: + src/datatype.c +-> Context change due to missing commit 72931553828af + ("src: expr: add expression etype") + +Signed-off-by: Phil Sutter +--- + src/datatype.c | 27 ++++++++++++++++++--------- + src/netlink.c | 16 +++++++++++++--- + 2 files changed, 31 insertions(+), 12 deletions(-) + +diff --git a/src/datatype.c b/src/datatype.c +index 5791a6a41599e..7bea6062de9c4 100644 +--- a/src/datatype.c ++++ b/src/datatype.c +@@ -251,10 +251,25 @@ const struct datatype invalid_type = { + .print = invalid_type_print, + }; + +-static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) ++static void verdict_jump_chain_print(const char *what, const struct expr *e, ++ struct output_ctx *octx) + { + char chain[NFT_CHAIN_MAXNAMELEN]; ++ unsigned int len; ++ ++ memset(chain, 0, sizeof(chain)); ++ ++ len = e->len / BITS_PER_BYTE; ++ if (len >= sizeof(chain)) ++ BUG("verdict expression length %u is too large (%lu bits max)", ++ e->len, (unsigned long)sizeof(chain) * BITS_PER_BYTE); + ++ mpz_export_data(chain, e->value, BYTEORDER_HOST_ENDIAN, len); ++ nft_print(octx, "%s %s", what, chain); ++} ++ ++static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) ++{ + switch (expr->verdict) { + case NFT_CONTINUE: + nft_print(octx, "continue"); +@@ -264,10 +279,7 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) + break; + case NFT_JUMP: + if (expr->chain->ops->type == EXPR_VALUE) { +- mpz_export_data(chain, expr->chain->value, +- BYTEORDER_HOST_ENDIAN, +- NFT_CHAIN_MAXNAMELEN); +- nft_print(octx, "jump %s", chain); ++ verdict_jump_chain_print("jump", expr->chain, octx); + } else { + nft_print(octx, "jump "); + expr_print(expr->chain, octx); +@@ -275,10 +287,7 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx) + break; + case NFT_GOTO: + if (expr->chain->ops->type == EXPR_VALUE) { +- mpz_export_data(chain, expr->chain->value, +- BYTEORDER_HOST_ENDIAN, +- NFT_CHAIN_MAXNAMELEN); +- nft_print(octx, "goto %s", chain); ++ verdict_jump_chain_print("goto", expr->chain, octx); + } else { + nft_print(octx, "goto "); + expr_print(expr->chain, octx); +diff --git a/src/netlink.c b/src/netlink.c +index fc310fd293d64..4ad527a02e871 100644 +--- a/src/netlink.c ++++ b/src/netlink.c +@@ -392,17 +392,27 @@ static void netlink_gen_verdict(const struct expr *expr, + struct nft_data_linearize *data) + { + char chain[NFT_CHAIN_MAXNAMELEN]; ++ unsigned int len; + + data->verdict = expr->verdict; + + switch (expr->verdict) { + case NFT_JUMP: + case NFT_GOTO: ++ len = expr->chain->len / BITS_PER_BYTE; ++ ++ if (!len) ++ BUG("chain length is 0"); ++ ++ if (len > sizeof(chain)) ++ BUG("chain is too large (%u, %u max)", ++ len, (unsigned int)sizeof(chain)); ++ ++ memset(chain, 0, sizeof(chain)); ++ + mpz_export_data(chain, expr->chain->value, +- BYTEORDER_HOST_ENDIAN, +- NFT_CHAIN_MAXNAMELEN); ++ BYTEORDER_HOST_ENDIAN, len); + snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain); +- data->chain[NFT_CHAIN_MAXNAMELEN-1] = '\0'; + break; + } + } +-- +2.22.0 + diff --git a/SOURCES/0068-src-json-fix-constant-parsing-on-bigendian.patch b/SOURCES/0068-src-json-fix-constant-parsing-on-bigendian.patch new file mode 100644 index 0000000..45cb829 --- /dev/null +++ b/SOURCES/0068-src-json-fix-constant-parsing-on-bigendian.patch @@ -0,0 +1,36 @@ +From 582df543fab12f6c9032ddf6c789a4e0a7242358 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Wed, 14 Aug 2019 13:45:19 +0200 +Subject: [PATCH] src: json: fix constant parsing on bigendian + +json restore is broken on big-endian because we errounously +passed uint8_t with 64 bit size indicator. + +On bigendian, this causes all values to get shifted by 56 bit, +this will then cause the eval step to bail because all values +are outside of the 8bit 0-255 protocol range. + +Signed-off-by: Florian Westphal +Acked-by: Pablo Neira Ayuso +(cherry picked from commit 452e7653334bd2808441fe40235307f1f3dd23c4) +Signed-off-by: Phil Sutter +--- + src/parser_json.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/parser_json.c b/src/parser_json.c +index 7e4da4838e40b..231f377c4f2da 100644 +--- a/src/parser_json.c ++++ b/src/parser_json.c +@@ -295,7 +295,7 @@ static struct expr *json_parse_constant(struct json_ctx *ctx, const char *name) + return constant_expr_alloc(int_loc, + constant_tbl[i].dtype, + BYTEORDER_HOST_ENDIAN, +- 8 * BITS_PER_BYTE, ++ BITS_PER_BYTE, + &constant_tbl[i].data); + } + json_error(ctx, "Unknown constant '%s'.", name); +-- +2.22.0 + diff --git a/SPECS/nftables.spec b/SPECS/nftables.spec index da9e66a..8525f0a 100644 --- a/SPECS/nftables.spec +++ b/SPECS/nftables.spec @@ -1,6 +1,6 @@ Name: nftables Version: 0.9.0 -Release: 8%{?dist} +Release: 14%{?dist} # Upstream released a 0.100 version, then 0.4. Need Epoch to get back on track. Epoch: 1 Summary: Netfilter Tables userspace utillites @@ -42,13 +42,49 @@ Patch28: 0028-json-Work-around-segfault-when-encountering-xt-stmt.patch Patch29: 0029-nft.8-Document-log-level-audit.patch Patch30: 0030-nft.8-Clarify-index-option-of-add-rule-command.patch Patch31: 0031-src-Reject-export-vm-json-command.patch - - -#BuildRequires: autogen -#BuildRequires: autoconf -#BuildRequires: automake -#BuildRequires: libtool -BuildRequires: gcc +Patch32: 0032-datatype-add-stolen-verdict.patch +Patch33: 0033-libnftables-Fix-exit_cookie.patch +Patch34: 0034-scanner-Do-not-convert-tabs-into-spaces.patch +Patch35: 0035-netlink_delinearize-Refactor-meta_may_dependency_kil.patch +Patch36: 0036-evaluate-skip-evaluation-of-datatype-concatenations.patch +Patch37: 0037-tests-shell-add-tests-for-listing-objects.patch +Patch38: 0038-rule-fix-object-listing-when-no-table-is-given.patch +Patch39: 0039-proto-fix-icmp-icmpv6-code-datatype.patch +Patch40: 0040-evaluate-throw-distinct-error-if-map-exists-but-cont.patch +Patch41: 0041-parser-bail-out-on-incorrect-burst-unit.patch +Patch42: 0042-src-fix-netdev-family-device-name-parsing.patch +Patch43: 0043-libnftables-Print-errors-before-freeing-commands.patch +Patch44: 0044-segtree-fix-crash-when-debug-mode-is-active.patch +Patch45: 0045-parser_bison-no-need-for-statement-separator-for-ct-.patch +Patch46: 0046-ct-use-nft_print-instead-of-printf.patch +Patch47: 0047-parser_bison-type_identifier-string-memleak.patch +Patch48: 0048-src-missing-destroy-function-in-statement-definition.patch +Patch49: 0049-tests-shell-validate-too-deep-jumpstack-from-basecha.patch +Patch50: 0050-netlink-remove-markup-json-parsing-code.patch +Patch51: 0051-rule-limit-don-t-print-default-burst-value.patch +Patch52: 0052-JSON-Review-verdict-statement-and-expression.patch +Patch53: 0053-parser_json-Duplicate-chain-name-when-parsing-jump-v.patch +Patch54: 0054-src-Introduce-chain_expr-in-jump-and-goto-statements.patch +Patch55: 0055-src-Allow-goto-and-jump-to-a-variable.patch +Patch56: 0056-parser_json-Fix-and-simplify-verdict-expression-pars.patch +Patch57: 0057-src-invalid-read-when-importing-chain-name.patch +Patch58: 0058-expression-use-expr_clone-from-verdict_expr_clone.patch +Patch59: 0059-parser_bison-free-chain-name-after-creating-constant.patch +Patch60: 0060-doc-update-nft-list-plural-form-parameters.patch +Patch61: 0061-doc-Add-minimal-description-of-v-map-statements.patch +Patch62: 0062-xt-pass-octx-to-translate-function.patch +Patch63: 0063-xt-always-build-with-a-minimal-support-for-xt-match-.patch +Patch64: 0064-src-fix-double-free-on-xt-stmt-destruction.patch +Patch65: 0065-tests-shell-Add-testcase-for-cache-update-problems.patch +Patch66: 0066-src-update-cache-if-cmd-is-more-specific.patch +Patch67: 0067-src-fix-jumps-on-bigendian-arches.patch +Patch68: 0068-src-json-fix-constant-parsing-on-bigendian.patch + +BuildRequires: autogen +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool +BuildRequires: gcc BuildRequires: flex BuildRequires: bison BuildRequires: libmnl-devel @@ -76,7 +112,8 @@ Development tools and static libraries and header files for the libnftables libr %autosetup -p1 %build -#./autogen.sh +autoreconf -fi +rm -Rf autom4te*.cache config.h.in~ %configure --disable-silent-rules --with-json --with-xtables make %{?_smp_mflags} @@ -94,8 +131,11 @@ cp -a %{SOURCE1} $RPM_BUILD_ROOT/%{_unitdir}/ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig cp -a %{SOURCE2} $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/ +chmod 600 $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/nftables.conf -mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/nftables +cp files/examples/netdev-ingress.nft $RPM_BUILD_ROOT/%{_sysconfdir}/nftables +chmod 750 $RPM_BUILD_ROOT/%{_sysconfdir}/nftables +chmod 600 $RPM_BUILD_ROOT/%{_sysconfdir}/nftables/*.nft %post %systemd_post nftables.service @@ -127,6 +167,30 @@ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/nftables %{_includedir}/nftables/libnftables.h %changelog +* Mon Aug 12 2019 Phil Sutter - 1:0.9.0-14 +- src: fix jumps on bigendian arches +- src: json: fix constant parsing on bigendian + +* Thu Aug 08 2019 Phil Sutter - 1:0.9.0-13 +- Fix for adding a rule with index and set reference + +* Wed Jul 31 2019 Phil Sutter - 1:0.9.0-12 +- Fix permissions of /etc/nftables directory + +* Wed Jun 26 2019 Phil Sutter - 1:0.9.0-11 +- Fix segfault with xtables support + +* Wed Jun 26 2019 Phil Sutter - 1:0.9.0-10 +- Fix typo in spec file + +* Wed Jun 26 2019 Phil Sutter - 1:0.9.0-9 +- Allow variables in jump statement +- Make example configs readable only by root +- Document nft list parameters +- Document vmap statement +- Install netdev-ingress.nft sample config in the right spot +- Backport upstream fixes since last release + * Fri Mar 01 2019 Phil Sutter - 1:0.9.0-8 - Add missing patch to spec file