]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
xtables: Align return codes with legacy iptables
authorPhil Sutter <phil@nwl.cc>
Fri, 31 Aug 2018 10:29:57 +0000 (12:29 +0200)
committerFlorian Westphal <fw@strlen.de>
Sat, 1 Sep 2018 08:12:40 +0000 (10:12 +0200)
Make sure return codes match legacy ones at least for a few selected
commands typically used to check ruleset state.

Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Florian Westphal <fw@strlen.de>
iptables/nft.c
iptables/nft.h
iptables/tests/shell/testcases/ip6tables/0004-return-codes_0 [new file with mode: 0755]
iptables/tests/shell/testcases/iptables/0004-return-codes_0 [new file with mode: 0755]
iptables/xtables.c

index b2165069c6d89660ec2a6d1cdfbab2a06f108dfb..7123060b34ef531dcdd7825aec149f6e9390a5f7 100644 (file)
@@ -1725,6 +1725,21 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain)
        return nft_chain_list_find(list, table, chain);
 }
 
+bool nft_chain_exists(struct nft_handle *h,
+                     const char *table, const char *chain)
+{
+       struct builtin_table *t = nft_table_builtin_find(h, table);
+
+       /* xtables does not support custom tables */
+       if (!t)
+               return false;
+
+       if (nft_chain_builtin_find(t, chain))
+               return true;
+
+       return !!nft_chain_find(h, table, chain);
+}
+
 int nft_chain_user_rename(struct nft_handle *h,const char *chain,
                          const char *table, const char *newname)
 {
index eb14e908ab9249def1590cb761cef8cab12904e3..7419ec21a63a808137be379b1258b03b57499dec 100644 (file)
@@ -86,6 +86,7 @@ int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list,
 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, bool verbose);
 struct builtin_chain *nft_chain_builtin_find(struct builtin_table *t, const char *chain);
+bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain);
 
 /*
  * Operations with rule-set.
diff --git a/iptables/tests/shell/testcases/ip6tables/0004-return-codes_0 b/iptables/tests/shell/testcases/ip6tables/0004-return-codes_0
new file mode 100755 (executable)
index 0000000..f023b79
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# make sure error return codes are as expected useful cases
+# (e.g. commands to check ruleset state)
+
+global_rc=0
+
+cmd() { # (rc, cmd, [args ...])
+       rc_exp=$1; shift
+
+       $XT_MULTI "$@"
+       rc=$?
+
+       [ $rc -eq $rc_exp ] || {
+               echo "---> expected $rc_exp, got $rc for command '$@'"
+               global_rc=1
+       }
+}
+
+# test chain creation
+cmd 0 ip6tables -N foo
+cmd 1 ip6tables -N foo
+# iptables-nft allows this - bug or feature?
+#cmd 2 ip6tables -N "invalid name"
+
+# test rule adding
+cmd 0 ip6tables -A INPUT -j ACCEPT
+cmd 1 ip6tables -A noexist -j ACCEPT
+
+# test rule checking
+cmd 0 ip6tables -C INPUT -j ACCEPT
+cmd 1 ip6tables -C FORWARD -j ACCEPT
+cmd 1 ip6tables -C nonexist -j ACCEPT
+cmd 2 ip6tables -C INPUT -j foobar
+cmd 2 ip6tables -C INPUT -m foobar -j ACCEPT
+cmd 3 ip6tables -t foobar -C INPUT -j ACCEPT
+
+exit $global_rc
diff --git a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
new file mode 100755 (executable)
index 0000000..34dffee
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# make sure error return codes are as expected useful cases
+# (e.g. commands to check ruleset state)
+
+global_rc=0
+
+cmd() { # (rc, cmd, [args ...])
+       rc_exp=$1; shift
+
+       $XT_MULTI "$@"
+       rc=$?
+
+       [ $rc -eq $rc_exp ] || {
+               echo "---> expected $rc_exp, got $rc for command '$@'"
+               global_rc=1
+       }
+}
+
+# test chain creation
+cmd 0 iptables -N foo
+cmd 1 iptables -N foo
+# iptables-nft allows this - bug or feature?
+#cmd 2 iptables -N "invalid name"
+
+# test rule adding
+cmd 0 iptables -A INPUT -j ACCEPT
+cmd 1 iptables -A noexist -j ACCEPT
+
+# test rule checking
+cmd 0 iptables -C INPUT -j ACCEPT
+cmd 1 iptables -C FORWARD -j ACCEPT
+cmd 1 iptables -C nonexist -j ACCEPT
+cmd 2 iptables -C INPUT -j foobar
+cmd 2 iptables -C INPUT -m foobar -j ACCEPT
+cmd 3 iptables -t foobar -C INPUT -j ACCEPT
+
+exit $global_rc
index 72f6596251da069ff94f9bb5fe013d3b9e41f1a7..313b985bbaa85739998c6fca5824484758f428d8 100644 (file)
@@ -976,6 +976,10 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
                        if (cs->invert)
                                xtables_error(PARAMETER_PROBLEM,
                                           "unexpected ! flag before --table");
+                       if (!nft_table_builtin_find(h, optarg))
+                               xtables_error(VERSION_PROBLEM,
+                                             "table '%s' does not exist",
+                                             optarg);
                        p->table = optarg;
                        break;
 
@@ -1156,12 +1160,18 @@ void do_parse(struct nft_handle *h, int argc, char *argv[],
                                           p->chain);
                }
 
-               /*
-                * Contrary to what iptables does, we assume that any jumpto
-                * is a custom chain jumps (if no target is found). Later on,
-                * nf_table will spot the error if the chain does not exists.
-                */
+               if (p->chain && !nft_chain_exists(h, p->table, p->chain))
+                       xtables_error(OTHER_PROBLEM,
+                                     "Chain '%s' does not exist", cs->jumpto);
+
+               if (!cs->target && strlen(cs->jumpto) > 0 &&
+                   !nft_chain_exists(h, p->table, cs->jumpto))
+                       xtables_error(PARAMETER_PROBLEM,
+                                     "Chain '%s' does not exist", cs->jumpto);
        }
+       if (p->command == CMD_NEW_CHAIN &&
+           nft_chain_exists(h, p->table, p->chain))
+               xtables_error(OTHER_PROBLEM, "Chain already exists");
 }
 
 int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,