Commit 9caffe92 authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

New upstream version 1.8.6

parent eb1d7c5f
......@@ -225,7 +225,8 @@ struct nft_xt_restore_cb {
int (*chain_restore)(struct nft_handle *h, const char *chain,
const char *table);
int (*table_flush)(struct nft_handle *h, const char *table);
int (*table_flush)(struct nft_handle *h, const char *table,
bool verbose);
int (*do_command)(struct nft_handle *h, int argc, char *argv[],
char **table, bool restore);
......
This diff is collapsed.
......@@ -8,10 +8,10 @@
#include <libiptc/linux_list.h>
enum nft_table_type {
NFT_TABLE_FILTER = 0,
NFT_TABLE_MANGLE,
NFT_TABLE_RAW,
NFT_TABLE_MANGLE = 0,
NFT_TABLE_SECURITY,
NFT_TABLE_RAW,
NFT_TABLE_FILTER,
NFT_TABLE_NAT,
};
#define NFT_TABLE_MAX (NFT_TABLE_NAT + 1)
......@@ -38,11 +38,10 @@ enum nft_cache_level {
};
struct nft_cache {
struct nftnl_table_list *tables;
struct {
struct nftnl_chain_list *chains;
struct nftnl_set_list *sets;
bool initialized;
bool exists;
} table[NFT_TABLE_MAX];
};
......@@ -68,7 +67,6 @@ enum obj_update_type {
NFT_COMPAT_RULE_SAVE,
NFT_COMPAT_RULE_ZERO,
NFT_COMPAT_BRIDGE_USER_CHAIN_UPDATE,
NFT_COMPAT_TABLE_NEW,
};
struct cache_chain {
......@@ -135,7 +133,6 @@ int nft_for_each_table(struct nft_handle *h, int (*func)(struct nft_handle *h, c
bool nft_table_find(struct nft_handle *h, const char *tablename);
int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list);
int nft_table_flush(struct nft_handle *h, const char *table);
void nft_table_new(struct nft_handle *h, const char *table);
const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table);
/*
......@@ -144,7 +141,7 @@ const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const c
struct nftnl_chain;
int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters);
int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list);
int nft_chain_save(struct nftnl_chain *c, void *data);
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, bool verbose);
int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table);
......
......@@ -4,6 +4,21 @@
TESTDIR="./$(dirname $0)/"
RETURNCODE_SEPARATOR="_"
usage() {
cat <<EOF
Usage: $(basename $0) [-v|--verbose] [-H|--host] [-V|--valgrind]
[[-l|--legacy]|[-n|--nft]] [testscript ...]
-v | --verbose Enable verbose mode (do not drop testscript output).
-H | --host Run tests against installed binaries in \$PATH,
not those built in this source tree.
-V | --valgrind Enable leak checking via valgrind.
-l | --legacy Test legacy variant only. Conflicts with --nft.
-n | --nft Test nft variant only. Conflicts with --legacy.
testscript Run only specific test(s). Implies --verbose.
EOF
}
msg_error() {
echo "E: $1 ..." >&2
exit 1
......@@ -50,6 +65,10 @@ while [ -n "$1" ]; do
VALGRIND=y
shift
;;
-h|--help)
usage
exit 0
;;
*${RETURNCODE_SEPARATOR}+([0-9]))
SINGLE+=" $1"
VERBOSE=y
......
#!/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
cmd 2 ip6tables -I INPUT -j foobar
# 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
#!/bin/bash
set -e
DUMP="*filter
:foo - [0:0]
:bar - [0:0]
-A foo -j ACCEPT
COMMIT
*nat
:natfoo - [0:0]
:natbar - [0:0]
-A natfoo -j ACCEPT
COMMIT
*raw
:rawfoo - [0:0]
COMMIT
*mangle
:manglefoo - [0:0]
COMMIT
*security
:secfoo - [0:0]
COMMIT
"
$XT_MULTI iptables-restore <<< "$DUMP"
$XT_MULTI ip6tables-restore <<< "$DUMP"
EXPECT="Flushing chain \`INPUT'
Flushing chain \`FORWARD'
Flushing chain \`OUTPUT'
Flushing chain \`bar'
Flushing chain \`foo'
Deleting chain \`bar'
Deleting chain \`foo'
Flushing chain \`PREROUTING'
Flushing chain \`INPUT'
Flushing chain \`OUTPUT'
Flushing chain \`POSTROUTING'
Flushing chain \`natbar'
Flushing chain \`natfoo'
Deleting chain \`natbar'
Deleting chain \`natfoo'
Flushing chain \`PREROUTING'
Flushing chain \`OUTPUT'
Flushing chain \`rawfoo'
Deleting chain \`rawfoo'
Flushing chain \`PREROUTING'
Flushing chain \`INPUT'
Flushing chain \`FORWARD'
Flushing chain \`OUTPUT'
Flushing chain \`POSTROUTING'
Flushing chain \`manglefoo'
Deleting chain \`manglefoo'
Flushing chain \`INPUT'
Flushing chain \`FORWARD'
Flushing chain \`OUTPUT'
Flushing chain \`secfoo'
Deleting chain \`secfoo'"
for ipt in iptables-restore ip6tables-restore; do
diff -u -Z <(sort <<< "$EXPECT") <($XT_MULTI $ipt -v <<< "$DUMP" | sort)
done
DUMP="*filter
:baz - [0:0]
-F foo
-X bar
-A foo -j ACCEPT
COMMIT
"
EXPECT=""
for ipt in iptables-restore ip6tables-restore; do
diff -u -Z <(echo -ne "$EXPECT") <($XT_MULTI $ipt -v --noflush <<< "$DUMP")
done
#!/bin/bash
# test for iptables-restore --noflush skipping an explicitly requested chain
# flush because the chain did not exist when cache was fetched. In order to
# expect for that chain to appear when refreshing the transaction (due to a
# concurrent ruleset change), the chain flush job has to be present in batch
# job list (although disabled at first).
# The input line requesting chain flush is ':FOO - [0:0]'. RS1 and RS2 contents
# are crafted to cause EBUSY when deleting the BAR* chains if FOO is not
# flushed in the same transaction.
set -e
RS="*filter
:INPUT ACCEPT [12024:3123388]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [12840:2144421]
:FOO - [0:0]
:BAR0 - [0:0]
:BAR1 - [0:0]
:BAR2 - [0:0]
:BAR3 - [0:0]
:BAR4 - [0:0]
:BAR5 - [0:0]
:BAR6 - [0:0]
:BAR7 - [0:0]
:BAR8 - [0:0]
:BAR9 - [0:0]
"
RS1="$RS
-X BAR3
-X BAR6
-X BAR9
-A FOO -s 9.9.0.1/32 -j BAR1
-A FOO -s 9.9.0.2/32 -j BAR2
-A FOO -s 9.9.0.4/32 -j BAR4
-A FOO -s 9.9.0.5/32 -j BAR5
-A FOO -s 9.9.0.7/32 -j BAR7
-A FOO -s 9.9.0.8/32 -j BAR8
COMMIT
"
RS2="$RS
-X BAR2
-X BAR5
-X BAR7
-A FOO -s 9.9.0.1/32 -j BAR1
-A FOO -s 9.9.0.3/32 -j BAR3
-A FOO -s 9.9.0.4/32 -j BAR4
-A FOO -s 9.9.0.6/32 -j BAR6
-A FOO -s 9.9.0.8/32 -j BAR8
-A FOO -s 9.9.0.9/32 -j BAR9
COMMIT
"
NORS="*filter
COMMIT
"
for n in $(seq 1 10); do
$XT_MULTI iptables-restore <<< "$NORS"
$XT_MULTI iptables-restore --noflush -w <<< "$RS1" &
$XT_MULTI iptables-restore --noflush -w <<< "$RS2" &
wait -n
wait -n
done
......@@ -13,75 +13,84 @@ cmd() { # (rc, msg, cmd, [args ...])
msg_exp="$1"; shift
}
msg="$($XT_MULTI "$@" 2>&1 >/dev/null)"
rc=$?
for ipt in iptables ip6tables; do
msg="$($XT_MULTI $ipt "$@" 2>&1 >/dev/null)"
rc=$?
[ $rc -eq $rc_exp ] || {
echo "---> expected return code $rc_exp, got $rc for command '$@'"
global_rc=1
}
[ $rc -eq $rc_exp ] || {
echo "---> expected return code $rc_exp, got $rc for command '$ipt $@'"
global_rc=1
}
[ -n "$msg_exp" ] || return
grep -q "$msg_exp" <<< $msg || {
echo "---> expected error message '$msg_exp', got '$msg' for command '$@'"
global_rc=1
}
[ -n "$msg_exp" ] || continue
msg_exp_full="${ipt}$msg_exp"
grep -q "$msg_exp_full" <<< $msg || {
echo "---> expected error message '$msg_exp_full', got '$msg' for command '$ipt $@'"
global_rc=1
}
done
}
EEXIST_F="File exists."
EEXIST="Chain already exists."
ENOENT="No chain/target/match by that name."
E2BIG_I="Index of insertion too big."
E2BIG_D="Index of deletion too big."
E2BIG_R="Index of replacement too big."
EBADRULE="Bad rule (does a matching rule exist in that chain?)."
ENOTGT="Couldn't load target \`foobar':No such file or directory"
ENOMTH="Couldn't load match \`foobar':No such file or directory"
ENOTBL="can't initialize iptables table \`foobar': Table does not exist"
EEXIST_F=": File exists."
EEXIST=": Chain already exists."
ENOENT=": No chain/target/match by that name."
E2BIG_I=": Index of insertion too big."
E2BIG_D=": Index of deletion too big."
E2BIG_R=": Index of replacement too big."
EBADRULE=": Bad rule (does a matching rule exist in that chain?)."
#ENOTGT=" v[0-9\.]* [^ ]*: Couldn't load target \`foobar':No such file or directory"
ENOMTH=" v[0-9\.]* [^ ]*: Couldn't load match \`foobar':No such file or directory"
ENOTBL=": can't initialize iptables table \`foobar': Table does not exist"
# test chain creation
cmd 0 iptables -N foo
cmd 1 "$EEXIST" iptables -N foo
cmd 0 -N foo
cmd 1 "$EEXIST" -N foo
# iptables-nft allows this - bug or feature?
#cmd 2 iptables -N "invalid name"
#cmd 2 -N "invalid name"
# test chain flushing/zeroing
cmd 0 iptables -F foo
cmd 0 iptables -Z foo
cmd 1 "$ENOENT" iptables -F bar
cmd 1 "$ENOENT" iptables -Z bar
cmd 0 -F foo
cmd 0 -Z foo
cmd 1 "$ENOENT" -F bar
cmd 1 "$ENOENT" -Z bar
# test chain rename
cmd 0 iptables -E foo bar
cmd 1 "$EEXIST_F" iptables -E foo bar
cmd 1 "$ENOENT" iptables -E foo bar2
cmd 0 iptables -N foo2
cmd 1 "$EEXIST_F" iptables -E foo2 bar
cmd 0 -E foo bar
cmd 1 "$EEXIST_F" -E foo bar
cmd 1 "$ENOENT" -E foo bar2
cmd 0 -N foo2
cmd 1 "$EEXIST_F" -E foo2 bar
# test rule adding
cmd 0 iptables -A INPUT -j ACCEPT
cmd 1 "$ENOENT" iptables -A noexist -j ACCEPT
cmd 2 "" iptables -I INPUT -j foobar
cmd 2 "" iptables -R INPUT 1 -j foobar
cmd 2 "" iptables -D INPUT -j foobar
cmd 0 -A INPUT -j ACCEPT
cmd 1 "$ENOENT" -A noexist -j ACCEPT
# next three differ:
# legacy: Couldn't load target `foobar':No such file or directory
# nft: Chain 'foobar' does not exist
cmd 2 "" -I INPUT -j foobar
cmd 2 "" -R INPUT 1 -j foobar
cmd 2 "" -D INPUT -j foobar
cmd 1 "$EBADRULE" -D INPUT -p tcp --dport 22 -j ACCEPT
# test rulenum commands
cmd 1 "$E2BIG_I" iptables -I INPUT 23 -j ACCEPT
cmd 1 "$E2BIG_D" iptables -D INPUT 23
cmd 1 "$E2BIG_R" iptables -R INPUT 23 -j ACCEPT
cmd 1 "$ENOENT" iptables -I nonexist 23 -j ACCEPT
cmd 1 "$ENOENT" iptables -D nonexist 23
cmd 1 "$ENOENT" iptables -R nonexist 23 -j ACCEPT
cmd 1 "$E2BIG_I" -I INPUT 23 -j ACCEPT
cmd 1 "$E2BIG_D" -D INPUT 23
cmd 1 "$E2BIG_R" -R INPUT 23 -j ACCEPT
cmd 1 "$ENOENT" -I nonexist 23 -j ACCEPT
cmd 1 "$ENOENT" -D nonexist 23
cmd 1 "$ENOENT" -R nonexist 23 -j ACCEPT
# test rule checking
cmd 0 iptables -C INPUT -j ACCEPT
cmd 1 "$EBADRULE" iptables -C FORWARD -j ACCEPT
cmd 1 "$BADRULE" iptables -C nonexist -j ACCEPT
cmd 2 "$ENOMTH" iptables -C INPUT -m foobar -j ACCEPT
cmd 0 -C INPUT -j ACCEPT
cmd 1 "$EBADRULE" -C FORWARD -j ACCEPT
cmd 1 "$BADRULE" -C nonexist -j ACCEPT
cmd 2 "$ENOMTH" -C INPUT -m foobar -j ACCEPT
# messages of those don't match, but iptables-nft ones are actually nicer.
#cmd 2 "$ENOTGT" iptables -C INPUT -j foobar
#cmd 3 "$ENOTBL" iptables -t foobar -C INPUT -j ACCEPT
cmd 2 "" iptables -C INPUT -j foobar
cmd 3 "" iptables -t foobar -C INPUT -j ACCEPT
# legacy: Couldn't load target `foobar':No such file or directory
# nft: Chain 'foobar' does not exist
cmd 2 "" -C INPUT -j foobar
# legacy: can't initialize ip6tables table `foobar': Table does not exist (do you need to insmod?)
# nft: table 'foobar' does not exist
cmd 3 "" -t foobar -C INPUT -j ACCEPT
exit $global_rc
#!/bin/bash
[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
nft -v >/dev/null || { echo "skip $XT_MULTI (no nft)"; exit 0; }
coproc $XT_MULTI iptables-restore --noflush
cat >&"${COPROC[1]}" <<EOF
*filter
:foo [0:0]
COMMIT
*filter
:foo [0:0]
EOF
$XT_MULTI iptables-save | grep -q ':foo'
nft flush ruleset
echo "COMMIT" >&"${COPROC[1]}"
sleep 1
[[ -n $COPROC_PID ]] && kill $COPROC_PID
wait
#!/bin/bash
[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
set -e
$XT_MULTI iptables -t raw -P OUTPUT DROP
# make sure iptables-nft-restore can correctly handle basechain policies when
# they aren't set with --noflush
#
$XT_MULTI iptables-restore --noflush <<EOF
*raw
:OUTPUT - [0:0]
:PREROUTING - [0:0]
:neutron-linuxbri-OUTPUT - [0:0]
:neutron-linuxbri-PREROUTING - [0:0]
-I OUTPUT 1 -j neutron-linuxbri-OUTPUT
-I PREROUTING 1 -j neutron-linuxbri-PREROUTING
-I neutron-linuxbri-PREROUTING 1 -m physdev --physdev-in brq7425e328-56 -j CT --zone 4097
-I neutron-linuxbri-PREROUTING 2 -i brq7425e328-56 -j CT --zone 4097
-I neutron-linuxbri-PREROUTING 3 -m physdev --physdev-in tap7f101a28-1d -j CT --zone 4097
COMMIT
EOF
$XT_MULTI iptables-save | grep -C2 raw | grep OUTPUT | grep DROP
if [ $? -ne 0 ]; then
exit 1
fi
......@@ -249,15 +249,20 @@ void xs_init_match(struct xtables_match *match)
static int xtables_lock(int wait, struct timeval *wait_interval)
{
struct timeval time_left, wait_time;
const char *lock_file;
int fd, i = 0;
time_left.tv_sec = wait;
time_left.tv_usec = 0;
fd = open(XT_LOCK_NAME, O_CREAT, 0600);
lock_file = getenv("XTABLES_LOCKFILE");
if (lock_file == NULL || lock_file[0] == '\0')
lock_file = XT_LOCK_NAME;
fd = open(lock_file, O_CREAT, 0600);
if (fd < 0) {
fprintf(stderr, "Fatal: can't open lock file %s: %s\n",
XT_LOCK_NAME, strerror(errno));
lock_file, strerror(errno));
return XT_LOCK_FAILED;
}
......@@ -265,7 +270,7 @@ static int xtables_lock(int wait, struct timeval *wait_interval)
if (flock(fd, LOCK_EX) == 0)
return fd;
fprintf(stderr, "Can't lock %s: %s\n", XT_LOCK_NAME,
fprintf(stderr, "Can't lock %s: %s\n", lock_file,
strerror(errno));
return XT_LOCK_BUSY;
}
......
......@@ -1155,7 +1155,7 @@ print_zero:
/*case 7 :*/ /* atomic-init */
/*case 10:*/ /* atomic-save */
case 11: /* init-table */
nft_cmd_table_flush(h, *table);
nft_cmd_table_flush(h, *table, false);
return 1;
/*
replace->command = c;
......
......@@ -93,6 +93,8 @@ static int rule_cb(const struct nlmsghdr *nlh, void *data)
if (arg->nfproto && arg->nfproto != family)
goto err_free;
arg->h->ops = nft_family_ops_lookup(family);
if (arg->is_event)
printf(" EVENT: ");
switch (family) {
......
......@@ -61,7 +61,6 @@ static void print_usage(const char *name, const char *version)
static const struct nft_xt_restore_cb restore_cb = {
.commit = nft_commit,
.abort = nft_abort,
.table_new = nft_cmd_table_new,
.table_flush = nft_cmd_table_flush,
.do_command = do_commandx,
.chain_set = nft_cmd_chain_set,
......@@ -135,7 +134,7 @@ static void xtables_restore_parse_line(struct nft_handle *h,
if (h->noflush == 0) {
DEBUGP("Cleaning all chains of table '%s'\n", table);
if (cb->table_flush)
cb->table_flush(h, table);
cb->table_flush(h, table, verbose);
}
ret = 1;
......@@ -260,7 +259,7 @@ void xtables_restore_parse(struct nft_handle *h,
struct nft_xt_restore_state state = {};
char buffer[10240] = {};
if (!h->noflush)
if (!verbose && !h->noflush)
nft_cache_level_set(h, NFT_CL_FAKE, NULL);
line = 0;
......@@ -410,7 +409,6 @@ int xtables_ip6_restore_main(int argc, char *argv[])
static const struct nft_xt_restore_cb ebt_restore_cb = {
.commit = nft_bridge_commit,
.table_new = nft_cmd_table_new,
.table_flush = nft_cmd_table_flush,
.do_command = do_commandeb,
.chain_set = nft_cmd_chain_set,
......@@ -456,7 +454,6 @@ int xtables_eb_restore_main(int argc, char *argv[])
static const struct nft_xt_restore_cb arp_restore_cb = {
.commit = nft_commit,
.table_new = nft_cmd_table_new,
.table_flush = nft_cmd_table_flush,
.do_command = do_commandarp,
.chain_set = nft_cmd_chain_set,
......
......@@ -92,7 +92,7 @@ __do_output(struct nft_handle *h, const char *tablename, void *data)
printf("*%s\n", tablename);
/* Dump out chain names first,
* thereby preventing dependency conflicts */
nft_chain_save(h, chain_list);
nftnl_chain_list_foreach(chain_list, nft_chain_save, h);
nft_rule_save(h, tablename, d->format);
if (d->commit)
printf("COMMIT\n");
......
......@@ -75,14 +75,10 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
xtables_fini();
if (!ret) {
if (errno == EINVAL) {
fprintf(stderr, "iptables: %s. "
"Run `dmesg' for more information.\n",
nft_strerror(errno));
} else {
fprintf(stderr, "iptables: %s.\n",
nft_strerror(errno));
}
fprintf(stderr, "%s: %s.%s\n", progname, nft_strerror(errno),
(errno == EINVAL ?
" Run `dmesg' for more information." : ""));
if (errno == EAGAIN)
exit(RESOURCE_PROBLEM);
}
......
......@@ -249,7 +249,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
cs.restore = restore;
if (!restore)
if (!restore && p.command != CMD_NONE)
printf("nft ");
switch (p.command) {
......@@ -310,13 +310,16 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
break;
case CMD_SET_POLICY:
break;
case CMD_NONE:
ret = 1;
break;
default:
/* We should never reach this... */
printf("Unsupported command?\n");
exit(1);
}
xtables_rule_matches_free(&cs.matches);
nft_clear_iptables_command_state(&cs);
if (h->family == AF_INET) {
free(args.s.addr.v4);
......
......@@ -275,6 +275,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XT_LOCK_NAME = @XT_LOCK_NAME@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
......
......@@ -282,6 +282,7 @@ SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
XT_LOCK_NAME = @XT_LOCK_NAME@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
......
......@@ -1169,7 +1169,7 @@ static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struc
else
foot->target.verdict = RETURN;
/* set policy-counters */
memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS));
foot->e.counters = c->counters;
return 0;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment