summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/libip6t_MASQUERADE.c2
-rw-r--r--extensions/libxt_conntrack.c46
-rw-r--r--extensions/libxt_conntrack.txlate8
-rw-r--r--extensions/libxt_devgroup.man2
-rw-r--r--extensions/libxt_hashlimit.t6
-rw-r--r--extensions/libxt_mac.c4
-rw-r--r--extensions/libxt_multiport.c38
-rw-r--r--extensions/libxt_multiport.txlate3
-rwxr-xr-xiptables-test.py75
-rw-r--r--iptables/ebtables-nft.864
-rw-r--r--iptables/iptables.8.in13
-rw-r--r--iptables/nft-bridge.c6
-rw-r--r--iptables/nft-cmd.c17
-rw-r--r--iptables/nft-cmd.h4
-rw-r--r--iptables/nft.c97
-rw-r--r--iptables/nft.h4
-rwxr-xr-xiptables/tests/shell/run-tests.sh2
-rwxr-xr-xiptables/tests/shell/testcases/ebtables/0007-chain-policies_041
-rwxr-xr-xiptables/tests/shell/testcases/iptables/0002-verbose-output_011
-rw-r--r--iptables/xshared.c8
-rw-r--r--iptables/xtables-arp.c4
-rw-r--r--iptables/xtables-eb.c69
-rw-r--r--iptables/xtables-monitor.8.in6
-rw-r--r--iptables/xtables-monitor.c1
-rw-r--r--iptables/xtables-restore.c1
-rw-r--r--iptables/xtables-save.c1
-rw-r--r--iptables/xtables-standalone.c1
-rw-r--r--iptables/xtables-translate.c1
-rw-r--r--iptables/xtables.c4
-rw-r--r--libxtables/xtables.c15
-rwxr-xr-xxlate-test.py34
31 files changed, 291 insertions, 297 deletions
diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c
index f92760fa..f28f071b 100644
--- a/extensions/libip6t_MASQUERADE.c
+++ b/extensions/libip6t_MASQUERADE.c
@@ -163,7 +163,7 @@ static int MASQUERADE_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, " ");
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- xt_xlate_add(xl, "random-fully ");
+ xt_xlate_add(xl, "fully-random ");
return 1;
}
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index 7f7b45ee..64018ce1 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -1151,40 +1151,30 @@ static void state_save(const void *ip, const struct xt_entry_match *match)
static void state_xlate_print(struct xt_xlate *xl, unsigned int statemask, int inverted)
{
const char *sep = "";
- int one_flag_set;
- one_flag_set = !(statemask & (statemask - 1));
-
- if (inverted && !one_flag_set)
- xt_xlate_add(xl, "& (");
- else if (inverted)
- xt_xlate_add(xl, "& ");
+ if (inverted)
+ xt_xlate_add(xl, "! ");
if (statemask & XT_CONNTRACK_STATE_INVALID) {
xt_xlate_add(xl, "%s%s", sep, "invalid");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
xt_xlate_add(xl, "%s%s", sep, "new");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
xt_xlate_add(xl, "%s%s", sep, "related");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
xt_xlate_add(xl, "%s%s", sep, "established");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
xt_xlate_add(xl, "%s%s", sep, "untracked");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
-
- if (inverted && !one_flag_set)
- xt_xlate_add(xl, ") == 0");
- else if (inverted)
- xt_xlate_add(xl, " == 0");
}
static int state_xlate(struct xt_xlate *xl,
@@ -1203,36 +1193,26 @@ static int state_xlate(struct xt_xlate *xl,
static void status_xlate_print(struct xt_xlate *xl, unsigned int statusmask, int inverted)
{
const char *sep = "";
- int one_flag_set;
- one_flag_set = !(statusmask & (statusmask - 1));
-
- if (inverted && !one_flag_set)
- xt_xlate_add(xl, "& (");
- else if (inverted)
- xt_xlate_add(xl, "& ");
+ if (inverted)
+ xt_xlate_add(xl, "! ");
if (statusmask & IPS_EXPECTED) {
xt_xlate_add(xl, "%s%s", sep, "expected");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statusmask & IPS_SEEN_REPLY) {
xt_xlate_add(xl, "%s%s", sep, "seen-reply");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statusmask & IPS_ASSURED) {
xt_xlate_add(xl, "%s%s", sep, "assured");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
if (statusmask & IPS_CONFIRMED) {
xt_xlate_add(xl, "%s%s", sep, "confirmed");
- sep = inverted && !one_flag_set ? "|" : ",";
+ sep = ",";
}
-
- if (inverted && !one_flag_set)
- xt_xlate_add(xl, ") == 0");
- else if (inverted)
- xt_xlate_add(xl, " == 0");
}
static void addr_xlate_print(struct xt_xlate *xl,
diff --git a/extensions/libxt_conntrack.txlate b/extensions/libxt_conntrack.txlate
index 8cc7c504..45fba984 100644
--- a/extensions/libxt_conntrack.txlate
+++ b/extensions/libxt_conntrack.txlate
@@ -2,10 +2,10 @@ iptables-translate -t filter -A INPUT -m conntrack --ctstate NEW,RELATED -j ACCE
nft add rule ip filter INPUT ct state new,related counter accept
ip6tables-translate -t filter -A INPUT -m conntrack ! --ctstate NEW,RELATED -j ACCEPT
-nft add rule ip6 filter INPUT ct state & (new|related) == 0 counter accept
+nft add rule ip6 filter INPUT ct state ! new,related counter accept
ip6tables-translate -t filter -A INPUT -m conntrack ! --ctstate NEW -j ACCEPT
-nft add rule ip6 filter INPUT ct state & new == 0 counter accept
+nft add rule ip6 filter INPUT ct state ! new counter accept
iptables-translate -t filter -A INPUT -m conntrack --ctproto UDP -j ACCEPT
nft add rule ip filter INPUT ct original protocol 17 counter accept
@@ -35,10 +35,10 @@ iptables-translate -t filter -A INPUT -m conntrack --ctstatus EXPECTED -j ACCEPT
nft add rule ip filter INPUT ct status expected counter accept
iptables-translate -t filter -A INPUT -m conntrack ! --ctstatus CONFIRMED -j ACCEPT
-nft add rule ip filter INPUT ct status & confirmed == 0 counter accept
+nft add rule ip filter INPUT ct status ! confirmed counter accept
iptables-translate -t filter -A INPUT -m conntrack ! --ctstatus CONFIRMED,ASSURED -j ACCEPT
-nft add rule ip filter INPUT ct status & (assured|confirmed) == 0 counter accept
+nft add rule ip filter INPUT ct status ! assured,confirmed counter accept
iptables-translate -t filter -A INPUT -m conntrack --ctstatus CONFIRMED,ASSURED -j ACCEPT
nft add rule ip filter INPUT ct status assured,confirmed counter accept
diff --git a/extensions/libxt_devgroup.man b/extensions/libxt_devgroup.man
index 4a66c9fe..480ee351 100644
--- a/extensions/libxt_devgroup.man
+++ b/extensions/libxt_devgroup.man
@@ -1,4 +1,4 @@
-Match device group of a packets incoming/outgoing interface.
+Match device group of a packet's incoming/outgoing interface.
.TP
[\fB!\fP] \fB\-\-src\-group\fP \fIname\fP
Match device group of incoming device
diff --git a/extensions/libxt_hashlimit.t b/extensions/libxt_hashlimit.t
index ccd0d1e6..83699337 100644
--- a/extensions/libxt_hashlimit.t
+++ b/extensions/libxt_hashlimit.t
@@ -3,14 +3,12 @@
-m hashlimit --hashlimit-above 1000000/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-above 1/min --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-above 1/hour --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-# kernel says "xt_hashlimit: overflow, try lower: 864000000/5"
--m hashlimit --hashlimit-above 1/day --hashlimit-burst 5 --hashlimit-name mini1;;FAIL
+-m hashlimit --hashlimit-above 1/day --hashlimit-burst 500 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1000000/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1/min --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-# kernel says "xt_hashlimit: overflow, try lower: 864000000/5"
--m hashlimit --hashlimit-upto 1/day --hashlimit-burst 5 --hashlimit-name mini1;;FAIL
+-m hashlimit --hashlimit-upto 1/day --hashlimit-burst 500 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode srcip --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK
diff --git a/extensions/libxt_mac.c b/extensions/libxt_mac.c
index b90eef20..55891b2b 100644
--- a/extensions/libxt_mac.c
+++ b/extensions/libxt_mac.c
@@ -42,10 +42,10 @@ mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_mac_info *info = (void *)match->data;
- printf(" MAC");
+ printf(" MAC ");
if (info->invert)
- printf(" !");
+ printf("! ");
xtables_print_mac(info->srcaddr);
}
diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c
index 4a42fa38..6b0c8190 100644
--- a/extensions/libxt_multiport.c
+++ b/extensions/libxt_multiport.c
@@ -465,7 +465,8 @@ static void multiport_save6_v1(const void *ip_void,
}
static int __multiport_xlate(struct xt_xlate *xl,
- const struct xt_xlate_mt_params *params)
+ const struct xt_xlate_mt_params *params,
+ uint8_t proto)
{
const struct xt_multiport *multiinfo
= (const struct xt_multiport *)params->match->data;
@@ -479,7 +480,17 @@ static int __multiport_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, " dport ");
break;
case XT_MULTIPORT_EITHER:
- return 0;
+ xt_xlate_add(xl, " sport . %s dport { ", proto_to_name(proto));
+ for (i = 0; i < multiinfo->count; i++) {
+ if (i != 0)
+ xt_xlate_add(xl, ", ");
+
+ xt_xlate_add(xl, "0-65535 . %u, %u . 0-65535",
+ multiinfo->ports[i], multiinfo->ports[i]);
+ }
+ xt_xlate_add(xl, " }");
+
+ return 1;
}
if (multiinfo->count > 1)
@@ -500,7 +511,7 @@ static int multiport_xlate(struct xt_xlate *xl,
uint8_t proto = ((const struct ipt_ip *)params->ip)->proto;
xt_xlate_add(xl, "%s", proto_to_name(proto));
- return __multiport_xlate(xl, params);
+ return __multiport_xlate(xl, params, proto);
}
static int multiport_xlate6(struct xt_xlate *xl,
@@ -509,11 +520,12 @@ static int multiport_xlate6(struct xt_xlate *xl,
uint8_t proto = ((const struct ip6t_ip6 *)params->ip)->proto;
xt_xlate_add(xl, "%s", proto_to_name(proto));
- return __multiport_xlate(xl, params);
+ return __multiport_xlate(xl, params, proto);
}
static int __multiport_xlate_v1(struct xt_xlate *xl,
- const struct xt_xlate_mt_params *params)
+ const struct xt_xlate_mt_params *params,
+ uint8_t proto)
{
const struct xt_multiport_v1 *multiinfo =
(const struct xt_multiport_v1 *)params->match->data;
@@ -527,7 +539,17 @@ static int __multiport_xlate_v1(struct xt_xlate *xl,
xt_xlate_add(xl, " dport ");
break;
case XT_MULTIPORT_EITHER:
- return 0;
+ xt_xlate_add(xl, " sport . %s dport { ", proto_to_name(proto));
+ for (i = 0; i < multiinfo->count; i++) {
+ if (i != 0)
+ xt_xlate_add(xl, ", ");
+
+ xt_xlate_add(xl, "0-65535 . %u, %u . 0-65535",
+ multiinfo->ports[i], multiinfo->ports[i]);
+ }
+ xt_xlate_add(xl, " }");
+
+ return 1;
}
if (multiinfo->invert)
@@ -556,7 +578,7 @@ static int multiport_xlate_v1(struct xt_xlate *xl,
uint8_t proto = ((const struct ipt_ip *)params->ip)->proto;
xt_xlate_add(xl, "%s", proto_to_name(proto));
- return __multiport_xlate_v1(xl, params);
+ return __multiport_xlate_v1(xl, params, proto);
}
static int multiport_xlate6_v1(struct xt_xlate *xl,
@@ -565,7 +587,7 @@ static int multiport_xlate6_v1(struct xt_xlate *xl,
uint8_t proto = ((const struct ip6t_ip6 *)params->ip)->proto;
xt_xlate_add(xl, "%s", proto_to_name(proto));
- return __multiport_xlate_v1(xl, params);
+ return __multiport_xlate_v1(xl, params, proto);
}
static struct xtables_match multiport_mt_reg[] = {
diff --git a/extensions/libxt_multiport.txlate b/extensions/libxt_multiport.txlate
index 752e7148..bced1b84 100644
--- a/extensions/libxt_multiport.txlate
+++ b/extensions/libxt_multiport.txlate
@@ -9,3 +9,6 @@ nft add rule ip filter INPUT ip protocol tcp tcp dport != 80-88 counter accept
iptables-translate -t filter -A INPUT -p tcp -m multiport --sports 50 -j ACCEPT
nft add rule ip filter INPUT ip protocol tcp tcp sport 50 counter accept
+
+iptables-translate -t filter -I INPUT -p tcp -m multiport --ports 10
+nft insert rule ip filter INPUT ip protocol tcp tcp sport . tcp dport { 0-65535 . 10, 10 . 0-65535 } counter
diff --git a/iptables-test.py b/iptables-test.py
index ca5efb1b..a876f616 100755
--- a/iptables-test.py
+++ b/iptables-test.py
@@ -32,22 +32,25 @@ EXTENSIONS_PATH = "extensions"
LOGFILE="/tmp/iptables-test.log"
log_file = None
+STDOUT_IS_TTY = sys.stdout.isatty()
-class Colors:
- HEADER = '\033[95m'
- BLUE = '\033[94m'
- GREEN = '\033[92m'
- YELLOW = '\033[93m'
- RED = '\033[91m'
- ENDC = '\033[0m'
+def maybe_colored(color, text):
+ terminal_sequences = {
+ 'green': '\033[92m',
+ 'red': '\033[91m',
+ }
+
+ return (
+ terminal_sequences[color] + text + '\033[0m' if STDOUT_IS_TTY else text
+ )
def print_error(reason, filename=None, lineno=None):
'''
Prints an error with nice colors, indicating file and line number.
'''
- print(filename + ": " + Colors.RED + "ERROR" +
- Colors.ENDC + ": line %d (%s)" % (lineno, reason))
+ print(filename + ": " + maybe_colored('red', "ERROR") +
+ ": line %d (%s)" % (lineno, reason), file=sys.stderr)
def delete_rule(iptables, rule, filename, lineno):
@@ -215,6 +218,7 @@ def run_test_file(filename, netns):
tests = 0
passed = 0
table = ""
+ chain_array = []
total_test_passed = True
if netns:
@@ -249,8 +253,10 @@ def run_test_file(filename, netns):
continue
if len(chain_array) == 0:
- print("broken test, missing chain, leaving")
- sys.exit()
+ print_error("broken test, missing chain",
+ filename = filename, lineno = lineno)
+ total_test_passed = False
+ break
test_passed = True
tests += 1
@@ -282,7 +288,7 @@ def run_test_file(filename, netns):
if netns:
execute_cmd("ip netns del ____iptables-container-test", filename, 0)
if total_test_passed:
- print(filename + ": " + Colors.GREEN + "OK" + Colors.ENDC)
+ print(filename + ": " + maybe_colored('green', "OK"))
f.close()
return tests, passed
@@ -304,6 +310,31 @@ def show_missing():
print('\n'.join(missing))
+def spawn_netns():
+ # prefer unshare module
+ try:
+ import unshare
+ unshare.unshare(unshare.CLONE_NEWNET)
+ return True
+ except:
+ pass
+
+ # sledgehammer style:
+ # - call ourselves prefixed by 'unshare -n' if found
+ # - pass extra --no-netns parameter to avoid another recursion
+ try:
+ import shutil
+
+ unshare = shutil.which("unshare")
+ if unshare is None:
+ return False
+
+ sys.argv.append("--no-netns")
+ os.execv(unshare, [unshare, "-n", sys.executable] + sys.argv)
+ except:
+ pass
+
+ return False
#
# main
@@ -323,6 +354,8 @@ def main():
help='Test iptables-over-nftables')
parser.add_argument('-N', '--netns', action='store_true',
help='Test netnamespace path')
+ parser.add_argument('--no-netns', action='store_true',
+ help='Do not run testsuite in own network namespace')
args = parser.parse_args()
#
@@ -338,9 +371,13 @@ def main():
EXECUTEABLE = "xtables-nft-multi"
if os.getuid() != 0:
- print("You need to be root to run this, sorry")
+ print("You need to be root to run this, sorry", file=sys.stderr)
return
+ if not args.netns and not args.no_netns and not spawn_netns():
+ print("Cannot run in own namespace, connectivity might break",
+ file=sys.stderr)
+
if not args.host:
os.putenv("XTABLES_LIBDIR", os.path.abspath(EXTENSIONS_PATH))
os.putenv("PATH", "%s/iptables:%s" % (os.path.abspath(os.path.curdir),
@@ -355,7 +392,7 @@ def main():
try:
log_file = open(LOGFILE, 'w')
except IOError:
- print("Couldn't open log file %s" % LOGFILE)
+ print("Couldn't open log file %s" % LOGFILE, file=sys.stderr)
return
if args.filename:
@@ -366,13 +403,6 @@ def main():
if i.endswith('.t')]
file_list.sort()
- if not args.netns:
- try:
- import unshare
- unshare.unshare(unshare.CLONE_NEWNET)
- except:
- print("Cannot run in own namespace, connectivity might break")
-
for filename in file_list:
file_tests, file_passed = run_test_file(filename, args.netns)
if file_tests:
@@ -381,7 +411,8 @@ def main():
test_files += 1
print("%d test files, %d unit tests, %d passed" % (test_files, tests, passed))
+ return passed - tests
if __name__ == '__main__':
- main()
+ sys.exit(main())
diff --git a/iptables/ebtables-nft.8 b/iptables/ebtables-nft.8
index 1fa5ad93..08e9766f 100644
--- a/iptables/ebtables-nft.8
+++ b/iptables/ebtables-nft.8
@@ -44,12 +44,6 @@ ebtables \- Ethernet bridge frame table administration (nft-based)
.br
.BR "ebtables " [ -t " table ] " --init-table
.br
-.BR "ebtables " [ -t " table ] [" --atomic-file " file] " --atomic-commit
-.br
-.BR "ebtables " [ -t " table ] [" --atomic-file " file] " --atomic-init
-.br
-.BR "ebtables " [ -t " table ] [" --atomic-file " file] " --atomic-save
-.br
.SH DESCRIPTION
.B ebtables
@@ -149,11 +143,9 @@ a table, the commands apply to the default filter table.
Only one command may be used on the command line at a time, except when
the commands
.BR -L " and " -Z
-are combined, the commands
+are combined or the commands
.BR -N " and " -P
-are combined, or when
-.B --atomic-file
-is used.
+are combined.
.TP
.B "-A, --append"
Append a rule to the end of the selected chain.
@@ -313,39 +305,6 @@ of the ebtables kernel table.
.TP
.B "--init-table"
Replace the current table data by the initial table data.
-.TP
-.B "--atomic-init"
-Copy the kernel's initial data of the table to the specified
-file. This can be used as the first action, after which rules are added
-to the file. The file can be specified using the
-.B --atomic-file
-command or through the
-.IR EBTABLES_ATOMIC_FILE " environment variable."
-.TP
-.B "--atomic-save"
-Copy the kernel's current data of the table to the specified
-file. This can be used as the first action, after which rules are added
-to the file. The file can be specified using the
-.B --atomic-file
-command or through the
-.IR EBTABLES_ATOMIC_FILE " environment variable."
-.TP
-.B "--atomic-commit"
-Replace the kernel table data with the data contained in the specified
-file. This is a useful command that allows you to load all your rules of a
-certain table into the kernel at once, saving the kernel a lot of precious
-time and allowing atomic updates of the tables. The file which contains
-the table data is constructed by using either the
-.B "--atomic-init"
-or the
-.B "--atomic-save"
-command to generate a starting file. After that, using the
-.B "--atomic-file"
-command when constructing rules or setting the
-.IR EBTABLES_ATOMIC_FILE " environment variable"
-allows you to extend the file and build the complete table before
-committing it to the kernel. This command can be very useful in boot scripts
-to populate the ebtables tables in a fast way.
.SS MISCELLANOUS COMMANDS
.TP
.B "-V, --version"
@@ -371,16 +330,6 @@ a target extension (see
.BR "TARGET EXTENSIONS" ")"
or a user-defined chain name.
.TP
-.B --atomic-file "\fIfile\fP"
-Let the command operate on the specified
-.IR file .
-The data of the table to
-operate on will be extracted from the file and the result of the operation
-will be saved back into the file. If specified, this option should come
-before the command specification. An alternative that should be preferred,
-is setting the
-.IR EBTABLES_ATOMIC_FILE " environment variable."
-.TP
.B -M, --modprobe "\fIprogram\fP"
When talking to the kernel, use this
.I program
@@ -1100,8 +1049,6 @@ arp message and the hardware address length in the arp header is 6 bytes.
.br
.SH FILES
.I /etc/ethertypes
-.SH ENVIRONMENT VARIABLES
-.I EBTABLES_ATOMIC_FILE
.SH MAILINGLISTS
.BR "" "See " http://netfilter.org/mailinglists.html
.SH BUGS
@@ -1109,7 +1056,12 @@ The version of ebtables this man page ships with does not support the
.B broute
table. Also there is no support for
.B string
-match. And finally, this list is probably not complete.
+match. Further, support for atomic-options
+.RB ( --atomic-file ", " --atomic-init ", " --atomic-save ", " --atomic-commit )
+has not been implemented, although
+.BR ebtables-save " and " ebtables-restore
+might replace them entirely given the inherent atomicity of nftables.
+Finally, this list is probably not complete.
.SH SEE ALSO
.BR xtables-nft "(8), " iptables "(8), " ip (8)
.PP
diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in
index 999cf339..759ec54f 100644
--- a/iptables/iptables.8.in
+++ b/iptables/iptables.8.in
@@ -25,10 +25,10 @@
.SH NAME
iptables/ip6tables \(em administration tool for IPv4/IPv6 packet filtering and NAT
.SH SYNOPSIS
-\fBiptables\fP [\fB\-t\fP \fItable\fP] {\fB\-A\fP|\fB\-C\fP|\fB\-D\fP}
+\fBiptables\fP [\fB\-t\fP \fItable\fP] {\fB\-A\fP|\fB\-C\fP|\fB\-D\fP|\fB-V\fP}
\fIchain\fP \fIrule-specification\fP
.P
-\fBip6tables\fP [\fB\-t\fP \fItable\fP] {\fB\-A\fP|\fB\-C\fP|\fB\-D\fP}
+\fBip6tables\fP [\fB\-t\fP \fItable\fP] {\fB\-A\fP|\fB\-C\fP|\fB\-D\fP|\fB-V\fP}
\fIchain rule-specification\fP
.PP
\fBiptables\fP [\fB\-t\fP \fItable\fP] \fB\-I\fP \fIchain\fP [\fIrulenum\fP] \fIrule-specification\fP
@@ -220,11 +220,11 @@ Create a new user-defined chain by the given name. There must be no
target of that name already.
.TP
\fB\-X\fP, \fB\-\-delete\-chain\fP [\fIchain\fP]
-Delete the optional user-defined chain specified. There must be no references
+Delete the chain specified. There must be no references
to the chain. If there are, you must delete or replace the referring rules
before the chain can be deleted. The chain must be empty, i.e. not contain
-any rules. If no argument is given, it will attempt to delete every
-non-builtin chain in the table.
+any rules. If no argument is given, it will delete all empty chains in the
+table. Empty builtin chains can only be deleted with \fBiptables-nft\fP.
.TP
\fB\-P\fP, \fB\-\-policy\fP \fIchain target\fP
Set the policy for the built-in (non-user-defined) chain to the given target.
@@ -362,6 +362,9 @@ For appending, insertion, deletion and replacement, this causes
detailed information on the rule or rules to be printed. \fB\-v\fP may be
specified multiple times to possibly emit more detailed debug statements.
.TP
+\fB\-V\fP, \fB\-\-version\fP
+Show program version and the kernel API used.
+.TP
\fB\-w\fP, \fB\-\-wait\fP [\fIseconds\fP]
Wait for the xtables lock.
To prevent multiple instances of the program from running concurrently,
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index d98fd527..11f3df35 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -477,11 +477,7 @@ static void nft_bridge_parse_lookup(struct nft_xt_ctx *ctx,
static void parse_watcher(void *object, struct ebt_match **match_list,
bool ismatch)
{
- struct ebt_match *m;
-
- m = calloc(1, sizeof(struct ebt_match));
- if (m == NULL)
- xtables_error(OTHER_PROBLEM, "Can't allocate memory");
+ struct ebt_match *m = xtables_calloc(1, sizeof(struct ebt_match));
if (ismatch)
m->u.match = object;
diff --git a/iptables/nft-cmd.c b/iptables/nft-cmd.c
index a0c76a79..2d874bd4 100644
--- a/iptables/nft-cmd.c
+++ b/iptables/nft-cmd.c
@@ -23,10 +23,7 @@ struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
struct nftnl_rule *rule;
struct nft_cmd *cmd;
- cmd = calloc(1, sizeof(struct nft_cmd));
- if (!cmd)
- return NULL;
-
+ cmd = xtables_calloc(1, sizeof(struct nft_cmd));
cmd->command = command;
cmd->table = xtables_strdup(table);
if (chain)
@@ -170,7 +167,9 @@ int nft_cmd_rule_flush(struct nft_handle *h, const char *chain,
if (!cmd)
return 0;
- if (chain || verbose)
+ if (h->family == NFPROTO_BRIDGE)
+ nft_cache_level_set(h, NFT_CL_RULES, cmd);
+ else if (chain || verbose)
nft_cache_level_set(h, NFT_CL_CHAINS, cmd);
else
nft_cache_level_set(h, NFT_CL_TABLES, cmd);
@@ -208,12 +207,12 @@ int nft_cmd_chain_user_add(struct nft_handle *h, const char *chain,
return 1;
}
-int nft_cmd_chain_user_del(struct nft_handle *h, const char *chain,
- const char *table, bool verbose)
+int nft_cmd_chain_del(struct nft_handle *h, const char *chain,
+ const char *table, bool verbose)
{
struct nft_cmd *cmd;
- cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_USER_DEL, table, chain, NULL, -1,
+ cmd = nft_cmd_new(h, NFT_COMPAT_CHAIN_DEL, table, chain, NULL, -1,
verbose);
if (!cmd)
return 0;
@@ -320,7 +319,7 @@ int nft_cmd_table_flush(struct nft_handle *h, const char *table, bool verbose)
if (verbose) {
return nft_cmd_rule_flush(h, NULL, table, verbose) &&
- nft_cmd_chain_user_del(h, NULL, table, verbose);
+ nft_cmd_chain_del(h, NULL, table, verbose);
}
cmd = nft_cmd_new(h, NFT_COMPAT_TABLE_FLUSH, table, NULL, NULL, -1,
diff --git a/iptables/nft-cmd.h b/iptables/nft-cmd.h
index ecf7655a..b5a99ef7 100644
--- a/iptables/nft-cmd.h
+++ b/iptables/nft-cmd.h
@@ -49,8 +49,8 @@ int nft_cmd_zero_counters(struct nft_handle *h, const char *chain,
const char *table, bool verbose);
int nft_cmd_chain_user_add(struct nft_handle *h, const char *chain,
const char *table);
-int nft_cmd_chain_user_del(struct nft_handle *h, const char *chain,
- const char *table, bool verbose);
+int nft_cmd_chain_del(struct nft_handle *h, const char *chain,
+ const char *table, bool verbose);
int nft_cmd_chain_zero_counters(struct nft_handle *h, const char *chain,
const char *table, bool verbose);
int nft_cmd_rule_list(struct nft_handle *h, const char *chain,
diff --git a/iptables/nft.c b/iptables/nft.c
index f1deb82f..89dde9ec 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -143,7 +143,7 @@ struct mnl_err {
static void mnl_err_list_node_add(struct list_head *err_list, int error,
int seqnum)
{
- struct mnl_err *err = malloc(sizeof(struct mnl_err));
+ struct mnl_err *err = xtables_malloc(sizeof(struct mnl_err));
err->seqnum = seqnum;
err->err = error;
@@ -290,7 +290,7 @@ static int mnl_append_error(const struct nft_handle *h,
[NFT_COMPAT_TABLE_FLUSH] = "TABLE_FLUSH",
[NFT_COMPAT_CHAIN_ADD] = "CHAIN_ADD",
[NFT_COMPAT_CHAIN_USER_ADD] = "CHAIN_USER_ADD",
- [NFT_COMPAT_CHAIN_USER_DEL] = "CHAIN_USER_DEL",
+ [NFT_COMPAT_CHAIN_DEL] = "CHAIN_DEL",
[NFT_COMPAT_CHAIN_USER_FLUSH] = "CHAIN_USER_FLUSH",
[NFT_COMPAT_CHAIN_UPDATE] = "CHAIN_UPDATE",
[NFT_COMPAT_CHAIN_RENAME] = "CHAIN_RENAME",
@@ -321,7 +321,7 @@ static int mnl_append_error(const struct nft_handle *h,
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_ZERO:
case NFT_COMPAT_CHAIN_USER_ADD:
- case NFT_COMPAT_CHAIN_USER_DEL:
+ case NFT_COMPAT_CHAIN_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
@@ -362,10 +362,7 @@ static struct obj_update *batch_add(struct nft_handle *h, enum obj_update_type t
{
struct obj_update *obj;
- obj = calloc(1, sizeof(struct obj_update));
- if (obj == NULL)
- return NULL;
-
+ obj = xtables_calloc(1, sizeof(struct obj_update));
obj->ptr = ptr;
obj->error.lineno = h->error.lineno;
obj->type = type;
@@ -997,10 +994,7 @@ static int __add_match(struct nftnl_expr *e, struct xt_entry_match *m)
nftnl_expr_set(e, NFTNL_EXPR_MT_NAME, m->u.user.name, strlen(m->u.user.name));
nftnl_expr_set_u32(e, NFTNL_EXPR_MT_REV, m->u.user.revision);
- info = calloc(1, m->u.match_size);
- if (info == NULL)
- return -ENOMEM;
-
+ info = xtables_calloc(1, m->u.match_size);
memcpy(info, m->data, m->u.match_size - sizeof(*m));
nftnl_expr_set(e, NFTNL_EXPR_MT_INFO, info, m->u.match_size - sizeof(*m));
@@ -1245,10 +1239,7 @@ static int __add_target(struct nftnl_expr *e, struct xt_entry_target *t)
strlen(t->u.user.name));
nftnl_expr_set_u32(e, NFTNL_EXPR_TG_REV, t->u.user.revision);
- info = calloc(1, t->u.target_size);
- if (info == NULL)
- return -ENOMEM;
-
+ info = xtables_calloc(1, t->u.target_size);
memcpy(info, t->data, t->u.target_size - sizeof(*t));
nftnl_expr_set(e, NFTNL_EXPR_TG_INFO, info, t->u.target_size - sizeof(*t));
@@ -1845,22 +1836,19 @@ int nft_chain_restore(struct nft_handle *h, const char *chain, const char *table
#define NLM_F_NONREC 0x100 /* Do not delete recursively */
#endif
-struct chain_user_del_data {
+struct chain_del_data {
struct nft_handle *handle;
+ struct nft_cache *cache;
+ enum nft_table_type type;
bool verbose;
- int builtin_err;
};
-static int __nft_chain_user_del(struct nft_chain *nc, void *data)
+static int __nft_chain_del(struct nft_chain *nc, void *data)
{
- struct chain_user_del_data *d = data;
+ struct chain_del_data *d = data;
struct nftnl_chain *c = nc->nftnl;
struct nft_handle *h = d->handle;
- /* don't delete built-in chain */
- if (nft_chain_builtin(c))
- return d->builtin_err;
-
if (d->verbose)
fprintf(stdout, "Deleting chain `%s'\n",
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
@@ -1868,9 +1856,16 @@ static int __nft_chain_user_del(struct nft_chain *nc, void *data)
/* XXX This triggers a fast lookup from the kernel. */
nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE);
- if (!batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c))
+ if (!batch_chain_add(h, NFT_COMPAT_CHAIN_DEL, c))
return -1;
+ if (nft_chain_builtin(c)) {
+ uint32_t num = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM);
+
+ if (nc == d->cache->table[d->type].base_chains[num])
+ d->cache->table[d->type].base_chains[num] = NULL;
+ }
+
/* nftnl_chain is freed when deleting the batch object */
nc->nftnl = NULL;
@@ -1879,17 +1874,18 @@ static int __nft_chain_user_del(struct nft_chain *nc, void *data)
return 0;
}
-int nft_chain_user_del(struct nft_handle *h, const char *chain,
+int nft_chain_del(struct nft_handle *h, const char *chain,
const char *table, bool verbose)
{
- struct chain_user_del_data d = {
+ const struct builtin_table *t;
+ struct chain_del_data d = {
.handle = h,
.verbose = verbose,
};
struct nft_chain *c;
int ret = 0;
- nft_fn = nft_chain_user_del;
+ nft_fn = nft_chain_del;
if (chain) {
c = nft_chain_find(h, table, chain);
@@ -1897,17 +1893,37 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain,
errno = ENOENT;
return 0;
}
- d.builtin_err = -2;
- ret = __nft_chain_user_del(c, &d);
+
+ if (nft_chain_builtin(c->nftnl)) {
+ t = nft_table_builtin_find(h, table);
+ if (!t) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ d.type = t->type;
+ d.cache = h->cache;
+ }
+
+ ret = __nft_chain_del(c, &d);
if (ret == -2)
errno = EINVAL;
goto out;
}
+ t = nft_table_builtin_find(h, table);
+ if (!t) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ d.type = t->type;
+ d.cache = h->cache;
+
if (verbose)
nft_cache_sort_chains(h, table);
- ret = nft_chain_foreach(h, table, __nft_chain_user_del, &d);
+ ret = nft_chain_foreach(h, table, __nft_chain_del, &d);
out:
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
@@ -2672,7 +2688,7 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o)
case NFT_COMPAT_CHAIN_USER_ADD:
case NFT_COMPAT_CHAIN_ADD:
break;
- case NFT_COMPAT_CHAIN_USER_DEL:
+ case NFT_COMPAT_CHAIN_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
@@ -2757,7 +2773,7 @@ static void nft_refresh_transaction(struct nft_handle *h)
case NFT_COMPAT_TABLE_ADD:
case NFT_COMPAT_CHAIN_ADD:
case NFT_COMPAT_CHAIN_ZERO:
- case NFT_COMPAT_CHAIN_USER_DEL:
+ case NFT_COMPAT_CHAIN_DEL:
case NFT_COMPAT_CHAIN_USER_FLUSH:
case NFT_COMPAT_CHAIN_UPDATE:
case NFT_COMPAT_CHAIN_RENAME:
@@ -2823,7 +2839,7 @@ retry:
NLM_F_EXCL, n->seq,
n->chain);
break;
- case NFT_COMPAT_CHAIN_USER_DEL:
+ case NFT_COMPAT_CHAIN_DEL:
nft_compat_chain_batch_add(h, NFT_MSG_DELCHAIN,
NLM_F_NONREC, n->seq,
n->chain);
@@ -3068,9 +3084,9 @@ static int nft_prepare(struct nft_handle *h)
case NFT_COMPAT_CHAIN_USER_ADD:
ret = nft_chain_user_add(h, cmd->chain, cmd->table);
break;
- case NFT_COMPAT_CHAIN_USER_DEL:
- ret = nft_chain_user_del(h, cmd->chain, cmd->table,
- cmd->verbose);
+ case NFT_COMPAT_CHAIN_DEL:
+ ret = nft_chain_del(h, cmd->chain, cmd->table,
+ cmd->verbose);
break;
case NFT_COMPAT_CHAIN_RESTORE:
ret = nft_chain_restore(h, cmd->chain, cmd->table);
@@ -3126,7 +3142,7 @@ static int nft_prepare(struct nft_handle *h)
case NFT_COMPAT_RULE_CHECK:
assert_chain_exists(h, cmd->table, cmd->jumpto);
ret = nft_rule_check(h, cmd->chain, cmd->table,
- cmd->obj.rule, cmd->rulenum);
+ cmd->obj.rule, cmd->verbose);
break;
case NFT_COMPAT_RULE_ZERO:
ret = nft_rule_zero_counters(h, cmd->chain, cmd->table,
@@ -3269,10 +3285,9 @@ const char *nft_strerror(int err)
const char *message;
} table[] =
{
- { nft_chain_user_del, ENOTEMPTY, "Chain is not empty" },
- { nft_chain_user_del, EINVAL, "Can't delete built-in chain" },
- { nft_chain_user_del, EBUSY, "Directory not empty" },
- { nft_chain_user_del, EMLINK,
+ { nft_chain_del, ENOTEMPTY, "Chain is not empty" },
+ { nft_chain_del, EBUSY, "Directory not empty" },
+ { nft_chain_del, EMLINK,
"Can't delete chain with references left" },
{ nft_chain_user_add, EEXIST, "Chain already exists" },
{ nft_chain_user_rename, EEXIST, "File exists" },
diff --git a/iptables/nft.h b/iptables/nft.h
index 4ac7e009..a7b652ff 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -53,7 +53,7 @@ enum obj_update_type {
NFT_COMPAT_TABLE_FLUSH,
NFT_COMPAT_CHAIN_ADD,
NFT_COMPAT_CHAIN_USER_ADD,
- NFT_COMPAT_CHAIN_USER_DEL,
+ NFT_COMPAT_CHAIN_DEL,
NFT_COMPAT_CHAIN_USER_FLUSH,
NFT_COMPAT_CHAIN_UPDATE,
NFT_COMPAT_CHAIN_RENAME,
@@ -147,7 +147,7 @@ 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_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_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);
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);
diff --git a/iptables/tests/shell/run-tests.sh b/iptables/tests/shell/run-tests.sh
index 65c37adb..7878760f 100755
--- a/iptables/tests/shell/run-tests.sh
+++ b/iptables/tests/shell/run-tests.sh
@@ -195,4 +195,4 @@ failed=$((legacy_fail+failed))
msg_info "combined results: [OK] $ok [FAILED] $failed [TOTAL] $((ok+failed))"
-exit 0
+exit -$failed
diff --git a/iptables/tests/shell/testcases/ebtables/0007-chain-policies_0 b/iptables/tests/shell/testcases/ebtables/0007-chain-policies_0
new file mode 100755
index 00000000..faf37d02
--- /dev/null
+++ b/iptables/tests/shell/testcases/ebtables/0007-chain-policies_0
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+case "$XT_MULTI" in
+*xtables-nft-multi)
+ ;;
+*)
+ echo "skip $XT_MULTI"
+ exit 0
+ ;;
+esac
+
+set -e
+
+# ebtables supports policies in user-defined chains %)
+# and the default policy is ACCEPT ...
+$XT_MULTI ebtables -N FOO -P DROP
+$XT_MULTI ebtables -N BAR
+$XT_MULTI ebtables -P BAR RETURN
+$XT_MULTI ebtables -N BAZ
+
+EXPECT_BASE="*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT"
+
+EXPECT="$EXPECT_BASE
+:BAR RETURN
+:BAZ ACCEPT
+:FOO DROP"
+
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ebtables-save | grep -v '^#')
+
+# rule commands must not break the policies
+$XT_MULTI ebtables -A FOO -j ACCEPT
+$XT_MULTI ebtables -D FOO -j ACCEPT
+$XT_MULTI ebtables -F
+diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI ebtables-save | grep -v '^#')
+
+# dropping the chains must implicitly remove the policy rule as well
+$XT_MULTI ebtables -X
+diff -u -Z <(echo -e "$EXPECT_BASE") <($XT_MULTI ebtables-save | grep -v '^#')
diff --git a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0
index b1ef91f6..5d2af4c8 100755
--- a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0
+++ b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0
@@ -54,3 +54,14 @@ diff -u <(echo "Flushing chain \`foobar'") <($XT_MULTI iptables -v -F foobar)
diff -u <(echo "Zeroing chain \`foobar'") <($XT_MULTI iptables -v -Z foobar)
diff -u <(echo "Deleting chain \`foobar'") <($XT_MULTI iptables -v -X foobar)
+
+# make sure non-verbose mode is silent
+diff -u <(echo -n "") <(
+ $XT_MULTI iptables -N foobar
+ $XT_MULTI iptables -A foobar $RULE1
+ $XT_MULTI iptables -A foobar $RULE2
+ $XT_MULTI iptables -C foobar $RULE1
+ $XT_MULTI iptables -D foobar $RULE2
+ $XT_MULTI iptables -F foobar
+ $XT_MULTI iptables -X foobar
+)
diff --git a/iptables/xshared.c b/iptables/xshared.c
index ed3e9c5a..2d3ef679 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -220,9 +220,7 @@ void xs_init_target(struct xtables_target *target)
{
if (target->udata_size != 0) {
free(target->udata);
- target->udata = calloc(1, target->udata_size);
- if (target->udata == NULL)
- xtables_error(RESOURCE_PROBLEM, "malloc");
+ target->udata = xtables_calloc(1, target->udata_size);
}
if (target->init != NULL)
target->init(target->t);
@@ -238,9 +236,7 @@ void xs_init_match(struct xtables_match *match)
* Same goes for target.
*/
free(match->udata);
- match->udata = calloc(1, match->udata_size);
- if (match->udata == NULL)
- xtables_error(RESOURCE_PROBLEM, "malloc");
+ match->udata = xtables_calloc(1, match->udata_size);
}
if (match->init != NULL)
match->init(match->m);
diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c
index 4a351f0c..9a079f06 100644
--- a/iptables/xtables-arp.c
+++ b/iptables/xtables-arp.c
@@ -893,8 +893,8 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table,
ret = nft_cmd_chain_user_add(h, chain, *table);
break;
case CMD_DELETE_CHAIN:
- ret = nft_cmd_chain_user_del(h, chain, *table,
- options & OPT_VERBOSE);
+ ret = nft_cmd_chain_del(h, chain, *table,
+ options & OPT_VERBOSE);
break;
case CMD_RENAME_CHAIN:
ret = nft_cmd_chain_user_rename(h, chain, *table, newname);
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index 6c58adaa..23023ce1 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -211,10 +211,6 @@ struct option ebt_original_options[] =
{ "new-chain" , required_argument, 0, 'N' },
{ "rename-chain" , required_argument, 0, 'E' },
{ "delete-chain" , optional_argument, 0, 'X' },
- { "atomic-init" , no_argument , 0, 7 },
- { "atomic-commit" , no_argument , 0, 8 },
- { "atomic-file" , required_argument, 0, 9 },
- { "atomic-save" , no_argument , 0, 10 },
{ "init-table" , no_argument , 0, 11 },
{ "concurrent" , no_argument , 0, 13 },
{ 0 }
@@ -278,9 +274,7 @@ static struct option *merge_options(struct option *oldopts,
ebtables_globals.option_offset += OPTION_OFFSET;
*options_offset = ebtables_globals.option_offset;
- merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
- if (!merge)
- return NULL;
+ merge = xtables_malloc(sizeof(struct option) * (num_new + num_old + 1));
memcpy(merge, oldopts, num_old * sizeof(struct option));
for (i = 0; i < num_new; i++) {
merge[num_old + i] = newopts[i];
@@ -320,10 +314,6 @@ static void print_help(const struct xtables_target *t,
"--new-chain -N chain : create a user defined chain\n"
"--rename-chain -E old new : rename a chain\n"
"--delete-chain -X [chain] : delete a user defined chain\n"
-"--atomic-commit : update the kernel w/t table contained in <FILE>\n"
-"--atomic-init : put the initial kernel table into <FILE>\n"
-"--atomic-save : put the current kernel table into <FILE>\n"
-"--atomic-file file : set <FILE> to file\n\n"
"Options:\n"
"--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
"--src -s [!] address[/mask]: source mac address\n"
@@ -579,10 +569,7 @@ void ebt_add_match(struct xtables_match *m,
m->mflags = 0;
/* glue code for watchers */
- newnode = calloc(1, sizeof(struct ebt_match));
- if (newnode == NULL)
- xtables_error(OTHER_PROBLEM, "Unable to alloc memory");
-
+ newnode = xtables_calloc(1, sizeof(struct ebt_match));
newnode->ismatch = true;
newnode->u.match = newm;
@@ -611,10 +598,7 @@ void ebt_add_watcher(struct xtables_target *watcher,
watcher->tflags = 0;
- newnode = calloc(1, sizeof(struct ebt_match));
- if (newnode == NULL)
- xtables_error(OTHER_PROBLEM, "Unable to alloc memory");
-
+ newnode = xtables_calloc(1, sizeof(struct ebt_match));
newnode->u.watcher = clone;
for (matchp = &cs->match_list; *matchp; matchp = &(*matchp)->next)
@@ -787,7 +771,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
chain = argv[optind];
optind++;
}
- ret = nft_cmd_chain_user_del(h, chain, *table, 0);
+ ret = nft_cmd_chain_del(h, chain, *table, 0);
break;
}
@@ -1087,54 +1071,9 @@ print_zero:
"Use --Lmac2 with -L");
flags |= LIST_MAC2;
break;
- case 8 : /* atomic-commit */
-/*
- replace->command = c;
- if (OPT_COMMANDS)
- ebt_print_error2("Multiple commands are not allowed");
- replace->flags |= OPT_COMMAND;
- if (!replace->filename)
- ebt_print_error2("No atomic file specified");*/
- /* Get the information from the file */
- /*ebt_get_table(replace, 0);*/
- /* We don't want the kernel giving us its counters,
- * they would overwrite the counters extracted from
- * the file */
- /*replace->num_counters = 0;*/
- /* Make sure the table will be written to the kernel */
- /*free(replace->filename);
- replace->filename = NULL;
- break;*/
- /*case 7 :*/ /* atomic-init */
- /*case 10:*/ /* atomic-save */
case 11: /* init-table */
nft_cmd_table_flush(h, *table, false);
return 1;
- /*
- replace->command = c;
- if (OPT_COMMANDS)
- ebt_print_error2("Multiple commands are not allowed");
- if (c != 11 && !replace->filename)
- ebt_print_error2("No atomic file specified");
- replace->flags |= OPT_COMMAND;
- {
- char *tmp = replace->filename;*/
-
- /* Get the kernel table */
- /*replace->filename = NULL;
- ebt_get_kernel_table(replace, c == 10 ? 0 : 1);
- replace->filename = tmp;
- }
- break;
- case 9 :*/ /* atomic */
- /*
- if (OPT_COMMANDS)
- ebt_print_error2("--atomic has to come before the command");*/
- /* A possible memory leak here, but this is not
- * executed in daemon mode */
- /*replace->filename = (char *)malloc(strlen(optarg) + 1);
- strcpy(replace->filename, optarg);
- break; */
case 13 :
break;
case 1 :
diff --git a/iptables/xtables-monitor.8.in b/iptables/xtables-monitor.8.in
index b647a79e..a7f22c0d 100644
--- a/iptables/xtables-monitor.8.in
+++ b/iptables/xtables-monitor.8.in
@@ -51,9 +51,9 @@ The second line dumps information about the packet. Incoming interface
and packet headers such as source and destination addresses are shown.
The third line shows that the packet completed traversal of the raw table
-PREROUTING chain, and is returning, followed by use the chain policy to make accept/drop
+PREROUTING chain, and is returning, followed by use of the chain policy to make accept/drop
decision (the example shows accept being applied).
-The fifth line shows that the packet leaves the filter INPUT chain, i.e., no rules in the filter tables
+The fifth line shows that the packet leaves the filter INPUT chain, i.e., no rules in the filter table's
INPUT chain matched the packet.
It then got DROPPED by the policy of the INPUT table, as shown by line six.
The last line shows another packet arriving \-\- the packet id is different.
@@ -81,7 +81,7 @@ by three base hooks INPUT, FORWARD and OUTPUT. The iptables-nftables tools all
chains automatically when needed, so this is expected when a table was not yet initialized or when it is
re-created from scratch by iptables-nftables-restore. Line five shows a new user-defined chain (TCP)
being added, followed by addition a few rules. the last line shows that a new ruleset generation has
-become active, i.e., the rule set changes are now active. This also lists the process id and the programs name.
+become active, i.e., the rule set changes are now active. This also lists the process id and the program name.
.SH LIMITATIONS
.B xtables-monitor
only works with rules added using iptables-nftables, rules added using
diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c
index 4b980980..21d4bec0 100644
--- a/iptables/xtables-monitor.c
+++ b/iptables/xtables-monitor.c
@@ -628,6 +628,7 @@ int xtables_monitor_main(int argc, char *argv[])
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
+ init_extensions6();
#endif
if (nft_init(&h, AF_INET, xtables_ipv4)) {
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index d2739497..72832103 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -364,6 +364,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[])
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
+ init_extensions6();
#endif
break;
case NFPROTO_ARP:
diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c
index cfce0472..98cd0ed3 100644
--- a/iptables/xtables-save.c
+++ b/iptables/xtables-save.c
@@ -203,6 +203,7 @@ xtables_save_main(int family, int argc, char *argv[],
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
+ init_extensions6();
#endif
tables = xtables_ipv4;
d.commit = true;
diff --git a/iptables/xtables-standalone.c b/iptables/xtables-standalone.c
index 7b71db62..1a6b7cf7 100644
--- a/iptables/xtables-standalone.c
+++ b/iptables/xtables-standalone.c
@@ -57,6 +57,7 @@ xtables_main(int family, const char *progname, int argc, char *argv[])
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
+ init_extensions6();
#endif
if (nft_init(&h, family, xtables_ipv4) < 0) {
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index 33ba68ec..49f44b6f 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -482,6 +482,7 @@ static int xtables_xlate_main_common(struct nft_handle *h,
#if defined(ALL_INCLUSIVE) || defined(NO_SHARED_LIBS)
init_extensions();
init_extensions4();
+ init_extensions6();
#endif
tables = xtables_ipv4;
break;
diff --git a/iptables/xtables.c b/iptables/xtables.c
index daa9b137..0a700e08 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -998,8 +998,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
ret = nft_cmd_chain_user_add(h, p.chain, p.table);
break;
case CMD_DELETE_CHAIN:
- ret = nft_cmd_chain_user_del(h, p.chain, p.table,
- cs.options & OPT_VERBOSE);
+ ret = nft_cmd_chain_del(h, p.chain, p.table,
+ cs.options & OPT_VERBOSE);
break;
case CMD_RENAME_CHAIN:
ret = nft_cmd_chain_user_rename(h, p.chain, p.table, p.newname);
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index 9fff1e0d..d670175d 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -245,6 +245,10 @@ static void dlreg_free(void)
void xtables_init(void)
{
+ /* xtables cannot be used with setuid in a safe way. */
+ if (getuid() != geteuid())
+ _exit(111);
+
xtables_libdir = getenv("XTABLES_LIBDIR");
if (xtables_libdir != NULL)
return;
@@ -2349,18 +2353,11 @@ struct xt_xlate {
struct xt_xlate *xt_xlate_alloc(int size)
{
- struct xt_xlate *xl;
+ struct xt_xlate *xl = xtables_malloc(sizeof(struct xt_xlate));
int i;
- xl = malloc(sizeof(struct xt_xlate));
- if (xl == NULL)
- xtables_error(RESOURCE_PROBLEM, "OOM");
-
for (i = 0; i < __XT_XLATE_MAX; i++) {
- xl->buf[i].data = malloc(size);
- if (xl->buf[i].data == NULL)
- xtables_error(RESOURCE_PROBLEM, "OOM");
-
+ xl->buf[i].data = xtables_malloc(size);
xl->buf[i].data[0] = '\0';
xl->buf[i].size = size;
xl->buf[i].rem = size;
diff --git a/xlate-test.py b/xlate-test.py
index cba98b6e..4a56e798 100755
--- a/xlate-test.py
+++ b/xlate-test.py
@@ -48,9 +48,9 @@ def run_test(name, payload):
if process.returncode == 0:
translation = output.decode("utf-8").rstrip(" \n")
expected = payload.readline().rstrip(" \n")
- next_expected = payload.readline().rstrip(" \n")
+ next_expected = payload.readline()
if next_expected.startswith("nft"):
- expected += "\n" + next_expected
+ expected += "\n" + next_expected.rstrip(" \n")
line = payload.readline()
else:
line = next_expected
@@ -61,7 +61,6 @@ def run_test(name, payload):
result.append(magenta("src: ") + line.rstrip(" \n"))
result.append(magenta("exp: ") + expected)
result.append(magenta("res: ") + translation + "\n")
- test_passed = False
else:
passed += 1
else:
@@ -75,11 +74,8 @@ def run_test(name, payload):
if (passed == tests) and not args.test:
print(name + ": " + green("OK"))
if not test_passed:
- print("\n".join(result))
- if args.test:
- print("1 test file, %d tests, %d tests passed, %d tests failed, %d errors" % (tests, passed, failed, errors))
- else:
- return tests, passed, failed, errors
+ print("\n".join(result), file=sys.stderr)
+ return tests, passed, failed, errors
def load_test_files():
@@ -93,10 +89,9 @@ def load_test_files():
total_passed += passed
total_failed += failed
total_error += errors
+ return (test_files, total_tests, total_passed, total_failed, total_error)
- print("%d test files, %d tests, %d tests passed, %d tests failed, %d errors" % (test_files, total_tests, total_passed, total_failed, total_error))
-
def main():
global xtables_nft_multi
if not args.host:
@@ -104,16 +99,27 @@ def main():
xtables_nft_multi = os.path.abspath(os.path.curdir) \
+ '/iptables/' + xtables_nft_multi
+ files = tests = passed = failed = errors = 0
if args.test:
if not args.test.endswith(".txlate"):
args.test += ".txlate"
try:
with open(args.test, "r") as payload:
- run_test(args.test, payload)
+ files = 1
+ tests, passed, failed, errors = run_test(args.test, payload)
except IOError:
- print(red("Error: ") + "test file does not exist")
+ print(red("Error: ") + "test file does not exist", file=sys.stderr)
+ return -1
+ else:
+ files, tests, passed, failed, errors = load_test_files()
+
+ if files > 1:
+ file_word = "files"
else:
- load_test_files()
+ file_word = "file"
+ print("%d test %s, %d tests, %d tests passed, %d tests failed, %d errors"
+ % (files, file_word, tests, passed, failed, errors))
+ return passed - tests
parser = argparse.ArgumentParser()
@@ -121,4 +127,4 @@ parser.add_argument('-H', '--host', action='store_true',
help='Run tests against installed binaries')
parser.add_argument("test", nargs="?", help="run only the specified test file")
args = parser.parse_args()
-main()
+sys.exit(main())