summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2018-08-31 12:29:57 +0200
committerFlorian Westphal <fw@strlen.de>2018-09-01 10:12:40 +0200
commitb6a06c1a215f867f7eee4a3f2f40ec14028fe186 (patch)
treea941776217826cb296c2477e403747f8397437a1
parent3bb497c61d743ba811e7f501e54cc5071216e1f5 (diff)
xtables: Align return codes with legacy iptables
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>
-rw-r--r--iptables/nft.c15
-rw-r--r--iptables/nft.h1
-rwxr-xr-xiptables/tests/shell/testcases/ip6tables/0004-return-codes_038
-rwxr-xr-xiptables/tests/shell/testcases/iptables/0004-return-codes_038
-rw-r--r--iptables/xtables.c20
5 files changed, 107 insertions, 5 deletions
diff --git a/iptables/nft.c b/iptables/nft.c
index b2165069..7123060b 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -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)
{
diff --git a/iptables/nft.h b/iptables/nft.h
index eb14e908..7419ec21 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -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
index 00000000..f023b791
--- /dev/null
+++ b/iptables/tests/shell/testcases/ip6tables/0004-return-codes_0
@@ -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
index 00000000..34dffeee
--- /dev/null
+++ b/iptables/tests/shell/testcases/iptables/0004-return-codes_0
@@ -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
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 72f65962..313b985b 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -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,