From 2ce9f65a374bad212899bc584d3e5f4698df6fc6 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sat, 4 Aug 2018 13:10:19 +0200 Subject: xtables: Match verbose ip{,6}tables output with legacy Legacy ip{,6}tables prints feedback for various commands if in verbose mode, make sure nft variants do the same. There is one difference, namely when checking a rule (-C command): Legacy ip{,6}tables print the rule in any case, nft variants don't in case the rule wasn't found. Changing this though would require to populate the nftnl_rule object just for printing, which is probably not feasible. Signed-off-by: Phil Sutter Signed-off-by: Florian Westphal --- iptables/nft.c | 39 +++++++++++++---- iptables/nft.h | 6 +-- .../testcases/ip6tables/0002-verbose-output_0 | 51 ++++++++++++++++++++++ .../shell/testcases/iptables/0002-verbose-output_0 | 51 ++++++++++++++++++++++ iptables/xtables-arp.c | 11 +++-- iptables/xtables-eb.c | 7 +-- iptables/xtables.c | 17 +++++--- 7 files changed, 157 insertions(+), 25 deletions(-) create mode 100755 iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0 create mode 100755 iptables/tests/shell/testcases/iptables/0002-verbose-output_0 (limited to 'iptables') diff --git a/iptables/nft.c b/iptables/nft.c index 154ae19c..ea58495b 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -1176,6 +1176,9 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, if (batch_rule_add(h, type, r) < 0) nftnl_rule_free(r); + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); + if (!nft_rule_list_get(h)) return 0; @@ -1474,7 +1477,8 @@ int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list, return 1; } -int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table) +int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + bool verbose) { int ret = 0; struct nftnl_chain_list *list; @@ -1511,6 +1515,9 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table) if (chain != NULL && strcmp(chain, chain_name) != 0) goto next; + if (verbose) + fprintf(stdout, "Flushing chain `%s'\n", chain_name); + __nft_rule_flush(h, table_name, chain_name); if (chain != NULL) @@ -1558,7 +1565,8 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl #define NLM_F_NONREC 0x100 /* Do not delete recursively */ #endif -int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table) +int nft_chain_user_del(struct nft_handle *h, const char *chain, + const char *table, bool verbose) { struct nftnl_chain_list *list; struct nftnl_chain_list_iter *iter; @@ -1593,6 +1601,9 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *tabl if (chain != NULL && strcmp(chain, chain_name) != 0) goto next; + if (verbose) + fprintf(stdout, "Deleting chain `%s'\n", chain); + ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); if (ret < 0) @@ -1958,7 +1969,7 @@ int nft_rule_check(struct nft_handle *h, const char *chain, const char *table, void *data, bool verbose) { struct nftnl_rule_list *list; - int ret; + struct nftnl_rule *r; nft_fn = nft_rule_check; @@ -1966,11 +1977,15 @@ int nft_rule_check(struct nft_handle *h, const char *chain, if (list == NULL) return 0; - ret = nft_rule_find(h, list, chain, table, data, -1) ? 1 : 0; - if (ret == 0) + r = nft_rule_find(h, list, chain, table, data, -1); + if (r == NULL) { errno = ENOENT; + return 0; + } + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); - return ret; + return 1; } int nft_rule_delete(struct nft_handle *h, const char *chain, @@ -1991,6 +2006,8 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, ret =__nft_rule_del(h, list, r); if (ret < 0) errno = ENOMEM; + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); } else errno = ENOENT; @@ -2016,6 +2033,9 @@ nft_rule_add(struct nft_handle *h, const char *chain, return NULL; } + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); + return r; } @@ -2894,8 +2914,8 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename, return h->config_done; } -int nft_chain_zero_counters(struct nft_handle *h, const char *chain, - const char *table) +int nft_chain_zero_counters(struct nft_handle *h, const char *chain, + const char *table, bool verbose) { struct nftnl_chain_list *list; struct nftnl_chain_list_iter *iter; @@ -2923,6 +2943,9 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, if (chain != NULL && strcmp(chain, chain_name) != 0) goto next; + if (verbose) + fprintf(stdout, "Zeroing chain `%s'\n", chain_name); + nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0); nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0); diff --git a/iptables/nft.h b/iptables/nft.h index 6f58de25..5febb9f9 100644 --- a/iptables/nft.h +++ b/iptables/nft.h @@ -79,11 +79,11 @@ struct nftnl_chain_list *nft_chain_dump(struct nft_handle *h); struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const char *table, const char *chain); int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table); int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); -int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table); +int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list, const char *chain, const char *table); int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname); -int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table); +int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose); /* * Operations with rule-set. @@ -99,7 +99,7 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, const char *table, int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, int rulenum, unsigned int format); int nft_rule_list_save(struct nft_handle *h, const char *chain, const char *table, int rulenum, int counters); int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format); -int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table); +int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, bool verbose); int nft_rule_zero_counters(struct nft_handle *h, const char *chain, const char *table, int rulenum); /* diff --git a/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0 b/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0 new file mode 100755 index 00000000..7b0e6468 --- /dev/null +++ b/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0 @@ -0,0 +1,51 @@ +#!/bin/bash + +set -e +#set -x + +# ensure verbose output is identical between legacy and nft tools + +RULE1='-i eth2 -o eth3 -s feed:babe::1 -d feed:babe::2 -j ACCEPT' +VOUT1='ACCEPT all opt in eth2 out eth3 feed:babe::1 -> feed:babe::2' +RULE2='-i eth2 -o eth3 -s feed:babe::4 -d feed:babe::5 -j ACCEPT' +VOUT2='ACCEPT all opt in eth2 out eth3 feed:babe::4 -> feed:babe::5' + +diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI ip6tables -v -A FORWARD $RULE1) +diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI ip6tables -v -I FORWARD 2 $RULE2) + +diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI ip6tables -v -C FORWARD $RULE1) +diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI ip6tables -v -C FORWARD $RULE2) + +EXPECT='Chain INPUT (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination + +Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination + 0 0 ACCEPT all eth2 eth3 feed:babe::1 feed:babe::2 + 0 0 ACCEPT all eth2 eth3 feed:babe::4 feed:babe::5 + +Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -v -n -L) + +diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI ip6tables -v -D FORWARD $RULE1) +diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI ip6tables -v -D FORWARD $RULE2) + +EXPECT="Flushing chain \`INPUT' +Flushing chain \`FORWARD' +Flushing chain \`OUTPUT'" + +diff -u <(echo -e "$EXPECT") <($XT_MULTI ip6tables -v -F) + +EXPECT="Zeroing chain \`INPUT' +Zeroing chain \`FORWARD' +Zeroing chain \`OUTPUT'" + +diff -u <(echo -e "$EXPECT") <($XT_MULTI ip6tables -v -Z) + +diff -u <(echo "Flushing chain \`OUTPUT'") <($XT_MULTI ip6tables -v -F OUTPUT) +diff -u <(echo "Zeroing chain \`OUTPUT'") <($XT_MULTI ip6tables -v -Z OUTPUT) + +$XT_MULTI ip6tables -N foo +diff -u <(echo "Deleting chain \`foo'") <($XT_MULTI ip6tables -v -X foo) diff --git a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 new file mode 100755 index 00000000..2e805953 --- /dev/null +++ b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 @@ -0,0 +1,51 @@ +#!/bin/bash + +set -e +#set -x + +# ensure verbose output is identical between legacy and nft tools + +RULE1='-i eth2 -o eth3 -s 10.0.0.1 -d 10.0.0.2 -j ACCEPT' +VOUT1='ACCEPT all opt -- in eth2 out eth3 10.0.0.1 -> 10.0.0.2' +RULE2='-i eth2 -o eth3 -s 10.0.0.4 -d 10.0.0.5 -j ACCEPT' +VOUT2='ACCEPT all opt -- in eth2 out eth3 10.0.0.4 -> 10.0.0.5' + +diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI iptables -v -A FORWARD $RULE1) +diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI iptables -v -I FORWARD 2 $RULE2) + +diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI iptables -v -C FORWARD $RULE1) +diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI iptables -v -C FORWARD $RULE2) + +EXPECT='Chain INPUT (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination + +Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination + 0 0 ACCEPT all -- eth2 eth3 10.0.0.1 10.0.0.2 + 0 0 ACCEPT all -- eth2 eth3 10.0.0.4 10.0.0.5 + +Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) + pkts bytes target prot opt in out source destination' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -n -L) + +diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI iptables -v -D FORWARD $RULE1) +diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI iptables -v -D FORWARD $RULE2) + +EXPECT="Flushing chain \`INPUT' +Flushing chain \`FORWARD' +Flushing chain \`OUTPUT'" + +diff -u <(echo -e "$EXPECT") <($XT_MULTI iptables -v -F) + +EXPECT="Zeroing chain \`INPUT' +Zeroing chain \`FORWARD' +Zeroing chain \`OUTPUT'" + +diff -u <(echo -e "$EXPECT") <($XT_MULTI iptables -v -Z) + +diff -u <(echo "Flushing chain \`OUTPUT'") <($XT_MULTI iptables -v -F OUTPUT) +diff -u <(echo "Zeroing chain \`OUTPUT'") <($XT_MULTI iptables -v -Z OUTPUT) + +$XT_MULTI iptables -N foo +diff -u <(echo "Deleting chain \`foo'") <($XT_MULTI iptables -v -X foo) diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c index 28f449e8..62282f42 100644 --- a/iptables/xtables-arp.c +++ b/iptables/xtables-arp.c @@ -1421,10 +1421,11 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) options&OPT_LINENUMBERS); break; case CMD_FLUSH: - ret = nft_rule_flush(h, chain, *table); + ret = nft_rule_flush(h, chain, *table, options & OPT_VERBOSE); break; case CMD_ZERO: - ret = nft_chain_zero_counters(h, chain, *table); + ret = nft_chain_zero_counters(h, chain, *table, + options & OPT_VERBOSE); break; case CMD_LIST|CMD_ZERO: ret = list_entries(h, chain, *table, rulenum, @@ -1433,13 +1434,15 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table) /*options&OPT_EXPANDED*/0, options&OPT_LINENUMBERS); if (ret) - ret = nft_chain_zero_counters(h, chain, *table); + ret = nft_chain_zero_counters(h, chain, *table, + options & OPT_VERBOSE); break; case CMD_NEW_CHAIN: ret = nft_chain_user_add(h, chain, *table); break; case CMD_DELETE_CHAIN: - ret = nft_chain_user_del(h, chain, *table); + ret = nft_chain_user_del(h, chain, *table, + options & OPT_VERBOSE); break; case CMD_RENAME_CHAIN: ret = nft_chain_user_rename(h, chain, *table, newname); diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c index b051e9f5..763d1ad9 100644 --- a/iptables/xtables-eb.c +++ b/iptables/xtables-eb.c @@ -856,7 +856,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table) chain = argv[optind]; optind++; } - ret = nft_chain_user_del(h, chain, *table); + ret = nft_chain_user_del(h, chain, *table, 0); break; } @@ -1317,9 +1317,10 @@ check_extension: } if (flags & OPT_ZERO) { selected_chain = zerochain; - ret = nft_chain_zero_counters(h, chain, *table); + ret = nft_chain_zero_counters(h, chain, *table, + flags & OPT_VERBOSE); } else if (command == 'F') { - ret = nft_rule_flush(h, chain, *table); + ret = nft_rule_flush(h, chain, *table, flags & OPT_VERBOSE); } else if (command == 'A') { ret = append_entry(h, chain, *table, &cs, 0, flags&OPT_VERBOSE, true); diff --git a/iptables/xtables.c b/iptables/xtables.c index ca6119b3..64081758 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -1213,10 +1213,12 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, cs.options&OPT_VERBOSE, h, false); break; case CMD_FLUSH: - ret = nft_rule_flush(h, p.chain, p.table); + ret = nft_rule_flush(h, p.chain, p.table, + cs.options & OPT_VERBOSE); break; case CMD_ZERO: - ret = nft_chain_zero_counters(h, p.chain, p.table); + ret = nft_chain_zero_counters(h, p.chain, p.table, + cs.options & OPT_VERBOSE); break; case CMD_ZERO_NUM: ret = nft_rule_zero_counters(h, p.chain, p.table, @@ -1231,8 +1233,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, cs.options & OPT_EXPANDED, cs.options & OPT_LINENUMBERS); if (ret && (p.command & CMD_ZERO)) { - ret = nft_chain_zero_counters(h, p.chain, - p.table); + ret = nft_chain_zero_counters(h, p.chain, p.table, + cs.options & OPT_VERBOSE); } if (ret && (p.command & CMD_ZERO_NUM)) { ret = nft_rule_zero_counters(h, p.chain, p.table, @@ -1246,8 +1248,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, ret = list_rules(h, p.chain, p.table, p.rulenum, cs.options & OPT_VERBOSE); if (ret && (p.command & CMD_ZERO)) { - ret = nft_chain_zero_counters(h, p.chain, - p.table); + ret = nft_chain_zero_counters(h, p.chain, p.table, + cs.options & OPT_VERBOSE); } if (ret && (p.command & CMD_ZERO_NUM)) { ret = nft_rule_zero_counters(h, p.chain, p.table, @@ -1259,7 +1261,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, ret = nft_chain_user_add(h, p.chain, p.table); break; case CMD_DELETE_CHAIN: - ret = nft_chain_user_del(h, p.chain, p.table); + ret = nft_chain_user_del(h, p.chain, p.table, + cs.options & OPT_VERBOSE); break; case CMD_RENAME_CHAIN: ret = nft_chain_user_rename(h, p.chain, p.table, p.newname); -- cgit v1.2.3