To be consistent with legacy iptables, calling -S with a non-existing chain should lead to an error message. This is how some scripts find out whether a user-defined chain exists or not. Make sure doing the same for an existing chain does succeed, even if an invalid rule number was given. Signed-off-by: Phil Sutter <phil@xxxxxx> --- iptables/nft.c | 16 ++--- .../testcases/ip6tables/0003-list-rules_0 | 64 +++++++++++++++++++ .../testcases/iptables/0003-list-rules_0 | 16 +++++ iptables/xtables.c | 5 +- 4 files changed, 86 insertions(+), 15 deletions(-) create mode 100755 iptables/tests/shell/testcases/ip6tables/0003-list-rules_0 diff --git a/iptables/nft.c b/iptables/nft.c index ad4f61bbd49ac..54755fcd1c6ac 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -2201,7 +2201,7 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table, struct nftnl_rule_list *list; struct nftnl_rule_list_iter *iter; struct nftnl_rule *r; - int rule_ctr = 0, ret = 0; + int rule_ctr = 0; list = nft_rule_list_get(h); if (list == NULL) @@ -2209,7 +2209,7 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table, iter = nftnl_rule_list_iter_create(list); if (iter == NULL) - goto err; + return 0; r = nftnl_rule_list_iter_next(iter); while (r != NULL) { @@ -2230,21 +2230,15 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table, } cb(r, rule_ctr, format); - if (rulenum > 0 && rule_ctr == rulenum) { - ret = 1; + if (rulenum > 0) break; - } next: r = nftnl_rule_list_iter_next(iter); } nftnl_rule_list_iter_destroy(iter); -err: - if (ret == 0) - errno = ENOENT; - - return ret; + return 1; } static int nft_rule_count(struct nft_handle *h, @@ -2443,7 +2437,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, struct nftnl_chain_list_iter *iter; unsigned int format = 0; struct nftnl_chain *c; - int ret = 1; + int ret = 0; /* If built-in chains don't exist for this table, create them */ if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) { diff --git a/iptables/tests/shell/testcases/ip6tables/0003-list-rules_0 b/iptables/tests/shell/testcases/ip6tables/0003-list-rules_0 new file mode 100755 index 0000000000000..c98bdd6e501aa --- /dev/null +++ b/iptables/tests/shell/testcases/ip6tables/0003-list-rules_0 @@ -0,0 +1,64 @@ +#!/bin/bash + +set -e + +$XT_MULTI ip6tables -N foo +$XT_MULTI ip6tables -A FORWARD -i eth23 -o eth42 -j ACCEPT +$XT_MULTI ip6tables -A FORWARD -i eth42 -o eth23 -g foo +$XT_MULTI ip6tables -t nat -A OUTPUT -o eth123 -m mark --mark 0x42 -j ACCEPT + +EXPECT='-P INPUT ACCEPT +-P FORWARD ACCEPT +-P OUTPUT ACCEPT +-N foo +-A FORWARD -i eth23 -o eth42 -j ACCEPT +-A FORWARD -i eth42 -o eth23 -g foo' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -S) + +EXPECT='-P INPUT ACCEPT -c 0 0 +-P FORWARD ACCEPT -c 0 0 +-P OUTPUT ACCEPT -c 0 0 +-N foo +-A FORWARD -i eth23 -o eth42 -c 0 0 -j ACCEPT +-A FORWARD -i eth42 -o eth23 -c 0 0 -g foo' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -v -S) + +EXPECT='-P FORWARD ACCEPT +-A FORWARD -i eth23 -o eth42 -j ACCEPT +-A FORWARD -i eth42 -o eth23 -g foo' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -S FORWARD) + +EXPECT='-P FORWARD ACCEPT -c 0 0 +-A FORWARD -i eth23 -o eth42 -c 0 0 -j ACCEPT +-A FORWARD -i eth42 -o eth23 -c 0 0 -g foo' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -v -S FORWARD) + +EXPECT='-P OUTPUT ACCEPT +-A OUTPUT -o eth123 -m mark --mark 0x42 -j ACCEPT' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -t nat -S OUTPUT) + +EXPECT='-P OUTPUT ACCEPT -c 0 0 +-A OUTPUT -o eth123 -m mark --mark 0x42 -c 0 0 -j ACCEPT' + +diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ip6tables -v -t nat -S OUTPUT) + +# some of the following commands are supposed to fail +set +e + +$XT_MULTI ip6tables -S nonexistent && { + echo "list-rules in non-existent chain should fail" + exit 1 +} +$XT_MULTI ip6tables -S nonexistent 23 && { + echo "list-rules in non-existent chain with given rule number should fail" + exit 1 +} +$XT_MULTI ip6tables -S FORWARD 234 || { + echo "list-rules in existent chain with invalid rule number should succeed" + exit 1 +} diff --git a/iptables/tests/shell/testcases/iptables/0003-list-rules_0 b/iptables/tests/shell/testcases/iptables/0003-list-rules_0 index 2e87ce5a6aec0..d335d44257a49 100755 --- a/iptables/tests/shell/testcases/iptables/0003-list-rules_0 +++ b/iptables/tests/shell/testcases/iptables/0003-list-rules_0 @@ -46,3 +46,19 @@ EXPECT='-P OUTPUT ACCEPT -c 0 0 -A OUTPUT -o eth123 -m mark --mark 0x42 -c 0 0 -j ACCEPT' diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -t nat -S OUTPUT) + +# some of the following commands are supposed to fail +set +e + +$XT_MULTI iptables -S nonexistent && { + echo "list-rules in non-existent chain should fail" + exit 1 +} +$XT_MULTI iptables -S nonexistent 23 && { + echo "list-rules in non-existent chain with given rule number should fail" + exit 1 +} +$XT_MULTI iptables -S FORWARD 234 || { + echo "list-rules in existent chain with invalid rule number should succeed" + exit 1 +} diff --git a/iptables/xtables.c b/iptables/xtables.c index 64081758a12ba..d9050b45c2c36 100644 --- a/iptables/xtables.c +++ b/iptables/xtables.c @@ -599,10 +599,7 @@ list_rules(struct nft_handle *h, const char *chain, const char *table, if (counters) counters = -1; /* iptables -c format */ - nft_rule_list_save(h, chain, table, rulenum, counters); - - /* iptables does not return error if rule number not found */ - return 1; + return nft_rule_list_save(h, chain, table, rulenum, counters); } static void command_jump(struct iptables_command_state *cs) -- 2.18.0