summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/GNUmakefile.in10
-rw-r--r--extensions/dscp_helper.c4
-rw-r--r--extensions/generic.txlate68
-rw-r--r--extensions/libebt_802_3.t6
-rw-r--r--extensions/libebt_among.c23
-rw-r--r--extensions/libebt_arp.c89
-rw-r--r--extensions/libebt_arp.t3
-rw-r--r--extensions/libebt_dnat.txlate6
-rw-r--r--extensions/libebt_ip.c262
-rw-r--r--extensions/libebt_ip.txlate18
-rw-r--r--extensions/libebt_ip6.c111
-rw-r--r--extensions/libebt_ip6.txlate20
-rw-r--r--extensions/libebt_limit.txlate6
-rw-r--r--extensions/libebt_log.c17
-rw-r--r--extensions/libebt_log.t6
-rw-r--r--extensions/libebt_log.txlate10
-rw-r--r--extensions/libebt_mark.c2
-rw-r--r--extensions/libebt_mark.txlate11
-rw-r--r--extensions/libebt_mark.xlate11
-rw-r--r--extensions/libebt_mark_m.txlate10
-rw-r--r--extensions/libebt_nflog.c8
-rw-r--r--extensions/libebt_nflog.t2
-rw-r--r--extensions/libebt_nflog.txlate8
-rw-r--r--extensions/libebt_pkttype.txlate14
-rw-r--r--extensions/libebt_redirect.c2
-rw-r--r--extensions/libebt_redirect.t2
-rw-r--r--extensions/libebt_snat.txlate4
-rw-r--r--extensions/libebt_stp.c4
-rw-r--r--extensions/libebt_stp.t2
-rw-r--r--extensions/libebt_vlan.t4
-rw-r--r--extensions/libebt_vlan.txlate8
-rw-r--r--extensions/libip6t_LOG.c250
-rw-r--r--extensions/libip6t_LOG.txlate6
-rw-r--r--extensions/libip6t_MASQUERADE.c188
-rw-r--r--extensions/libip6t_MASQUERADE.txlate15
-rw-r--r--extensions/libip6t_NETMAP.t2
-rw-r--r--extensions/libip6t_REJECT.t2
-rw-r--r--extensions/libip6t_REJECT.txlate6
-rw-r--r--extensions/libip6t_SNAT.c308
-rw-r--r--extensions/libip6t_SNAT.t6
-rw-r--r--extensions/libip6t_SNAT.txlate8
-rw-r--r--extensions/libip6t_ah.txlate12
-rw-r--r--extensions/libip6t_dst.c6
-rw-r--r--extensions/libip6t_frag.c30
-rw-r--r--extensions/libip6t_frag.txlate12
-rw-r--r--extensions/libip6t_hbh.txlate4
-rw-r--r--extensions/libip6t_hl.txlate4
-rw-r--r--extensions/libip6t_icmp6.c97
-rw-r--r--extensions/libip6t_icmp6.txlate6
-rw-r--r--extensions/libip6t_mh.c2
-rw-r--r--extensions/libip6t_mh.txlate4
-rw-r--r--extensions/libip6t_rt.c7
-rw-r--r--extensions/libip6t_rt.txlate10
-rw-r--r--extensions/libipt_CLUSTERIP.c10
-rw-r--r--extensions/libipt_LOG.c250
-rw-r--r--extensions/libipt_LOG.txlate4
-rw-r--r--extensions/libipt_MASQUERADE.c190
-rw-r--r--extensions/libipt_MASQUERADE.txlate15
-rw-r--r--extensions/libipt_NETMAP.t2
-rw-r--r--extensions/libipt_REJECT.t2
-rw-r--r--extensions/libipt_REJECT.txlate6
-rw-r--r--extensions/libipt_SNAT.c280
-rw-r--r--extensions/libipt_SNAT.t6
-rw-r--r--extensions/libipt_SNAT.txlate10
-rw-r--r--extensions/libipt_ah.txlate6
-rw-r--r--extensions/libipt_icmp.c110
-rw-r--r--extensions/libipt_icmp.txlate8
-rw-r--r--extensions/libipt_realm.txlate8
-rw-r--r--extensions/libipt_ttl.c4
-rw-r--r--extensions/libipt_ttl.txlate4
-rw-r--r--extensions/libxt_AUDIT.txlate6
-rw-r--r--extensions/libxt_CLASSIFY.txlate6
-rw-r--r--extensions/libxt_CONNMARK.c15
-rw-r--r--extensions/libxt_CONNMARK.t8
-rw-r--r--extensions/libxt_CONNMARK.txlate17
-rw-r--r--extensions/libxt_CONNSECMARK.c3
-rw-r--r--extensions/libxt_CT.c2
-rw-r--r--extensions/libxt_DNAT.txlate24
-rw-r--r--extensions/libxt_DSCP.t2
-rw-r--r--extensions/libxt_DSCP.txlate4
-rw-r--r--extensions/libxt_IDLETIMER.t2
-rw-r--r--extensions/libxt_LOG.c204
-rw-r--r--extensions/libxt_MARK.c2
-rw-r--r--extensions/libxt_MARK.t4
-rw-r--r--extensions/libxt_MARK.txlate18
-rw-r--r--extensions/libxt_NAT.c (renamed from extensions/libxt_DNAT.c)440
-rw-r--r--extensions/libxt_NFLOG.c12
-rw-r--r--extensions/libxt_NFLOG.txlate10
-rw-r--r--extensions/libxt_NFQUEUE.c2
-rw-r--r--extensions/libxt_NFQUEUE.man2
-rw-r--r--extensions/libxt_NFQUEUE.t7
-rw-r--r--extensions/libxt_NFQUEUE.txlate6
-rw-r--r--extensions/libxt_NOTRACK.txlate2
-rw-r--r--extensions/libxt_REDIRECT.t1
-rw-r--r--extensions/libxt_REDIRECT.txlate21
-rw-r--r--extensions/libxt_SECMARK.c2
-rw-r--r--extensions/libxt_SYNPROXY.txlate2
-rw-r--r--extensions/libxt_TCPMSS.c1
-rw-r--r--extensions/libxt_TCPMSS.txlate4
-rw-r--r--extensions/libxt_TCPOPTSTRIP.c13
-rw-r--r--extensions/libxt_TEE.txlate8
-rw-r--r--extensions/libxt_TOS.c33
-rw-r--r--extensions/libxt_TOS.t12
-rw-r--r--extensions/libxt_TOS.txlate19
-rw-r--r--extensions/libxt_TRACE.txlate2
-rw-r--r--extensions/libxt_addrtype.txlate8
-rw-r--r--extensions/libxt_bpf.c3
-rw-r--r--extensions/libxt_cgroup.txlate4
-rw-r--r--extensions/libxt_cluster.txlate18
-rw-r--r--extensions/libxt_comment.c7
-rw-r--r--extensions/libxt_comment.txlate6
-rw-r--r--extensions/libxt_connbytes.txlate10
-rw-r--r--extensions/libxt_connlabel.txlate4
-rw-r--r--extensions/libxt_connlimit.t12
-rw-r--r--extensions/libxt_connlimit.txlate16
-rw-r--r--extensions/libxt_connmark.t4
-rw-r--r--extensions/libxt_connmark.txlate10
-rw-r--r--extensions/libxt_conntrack.c1
-rw-r--r--extensions/libxt_conntrack.txlate40
-rw-r--r--extensions/libxt_cpu.txlate4
-rw-r--r--extensions/libxt_dccp.c11
-rw-r--r--extensions/libxt_dccp.txlate14
-rw-r--r--extensions/libxt_devgroup.c4
-rw-r--r--extensions/libxt_devgroup.txlate12
-rw-r--r--extensions/libxt_dscp.t2
-rw-r--r--extensions/libxt_dscp.txlate4
-rw-r--r--extensions/libxt_ecn.c2
-rw-r--r--extensions/libxt_ecn.txlate20
-rw-r--r--extensions/libxt_esp.txlate8
-rw-r--r--extensions/libxt_hashlimit.c10
-rw-r--r--extensions/libxt_hashlimit.txlate4
-rw-r--r--extensions/libxt_helper.c8
-rw-r--r--extensions/libxt_helper.txlate4
-rw-r--r--extensions/libxt_icmp.h242
-rw-r--r--extensions/libxt_ipcomp.c2
-rw-r--r--extensions/libxt_ipcomp.c.man3
-rw-r--r--extensions/libxt_ipcomp.txlate4
-rw-r--r--extensions/libxt_iprange.c12
-rw-r--r--extensions/libxt_iprange.txlate10
-rw-r--r--extensions/libxt_length.t2
-rw-r--r--extensions/libxt_length.txlate8
-rw-r--r--extensions/libxt_limit.c4
-rw-r--r--extensions/libxt_limit.txlate6
-rw-r--r--extensions/libxt_mac.txlate4
-rw-r--r--extensions/libxt_mark.t3
-rw-r--r--extensions/libxt_mark.txlate4
-rw-r--r--extensions/libxt_multiport.c4
-rw-r--r--extensions/libxt_multiport.txlate10
-rw-r--r--extensions/libxt_owner.txlate6
-rw-r--r--extensions/libxt_pkttype.c2
-rw-r--r--extensions/libxt_pkttype.txlate6
-rw-r--r--extensions/libxt_policy.txlate4
-rw-r--r--extensions/libxt_quota.txlate4
-rw-r--r--extensions/libxt_recent.t4
-rw-r--r--extensions/libxt_rpfilter.txlate6
-rw-r--r--extensions/libxt_sctp.c41
-rw-r--r--extensions/libxt_sctp.txlate30
-rw-r--r--extensions/libxt_set.c59
-rw-r--r--extensions/libxt_statistic.c8
-rw-r--r--extensions/libxt_statistic.txlate6
-rw-r--r--extensions/libxt_tcp.c23
-rw-r--r--extensions/libxt_tcp.txlate24
-rw-r--r--extensions/libxt_tcpmss.txlate8
-rw-r--r--extensions/libxt_time.c12
-rw-r--r--extensions/libxt_time.txlate18
-rw-r--r--extensions/libxt_tos.t8
-rw-r--r--extensions/libxt_udp.c6
-rw-r--r--extensions/libxt_udp.txlate8
-rw-r--r--include/linux/netfilter/nf_tables.h483
-rw-r--r--include/linux/netfilter_bridge/ebt_ip.h15
-rw-r--r--include/xtables.h7
-rwxr-xr-xiptables-test.py298
-rw-r--r--iptables/ip6tables.c51
-rw-r--r--iptables/iptables-restore.c42
-rw-r--r--iptables/iptables-save.c5
-rw-r--r--iptables/iptables-xml.c26
-rw-r--r--iptables/iptables.c51
-rw-r--r--iptables/nft-arp.c68
-rw-r--r--iptables/nft-bridge.c178
-rw-r--r--iptables/nft-cache.c19
-rw-r--r--iptables/nft-cmd.c1
-rw-r--r--iptables/nft-cmd.h3
-rw-r--r--iptables/nft-ipv4.c61
-rw-r--r--iptables/nft-ipv6.c50
-rw-r--r--iptables/nft-shared.c518
-rw-r--r--iptables/nft-shared.h117
-rw-r--r--iptables/nft.c55
-rw-r--r--iptables/nft.h2
-rwxr-xr-xiptables/tests/shell/run-tests.sh3
-rwxr-xr-xiptables/tests/shell/testcases/chain/0006rename-segfault_019
-rwxr-xr-xiptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_016
-rwxr-xr-xiptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_02
-rwxr-xr-xiptables/tests/shell/testcases/ebtables/0006-flush_047
-rwxr-xr-xiptables/tests/shell/testcases/ebtables/0008-ebtables-among_098
-rwxr-xr-xiptables/tests/shell/testcases/ip6tables/0002-verbose-output_04
-rw-r--r--iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt26
-rwxr-xr-xiptables/tests/shell/testcases/nft-only/0010-native-delinearize_09
-rw-r--r--iptables/tests/shell/testcases/nft-only/0010-nft-native.txt41
-rw-r--r--iptables/xshared.c84
-rw-r--r--iptables/xshared.h11
-rw-r--r--iptables/xtables-eb-translate.c14
-rw-r--r--iptables/xtables-eb.c42
-rw-r--r--iptables/xtables-monitor.c2
-rw-r--r--iptables/xtables-restore.c33
-rw-r--r--iptables/xtables-translate.c33
-rw-r--r--iptables/xtables.c2
-rw-r--r--libiptc/libiptc.c13
-rw-r--r--libxtables/xtables.c58
-rw-r--r--libxtables/xtoptions.c4
-rwxr-xr-xxlate-test.py202
210 files changed, 3497 insertions, 3734 deletions
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index 3c68f8de..0239a06a 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -42,7 +42,7 @@ endif
pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c)))
@ENABLE_NFTABLES_TRUE@ pfb_build_mod := $(patsubst ${srcdir}/libebt_%.c,%,$(sort $(wildcard ${srcdir}/libebt_*.c)))
@ENABLE_NFTABLES_TRUE@ pfa_build_mod := $(patsubst ${srcdir}/libarpt_%.c,%,$(sort $(wildcard ${srcdir}/libarpt_*.c)))
-pfx_symlinks := NOTRACK state REDIRECT
+pfx_symlinks := NOTRACK state REDIRECT MASQUERADE SNAT DNAT
@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c)))
@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c)))
pfx_build_mod := $(filter-out @blacklist_modules@ @blacklist_x_modules@,${pfx_build_mod})
@@ -130,7 +130,13 @@ libxt_NOTRACK.so: libxt_CT.so
ln -fs $< $@
libxt_state.so: libxt_conntrack.so
ln -fs $< $@
-libxt_REDIRECT.so: libxt_DNAT.so
+libxt_REDIRECT.so: libxt_NAT.so
+ ln -fs $< $@
+libxt_MASQUERADE.so: libxt_NAT.so
+ ln -fs $< $@
+libxt_SNAT.so: libxt_NAT.so
+ ln -fs $< $@
+libxt_DNAT.so: libxt_NAT.so
ln -fs $< $@
# Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD
diff --git a/extensions/dscp_helper.c b/extensions/dscp_helper.c
index 75b1fece..1f20b2a5 100644
--- a/extensions/dscp_helper.c
+++ b/extensions/dscp_helper.c
@@ -58,7 +58,7 @@ class_to_dscp(const char *name)
}
xtables_error(PARAMETER_PROBLEM,
- "Invalid DSCP value `%s'\n", name);
+ "Invalid DSCP value `%s'", name);
}
@@ -73,7 +73,7 @@ dscp_to_name(unsigned int dscp)
return ds_classes[i].name;
xtables_error(PARAMETER_PROBLEM,
- "Invalid DSCP value `%d'\n", dscp);
+ "Invalid DSCP value `%d'", dscp);
}
#endif
diff --git a/extensions/generic.txlate b/extensions/generic.txlate
index 9ae9a5b5..c24ed156 100644
--- a/extensions/generic.txlate
+++ b/extensions/generic.txlate
@@ -1,84 +1,90 @@
iptables-translate -I OUTPUT -p udp -d 8.8.8.8 -j ACCEPT
-nft insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept
+nft 'insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept'
iptables-translate -F -t nat
nft flush table ip nat
iptables-translate -I INPUT -i iifname -s 10.0.0.0/8
-nft insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter
+nft 'insert rule ip filter INPUT iifname "iifname" ip saddr 10.0.0.0/8 counter'
iptables-translate -A INPUT -i iif+ ! -d 10.0.0.0/8
-nft add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter
+nft 'add rule ip filter INPUT iifname "iif*" ip daddr != 10.0.0.0/8 counter'
iptables-translate -I INPUT -s 10.11.12.13/255.255.0.0
-nft insert rule ip filter INPUT ip saddr 10.11.0.0/16 counter
+nft 'insert rule ip filter INPUT ip saddr 10.11.0.0/16 counter'
iptables-translate -I INPUT -s 10.11.12.13/255.0.255.0
-nft insert rule ip filter INPUT ip saddr & 255.0.255.0 == 10.0.12.0 counter
+nft 'insert rule ip filter INPUT ip saddr & 255.0.255.0 == 10.0.12.0 counter'
iptables-translate -I INPUT -s 10.11.12.13/0.255.0.255
-nft insert rule ip filter INPUT ip saddr & 0.255.0.255 == 0.11.0.13 counter
+nft 'insert rule ip filter INPUT ip saddr & 0.255.0.255 == 0.11.0.13 counter'
iptables-translate -I INPUT ! -s 10.11.12.13/0.255.0.255
-nft insert rule ip filter INPUT ip saddr & 0.255.0.255 != 0.11.0.13 counter
+nft 'insert rule ip filter INPUT ip saddr & 0.255.0.255 != 0.11.0.13 counter'
iptables-translate -I INPUT -s 0.0.0.0/16
-nft insert rule ip filter INPUT ip saddr 0.0.0.0/16 counter
+nft 'insert rule ip filter INPUT ip saddr 0.0.0.0/16 counter'
iptables-translate -I INPUT -s 0.0.0.0/0
-nft insert rule ip filter INPUT counter
+nft 'insert rule ip filter INPUT counter'
iptables-translate -I INPUT ! -s 0.0.0.0/0
-nft insert rule ip filter INPUT ip saddr != 0.0.0.0/0 counter
+nft 'insert rule ip filter INPUT ip saddr != 0.0.0.0/0 counter'
ip6tables-translate -I INPUT -i iifname -s feed::/16
-nft insert rule ip6 filter INPUT iifname "iifname" ip6 saddr feed::/16 counter
+nft 'insert rule ip6 filter INPUT iifname "iifname" ip6 saddr feed::/16 counter'
ip6tables-translate -A INPUT -i iif+ ! -d feed::/16
-nft add rule ip6 filter INPUT iifname "iif*" ip6 daddr != feed::/16 counter
+nft 'add rule ip6 filter INPUT iifname "iif*" ip6 daddr != feed::/16 counter'
ip6tables-translate -I INPUT -s feed:babe::1/ffff:ff00::
-nft insert rule ip6 filter INPUT ip6 saddr feed:ba00::/24 counter
+nft 'insert rule ip6 filter INPUT ip6 saddr feed:ba00::/24 counter'
ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/ffff:0:ffff:0:ffff:0:ffff:0
-nft insert rule ip6 filter INPUT ip6 saddr & ffff:0:ffff:0:ffff:0:ffff:0 == feed:0:c0ff:0:c0be:0:5678:0 counter
+nft 'insert rule ip6 filter INPUT ip6 saddr & ffff:0:ffff:0:ffff:0:ffff:0 == feed:0:c0ff:0:c0be:0:5678:0 counter'
ip6tables-translate -I INPUT -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff
-nft insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff == 0:babe:0:ee00:0:1234:0:90ab counter
+nft 'insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff == 0:babe:0:ee00:0:1234:0:90ab counter'
ip6tables-translate -I INPUT ! -s feed:babe:c0ff:ee00:c0be:1234:5678:90ab/0:ffff:0:ffff:0:ffff:0:ffff
-nft insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff != 0:babe:0:ee00:0:1234:0:90ab counter
+nft 'insert rule ip6 filter INPUT ip6 saddr & 0:ffff:0:ffff:0:ffff:0:ffff != 0:babe:0:ee00:0:1234:0:90ab counter'
ip6tables-translate -I INPUT -s ::/16
-nft insert rule ip6 filter INPUT ip6 saddr ::/16 counter
+nft 'insert rule ip6 filter INPUT ip6 saddr ::/16 counter'
ip6tables-translate -I INPUT -s ::/0
-nft insert rule ip6 filter INPUT counter
+nft 'insert rule ip6 filter INPUT counter'
ip6tables-translate -I INPUT ! -s ::/0
-nft insert rule ip6 filter INPUT ip6 saddr != ::/0 counter
+nft 'insert rule ip6 filter INPUT ip6 saddr != ::/0 counter'
ebtables-translate -I INPUT -i iname --logical-in ilogname -s 0:0:0:0:0:0
-nft insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter
+nft 'insert rule bridge filter INPUT iifname "iname" meta ibrname "ilogname" ether saddr 00:00:00:00:00:00 counter'
ebtables-translate -A FORWARD ! -i iname --logical-in ilogname -o out+ --logical-out lout+ -d 1:2:3:4:de:af
-nft add rule bridge filter FORWARD iifname != "iname" meta ibrname "ilogname" oifname "out*" meta obrname "lout*" ether daddr 01:02:03:04:de:af counter
+nft 'add rule bridge filter FORWARD iifname != "iname" meta ibrname "ilogname" oifname "out*" meta obrname "lout*" ether daddr 01:02:03:04:de:af counter'
ebtables-translate -I INPUT -p ip -d 1:2:3:4:5:6/ff:ff:ff:ff:00:00
-nft insert rule bridge filter INPUT ether type 0x800 ether daddr 01:02:03:04:00:00 and ff:ff:ff:ff:00:00 == 01:02:03:04:00:00 counter
+nft 'insert rule bridge filter INPUT ether type 0x800 ether daddr and ff:ff:ff:ff:00:00 == 01:02:03:04:00:00 counter'
+
+ebtables-translate -I INPUT -p Length
+nft 'insert rule bridge filter INPUT ether type < 0x0600 counter'
+
+ebtables-translate -I INPUT -p ! Length
+nft 'insert rule bridge filter INPUT ether type >= 0x0600 counter'
# asterisk is not special in iptables and it is even a valid interface name
-iptables-translate -A FORWARD -i '*' -o 'eth*foo'
-nft add rule ip filter FORWARD iifname "\*" oifname "eth\*foo" counter
+iptables-translate -A FORWARD -i * -o eth*foo
+nft 'add rule ip filter FORWARD iifname "\*" oifname "eth*foo" counter'
-# escape all asterisks but translate only the first plus character
-iptables-translate -A FORWARD -i 'eth*foo*+' -o 'eth++'
-nft add rule ip filter FORWARD iifname "eth\*foo\**" oifname "eth+*" counter
+# escape only suffix asterisk and translate only the last plus character
+iptables-translate -A FORWARD -i eth*foo*+ -o eth++
+nft 'add rule ip filter FORWARD iifname "eth*foo**" oifname "eth+*" counter'
# skip for always matching interface names
-iptables-translate -A FORWARD -i '+'
-nft add rule ip filter FORWARD counter
+iptables-translate -A FORWARD -i +
+nft 'add rule ip filter FORWARD counter'
# match against invalid interface name to simulate never matching rule
-iptables-translate -A FORWARD ! -i '+'
-nft add rule ip filter FORWARD iifname "INVAL/D" counter
+iptables-translate -A FORWARD ! -i +
+nft 'add rule ip filter FORWARD iifname "INVAL/D" counter'
diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t
index ddfb2f0a..a138f35d 100644
--- a/extensions/libebt_802_3.t
+++ b/extensions/libebt_802_3.t
@@ -1,3 +1,5 @@
:INPUT,FORWARD,OUTPUT
---802_3-sap ! 0x0a -j CONTINUE;=;OK
---802_3-type 0x000a -j RETURN;=;OK
+--802_3-sap ! 0x0a -j CONTINUE;=;FAIL
+--802_3-type 0x000a -j RETURN;=;FAIL
+-p Length --802_3-sap ! 0x0a -j CONTINUE;=;OK
+-p Length --802_3-type 0x000a -j RETURN;=;OK
diff --git a/extensions/libebt_among.c b/extensions/libebt_among.c
index 7eb898f9..a80fb804 100644
--- a/extensions/libebt_among.c
+++ b/extensions/libebt_among.c
@@ -68,12 +68,12 @@ parse_nft_among_pair(char *buf, struct nft_among_pair *pair, bool have_ip)
if (!inet_pton(AF_INET, sep + 1, &pair->in))
xtables_error(PARAMETER_PROBLEM,
- "Invalid IP address '%s'\n", sep + 1);
+ "Invalid IP address '%s'", sep + 1);
}
ether = ether_aton(buf);
if (!ether)
xtables_error(PARAMETER_PROBLEM,
- "Invalid MAC address '%s'\n", buf);
+ "Invalid MAC address '%s'", buf);
memcpy(&pair->ether, ether, sizeof(*ether));
}
@@ -119,7 +119,6 @@ static int bramong_parse(int c, char **argv, int invert,
struct xt_entry_match **match)
{
struct nft_among_data *data = (struct nft_among_data *)(*match)->data;
- struct xt_entry_match *new_match;
bool have_ip, dst = false;
size_t new_size, cnt;
struct stat stats;
@@ -152,10 +151,9 @@ static int bramong_parse(int c, char **argv, int invert,
xtables_error(PARAMETER_PROBLEM,
"File should only contain one line");
optarg[flen-1] = '\0';
- /* fall through */
+ break;
case AMONG_DST:
- if (c == AMONG_DST)
- dst = true;
+ dst = true;
/* fall through */
case AMONG_SRC:
break;
@@ -171,18 +169,17 @@ static int bramong_parse(int c, char **argv, int invert,
new_size *= sizeof(struct nft_among_pair);
new_size += XT_ALIGN(sizeof(struct xt_entry_match)) +
sizeof(struct nft_among_data);
- new_match = xtables_calloc(1, new_size);
- memcpy(new_match, *match, (*match)->u.match_size);
- new_match->u.match_size = new_size;
- data = (struct nft_among_data *)new_match->data;
+ if (new_size > (*match)->u.match_size) {
+ *match = xtables_realloc(*match, new_size);
+ (*match)->u.match_size = new_size;
+ data = (struct nft_among_data *)(*match)->data;
+ }
+
have_ip = nft_among_pairs_have_ip(optarg);
poff = nft_among_prepare_data(data, dst, cnt, invert, have_ip);
parse_nft_among_pairs(data->pairs + poff, optarg, cnt, have_ip);
- free(*match);
- *match = new_match;
-
if (c == AMONG_DST_F || c == AMONG_SRC_F) {
munmap(argv, flen);
close(fd);
diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c
index d5035b95..63a953d4 100644
--- a/extensions/libebt_arp.c
+++ b/extensions/libebt_arp.c
@@ -87,91 +87,17 @@ static void brarp_print_help(void)
#define OPT_MAC_D 0x40
#define OPT_GRAT 0x80
-static int undot_ip(char *ip, unsigned char *ip2)
-{
- char *p, *q, *end;
- long int onebyte;
- int i;
- char buf[20];
-
- strncpy(buf, ip, sizeof(buf) - 1);
-
- p = buf;
- for (i = 0; i < 3; i++) {
- if ((q = strchr(p, '.')) == NULL)
- return -1;
- *q = '\0';
- onebyte = strtol(p, &end, 10);
- if (*end != '\0' || onebyte > 255 || onebyte < 0)
- return -1;
- ip2[i] = (unsigned char)onebyte;
- p = q + 1;
- }
-
- onebyte = strtol(p, &end, 10);
- if (*end != '\0' || onebyte > 255 || onebyte < 0)
- return -1;
- ip2[3] = (unsigned char)onebyte;
-
- return 0;
-}
-
-static int ip_mask(char *mask, unsigned char *mask2)
-{
- char *end;
- long int bits;
- uint32_t mask22;
-
- if (undot_ip(mask, mask2)) {
- /* not the /a.b.c.e format, maybe the /x format */
- bits = strtol(mask, &end, 10);
- if (*end != '\0' || bits > 32 || bits < 0)
- return -1;
- if (bits != 0) {
- mask22 = htonl(0xFFFFFFFF << (32 - bits));
- memcpy(mask2, &mask22, 4);
- } else {
- mask22 = 0xFFFFFFFF;
- memcpy(mask2, &mask22, 4);
- }
- }
- return 0;
-}
-
-static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
-{
- char *p;
-
- /* first the mask */
- if ((p = strrchr(address, '/')) != NULL) {
- *p = '\0';
- if (ip_mask(p + 1, (unsigned char *)msk)) {
- xtables_error(PARAMETER_PROBLEM,
- "Problem with the IP mask '%s'", p + 1);
- return;
- }
- } else
- *msk = 0xFFFFFFFF;
-
- if (undot_ip(address, (unsigned char *)addr)) {
- xtables_error(PARAMETER_PROBLEM,
- "Problem with the IP address '%s'", address);
- return;
- }
- *addr = *addr & *msk;
-}
-
static int
brarp_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
+ struct in_addr *ipaddr, ipmask;
long int i;
char *end;
- uint32_t *addr;
- uint32_t *mask;
unsigned char *maddr;
unsigned char *mmask;
+ unsigned int ipnr;
switch (c) {
case ARP_OPCODE:
@@ -231,24 +157,25 @@ brarp_parse(int c, char **argv, int invert, unsigned int *flags,
case ARP_IP_S:
case ARP_IP_D:
+ xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
if (c == ARP_IP_S) {
EBT_CHECK_OPTION(flags, OPT_IP_S);
- addr = &arpinfo->saddr;
- mask = &arpinfo->smsk;
+ arpinfo->saddr = ipaddr->s_addr;
+ arpinfo->smsk = ipmask.s_addr;
arpinfo->bitmask |= EBT_ARP_SRC_IP;
} else {
EBT_CHECK_OPTION(flags, OPT_IP_D);
- addr = &arpinfo->daddr;
- mask = &arpinfo->dmsk;
+ arpinfo->daddr = ipaddr->s_addr;
+ arpinfo->dmsk = ipmask.s_addr;
arpinfo->bitmask |= EBT_ARP_DST_IP;
}
+ free(ipaddr);
if (invert) {
if (c == ARP_IP_S)
arpinfo->invflags |= EBT_ARP_SRC_IP;
else
arpinfo->invflags |= EBT_ARP_DST_IP;
}
- ebt_parse_ip_address(optarg, addr, mask);
break;
case ARP_MAC_S:
case ARP_MAC_D:
diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t
index 14ff0f09..96fbce90 100644
--- a/extensions/libebt_arp.t
+++ b/extensions/libebt_arp.t
@@ -6,6 +6,9 @@
-p ARP ! --arp-ip-dst 1.2.3.4;-p ARP --arp-ip-dst ! 1.2.3.4 -j CONTINUE;OK
-p ARP --arp-ip-src ! 0.0.0.0;=;OK
-p ARP --arp-ip-dst ! 0.0.0.0/8;=;OK
+-p ARP --arp-ip-src ! 1.2.3.4/32;-p ARP --arp-ip-src ! 1.2.3.4;OK
+-p ARP --arp-ip-src ! 1.2.3.4/255.255.255.0;-p ARP --arp-ip-src ! 1.2.3.0/24;OK
+-p ARP --arp-ip-src ! 1.2.3.4/255.0.255.255;-p ARP --arp-ip-src ! 1.0.3.4/255.0.255.255;OK
-p ARP --arp-mac-src 00:de:ad:be:ef:00;=;OK
-p ARP --arp-mac-dst de:ad:be:ef:00:00/ff:ff:ff:ff:00:00;=;OK
-p ARP --arp-gratuitous;=;OK
diff --git a/extensions/libebt_dnat.txlate b/extensions/libebt_dnat.txlate
index 2652dd55..9f305c76 100644
--- a/extensions/libebt_dnat.txlate
+++ b/extensions/libebt_dnat.txlate
@@ -1,8 +1,8 @@
ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff
-nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter
+nft 'add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter'
ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT
-nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter
+nft 'add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff accept counter'
ebtables-translate -t nat -A PREROUTING -i someport --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE
-nft add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff continue counter
+nft 'add rule bridge nat PREROUTING iifname "someport" ether daddr set de:ad:0:be:ee:ff continue counter'
diff --git a/extensions/libebt_ip.c b/extensions/libebt_ip.c
index 51649ffb..fd87dae7 100644
--- a/extensions/libebt_ip.c
+++ b/extensions/libebt_ip.c
@@ -20,40 +20,10 @@
#include <netdb.h>
#include <inttypes.h>
#include <xtables.h>
+#include <linux/netfilter_bridge/ebt_ip.h>
#include "libxt_icmp.h"
-#define EBT_IP_SOURCE 0x01
-#define EBT_IP_DEST 0x02
-#define EBT_IP_TOS 0x04
-#define EBT_IP_PROTO 0x08
-#define EBT_IP_SPORT 0x10
-#define EBT_IP_DPORT 0x20
-#define EBT_IP_ICMP 0x40
-#define EBT_IP_IGMP 0x80
-#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
- EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
-
-struct ebt_ip_info {
- __be32 saddr;
- __be32 daddr;
- __be32 smsk;
- __be32 dmsk;
- __u8 tos;
- __u8 protocol;
- __u8 bitmask;
- __u8 invflags;
- union {
- __u16 sport[2];
- __u8 icmp_type[2];
- __u8 igmp_type[2];
- };
- union {
- __u16 dport[2];
- __u8 icmp_code[2];
- };
-};
-
#define IP_SOURCE '1'
#define IP_DEST '2'
#define IP_EBT_TOS '3' /* include/bits/in.h seems to already define IP_TOS */
@@ -80,68 +50,6 @@ static const struct option brip_opts[] = {
XT_GETOPT_TABLEEND,
};
-static const struct xt_icmp_names icmp_codes[] = {
- { "echo-reply", 0, 0, 0xFF },
- /* Alias */ { "pong", 0, 0, 0xFF },
-
- { "destination-unreachable", 3, 0, 0xFF },
- { "network-unreachable", 3, 0, 0 },
- { "host-unreachable", 3, 1, 1 },
- { "protocol-unreachable", 3, 2, 2 },
- { "port-unreachable", 3, 3, 3 },
- { "fragmentation-needed", 3, 4, 4 },
- { "source-route-failed", 3, 5, 5 },
- { "network-unknown", 3, 6, 6 },
- { "host-unknown", 3, 7, 7 },
- { "network-prohibited", 3, 9, 9 },
- { "host-prohibited", 3, 10, 10 },
- { "TOS-network-unreachable", 3, 11, 11 },
- { "TOS-host-unreachable", 3, 12, 12 },
- { "communication-prohibited", 3, 13, 13 },
- { "host-precedence-violation", 3, 14, 14 },
- { "precedence-cutoff", 3, 15, 15 },
-
- { "source-quench", 4, 0, 0xFF },
-
- { "redirect", 5, 0, 0xFF },
- { "network-redirect", 5, 0, 0 },
- { "host-redirect", 5, 1, 1 },
- { "TOS-network-redirect", 5, 2, 2 },
- { "TOS-host-redirect", 5, 3, 3 },
-
- { "echo-request", 8, 0, 0xFF },
- /* Alias */ { "ping", 8, 0, 0xFF },
-
- { "router-advertisement", 9, 0, 0xFF },
-
- { "router-solicitation", 10, 0, 0xFF },
-
- { "time-exceeded", 11, 0, 0xFF },
- /* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
- { "ttl-zero-during-transit", 11, 0, 0 },
- { "ttl-zero-during-reassembly", 11, 1, 1 },
-
- { "parameter-problem", 12, 0, 0xFF },
- { "ip-header-bad", 12, 0, 0 },
- { "required-option-missing", 12, 1, 1 },
-
- { "timestamp-request", 13, 0, 0xFF },
-
- { "timestamp-reply", 14, 0, 0xFF },
-
- { "address-mask-request", 17, 0, 0xFF },
-
- { "address-mask-reply", 18, 0, 0xFF }
-};
-
-static const struct xt_icmp_names igmp_types[] = {
- { "membership-query", 0x11 },
- { "membership-report-v1", 0x12 },
- { "membership-report-v2", 0x16 },
- { "leave-group", 0x17 },
- { "membership-report-v3", 0x22 },
-};
-
static void brip_print_help(void)
{
printf(
@@ -194,156 +102,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
}
/* original code from ebtables: useful_functions.c */
-static int undot_ip(char *ip, unsigned char *ip2)
-{
- char *p, *q, *end;
- long int onebyte;
- int i;
- char buf[20];
-
- strncpy(buf, ip, sizeof(buf) - 1);
-
- p = buf;
- for (i = 0; i < 3; i++) {
- if ((q = strchr(p, '.')) == NULL)
- return -1;
- *q = '\0';
- onebyte = strtol(p, &end, 10);
- if (*end != '\0' || onebyte > 255 || onebyte < 0)
- return -1;
- ip2[i] = (unsigned char)onebyte;
- p = q + 1;
- }
-
- onebyte = strtol(p, &end, 10);
- if (*end != '\0' || onebyte > 255 || onebyte < 0)
- return -1;
- ip2[3] = (unsigned char)onebyte;
-
- return 0;
-}
-
-static int ip_mask(char *mask, unsigned char *mask2)
-{
- char *end;
- long int bits;
- uint32_t mask22;
-
- if (undot_ip(mask, mask2)) {
- /* not the /a.b.c.e format, maybe the /x format */
- bits = strtol(mask, &end, 10);
- if (*end != '\0' || bits > 32 || bits < 0)
- return -1;
- if (bits != 0) {
- mask22 = htonl(0xFFFFFFFF << (32 - bits));
- memcpy(mask2, &mask22, 4);
- } else {
- mask22 = 0xFFFFFFFF;
- memcpy(mask2, &mask22, 4);
- }
- }
- return 0;
-}
-
-static void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk)
-{
- char *p;
-
- /* first the mask */
- if ((p = strrchr(address, '/')) != NULL) {
- *p = '\0';
- if (ip_mask(p + 1, (unsigned char *)msk)) {
- xtables_error(PARAMETER_PROBLEM,
- "Problem with the IP mask '%s'", p + 1);
- return;
- }
- } else
- *msk = 0xFFFFFFFF;
-
- if (undot_ip(address, (unsigned char *)addr)) {
- xtables_error(PARAMETER_PROBLEM,
- "Problem with the IP address '%s'", address);
- return;
- }
- *addr = *addr & *msk;
-}
-
-static char *parse_range(const char *str, unsigned int res[])
-{
- char *next;
-
- if (!xtables_strtoui(str, &next, &res[0], 0, 255))
- return NULL;
-
- res[1] = res[0];
- if (*next == ':') {
- str = next + 1;
- if (!xtables_strtoui(str, &next, &res[1], 0, 255))
- return NULL;
- }
-
- return next;
-}
-
-static int ebt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
- const char *icmptype, uint8_t type[], uint8_t code[])
-{
- unsigned int match = n_codes;
- unsigned int i, number[2];
-
- for (i = 0; i < n_codes; i++) {
- if (strncasecmp(codes[i].name, icmptype, strlen(icmptype)))
- continue;
- if (match != n_codes)
- xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMP type `%s':"
- " `%s' or `%s'?",
- icmptype, codes[match].name,
- codes[i].name);
- match = i;
- }
-
- if (match < n_codes) {
- type[0] = type[1] = codes[match].type;
- if (code) {
- code[0] = codes[match].code_min;
- code[1] = codes[match].code_max;
- }
- } else {
- char *next = parse_range(icmptype, number);
- if (!next) {
- xtables_error(PARAMETER_PROBLEM, "Unknown ICMP type `%s'",
- icmptype);
- return -1;
- }
-
- type[0] = (uint8_t) number[0];
- type[1] = (uint8_t) number[1];
- switch (*next) {
- case 0:
- if (code) {
- code[0] = 0;
- code[1] = 255;
- }
- return 0;
- case '/':
- if (code) {
- next = parse_range(next+1, number);
- code[0] = (uint8_t) number[0];
- code[1] = (uint8_t) number[1];
- if (next == NULL)
- return -1;
- if (next && *next == 0)
- return 0;
- }
- /* fallthrough */
- default:
- xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
- return -1;
- }
- }
- return 0;
-}
-
static void print_icmp_code(uint8_t *code)
{
if (!code)
@@ -385,18 +143,26 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct ebt_ip_info *info = (struct ebt_ip_info *)(*match)->data;
+ struct in_addr *ipaddr, ipmask;
+ unsigned int ipnr;
switch (c) {
case IP_SOURCE:
if (invert)
info->invflags |= EBT_IP_SOURCE;
- ebt_parse_ip_address(optarg, &info->saddr, &info->smsk);
+ xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
+ info->saddr = ipaddr->s_addr;
+ info->smsk = ipmask.s_addr;
+ free(ipaddr);
info->bitmask |= EBT_IP_SOURCE;
break;
case IP_DEST:
if (invert)
info->invflags |= EBT_IP_DEST;
- ebt_parse_ip_address(optarg, &info->daddr, &info->dmsk);
+ xtables_ipparse_any(optarg, &ipaddr, &ipmask, &ipnr);
+ info->daddr = ipaddr->s_addr;
+ info->dmsk = ipmask.s_addr;
+ free(ipaddr);
info->bitmask |= EBT_IP_DEST;
break;
case IP_SPORT:
@@ -414,15 +180,13 @@ brip_parse(int c, char **argv, int invert, unsigned int *flags,
case IP_EBT_ICMP:
if (invert)
info->invflags |= EBT_IP_ICMP;
- ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg,
- info->icmp_type, info->icmp_code);
+ ebt_parse_icmp(optarg, info->icmp_type, info->icmp_code);
info->bitmask |= EBT_IP_ICMP;
break;
case IP_EBT_IGMP:
if (invert)
info->invflags |= EBT_IP_IGMP;
- ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg,
- info->igmp_type, NULL);
+ ebt_parse_igmp(optarg, info->igmp_type);
info->bitmask |= EBT_IP_IGMP;
break;
case IP_EBT_TOS: {
diff --git a/extensions/libebt_ip.txlate b/extensions/libebt_ip.txlate
index b5882c34..75c1db24 100644
--- a/extensions/libebt_ip.txlate
+++ b/extensions/libebt_ip.txlate
@@ -1,26 +1,26 @@
ebtables-translate -A FORWARD -p ip --ip-src ! 192.168.0.0/24 -j ACCEPT
-nft add rule bridge filter FORWARD ip saddr != 192.168.0.0/24 counter accept
+nft 'add rule bridge filter FORWARD ip saddr != 192.168.0.0/24 counter accept'
ebtables-translate -I FORWARD -p ip --ip-dst 10.0.0.1
-nft insert rule bridge filter FORWARD ip daddr 10.0.0.1 counter
+nft 'insert rule bridge filter FORWARD ip daddr 10.0.0.1 counter'
ebtables-translate -I OUTPUT 3 -p ip -o eth0 --ip-tos 0xff
-nft insert rule bridge filter OUTPUT oifname "eth0" ip dscp 0x3f counter
+nft 'insert rule bridge filter OUTPUT oifname "eth0" ip dscp 0x3f counter'
ebtables-translate -A FORWARD -p ip --ip-proto tcp --ip-dport 22
-nft add rule bridge filter FORWARD tcp dport 22 counter
+nft 'add rule bridge filter FORWARD tcp dport 22 counter'
ebtables-translate -A FORWARD -p ip --ip-proto udp --ip-sport 1024:65535
-nft add rule bridge filter FORWARD udp sport 1024-65535 counter
+nft 'add rule bridge filter FORWARD udp sport 1024-65535 counter'
ebtables-translate -A FORWARD -p ip --ip-proto 253
-nft add rule bridge filter FORWARD ip protocol 253 counter
+nft 'add rule bridge filter FORWARD ip protocol 253 counter'
ebtables-translate -A FORWARD -p ip --ip-protocol icmp --ip-icmp-type "echo-request"
-nft add rule bridge filter FORWARD icmp type 8 counter
+nft 'add rule bridge filter FORWARD icmp type 8 counter'
ebtables-translate -A FORWARD -p ip --ip-proto icmp --ip-icmp-type 1/1
-nft add rule bridge filter FORWARD icmp type 1 icmp code 1 counter
+nft 'add rule bridge filter FORWARD icmp type 1 icmp code 1 counter'
ebtables-translate -A FORWARD -p ip --ip-protocol icmp --ip-icmp-type ! 1:10
-nft add rule bridge filter FORWARD icmp type != 1-10 counter
+nft 'add rule bridge filter FORWARD icmp type != 1-10 counter'
diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c
index a686a285..18bb2720 100644
--- a/extensions/libebt_ip6.c
+++ b/extensions/libebt_ip6.c
@@ -49,44 +49,6 @@ static const struct option brip6_opts[] = {
XT_GETOPT_TABLEEND,
};
-static const struct xt_icmp_names icmpv6_codes[] = {
- { "destination-unreachable", 1, 0, 0xFF },
- { "no-route", 1, 0, 0 },
- { "communication-prohibited", 1, 1, 1 },
- { "address-unreachable", 1, 3, 3 },
- { "port-unreachable", 1, 4, 4 },
-
- { "packet-too-big", 2, 0, 0xFF },
-
- { "time-exceeded", 3, 0, 0xFF },
- /* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
- { "ttl-zero-during-transit", 3, 0, 0 },
- { "ttl-zero-during-reassembly", 3, 1, 1 },
-
- { "parameter-problem", 4, 0, 0xFF },
- { "bad-header", 4, 0, 0 },
- { "unknown-header-type", 4, 1, 1 },
- { "unknown-option", 4, 2, 2 },
-
- { "echo-request", 128, 0, 0xFF },
- /* Alias */ { "ping", 128, 0, 0xFF },
-
- { "echo-reply", 129, 0, 0xFF },
- /* Alias */ { "pong", 129, 0, 0xFF },
-
- { "router-solicitation", 133, 0, 0xFF },
-
- { "router-advertisement", 134, 0, 0xFF },
-
- { "neighbour-solicitation", 135, 0, 0xFF },
- /* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
-
- { "neighbour-advertisement", 136, 0, 0xFF },
- /* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
-
- { "redirect", 137, 0, 0xFF },
-};
-
static void
parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
{
@@ -110,76 +72,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports)
free(buffer);
}
-static char *parse_range(const char *str, unsigned int res[])
-{
- char *next;
-
- if (!xtables_strtoui(str, &next, &res[0], 0, 255))
- return NULL;
-
- res[1] = res[0];
- if (*next == ':') {
- str = next + 1;
- if (!xtables_strtoui(str, &next, &res[1], 0, 255))
- return NULL;
- }
-
- return next;
-}
-
-static int
-parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[])
-{
- static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
- unsigned int match = limit;
- unsigned int i, number[2];
-
- for (i = 0; i < limit; i++) {
- if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type)))
- continue;
- if (match != limit)
- xtables_error(PARAMETER_PROBLEM, "Ambiguous ICMPv6 type `%s':"
- " `%s' or `%s'?",
- icmpv6type, icmpv6_codes[match].name,
- icmpv6_codes[i].name);
- match = i;
- }
-
- if (match < limit) {
- type[0] = type[1] = icmpv6_codes[match].type;
- code[0] = icmpv6_codes[match].code_min;
- code[1] = icmpv6_codes[match].code_max;
- } else {
- char *next = parse_range(icmpv6type, number);
- if (!next) {
- xtables_error(PARAMETER_PROBLEM, "Unknown ICMPv6 type `%s'",
- icmpv6type);
- return -1;
- }
- type[0] = (uint8_t) number[0];
- type[1] = (uint8_t) number[1];
- switch (*next) {
- case 0:
- code[0] = 0;
- code[1] = 255;
- return 0;
- case '/':
- next = parse_range(next+1, number);
- code[0] = (uint8_t) number[0];
- code[1] = (uint8_t) number[1];
- if (next == NULL)
- return -1;
- if (next && *next == 0)
- return 0;
- /* fallthrough */
- default:
- xtables_error(PARAMETER_PROBLEM, "unknown character %c", *next);
- return -1;
- }
- }
- return 0;
-}
-
static void print_port_range(uint16_t *ports)
{
if (ports[0] == ports[1])
@@ -304,8 +196,7 @@ brip6_parse(int c, char **argv, int invert, unsigned int *flags,
case IP_ICMP6:
if (invert)
info->invflags |= EBT_IP6_ICMP6;
- if (parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code))
- return 0;
+ ebt_parse_icmpv6(optarg, info->icmpv6_type, info->icmpv6_code);
info->bitmask |= EBT_IP6_ICMP6;
break;
case IP_TCLASS:
diff --git a/extensions/libebt_ip6.txlate b/extensions/libebt_ip6.txlate
index 0271734c..0debbe12 100644
--- a/extensions/libebt_ip6.txlate
+++ b/extensions/libebt_ip6.txlate
@@ -1,29 +1,29 @@
ebtables-translate -A FORWARD -p ip6 --ip6-src ! dead::beef/64 -j ACCEPT
-nft add rule bridge filter FORWARD ip6 saddr != dead::/64 counter accept
+nft 'add rule bridge filter FORWARD ip6 saddr != dead::/64 counter accept'
ebtables-translate -A FORWARD -p ip6 ! --ip6-dst dead:beef::/64 -j ACCEPT
-nft add rule bridge filter FORWARD ip6 daddr != dead:beef::/64 counter accept
+nft 'add rule bridge filter FORWARD ip6 daddr != dead:beef::/64 counter accept'
ebtables-translate -I FORWARD -p ip6 --ip6-dst f00:ba::
-nft insert rule bridge filter FORWARD ip6 daddr f00:ba:: counter
+nft 'insert rule bridge filter FORWARD ip6 daddr f00:ba:: counter'
ebtables-translate -I OUTPUT -o eth0 -p ip6 --ip6-tclass 0xff
-nft insert rule bridge filter OUTPUT oifname "eth0" ip6 dscp 0x3f counter
+nft 'insert rule bridge filter OUTPUT oifname "eth0" ip6 dscp 0x3f counter'
ebtables-translate -A FORWARD -p ip6 --ip6-proto tcp --ip6-dport 22
-nft add rule bridge filter FORWARD ether type ip6 tcp dport 22 counter
+nft 'add rule bridge filter FORWARD ether type ip6 tcp dport 22 counter'
ebtables-translate -A FORWARD -p ip6 --ip6-proto udp --ip6-sport 1024:65535
-nft add rule bridge filter FORWARD ether type ip6 udp sport 1024-65535 counter
+nft 'add rule bridge filter FORWARD ether type ip6 udp sport 1024-65535 counter'
ebtables-translate -A FORWARD -p ip6 --ip6-proto 253
-nft add rule bridge filter FORWARD ether type ip6 meta l4proto 253 counter
+nft 'add rule bridge filter FORWARD ether type ip6 meta l4proto 253 counter'
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type "echo-request"
-nft add rule bridge filter FORWARD icmpv6 type 128 counter
+nft 'add rule bridge filter FORWARD icmpv6 type 128 counter'
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1
-nft add rule bridge filter FORWARD icmpv6 type 1 icmpv6 code 1 counter
+nft 'add rule bridge filter FORWARD icmpv6 type 1 icmpv6 code 1 counter'
ebtables-translate -A FORWARD -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type ! 1:10
-nft add rule bridge filter FORWARD icmpv6 type != 1-10 counter
+nft 'add rule bridge filter FORWARD icmpv6 type != 1-10 counter'
diff --git a/extensions/libebt_limit.txlate b/extensions/libebt_limit.txlate
index b6af15d5..adcce3ed 100644
--- a/extensions/libebt_limit.txlate
+++ b/extensions/libebt_limit.txlate
@@ -1,8 +1,8 @@
ebtables-translate -A INPUT --limit 3/m --limit-burst 3
-nft add rule bridge filter INPUT limit rate 3/minute burst 3 packets counter
+nft 'add rule bridge filter INPUT limit rate 3/minute burst 3 packets counter'
ebtables-translate -A INPUT --limit 10/s --limit-burst 5
-nft add rule bridge filter INPUT limit rate 10/second burst 5 packets counter
+nft 'add rule bridge filter INPUT limit rate 10/second burst 5 packets counter'
ebtables-translate -A INPUT --limit 10/s --limit-burst 0
-nft add rule bridge filter INPUT limit rate 10/second counter
+nft 'add rule bridge filter INPUT limit rate 10/second counter'
diff --git a/extensions/libebt_log.c b/extensions/libebt_log.c
index 8858cf0e..04506219 100644
--- a/extensions/libebt_log.c
+++ b/extensions/libebt_log.c
@@ -161,9 +161,10 @@ static void brlog_print(const void *ip, const struct xt_entry_target *target,
{
struct ebt_log_info *loginfo = (struct ebt_log_info *)target->data;
- printf("--log-level %s --log-prefix \"%s\"",
- eight_priority[loginfo->loglevel].c_name,
- loginfo->prefix);
+ printf("--log-level %s", eight_priority[loginfo->loglevel].c_name);
+
+ if (loginfo->prefix[0])
+ printf(" --log-prefix \"%s\"", loginfo->prefix);
if (loginfo->bitmask & EBT_LOG_IP)
printf(" --log-ip");
@@ -180,16 +181,14 @@ static int brlog_xlate(struct xt_xlate *xl,
const struct ebt_log_info *loginfo = (const void *)params->target->data;
xt_xlate_add(xl, "log");
- if (loginfo->prefix[0]) {
- if (params->escape_quotes)
- xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix);
- else
- xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
- }
+ if (loginfo->prefix[0])
+ xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
if (loginfo->loglevel != LOG_DEFAULT_LEVEL)
xt_xlate_add(xl, " level %s", eight_priority[loginfo->loglevel].c_name);
+ /* ebt_log always decodes MAC header, nft_log always decodes upper header -
+ * so set flags ether and ignore EBT_LOG_IP, EBT_LOG_ARP and EBT_LOG_IP6 */
xt_xlate_add(xl, " flags ether ");
return 1;
diff --git a/extensions/libebt_log.t b/extensions/libebt_log.t
index a0df6169..e6adbd3b 100644
--- a/extensions/libebt_log.t
+++ b/extensions/libebt_log.t
@@ -1,6 +1,6 @@
:INPUT,FORWARD,OUTPUT
---log;=;OK
+--log;--log-level notice;OK
--log-level crit;=;OK
---log-level 1;--log-level alert --log-prefix "";OK
---log-level emerg --log-ip --log-arp --log-ip6;--log-level emerg --log-prefix "" --log-ip --log-arp --log-ip6 -j CONTINUE;OK
+--log-level 1;--log-level alert;OK
+--log-level emerg --log-ip --log-arp --log-ip6;=;OK
--log-level crit --log-ip --log-arp --log-ip6 --log-prefix foo;--log-level crit --log-prefix "foo" --log-ip --log-arp --log-ip6 -j CONTINUE;OK
diff --git a/extensions/libebt_log.txlate b/extensions/libebt_log.txlate
index 7ef8d5e1..9847e4c1 100644
--- a/extensions/libebt_log.txlate
+++ b/extensions/libebt_log.txlate
@@ -1,15 +1,15 @@
ebtables-translate -A INPUT --log
-nft add rule bridge filter INPUT log level notice flags ether counter
+nft 'add rule bridge filter INPUT log level notice flags ether counter'
ebtables-translate -A INPUT --log-level 1
-nft add rule bridge filter INPUT log level alert flags ether counter
+nft 'add rule bridge filter INPUT log level alert flags ether counter'
ebtables-translate -A INPUT --log-level crit
-nft add rule bridge filter INPUT log level crit flags ether counter
+nft 'add rule bridge filter INPUT log level crit flags ether counter'
ebtables-translate -A INPUT --log-level emerg --log-ip --log-arp --log-ip6
-nft add rule bridge filter INPUT log level emerg flags ether counter
+nft 'add rule bridge filter INPUT log level emerg flags ether counter'
ebtables-translate -A INPUT --log-level crit --log-ip --log-arp --log-ip6 --log-prefix foo
-nft add rule bridge filter INPUT log prefix "foo" level crit flags ether counter
+nft 'add rule bridge filter INPUT log prefix "foo" level crit flags ether counter'
diff --git a/extensions/libebt_mark.c b/extensions/libebt_mark.c
index 423c5c91..40e49618 100644
--- a/extensions/libebt_mark.c
+++ b/extensions/libebt_mark.c
@@ -201,7 +201,7 @@ static int brmark_xlate(struct xt_xlate *xl,
return 0;
}
- tmp = info->target & EBT_VERDICT_BITS;
+ tmp = info->target | ~EBT_VERDICT_BITS;
xt_xlate_add(xl, "0x%lx %s ", info->mark, brmark_verdict(tmp));
return 1;
}
diff --git a/extensions/libebt_mark.txlate b/extensions/libebt_mark.txlate
new file mode 100644
index 00000000..d006e8ac
--- /dev/null
+++ b/extensions/libebt_mark.txlate
@@ -0,0 +1,11 @@
+ebtables-translate -A INPUT --mark-set 42
+nft 'add rule bridge filter INPUT meta mark set 0x2a accept counter'
+
+ebtables-translate -A INPUT --mark-or 42 --mark-target RETURN
+nft 'add rule bridge filter INPUT meta mark set meta mark or 0x2a return counter'
+
+ebtables-translate -A INPUT --mark-and 42 --mark-target ACCEPT
+nft 'add rule bridge filter INPUT meta mark set meta mark and 0x2a accept counter'
+
+ebtables-translate -A INPUT --mark-xor 42 --mark-target DROP
+nft 'add rule bridge filter INPUT meta mark set meta mark xor 0x2a drop counter'
diff --git a/extensions/libebt_mark.xlate b/extensions/libebt_mark.xlate
deleted file mode 100644
index e0982a1e..00000000
--- a/extensions/libebt_mark.xlate
+++ /dev/null
@@ -1,11 +0,0 @@
-ebtables-translate -A INPUT --mark-set 42
-nft add rule bridge filter INPUT mark set 0x2a counter
-
-ebtables-translate -A INPUT --mark-or 42 --mark-target RETURN
-nft add rule bridge filter INPUT mark set mark or 0x2a counter return
-
-ebtables-translate -A INPUT --mark-and 42 --mark-target ACCEPT
-nft add rule bridge filter INPUT mark set mark and 0x2a counter accept
-
-ebtables-translate -A INPUT --mark-xor 42 --mark-target DROP
-nft add rule bridge filter INPUT mark set mark xor 0x2a counter drop
diff --git a/extensions/libebt_mark_m.txlate b/extensions/libebt_mark_m.txlate
index 7b44425b..2981a564 100644
--- a/extensions/libebt_mark_m.txlate
+++ b/extensions/libebt_mark_m.txlate
@@ -1,14 +1,14 @@
ebtables-translate -A INPUT --mark 42
-nft add rule bridge filter INPUT meta mark 0x2a counter
+nft 'add rule bridge filter INPUT meta mark 0x2a counter'
ebtables-translate -A INPUT ! --mark 42
-nft add rule bridge filter INPUT meta mark != 0x2a counter
+nft 'add rule bridge filter INPUT meta mark != 0x2a counter'
ebtables-translate -A INPUT --mark ! 42
-nft add rule bridge filter INPUT meta mark != 0x2a counter
+nft 'add rule bridge filter INPUT meta mark != 0x2a counter'
ebtables-translate -A INPUT --mark ! 0x1/0xff
-nft add rule bridge filter INPUT meta mark and 0xff != 0x1 counter
+nft 'add rule bridge filter INPUT meta mark and 0xff != 0x1 counter'
ebtables-translate -A INPUT --mark /0x02
-nft add rule bridge filter INPUT meta mark and 0x2 != 0 counter
+nft 'add rule bridge filter INPUT meta mark and 0x2 != 0 counter'
diff --git a/extensions/libebt_nflog.c b/extensions/libebt_nflog.c
index 9801f358..115e15da 100644
--- a/extensions/libebt_nflog.c
+++ b/extensions/libebt_nflog.c
@@ -130,12 +130,8 @@ static int brnflog_xlate(struct xt_xlate *xl,
const struct ebt_nflog_info *info = (void *)params->target->data;
xt_xlate_add(xl, "log ");
- if (info->prefix[0] != '\0') {
- if (params->escape_quotes)
- xt_xlate_add(xl, "prefix \\\"%s\\\" ", info->prefix);
- else
- xt_xlate_add(xl, "prefix \"%s\" ", info->prefix);
- }
+ if (info->prefix[0] != '\0')
+ xt_xlate_add(xl, "prefix \"%s\" ", info->prefix);
xt_xlate_add(xl, "group %u ", info->group);
diff --git a/extensions/libebt_nflog.t b/extensions/libebt_nflog.t
index f867df30..e98d8f5f 100644
--- a/extensions/libebt_nflog.t
+++ b/extensions/libebt_nflog.t
@@ -1,5 +1,5 @@
:INPUT,FORWARD,OUTPUT
---nflog;=;OK
+--nflog;--nflog-group 1;OK
--nflog-group 42;=;OK
--nflog-range 42;--nflog-group 1 --nflog-range 42 -j CONTINUE;OK
--nflog-threshold 100 --nflog-prefix foo;--nflog-prefix "foo" --nflog-group 1 --nflog-threshold 100 -j CONTINUE;OK
diff --git a/extensions/libebt_nflog.txlate b/extensions/libebt_nflog.txlate
index bc3f5364..6f292fd2 100644
--- a/extensions/libebt_nflog.txlate
+++ b/extensions/libebt_nflog.txlate
@@ -1,11 +1,11 @@
ebtables-translate -A INPUT --nflog
-nft add rule bridge filter INPUT log group 1 counter
+nft 'add rule bridge filter INPUT log group 1 counter'
ebtables-translate -A INPUT --nflog-group 42
-nft add rule bridge filter INPUT log group 42 counter
+nft 'add rule bridge filter INPUT log group 42 counter'
ebtables-translate -A INPUT --nflog-range 42
-nft add rule bridge filter INPUT log group 1 snaplen 42 counter
+nft 'add rule bridge filter INPUT log group 1 snaplen 42 counter'
ebtables-translate -A INPUT --nflog-threshold 100 --nflog-prefix foo
-nft add rule bridge filter INPUT log prefix "foo" group 1 queue-threshold 100 counter
+nft 'add rule bridge filter INPUT log prefix "foo" group 1 queue-threshold 100 counter'
diff --git a/extensions/libebt_pkttype.txlate b/extensions/libebt_pkttype.txlate
index 94d016d9..6a828a98 100644
--- a/extensions/libebt_pkttype.txlate
+++ b/extensions/libebt_pkttype.txlate
@@ -1,20 +1,20 @@
ebtables-translate -A INPUT --pkttype-type host
-nft add rule bridge filter INPUT meta pkttype host counter
+nft 'add rule bridge filter INPUT meta pkttype host counter'
ebtables-translate -A INPUT ! --pkttype-type broadcast
-nft add rule bridge filter INPUT meta pkttype != broadcast counter
+nft 'add rule bridge filter INPUT meta pkttype != broadcast counter'
ebtables-translate -A INPUT --pkttype-type ! multicast
-nft add rule bridge filter INPUT meta pkttype != multicast counter
+nft 'add rule bridge filter INPUT meta pkttype != multicast counter'
ebtables-translate -A INPUT --pkttype-type otherhost
-nft add rule bridge filter INPUT meta pkttype other counter
+nft 'add rule bridge filter INPUT meta pkttype other counter'
ebtables-translate -A INPUT --pkttype-type outgoing
-nft add rule bridge filter INPUT meta pkttype 4 counter
+nft 'add rule bridge filter INPUT meta pkttype 4 counter'
ebtables-translate -A INPUT --pkttype-type loopback
-nft add rule bridge filter INPUT meta pkttype 5 counter
+nft 'add rule bridge filter INPUT meta pkttype 5 counter'
ebtables-translate -A INPUT --pkttype-type fastroute
-nft add rule bridge filter INPUT meta pkttype 6 counter
+nft 'add rule bridge filter INPUT meta pkttype 6 counter'
diff --git a/extensions/libebt_redirect.c b/extensions/libebt_redirect.c
index 6e653997..4d4c7a02 100644
--- a/extensions/libebt_redirect.c
+++ b/extensions/libebt_redirect.c
@@ -86,7 +86,7 @@ static int brredir_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, "meta set pkttype host");
if (red->target != EBT_ACCEPT)
xt_xlate_add(xl, " %s ", brredir_verdict(red->target));
- return 0;
+ return 1;
}
static struct xtables_target brredirect_target = {
diff --git a/extensions/libebt_redirect.t b/extensions/libebt_redirect.t
index 23858afa..58492b79 100644
--- a/extensions/libebt_redirect.t
+++ b/extensions/libebt_redirect.t
@@ -1,4 +1,4 @@
:PREROUTING
*nat
--j redirect;=;OK
+-j redirect ;=;OK
-j redirect --redirect-target RETURN;=;OK
diff --git a/extensions/libebt_snat.txlate b/extensions/libebt_snat.txlate
index 0d846024..857a6052 100644
--- a/extensions/libebt_snat.txlate
+++ b/extensions/libebt_snat.txlate
@@ -1,5 +1,5 @@
ebtables-translate -t nat -A POSTROUTING -s 0:0:0:0:0:0 -o someport+ --to-source de:ad:00:be:ee:ff
-nft add rule bridge nat POSTROUTING oifname "someport*" ether saddr 00:00:00:00:00:00 ether saddr set de:ad:0:be:ee:ff accept counter
+nft 'add rule bridge nat POSTROUTING oifname "someport*" ether saddr 00:00:00:00:00:00 ether saddr set de:ad:0:be:ee:ff accept counter'
ebtables-translate -t nat -A POSTROUTING -o someport --to-src de:ad:00:be:ee:ff --snat-target CONTINUE
-nft add rule bridge nat POSTROUTING oifname "someport" ether saddr set de:ad:0:be:ee:ff continue counter
+nft 'add rule bridge nat POSTROUTING oifname "someport" ether saddr set de:ad:0:be:ee:ff continue counter'
diff --git a/extensions/libebt_stp.c b/extensions/libebt_stp.c
index 3e9e2447..41059baa 100644
--- a/extensions/libebt_stp.c
+++ b/extensions/libebt_stp.c
@@ -146,9 +146,9 @@ out:
static void print_range(unsigned int l, unsigned int u)
{
if (l == u)
- printf("%u ", l);
+ printf("%u", l);
else
- printf("%u:%u ", l, u);
+ printf("%u:%u", l, u);
}
static int
diff --git a/extensions/libebt_stp.t b/extensions/libebt_stp.t
index 0c6b77b9..17d6c1c0 100644
--- a/extensions/libebt_stp.t
+++ b/extensions/libebt_stp.t
@@ -1,7 +1,7 @@
:INPUT,FORWARD,OUTPUT
--stp-type 1;=;OK
--stp-flags 0x1;--stp-flags topology-change -j CONTINUE;OK
---stp-root-prio 1 -j ACCEPT;=;OK
+--stp-root-prio 1 -j ACCEPT;=;OK
--stp-root-addr 0d:ea:d0:0b:ee:f0;=;OK
--stp-root-cost 1;=;OK
--stp-sender-prio 1;=;OK
diff --git a/extensions/libebt_vlan.t b/extensions/libebt_vlan.t
index 81c79585..3ec05599 100644
--- a/extensions/libebt_vlan.t
+++ b/extensions/libebt_vlan.t
@@ -4,8 +4,8 @@
-p 802_1Q --vlan-prio 1;=;OK
-p 802_1Q --vlan-prio ! 1;=;OK
-p 802_1Q --vlan-encap ip;-p 802_1Q --vlan-encap 0800 -j CONTINUE;OK
--p 802_1Q --vlan-encap 0800 ;=;OK
--p 802_1Q --vlan-encap ! 0800 ;=;OK
+-p 802_1Q --vlan-encap 0800;=;OK
+-p 802_1Q --vlan-encap ! 0800;=;OK
-p 802_1Q --vlan-encap IPv6 ! --vlan-id 1;-p 802_1Q --vlan-id ! 1 --vlan-encap 86DD -j CONTINUE;OK
-p 802_1Q --vlan-id ! 1 --vlan-encap 86DD;=;OK
--vlan-encap ip;=;FAIL
diff --git a/extensions/libebt_vlan.txlate b/extensions/libebt_vlan.txlate
index 2ab62d53..5d21e3eb 100644
--- a/extensions/libebt_vlan.txlate
+++ b/extensions/libebt_vlan.txlate
@@ -1,11 +1,11 @@
ebtables-translate -A INPUT -p 802_1Q --vlan-id 42
-nft add rule bridge filter INPUT vlan id 42 counter
+nft 'add rule bridge filter INPUT vlan id 42 counter'
ebtables-translate -A INPUT -p 802_1Q --vlan-prio ! 1
-nft add rule bridge filter INPUT vlan pcp != 1 counter
+nft 'add rule bridge filter INPUT vlan pcp != 1 counter'
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ip
-nft add rule bridge filter INPUT vlan type 0x0800 counter
+nft 'add rule bridge filter INPUT vlan type 0x0800 counter'
ebtables-translate -A INPUT -p 802_1Q --vlan-encap ipv6 ! --vlan-id 1
-nft add rule bridge filter INPUT vlan id != 1 vlan type 0x86dd counter
+nft 'add rule bridge filter INPUT vlan id != 1 vlan type 0x86dd counter'
diff --git a/extensions/libip6t_LOG.c b/extensions/libip6t_LOG.c
deleted file mode 100644
index 40adc69d..00000000
--- a/extensions/libip6t_LOG.c
+++ /dev/null
@@ -1,250 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <xtables.h>
-#include <linux/netfilter_ipv6/ip6t_LOG.h>
-
-#ifndef IP6T_LOG_UID /* Old kernel */
-#define IP6T_LOG_UID 0x08
-#undef IP6T_LOG_MASK
-#define IP6T_LOG_MASK 0x0f
-#endif
-
-#define LOG_DEFAULT_LEVEL LOG_WARNING
-
-enum {
- O_LOG_LEVEL = 0,
- O_LOG_PREFIX,
- O_LOG_TCPSEQ,
- O_LOG_TCPOPTS,
- O_LOG_IPOPTS,
- O_LOG_UID,
- O_LOG_MAC,
-};
-
-static void LOG_help(void)
-{
- printf(
-"LOG target options:\n"
-" --log-level level Level of logging (numeric or see syslog.conf)\n"
-" --log-prefix prefix Prefix log messages with this prefix.\n"
-" --log-tcp-sequence Log TCP sequence numbers.\n"
-" --log-tcp-options Log TCP options.\n"
-" --log-ip-options Log IP options.\n"
-" --log-uid Log UID owning the local socket.\n"
-" --log-macdecode Decode MAC addresses and protocol.\n");
-}
-
-#define s struct ip6t_log_info
-static const struct xt_option_entry LOG_opts[] = {
- {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
- {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
- {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
- {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
- {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
- {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
- {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-#undef s
-
-static void LOG_init(struct xt_entry_target *t)
-{
- struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data;
-
- loginfo->level = LOG_DEFAULT_LEVEL;
-
-}
-
-struct ip6t_log_names {
- const char *name;
- unsigned int level;
-};
-
-struct ip6t_log_xlate {
- const char *name;
- unsigned int level;
-};
-
-static const struct ip6t_log_names ip6t_log_names[]
-= { { .name = "alert", .level = LOG_ALERT },
- { .name = "crit", .level = LOG_CRIT },
- { .name = "debug", .level = LOG_DEBUG },
- { .name = "emerg", .level = LOG_EMERG },
- { .name = "error", .level = LOG_ERR }, /* DEPRECATED */
- { .name = "info", .level = LOG_INFO },
- { .name = "notice", .level = LOG_NOTICE },
- { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */
- { .name = "warning", .level = LOG_WARNING }
-};
-
-static void LOG_parse(struct xt_option_call *cb)
-{
- struct ip6t_log_info *info = cb->data;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_LOG_PREFIX:
- if (strchr(cb->arg, '\n') != NULL)
- xtables_error(PARAMETER_PROBLEM,
- "Newlines not allowed in --log-prefix");
- break;
- case O_LOG_TCPSEQ:
- info->logflags |= IP6T_LOG_TCPSEQ;
- break;
- case O_LOG_TCPOPTS:
- info->logflags |= IP6T_LOG_TCPOPT;
- break;
- case O_LOG_IPOPTS:
- info->logflags |= IP6T_LOG_IPOPT;
- break;
- case O_LOG_UID:
- info->logflags |= IP6T_LOG_UID;
- break;
- case O_LOG_MAC:
- info->logflags |= IP6T_LOG_MACDECODE;
- break;
- }
-}
-
-static void LOG_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct ip6t_log_info *loginfo
- = (const struct ip6t_log_info *)target->data;
- unsigned int i = 0;
-
- printf(" LOG");
- if (numeric)
- printf(" flags %u level %u",
- loginfo->logflags, loginfo->level);
- else {
- for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
- if (loginfo->level == ip6t_log_names[i].level) {
- printf(" level %s", ip6t_log_names[i].name);
- break;
- }
- if (i == ARRAY_SIZE(ip6t_log_names))
- printf(" UNKNOWN level %u", loginfo->level);
- if (loginfo->logflags & IP6T_LOG_TCPSEQ)
- printf(" tcp-sequence");
- if (loginfo->logflags & IP6T_LOG_TCPOPT)
- printf(" tcp-options");
- if (loginfo->logflags & IP6T_LOG_IPOPT)
- printf(" ip-options");
- if (loginfo->logflags & IP6T_LOG_UID)
- printf(" uid");
- if (loginfo->logflags & IP6T_LOG_MACDECODE)
- printf(" macdecode");
- if (loginfo->logflags & ~(IP6T_LOG_MASK))
- printf(" unknown-flags");
- }
-
- if (strcmp(loginfo->prefix, "") != 0)
- printf(" prefix \"%s\"", loginfo->prefix);
-}
-
-static void LOG_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct ip6t_log_info *loginfo
- = (const struct ip6t_log_info *)target->data;
-
- if (strcmp(loginfo->prefix, "") != 0) {
- printf(" --log-prefix");
- xtables_save_string(loginfo->prefix);
- }
-
- if (loginfo->level != LOG_DEFAULT_LEVEL)
- printf(" --log-level %d", loginfo->level);
-
- if (loginfo->logflags & IP6T_LOG_TCPSEQ)
- printf(" --log-tcp-sequence");
- if (loginfo->logflags & IP6T_LOG_TCPOPT)
- printf(" --log-tcp-options");
- if (loginfo->logflags & IP6T_LOG_IPOPT)
- printf(" --log-ip-options");
- if (loginfo->logflags & IP6T_LOG_UID)
- printf(" --log-uid");
- if (loginfo->logflags & IP6T_LOG_MACDECODE)
- printf(" --log-macdecode");
-}
-
-static const struct ip6t_log_xlate ip6t_log_xlate_names[] = {
- {"alert", LOG_ALERT },
- {"crit", LOG_CRIT },
- {"debug", LOG_DEBUG },
- {"emerg", LOG_EMERG },
- {"err", LOG_ERR },
- {"info", LOG_INFO },
- {"notice", LOG_NOTICE },
- {"warn", LOG_WARNING }
-};
-
-static int LOG_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- const struct ip6t_log_info *loginfo =
- (const struct ip6t_log_info *)params->target->data;
- unsigned int i = 0;
-
- xt_xlate_add(xl, "log");
- if (strcmp(loginfo->prefix, "") != 0) {
- if (params->escape_quotes)
- xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix);
- else
- xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
- }
-
- for (i = 0; i < ARRAY_SIZE(ip6t_log_xlate_names); ++i)
- if (loginfo->level == ip6t_log_xlate_names[i].level &&
- loginfo->level != LOG_DEFAULT_LEVEL) {
- xt_xlate_add(xl, " level %s",
- ip6t_log_xlate_names[i].name);
- break;
- }
-
- if ((loginfo->logflags & IP6T_LOG_MASK) == IP6T_LOG_MASK) {
- xt_xlate_add(xl, " flags all");
- } else {
- if (loginfo->logflags & (IP6T_LOG_TCPSEQ | IP6T_LOG_TCPOPT)) {
- const char *delim = " ";
-
- xt_xlate_add(xl, " flags tcp");
- if (loginfo->logflags & IP6T_LOG_TCPSEQ) {
- xt_xlate_add(xl, " sequence");
- delim = ",";
- }
- if (loginfo->logflags & IP6T_LOG_TCPOPT)
- xt_xlate_add(xl, "%soptions", delim);
- }
- if (loginfo->logflags & IP6T_LOG_IPOPT)
- xt_xlate_add(xl, " flags ip options");
- if (loginfo->logflags & IP6T_LOG_UID)
- xt_xlate_add(xl, " flags skuid");
- if (loginfo->logflags & IP6T_LOG_MACDECODE)
- xt_xlate_add(xl, " flags ether");
- }
-
- return 1;
-}
-static struct xtables_target log_tg6_reg = {
- .name = "LOG",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV6,
- .size = XT_ALIGN(sizeof(struct ip6t_log_info)),
- .userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)),
- .help = LOG_help,
- .init = LOG_init,
- .print = LOG_print,
- .save = LOG_save,
- .x6_parse = LOG_parse,
- .x6_options = LOG_opts,
- .xlate = LOG_xlate,
-};
-
-void _init(void)
-{
- xtables_register_target(&log_tg6_reg);
-}
diff --git a/extensions/libip6t_LOG.txlate b/extensions/libip6t_LOG.txlate
index 2820a82c..29ffce72 100644
--- a/extensions/libip6t_LOG.txlate
+++ b/extensions/libip6t_LOG.txlate
@@ -1,8 +1,8 @@
iptables-translate -I INPUT -j LOG
-nft insert rule ip filter INPUT counter log
+nft 'insert rule ip filter INPUT counter log'
ip6tables-translate -A FORWARD -p tcp -j LOG --log-level debug
-nft add rule ip6 filter FORWARD meta l4proto tcp counter log level debug
+nft 'add rule ip6 filter FORWARD meta l4proto tcp counter log level debug'
ip6tables-translate -A FORWARD -p tcp -j LOG --log-prefix "Checking log"
-nft add rule ip6 filter FORWARD meta l4proto tcp counter log prefix \"Checking log\"
+nft 'add rule ip6 filter FORWARD meta l4proto tcp counter log prefix "Checking log"'
diff --git a/extensions/libip6t_MASQUERADE.c b/extensions/libip6t_MASQUERADE.c
deleted file mode 100644
index f28f071b..00000000
--- a/extensions/libip6t_MASQUERADE.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
- *
- * Based on Rusty Russell's IPv4 MASQUERADE target. Development of IPv6 NAT
- * funded by Astaro.
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <xtables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
- O_TO_PORTS = 0,
- O_RANDOM,
- O_RANDOM_FULLY,
-};
-
-static void MASQUERADE_help(void)
-{
- printf(
-"MASQUERADE target options:\n"
-" --to-ports <port>[-<port>]\n"
-" Port (range) to map to.\n"
-" --random\n"
-" Randomize source port.\n"
-" --random-fully\n"
-" Fully randomize source port.\n");
-}
-
-static const struct xt_option_entry MASQUERADE_opts[] = {
- {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
- {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
- {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-
-/* Parses ports */
-static void
-parse_ports(const char *arg, struct nf_nat_range *r)
-{
- char *end;
- unsigned int port, maxport;
-
- r->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
- if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-
- switch (*end) {
- case '\0':
- r->min_proto.tcp.port
- = r->max_proto.tcp.port
- = htons(port);
- return;
- case '-':
- if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
- break;
-
- if (maxport < port)
- break;
-
- r->min_proto.tcp.port = htons(port);
- r->max_proto.tcp.port = htons(maxport);
- return;
- default:
- break;
- }
- xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-}
-
-static void MASQUERADE_parse(struct xt_option_call *cb)
-{
- const struct ip6t_entry *entry = cb->xt_entry;
- struct nf_nat_range *r = cb->data;
- int portok;
-
- if (entry->ipv6.proto == IPPROTO_TCP ||
- entry->ipv6.proto == IPPROTO_UDP ||
- entry->ipv6.proto == IPPROTO_SCTP ||
- entry->ipv6.proto == IPPROTO_DCCP ||
- entry->ipv6.proto == IPPROTO_ICMP)
- portok = 1;
- else
- portok = 0;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_TO_PORTS:
- if (!portok)
- xtables_error(PARAMETER_PROBLEM,
- "Need TCP, UDP, SCTP or DCCP with port specification");
- parse_ports(cb->arg, r);
- break;
- case O_RANDOM:
- r->flags |= NF_NAT_RANGE_PROTO_RANDOM;
- break;
- case O_RANDOM_FULLY:
- r->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
- break;
- }
-}
-
-static void
-MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct nf_nat_range *r = (const void *)target->data;
-
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- printf(" masq ports: ");
- printf("%hu", ntohs(r->min_proto.tcp.port));
- if (r->max_proto.tcp.port != r->min_proto.tcp.port)
- printf("-%hu", ntohs(r->max_proto.tcp.port));
- }
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" random");
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" random-fully");
-}
-
-static void
-MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct nf_nat_range *r = (const void *)target->data;
-
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- printf(" --to-ports %hu", ntohs(r->min_proto.tcp.port));
- if (r->max_proto.tcp.port != r->min_proto.tcp.port)
- printf("-%hu", ntohs(r->max_proto.tcp.port));
- }
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" --random");
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" --random-fully");
-}
-
-static int MASQUERADE_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- const struct nf_nat_range *r = (const void *)params->target->data;
-
- xt_xlate_add(xl, "masquerade");
-
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- xt_xlate_add(xl, " to :%hu", ntohs(r->min_proto.tcp.port));
- if (r->max_proto.tcp.port != r->min_proto.tcp.port)
- xt_xlate_add(xl, "-%hu", ntohs(r->max_proto.tcp.port));
- }
-
- xt_xlate_add(xl, " ");
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- xt_xlate_add(xl, "random ");
-
- xt_xlate_add(xl, " ");
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- xt_xlate_add(xl, "fully-random ");
-
- return 1;
-}
-
-static struct xtables_target masquerade_tg_reg = {
- .name = "MASQUERADE",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV6,
- .size = XT_ALIGN(sizeof(struct nf_nat_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
- .help = MASQUERADE_help,
- .x6_parse = MASQUERADE_parse,
- .print = MASQUERADE_print,
- .save = MASQUERADE_save,
- .x6_options = MASQUERADE_opts,
- .xlate = MASQUERADE_xlate,
-};
-
-void _init(void)
-{
- xtables_register_target(&masquerade_tg_reg);
-}
diff --git a/extensions/libip6t_MASQUERADE.txlate b/extensions/libip6t_MASQUERADE.txlate
index 6c289c2b..3f003477 100644
--- a/extensions/libip6t_MASQUERADE.txlate
+++ b/extensions/libip6t_MASQUERADE.txlate
@@ -1,8 +1,17 @@
ip6tables-translate -t nat -A POSTROUTING -j MASQUERADE
-nft add rule ip6 nat POSTROUTING counter masquerade
+nft 'add rule ip6 nat POSTROUTING counter masquerade'
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10
-nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10
+nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10'
ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
-nft add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10-20 random
+nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade to :10-20 random'
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random
+nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade random'
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random-fully
+nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade fully-random'
+
+ip6tables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random --random-fully
+nft 'add rule ip6 nat POSTROUTING meta l4proto tcp counter masquerade random,fully-random'
diff --git a/extensions/libip6t_NETMAP.t b/extensions/libip6t_NETMAP.t
index 043562d2..79d47bf6 100644
--- a/extensions/libip6t_NETMAP.t
+++ b/extensions/libip6t_NETMAP.t
@@ -1,4 +1,4 @@
:PREROUTING,INPUT,OUTPUT,POSTROUTING
*nat
-j NETMAP --to dead::/64;=;OK
--j NETMAP --to dead::beef;=;OK
+-j NETMAP --to dead::beef;-j NETMAP --to dead::beef/128;OK
diff --git a/extensions/libip6t_REJECT.t b/extensions/libip6t_REJECT.t
index d2b337d7..8294f0bb 100644
--- a/extensions/libip6t_REJECT.t
+++ b/extensions/libip6t_REJECT.t
@@ -1,5 +1,5 @@
:INPUT,FORWARD,OUTPUT
--j REJECT;=;OK
+-j REJECT;-j REJECT --reject-with icmp6-port-unreachable;OK
# manpage for IPv6 variant of REJECT does not show up for some reason?
-j REJECT --reject-with icmp6-no-route;=;OK
-j REJECT --reject-with icmp6-adm-prohibited;=;OK
diff --git a/extensions/libip6t_REJECT.txlate b/extensions/libip6t_REJECT.txlate
index cfa35ebf..184713d1 100644
--- a/extensions/libip6t_REJECT.txlate
+++ b/extensions/libip6t_REJECT.txlate
@@ -1,8 +1,8 @@
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT
-nft add rule ip6 filter FORWARD tcp dport 22 counter reject
+nft 'add rule ip6 filter FORWARD tcp dport 22 counter reject'
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with icmp6-reject-route
-nft add rule ip6 filter FORWARD tcp dport 22 counter reject with icmpv6 type reject-route
+nft 'add rule ip6 filter FORWARD tcp dport 22 counter reject with icmpv6 type reject-route'
ip6tables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
-nft add rule ip6 filter FORWARD tcp dport 22 counter reject with tcp reset
+nft 'add rule ip6 filter FORWARD tcp dport 22 counter reject with tcp reset'
diff --git a/extensions/libip6t_SNAT.c b/extensions/libip6t_SNAT.c
deleted file mode 100644
index 4fe272b2..00000000
--- a/extensions/libip6t_SNAT.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
- *
- * Based on Rusty Russell's IPv4 SNAT target. Development of IPv6 NAT
- * funded by Astaro.
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <xtables.h>
-#include <iptables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
- O_TO_SRC = 0,
- O_RANDOM,
- O_RANDOM_FULLY,
- O_PERSISTENT,
- F_TO_SRC = 1 << O_TO_SRC,
- F_RANDOM = 1 << O_RANDOM,
- F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
-};
-
-static void SNAT_help(void)
-{
- printf(
-"SNAT target options:\n"
-" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
-" Address to map source to.\n"
-"[--random] [--random-fully] [--persistent]\n");
-}
-
-static const struct xt_option_entry SNAT_opts[] = {
- {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
- .flags = XTOPT_MAND},
- {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
- {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
- {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-
-/* Ranges expected in network order. */
-static void
-parse_to(const char *orig_arg, int portok, struct nf_nat_range *range)
-{
- char *arg, *start, *end = NULL, *colon = NULL, *dash, *error;
- const struct in6_addr *ip;
-
- arg = xtables_strdup(orig_arg);
-
- start = strchr(arg, '[');
- if (start == NULL) {
- start = arg;
- /* Lets assume one colon is port information. Otherwise its an IPv6 address */
- colon = strchr(arg, ':');
- if (colon && strchr(colon+1, ':'))
- colon = NULL;
- }
- else {
- start++;
- end = strchr(start, ']');
- if (end == NULL)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid address format");
-
- *end = '\0';
- colon = strchr(end + 1, ':');
- }
-
- if (colon) {
- int port;
-
- if (!portok)
- xtables_error(PARAMETER_PROBLEM,
- "Need TCP, UDP, SCTP or DCCP with port specification");
-
- range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
- port = atoi(colon+1);
- if (port <= 0 || port > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", colon+1);
-
- error = strchr(colon+1, ':');
- if (error)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
-
- dash = strchr(colon, '-');
- if (!dash) {
- range->min_proto.tcp.port
- = range->max_proto.tcp.port
- = htons(port);
- } else {
- int maxport;
-
- maxport = atoi(dash + 1);
- if (maxport <= 0 || maxport > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
- if (maxport < port)
- /* People are stupid. */
- xtables_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
- range->min_proto.tcp.port = htons(port);
- range->max_proto.tcp.port = htons(maxport);
- }
- /* Starts with colon or [] colon? No IP info...*/
- if (colon == arg || colon == arg+2) {
- free(arg);
- return;
- }
- *colon = '\0';
- }
-
- range->flags |= NF_NAT_RANGE_MAP_IPS;
- dash = strchr(start, '-');
- if (colon && dash && dash > colon)
- dash = NULL;
-
- if (dash)
- *dash = '\0';
-
- ip = xtables_numeric_to_ip6addr(start);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- start);
- range->min_addr.in6 = *ip;
- if (dash) {
- ip = xtables_numeric_to_ip6addr(dash + 1);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- dash+1);
- range->max_addr.in6 = *ip;
- } else
- range->max_addr = range->min_addr;
-
- free(arg);
- return;
-}
-
-static void SNAT_parse(struct xt_option_call *cb)
-{
- const struct ip6t_entry *entry = cb->xt_entry;
- struct nf_nat_range *range = cb->data;
- int portok;
-
- if (entry->ipv6.proto == IPPROTO_TCP ||
- entry->ipv6.proto == IPPROTO_UDP ||
- entry->ipv6.proto == IPPROTO_SCTP ||
- entry->ipv6.proto == IPPROTO_DCCP ||
- entry->ipv6.proto == IPPROTO_ICMP)
- portok = 1;
- else
- portok = 0;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_TO_SRC:
- parse_to(cb->arg, portok, range);
- break;
- case O_PERSISTENT:
- range->flags |= NF_NAT_RANGE_PERSISTENT;
- break;
- }
-}
-
-static void SNAT_fcheck(struct xt_fcheck_call *cb)
-{
- static const unsigned int f = F_TO_SRC | F_RANDOM;
- static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
- struct nf_nat_range *range = cb->data;
-
- if ((cb->xflags & f) == f)
- range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
- if ((cb->xflags & r) == r)
- range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-}
-
-static void print_range(const struct nf_nat_range *range)
-{
- if (range->flags & NF_NAT_RANGE_MAP_IPS) {
- if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
- printf("[");
- printf("%s", xtables_ip6addr_to_numeric(&range->min_addr.in6));
- if (memcmp(&range->min_addr, &range->max_addr,
- sizeof(range->min_addr)))
- printf("-%s", xtables_ip6addr_to_numeric(&range->max_addr.in6));
- if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)
- printf("]");
- }
- if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- printf(":");
- printf("%hu", ntohs(range->min_proto.tcp.port));
- if (range->max_proto.tcp.port != range->min_proto.tcp.port)
- printf("-%hu", ntohs(range->max_proto.tcp.port));
- }
-}
-
-static void SNAT_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct nf_nat_range *range = (const void *)target->data;
-
- printf(" to:");
- print_range(range);
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" random");
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" random-fully");
- if (range->flags & NF_NAT_RANGE_PERSISTENT)
- printf(" persistent");
-}
-
-static void SNAT_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct nf_nat_range *range = (const void *)target->data;
-
- printf(" --to-source ");
- print_range(range);
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" --random");
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" --random-fully");
- if (range->flags & NF_NAT_RANGE_PERSISTENT)
- printf(" --persistent");
-}
-
-static void print_range_xlate(const struct nf_nat_range *range,
- struct xt_xlate *xl)
-{
- bool proto_specified = range->flags & NF_NAT_RANGE_PROTO_SPECIFIED;
-
- if (range->flags & NF_NAT_RANGE_MAP_IPS) {
- xt_xlate_add(xl, "%s%s%s",
- proto_specified ? "[" : "",
- xtables_ip6addr_to_numeric(&range->min_addr.in6),
- proto_specified ? "]" : "");
-
- if (memcmp(&range->min_addr, &range->max_addr,
- sizeof(range->min_addr))) {
- xt_xlate_add(xl, "-%s%s%s",
- proto_specified ? "[" : "",
- xtables_ip6addr_to_numeric(&range->max_addr.in6),
- proto_specified ? "]" : "");
- }
- }
- if (proto_specified) {
- xt_xlate_add(xl, ":%hu", ntohs(range->min_proto.tcp.port));
-
- if (range->max_proto.tcp.port != range->min_proto.tcp.port)
- xt_xlate_add(xl, "-%hu",
- ntohs(range->max_proto.tcp.port));
- }
-}
-
-static int SNAT_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- const struct nf_nat_range *range = (const void *)params->target->data;
- bool sep_need = false;
- const char *sep = " ";
-
- xt_xlate_add(xl, "snat to ");
- print_range_xlate(range, xl);
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
- xt_xlate_add(xl, " random");
- sep_need = true;
- }
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
- if (sep_need)
- sep = ",";
- xt_xlate_add(xl, "%sfully-random", sep);
- sep_need = true;
- }
- if (range->flags & NF_NAT_RANGE_PERSISTENT) {
- if (sep_need)
- sep = ",";
- xt_xlate_add(xl, "%spersistent", sep);
- }
-
- return 1;
-}
-
-static struct xtables_target snat_tg_reg = {
- .name = "SNAT",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV6,
- .revision = 1,
- .size = XT_ALIGN(sizeof(struct nf_nat_range)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
- .help = SNAT_help,
- .x6_parse = SNAT_parse,
- .x6_fcheck = SNAT_fcheck,
- .print = SNAT_print,
- .save = SNAT_save,
- .x6_options = SNAT_opts,
- .xlate = SNAT_xlate,
-};
-
-void _init(void)
-{
- xtables_register_target(&snat_tg_reg);
-}
diff --git a/extensions/libip6t_SNAT.t b/extensions/libip6t_SNAT.t
index d188a6bb..98aa7602 100644
--- a/extensions/libip6t_SNAT.t
+++ b/extensions/libip6t_SNAT.t
@@ -4,6 +4,12 @@
-j SNAT --to-source dead::beef-dead::fee7;=;OK
-j SNAT --to-source [dead::beef]:1025-65535;;FAIL
-j SNAT --to-source [dead::beef] --to-source [dead::fee7];;FAIL
+-j SNAT --to-source dead::beef --random;=;OK
+-j SNAT --to-source dead::beef --random-fully;=;OK
+-j SNAT --to-source dead::beef --persistent;=;OK
+-j SNAT --to-source dead::beef --random --persistent;=;OK
+-j SNAT --to-source dead::beef --random --random-fully;=;OK
+-j SNAT --to-source dead::beef --random --random-fully --persistent;=;OK
-p tcp -j SNAT --to-source [dead::beef]:1025-65535;=;OK
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535;=;OK
-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65536;;FAIL
diff --git a/extensions/libip6t_SNAT.txlate b/extensions/libip6t_SNAT.txlate
index 44f2fcea..e5f6f735 100644
--- a/extensions/libip6t_SNAT.txlate
+++ b/extensions/libip6t_SNAT.txlate
@@ -1,11 +1,11 @@
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:80
-nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:80
+nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:80'
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:1-20
-nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:1-20
+nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:1-20'
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random
-nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 random
+nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 random'
ip6tables-translate -t nat -A postrouting -o eth0 -p tcp -j SNAT --to [fec0::1234]:123 --random-fully --persistent
-nft add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 fully-random,persistent
+nft 'add rule ip6 nat postrouting oifname "eth0" meta l4proto tcp counter snat to [fec0::1234]:123 fully-random,persistent'
diff --git a/extensions/libip6t_ah.txlate b/extensions/libip6t_ah.txlate
index c6b09a2e..cc33ac27 100644
--- a/extensions/libip6t_ah.txlate
+++ b/extensions/libip6t_ah.txlate
@@ -1,17 +1,17 @@
ip6tables-translate -A INPUT -m ah --ahspi 500 -j DROP
-nft add rule ip6 filter INPUT ah spi 500 counter drop
+nft 'add rule ip6 filter INPUT ah spi 500 counter drop'
ip6tables-translate -A INPUT -m ah --ahspi 500:550 -j DROP
-nft add rule ip6 filter INPUT ah spi 500-550 counter drop
+nft 'add rule ip6 filter INPUT ah spi 500-550 counter drop'
ip6tables-translate -A INPUT -m ah ! --ahlen 120
-nft add rule ip6 filter INPUT ah hdrlength != 120 counter
+nft 'add rule ip6 filter INPUT ah hdrlength != 120 counter'
ip6tables-translate -A INPUT -m ah --ahres
-nft add rule ip6 filter INPUT ah reserved 1 counter
+nft 'add rule ip6 filter INPUT ah reserved 1 counter'
ip6tables-translate -A INPUT -m ah --ahspi 500 ! --ahlen 120 -j DROP
-nft add rule ip6 filter INPUT ah spi 500 ah hdrlength != 120 counter drop
+nft 'add rule ip6 filter INPUT ah spi 500 ah hdrlength != 120 counter drop'
ip6tables-translate -A INPUT -m ah --ahspi 500 --ahlen 120 --ahres -j ACCEPT
-nft add rule ip6 filter INPUT ah spi 500 ah hdrlength 120 ah reserved 1 counter accept
+nft 'add rule ip6 filter INPUT ah spi 500 ah hdrlength 120 ah reserved 1 counter accept'
diff --git a/extensions/libip6t_dst.c b/extensions/libip6t_dst.c
index bf0e3e43..baa010f5 100644
--- a/extensions/libip6t_dst.c
+++ b/extensions/libip6t_dst.c
@@ -125,15 +125,15 @@ static void
print_options(unsigned int optsnr, uint16_t *optsp)
{
unsigned int i;
+ char sep = ' ';
- printf(" ");
for(i = 0; i < optsnr; i++) {
- printf("%d", (optsp[i] & 0xFF00) >> 8);
+ printf("%c%d", sep, (optsp[i] & 0xFF00) >> 8);
if ((optsp[i] & 0x00FF) != 0x00FF)
printf(":%d", (optsp[i] & 0x00FF));
- printf("%c", (i != optsnr - 1) ? ',' : ' ');
+ sep = ',';
}
}
diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c
index 3842496e..49c787e7 100644
--- a/extensions/libip6t_frag.c
+++ b/extensions/libip6t_frag.c
@@ -178,7 +178,6 @@ static int frag_xlate(struct xt_xlate *xl,
{
const struct ip6t_frag *fraginfo =
(struct ip6t_frag *)params->match->data;
- char *space= "";
if (!(fraginfo->ids[0] == 0 && fraginfo->ids[1] == 0xFFFFFFFF)) {
xt_xlate_add(xl, "frag id %s",
@@ -190,24 +189,21 @@ static int frag_xlate(struct xt_xlate *xl,
else
xt_xlate_add(xl, "%u", fraginfo->ids[0]);
- space = " ";
}
- if (fraginfo->flags & IP6T_FRAG_RES) {
- xt_xlate_add(xl, "%sfrag reserved 1", space);
- space = " ";
- }
- if (fraginfo->flags & IP6T_FRAG_FST) {
- xt_xlate_add(xl, "%sfrag frag-off 0", space);
- space = " ";
- }
- if (fraginfo->flags & IP6T_FRAG_MF) {
- xt_xlate_add(xl, "%sfrag more-fragments 1", space);
- space = " ";
- }
- if (fraginfo->flags & IP6T_FRAG_NMF) {
- xt_xlate_add(xl, "%sfrag more-fragments 0", space);
- }
+ /* ignore ineffective IP6T_FRAG_LEN bit */
+
+ if (fraginfo->flags & IP6T_FRAG_RES)
+ xt_xlate_add(xl, "frag reserved 1");
+
+ if (fraginfo->flags & IP6T_FRAG_FST)
+ xt_xlate_add(xl, "frag frag-off 0");
+
+ if (fraginfo->flags & IP6T_FRAG_MF)
+ xt_xlate_add(xl, "frag more-fragments 1");
+
+ if (fraginfo->flags & IP6T_FRAG_NMF)
+ xt_xlate_add(xl, "frag more-fragments 0");
return 1;
}
diff --git a/extensions/libip6t_frag.txlate b/extensions/libip6t_frag.txlate
index e8bd9d4b..33fc0631 100644
--- a/extensions/libip6t_frag.txlate
+++ b/extensions/libip6t_frag.txlate
@@ -1,17 +1,17 @@
ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 -j ACCEPT
-nft add rule ip6 filter INPUT frag id 100-200 counter accept
+nft 'add rule ip6 filter INPUT frag id 100-200 counter accept'
ip6tables-translate -t filter -A INPUT -m frag --fragid 100 --fragres --fragmore -j ACCEPT
-nft add rule ip6 filter INPUT frag id 100 frag reserved 1 frag more-fragments 1 counter accept
+nft 'add rule ip6 filter INPUT frag id 100 frag reserved 1 frag more-fragments 1 counter accept'
ip6tables-translate -t filter -A INPUT -m frag ! --fragid 100:200 -j ACCEPT
-nft add rule ip6 filter INPUT frag id != 100-200 counter accept
+nft 'add rule ip6 filter INPUT frag id != 100-200 counter accept'
ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 --fraglast -j ACCEPT
-nft add rule ip6 filter INPUT frag id 100-200 frag more-fragments 0 counter accept
+nft 'add rule ip6 filter INPUT frag id 100-200 frag more-fragments 0 counter accept'
ip6tables-translate -t filter -A INPUT -m frag --fragid 100:200 --fragfirst -j ACCEPT
-nft add rule ip6 filter INPUT frag id 100-200 frag frag-off 0 counter accept
+nft 'add rule ip6 filter INPUT frag id 100-200 frag frag-off 0 counter accept'
ip6tables-translate -t filter -A INPUT -m frag --fraglast -j ACCEPT
-nft add rule ip6 filter INPUT frag more-fragments 0 counter accept
+nft 'add rule ip6 filter INPUT frag more-fragments 0 counter accept'
diff --git a/extensions/libip6t_hbh.txlate b/extensions/libip6t_hbh.txlate
index 28101fd7..a753df0d 100644
--- a/extensions/libip6t_hbh.txlate
+++ b/extensions/libip6t_hbh.txlate
@@ -1,5 +1,5 @@
ip6tables-translate -t filter -A INPUT -m hbh --hbh-len 22
-nft add rule ip6 filter INPUT hbh hdrlength 22 counter
+nft 'add rule ip6 filter INPUT hbh hdrlength 22 counter'
ip6tables-translate -t filter -A INPUT -m hbh ! --hbh-len 22
-nft add rule ip6 filter INPUT hbh hdrlength != 22 counter
+nft 'add rule ip6 filter INPUT hbh hdrlength != 22 counter'
diff --git a/extensions/libip6t_hl.txlate b/extensions/libip6t_hl.txlate
index 17563938..9ff0df9c 100644
--- a/extensions/libip6t_hl.txlate
+++ b/extensions/libip6t_hl.txlate
@@ -1,5 +1,5 @@
ip6tables-translate -t nat -A postrouting -m hl --hl-gt 3
-nft add rule ip6 nat postrouting ip6 hoplimit gt 3 counter
+nft 'add rule ip6 nat postrouting ip6 hoplimit gt 3 counter'
ip6tables-translate -t nat -A postrouting -m hl ! --hl-eq 3
-nft add rule ip6 nat postrouting ip6 hoplimit != 3 counter
+nft 'add rule ip6 nat postrouting ip6 hoplimit != 3 counter'
diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c
index cc7bfaeb..439291ea 100644
--- a/extensions/libip6t_icmp6.c
+++ b/extensions/libip6t_icmp6.c
@@ -12,48 +12,6 @@ enum {
O_ICMPV6_TYPE = 0,
};
-static const struct xt_icmp_names icmpv6_codes[] = {
- { "destination-unreachable", 1, 0, 0xFF },
- { "no-route", 1, 0, 0 },
- { "communication-prohibited", 1, 1, 1 },
- { "beyond-scope", 1, 2, 2 },
- { "address-unreachable", 1, 3, 3 },
- { "port-unreachable", 1, 4, 4 },
- { "failed-policy", 1, 5, 5 },
- { "reject-route", 1, 6, 6 },
-
- { "packet-too-big", 2, 0, 0xFF },
-
- { "time-exceeded", 3, 0, 0xFF },
- /* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
- { "ttl-zero-during-transit", 3, 0, 0 },
- { "ttl-zero-during-reassembly", 3, 1, 1 },
-
- { "parameter-problem", 4, 0, 0xFF },
- { "bad-header", 4, 0, 0 },
- { "unknown-header-type", 4, 1, 1 },
- { "unknown-option", 4, 2, 2 },
-
- { "echo-request", 128, 0, 0xFF },
- /* Alias */ { "ping", 128, 0, 0xFF },
-
- { "echo-reply", 129, 0, 0xFF },
- /* Alias */ { "pong", 129, 0, 0xFF },
-
- { "router-solicitation", 133, 0, 0xFF },
-
- { "router-advertisement", 134, 0, 0xFF },
-
- { "neighbour-solicitation", 135, 0, 0xFF },
- /* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
-
- { "neighbour-advertisement", 136, 0, 0xFF },
- /* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
-
- { "redirect", 137, 0, 0xFF },
-
-};
-
static void icmp6_help(void)
{
printf(
@@ -70,59 +28,6 @@ static const struct xt_option_entry icmp6_opts[] = {
XTOPT_TABLEEND,
};
-static void
-parse_icmpv6(const char *icmpv6type, uint8_t *type, uint8_t code[])
-{
- static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
- unsigned int match = limit;
- unsigned int i;
-
- for (i = 0; i < limit; i++) {
- if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type))
- == 0) {
- if (match != limit)
- xtables_error(PARAMETER_PROBLEM,
- "Ambiguous ICMPv6 type `%s':"
- " `%s' or `%s'?",
- icmpv6type,
- icmpv6_codes[match].name,
- icmpv6_codes[i].name);
- match = i;
- }
- }
-
- if (match != limit) {
- *type = icmpv6_codes[match].type;
- code[0] = icmpv6_codes[match].code_min;
- code[1] = icmpv6_codes[match].code_max;
- } else {
- char *slash;
- char buffer[strlen(icmpv6type) + 1];
- unsigned int number;
-
- strcpy(buffer, icmpv6type);
- slash = strchr(buffer, '/');
-
- if (slash)
- *slash = '\0';
-
- if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "Invalid ICMPv6 type `%s'\n", buffer);
- *type = number;
- if (slash) {
- if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "Invalid ICMPv6 code `%s'\n",
- slash+1);
- code[0] = code[1] = number;
- } else {
- code[0] = 0;
- code[1] = 0xFF;
- }
- }
-}
-
static void icmp6_init(struct xt_entry_match *m)
{
struct ip6t_icmp *icmpv6info = (struct ip6t_icmp *)m->data;
@@ -135,7 +40,7 @@ static void icmp6_parse(struct xt_option_call *cb)
struct ip6t_icmp *icmpv6info = cb->data;
xtables_option_parse(cb);
- parse_icmpv6(cb->arg, &icmpv6info->type, icmpv6info->code);
+ ipt_parse_icmpv6(cb->arg, &icmpv6info->type, icmpv6info->code);
if (cb->invert)
icmpv6info->invflags |= IP6T_ICMP_INV;
}
diff --git a/extensions/libip6t_icmp6.txlate b/extensions/libip6t_icmp6.txlate
index 15481ad6..324a48b9 100644
--- a/extensions/libip6t_icmp6.txlate
+++ b/extensions/libip6t_icmp6.txlate
@@ -1,8 +1,8 @@
ip6tables-translate -t filter -A INPUT -m icmp6 --icmpv6-type 1 -j LOG
-nft add rule ip6 filter INPUT icmpv6 type destination-unreachable counter log
+nft 'add rule ip6 filter INPUT icmpv6 type destination-unreachable counter log'
ip6tables-translate -t filter -A INPUT -m icmp6 --icmpv6-type neighbour-advertisement -j LOG
-nft add rule ip6 filter INPUT icmpv6 type nd-neighbor-advert counter log
+nft 'add rule ip6 filter INPUT icmpv6 type nd-neighbor-advert counter log'
ip6tables-translate -t filter -A INPUT -m icmp6 ! --icmpv6-type packet-too-big -j LOG
-nft add rule ip6 filter INPUT icmpv6 type != packet-too-big counter log
+nft 'add rule ip6 filter INPUT icmpv6 type != packet-too-big counter log'
diff --git a/extensions/libip6t_mh.c b/extensions/libip6t_mh.c
index 64675405..1410d324 100644
--- a/extensions/libip6t_mh.c
+++ b/extensions/libip6t_mh.c
@@ -97,7 +97,7 @@ static unsigned int name_to_type(const char *name)
if (!xtables_strtoui(name, NULL, &number, 0, UINT8_MAX))
xtables_error(PARAMETER_PROBLEM,
- "Invalid MH type `%s'\n", name);
+ "Invalid MH type `%s'", name);
return number;
}
}
diff --git a/extensions/libip6t_mh.txlate b/extensions/libip6t_mh.txlate
index f5d638c0..4dfaf46a 100644
--- a/extensions/libip6t_mh.txlate
+++ b/extensions/libip6t_mh.txlate
@@ -1,5 +1,5 @@
ip6tables-translate -A INPUT -p mh --mh-type 1 -j ACCEPT
-nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1 counter accept
+nft 'add rule ip6 filter INPUT meta l4proto mobility-header mh type 1 counter accept'
ip6tables-translate -A INPUT -p mh --mh-type 1:3 -j ACCEPT
-nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1-3 counter accept
+nft 'add rule ip6 filter INPUT meta l4proto mobility-header mh type 1-3 counter accept'
diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c
index 9708b5a0..d5b0458b 100644
--- a/extensions/libip6t_rt.c
+++ b/extensions/libip6t_rt.c
@@ -248,17 +248,15 @@ static int rt_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)params->match->data;
- char *space = "";
if (rtinfo->flags & IP6T_RT_TYP) {
xt_xlate_add(xl, "rt type%s %u",
(rtinfo->invflags & IP6T_RT_INV_TYP) ? " !=" : "",
rtinfo->rt_type);
- space = " ";
}
if (!(rtinfo->segsleft[0] == 0 && rtinfo->segsleft[1] == 0xFFFFFFFF)) {
- xt_xlate_add(xl, "%srt seg-left%s ", space,
+ xt_xlate_add(xl, "rt seg-left%s ",
(rtinfo->invflags & IP6T_RT_INV_SGS) ? " !=" : "");
if (rtinfo->segsleft[0] != rtinfo->segsleft[1])
@@ -266,11 +264,10 @@ static int rt_xlate(struct xt_xlate *xl,
rtinfo->segsleft[1]);
else
xt_xlate_add(xl, "%u", rtinfo->segsleft[0]);
- space = " ";
}
if (rtinfo->flags & IP6T_RT_LEN) {
- xt_xlate_add(xl, "%srt hdrlength%s %u", space,
+ xt_xlate_add(xl, "rt hdrlength%s %u",
(rtinfo->invflags & IP6T_RT_INV_LEN) ? " !=" : "",
rtinfo->hdrlen);
}
diff --git a/extensions/libip6t_rt.txlate b/extensions/libip6t_rt.txlate
index 6464cf9e..3578bcba 100644
--- a/extensions/libip6t_rt.txlate
+++ b/extensions/libip6t_rt.txlate
@@ -1,14 +1,14 @@
ip6tables-translate -A INPUT -m rt --rt-type 0 -j DROP
-nft add rule ip6 filter INPUT rt type 0 counter drop
+nft 'add rule ip6 filter INPUT rt type 0 counter drop'
ip6tables-translate -A INPUT -m rt ! --rt-len 22 -j DROP
-nft add rule ip6 filter INPUT rt hdrlength != 22 counter drop
+nft 'add rule ip6 filter INPUT rt hdrlength != 22 counter drop'
ip6tables-translate -A INPUT -m rt --rt-segsleft 26 -j ACCEPT
-nft add rule ip6 filter INPUT rt seg-left 26 counter accept
+nft 'add rule ip6 filter INPUT rt seg-left 26 counter accept'
ip6tables-translate -A INPUT -m rt --rt-type 0 --rt-len 22 -j DROP
-nft add rule ip6 filter INPUT rt type 0 rt hdrlength 22 counter drop
+nft 'add rule ip6 filter INPUT rt type 0 rt hdrlength 22 counter drop'
ip6tables-translate -A INPUT -m rt --rt-type 0 --rt-len 22 ! --rt-segsleft 26 -j ACCEPT
-nft add rule ip6 filter INPUT rt type 0 rt seg-left != 26 rt hdrlength 22 counter accept
+nft 'add rule ip6 filter INPUT rt type 0 rt seg-left != 26 rt hdrlength 22 counter accept'
diff --git a/extensions/libipt_CLUSTERIP.c b/extensions/libipt_CLUSTERIP.c
index f4b638b2..b207cde3 100644
--- a/extensions/libipt_CLUSTERIP.c
+++ b/extensions/libipt_CLUSTERIP.c
@@ -87,12 +87,13 @@ static void CLUSTERIP_parse(struct xt_option_call *cb)
else if (strcmp(cb->arg, "sourceip-sourceport-destport") == 0)
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT_DPT;
else
- xtables_error(PARAMETER_PROBLEM, "Unknown hashmode \"%s\"\n",
- cb->arg);
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown hashmode \"%s\"", cb->arg);
break;
case O_CLUSTERMAC:
if (!(cipinfo->clustermac[0] & 0x01))
- xtables_error(PARAMETER_PROBLEM, "MAC has to be a multicast ethernet address\n");
+ xtables_error(PARAMETER_PROBLEM,
+ "MAC has to be a multicast ethernet address");
break;
case O_LOCAL_NODE:
cipinfo->num_local_nodes = 1;
@@ -107,7 +108,8 @@ static void CLUSTERIP_check(struct xt_fcheck_call *cb)
if ((cb->xflags & F_FULL) == F_FULL)
return;
- xtables_error(PARAMETER_PROBLEM, "CLUSTERIP target: Invalid parameter combination\n");
+ xtables_error(PARAMETER_PROBLEM,
+ "CLUSTERIP target: Invalid parameter combination");
}
static const char *hashmode2str(enum clusterip_hashmode mode)
diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c
deleted file mode 100644
index 36e2e73b..00000000
--- a/extensions/libipt_LOG.c
+++ /dev/null
@@ -1,250 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <xtables.h>
-#include <linux/netfilter_ipv4/ipt_LOG.h>
-
-#define LOG_DEFAULT_LEVEL LOG_WARNING
-
-#ifndef IPT_LOG_UID /* Old kernel */
-#define IPT_LOG_UID 0x08 /* Log UID owning local socket */
-#undef IPT_LOG_MASK
-#define IPT_LOG_MASK 0x0f
-#endif
-
-enum {
- O_LOG_LEVEL = 0,
- O_LOG_PREFIX,
- O_LOG_TCPSEQ,
- O_LOG_TCPOPTS,
- O_LOG_IPOPTS,
- O_LOG_UID,
- O_LOG_MAC,
-};
-
-static void LOG_help(void)
-{
- printf(
-"LOG target options:\n"
-" --log-level level Level of logging (numeric or see syslog.conf)\n"
-" --log-prefix prefix Prefix log messages with this prefix.\n\n"
-" --log-tcp-sequence Log TCP sequence numbers.\n\n"
-" --log-tcp-options Log TCP options.\n\n"
-" --log-ip-options Log IP options.\n\n"
-" --log-uid Log UID owning the local socket.\n\n"
-" --log-macdecode Decode MAC addresses and protocol.\n\n");
-}
-
-#define s struct ipt_log_info
-static const struct xt_option_entry LOG_opts[] = {
- {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
- {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
- {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
- {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
- {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
- {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
- {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-#undef s
-
-static void LOG_init(struct xt_entry_target *t)
-{
- struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
-
- loginfo->level = LOG_DEFAULT_LEVEL;
-
-}
-
-struct ipt_log_names {
- const char *name;
- unsigned int level;
-};
-
-struct ipt_log_xlate {
- const char *name;
- unsigned int level;
-};
-
-static const struct ipt_log_names ipt_log_names[]
-= { { .name = "alert", .level = LOG_ALERT },
- { .name = "crit", .level = LOG_CRIT },
- { .name = "debug", .level = LOG_DEBUG },
- { .name = "emerg", .level = LOG_EMERG },
- { .name = "error", .level = LOG_ERR }, /* DEPRECATED */
- { .name = "info", .level = LOG_INFO },
- { .name = "notice", .level = LOG_NOTICE },
- { .name = "panic", .level = LOG_EMERG }, /* DEPRECATED */
- { .name = "warning", .level = LOG_WARNING }
-};
-
-static void LOG_parse(struct xt_option_call *cb)
-{
- struct ipt_log_info *info = cb->data;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_LOG_PREFIX:
- if (strchr(cb->arg, '\n') != NULL)
- xtables_error(PARAMETER_PROBLEM,
- "Newlines not allowed in --log-prefix");
- break;
- case O_LOG_TCPSEQ:
- info->logflags |= IPT_LOG_TCPSEQ;
- break;
- case O_LOG_TCPOPTS:
- info->logflags |= IPT_LOG_TCPOPT;
- break;
- case O_LOG_IPOPTS:
- info->logflags |= IPT_LOG_IPOPT;
- break;
- case O_LOG_UID:
- info->logflags |= IPT_LOG_UID;
- break;
- case O_LOG_MAC:
- info->logflags |= IPT_LOG_MACDECODE;
- break;
- }
-}
-
-static void LOG_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct ipt_log_info *loginfo
- = (const struct ipt_log_info *)target->data;
- unsigned int i = 0;
-
- printf(" LOG");
- if (numeric)
- printf(" flags %u level %u",
- loginfo->logflags, loginfo->level);
- else {
- for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
- if (loginfo->level == ipt_log_names[i].level) {
- printf(" level %s", ipt_log_names[i].name);
- break;
- }
- if (i == ARRAY_SIZE(ipt_log_names))
- printf(" UNKNOWN level %u", loginfo->level);
- if (loginfo->logflags & IPT_LOG_TCPSEQ)
- printf(" tcp-sequence");
- if (loginfo->logflags & IPT_LOG_TCPOPT)
- printf(" tcp-options");
- if (loginfo->logflags & IPT_LOG_IPOPT)
- printf(" ip-options");
- if (loginfo->logflags & IPT_LOG_UID)
- printf(" uid");
- if (loginfo->logflags & IPT_LOG_MACDECODE)
- printf(" macdecode");
- if (loginfo->logflags & ~(IPT_LOG_MASK))
- printf(" unknown-flags");
- }
-
- if (strcmp(loginfo->prefix, "") != 0)
- printf(" prefix \"%s\"", loginfo->prefix);
-}
-
-static void LOG_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct ipt_log_info *loginfo
- = (const struct ipt_log_info *)target->data;
-
- if (strcmp(loginfo->prefix, "") != 0) {
- printf(" --log-prefix");
- xtables_save_string(loginfo->prefix);
- }
-
- if (loginfo->level != LOG_DEFAULT_LEVEL)
- printf(" --log-level %d", loginfo->level);
-
- if (loginfo->logflags & IPT_LOG_TCPSEQ)
- printf(" --log-tcp-sequence");
- if (loginfo->logflags & IPT_LOG_TCPOPT)
- printf(" --log-tcp-options");
- if (loginfo->logflags & IPT_LOG_IPOPT)
- printf(" --log-ip-options");
- if (loginfo->logflags & IPT_LOG_UID)
- printf(" --log-uid");
- if (loginfo->logflags & IPT_LOG_MACDECODE)
- printf(" --log-macdecode");
-}
-
-static const struct ipt_log_xlate ipt_log_xlate_names[] = {
- {"alert", LOG_ALERT },
- {"crit", LOG_CRIT },
- {"debug", LOG_DEBUG },
- {"emerg", LOG_EMERG },
- {"err", LOG_ERR },
- {"info", LOG_INFO },
- {"notice", LOG_NOTICE },
- {"warn", LOG_WARNING }
-};
-
-static int LOG_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- const struct ipt_log_info *loginfo =
- (const struct ipt_log_info *)params->target->data;
- unsigned int i = 0;
-
- xt_xlate_add(xl, "log");
- if (strcmp(loginfo->prefix, "") != 0) {
- if (params->escape_quotes)
- xt_xlate_add(xl, " prefix \\\"%s\\\"", loginfo->prefix);
- else
- xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
- }
-
- for (i = 0; i < ARRAY_SIZE(ipt_log_xlate_names); ++i)
- if (loginfo->level != LOG_DEFAULT_LEVEL &&
- loginfo->level == ipt_log_xlate_names[i].level) {
- xt_xlate_add(xl, " level %s",
- ipt_log_xlate_names[i].name);
- break;
- }
-
- if ((loginfo->logflags & IPT_LOG_MASK) == IPT_LOG_MASK) {
- xt_xlate_add(xl, " flags all");
- } else {
- if (loginfo->logflags & (IPT_LOG_TCPSEQ | IPT_LOG_TCPOPT)) {
- const char *delim = " ";
-
- xt_xlate_add(xl, " flags tcp");
- if (loginfo->logflags & IPT_LOG_TCPSEQ) {
- xt_xlate_add(xl, " sequence");
- delim = ",";
- }
- if (loginfo->logflags & IPT_LOG_TCPOPT)
- xt_xlate_add(xl, "%soptions", delim);
- }
- if (loginfo->logflags & IPT_LOG_IPOPT)
- xt_xlate_add(xl, " flags ip options");
- if (loginfo->logflags & IPT_LOG_UID)
- xt_xlate_add(xl, " flags skuid");
- if (loginfo->logflags & IPT_LOG_MACDECODE)
- xt_xlate_add(xl, " flags ether");
- }
-
- return 1;
-}
-static struct xtables_target log_tg_reg = {
- .name = "LOG",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct ipt_log_info)),
- .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
- .help = LOG_help,
- .init = LOG_init,
- .print = LOG_print,
- .save = LOG_save,
- .x6_parse = LOG_parse,
- .x6_options = LOG_opts,
- .xlate = LOG_xlate,
-};
-
-void _init(void)
-{
- xtables_register_target(&log_tg_reg);
-}
diff --git a/extensions/libipt_LOG.txlate b/extensions/libipt_LOG.txlate
index 81f64fb2..13a2ef55 100644
--- a/extensions/libipt_LOG.txlate
+++ b/extensions/libipt_LOG.txlate
@@ -1,5 +1,5 @@
iptables-translate -A FORWARD -p tcp -j LOG --log-level error
-nft add rule ip filter FORWARD ip protocol tcp counter log level err
+nft 'add rule ip filter FORWARD ip protocol tcp counter log level err'
iptables-translate -A FORWARD -p tcp -j LOG --log-prefix "Random prefix"
-nft add rule ip filter FORWARD ip protocol tcp counter log prefix \"Random prefix\"
+nft 'add rule ip filter FORWARD ip protocol tcp counter log prefix "Random prefix"'
diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c
deleted file mode 100644
index 90bf6065..00000000
--- a/extensions/libipt_MASQUERADE.c
+++ /dev/null
@@ -1,190 +0,0 @@
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <xtables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
- O_TO_PORTS = 0,
- O_RANDOM,
- O_RANDOM_FULLY,
-};
-
-static void MASQUERADE_help(void)
-{
- printf(
-"MASQUERADE target options:\n"
-" --to-ports <port>[-<port>]\n"
-" Port (range) to map to.\n"
-" --random\n"
-" Randomize source port.\n"
-" --random-fully\n"
-" Fully randomize source port.\n");
-}
-
-static const struct xt_option_entry MASQUERADE_opts[] = {
- {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
- {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
- {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-
-static void MASQUERADE_init(struct xt_entry_target *t)
-{
- struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
-
- /* Actually, it's 0, but it's ignored at the moment. */
- mr->rangesize = 1;
-}
-
-/* Parses ports */
-static void
-parse_ports(const char *arg, struct nf_nat_ipv4_multi_range_compat *mr)
-{
- char *end;
- unsigned int port, maxport;
-
- mr->range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
- if (!xtables_strtoui(arg, &end, &port, 0, UINT16_MAX))
- xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-
- switch (*end) {
- case '\0':
- mr->range[0].min.tcp.port
- = mr->range[0].max.tcp.port
- = htons(port);
- return;
- case '-':
- if (!xtables_strtoui(end + 1, NULL, &maxport, 0, UINT16_MAX))
- break;
-
- if (maxport < port)
- break;
-
- mr->range[0].min.tcp.port = htons(port);
- mr->range[0].max.tcp.port = htons(maxport);
- return;
- default:
- break;
- }
- xtables_param_act(XTF_BAD_VALUE, "MASQUERADE", "--to-ports", arg);
-}
-
-static void MASQUERADE_parse(struct xt_option_call *cb)
-{
- const struct ipt_entry *entry = cb->xt_entry;
- int portok;
- struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
-
- if (entry->ip.proto == IPPROTO_TCP
- || entry->ip.proto == IPPROTO_UDP
- || entry->ip.proto == IPPROTO_SCTP
- || entry->ip.proto == IPPROTO_DCCP
- || entry->ip.proto == IPPROTO_ICMP)
- portok = 1;
- else
- portok = 0;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_TO_PORTS:
- if (!portok)
- xtables_error(PARAMETER_PROBLEM,
- "Need TCP, UDP, SCTP or DCCP with port specification");
- parse_ports(cb->arg, mr);
- break;
- case O_RANDOM:
- mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
- break;
- case O_RANDOM_FULLY:
- mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
- break;
- }
-}
-
-static void
-MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
- const struct nf_nat_ipv4_range *r = &mr->range[0];
-
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- printf(" masq ports: ");
- printf("%hu", ntohs(r->min.tcp.port));
- if (r->max.tcp.port != r->min.tcp.port)
- printf("-%hu", ntohs(r->max.tcp.port));
- }
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" random");
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" random-fully");
-}
-
-static void
-MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
- const struct nf_nat_ipv4_range *r = &mr->range[0];
-
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- printf(" --to-ports %hu", ntohs(r->min.tcp.port));
- if (r->max.tcp.port != r->min.tcp.port)
- printf("-%hu", ntohs(r->max.tcp.port));
- }
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" --random");
-
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" --random-fully");
-}
-
-static int MASQUERADE_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- const struct nf_nat_ipv4_multi_range_compat *mr =
- (const void *)params->target->data;
- const struct nf_nat_ipv4_range *r = &mr->range[0];
-
- xt_xlate_add(xl, "masquerade");
-
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- xt_xlate_add(xl, " to :%hu", ntohs(r->min.tcp.port));
- if (r->max.tcp.port != r->min.tcp.port)
- xt_xlate_add(xl, "-%hu", ntohs(r->max.tcp.port));
- }
-
- xt_xlate_add(xl, " ");
- if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
- xt_xlate_add(xl, "random ");
-
- return 1;
-}
-
-static struct xtables_target masquerade_tg_reg = {
- .name = "MASQUERADE",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
- .help = MASQUERADE_help,
- .init = MASQUERADE_init,
- .x6_parse = MASQUERADE_parse,
- .print = MASQUERADE_print,
- .save = MASQUERADE_save,
- .x6_options = MASQUERADE_opts,
- .xlate = MASQUERADE_xlate,
-};
-
-void _init(void)
-{
- xtables_register_target(&masquerade_tg_reg);
-}
diff --git a/extensions/libipt_MASQUERADE.txlate b/extensions/libipt_MASQUERADE.txlate
index 40b6958a..0293b05b 100644
--- a/extensions/libipt_MASQUERADE.txlate
+++ b/extensions/libipt_MASQUERADE.txlate
@@ -1,8 +1,17 @@
iptables-translate -t nat -A POSTROUTING -j MASQUERADE
-nft add rule ip nat POSTROUTING counter masquerade
+nft 'add rule ip nat POSTROUTING counter masquerade'
iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10
-nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10
+nft 'add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10'
iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --to-ports 10-20 --random
-nft add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10-20 random
+nft 'add rule ip nat POSTROUTING ip protocol tcp counter masquerade to :10-20 random'
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random
+nft 'add rule ip nat POSTROUTING ip protocol tcp counter masquerade random'
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random-fully
+nft 'add rule ip nat POSTROUTING ip protocol tcp counter masquerade fully-random'
+
+iptables-translate -t nat -A POSTROUTING -p tcp -j MASQUERADE --random --random-fully
+nft 'add rule ip nat POSTROUTING ip protocol tcp counter masquerade random,fully-random'
diff --git a/extensions/libipt_NETMAP.t b/extensions/libipt_NETMAP.t
index 31924b98..0de856f0 100644
--- a/extensions/libipt_NETMAP.t
+++ b/extensions/libipt_NETMAP.t
@@ -1,4 +1,4 @@
:PREROUTING,INPUT,OUTPUT,POSTROUTING
*nat
-j NETMAP --to 1.2.3.0/24;=;OK
--j NETMAP --to 1.2.3.4;=;OK
+-j NETMAP --to 1.2.3.4;-j NETMAP --to 1.2.3.4/32;OK
diff --git a/extensions/libipt_REJECT.t b/extensions/libipt_REJECT.t
index 5b26b107..3f69a729 100644
--- a/extensions/libipt_REJECT.t
+++ b/extensions/libipt_REJECT.t
@@ -1,5 +1,5 @@
:INPUT,FORWARD,OUTPUT
--j REJECT;=;OK
+-j REJECT;-j REJECT --reject-with icmp-port-unreachable;OK
-j REJECT --reject-with icmp-net-unreachable;=;OK
-j REJECT --reject-with icmp-host-unreachable;=;OK
-j REJECT --reject-with icmp-port-unreachable;=;OK
diff --git a/extensions/libipt_REJECT.txlate b/extensions/libipt_REJECT.txlate
index a1bfb5f4..022166a6 100644
--- a/extensions/libipt_REJECT.txlate
+++ b/extensions/libipt_REJECT.txlate
@@ -1,8 +1,8 @@
iptables-translate -A FORWARD -p TCP --dport 22 -j REJECT
-nft add rule ip filter FORWARD tcp dport 22 counter reject
+nft 'add rule ip filter FORWARD tcp dport 22 counter reject'
iptables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with icmp-net-unreachable
-nft add rule ip filter FORWARD tcp dport 22 counter reject with icmp type net-unreachable
+nft 'add rule ip filter FORWARD tcp dport 22 counter reject with icmp type net-unreachable'
iptables-translate -A FORWARD -p TCP --dport 22 -j REJECT --reject-with tcp-reset
-nft add rule ip filter FORWARD tcp dport 22 counter reject with tcp reset
+nft 'add rule ip filter FORWARD tcp dport 22 counter reject with tcp reset'
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
deleted file mode 100644
index 211a20bc..00000000
--- a/extensions/libipt_SNAT.c
+++ /dev/null
@@ -1,280 +0,0 @@
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <xtables.h>
-#include <iptables.h>
-#include <limits.h> /* INT_MAX in ip_tables.h */
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter/nf_nat.h>
-
-enum {
- O_TO_SRC = 0,
- O_RANDOM,
- O_RANDOM_FULLY,
- O_PERSISTENT,
- F_TO_SRC = 1 << O_TO_SRC,
- F_RANDOM = 1 << O_RANDOM,
- F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
-};
-
-static void SNAT_help(void)
-{
- printf(
-"SNAT target options:\n"
-" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
-" Address to map source to.\n"
-"[--random] [--random-fully] [--persistent]\n");
-}
-
-static const struct xt_option_entry SNAT_opts[] = {
- {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
- .flags = XTOPT_MAND},
- {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
- {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
- {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
- XTOPT_TABLEEND,
-};
-
-/* Ranges expected in network order. */
-static void
-parse_to(const char *orig_arg, int portok, struct nf_nat_ipv4_range *range)
-{
- char *arg, *colon, *dash, *error;
- const struct in_addr *ip;
-
- arg = xtables_strdup(orig_arg);
- colon = strchr(arg, ':');
-
- if (colon) {
- int port;
-
- if (!portok)
- xtables_error(PARAMETER_PROBLEM,
- "Need TCP, UDP, SCTP or DCCP with port specification");
-
- range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
-
- port = atoi(colon+1);
- if (port <= 0 || port > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", colon+1);
-
- error = strchr(colon+1, ':');
- if (error)
- xtables_error(PARAMETER_PROBLEM,
- "Invalid port:port syntax - use dash\n");
-
- dash = strchr(colon, '-');
- if (!dash) {
- range->min.tcp.port
- = range->max.tcp.port
- = htons(port);
- } else {
- int maxport;
-
- maxport = atoi(dash + 1);
- if (maxport <= 0 || maxport > 65535)
- xtables_error(PARAMETER_PROBLEM,
- "Port `%s' not valid\n", dash+1);
- if (maxport < port)
- /* People are stupid. */
- xtables_error(PARAMETER_PROBLEM,
- "Port range `%s' funky\n", colon+1);
- range->min.tcp.port = htons(port);
- range->max.tcp.port = htons(maxport);
- }
- /* Starts with a colon? No IP info...*/
- if (colon == arg) {
- free(arg);
- return;
- }
- *colon = '\0';
- }
-
- range->flags |= NF_NAT_RANGE_MAP_IPS;
- dash = strchr(arg, '-');
- if (colon && dash && dash > colon)
- dash = NULL;
-
- if (dash)
- *dash = '\0';
-
- ip = xtables_numeric_to_ipaddr(arg);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- arg);
- range->min_ip = ip->s_addr;
- if (dash) {
- ip = xtables_numeric_to_ipaddr(dash+1);
- if (!ip)
- xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
- dash+1);
- range->max_ip = ip->s_addr;
- } else
- range->max_ip = range->min_ip;
-
- free(arg);
- return;
-}
-
-static void SNAT_parse(struct xt_option_call *cb)
-{
- struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
- const struct ipt_entry *entry = cb->xt_entry;
- int portok;
-
- if (entry->ip.proto == IPPROTO_TCP
- || entry->ip.proto == IPPROTO_UDP
- || entry->ip.proto == IPPROTO_SCTP
- || entry->ip.proto == IPPROTO_DCCP
- || entry->ip.proto == IPPROTO_ICMP)
- portok = 1;
- else
- portok = 0;
-
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_TO_SRC:
- parse_to(cb->arg, portok, mr->range);
- break;
- case O_PERSISTENT:
- mr->range->flags |= NF_NAT_RANGE_PERSISTENT;
- break;
- }
-}
-
-static void SNAT_fcheck(struct xt_fcheck_call *cb)
-{
- static const unsigned int f = F_TO_SRC | F_RANDOM;
- static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
- struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
-
- if ((cb->xflags & f) == f)
- mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
- if ((cb->xflags & r) == r)
- mr->range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
-
- mr->rangesize = 1;
-}
-
-static void print_range(const struct nf_nat_ipv4_range *r)
-{
- if (r->flags & NF_NAT_RANGE_MAP_IPS) {
- struct in_addr a;
-
- a.s_addr = r->min_ip;
- printf("%s", xtables_ipaddr_to_numeric(&a));
- if (r->max_ip != r->min_ip) {
- a.s_addr = r->max_ip;
- printf("-%s", xtables_ipaddr_to_numeric(&a));
- }
- }
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- printf(":");
- printf("%hu", ntohs(r->min.tcp.port));
- if (r->max.tcp.port != r->min.tcp.port)
- printf("-%hu", ntohs(r->max.tcp.port));
- }
-}
-
-static void SNAT_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct nf_nat_ipv4_multi_range_compat *mr =
- (const void *)target->data;
-
- printf(" to:");
- print_range(mr->range);
- if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" random");
- if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" random-fully");
- if (mr->range->flags & NF_NAT_RANGE_PERSISTENT)
- printf(" persistent");
-}
-
-static void SNAT_save(const void *ip, const struct xt_entry_target *target)
-{
- const struct nf_nat_ipv4_multi_range_compat *mr =
- (const void *)target->data;
-
- printf(" --to-source ");
- print_range(mr->range);
- if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM)
- printf(" --random");
- if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
- printf(" --random-fully");
- if (mr->range->flags & NF_NAT_RANGE_PERSISTENT)
- printf(" --persistent");
-}
-
-static void print_range_xlate(const struct nf_nat_ipv4_range *r,
- struct xt_xlate *xl)
-{
- if (r->flags & NF_NAT_RANGE_MAP_IPS) {
- struct in_addr a;
-
- a.s_addr = r->min_ip;
- xt_xlate_add(xl, "%s", xtables_ipaddr_to_numeric(&a));
- if (r->max_ip != r->min_ip) {
- a.s_addr = r->max_ip;
- xt_xlate_add(xl, "-%s", xtables_ipaddr_to_numeric(&a));
- }
- }
- if (r->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
- xt_xlate_add(xl, ":");
- xt_xlate_add(xl, "%hu", ntohs(r->min.tcp.port));
- if (r->max.tcp.port != r->min.tcp.port)
- xt_xlate_add(xl, "-%hu", ntohs(r->max.tcp.port));
- }
-}
-
-static int SNAT_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- const struct nf_nat_ipv4_multi_range_compat *mr =
- (const void *)params->target->data;
- bool sep_need = false;
- const char *sep = " ";
-
- xt_xlate_add(xl, "snat to ");
- print_range_xlate(mr->range, xl);
- if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM) {
- xt_xlate_add(xl, " random");
- sep_need = true;
- }
- if (mr->range->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
- if (sep_need)
- sep = ",";
- xt_xlate_add(xl, "%sfully-random", sep);
- sep_need = true;
- }
- if (mr->range->flags & NF_NAT_RANGE_PERSISTENT) {
- if (sep_need)
- sep = ",";
- xt_xlate_add(xl, "%spersistent", sep);
- }
-
- return 1;
-}
-
-static struct xtables_target snat_tg_reg = {
- .name = "SNAT",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
- .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
- .help = SNAT_help,
- .x6_parse = SNAT_parse,
- .x6_fcheck = SNAT_fcheck,
- .print = SNAT_print,
- .save = SNAT_save,
- .x6_options = SNAT_opts,
- .xlate = SNAT_xlate,
-};
-
-void _init(void)
-{
- xtables_register_target(&snat_tg_reg);
-}
diff --git a/extensions/libipt_SNAT.t b/extensions/libipt_SNAT.t
index 186e1cb8..c31d6e7c 100644
--- a/extensions/libipt_SNAT.t
+++ b/extensions/libipt_SNAT.t
@@ -4,6 +4,12 @@
-j SNAT --to-source 1.1.1.1-1.1.1.10;=;OK
-j SNAT --to-source 1.1.1.1:1025-65535;;FAIL
-j SNAT --to-source 1.1.1.1 --to-source 2.2.2.2;;FAIL
+-j SNAT --to-source 1.1.1.1 --random;=;OK
+-j SNAT --to-source 1.1.1.1 --random-fully;=;OK
+-j SNAT --to-source 1.1.1.1 --persistent;=;OK
+-j SNAT --to-source 1.1.1.1 --random --persistent;=;OK
+-j SNAT --to-source 1.1.1.1 --random --random-fully;=;OK
+-j SNAT --to-source 1.1.1.1 --random --random-fully --persistent;=;OK
-p tcp -j SNAT --to-source 1.1.1.1:1025-65535;=;OK
-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65535;=;OK
-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65536;;FAIL
diff --git a/extensions/libipt_SNAT.txlate b/extensions/libipt_SNAT.txlate
index 01592fad..83afef95 100644
--- a/extensions/libipt_SNAT.txlate
+++ b/extensions/libipt_SNAT.txlate
@@ -1,14 +1,14 @@
iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4
-nft add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4
+nft 'add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4'
iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6
-nft add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4-1.2.3.6
+nft 'add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4-1.2.3.6'
iptables-translate -t nat -A postrouting -p tcp -o eth0 -j SNAT --to 1.2.3.4:1-1023
-nft add rule ip nat postrouting oifname "eth0" ip protocol tcp counter snat to 1.2.3.4:1-1023
+nft 'add rule ip nat postrouting oifname "eth0" ip protocol tcp counter snat to 1.2.3.4:1-1023'
iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4 --random
-nft add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4 random
+nft 'add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4 random'
iptables-translate -t nat -A postrouting -o eth0 -j SNAT --to 1.2.3.4 --random --persistent
-nft add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4 random,persistent
+nft 'add rule ip nat postrouting oifname "eth0" counter snat to 1.2.3.4 random,persistent'
diff --git a/extensions/libipt_ah.txlate b/extensions/libipt_ah.txlate
index ea3ef3e9..897c82b5 100644
--- a/extensions/libipt_ah.txlate
+++ b/extensions/libipt_ah.txlate
@@ -1,8 +1,8 @@
iptables-translate -A INPUT -p 51 -m ah --ahspi 500 -j DROP
-nft add rule ip filter INPUT ah spi 500 counter drop
+nft 'add rule ip filter INPUT ah spi 500 counter drop'
iptables-translate -A INPUT -p 51 -m ah --ahspi 500:600 -j DROP
-nft add rule ip filter INPUT ah spi 500-600 counter drop
+nft 'add rule ip filter INPUT ah spi 500-600 counter drop'
iptables-translate -A INPUT -p 51 -m ah ! --ahspi 50 -j DROP
-nft add rule ip filter INPUT ah spi != 50 counter drop
+nft 'add rule ip filter INPUT ah spi != 50 counter drop'
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
index e5e23661..b0318aeb 100644
--- a/extensions/libipt_icmp.c
+++ b/extensions/libipt_icmp.c
@@ -19,61 +19,6 @@ enum {
O_ICMP_TYPE = 0,
};
-static const struct xt_icmp_names icmp_codes[] = {
- { "any", 0xFF, 0, 0xFF },
- { "echo-reply", 0, 0, 0xFF },
- /* Alias */ { "pong", 0, 0, 0xFF },
-
- { "destination-unreachable", 3, 0, 0xFF },
- { "network-unreachable", 3, 0, 0 },
- { "host-unreachable", 3, 1, 1 },
- { "protocol-unreachable", 3, 2, 2 },
- { "port-unreachable", 3, 3, 3 },
- { "fragmentation-needed", 3, 4, 4 },
- { "source-route-failed", 3, 5, 5 },
- { "network-unknown", 3, 6, 6 },
- { "host-unknown", 3, 7, 7 },
- { "network-prohibited", 3, 9, 9 },
- { "host-prohibited", 3, 10, 10 },
- { "TOS-network-unreachable", 3, 11, 11 },
- { "TOS-host-unreachable", 3, 12, 12 },
- { "communication-prohibited", 3, 13, 13 },
- { "host-precedence-violation", 3, 14, 14 },
- { "precedence-cutoff", 3, 15, 15 },
-
- { "source-quench", 4, 0, 0xFF },
-
- { "redirect", 5, 0, 0xFF },
- { "network-redirect", 5, 0, 0 },
- { "host-redirect", 5, 1, 1 },
- { "TOS-network-redirect", 5, 2, 2 },
- { "TOS-host-redirect", 5, 3, 3 },
-
- { "echo-request", 8, 0, 0xFF },
- /* Alias */ { "ping", 8, 0, 0xFF },
-
- { "router-advertisement", 9, 0, 0xFF },
-
- { "router-solicitation", 10, 0, 0xFF },
-
- { "time-exceeded", 11, 0, 0xFF },
- /* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
- { "ttl-zero-during-transit", 11, 0, 0 },
- { "ttl-zero-during-reassembly", 11, 1, 1 },
-
- { "parameter-problem", 12, 0, 0xFF },
- { "ip-header-bad", 12, 0, 0 },
- { "required-option-missing", 12, 1, 1 },
-
- { "timestamp-request", 13, 0, 0xFF },
-
- { "timestamp-reply", 14, 0, 0xFF },
-
- { "address-mask-request", 17, 0, 0xFF },
-
- { "address-mask-reply", 18, 0, 0xFF }
-};
-
static void icmp_help(void)
{
printf(
@@ -90,59 +35,6 @@ static const struct xt_option_entry icmp_opts[] = {
XTOPT_TABLEEND,
};
-static void
-parse_icmp(const char *icmptype, uint8_t *type, uint8_t code[])
-{
- static const unsigned int limit = ARRAY_SIZE(icmp_codes);
- unsigned int match = limit;
- unsigned int i;
-
- for (i = 0; i < limit; i++) {
- if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype))
- == 0) {
- if (match != limit)
- xtables_error(PARAMETER_PROBLEM,
- "Ambiguous ICMP type `%s':"
- " `%s' or `%s'?",
- icmptype,
- icmp_codes[match].name,
- icmp_codes[i].name);
- match = i;
- }
- }
-
- if (match != limit) {
- *type = icmp_codes[match].type;
- code[0] = icmp_codes[match].code_min;
- code[1] = icmp_codes[match].code_max;
- } else {
- char *slash;
- char buffer[strlen(icmptype) + 1];
- unsigned int number;
-
- strcpy(buffer, icmptype);
- slash = strchr(buffer, '/');
-
- if (slash)
- *slash = '\0';
-
- if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "Invalid ICMP type `%s'\n", buffer);
- *type = number;
- if (slash) {
- if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
- xtables_error(PARAMETER_PROBLEM,
- "Invalid ICMP code `%s'\n",
- slash+1);
- code[0] = code[1] = number;
- } else {
- code[0] = 0;
- code[1] = 0xFF;
- }
- }
-}
-
static void icmp_init(struct xt_entry_match *m)
{
struct ipt_icmp *icmpinfo = (struct ipt_icmp *)m->data;
@@ -156,7 +48,7 @@ static void icmp_parse(struct xt_option_call *cb)
struct ipt_icmp *icmpinfo = cb->data;
xtables_option_parse(cb);
- parse_icmp(cb->arg, &icmpinfo->type, icmpinfo->code);
+ ipt_parse_icmp(cb->arg, &icmpinfo->type, icmpinfo->code);
if (cb->invert)
icmpinfo->invflags |= IPT_ICMP_INV;
}
diff --git a/extensions/libipt_icmp.txlate b/extensions/libipt_icmp.txlate
index a2aec8e2..e7208d8b 100644
--- a/extensions/libipt_icmp.txlate
+++ b/extensions/libipt_icmp.txlate
@@ -1,11 +1,11 @@
iptables-translate -t filter -A INPUT -m icmp --icmp-type echo-reply -j ACCEPT
-nft add rule ip filter INPUT icmp type echo-reply counter accept
+nft 'add rule ip filter INPUT icmp type echo-reply counter accept'
iptables-translate -t filter -A INPUT -m icmp --icmp-type 3 -j ACCEPT
-nft add rule ip filter INPUT icmp type destination-unreachable counter accept
+nft 'add rule ip filter INPUT icmp type destination-unreachable counter accept'
iptables-translate -t filter -A INPUT -m icmp ! --icmp-type 3 -j ACCEPT
-nft add rule ip filter INPUT icmp type != destination-unreachable counter accept
+nft 'add rule ip filter INPUT icmp type != destination-unreachable counter accept'
iptables-translate -t filter -A INPUT -m icmp --icmp-type any -j ACCEPT
-nft add rule ip filter INPUT ip protocol icmp counter accept
+nft 'add rule ip filter INPUT ip protocol icmp counter accept'
diff --git a/extensions/libipt_realm.txlate b/extensions/libipt_realm.txlate
index 7d710294..6d134546 100644
--- a/extensions/libipt_realm.txlate
+++ b/extensions/libipt_realm.txlate
@@ -1,11 +1,11 @@
iptables-translate -A PREROUTING -m realm --realm 4
-nft add rule ip filter PREROUTING rtclassid 0x4 counter
+nft 'add rule ip filter PREROUTING rtclassid 0x4 counter'
iptables-translate -A PREROUTING -m realm --realm 5/5
-nft add rule ip filter PREROUTING rtclassid and 0x5 == 0x5 counter
+nft 'add rule ip filter PREROUTING rtclassid and 0x5 == 0x5 counter'
iptables-translate -A PREROUTING -m realm ! --realm 50
-nft add rule ip filter PREROUTING rtclassid != 0x32 counter
+nft 'add rule ip filter PREROUTING rtclassid != 0x32 counter'
iptables-translate -A INPUT -m realm --realm 1/0xf
-nft add rule ip filter INPUT rtclassid and 0xf == 0x1 counter
+nft 'add rule ip filter INPUT rtclassid and 0xf == 0x1 counter'
diff --git a/extensions/libipt_ttl.c b/extensions/libipt_ttl.c
index 6bdd2196..86ba554e 100644
--- a/extensions/libipt_ttl.c
+++ b/extensions/libipt_ttl.c
@@ -106,7 +106,7 @@ static int ttl_xlate(struct xt_xlate *xl,
const struct ipt_ttl_info *info =
(struct ipt_ttl_info *) params->match->data;
- switch (info->mode) {
+ switch (info->mode) {
case IPT_TTL_EQ:
xt_xlate_add(xl, "ip ttl");
break;
@@ -121,7 +121,7 @@ static int ttl_xlate(struct xt_xlate *xl,
break;
default:
/* Should not happen. */
- break;
+ return 0;
}
xt_xlate_add(xl, " %u", info->ttl);
diff --git a/extensions/libipt_ttl.txlate b/extensions/libipt_ttl.txlate
index 3d5d6a70..6b90ff99 100644
--- a/extensions/libipt_ttl.txlate
+++ b/extensions/libipt_ttl.txlate
@@ -1,5 +1,5 @@
iptables-translate -A INPUT -m ttl --ttl-eq 3 -j ACCEPT
-nft add rule ip filter INPUT ip ttl 3 counter accept
+nft 'add rule ip filter INPUT ip ttl 3 counter accept'
iptables-translate -A INPUT -m ttl --ttl-gt 5 -j ACCEPT
-nft add rule ip filter INPUT ip ttl gt 5 counter accept
+nft 'add rule ip filter INPUT ip ttl gt 5 counter accept'
diff --git a/extensions/libxt_AUDIT.txlate b/extensions/libxt_AUDIT.txlate
index abd11eae..c1650b9a 100644
--- a/extensions/libxt_AUDIT.txlate
+++ b/extensions/libxt_AUDIT.txlate
@@ -1,8 +1,8 @@
iptables-translate -t filter -A INPUT -j AUDIT --type accept
-nft add rule ip filter INPUT counter log level audit
+nft 'add rule ip filter INPUT counter log level audit'
iptables-translate -t filter -A INPUT -j AUDIT --type drop
-nft add rule ip filter INPUT counter log level audit
+nft 'add rule ip filter INPUT counter log level audit'
iptables-translate -t filter -A INPUT -j AUDIT --type reject
-nft add rule ip filter INPUT counter log level audit
+nft 'add rule ip filter INPUT counter log level audit'
diff --git a/extensions/libxt_CLASSIFY.txlate b/extensions/libxt_CLASSIFY.txlate
index 3b349237..3150c69e 100644
--- a/extensions/libxt_CLASSIFY.txlate
+++ b/extensions/libxt_CLASSIFY.txlate
@@ -1,8 +1,8 @@
iptables-translate -A OUTPUT -j CLASSIFY --set-class 0:0
-nft add rule ip filter OUTPUT counter meta priority set none
+nft 'add rule ip filter OUTPUT counter meta priority set none'
iptables-translate -A OUTPUT -j CLASSIFY --set-class ffff:ffff
-nft add rule ip filter OUTPUT counter meta priority set root
+nft 'add rule ip filter OUTPUT counter meta priority set root'
iptables-translate -A OUTPUT -j CLASSIFY --set-class 1:234
-nft add rule ip filter OUTPUT counter meta priority set 1:234
+nft 'add rule ip filter OUTPUT counter meta priority set 1:234'
diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c
index 21e10913..a6568c99 100644
--- a/extensions/libxt_CONNMARK.c
+++ b/extensions/libxt_CONNMARK.c
@@ -595,11 +595,11 @@ static int connmark_tg_xlate_v2(struct xt_xlate *xl,
{
const struct xt_connmark_tginfo2 *info =
(const void *)params->target->data;
- const char *shift_op = xt_connmark_shift_ops[info->shift_dir];
+ const char *braces = info->shift_bits ? "( " : "";
switch (info->mode) {
case XT_CONNMARK_SET:
- xt_xlate_add(xl, "ct mark set ");
+ xt_xlate_add(xl, "ct mark set %s", braces);
if (info->ctmask == 0xFFFFFFFFU)
xt_xlate_add(xl, "0x%x ", info->ctmark);
else if (info->ctmark == 0)
@@ -615,26 +615,31 @@ static int connmark_tg_xlate_v2(struct xt_xlate *xl,
info->ctmark, ~info->ctmask);
break;
case XT_CONNMARK_SAVE:
- xt_xlate_add(xl, "ct mark set mark");
+ xt_xlate_add(xl, "ct mark set %smark", braces);
if (!(info->nfmask == UINT32_MAX &&
info->ctmask == UINT32_MAX)) {
if (info->nfmask == info->ctmask)
xt_xlate_add(xl, " and 0x%x", info->nfmask);
+ else
+ return 0;
}
break;
case XT_CONNMARK_RESTORE:
- xt_xlate_add(xl, "meta mark set ct mark");
+ xt_xlate_add(xl, "meta mark set %sct mark", braces);
if (!(info->nfmask == UINT32_MAX &&
info->ctmask == UINT32_MAX)) {
if (info->nfmask == info->ctmask)
xt_xlate_add(xl, " and 0x%x", info->nfmask);
+ else
+ return 0;
}
break;
}
if (info->mode <= XT_CONNMARK_RESTORE &&
info->shift_bits != 0) {
- xt_xlate_add(xl, " %s %u", shift_op, info->shift_bits);
+ xt_xlate_add(xl, " ) %s %u",
+ info->shift_dir ? ">>" : "<<", info->shift_bits);
}
return 1;
diff --git a/extensions/libxt_CONNMARK.t b/extensions/libxt_CONNMARK.t
index 79a838fe..c9b2b4a5 100644
--- a/extensions/libxt_CONNMARK.t
+++ b/extensions/libxt_CONNMARK.t
@@ -1,7 +1,7 @@
:PREROUTING,FORWARD,OUTPUT,POSTROUTING
*mangle
--j CONNMARK --restore-mark;=;OK
--j CONNMARK --save-mark;=;OK
--j CONNMARK --save-mark --nfmask 0xfffffff --ctmask 0xffffffff;-j CONNMARK --save-mark;OK
--j CONNMARK --restore-mark --nfmask 0xfffffff --ctmask 0xffffffff;-j CONNMARK --restore-mark;OK
+-j CONNMARK --restore-mark;-j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff;OK
+-j CONNMARK --save-mark;-j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff;OK
+-j CONNMARK --save-mark --nfmask 0xfffffff --ctmask 0xffffffff;=;OK
+-j CONNMARK --restore-mark --nfmask 0xfffffff --ctmask 0xffffffff;=;OK
-j CONNMARK;;FAIL
diff --git a/extensions/libxt_CONNMARK.txlate b/extensions/libxt_CONNMARK.txlate
index ce40ae5e..5da4d6c7 100644
--- a/extensions/libxt_CONNMARK.txlate
+++ b/extensions/libxt_CONNMARK.txlate
@@ -1,20 +1,23 @@
iptables-translate -t mangle -A PREROUTING -j CONNMARK --set-mark 0
-nft add rule ip mangle PREROUTING counter ct mark set 0x0
+nft 'add rule ip mangle PREROUTING counter ct mark set 0x0'
iptables-translate -t mangle -A PREROUTING -j CONNMARK --set-mark 0x16
-nft add rule ip mangle PREROUTING counter ct mark set 0x16
+nft 'add rule ip mangle PREROUTING counter ct mark set 0x16'
iptables-translate -t mangle -A PREROUTING -j CONNMARK --set-xmark 0x16/0x12
-nft add rule ip mangle PREROUTING counter ct mark set ct mark xor 0x16 and 0xffffffed
+nft 'add rule ip mangle PREROUTING counter ct mark set ct mark xor 0x16 and 0xffffffed'
iptables-translate -t mangle -A PREROUTING -j CONNMARK --and-mark 0x16
-nft add rule ip mangle PREROUTING counter ct mark set ct mark and 0x16
+nft 'add rule ip mangle PREROUTING counter ct mark set ct mark and 0x16'
iptables-translate -t mangle -A PREROUTING -j CONNMARK --or-mark 0x16
-nft add rule ip mangle PREROUTING counter ct mark set ct mark or 0x16
+nft 'add rule ip mangle PREROUTING counter ct mark set ct mark or 0x16'
iptables-translate -t mangle -A PREROUTING -j CONNMARK --save-mark
-nft add rule ip mangle PREROUTING counter ct mark set mark
+nft 'add rule ip mangle PREROUTING counter ct mark set mark'
iptables-translate -t mangle -A PREROUTING -j CONNMARK --restore-mark
-nft add rule ip mangle PREROUTING counter meta mark set ct mark
+nft 'add rule ip mangle PREROUTING counter meta mark set ct mark'
+
+iptables-translate -t mangle -A PREROUTING -j CONNMARK --set-mark 0x23/0x42 --right-shift-mark 5
+nft 'add rule ip mangle PREROUTING counter ct mark set ( ct mark xor 0x23 and 0xffffff9c ) >> 5'
diff --git a/extensions/libxt_CONNSECMARK.c b/extensions/libxt_CONNSECMARK.c
index 0b3cd79d..6da589d3 100644
--- a/extensions/libxt_CONNSECMARK.c
+++ b/extensions/libxt_CONNSECMARK.c
@@ -66,7 +66,8 @@ static void print_connsecmark(const struct xt_connsecmark_target_info *info)
break;
default:
- xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+ xtables_error(OTHER_PROBLEM,
+ PFX "invalid mode %hhu", info->mode);
}
}
diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c
index fbbbe266..18824665 100644
--- a/extensions/libxt_CT.c
+++ b/extensions/libxt_CT.c
@@ -117,7 +117,7 @@ static void ct_parse_zone_id(const char *opt, unsigned int opt_id,
if (!xtables_strtoul(opt, NULL, &val, 0, UINT16_MAX))
xtables_error(PARAMETER_PROBLEM,
- "Cannot parse %s as a zone ID\n", opt);
+ "Cannot parse %s as a zone ID", opt);
*zone_id = (uint16_t)val;
}
diff --git a/extensions/libxt_DNAT.txlate b/extensions/libxt_DNAT.txlate
index a6597656..e005245d 100644
--- a/extensions/libxt_DNAT.txlate
+++ b/extensions/libxt_DNAT.txlate
@@ -1,35 +1,35 @@
iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4
-nft add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4
+nft 'add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4'
iptables-translate -t nat -A prerouting -p tcp -d 15.45.23.67 --dport 80 -j DNAT --to-destination 192.168.1.1-192.168.1.10
-nft add rule ip nat prerouting ip daddr 15.45.23.67 tcp dport 80 counter dnat to 192.168.1.1-192.168.1.10
+nft 'add rule ip nat prerouting ip daddr 15.45.23.67 tcp dport 80 counter dnat to 192.168.1.1-192.168.1.10'
iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4:1-1023
-nft add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4:1-1023
+nft 'add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4:1-1023'
iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4 --random
-nft add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4 random
+nft 'add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4 random'
iptables-translate -t nat -A prerouting -p tcp -o eth0 -j DNAT --to-destination 1.2.3.4 --random --persistent
-nft add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4 random,persistent
+nft 'add rule ip nat prerouting oifname "eth0" ip protocol tcp counter dnat to 1.2.3.4 random,persistent'
ip6tables-translate -t nat -A prerouting -p tcp --dport 8080 -j DNAT --to-destination fec0::1234
-nft add rule ip6 nat prerouting tcp dport 8080 counter dnat to fec0::1234
+nft 'add rule ip6 nat prerouting tcp dport 8080 counter dnat to fec0::1234'
ip6tables-translate -t nat -A prerouting -p tcp --dport 8080 -j DNAT --to-destination fec0::1234-fec0::2000
-nft add rule ip6 nat prerouting tcp dport 8080 counter dnat to fec0::1234-fec0::2000
+nft 'add rule ip6 nat prerouting tcp dport 8080 counter dnat to fec0::1234-fec0::2000'
ip6tables-translate -t nat -A prerouting -i eth1 -p tcp --dport 8080 -j DNAT --to-destination [fec0::1234]:80
-nft add rule ip6 nat prerouting iifname "eth1" tcp dport 8080 counter dnat to [fec0::1234]:80
+nft 'add rule ip6 nat prerouting iifname "eth1" tcp dport 8080 counter dnat to [fec0::1234]:80'
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:1-20
-nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:1-20
+nft 'add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:1-20'
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234-fec0::2000]:1-20
-nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234-fec0::2000]:1-20
+nft 'add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234-fec0::2000]:1-20'
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:80 --persistent
-nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 persistent
+nft 'add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 persistent'
ip6tables-translate -t nat -A prerouting -p tcp -j DNAT --to-destination [fec0::1234]:80 --random --persistent
-nft add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 random,persistent
+nft 'add rule ip6 nat prerouting meta l4proto tcp counter dnat to [fec0::1234]:80 random,persistent'
diff --git a/extensions/libxt_DSCP.t b/extensions/libxt_DSCP.t
index fcc55986..762fcd31 100644
--- a/extensions/libxt_DSCP.t
+++ b/extensions/libxt_DSCP.t
@@ -1,6 +1,6 @@
:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
*mangle
--j DSCP --set-dscp 0;=;OK
+-j DSCP --set-dscp 0x00;=;OK
-j DSCP --set-dscp 0x3f;=;OK
-j DSCP --set-dscp -1;;FAIL
-j DSCP --set-dscp 0x40;;FAIL
diff --git a/extensions/libxt_DSCP.txlate b/extensions/libxt_DSCP.txlate
index 442742ef..f7801a83 100644
--- a/extensions/libxt_DSCP.txlate
+++ b/extensions/libxt_DSCP.txlate
@@ -1,5 +1,5 @@
iptables-translate -A OUTPUT -j DSCP --set-dscp 1
-nft add rule ip filter OUTPUT counter ip dscp set 0x01
+nft 'add rule ip filter OUTPUT counter ip dscp set 0x01'
ip6tables-translate -A OUTPUT -j DSCP --set-dscp 6
-nft add rule ip6 filter OUTPUT counter ip6 dscp set 0x06
+nft 'add rule ip6 filter OUTPUT counter ip6 dscp set 0x06'
diff --git a/extensions/libxt_IDLETIMER.t b/extensions/libxt_IDLETIMER.t
index e8f306d2..3345d5be 100644
--- a/extensions/libxt_IDLETIMER.t
+++ b/extensions/libxt_IDLETIMER.t
@@ -2,4 +2,4 @@
-j IDLETIMER --timeout;;FAIL
-j IDLETIMER --timeout 42;;FAIL
-j IDLETIMER --timeout 42 --label foo;=;OK
--j IDLETIMER --timeout 42 --label foo --alarm;;OK
+-j IDLETIMER --timeout 42 --label bar --alarm;=;OK
diff --git a/extensions/libxt_LOG.c b/extensions/libxt_LOG.c
new file mode 100644
index 00000000..b6fe0b2e
--- /dev/null
+++ b/extensions/libxt_LOG.c
@@ -0,0 +1,204 @@
+#include <stdio.h>
+#include <string.h>
+#define SYSLOG_NAMES
+#include <syslog.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_LOG.h>
+
+#define LOG_DEFAULT_LEVEL LOG_WARNING
+
+enum {
+ /* make sure the values correspond with XT_LOG_* bit positions */
+ O_LOG_TCPSEQ = 0,
+ O_LOG_TCPOPTS,
+ O_LOG_IPOPTS,
+ O_LOG_UID,
+ __O_LOG_NFLOG,
+ O_LOG_MAC,
+ O_LOG_LEVEL,
+ O_LOG_PREFIX,
+};
+
+static void LOG_help(void)
+{
+ printf(
+"LOG target options:\n"
+" --log-level level Level of logging (numeric or see syslog.conf)\n"
+" --log-prefix prefix Prefix log messages with this prefix.\n"
+" --log-tcp-sequence Log TCP sequence numbers.\n"
+" --log-tcp-options Log TCP options.\n"
+" --log-ip-options Log IP options.\n"
+" --log-uid Log UID owning the local socket.\n"
+" --log-macdecode Decode MAC addresses and protocol.\n");
+}
+
+#define s struct xt_log_info
+static const struct xt_option_entry LOG_opts[] = {
+ {.name = "log-level", .id = O_LOG_LEVEL, .type = XTTYPE_SYSLOGLEVEL,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, level)},
+ {.name = "log-prefix", .id = O_LOG_PREFIX, .type = XTTYPE_STRING,
+ .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix), .min = 1},
+ {.name = "log-tcp-sequence", .id = O_LOG_TCPSEQ, .type = XTTYPE_NONE},
+ {.name = "log-tcp-options", .id = O_LOG_TCPOPTS, .type = XTTYPE_NONE},
+ {.name = "log-ip-options", .id = O_LOG_IPOPTS, .type = XTTYPE_NONE},
+ {.name = "log-uid", .id = O_LOG_UID, .type = XTTYPE_NONE},
+ {.name = "log-macdecode", .id = O_LOG_MAC, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+#undef s
+
+static void LOG_init(struct xt_entry_target *t)
+{
+ struct xt_log_info *loginfo = (void *)t->data;
+
+ loginfo->level = LOG_DEFAULT_LEVEL;
+}
+
+static void LOG_parse(struct xt_option_call *cb)
+{
+ struct xt_log_info *info = cb->data;
+
+ xtables_option_parse(cb);
+ switch (cb->entry->id) {
+ case O_LOG_PREFIX:
+ if (strchr(cb->arg, '\n') != NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Newlines not allowed in --log-prefix");
+ break;
+ case O_LOG_TCPSEQ:
+ case O_LOG_TCPOPTS:
+ case O_LOG_IPOPTS:
+ case O_LOG_UID:
+ case O_LOG_MAC:
+ info->logflags |= 1 << cb->entry->id;
+ break;
+ }
+}
+
+static const char *priority2name(unsigned char level)
+{
+ int i;
+
+ for (i = 0; prioritynames[i].c_name; ++i) {
+ if (level == prioritynames[i].c_val)
+ return prioritynames[i].c_name;
+ }
+ return NULL;
+}
+
+static void LOG_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_log_info *loginfo = (const void *)target->data;
+
+ printf(" LOG");
+ if (numeric)
+ printf(" flags %u level %u",
+ loginfo->logflags, loginfo->level);
+ else {
+ const char *pname = priority2name(loginfo->level);
+
+ if (pname)
+ printf(" level %s", pname);
+ else
+ printf(" UNKNOWN level %u", loginfo->level);
+ if (loginfo->logflags & XT_LOG_TCPSEQ)
+ printf(" tcp-sequence");
+ if (loginfo->logflags & XT_LOG_TCPOPT)
+ printf(" tcp-options");
+ if (loginfo->logflags & XT_LOG_IPOPT)
+ printf(" ip-options");
+ if (loginfo->logflags & XT_LOG_UID)
+ printf(" uid");
+ if (loginfo->logflags & XT_LOG_MACDECODE)
+ printf(" macdecode");
+ if (loginfo->logflags & ~(XT_LOG_MASK))
+ printf(" unknown-flags");
+ }
+
+ if (strcmp(loginfo->prefix, "") != 0)
+ printf(" prefix \"%s\"", loginfo->prefix);
+}
+
+static void LOG_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_log_info *loginfo = (const void *)target->data;
+
+ if (strcmp(loginfo->prefix, "") != 0) {
+ printf(" --log-prefix");
+ xtables_save_string(loginfo->prefix);
+ }
+
+ if (loginfo->level != LOG_DEFAULT_LEVEL)
+ printf(" --log-level %d", loginfo->level);
+
+ if (loginfo->logflags & XT_LOG_TCPSEQ)
+ printf(" --log-tcp-sequence");
+ if (loginfo->logflags & XT_LOG_TCPOPT)
+ printf(" --log-tcp-options");
+ if (loginfo->logflags & XT_LOG_IPOPT)
+ printf(" --log-ip-options");
+ if (loginfo->logflags & XT_LOG_UID)
+ printf(" --log-uid");
+ if (loginfo->logflags & XT_LOG_MACDECODE)
+ printf(" --log-macdecode");
+}
+
+static int LOG_xlate(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params)
+{
+ const struct xt_log_info *loginfo = (const void *)params->target->data;
+ const char *pname = priority2name(loginfo->level);
+
+ xt_xlate_add(xl, "log");
+ if (strcmp(loginfo->prefix, "") != 0)
+ xt_xlate_add(xl, " prefix \"%s\"", loginfo->prefix);
+
+ if (loginfo->level != LOG_DEFAULT_LEVEL && pname)
+ xt_xlate_add(xl, " level %s", pname);
+ else if (!pname)
+ return 0;
+
+ if ((loginfo->logflags & XT_LOG_MASK) == XT_LOG_MASK) {
+ xt_xlate_add(xl, " flags all");
+ } else {
+ if (loginfo->logflags & (XT_LOG_TCPSEQ | XT_LOG_TCPOPT)) {
+ const char *delim = " ";
+
+ xt_xlate_add(xl, " flags tcp");
+ if (loginfo->logflags & XT_LOG_TCPSEQ) {
+ xt_xlate_add(xl, " sequence");
+ delim = ",";
+ }
+ if (loginfo->logflags & XT_LOG_TCPOPT)
+ xt_xlate_add(xl, "%soptions", delim);
+ }
+ if (loginfo->logflags & XT_LOG_IPOPT)
+ xt_xlate_add(xl, " flags ip options");
+ if (loginfo->logflags & XT_LOG_UID)
+ xt_xlate_add(xl, " flags skuid");
+ if (loginfo->logflags & XT_LOG_MACDECODE)
+ xt_xlate_add(xl, " flags ether");
+ }
+
+ return 1;
+}
+static struct xtables_target log_tg_reg = {
+ .name = "LOG",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_log_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_log_info)),
+ .help = LOG_help,
+ .init = LOG_init,
+ .print = LOG_print,
+ .save = LOG_save,
+ .x6_parse = LOG_parse,
+ .x6_options = LOG_opts,
+ .xlate = LOG_xlate,
+};
+
+void _init(void)
+{
+ xtables_register_target(&log_tg_reg);
+}
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
index 1536563d..100f6a38 100644
--- a/extensions/libxt_MARK.c
+++ b/extensions/libxt_MARK.c
@@ -366,6 +366,8 @@ static int MARK_xlate(struct xt_xlate *xl,
case XT_MARK_OR:
xt_xlate_add(xl, "mark or 0x%x ", (uint32_t)markinfo->mark);
break;
+ default:
+ return 0;
}
return 1;
diff --git a/extensions/libxt_MARK.t b/extensions/libxt_MARK.t
index 9d1aa7d7..ae026dbb 100644
--- a/extensions/libxt_MARK.t
+++ b/extensions/libxt_MARK.t
@@ -1,7 +1,7 @@
:INPUT,FORWARD,OUTPUT
-j MARK --set-xmark 0xfeedcafe/0xfeedcafe;=;OK
--j MARK --set-xmark 0;=;OK
--j MARK --set-xmark 4294967295;-j MARK --set-xmark 0xffffffff;OK
+-j MARK --set-xmark 0x0;-j MARK --set-xmark 0x0/0xffffffff;OK
+-j MARK --set-xmark 4294967295;-j MARK --set-xmark 0xffffffff/0xffffffff;OK
-j MARK --set-xmark 4294967296;;FAIL
-j MARK --set-xmark -1;;FAIL
-j MARK;;FAIL
diff --git a/extensions/libxt_MARK.txlate b/extensions/libxt_MARK.txlate
index d3250ab6..36ee7a3b 100644
--- a/extensions/libxt_MARK.txlate
+++ b/extensions/libxt_MARK.txlate
@@ -1,26 +1,26 @@
iptables-translate -t mangle -A OUTPUT -j MARK --set-mark 0
-nft add rule ip mangle OUTPUT counter meta mark set 0x0
+nft 'add rule ip mangle OUTPUT counter meta mark set 0x0'
iptables-translate -t mangle -A OUTPUT -j MARK --set-mark 64
-nft add rule ip mangle OUTPUT counter meta mark set 0x40
+nft 'add rule ip mangle OUTPUT counter meta mark set 0x40'
iptables-translate -t mangle -A OUTPUT -j MARK --set-xmark 0x40/0x32
-nft add rule ip mangle OUTPUT counter meta mark set mark and 0xffffffcd xor 0x40
+nft 'add rule ip mangle OUTPUT counter meta mark set mark and 0xffffffcd xor 0x40'
iptables-translate -t mangle -A OUTPUT -j MARK --or-mark 64
-nft add rule ip mangle OUTPUT counter meta mark set mark or 0x40
+nft 'add rule ip mangle OUTPUT counter meta mark set mark or 0x40'
iptables-translate -t mangle -A OUTPUT -j MARK --and-mark 64
-nft add rule ip mangle OUTPUT counter meta mark set mark and 0x40
+nft 'add rule ip mangle OUTPUT counter meta mark set mark and 0x40'
iptables-translate -t mangle -A OUTPUT -j MARK --xor-mark 64
-nft add rule ip mangle OUTPUT counter meta mark set mark xor 0x40
+nft 'add rule ip mangle OUTPUT counter meta mark set mark xor 0x40'
iptables-translate -t mangle -A PREROUTING -j MARK --set-mark 0x64
-nft add rule ip mangle PREROUTING counter meta mark set 0x64
+nft 'add rule ip mangle PREROUTING counter meta mark set 0x64'
iptables-translate -t mangle -A PREROUTING -j MARK --and-mark 0x64
-nft add rule ip mangle PREROUTING counter meta mark set mark and 0x64
+nft 'add rule ip mangle PREROUTING counter meta mark set mark and 0x64'
iptables-translate -t mangle -A PREROUTING -j MARK --or-mark 0x64
-nft add rule ip mangle PREROUTING counter meta mark set mark or 0x64
+nft 'add rule ip mangle PREROUTING counter meta mark set mark or 0x64'
diff --git a/extensions/libxt_DNAT.c b/extensions/libxt_NAT.c
index 5696d31f..da9f2201 100644
--- a/extensions/libxt_DNAT.c
+++ b/extensions/libxt_NAT.c
@@ -25,17 +25,45 @@
.min_proto = TO_IPV4_MRC(ptr)->range[0].min, \
.max_proto = TO_IPV4_MRC(ptr)->range[0].max, \
};
+#define TO_NF_NAT_RANGE(ptr) ((const struct nf_nat_range *)(ptr))
+#define RANGE2_INIT_FROM_RANGE(ptr) { \
+ .flags = TO_NF_NAT_RANGE(ptr)->flags, \
+ .min_addr = TO_NF_NAT_RANGE(ptr)->min_addr, \
+ .max_addr = TO_NF_NAT_RANGE(ptr)->max_addr, \
+ .min_proto = TO_NF_NAT_RANGE(ptr)->min_proto, \
+ .max_proto = TO_NF_NAT_RANGE(ptr)->max_proto, \
+};
enum {
O_TO_DEST = 0,
+ O_TO_SRC,
O_TO_PORTS,
O_RANDOM,
+ O_RANDOM_FULLY,
O_PERSISTENT,
- F_TO_DEST = 1 << O_TO_DEST,
- F_TO_PORTS = 1 << O_TO_PORTS,
- F_RANDOM = 1 << O_RANDOM,
};
+static void SNAT_help(void)
+{
+ printf(
+"SNAT target options:\n"
+" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
+" Address to map source to.\n"
+"[--random] [--random-fully] [--persistent]\n");
+}
+
+static void MASQUERADE_help(void)
+{
+ printf(
+"MASQUERADE target options:\n"
+" --to-ports <port>[-<port>]\n"
+" Port (range) to map to.\n"
+" --random\n"
+" Randomize source port.\n"
+" --random-fully\n"
+" Fully randomize source port.\n");
+}
+
static void DNAT_help(void)
{
printf(
@@ -63,6 +91,22 @@ static void REDIRECT_help(void)
" [--random]\n");
}
+static const struct xt_option_entry SNAT_opts[] = {
+ {.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
+ .flags = XTOPT_MAND},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
+ {.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
+static const struct xt_option_entry MASQUERADE_opts[] = {
+ {.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
+ {.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
+ {.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
+ XTOPT_TABLEEND,
+};
+
static const struct xt_option_entry DNAT_opts[] = {
{.name = "to-destination", .id = O_TO_DEST, .type = XTTYPE_STRING,
.flags = XTOPT_MAND},
@@ -197,7 +241,7 @@ parse_to(const char *orig_arg, bool portok,
if (!inet_pton(family, start, &range->min_addr))
xtables_error(PARAMETER_PROBLEM,
- "Bad IP address \"%s\"", arg);
+ "Bad IP address \"%s\"", start);
if (dash) {
if (!inet_pton(family, dash + 1, &range->max_addr))
xtables_error(PARAMETER_PROBLEM,
@@ -209,8 +253,8 @@ parse_to(const char *orig_arg, bool portok,
return;
}
-static void __DNAT_parse(struct xt_option_call *cb, __u16 proto,
- struct nf_nat_range2 *range, int family)
+static void __NAT_parse(struct xt_option_call *cb, __u16 proto,
+ struct nf_nat_range2 *range, int family)
{
bool portok = proto == IPPROTO_TCP ||
proto == IPPROTO_UDP ||
@@ -221,6 +265,7 @@ static void __DNAT_parse(struct xt_option_call *cb, __u16 proto,
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_TO_DEST:
+ case O_TO_SRC:
parse_to(cb->arg, portok, range, family);
break;
case O_TO_PORTS:
@@ -229,19 +274,26 @@ static void __DNAT_parse(struct xt_option_call *cb, __u16 proto,
case O_PERSISTENT:
range->flags |= NF_NAT_RANGE_PERSISTENT;
break;
+ case O_RANDOM:
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ break;
+ case O_RANDOM_FULLY:
+ range->flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
+ break;
}
}
-static void DNAT_parse(struct xt_option_call *cb)
+static void NAT_parse(struct xt_option_call *cb)
{
struct nf_nat_ipv4_multi_range_compat *mr = (void *)cb->data;
const struct ipt_entry *entry = cb->xt_entry;
struct nf_nat_range2 range = {};
- __DNAT_parse(cb, entry->ip.proto, &range, AF_INET);
+ __NAT_parse(cb, entry->ip.proto, &range, AF_INET);
switch (cb->entry->id) {
case O_TO_DEST:
+ case O_TO_SRC:
mr->range->min_ip = range.min_addr.ip;
mr->range->max_ip = range.max_addr.ip;
/* fall through */
@@ -250,19 +302,42 @@ static void DNAT_parse(struct xt_option_call *cb)
mr->range->max = range.max_proto;
/* fall through */
case O_PERSISTENT:
+ case O_RANDOM:
+ case O_RANDOM_FULLY:
mr->range->flags |= range.flags;
break;
}
}
-static void __DNAT_fcheck(struct xt_fcheck_call *cb, unsigned int *flags)
+static void NAT_parse6(struct xt_option_call *cb)
+{
+ struct nf_nat_range2 range = RANGE2_INIT_FROM_RANGE(cb->data);
+ struct nf_nat_range *range_v1 = (void *)cb->data;
+ const struct ip6t_entry *entry = cb->xt_entry;
+
+ __NAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
+ memcpy(range_v1, &range, sizeof(*range_v1));
+}
+
+static void DNAT_parse_v2(struct xt_option_call *cb)
{
- static const unsigned int redir_f = F_TO_PORTS | F_RANDOM;
- static const unsigned int dnat_f = F_TO_DEST | F_RANDOM;
+ const struct ipt_entry *entry = cb->xt_entry;
- if ((cb->xflags & redir_f) == redir_f ||
- (cb->xflags & dnat_f) == dnat_f)
- *flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ __NAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
+}
+
+static void DNAT_parse6_v2(struct xt_option_call *cb)
+{
+ const struct ip6t_entry *entry = cb->xt_entry;
+
+ __NAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
+}
+
+static void SNAT_fcheck(struct xt_fcheck_call *cb)
+{
+ struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
+
+ mr->rangesize = 1;
}
static void DNAT_fcheck(struct xt_fcheck_call *cb)
@@ -274,8 +349,15 @@ static void DNAT_fcheck(struct xt_fcheck_call *cb)
if (mr->range[0].flags & NF_NAT_RANGE_PROTO_OFFSET)
xtables_error(PARAMETER_PROBLEM,
"Shifted portmap ranges not supported with this kernel");
+}
- __DNAT_fcheck(cb, &mr->range[0].flags);
+static void DNAT_fcheck6(struct xt_fcheck_call *cb)
+{
+ struct nf_nat_range *range = (void *)cb->data;
+
+ if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
+ xtables_error(PARAMETER_PROBLEM,
+ "Shifted portmap ranges not supported with this kernel");
}
static char *sprint_range(const struct nf_nat_range2 *r, int family)
@@ -325,31 +407,15 @@ static void __NAT_print(const struct nf_nat_range2 *r, int family,
}
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" %srandom", flag_pfx);
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
+ printf(" %srandom-fully", flag_pfx);
if (r->flags & NF_NAT_RANGE_PERSISTENT)
printf(" %spersistent", flag_pfx);
}
-#define __DNAT_print(r, family) __NAT_print(r, family, "to:", "", false)
-#define __DNAT_save(r, family) __NAT_print(r, family, "--to-destination ", "--", false)
-#define __REDIRECT_print(r) __NAT_print(r, AF_INET, "redir ports ", "", true)
-#define __REDIRECT_save(r) __NAT_print(r, AF_INET, "--to-ports ", "--", true)
-
-static void DNAT_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
- __DNAT_print(&range, AF_INET);
-}
-
-static void DNAT_save(const void *ip, const struct xt_entry_target *target)
-{
- struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
- __DNAT_save(&range, AF_INET);
-}
static int
-__DNAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r, int family)
+__NAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r,
+ int family, const char *tgt)
{
char *range_str = sprint_range(r, family);
const char *sep = " ";
@@ -358,13 +424,17 @@ __DNAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r, int family)
if (r->flags & NF_NAT_RANGE_PROTO_OFFSET)
return 0;
- xt_xlate_add(xl, "dnat");
+ xt_xlate_add(xl, tgt);
if (strlen(range_str))
xt_xlate_add(xl, " to %s", range_str);
if (r->flags & NF_NAT_RANGE_PROTO_RANDOM) {
xt_xlate_add(xl, "%srandom", sep);
sep = ",";
}
+ if (r->flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
+ xt_xlate_add(xl, "%sfully-random", sep);
+ sep = ",";
+ }
if (r->flags & NF_NAT_RANGE_PERSISTENT) {
xt_xlate_add(xl, "%spersistent", sep);
sep = ",";
@@ -372,183 +442,74 @@ __DNAT_xlate(struct xt_xlate *xl, const struct nf_nat_range2 *r, int family)
return 1;
}
-static int DNAT_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- struct nf_nat_range2 range =
- RANGE2_INIT_FROM_IPV4_MRC(params->target->data);
-
- return __DNAT_xlate(xl, &range, AF_INET);
+#define PSX_GEN(name, converter, family, \
+ print_rangeopt, save_rangeopt, skip_colon, xlate) \
+static void name##_print(const void *ip, const struct xt_entry_target *target, \
+ int numeric) \
+{ \
+ struct nf_nat_range2 range = converter(target->data); \
+ \
+ __NAT_print(&range, family, print_rangeopt, "", skip_colon); \
+} \
+static void name##_save(const void *ip, const struct xt_entry_target *target) \
+{ \
+ struct nf_nat_range2 range = converter(target->data); \
+ \
+ __NAT_print(&range, family, save_rangeopt, "--", skip_colon); \
+} \
+static int name##_xlate(struct xt_xlate *xl, \
+ const struct xt_xlate_tg_params *params) \
+{ \
+ struct nf_nat_range2 range = converter(params->target->data); \
+ \
+ return __NAT_xlate(xl, &range, family, xlate); \
}
-static void DNAT_parse_v2(struct xt_option_call *cb)
-{
- const struct ipt_entry *entry = cb->xt_entry;
+PSX_GEN(DNAT, RANGE2_INIT_FROM_IPV4_MRC, \
+ AF_INET, "to:", "--to-destination ", false, "dnat")
- __DNAT_parse(cb, entry->ip.proto, cb->data, AF_INET);
-}
+PSX_GEN(DNATv2, *(struct nf_nat_range2 *), \
+ AF_INET, "to:", "--to-destination ", false, "dnat")
-static void DNAT_fcheck_v2(struct xt_fcheck_call *cb)
-{
- __DNAT_fcheck(cb, &((struct nf_nat_range2 *)cb->data)->flags);
-}
+PSX_GEN(DNAT6, RANGE2_INIT_FROM_RANGE, \
+ AF_INET6, "to:", "--to-destination ", false, "dnat")
-static void DNAT_print_v2(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- __DNAT_print((const void *)target->data, AF_INET);
-}
+PSX_GEN(DNAT6v2, *(struct nf_nat_range2 *), \
+ AF_INET6, "to:", "--to-destination ", false, "dnat")
-static void DNAT_save_v2(const void *ip, const struct xt_entry_target *target)
-{
- __DNAT_save((const void *)target->data, AF_INET);
-}
+PSX_GEN(REDIRECT, RANGE2_INIT_FROM_IPV4_MRC, \
+ AF_INET, "redir ports ", "--to-ports ", true, "redirect")
-static int DNAT_xlate_v2(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- return __DNAT_xlate(xl, (const void *)params->target->data, AF_INET);
-}
-
-static void DNAT_parse6(struct xt_option_call *cb)
-{
- const struct ip6t_entry *entry = cb->xt_entry;
- struct nf_nat_range *range_v1 = (void *)cb->data;
- struct nf_nat_range2 range = {};
+PSX_GEN(REDIRECT6, RANGE2_INIT_FROM_RANGE, \
+ AF_INET6, "redir ports ", "--to-ports ", true, "redirect")
- memcpy(&range, range_v1, sizeof(*range_v1));
- __DNAT_parse(cb, entry->ipv6.proto, &range, AF_INET6);
- memcpy(range_v1, &range, sizeof(*range_v1));
-}
+PSX_GEN(SNAT, RANGE2_INIT_FROM_IPV4_MRC, \
+ AF_INET, "to:", "--to-source ", false, "snat")
-static void DNAT_fcheck6(struct xt_fcheck_call *cb)
-{
- struct nf_nat_range *range = (void *)cb->data;
+PSX_GEN(SNAT6, RANGE2_INIT_FROM_RANGE, \
+ AF_INET6, "to:", "--to-source ", false, "snat")
- if (range->flags & NF_NAT_RANGE_PROTO_OFFSET)
- xtables_error(PARAMETER_PROBLEM,
- "Shifted portmap ranges not supported with this kernel");
+PSX_GEN(MASQUERADE, RANGE2_INIT_FROM_IPV4_MRC, \
+ AF_INET, "masq ports: ", "--to-ports ", true, "masquerade")
- __DNAT_fcheck(cb, &range->flags);
-}
+PSX_GEN(MASQUERADE6, RANGE2_INIT_FROM_RANGE, \
+ AF_INET6, "masq ports: ", "--to-ports ", true, "masquerade")
-static void DNAT_print6(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- struct nf_nat_range2 range = {};
-
- memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
- __DNAT_print(&range, AF_INET6);
-}
-
-static void DNAT_save6(const void *ip, const struct xt_entry_target *target)
-{
- struct nf_nat_range2 range = {};
-
- memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
- __DNAT_save(&range, AF_INET6);
-}
-
-static int DNAT_xlate6(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- struct nf_nat_range2 range = {};
-
- memcpy(&range, (const void *)params->target->data,
- sizeof(struct nf_nat_range));
- return __DNAT_xlate(xl, &range, AF_INET6);
-}
-
-static void DNAT_parse6_v2(struct xt_option_call *cb)
-{
- const struct ip6t_entry *entry = cb->xt_entry;
-
- __DNAT_parse(cb, entry->ipv6.proto, cb->data, AF_INET6);
-}
-
-static void DNAT_print6_v2(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- __DNAT_print((const void *)target->data, AF_INET6);
-}
-
-static void DNAT_save6_v2(const void *ip, const struct xt_entry_target *target)
-{
- __DNAT_save((const void *)target->data, AF_INET6);
-}
-
-static int DNAT_xlate6_v2(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- return __DNAT_xlate(xl, (const void *)params->target->data, AF_INET6);
-}
-
-static int __REDIRECT_xlate(struct xt_xlate *xl,
- const struct nf_nat_range2 *range)
-{
- char *range_str = sprint_range(range, AF_INET);
-
- xt_xlate_add(xl, "redirect");
- if (strlen(range_str))
- xt_xlate_add(xl, " to %s", range_str);
- if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
- xt_xlate_add(xl, " random");
-
- return 1;
-}
-
-static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
- __REDIRECT_print(&range);
-}
-
-static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
-{
- struct nf_nat_range2 range = RANGE2_INIT_FROM_IPV4_MRC(target->data);
-
- __REDIRECT_save(&range);
-}
-
-static int REDIRECT_xlate(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- struct nf_nat_range2 range =
- RANGE2_INIT_FROM_IPV4_MRC(params->target->data);
-
- return __REDIRECT_xlate(xl, &range);
-}
-
-static void REDIRECT_print6(const void *ip, const struct xt_entry_target *target,
- int numeric)
-{
- struct nf_nat_range2 range = {};
-
- memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
- __REDIRECT_print(&range);
-}
-
-static void REDIRECT_save6(const void *ip, const struct xt_entry_target *target)
-{
- struct nf_nat_range2 range = {};
-
- memcpy(&range, (const void *)target->data, sizeof(struct nf_nat_range));
- __REDIRECT_save(&range);
-}
-
-static int REDIRECT_xlate6(struct xt_xlate *xl,
- const struct xt_xlate_tg_params *params)
-{
- struct nf_nat_range2 range = {};
-
- memcpy(&range, (const void *)params->target->data,
- sizeof(struct nf_nat_range));
- return __REDIRECT_xlate(xl, &range);
-}
-
-static struct xtables_target dnat_tg_reg[] = {
+static struct xtables_target nat_tg_reg[] = {
+ {
+ .name = "SNAT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .help = SNAT_help,
+ .x6_parse = NAT_parse,
+ .x6_fcheck = SNAT_fcheck,
+ .print = SNAT_print,
+ .save = SNAT_save,
+ .x6_options = SNAT_opts,
+ .xlate = SNAT_xlate,
+ },
{
.name = "DNAT",
.version = XTABLES_VERSION,
@@ -559,12 +520,39 @@ static struct xtables_target dnat_tg_reg[] = {
.help = DNAT_help,
.print = DNAT_print,
.save = DNAT_save,
- .x6_parse = DNAT_parse,
+ .x6_parse = NAT_parse,
.x6_fcheck = DNAT_fcheck,
.x6_options = DNAT_opts,
.xlate = DNAT_xlate,
},
{
+ .name = "MASQUERADE",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
+ .help = MASQUERADE_help,
+ .x6_parse = NAT_parse,
+ .x6_fcheck = SNAT_fcheck,
+ .print = MASQUERADE_print,
+ .save = MASQUERADE_save,
+ .x6_options = MASQUERADE_opts,
+ .xlate = MASQUERADE_xlate,
+ },
+ {
+ .name = "MASQUERADE",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = MASQUERADE_help,
+ .x6_parse = NAT_parse6,
+ .print = MASQUERADE6_print,
+ .save = MASQUERADE6_save,
+ .x6_options = MASQUERADE_opts,
+ .xlate = MASQUERADE6_xlate,
+ },
+ {
.name = "REDIRECT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
@@ -574,12 +562,26 @@ static struct xtables_target dnat_tg_reg[] = {
.help = REDIRECT_help,
.print = REDIRECT_print,
.save = REDIRECT_save,
- .x6_parse = DNAT_parse,
+ .x6_parse = NAT_parse,
.x6_fcheck = DNAT_fcheck,
.x6_options = REDIRECT_opts,
.xlate = REDIRECT_xlate,
},
{
+ .name = "SNAT",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
+ .help = SNAT_help,
+ .x6_parse = NAT_parse6,
+ .print = SNAT6_print,
+ .save = SNAT6_save,
+ .x6_options = SNAT_opts,
+ .xlate = SNAT6_xlate,
+ },
+ {
.name = "DNAT",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV6,
@@ -587,12 +589,12 @@ static struct xtables_target dnat_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
.help = DNAT_help,
- .print = DNAT_print6,
- .save = DNAT_save6,
- .x6_parse = DNAT_parse6,
+ .print = DNAT6_print,
+ .save = DNAT6_save,
+ .x6_parse = NAT_parse6,
.x6_fcheck = DNAT_fcheck6,
.x6_options = DNAT_opts,
- .xlate = DNAT_xlate6,
+ .xlate = DNAT6_xlate,
},
{
.name = "REDIRECT",
@@ -601,12 +603,12 @@ static struct xtables_target dnat_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct nf_nat_range)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range)),
.help = REDIRECT_help,
- .print = REDIRECT_print6,
- .save = REDIRECT_save6,
- .x6_parse = DNAT_parse6,
+ .print = REDIRECT6_print,
+ .save = REDIRECT6_save,
+ .x6_parse = NAT_parse6,
.x6_fcheck = DNAT_fcheck6,
.x6_options = REDIRECT_opts,
- .xlate = REDIRECT_xlate6,
+ .xlate = REDIRECT6_xlate,
},
{
.name = "DNAT",
@@ -616,12 +618,11 @@ static struct xtables_target dnat_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct nf_nat_range2)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range2)),
.help = DNAT_help_v2,
- .print = DNAT_print_v2,
- .save = DNAT_save_v2,
+ .print = DNATv2_print,
+ .save = DNATv2_save,
.x6_parse = DNAT_parse_v2,
- .x6_fcheck = DNAT_fcheck_v2,
.x6_options = DNAT_opts,
- .xlate = DNAT_xlate_v2,
+ .xlate = DNATv2_xlate,
},
{
.name = "DNAT",
@@ -631,16 +632,15 @@ static struct xtables_target dnat_tg_reg[] = {
.size = XT_ALIGN(sizeof(struct nf_nat_range2)),
.userspacesize = XT_ALIGN(sizeof(struct nf_nat_range2)),
.help = DNAT_help_v2,
- .print = DNAT_print6_v2,
- .save = DNAT_save6_v2,
+ .print = DNAT6v2_print,
+ .save = DNAT6v2_save,
.x6_parse = DNAT_parse6_v2,
- .x6_fcheck = DNAT_fcheck_v2,
.x6_options = DNAT_opts,
- .xlate = DNAT_xlate6_v2,
+ .xlate = DNAT6v2_xlate,
},
};
void _init(void)
{
- xtables_register_targets(dnat_tg_reg, ARRAY_SIZE(dnat_tg_reg));
+ xtables_register_targets(nat_tg_reg, ARRAY_SIZE(nat_tg_reg));
}
diff --git a/extensions/libxt_NFLOG.c b/extensions/libxt_NFLOG.c
index 7a12e5ac..d12ef044 100644
--- a/extensions/libxt_NFLOG.c
+++ b/extensions/libxt_NFLOG.c
@@ -112,16 +112,12 @@ static void NFLOG_save(const void *ip, const struct xt_entry_target *target)
}
static void nflog_print_xlate(const struct xt_nflog_info *info,
- struct xt_xlate *xl, bool escape_quotes)
+ struct xt_xlate *xl)
{
xt_xlate_add(xl, "log ");
- if (info->prefix[0] != '\0') {
- if (escape_quotes)
- xt_xlate_add(xl, "prefix \\\"%s\\\" ", info->prefix);
- else
- xt_xlate_add(xl, "prefix \"%s\" ", info->prefix);
+ if (info->prefix[0] != '\0')
+ xt_xlate_add(xl, "prefix \"%s\" ", info->prefix);
- }
if (info->flags & XT_NFLOG_F_COPY_LEN)
xt_xlate_add(xl, "snaplen %u ", info->len);
if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
@@ -135,7 +131,7 @@ static int NFLOG_xlate(struct xt_xlate *xl,
const struct xt_nflog_info *info =
(struct xt_nflog_info *)params->target->data;
- nflog_print_xlate(info, xl, params->escape_quotes);
+ nflog_print_xlate(info, xl);
return 1;
}
diff --git a/extensions/libxt_NFLOG.txlate b/extensions/libxt_NFLOG.txlate
index a0872c9e..ebd81be3 100644
--- a/extensions/libxt_NFLOG.txlate
+++ b/extensions/libxt_NFLOG.txlate
@@ -1,14 +1,14 @@
iptables-translate -A FORWARD -j NFLOG --nflog-group 32 --nflog-prefix "Prefix 1.0"
-nft add rule ip filter FORWARD counter log prefix \"Prefix 1.0\" group 32
+nft 'add rule ip filter FORWARD counter log prefix "Prefix 1.0" group 32'
iptables-translate -A OUTPUT -j NFLOG --nflog-group 30
-nft add rule ip filter OUTPUT counter log group 30
+nft 'add rule ip filter OUTPUT counter log group 30'
iptables-translate -I INPUT -j NFLOG --nflog-threshold 2
-nft insert rule ip filter INPUT counter log queue-threshold 2 group 0
+nft 'insert rule ip filter INPUT counter log queue-threshold 2 group 0'
iptables-translate -I INPUT -j NFLOG --nflog-size 256
-nft insert rule ip filter INPUT counter log snaplen 256 group 0
+nft 'insert rule ip filter INPUT counter log snaplen 256 group 0'
iptables-translate -I INPUT -j NFLOG --nflog-threshold 25
-nft insert rule ip filter INPUT counter log queue-threshold 25 group 0
+nft 'insert rule ip filter INPUT counter log queue-threshold 25 group 0'
diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c
index fe519078..ca6cdaf4 100644
--- a/extensions/libxt_NFQUEUE.c
+++ b/extensions/libxt_NFQUEUE.c
@@ -64,7 +64,7 @@ static const struct xt_option_entry NFQUEUE_opts[] = {
{.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
.flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
.excl = F_QUEUE_BALANCE},
- {.name = "queue-balance", .id = O_QUEUE_BALANCE,
+ {.name = "queue-balance", .id = O_QUEUE_BALANCE, .max = UINT16_MAX - 1,
.type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
{.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
{.name = "queue-cpu-fanout", .id = O_QUEUE_CPU_FANOUT,
diff --git a/extensions/libxt_NFQUEUE.man b/extensions/libxt_NFQUEUE.man
index 1bfb7b84..950b0d24 100644
--- a/extensions/libxt_NFQUEUE.man
+++ b/extensions/libxt_NFQUEUE.man
@@ -18,6 +18,8 @@ This specifies a range of queues to use. Packets are then balanced across the gi
This is useful for multicore systems: start multiple instances of the userspace program on
queues x, x+1, .. x+n and use "\-\-queue\-balance \fIx\fP\fB:\fP\fIx+n\fP".
Packets belonging to the same connection are put into the same nfqueue.
+Due to implementation details, a lower range value of 0 limits the higher range
+value to 65534, i.e. one can only balance between at most 65535 queues.
.PP
.TP
\fB\-\-queue\-bypass\fP
diff --git a/extensions/libxt_NFQUEUE.t b/extensions/libxt_NFQUEUE.t
index b51b19fd..8fb2b760 100644
--- a/extensions/libxt_NFQUEUE.t
+++ b/extensions/libxt_NFQUEUE.t
@@ -1,12 +1,11 @@
:INPUT,FORWARD,OUTPUT
--j NFQUEUE;=;OK
+-j NFQUEUE;-j NFQUEUE --queue-num 0;OK
-j NFQUEUE --queue-num 0;=;OK
-j NFQUEUE --queue-num 65535;=;OK
-j NFQUEUE --queue-num 65536;;FAIL
-j NFQUEUE --queue-num -1;;FAIL
-# it says "NFQUEUE: number of total queues is 0", overflow in NFQUEUE_parse_v1?
-# ERROR: cannot load: iptables -A INPUT -j NFQUEUE --queue-balance 0:65535
-# -j NFQUEUE --queue-balance 0:65535;=;OK
+-j NFQUEUE --queue-balance 0:65534;=;OK
+-j NFQUEUE --queue-balance 0:65535;;FAIL
-j NFQUEUE --queue-balance 0:65536;;FAIL
-j NFQUEUE --queue-balance -1:65535;;FAIL
-j NFQUEUE --queue-num 10 --queue-bypass;=;OK
diff --git a/extensions/libxt_NFQUEUE.txlate b/extensions/libxt_NFQUEUE.txlate
index 3d188a7a..3698dcbc 100644
--- a/extensions/libxt_NFQUEUE.txlate
+++ b/extensions/libxt_NFQUEUE.txlate
@@ -1,8 +1,8 @@
iptables-translate -t nat -A PREROUTING -p tcp --dport 80 -j NFQUEUE --queue-num 30
-nft add rule ip nat PREROUTING tcp dport 80 counter queue num 30
+nft 'add rule ip nat PREROUTING tcp dport 80 counter queue num 30'
iptables-translate -A FORWARD -j NFQUEUE --queue-num 0 --queue-bypass -p TCP --sport 80
-nft add rule ip filter FORWARD tcp sport 80 counter queue num 0 bypass
+nft 'add rule ip filter FORWARD tcp sport 80 counter queue num 0 bypass'
iptables-translate -A FORWARD -j NFQUEUE --queue-bypass -p TCP --sport 80 --queue-balance 0:3 --queue-cpu-fanout
-nft add rule ip filter FORWARD tcp sport 80 counter queue num 0-3 bypass,fanout
+nft 'add rule ip filter FORWARD tcp sport 80 counter queue num 0-3 bypass,fanout'
diff --git a/extensions/libxt_NOTRACK.txlate b/extensions/libxt_NOTRACK.txlate
index 9d35619d..9490ee8f 100644
--- a/extensions/libxt_NOTRACK.txlate
+++ b/extensions/libxt_NOTRACK.txlate
@@ -1,2 +1,2 @@
iptables-translate -A PREROUTING -t raw -j NOTRACK
-nft add rule ip raw PREROUTING counter notrack
+nft 'add rule ip raw PREROUTING counter notrack'
diff --git a/extensions/libxt_REDIRECT.t b/extensions/libxt_REDIRECT.t
index f607dd0a..362efa84 100644
--- a/extensions/libxt_REDIRECT.t
+++ b/extensions/libxt_REDIRECT.t
@@ -14,3 +14,4 @@
-p tcp -j REDIRECT --to-ports ftp-ssh;;FAIL
-p tcp -j REDIRECT --to-ports 10-ssh;;FAIL
-j REDIRECT --to-ports 42;;FAIL
+-j REDIRECT --random;=;OK
diff --git a/extensions/libxt_REDIRECT.txlate b/extensions/libxt_REDIRECT.txlate
index 2c536495..dc473340 100644
--- a/extensions/libxt_REDIRECT.txlate
+++ b/extensions/libxt_REDIRECT.txlate
@@ -1,26 +1,29 @@
iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT
-nft add rule ip nat prerouting tcp dport 80 counter redirect
+nft 'add rule ip nat prerouting tcp dport 80 counter redirect'
iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 0
-nft add rule ip nat prerouting tcp dport 80 counter redirect to :0
+nft 'add rule ip nat prerouting tcp dport 80 counter redirect to :0'
iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080
-nft add rule ip nat prerouting tcp dport 80 counter redirect to :8080
+nft 'add rule ip nat prerouting tcp dport 80 counter redirect to :8080'
iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 0-65535
-nft add rule ip nat prerouting tcp dport 80 counter redirect to :0-65535
+nft 'add rule ip nat prerouting tcp dport 80 counter redirect to :0-65535'
iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 10-22
-nft add rule ip nat prerouting tcp dport 80 counter redirect to :10-22
+nft 'add rule ip nat prerouting tcp dport 80 counter redirect to :10-22'
iptables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080 --random
-nft add rule ip nat prerouting tcp dport 80 counter redirect to :8080 random
+nft 'add rule ip nat prerouting tcp dport 80 counter redirect to :8080 random'
+
+iptables-translate -t nat -A prerouting -j REDIRECT --random
+nft 'add rule ip nat prerouting counter redirect random'
ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT
-nft add rule ip6 nat prerouting tcp dport 80 counter redirect
+nft 'add rule ip6 nat prerouting tcp dport 80 counter redirect'
ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080
-nft add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080
+nft 'add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080'
ip6tables-translate -t nat -A prerouting -p tcp --dport 80 -j REDIRECT --to-ports 8080 --random
-nft add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080 random
+nft 'add rule ip6 nat prerouting tcp dport 80 counter redirect to :8080 random'
diff --git a/extensions/libxt_SECMARK.c b/extensions/libxt_SECMARK.c
index 24249bd6..a4ee60f0 100644
--- a/extensions/libxt_SECMARK.c
+++ b/extensions/libxt_SECMARK.c
@@ -60,7 +60,7 @@ static void print_secmark(__u8 mode, const char *secctx)
break;
default:
- xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", mode);
+ xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu", mode);
}
}
diff --git a/extensions/libxt_SYNPROXY.txlate b/extensions/libxt_SYNPROXY.txlate
index b3de2b2a..b996c4b7 100644
--- a/extensions/libxt_SYNPROXY.txlate
+++ b/extensions/libxt_SYNPROXY.txlate
@@ -1,2 +1,2 @@
iptables-translate -t mangle -A INPUT -i iifname -p tcp -m tcp --dport 80 -m state --state INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
-nft add rule ip mangle INPUT iifname "iifname" tcp dport 80 ct state invalid,untracked counter synproxy sack-perm timestamp wscale 7 mss 1460
+nft 'add rule ip mangle INPUT iifname "iifname" tcp dport 80 ct state invalid,untracked counter synproxy sack-perm timestamp wscale 7 mss 1460'
diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c
index 0d9b200e..251a5532 100644
--- a/extensions/libxt_TCPMSS.c
+++ b/extensions/libxt_TCPMSS.c
@@ -131,6 +131,7 @@ static struct xtables_target tcpmss_tg_reg[] = {
.x6_parse = TCPMSS_parse,
.x6_fcheck = TCPMSS_check,
.x6_options = TCPMSS6_opts,
+ .xlate = TCPMSS_xlate,
},
};
diff --git a/extensions/libxt_TCPMSS.txlate b/extensions/libxt_TCPMSS.txlate
index 3dbbad66..a059c602 100644
--- a/extensions/libxt_TCPMSS.txlate
+++ b/extensions/libxt_TCPMSS.txlate
@@ -1,5 +1,5 @@
iptables-translate -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
-nft add rule ip filter FORWARD tcp flags syn / syn,rst counter tcp option maxseg size set rt mtu
+nft 'add rule ip filter FORWARD tcp flags syn / syn,rst counter tcp option maxseg size set rt mtu'
iptables-translate -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 90
-nft add rule ip filter FORWARD tcp flags syn / syn,rst counter tcp option maxseg size set 90
+nft 'add rule ip filter FORWARD tcp flags syn / syn,rst counter tcp option maxseg size set 90'
diff --git a/extensions/libxt_TCPOPTSTRIP.c b/extensions/libxt_TCPOPTSTRIP.c
index 6ea34892..ff873f98 100644
--- a/extensions/libxt_TCPOPTSTRIP.c
+++ b/extensions/libxt_TCPOPTSTRIP.c
@@ -142,6 +142,13 @@ tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info,
}
}
+static bool tcpoptstrip_empty(const struct xt_tcpoptstrip_target_info *info)
+{
+ static const struct xt_tcpoptstrip_target_info empty = {};
+
+ return memcmp(info, &empty, sizeof(empty)) == 0;
+}
+
static void
tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target,
int numeric)
@@ -149,6 +156,9 @@ tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target,
const struct xt_tcpoptstrip_target_info *info =
(const void *)target->data;
+ if (tcpoptstrip_empty(info))
+ return;
+
printf(" TCPOPTSTRIP options ");
tcpoptstrip_print_list(info, numeric);
}
@@ -159,6 +169,9 @@ tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target)
const struct xt_tcpoptstrip_target_info *info =
(const void *)target->data;
+ if (tcpoptstrip_empty(info))
+ return;
+
printf(" --strip-options ");
tcpoptstrip_print_list(info, true);
}
diff --git a/extensions/libxt_TEE.txlate b/extensions/libxt_TEE.txlate
index 9fcee254..fa1d5fe3 100644
--- a/extensions/libxt_TEE.txlate
+++ b/extensions/libxt_TEE.txlate
@@ -1,11 +1,11 @@
# iptables-translate -t mangle -A PREROUTING -j TEE --gateway 192.168.0.2 --oif eth0
-# nft add rule ip mangle PREROUTING counter dup to 192.168.0.2 device eth0
+# nft 'add rule ip mangle PREROUTING counter dup to 192.168.0.2 device eth0
#
# iptables-translate -t mangle -A PREROUTING -j TEE --gateway 192.168.0.2
-# nft add rule ip mangle PREROUTING counter dup to 192.168.0.2
+# nft 'add rule ip mangle PREROUTING counter dup to 192.168.0.2
ip6tables-translate -t mangle -A PREROUTING -j TEE --gateway ab12:00a1:1112:acba::
-nft add rule ip6 mangle PREROUTING counter dup to ab12:a1:1112:acba::
+nft 'add rule ip6 mangle PREROUTING counter dup to ab12:a1:1112:acba::'
ip6tables-translate -t mangle -A PREROUTING -j TEE --gateway ab12:00a1:1112:acba:: --oif eth0
-nft add rule ip6 mangle PREROUTING counter dup to ab12:a1:1112:acba:: device eth0
+nft 'add rule ip6 mangle PREROUTING counter dup to ab12:a1:1112:acba:: device eth0'
diff --git a/extensions/libxt_TOS.c b/extensions/libxt_TOS.c
index b66fa329..4fc849bd 100644
--- a/extensions/libxt_TOS.c
+++ b/extensions/libxt_TOS.c
@@ -183,28 +183,41 @@ static void tos_tg_save(const void *ip, const struct xt_entry_target *target)
printf(" --set-tos 0x%02x/0x%02x", info->tos_value, info->tos_mask);
}
+static int __tos_xlate(struct xt_xlate *xl, const char *ip,
+ uint8_t tos, uint8_t tosmask)
+{
+ xt_xlate_add(xl, "%s dscp set ", ip);
+ if ((tosmask & 0x3f) == 0x3f)
+ xt_xlate_add(xl, "0x%02x", tos >> 2);
+ else if (!tos)
+ xt_xlate_add(xl, "%s dscp and 0x%02x",
+ ip, (uint8_t)~tosmask >> 2);
+ else if (tos == tosmask)
+ xt_xlate_add(xl, "%s dscp or 0x%02x", ip, tos >> 2);
+ else if (!tosmask)
+ xt_xlate_add(xl, "%s dscp xor 0x%02x", ip, tos >> 2);
+ else
+ xt_xlate_add(xl, "%s dscp and 0x%02x xor 0x%02x",
+ ip, (uint8_t)~tosmask >> 2, tos >> 2);
+ return 1;
+}
+
static int tos_xlate(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
const struct ipt_tos_target_info *info =
(struct ipt_tos_target_info *) params->target->data;
- uint8_t dscp = info->tos >> 2;
-
- xt_xlate_add(xl, "ip dscp set 0x%02x", dscp);
- return 1;
+ return __tos_xlate(xl, "ip", info->tos, UINT8_MAX);
}
static int tos_xlate6(struct xt_xlate *xl,
const struct xt_xlate_tg_params *params)
{
- const struct ipt_tos_target_info *info =
- (struct ipt_tos_target_info *) params->target->data;
- uint8_t dscp = info->tos >> 2;
+ const struct xt_tos_target_info *info =
+ (struct xt_tos_target_info *)params->target->data;
- xt_xlate_add(xl, "ip6 dscp set 0x%02x", dscp);
-
- return 1;
+ return __tos_xlate(xl, "ip6", info->tos_value, info->tos_mask);
}
static struct xtables_target tos_tg_reg[] = {
diff --git a/extensions/libxt_TOS.t b/extensions/libxt_TOS.t
index ae8531cc..9f8e33fd 100644
--- a/extensions/libxt_TOS.t
+++ b/extensions/libxt_TOS.t
@@ -1,15 +1,15 @@
:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
*mangle
--j TOS --set-tos 0x1f;=;OK
+-j TOS --set-tos 0x1f;-j TOS --set-tos 0x1f/0xff;OK
-j TOS --set-tos 0x1f/0x1f;=;OK
# maximum TOS is 0x1f (5 bits)
# ERROR: should fail: iptables -A PREROUTING -t mangle -j TOS --set-tos 0xff
# -j TOS --set-tos 0xff;;FAIL
--j TOS --set-tos Minimize-Delay;-j TOS --set-tos 0x10;OK
--j TOS --set-tos Maximize-Throughput;-j TOS --set-tos 0x08;OK
--j TOS --set-tos Maximize-Reliability;-j TOS --set-tos 0x04;OK
--j TOS --set-tos Minimize-Cost;-j TOS --set-tos 0x02;OK
--j TOS --set-tos Normal-Service;-j TOS --set-tos 0x00;OK
+-j TOS --set-tos Minimize-Delay;-j TOS --set-tos 0x10/0x3f;OK
+-j TOS --set-tos Maximize-Throughput;-j TOS --set-tos 0x08/0x3f;OK
+-j TOS --set-tos Maximize-Reliability;-j TOS --set-tos 0x04/0x3f;OK
+-j TOS --set-tos Minimize-Cost;-j TOS --set-tos 0x02/0x3f;OK
+-j TOS --set-tos Normal-Service;-j TOS --set-tos 0x00/0x3f;OK
-j TOS --and-tos 0x12;-j TOS --set-tos 0x00/0xed;OK
-j TOS --or-tos 0x12;-j TOS --set-tos 0x12/0x12;OK
-j TOS --xor-tos 0x12;-j TOS --set-tos 0x12/0x00;OK
diff --git a/extensions/libxt_TOS.txlate b/extensions/libxt_TOS.txlate
index 0952310e..37ef1d86 100644
--- a/extensions/libxt_TOS.txlate
+++ b/extensions/libxt_TOS.txlate
@@ -1,23 +1,26 @@
ip6tables-translate -A INPUT -j TOS --set-tos 0x1f
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x07
+nft 'add rule ip6 filter INPUT counter ip6 dscp set 0x07'
ip6tables-translate -A INPUT -j TOS --set-tos 0xff
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x3f
+nft 'add rule ip6 filter INPUT counter ip6 dscp set 0x3f'
ip6tables-translate -A INPUT -j TOS --set-tos Minimize-Delay
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x04
+nft 'add rule ip6 filter INPUT counter ip6 dscp set 0x04'
ip6tables-translate -A INPUT -j TOS --set-tos Minimize-Cost
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x00
+nft 'add rule ip6 filter INPUT counter ip6 dscp set 0x00'
ip6tables-translate -A INPUT -j TOS --set-tos Normal-Service
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x00
+nft 'add rule ip6 filter INPUT counter ip6 dscp set 0x00'
ip6tables-translate -A INPUT -j TOS --and-tos 0x12
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x00
+nft 'add rule ip6 filter INPUT counter ip6 dscp set ip6 dscp and 0x04'
ip6tables-translate -A INPUT -j TOS --or-tos 0x12
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x04
+nft 'add rule ip6 filter INPUT counter ip6 dscp set ip6 dscp or 0x04'
ip6tables-translate -A INPUT -j TOS --xor-tos 0x12
-nft add rule ip6 filter INPUT counter ip6 dscp set 0x04
+nft 'add rule ip6 filter INPUT counter ip6 dscp set ip6 dscp xor 0x04'
+
+ip6tables-translate -A INPUT -j TOS --set-tos 0x12/0x34
+nft 'add rule ip6 filter INPUT counter ip6 dscp set ip6 dscp and 0x32 xor 0x04'
diff --git a/extensions/libxt_TRACE.txlate b/extensions/libxt_TRACE.txlate
index 8e3d2a7a..a9d28fe0 100644
--- a/extensions/libxt_TRACE.txlate
+++ b/extensions/libxt_TRACE.txlate
@@ -1,2 +1,2 @@
iptables-translate -t raw -A PREROUTING -j TRACE
-nft add rule ip raw PREROUTING counter nftrace set 1
+nft 'add rule ip raw PREROUTING counter nftrace set 1'
diff --git a/extensions/libxt_addrtype.txlate b/extensions/libxt_addrtype.txlate
index a719b2c9..70c0a345 100644
--- a/extensions/libxt_addrtype.txlate
+++ b/extensions/libxt_addrtype.txlate
@@ -1,11 +1,11 @@
iptables-translate -A INPUT -m addrtype --src-type LOCAL
-nft add rule ip filter INPUT fib saddr type local counter
+nft 'add rule ip filter INPUT fib saddr type local counter'
iptables-translate -A INPUT -m addrtype --dst-type LOCAL
-nft add rule ip filter INPUT fib daddr type local counter
+nft 'add rule ip filter INPUT fib daddr type local counter'
iptables-translate -A INPUT -m addrtype ! --dst-type ANYCAST,LOCAL
-nft add rule ip filter INPUT fib daddr type != { local, anycast } counter
+nft 'add rule ip filter INPUT fib daddr type != { local, anycast } counter'
iptables-translate -A INPUT -m addrtype --limit-iface-in --dst-type ANYCAST,LOCAL
-nft add rule ip filter INPUT fib daddr . iif type { local, anycast } counter
+nft 'add rule ip filter INPUT fib daddr . iif type { local, anycast } counter'
diff --git a/extensions/libxt_bpf.c b/extensions/libxt_bpf.c
index eeae86e5..5e035837 100644
--- a/extensions/libxt_bpf.c
+++ b/extensions/libxt_bpf.c
@@ -83,8 +83,7 @@ static int bpf_obj_get_readonly(const char *filepath)
attr.file_flags = 0;
return syscall(__NR_bpf, BPF_OBJ_GET, &attr, sizeof(attr));
#else
- xtables_error(OTHER_PROBLEM,
- "No bpf header, kernel headers too old?\n");
+ xtables_error(OTHER_PROBLEM, "No bpf header, kernel headers too old?");
return -EINVAL;
#endif
}
diff --git a/extensions/libxt_cgroup.txlate b/extensions/libxt_cgroup.txlate
index 75f2e6ae..6e3aab76 100644
--- a/extensions/libxt_cgroup.txlate
+++ b/extensions/libxt_cgroup.txlate
@@ -1,5 +1,5 @@
iptables-translate -t filter -A INPUT -m cgroup --cgroup 0 -j ACCEPT
-nft add rule ip filter INPUT meta cgroup 0 counter accept
+nft 'add rule ip filter INPUT meta cgroup 0 counter accept'
iptables-translate -t filter -A INPUT -m cgroup ! --cgroup 0 -j ACCEPT
-nft add rule ip filter INPUT meta cgroup != 0 counter accept
+nft 'add rule ip filter INPUT meta cgroup != 0 counter accept'
diff --git a/extensions/libxt_cluster.txlate b/extensions/libxt_cluster.txlate
index 9dcf5707..4dc1c691 100644
--- a/extensions/libxt_cluster.txlate
+++ b/extensions/libxt_cluster.txlate
@@ -1,26 +1,26 @@
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 2 --cluster-local-node 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 2 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 2 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 1 --cluster-local-node 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 1 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 1 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 2 --cluster-local-nodemask 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 2 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 2 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 1 --cluster-local-nodemask 1 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 1 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 1 seed 0xdeadbeef eq 1 meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 32 --cluster-local-node 32 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 32 seed 0xdeadbeef eq 32 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 32 seed 0xdeadbeef eq 32 meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 32 --cluster-local-nodemask 32 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 32 seed 0xdeadbeef eq 6 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 32 seed 0xdeadbeef eq 6 meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 32 --cluster-local-nodemask 5 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 32 seed 0xdeadbeef { 0, 2 } meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 32 seed 0xdeadbeef { 0, 2 } meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 7 --cluster-local-nodemask 9 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 7 seed 0xdeadbeef { 0, 3 } meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 7 seed 0xdeadbeef { 0, 3 } meta pkttype set host counter meta mark set 0xffff'
iptables-translate -A PREROUTING -t mangle -i eth1 -m cluster --cluster-total-nodes 7 --cluster-local-node 5 --cluster-hash-seed 0xdeadbeef -j MARK --set-mark 0xffff
-nft add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 7 seed 0xdeadbeef eq 5 meta pkttype set host counter meta mark set 0xffff
+nft 'add rule ip mangle PREROUTING iifname "eth1" jhash ct original saddr mod 7 seed 0xdeadbeef eq 5 meta pkttype set host counter meta mark set 0xffff'
diff --git a/extensions/libxt_comment.c b/extensions/libxt_comment.c
index 69795b6c..e9c539f6 100644
--- a/extensions/libxt_comment.c
+++ b/extensions/libxt_comment.c
@@ -55,12 +55,7 @@ static int comment_xlate(struct xt_xlate *xl,
char comment[XT_MAX_COMMENT_LEN + sizeof("\\\"\\\"")];
commentinfo->comment[XT_MAX_COMMENT_LEN - 1] = '\0';
- if (params->escape_quotes)
- snprintf(comment, sizeof(comment), "\\\"%s\\\"",
- commentinfo->comment);
- else
- snprintf(comment, sizeof(comment), "\"%s\"",
- commentinfo->comment);
+ snprintf(comment, sizeof(comment), "\"%s\"", commentinfo->comment);
xt_xlate_add_comment(xl, comment);
diff --git a/extensions/libxt_comment.txlate b/extensions/libxt_comment.txlate
index c610b0e5..5d4ce59d 100644
--- a/extensions/libxt_comment.txlate
+++ b/extensions/libxt_comment.txlate
@@ -1,8 +1,8 @@
iptables-translate -A INPUT -s 192.168.0.0 -m comment --comment "A privatized IP block"
-nft add rule ip filter INPUT ip saddr 192.168.0.0 counter comment \"A privatized IP block\"
+nft 'add rule ip filter INPUT ip saddr 192.168.0.0 counter comment "A privatized IP block"'
iptables-translate -A INPUT -p tcp -m tcp --sport http -s 192.168.0.0/16 -d 192.168.0.0/16 -j LONGNACCEPT -m comment --comment "foobar"
-nft add rule ip filter INPUT ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 tcp sport 80 counter jump LONGNACCEPT comment \"foobar\"
+nft 'add rule ip filter INPUT ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 tcp sport 80 counter jump LONGNACCEPT comment "foobar"'
iptables-translate -A FORWARD -p tcp -m tcp --sport http -s 192.168.0.0/16 -d 192.168.0.0/16 -j DROP -m comment --comment singlecomment
-nft add rule ip filter FORWARD ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 tcp sport 80 counter drop comment \"singlecomment\"
+nft 'add rule ip filter FORWARD ip saddr 192.168.0.0/16 ip daddr 192.168.0.0/16 tcp sport 80 counter drop comment "singlecomment"'
diff --git a/extensions/libxt_connbytes.txlate b/extensions/libxt_connbytes.txlate
index f78958d2..a6af1b87 100644
--- a/extensions/libxt_connbytes.txlate
+++ b/extensions/libxt_connbytes.txlate
@@ -1,14 +1,14 @@
iptables-translate -A OUTPUT -m connbytes --connbytes 200 --connbytes-dir original --connbytes-mode packets
-nft add rule ip filter OUTPUT ct original packets ge 200 counter
+nft 'add rule ip filter OUTPUT ct original packets ge 200 counter'
iptables-translate -A OUTPUT -m connbytes ! --connbytes 200 --connbytes-dir reply --connbytes-mode packets
-nft add rule ip filter OUTPUT ct reply packets lt 200 counter
+nft 'add rule ip filter OUTPUT ct reply packets lt 200 counter'
iptables-translate -A OUTPUT -m connbytes --connbytes 200:600 --connbytes-dir both --connbytes-mode bytes
-nft add rule ip filter OUTPUT ct bytes 200-600 counter
+nft 'add rule ip filter OUTPUT ct bytes 200-600 counter'
iptables-translate -A OUTPUT -m connbytes ! --connbytes 200:600 --connbytes-dir both --connbytes-mode bytes
-nft add rule ip filter OUTPUT ct bytes != 200-600 counter
+nft 'add rule ip filter OUTPUT ct bytes != 200-600 counter'
iptables-translate -A OUTPUT -m connbytes --connbytes 200:200 --connbytes-dir both --connbytes-mode avgpkt
-nft add rule ip filter OUTPUT ct avgpkt 200 counter
+nft 'add rule ip filter OUTPUT ct avgpkt 200 counter'
diff --git a/extensions/libxt_connlabel.txlate b/extensions/libxt_connlabel.txlate
index 12e4ac03..cba01d2d 100644
--- a/extensions/libxt_connlabel.txlate
+++ b/extensions/libxt_connlabel.txlate
@@ -1,5 +1,5 @@
iptables-translate -A INPUT -m connlabel --label 40
-nft add rule ip filter INPUT ct label 40 counter
+nft 'add rule ip filter INPUT ct label 40 counter'
iptables-translate -A INPUT -m connlabel ! --label 40 --set
-nft add rule ip filter INPUT ct label set 40 ct label and 40 != 40 counter
+nft 'add rule ip filter INPUT ct label set 40 ct label and 40 != 40 counter'
diff --git a/extensions/libxt_connlimit.t b/extensions/libxt_connlimit.t
index c7ea61e9..366cea74 100644
--- a/extensions/libxt_connlimit.t
+++ b/extensions/libxt_connlimit.t
@@ -1,11 +1,11 @@
:INPUT,FORWARD,OUTPUT
--m connlimit --connlimit-upto 0;=;OK
--m connlimit --connlimit-upto 4294967295;=;OK
--m connlimit --connlimit-upto 4294967296;;FAIL
+-m connlimit --connlimit-upto 0;-m connlimit --connlimit-upto 0 --connlimit-mask 32 --connlimit-saddr;OK
+-m connlimit --connlimit-upto 4294967295 --connlimit-mask 32 --connlimit-saddr;=;OK
+-m connlimit --connlimit-upto 4294967296 --connlimit-mask 32 --connlimit-saddr;;FAIL
-m connlimit --connlimit-upto -1;;FAIL
--m connlimit --connlimit-above 0;=;OK
--m connlimit --connlimit-above 4294967295;=;OK
--m connlimit --connlimit-above 4294967296;;FAIL
+-m connlimit --connlimit-above 0;-m connlimit --connlimit-above 0 --connlimit-mask 32 --connlimit-saddr;OK
+-m connlimit --connlimit-above 4294967295 --connlimit-mask 32 --connlimit-saddr;=;OK
+-m connlimit --connlimit-above 4294967296 --connlimit-mask 32 --connlimit-saddr;;FAIL
-m connlimit --connlimit-above -1;;FAIL
-m connlimit --connlimit-upto 1 --conlimit-above 1;;FAIL
-m connlimit --connlimit-above 10 --connlimit-saddr;-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-saddr;OK
diff --git a/extensions/libxt_connlimit.txlate b/extensions/libxt_connlimit.txlate
index 758868c4..3108a529 100644
--- a/extensions/libxt_connlimit.txlate
+++ b/extensions/libxt_connlimit.txlate
@@ -1,15 +1,15 @@
iptables-translate -A INPUT -m connlimit --connlimit-above 2
-nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
-nft add rule ip filter INPUT add @connlimit0 { ip saddr ct count over 2 } counter
+nft 'add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }'
+nft 'add rule ip filter INPUT add @connlimit0 { ip saddr ct count over 2 } counter'
iptables-translate -A INPUT -m connlimit --connlimit-upto 2
-nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
-nft add rule ip filter INPUT add @connlimit0 { ip saddr ct count 2 } counter
+nft 'add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }'
+nft 'add rule ip filter INPUT add @connlimit0 { ip saddr ct count 2 } counter'
iptables-translate -A INPUT -m connlimit --connlimit-upto 2 --connlimit-mask 24
-nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
-nft add rule ip filter INPUT add @connlimit0 { ip saddr and 255.255.255.0 ct count 2 } counter
+nft 'add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }'
+nft 'add rule ip filter INPUT add @connlimit0 { ip saddr and 255.255.255.0 ct count 2 } counter'
iptables-translate -A INPUT -m connlimit --connlimit-upto 2 --connlimit-daddr
-nft add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }
-nft add rule ip filter INPUT add @connlimit0 { ip daddr ct count 2 } counter
+nft 'add set ip filter connlimit0 { type ipv4_addr; flags dynamic; }'
+nft 'add rule ip filter INPUT add @connlimit0 { ip daddr ct count 2 } counter'
diff --git a/extensions/libxt_connmark.t b/extensions/libxt_connmark.t
index 4dd7d9af..353970a8 100644
--- a/extensions/libxt_connmark.t
+++ b/extensions/libxt_connmark.t
@@ -2,8 +2,8 @@
*mangle
-m connmark --mark 0xffffffff;=;OK
-m connmark --mark 0xffffffff/0xffffffff;-m connmark --mark 0xffffffff;OK
--m connmark --mark 0xffffffff/0;=;OK
--m connmark --mark 0/0xffffffff;-m connmark --mark 0;OK
+-m connmark --mark 0xffffffff/0x0;=;OK
+-m connmark --mark 0/0xffffffff;-m connmark --mark 0x0;OK
-m connmark --mark -1;;FAIL
-m connmark --mark 0xfffffffff;;FAIL
-m connmark;;FAIL
diff --git a/extensions/libxt_connmark.txlate b/extensions/libxt_connmark.txlate
index 89423259..e7bfd721 100644
--- a/extensions/libxt_connmark.txlate
+++ b/extensions/libxt_connmark.txlate
@@ -1,14 +1,14 @@
iptables-translate -A INPUT -m connmark --mark 2 -j ACCEPT
-nft add rule ip filter INPUT ct mark 0x2 counter accept
+nft 'add rule ip filter INPUT ct mark 0x2 counter accept'
iptables-translate -A INPUT -m connmark ! --mark 2 -j ACCEPT
-nft add rule ip filter INPUT ct mark != 0x2 counter accept
+nft 'add rule ip filter INPUT ct mark != 0x2 counter accept'
iptables-translate -A INPUT -m connmark --mark 10/10 -j ACCEPT
-nft add rule ip filter INPUT ct mark and 0xa == 0xa counter accept
+nft 'add rule ip filter INPUT ct mark and 0xa == 0xa counter accept'
iptables-translate -A INPUT -m connmark ! --mark 10/10 -j ACCEPT
-nft add rule ip filter INPUT ct mark and 0xa != 0xa counter accept
+nft 'add rule ip filter INPUT ct mark and 0xa != 0xa counter accept'
iptables-translate -t mangle -A PREROUTING -p tcp --dport 40 -m connmark --mark 0x40
-nft add rule ip mangle PREROUTING tcp dport 40 ct mark 0x40 counter
+nft 'add rule ip mangle PREROUTING tcp dport 40 ct mark 0x40 counter'
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index 08dba42d..09548c29 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -1186,7 +1186,6 @@ static int state_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, "ct state ");
state_xlate_print(xl, sinfo->state_mask,
sinfo->invert_flags & XT_CONNTRACK_STATE);
- xt_xlate_add(xl, " ");
return 1;
}
diff --git a/extensions/libxt_conntrack.txlate b/extensions/libxt_conntrack.txlate
index 45fba984..0f44a957 100644
--- a/extensions/libxt_conntrack.txlate
+++ b/extensions/libxt_conntrack.txlate
@@ -1,60 +1,60 @@
iptables-translate -t filter -A INPUT -m conntrack --ctstate NEW,RELATED -j ACCEPT
-nft add rule ip filter INPUT ct state new,related counter accept
+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 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 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
+nft 'add rule ip filter INPUT ct original protocol 17 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
+nft 'add rule ip filter INPUT ct original protocol != 17 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctorigsrc 10.100.2.131 -j ACCEPT
-nft add rule ip filter INPUT ct original saddr 10.100.2.131 counter accept
+nft 'add rule ip filter INPUT ct original saddr 10.100.2.131 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctorigsrc 10.100.0.0/255.255.0.0 -j ACCEPT
-nft add rule ip filter INPUT ct original saddr 10.100.0.0/16 counter accept
+nft 'add rule ip filter INPUT ct original saddr 10.100.0.0/16 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctorigdst 10.100.2.131 -j ACCEPT
-nft add rule ip filter INPUT ct original daddr 10.100.2.131 counter accept
+nft 'add rule ip filter INPUT ct original daddr 10.100.2.131 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctreplsrc 10.100.2.131 -j ACCEPT
-nft add rule ip filter INPUT ct reply saddr 10.100.2.131 counter accept
+nft 'add rule ip filter INPUT ct reply saddr 10.100.2.131 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctrepldst 10.100.2.131 -j ACCEPT
-nft add rule ip filter INPUT ct reply daddr 10.100.2.131 counter accept
+nft 'add rule ip filter INPUT ct reply daddr 10.100.2.131 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctproto tcp --ctorigsrcport 443:444 -j ACCEPT
-nft add rule ip filter INPUT ct original protocol 6 ct original proto-src 443-444 counter accept
+nft 'add rule ip filter INPUT ct original protocol 6 ct original proto-src 443-444 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctstatus EXPECTED -j ACCEPT
-nft add rule ip filter INPUT ct status expected counter 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 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 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
+nft 'add rule ip filter INPUT ct status assured,confirmed counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctexpire 3 -j ACCEPT
-nft add rule ip filter INPUT ct expiration 3 counter accept
+nft 'add rule ip filter INPUT ct expiration 3 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctdir ORIGINAL -j ACCEPT
-nft add rule ip filter INPUT ct direction original counter accept
+nft 'add rule ip filter INPUT ct direction original counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctstate NEW --ctproto tcp --ctorigsrc 192.168.0.1 --ctorigdst 192.168.0.1 --ctreplsrc 192.168.0.1 --ctrepldst 192.168.0.1 --ctorigsrcport 12 --ctorigdstport 14 --ctreplsrcport 16 --ctrepldstport 18 --ctexpire 10 --ctstatus SEEN_REPLY --ctdir ORIGINAL -j ACCEPT
-nft add rule ip filter INPUT ct direction original ct original protocol 6 ct state new ct status seen-reply ct expiration 10 ct original saddr 192.168.0.1 ct original daddr 192.168.0.1 ct reply saddr 192.168.0.1 ct reply daddr 192.168.0.1 ct original proto-src 12 ct original proto-dst 14 ct reply proto-src 16 ct reply proto-dst 18 counter accept
+nft 'add rule ip filter INPUT ct direction original ct original protocol 6 ct state new ct status seen-reply ct expiration 10 ct original saddr 192.168.0.1 ct original daddr 192.168.0.1 ct reply saddr 192.168.0.1 ct reply daddr 192.168.0.1 ct original proto-src 12 ct original proto-dst 14 ct reply proto-src 16 ct reply proto-dst 18 counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctstate SNAT -j ACCEPT
-nft add rule ip filter INPUT ct status snat counter accept
+nft 'add rule ip filter INPUT ct status snat counter accept'
iptables-translate -t filter -A INPUT -m conntrack --ctstate DNAT -j ACCEPT
-nft add rule ip filter INPUT ct status dnat counter accept
+nft 'add rule ip filter INPUT ct status dnat counter accept'
diff --git a/extensions/libxt_cpu.txlate b/extensions/libxt_cpu.txlate
index c59b0e02..937c939e 100644
--- a/extensions/libxt_cpu.txlate
+++ b/extensions/libxt_cpu.txlate
@@ -1,5 +1,5 @@
iptables-translate -A INPUT -p tcp --dport 80 -m cpu --cpu 0 -j ACCEPT
-nft add rule ip filter INPUT tcp dport 80 cpu 0 counter accept
+nft 'add rule ip filter INPUT tcp dport 80 cpu 0 counter accept'
iptables-translate -A INPUT -p tcp --dport 80 -m cpu ! --cpu 1 -j ACCEPT
-nft add rule ip filter INPUT tcp dport 80 cpu != 1 counter accept
+nft 'add rule ip filter INPUT tcp dport 80 cpu != 1 counter accept'
diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c
index abd420fc..bfceced3 100644
--- a/extensions/libxt_dccp.c
+++ b/extensions/libxt_dccp.c
@@ -343,7 +343,6 @@ static int dccp_xlate(struct xt_xlate *xl,
{
const struct xt_dccp_info *einfo =
(const struct xt_dccp_info *)params->match->data;
- char *space = "";
int ret = 1;
if (einfo->flags & XT_DCCP_SRC_PORTS) {
@@ -353,27 +352,21 @@ static int dccp_xlate(struct xt_xlate *xl,
if (einfo->spts[0] != einfo->spts[1])
xt_xlate_add(xl, "-%u", einfo->spts[1]);
-
- space = " ";
}
if (einfo->flags & XT_DCCP_DEST_PORTS) {
- xt_xlate_add(xl, "%sdccp dport%s %u", space,
+ xt_xlate_add(xl, "dccp dport%s %u",
einfo->invflags & XT_DCCP_DEST_PORTS ? " !=" : "",
einfo->dpts[0]);
if (einfo->dpts[0] != einfo->dpts[1])
xt_xlate_add(xl, "-%u", einfo->dpts[1]);
-
- space = " ";
}
if (einfo->flags & XT_DCCP_TYPE && einfo->typemask) {
- xt_xlate_add(xl, "%sdccp type%s ", space,
+ xt_xlate_add(xl, "dccp type%s ",
einfo->invflags & XT_DCCP_TYPE ? " !=" : "");
ret = dccp_type_xlate(einfo, xl);
-
- space = " ";
}
/* FIXME: no dccp option support in nftables yet */
diff --git a/extensions/libxt_dccp.txlate b/extensions/libxt_dccp.txlate
index ea853f6a..a4da1a79 100644
--- a/extensions/libxt_dccp.txlate
+++ b/extensions/libxt_dccp.txlate
@@ -1,20 +1,20 @@
iptables-translate -A INPUT -p dccp -m dccp --sport 100
-nft add rule ip filter INPUT dccp sport 100 counter
+nft 'add rule ip filter INPUT dccp sport 100 counter'
iptables-translate -A INPUT -p dccp -m dccp --dport 100:200
-nft add rule ip filter INPUT dccp dport 100-200 counter
+nft 'add rule ip filter INPUT dccp dport 100-200 counter'
iptables-translate -A INPUT -p dccp -m dccp ! --dport 100
-nft add rule ip filter INPUT dccp dport != 100 counter
+nft 'add rule ip filter INPUT dccp dport != 100 counter'
iptables-translate -A INPUT -p dccp -m dccp --dccp-types CLOSE
-nft add rule ip filter INPUT dccp type close counter
+nft 'add rule ip filter INPUT dccp type close counter'
iptables-translate -A INPUT -p dccp -m dccp --dccp-types INVALID
-nft add rule ip filter INPUT dccp type 10-15 counter
+nft 'add rule ip filter INPUT dccp type 10-15 counter'
iptables-translate -A INPUT -p dccp -m dccp --dport 100 --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,SYNC,SYNCACK,INVALID
-nft add rule ip filter INPUT dccp dport 100 dccp type {request, response, data, ack, dataack, closereq, close, sync, syncack, 10-15} counter
+nft 'add rule ip filter INPUT dccp dport 100 dccp type { request, response, data, ack, dataack, closereq, close, sync, syncack, 10-15 } counter'
iptables-translate -A INPUT -p dccp -m dccp --sport 200 --dport 100
-nft add rule ip filter INPUT dccp sport 200 dccp dport 100 counter
+nft 'add rule ip filter INPUT dccp sport 200 dccp dport 100 counter'
diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c
index a88211c5..f60526ff 100644
--- a/extensions/libxt_devgroup.c
+++ b/extensions/libxt_devgroup.c
@@ -129,7 +129,6 @@ static void devgroup_show_xlate(const struct xt_devgroup_info *info,
struct xt_xlate *xl, int numeric)
{
enum xt_op op = XT_OP_EQ;
- char *space = "";
if (info->flags & XT_DEVGROUP_MATCH_SRC) {
if (info->flags & XT_DEVGROUP_INVERT_SRC)
@@ -137,13 +136,12 @@ static void devgroup_show_xlate(const struct xt_devgroup_info *info,
xt_xlate_add(xl, "iifgroup ");
print_devgroup_xlate(info->src_group, op,
info->src_mask, xl, numeric);
- space = " ";
}
if (info->flags & XT_DEVGROUP_MATCH_DST) {
if (info->flags & XT_DEVGROUP_INVERT_DST)
op = XT_OP_NEQ;
- xt_xlate_add(xl, "%soifgroup ", space);
+ xt_xlate_add(xl, "oifgroup ");
print_devgroup_xlate(info->dst_group, op,
info->dst_mask, xl, numeric);
}
diff --git a/extensions/libxt_devgroup.txlate b/extensions/libxt_devgroup.txlate
index aeb597bd..dea47a99 100644
--- a/extensions/libxt_devgroup.txlate
+++ b/extensions/libxt_devgroup.txlate
@@ -1,17 +1,17 @@
iptables-translate -A FORWARD -m devgroup --src-group 0x2 -j ACCEPT
-nft add rule ip filter FORWARD iifgroup 0x2 counter accept
+nft 'add rule ip filter FORWARD iifgroup 0x2 counter accept'
iptables-translate -A FORWARD -m devgroup --dst-group 0xc/0xc -j ACCEPT
-nft add rule ip filter FORWARD oifgroup and 0xc == 0xc counter accept
+nft 'add rule ip filter FORWARD oifgroup and 0xc == 0xc counter accept'
iptables-translate -t mangle -A PREROUTING -p tcp --dport 46000 -m devgroup --src-group 23 -j ACCEPT
-nft add rule ip mangle PREROUTING tcp dport 46000 iifgroup 0x17 counter accept
+nft 'add rule ip mangle PREROUTING tcp dport 46000 iifgroup 0x17 counter accept'
iptables-translate -A FORWARD -m devgroup ! --dst-group 0xc/0xc -j ACCEPT
-nft add rule ip filter FORWARD oifgroup and 0xc != 0xc counter accept
+nft 'add rule ip filter FORWARD oifgroup and 0xc != 0xc counter accept'
iptables-translate -A FORWARD -m devgroup ! --src-group 0x2 -j ACCEPT
-nft add rule ip filter FORWARD iifgroup != 0x2 counter accept
+nft 'add rule ip filter FORWARD iifgroup != 0x2 counter accept'
iptables-translate -A FORWARD -m devgroup ! --src-group 0x2 --dst-group 0xc/0xc -j ACCEPT
-nft add rule ip filter FORWARD iifgroup != 0x2 oifgroup and 0xc != 0xc counter accept
+nft 'add rule ip filter FORWARD iifgroup != 0x2 oifgroup and 0xc != 0xc counter accept'
diff --git a/extensions/libxt_dscp.t b/extensions/libxt_dscp.t
index 38d7f04e..e0101906 100644
--- a/extensions/libxt_dscp.t
+++ b/extensions/libxt_dscp.t
@@ -1,5 +1,5 @@
:INPUT,FORWARD,OUTPUT
--m dscp --dscp 0;=;OK
+-m dscp --dscp 0x00;=;OK
-m dscp --dscp 0x3f;=;OK
-m dscp --dscp -1;;FAIL
-m dscp --dscp 0x40;;FAIL
diff --git a/extensions/libxt_dscp.txlate b/extensions/libxt_dscp.txlate
index 2cccc3b4..ca2ec724 100644
--- a/extensions/libxt_dscp.txlate
+++ b/extensions/libxt_dscp.txlate
@@ -1,5 +1,5 @@
iptables-translate -t filter -A INPUT -m dscp --dscp 0x32 -j ACCEPT
-nft add rule ip filter INPUT ip dscp 0x32 counter accept
+nft 'add rule ip filter INPUT ip dscp 0x32 counter accept'
ip6tables-translate -t filter -A INPUT -m dscp ! --dscp 0x32 -j ACCEPT
-nft add rule ip6 filter INPUT ip6 dscp != 0x32 counter accept
+nft 'add rule ip6 filter INPUT ip6 dscp != 0x32 counter accept'
diff --git a/extensions/libxt_ecn.c b/extensions/libxt_ecn.c
index ad3c7a03..83a4acfa 100644
--- a/extensions/libxt_ecn.c
+++ b/extensions/libxt_ecn.c
@@ -156,6 +156,8 @@ static int ecn_xlate(struct xt_xlate *xl,
case 3:
xt_xlate_add(xl, "ce");
break;
+ default:
+ return 0;
}
}
return 1;
diff --git a/extensions/libxt_ecn.txlate b/extensions/libxt_ecn.txlate
index f012f128..8488f8ce 100644
--- a/extensions/libxt_ecn.txlate
+++ b/extensions/libxt_ecn.txlate
@@ -1,29 +1,29 @@
iptables-translate -A INPUT -m ecn --ecn-ip-ect 0
-nft add rule ip filter INPUT ip ecn not-ect counter
+nft 'add rule ip filter INPUT ip ecn not-ect counter'
iptables-translate -A INPUT -m ecn --ecn-ip-ect 1
-nft add rule ip filter INPUT ip ecn ect1 counter
+nft 'add rule ip filter INPUT ip ecn ect1 counter'
iptables-translate -A INPUT -m ecn --ecn-ip-ect 2
-nft add rule ip filter INPUT ip ecn ect0 counter
+nft 'add rule ip filter INPUT ip ecn ect0 counter'
iptables-translate -A INPUT -m ecn --ecn-ip-ect 3
-nft add rule ip filter INPUT ip ecn ce counter
+nft 'add rule ip filter INPUT ip ecn ce counter'
iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 0
-nft add rule ip filter INPUT ip ecn != not-ect counter
+nft 'add rule ip filter INPUT ip ecn != not-ect counter'
iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 1
-nft add rule ip filter INPUT ip ecn != ect1 counter
+nft 'add rule ip filter INPUT ip ecn != ect1 counter'
iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 2
-nft add rule ip filter INPUT ip ecn != ect0 counter
+nft 'add rule ip filter INPUT ip ecn != ect0 counter'
iptables-translate -A INPUT -m ecn ! --ecn-ip-ect 3
-nft add rule ip filter INPUT ip ecn != ce counter
+nft 'add rule ip filter INPUT ip ecn != ce counter'
iptables-translate -A INPUT -m ecn ! --ecn-tcp-ece
-nft add rule ip filter INPUT tcp flags != ecn counter
+nft 'add rule ip filter INPUT tcp flags != ecn counter'
iptables-translate -A INPUT -m ecn --ecn-tcp-cwr
-nft add rule ip filter INPUT tcp flags cwr counter
+nft 'add rule ip filter INPUT tcp flags cwr counter'
diff --git a/extensions/libxt_esp.txlate b/extensions/libxt_esp.txlate
index 5e2f18fa..f6aba52f 100644
--- a/extensions/libxt_esp.txlate
+++ b/extensions/libxt_esp.txlate
@@ -1,11 +1,11 @@
iptables-translate -A FORWARD -p esp -j ACCEPT
-nft add rule ip filter FORWARD ip protocol esp counter accept
+nft 'add rule ip filter FORWARD ip protocol esp counter accept'
iptables-translate -A INPUT --in-interface wan --protocol esp -j ACCEPT
-nft add rule ip filter INPUT iifname "wan" ip protocol esp counter accept
+nft 'add rule ip filter INPUT iifname "wan" ip protocol esp counter accept'
iptables-translate -A INPUT -p 50 -m esp --espspi 500 -j DROP
-nft add rule ip filter INPUT esp spi 500 counter drop
+nft 'add rule ip filter INPUT esp spi 500 counter drop'
iptables-translate -A INPUT -p 50 -m esp --espspi 500:600 -j DROP
-nft add rule ip filter INPUT esp spi 500-600 counter drop
+nft 'add rule ip filter INPUT esp spi 500-600 counter drop'
diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index 3f3c4301..24e784ab 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -356,12 +356,12 @@ static bool parse_bytes(const char *rate, void *val, struct hashlimit_mt_udata *
tmp = (uint64_t) r * factor;
if (tmp > max)
xtables_error(PARAMETER_PROBLEM,
- "Rate value too large \"%"PRIu64"\" (max %"PRIu64")\n",
- tmp, max);
+ "Rate value too large \"%"PRIu64"\" (max %"PRIu64")",
+ tmp, max);
tmp = bytes_to_cost(tmp);
if (tmp == 0)
- xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"\n", rate);
+ xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"", rate);
ud->mult = XT_HASHLIMIT_BYTE_EXPIRE;
@@ -407,7 +407,7 @@ int parse_rate(const char *rate, void *val, struct hashlimit_mt_udata *ud, int r
* The rate maps to infinity. (1/day is the minimum they can
* specify, so we are ok at that end).
*/
- xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
+ xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"", rate);
if(revision == 1)
*((uint32_t*)val) = tmp;
@@ -1270,7 +1270,7 @@ static void hashlimit_print_subnet_xlate(struct xt_xlate *xl,
}
}
- xt_xlate_add(xl, fmt, acm);
+ xt_xlate_add_nospc(xl, fmt, acm);
if (nblocks > 0)
xt_xlate_add(xl, "%c", sep);
}
diff --git a/extensions/libxt_hashlimit.txlate b/extensions/libxt_hashlimit.txlate
index 6c8d07f1..306ee783 100644
--- a/extensions/libxt_hashlimit.txlate
+++ b/extensions/libxt_hashlimit.txlate
@@ -1,5 +1,5 @@
iptables-translate -A OUTPUT -m tcp -p tcp --dport 443 -m hashlimit --hashlimit-above 20kb/s --hashlimit-burst 1mb --hashlimit-mode dstip --hashlimit-name https --hashlimit-dstmask 24 -m state --state NEW -j DROP
-nft add rule ip filter OUTPUT tcp dport 443 meter https { ip daddr and 255.255.255.0 timeout 60s limit rate over 20 kbytes/second burst 1 mbytes} ct state new counter drop
+nft 'add rule ip filter OUTPUT tcp dport 443 meter https { ip daddr and 255.255.255.0 timeout 60s limit rate over 20 kbytes/second burst 1 mbytes } ct state new counter drop'
iptables-translate -A OUTPUT -m tcp -p tcp --dport 443 -m hashlimit --hashlimit-upto 300 --hashlimit-burst 15 --hashlimit-mode srcip,dstip --hashlimit-name https --hashlimit-htable-expire 300000 -m state --state NEW -j DROP
-nft add rule ip filter OUTPUT tcp dport 443 meter https { ip daddr . ip saddr timeout 300s limit rate 300/second burst 15 packets} ct state new counter drop
+nft 'add rule ip filter OUTPUT tcp dport 443 meter https { ip daddr . ip saddr timeout 300s limit rate 300/second burst 15 packets } ct state new counter drop'
diff --git a/extensions/libxt_helper.c b/extensions/libxt_helper.c
index 2afbf996..0f72eec6 100644
--- a/extensions/libxt_helper.c
+++ b/extensions/libxt_helper.c
@@ -50,12 +50,8 @@ static int helper_xlate(struct xt_xlate *xl,
{
const struct xt_helper_info *info = (const void *)params->match->data;
- if (params->escape_quotes)
- xt_xlate_add(xl, "ct helper%s \\\"%s\\\"",
- info->invert ? " !=" : "", info->name);
- else
- xt_xlate_add(xl, "ct helper%s \"%s\"",
- info->invert ? " !=" : "", info->name);
+ xt_xlate_add(xl, "ct helper%s \"%s\"",
+ info->invert ? " !=" : "", info->name);
return 1;
}
diff --git a/extensions/libxt_helper.txlate b/extensions/libxt_helper.txlate
index 8259aba3..2d94f740 100644
--- a/extensions/libxt_helper.txlate
+++ b/extensions/libxt_helper.txlate
@@ -1,5 +1,5 @@
iptables-translate -A FORWARD -m helper --helper sip
-nft add rule ip filter FORWARD ct helper \"sip\" counter
+nft 'add rule ip filter FORWARD ct helper "sip" counter'
iptables-translate -A FORWARD -m helper ! --helper ftp
-nft add rule ip filter FORWARD ct helper != \"ftp\" counter
+nft 'add rule ip filter FORWARD ct helper != "ftp" counter'
diff --git a/extensions/libxt_icmp.h b/extensions/libxt_icmp.h
index 5820206e..a763e50c 100644
--- a/extensions/libxt_icmp.h
+++ b/extensions/libxt_icmp.h
@@ -1,25 +1,249 @@
-struct xt_icmp_names {
+static const struct xt_icmp_names {
const char *name;
uint8_t type;
uint8_t code_min, code_max;
+} icmp_codes[] = {
+ { "any", 0xFF, 0, 0xFF },
+ { "echo-reply", 0, 0, 0xFF },
+ /* Alias */ { "pong", 0, 0, 0xFF },
+
+ { "destination-unreachable", 3, 0, 0xFF },
+ { "network-unreachable", 3, 0, 0 },
+ { "host-unreachable", 3, 1, 1 },
+ { "protocol-unreachable", 3, 2, 2 },
+ { "port-unreachable", 3, 3, 3 },
+ { "fragmentation-needed", 3, 4, 4 },
+ { "source-route-failed", 3, 5, 5 },
+ { "network-unknown", 3, 6, 6 },
+ { "host-unknown", 3, 7, 7 },
+ { "network-prohibited", 3, 9, 9 },
+ { "host-prohibited", 3, 10, 10 },
+ { "TOS-network-unreachable", 3, 11, 11 },
+ { "TOS-host-unreachable", 3, 12, 12 },
+ { "communication-prohibited", 3, 13, 13 },
+ { "host-precedence-violation", 3, 14, 14 },
+ { "precedence-cutoff", 3, 15, 15 },
+
+ { "source-quench", 4, 0, 0xFF },
+
+ { "redirect", 5, 0, 0xFF },
+ { "network-redirect", 5, 0, 0 },
+ { "host-redirect", 5, 1, 1 },
+ { "TOS-network-redirect", 5, 2, 2 },
+ { "TOS-host-redirect", 5, 3, 3 },
+
+ { "echo-request", 8, 0, 0xFF },
+ /* Alias */ { "ping", 8, 0, 0xFF },
+
+ { "router-advertisement", 9, 0, 0xFF },
+
+ { "router-solicitation", 10, 0, 0xFF },
+
+ { "time-exceeded", 11, 0, 0xFF },
+ /* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
+ { "ttl-zero-during-transit", 11, 0, 0 },
+ { "ttl-zero-during-reassembly", 11, 1, 1 },
+
+ { "parameter-problem", 12, 0, 0xFF },
+ { "ip-header-bad", 12, 0, 0 },
+ { "required-option-missing", 12, 1, 1 },
+
+ { "timestamp-request", 13, 0, 0xFF },
+
+ { "timestamp-reply", 14, 0, 0xFF },
+
+ { "address-mask-request", 17, 0, 0xFF },
+
+ { "address-mask-reply", 18, 0, 0xFF }
+}, icmpv6_codes[] = {
+ { "destination-unreachable", 1, 0, 0xFF },
+ { "no-route", 1, 0, 0 },
+ { "communication-prohibited", 1, 1, 1 },
+ { "beyond-scope", 1, 2, 2 },
+ { "address-unreachable", 1, 3, 3 },
+ { "port-unreachable", 1, 4, 4 },
+ { "failed-policy", 1, 5, 5 },
+ { "reject-route", 1, 6, 6 },
+
+ { "packet-too-big", 2, 0, 0xFF },
+
+ { "time-exceeded", 3, 0, 0xFF },
+ /* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
+ { "ttl-zero-during-transit", 3, 0, 0 },
+ { "ttl-zero-during-reassembly", 3, 1, 1 },
+
+ { "parameter-problem", 4, 0, 0xFF },
+ { "bad-header", 4, 0, 0 },
+ { "unknown-header-type", 4, 1, 1 },
+ { "unknown-option", 4, 2, 2 },
+
+ { "echo-request", 128, 0, 0xFF },
+ /* Alias */ { "ping", 128, 0, 0xFF },
+
+ { "echo-reply", 129, 0, 0xFF },
+ /* Alias */ { "pong", 129, 0, 0xFF },
+
+ { "router-solicitation", 133, 0, 0xFF },
+
+ { "router-advertisement", 134, 0, 0xFF },
+
+ { "neighbour-solicitation", 135, 0, 0xFF },
+ /* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
+
+ { "neighbour-advertisement", 136, 0, 0xFF },
+ /* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
+
+ { "redirect", 137, 0, 0xFF },
+}, igmp_types[] = {
+ { "membership-query", 0x11 },
+ { "membership-report-v1", 0x12 },
+ { "membership-report-v2", 0x16 },
+ { "leave-group", 0x17 },
+ { "membership-report-v3", 0x22 },
};
-static void xt_print_icmp_types(const struct xt_icmp_names *icmp_codes,
+static inline char *parse_range(const char *str, unsigned int res[])
+{
+ char *next;
+
+ if (!xtables_strtoui(str, &next, &res[0], 0, 255))
+ return NULL;
+
+ res[1] = res[0];
+ if (*next == ':') {
+ str = next + 1;
+ if (!xtables_strtoui(str, &next, &res[1], 0, 255))
+ return NULL;
+ }
+
+ return next;
+}
+
+static void
+__parse_icmp(const struct xt_icmp_names codes[], size_t n_codes,
+ const char *codes_name, const char *fmtstring,
+ uint8_t type[], uint8_t code[])
+{
+ unsigned int match = n_codes;
+ unsigned int i, number[2];
+
+ for (i = 0; i < n_codes; i++) {
+ if (strncasecmp(codes[i].name, fmtstring, strlen(fmtstring)))
+ continue;
+ if (match != n_codes)
+ xtables_error(PARAMETER_PROBLEM,
+ "Ambiguous %s type `%s': `%s' or `%s'?",
+ codes_name, fmtstring, codes[match].name,
+ codes[i].name);
+ match = i;
+ }
+
+ if (match < n_codes) {
+ type[0] = type[1] = codes[match].type;
+ if (code) {
+ code[0] = codes[match].code_min;
+ code[1] = codes[match].code_max;
+ }
+ } else {
+ char *next = parse_range(fmtstring, number);
+ if (!next)
+ xtables_error(PARAMETER_PROBLEM, "Unknown %s type `%s'",
+ codes_name, fmtstring);
+ type[0] = (uint8_t) number[0];
+ type[1] = (uint8_t) number[1];
+ switch (*next) {
+ case 0:
+ if (code) {
+ code[0] = 0;
+ code[1] = 255;
+ }
+ return;
+ case '/':
+ if (!code)
+ break;
+
+ next = parse_range(next + 1, number);
+ if (!next)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown %s code `%s'",
+ codes_name, fmtstring);
+ code[0] = (uint8_t) number[0];
+ code[1] = (uint8_t) number[1];
+ if (!*next)
+ break;
+ /* fallthrough */
+ default:
+ xtables_error(PARAMETER_PROBLEM,
+ "unknown character %c", *next);
+ }
+ }
+}
+
+static inline void
+__ipt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
+ const char *codes_name, const char *fmtstr,
+ uint8_t *type, uint8_t code[])
+{
+ uint8_t types[2];
+
+ __parse_icmp(codes, n_codes, codes_name, fmtstr, types, code);
+ if (types[1] != types[0])
+ xtables_error(PARAMETER_PROBLEM,
+ "%s type range not supported", codes_name);
+ *type = types[0];
+}
+
+static inline void
+ipt_parse_icmp(const char *str, uint8_t *type, uint8_t code[])
+{
+ __ipt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes),
+ "ICMP", str, type, code);
+}
+
+static inline void
+ipt_parse_icmpv6(const char *str, uint8_t *type, uint8_t code[])
+{
+ __ipt_parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
+ "ICMPv6", str, type, code);
+}
+
+static inline void
+ebt_parse_icmp(const char *str, uint8_t type[], uint8_t code[])
+{
+ __parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes),
+ "ICMP", str, type, code);
+}
+
+static inline void
+ebt_parse_icmpv6(const char *str, uint8_t type[], uint8_t code[])
+{
+ __parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
+ "ICMPv6", str, type, code);
+}
+
+static inline void
+ebt_parse_igmp(const char *str, uint8_t type[])
+{
+ __parse_icmp(igmp_types, ARRAY_SIZE(igmp_types),
+ "IGMP", str, type, NULL);
+}
+
+static void xt_print_icmp_types(const struct xt_icmp_names *_icmp_codes,
unsigned int n_codes)
{
unsigned int i;
for (i = 0; i < n_codes; ++i) {
- if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
- if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
- && (icmp_codes[i].code_max
- == icmp_codes[i-1].code_max))
- printf(" (%s)", icmp_codes[i].name);
+ if (i && _icmp_codes[i].type == _icmp_codes[i-1].type) {
+ if (_icmp_codes[i].code_min == _icmp_codes[i-1].code_min
+ && (_icmp_codes[i].code_max
+ == _icmp_codes[i-1].code_max))
+ printf(" (%s)", _icmp_codes[i].name);
else
- printf("\n %s", icmp_codes[i].name);
+ printf("\n %s", _icmp_codes[i].name);
}
else
- printf("\n%s", icmp_codes[i].name);
+ printf("\n%s", _icmp_codes[i].name);
}
printf("\n");
}
diff --git a/extensions/libxt_ipcomp.c b/extensions/libxt_ipcomp.c
index b5c43128..4171c4a1 100644
--- a/extensions/libxt_ipcomp.c
+++ b/extensions/libxt_ipcomp.c
@@ -101,6 +101,8 @@ static int comp_xlate(struct xt_xlate *xl,
const struct xt_ipcomp *compinfo =
(struct xt_ipcomp *)params->match->data;
+ /* ignore compinfo->hdrres like kernel's xt_ipcomp.c does */
+
xt_xlate_add(xl, "comp cpi %s",
compinfo->invflags & XT_IPCOMP_INV_SPI ? "!= " : "");
if (compinfo->spis[0] != compinfo->spis[1])
diff --git a/extensions/libxt_ipcomp.c.man b/extensions/libxt_ipcomp.c.man
index f3b17d21..824f5b3d 100644
--- a/extensions/libxt_ipcomp.c.man
+++ b/extensions/libxt_ipcomp.c.man
@@ -2,6 +2,3 @@ This module matches the parameters in IPcomp header of IPsec packets.
.TP
[\fB!\fP] \fB\-\-ipcompspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
Matches IPcomp header CPI value.
-.TP
-\fB\-\-compres\fP
-Matches if the reserved field is filled with zero.
diff --git a/extensions/libxt_ipcomp.txlate b/extensions/libxt_ipcomp.txlate
index f9efe53c..877cccbb 100644
--- a/extensions/libxt_ipcomp.txlate
+++ b/extensions/libxt_ipcomp.txlate
@@ -1,5 +1,5 @@
iptables-translate -t filter -A INPUT -m ipcomp --ipcompspi 0x12 -j ACCEPT
-nft add rule ip filter INPUT comp cpi 18 counter accept
+nft 'add rule ip filter INPUT comp cpi 18 counter accept'
iptables-translate -t filter -A INPUT -m ipcomp ! --ipcompspi 0x12 -j ACCEPT
-nft add rule ip filter INPUT comp cpi != 18 counter accept
+nft 'add rule ip filter INPUT comp cpi != 18 counter accept'
diff --git a/extensions/libxt_iprange.c b/extensions/libxt_iprange.c
index 04ce7b36..0df709d5 100644
--- a/extensions/libxt_iprange.c
+++ b/extensions/libxt_iprange.c
@@ -317,16 +317,14 @@ static int iprange_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ipt_iprange_info *info = (const void *)params->match->data;
- char *space = "";
if (info->flags & IPRANGE_SRC) {
xt_xlate_add(xl, "ip saddr%s",
info->flags & IPRANGE_SRC_INV ? " !=" : "");
print_iprange_xlate(&info->src, xl);
- space = " ";
}
if (info->flags & IPRANGE_DST) {
- xt_xlate_add(xl, "%sip daddr%s", space,
+ xt_xlate_add(xl, "ip daddr%s",
info->flags & IPRANGE_DST_INV ? " !=" : "");
print_iprange_xlate(&info->dst, xl);
}
@@ -339,7 +337,6 @@ static int iprange_mt4_xlate(struct xt_xlate *xl,
{
const struct xt_iprange_mtinfo *info =
(const void *)params->match->data;
- char *space = "";
if (info->flags & IPRANGE_SRC) {
xt_xlate_add(xl, "ip saddr%s %s",
@@ -347,10 +344,9 @@ static int iprange_mt4_xlate(struct xt_xlate *xl,
xtables_ipaddr_to_numeric(&info->src_min.in));
xt_xlate_add(xl, "-%s",
xtables_ipaddr_to_numeric(&info->src_max.in));
- space = " ";
}
if (info->flags & IPRANGE_DST) {
- xt_xlate_add(xl, "%sip daddr%s %s", space,
+ xt_xlate_add(xl, "ip daddr%s %s",
info->flags & IPRANGE_DST_INV ? " !=" : "",
xtables_ipaddr_to_numeric(&info->dst_min.in));
xt_xlate_add(xl, "-%s",
@@ -365,7 +361,6 @@ static int iprange_mt6_xlate(struct xt_xlate *xl,
{
const struct xt_iprange_mtinfo *info =
(const void *)params->match->data;
- char *space = "";
if (info->flags & IPRANGE_SRC) {
xt_xlate_add(xl, "ip6 saddr%s %s",
@@ -373,10 +368,9 @@ static int iprange_mt6_xlate(struct xt_xlate *xl,
xtables_ip6addr_to_numeric(&info->src_min.in6));
xt_xlate_add(xl, "-%s",
xtables_ip6addr_to_numeric(&info->src_max.in6));
- space = " ";
}
if (info->flags & IPRANGE_DST) {
- xt_xlate_add(xl, "%sip6 daddr%s %s", space,
+ xt_xlate_add(xl, "ip6 daddr%s %s",
info->flags & IPRANGE_DST_INV ? " !=" : "",
xtables_ip6addr_to_numeric(&info->dst_min.in6));
xt_xlate_add(xl, "-%s",
diff --git a/extensions/libxt_iprange.txlate b/extensions/libxt_iprange.txlate
index 999f4b72..80369650 100644
--- a/extensions/libxt_iprange.txlate
+++ b/extensions/libxt_iprange.txlate
@@ -1,14 +1,14 @@
iptables-translate -A INPUT -m iprange --src-range 192.168.25.149-192.168.25.151 -j ACCEPT
-nft add rule ip filter INPUT ip saddr 192.168.25.149-192.168.25.151 counter accept
+nft 'add rule ip filter INPUT ip saddr 192.168.25.149-192.168.25.151 counter accept'
iptables-translate -A INPUT -m iprange --dst-range 192.168.25.149-192.168.25.151 -j ACCEPT
-nft add rule ip filter INPUT ip daddr 192.168.25.149-192.168.25.151 counter accept
+nft 'add rule ip filter INPUT ip daddr 192.168.25.149-192.168.25.151 counter accept'
iptables-translate -A INPUT -m iprange --dst-range 3.3.3.3-6.6.6.6 --src-range 4.4.4.4-7.7.7.7 -j ACCEPT
-nft add rule ip filter INPUT ip saddr 4.4.4.4-7.7.7.7 ip daddr 3.3.3.3-6.6.6.6 counter accept
+nft 'add rule ip filter INPUT ip saddr 4.4.4.4-7.7.7.7 ip daddr 3.3.3.3-6.6.6.6 counter accept'
ip6tables-translate -A INPUT -m iprange ! --dst-range ::2d01-::2d03 -j ACCEPT
-nft add rule ip6 filter INPUT ip6 daddr != ::2d01-::2d03 counter accept
+nft 'add rule ip6 filter INPUT ip6 daddr != ::2d01-::2d03 counter accept'
ip6tables-translate -A INPUT -m iprange ! --dst-range ::2d01-::2d03 --src-range ::2d01-::2d03 -j ACCEPT
-nft add rule ip6 filter INPUT ip6 saddr ::2d01-::2d03 ip6 daddr != ::2d01-::2d03 counter accept
+nft 'add rule ip6 filter INPUT ip6 saddr ::2d01-::2d03 ip6 daddr != ::2d01-::2d03 counter accept'
diff --git a/extensions/libxt_length.t b/extensions/libxt_length.t
index 0b6624ee..8b70fc31 100644
--- a/extensions/libxt_length.t
+++ b/extensions/libxt_length.t
@@ -2,7 +2,7 @@
-m length --length 1;=;OK
-m length --length :2;-m length --length 0:2;OK
-m length --length 0:3;=;OK
--m length --length 4:;=;OK
+-m length --length 4:;-m length --length 4:65535;OK
-m length --length 0:65535;=;OK
-m length ! --length 0:65535;=;OK
-m length --length 0:65536;;FAIL
diff --git a/extensions/libxt_length.txlate b/extensions/libxt_length.txlate
index e777c265..38f835dc 100644
--- a/extensions/libxt_length.txlate
+++ b/extensions/libxt_length.txlate
@@ -1,11 +1,11 @@
iptables-translate -A INPUT -p icmp -m length --length 86:0xffff -j DROP
-nft add rule ip filter INPUT ip protocol icmp meta length 86-65535 counter drop
+nft 'add rule ip filter INPUT ip protocol icmp meta length 86-65535 counter drop'
iptables-translate -A INPUT -p udp -m length --length :400
-nft add rule ip filter INPUT ip protocol udp meta length 0-400 counter
+nft 'add rule ip filter INPUT ip protocol udp meta length 0-400 counter'
iptables-translate -A INPUT -p udp -m length --length 40
-nft add rule ip filter INPUT ip protocol udp meta length 40 counter
+nft 'add rule ip filter INPUT ip protocol udp meta length 40 counter'
iptables-translate -A INPUT -p udp -m length ! --length 40
-nft add rule ip filter INPUT ip protocol udp meta length != 40 counter
+nft 'add rule ip filter INPUT ip protocol udp meta length != 40 counter'
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index 1b324657..e6ec67f3 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -77,7 +77,7 @@ int parse_rate(const char *rate, uint32_t *val)
* The rate maps to infinity. (1/day is the minimum they can
* specify, so we are ok at that end).
*/
- xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
+ xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"", rate);
return 1;
}
@@ -93,7 +93,7 @@ static void limit_init(struct xt_entry_match *m)
/* FIXME: handle overflow:
if (r->avg*r->burst/r->burst != r->avg)
xtables_error(PARAMETER_PROBLEM,
- "Sorry: burst too large for that avg rate.\n");
+ "Sorry: burst too large for that avg rate.");
*/
static void limit_parse(struct xt_option_call *cb)
diff --git a/extensions/libxt_limit.txlate b/extensions/libxt_limit.txlate
index df9ed2d5..fa8e1bc0 100644
--- a/extensions/libxt_limit.txlate
+++ b/extensions/libxt_limit.txlate
@@ -1,8 +1,8 @@
iptables-translate -A INPUT -m limit --limit 3/m --limit-burst 3
-nft add rule ip filter INPUT limit rate 3/minute burst 3 packets counter
+nft 'add rule ip filter INPUT limit rate 3/minute burst 3 packets counter'
iptables-translate -A INPUT -m limit --limit 10/s --limit-burst 5
-nft add rule ip filter INPUT limit rate 10/second burst 5 packets counter
+nft 'add rule ip filter INPUT limit rate 10/second burst 5 packets counter'
iptables-translate -A INPUT -m limit --limit 10/s --limit-burst 0
-nft add rule ip filter INPUT limit rate 10/second counter
+nft 'add rule ip filter INPUT limit rate 10/second counter'
diff --git a/extensions/libxt_mac.txlate b/extensions/libxt_mac.txlate
index 08696f3d..16800179 100644
--- a/extensions/libxt_mac.txlate
+++ b/extensions/libxt_mac.txlate
@@ -1,5 +1,5 @@
iptables-translate -A INPUT -m mac --mac-source 0a:12:3e:4f:b2:c6 -j DROP
-nft add rule ip filter INPUT ether saddr 0a:12:3e:4f:b2:c6 counter drop
+nft 'add rule ip filter INPUT ether saddr 0a:12:3e:4f:b2:c6 counter drop'
iptables-translate -A INPUT -p tcp --dport 80 -m mac --mac-source 0a:12:3e:4f:b2:c6 -j ACCEPT
-nft add rule ip filter INPUT tcp dport 80 ether saddr 0a:12:3e:4f:b2:c6 counter accept
+nft 'add rule ip filter INPUT tcp dport 80 ether saddr 0a:12:3e:4f:b2:c6 counter accept'
diff --git a/extensions/libxt_mark.t b/extensions/libxt_mark.t
index 7c005379..12c05865 100644
--- a/extensions/libxt_mark.t
+++ b/extensions/libxt_mark.t
@@ -1,7 +1,8 @@
:INPUT,FORWARD,OUTPUT
-m mark --mark 0xfeedcafe/0xfeedcafe;=;OK
--m mark --mark 0;=;OK
+-m mark --mark 0x0;=;OK
-m mark --mark 4294967295;-m mark --mark 0xffffffff;OK
-m mark --mark 4294967296;;FAIL
-m mark --mark -1;;FAIL
-m mark;;FAIL
+-s 1.2.0.0/15 -m mark --mark 0x0/0xff0;=;OK
diff --git a/extensions/libxt_mark.txlate b/extensions/libxt_mark.txlate
index 6bfb5243..6e097091 100644
--- a/extensions/libxt_mark.txlate
+++ b/extensions/libxt_mark.txlate
@@ -1,5 +1,5 @@
iptables-translate -I INPUT -p tcp -m mark ! --mark 0xa/0xa
-nft insert rule ip filter INPUT ip protocol tcp mark and 0xa != 0xa counter
+nft 'insert rule ip filter INPUT ip protocol tcp mark and 0xa != 0xa counter'
iptables-translate -I INPUT -p tcp -m mark ! --mark 0x1
-nft insert rule ip filter INPUT ip protocol tcp mark != 0x1 counter
+nft 'insert rule ip filter INPUT ip protocol tcp mark != 0x1 counter'
diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c
index 6b0c8190..f3136d8a 100644
--- a/extensions/libxt_multiport.c
+++ b/extensions/libxt_multiport.c
@@ -497,7 +497,7 @@ static int __multiport_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, "{ ");
for (i = 0; i < multiinfo->count; i++)
- xt_xlate_add(xl, "%s%u", i ? "," : "", multiinfo->ports[i]);
+ xt_xlate_add(xl, "%s%u", i ? ", " : "", multiinfo->ports[i]);
if (multiinfo->count > 1)
xt_xlate_add(xl, "}");
@@ -560,7 +560,7 @@ static int __multiport_xlate_v1(struct xt_xlate *xl,
xt_xlate_add(xl, "{ ");
for (i = 0; i < multiinfo->count; i++) {
- xt_xlate_add(xl, "%s%u", i ? "," : "", multiinfo->ports[i]);
+ xt_xlate_add(xl, "%s%u", i ? ", " : "", multiinfo->ports[i]);
if (multiinfo->pflags[i])
xt_xlate_add(xl, "-%u", multiinfo->ports[++i]);
}
diff --git a/extensions/libxt_multiport.txlate b/extensions/libxt_multiport.txlate
index bced1b84..aa5f006d 100644
--- a/extensions/libxt_multiport.txlate
+++ b/extensions/libxt_multiport.txlate
@@ -1,14 +1,14 @@
iptables-translate -t filter -A INPUT -p tcp -m multiport --dports 80,81 -j ACCEPT
-nft add rule ip filter INPUT ip protocol tcp tcp dport { 80,81} counter accept
+nft 'add rule ip filter INPUT ip protocol tcp tcp dport { 80, 81 } counter accept'
iptables-translate -t filter -A INPUT -p tcp -m multiport --dports 80:88 -j ACCEPT
-nft add rule ip filter INPUT ip protocol tcp tcp dport 80-88 counter accept
+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 ! --dports 80:88 -j ACCEPT
-nft add rule ip filter INPUT ip protocol tcp tcp dport != 80-88 counter accept
+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
+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
+nft 'insert rule ip filter INPUT ip protocol tcp tcp sport . tcp dport { 0-65535 . 10, 10 . 0-65535 } counter'
diff --git a/extensions/libxt_owner.txlate b/extensions/libxt_owner.txlate
index 86fb0585..8fbd68eb 100644
--- a/extensions/libxt_owner.txlate
+++ b/extensions/libxt_owner.txlate
@@ -1,8 +1,8 @@
iptables-translate -t nat -A OUTPUT -p tcp --dport 80 -m owner --uid-owner root -j ACCEPT
-nft add rule ip nat OUTPUT tcp dport 80 skuid 0 counter accept
+nft 'add rule ip nat OUTPUT tcp dport 80 skuid 0 counter accept'
iptables-translate -t nat -A OUTPUT -p tcp --dport 80 -m owner --gid-owner 0-10 -j ACCEPT
-nft add rule ip nat OUTPUT tcp dport 80 skgid 0-10 counter accept
+nft 'add rule ip nat OUTPUT tcp dport 80 skgid 0-10 counter accept'
iptables-translate -t nat -A OUTPUT -p tcp --dport 80 -m owner ! --uid-owner 1000 -j ACCEPT
-nft add rule ip nat OUTPUT tcp dport 80 skuid != 1000 counter accept
+nft 'add rule ip nat OUTPUT tcp dport 80 skuid != 1000 counter accept'
diff --git a/extensions/libxt_pkttype.c b/extensions/libxt_pkttype.c
index bf6f5b96..a76310b0 100644
--- a/extensions/libxt_pkttype.c
+++ b/extensions/libxt_pkttype.c
@@ -30,8 +30,8 @@ static const struct pkttypes supported_types[] = {
{"unicast", PACKET_HOST, 1, "to us"},
{"broadcast", PACKET_BROADCAST, 1, "to all"},
{"multicast", PACKET_MULTICAST, 1, "to group"},
-/*
{"otherhost", PACKET_OTHERHOST, 1, "to someone else"},
+/*
{"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"},
*/
/* aliases */
diff --git a/extensions/libxt_pkttype.txlate b/extensions/libxt_pkttype.txlate
index 6506a380..c69f56f9 100644
--- a/extensions/libxt_pkttype.txlate
+++ b/extensions/libxt_pkttype.txlate
@@ -1,8 +1,8 @@
iptables-translate -A INPUT -m pkttype --pkt-type broadcast -j DROP
-nft add rule ip filter INPUT pkttype broadcast counter drop
+nft 'add rule ip filter INPUT pkttype broadcast counter drop'
iptables-translate -A INPUT -m pkttype ! --pkt-type unicast -j DROP
-nft add rule ip filter INPUT pkttype != unicast counter drop
+nft 'add rule ip filter INPUT pkttype != unicast counter drop'
iptables-translate -A INPUT -m pkttype --pkt-type multicast -j ACCEPT
-nft add rule ip filter INPUT pkttype multicast counter accept
+nft 'add rule ip filter INPUT pkttype multicast counter accept'
diff --git a/extensions/libxt_policy.txlate b/extensions/libxt_policy.txlate
index 66788a76..a960b395 100644
--- a/extensions/libxt_policy.txlate
+++ b/extensions/libxt_policy.txlate
@@ -1,5 +1,5 @@
iptables-translate -A INPUT -m policy --pol ipsec --dir in
-nft add rule ip filter INPUT meta secpath exists counter
+nft 'add rule ip filter INPUT meta secpath exists counter'
iptables-translate -A INPUT -m policy --pol none --dir in
-nft add rule ip filter INPUT meta secpath missing counter
+nft 'add rule ip filter INPUT meta secpath missing counter'
diff --git a/extensions/libxt_quota.txlate b/extensions/libxt_quota.txlate
index 91142141..6edd925d 100644
--- a/extensions/libxt_quota.txlate
+++ b/extensions/libxt_quota.txlate
@@ -1,5 +1,5 @@
iptables-translate -A OUTPUT -m quota --quota 111
-nft add rule ip filter OUTPUT quota 111 bytes counter
+nft 'add rule ip filter OUTPUT quota 111 bytes counter'
iptables-translate -A OUTPUT -m quota ! --quota 111
-nft add rule ip filter OUTPUT quota over 111 bytes counter
+nft 'add rule ip filter OUTPUT quota over 111 bytes counter'
diff --git a/extensions/libxt_recent.t b/extensions/libxt_recent.t
index 9a83918e..cf23aabc 100644
--- a/extensions/libxt_recent.t
+++ b/extensions/libxt_recent.t
@@ -1,8 +1,8 @@
:INPUT,FORWARD,OUTPUT
--m recent --set;=;OK
+-m recent --set;-m recent --set --name DEFAULT --mask 255.255.255.255 --rsource;OK
-m recent --rcheck --hitcount 8 --name foo --mask 255.255.255.255 --rsource;=;OK
-m recent --rcheck --hitcount 12 --name foo --mask 255.255.255.255 --rsource;=;OK
--m recent --update --rttl;=;OK
+-m recent --update --rttl;-m recent --update --rttl --name DEFAULT --mask 255.255.255.255 --rsource;OK
-m recent --set --rttl;;FAIL
-m recent --rcheck --hitcount 999 --name foo --mask 255.255.255.255 --rsource;;FAIL
# nonsensical, but all should load successfully:
diff --git a/extensions/libxt_rpfilter.txlate b/extensions/libxt_rpfilter.txlate
index 8d7733ba..a551c419 100644
--- a/extensions/libxt_rpfilter.txlate
+++ b/extensions/libxt_rpfilter.txlate
@@ -1,8 +1,8 @@
iptables-translate -t mangle -A PREROUTING -m rpfilter
-nft add rule ip mangle PREROUTING fib saddr . iif oif != 0 counter
+nft 'add rule ip mangle PREROUTING fib saddr . iif oif != 0 counter'
iptables-translate -t mangle -A PREROUTING -m rpfilter --validmark --loose
-nft add rule ip mangle PREROUTING fib saddr . mark oif != 0 counter
+nft 'add rule ip mangle PREROUTING fib saddr . mark oif != 0 counter'
ip6tables-translate -t mangle -A PREROUTING -m rpfilter --validmark --invert
-nft add rule ip6 mangle PREROUTING fib saddr . mark . iif oif 0 counter
+nft 'add rule ip6 mangle PREROUTING fib saddr . mark . iif oif 0 counter'
diff --git a/extensions/libxt_sctp.c b/extensions/libxt_sctp.c
index 3fb6cf1a..fe5f5621 100644
--- a/extensions/libxt_sctp.c
+++ b/extensions/libxt_sctp.c
@@ -144,10 +144,8 @@ save_chunk_flag_info(struct xt_sctp_flag_info *flag_info,
}
if (*flag_count == XT_NUM_SCTP_FLAGS) {
- xtables_error (PARAMETER_PROBLEM,
- "Number of chunk types with flags exceeds currently allowed limit."
- "Increasing this limit involves changing IPT_NUM_SCTP_FLAGS and"
- "recompiling both the kernel space and user space modules\n");
+ xtables_error(PARAMETER_PROBLEM,
+ "Number of chunk types with flags exceeds currently allowed limit. Increasing this limit involves changing IPT_NUM_SCTP_FLAGS and recompiling both the kernel space and user space modules");
}
flag_info[*flag_count].chunktype = chunktype;
@@ -219,7 +217,8 @@ parse_sctp_chunk(struct xt_sctp_info *einfo,
isupper(chunk_flags[j]));
} else {
xtables_error(PARAMETER_PROBLEM,
- "Invalid flags for chunk type %d\n", i);
+ "Invalid flags for chunk type %d",
+ i);
}
}
}
@@ -490,24 +489,24 @@ static void sctp_save(const void *ip, const struct xt_entry_match *match)
}
}
-static const char *sctp_xlate_chunk(struct xt_xlate *xl, const char *space,
- const struct xt_sctp_info *einfo,
- const struct sctp_chunk_names *scn)
+static void sctp_xlate_chunk(struct xt_xlate *xl,
+ const struct xt_sctp_info *einfo,
+ const struct sctp_chunk_names *scn)
{
bool inv = einfo->invflags & XT_SCTP_CHUNK_TYPES;
const struct xt_sctp_flag_info *flag_info = NULL;
int i;
if (!scn->nftname)
- return space;
+ return;
if (!SCTP_CHUNKMAP_IS_SET(einfo->chunkmap, scn->chunk_type)) {
if (einfo->chunk_match_type != SCTP_CHUNK_MATCH_ONLY)
- return space;
+ return;
- xt_xlate_add(xl, "%ssctp chunk %s %s", space,
+ xt_xlate_add(xl, "sctp chunk %s %s",
scn->nftname, inv ? "exists" : "missing");
- return " ";
+ return;
}
for (i = 0; i < einfo->flag_count; i++) {
@@ -518,16 +517,14 @@ static const char *sctp_xlate_chunk(struct xt_xlate *xl, const char *space,
}
if (!flag_info) {
- xt_xlate_add(xl, "%ssctp chunk %s %s", space,
+ xt_xlate_add(xl, "sctp chunk %s %s",
scn->nftname, inv ? "missing" : "exists");
- return " ";
+ return;
}
- xt_xlate_add(xl, "%ssctp chunk %s flags & 0x%x %s 0x%x", space,
+ xt_xlate_add(xl, "sctp chunk %s flags & 0x%x %s 0x%x",
scn->nftname, flag_info->flag_mask,
inv ? "!=" : "==", flag_info->flag);
-
- return " ";
}
static int sctp_xlate(struct xt_xlate *xl,
@@ -535,7 +532,6 @@ static int sctp_xlate(struct xt_xlate *xl,
{
const struct xt_sctp_info *einfo =
(const struct xt_sctp_info *)params->match->data;
- const char *space = "";
if (!einfo->flags)
return 0;
@@ -549,19 +545,17 @@ static int sctp_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, "sctp sport%s %u",
einfo->invflags & XT_SCTP_SRC_PORTS ? " !=" : "",
einfo->spts[0]);
- space = " ";
}
if (einfo->flags & XT_SCTP_DEST_PORTS) {
if (einfo->dpts[0] != einfo->dpts[1])
- xt_xlate_add(xl, "%ssctp dport%s %u-%u", space,
+ xt_xlate_add(xl, "sctp dport%s %u-%u",
einfo->invflags & XT_SCTP_DEST_PORTS ? " !=" : "",
einfo->dpts[0], einfo->dpts[1]);
else
- xt_xlate_add(xl, "%ssctp dport%s %u", space,
+ xt_xlate_add(xl, "sctp dport%s %u",
einfo->invflags & XT_SCTP_DEST_PORTS ? " !=" : "",
einfo->dpts[0]);
- space = " ";
}
if (einfo->flags & XT_SCTP_CHUNK_TYPES) {
@@ -571,8 +565,7 @@ static int sctp_xlate(struct xt_xlate *xl,
return 0;
for (i = 0; i < ARRAY_SIZE(sctp_chunk_names); i++)
- space = sctp_xlate_chunk(xl, space, einfo,
- &sctp_chunk_names[i]);
+ sctp_xlate_chunk(xl, einfo, &sctp_chunk_names[i]);
}
return 1;
diff --git a/extensions/libxt_sctp.txlate b/extensions/libxt_sctp.txlate
index 6443abf9..0aa7371d 100644
--- a/extensions/libxt_sctp.txlate
+++ b/extensions/libxt_sctp.txlate
@@ -1,44 +1,44 @@
iptables-translate -A INPUT -p sctp --dport 80 -j DROP
-nft add rule ip filter INPUT sctp dport 80 counter drop
+nft 'add rule ip filter INPUT sctp dport 80 counter drop'
iptables-translate -A INPUT -p sctp --sport 50 -j DROP
-nft add rule ip filter INPUT sctp sport 50 counter drop
+nft 'add rule ip filter INPUT sctp sport 50 counter drop'
iptables-translate -A INPUT -p sctp ! --dport 80 -j DROP
-nft add rule ip filter INPUT sctp dport != 80 counter drop
+nft 'add rule ip filter INPUT sctp dport != 80 counter drop'
iptables-translate -A INPUT -p sctp ! --sport 50 -j DROP
-nft add rule ip filter INPUT sctp sport != 50 counter drop
+nft 'add rule ip filter INPUT sctp sport != 50 counter drop'
iptables-translate -A INPUT -p sctp --sport 80:100 -j ACCEPT
-nft add rule ip filter INPUT sctp sport 80-100 counter accept
+nft 'add rule ip filter INPUT sctp sport 80-100 counter accept'
iptables-translate -A INPUT -p sctp --dport 50:56 -j ACCEPT
-nft add rule ip filter INPUT sctp dport 50-56 counter accept
+nft 'add rule ip filter INPUT sctp dport 50-56 counter accept'
iptables-translate -A INPUT -p sctp ! --sport 80:100 -j ACCEPT
-nft add rule ip filter INPUT sctp sport != 80-100 counter accept
+nft 'add rule ip filter INPUT sctp sport != 80-100 counter accept'
iptables-translate -A INPUT -p sctp ! --dport 50:56 -j ACCEPT
-nft add rule ip filter INPUT sctp dport != 50-56 counter accept
+nft 'add rule ip filter INPUT sctp dport != 50-56 counter accept'
iptables-translate -A INPUT -p sctp --dport 80 --sport 50 -j ACCEPT
-nft add rule ip filter INPUT sctp sport 50 sctp dport 80 counter accept
+nft 'add rule ip filter INPUT sctp sport 50 sctp dport 80 counter accept'
iptables-translate -A INPUT -p sctp --dport 80:100 --sport 50 -j ACCEPT
-nft add rule ip filter INPUT sctp sport 50 sctp dport 80-100 counter accept
+nft 'add rule ip filter INPUT sctp sport 50 sctp dport 80-100 counter accept'
iptables-translate -A INPUT -p sctp --dport 80 --sport 50:55 -j ACCEPT
-nft add rule ip filter INPUT sctp sport 50-55 sctp dport 80 counter accept
+nft 'add rule ip filter INPUT sctp sport 50-55 sctp dport 80 counter accept'
iptables-translate -A INPUT -p sctp ! --dport 80:100 --sport 50 -j ACCEPT
-nft add rule ip filter INPUT sctp sport 50 sctp dport != 80-100 counter accept
+nft 'add rule ip filter INPUT sctp sport 50 sctp dport != 80-100 counter accept'
iptables-translate -A INPUT -p sctp --dport 80 ! --sport 50:55 -j ACCEPT
-nft add rule ip filter INPUT sctp sport != 50-55 sctp dport 80 counter accept
+nft 'add rule ip filter INPUT sctp sport != 50-55 sctp dport 80 counter accept'
iptables-translate -A INPUT -p sctp --chunk-types all INIT,DATA:iUbE,SACK,ABORT:T -j ACCEPT
-nft add rule ip filter INPUT sctp chunk data flags & 0xf == 0x5 sctp chunk init exists sctp chunk sack exists sctp chunk abort flags & 0x1 == 0x1 counter accept
+nft 'add rule ip filter INPUT sctp chunk data flags & 0xf == 0x5 sctp chunk init exists sctp chunk sack exists sctp chunk abort flags & 0x1 == 0x1 counter accept'
iptables-translate -A INPUT -p sctp --chunk-types only SHUTDOWN_COMPLETE -j ACCEPT
-nft add rule ip filter INPUT sctp chunk data missing sctp chunk init missing sctp chunk init-ack missing sctp chunk sack missing sctp chunk heartbeat missing sctp chunk heartbeat-ack missing sctp chunk abort missing sctp chunk shutdown missing sctp chunk shutdown-ack missing sctp chunk error missing sctp chunk cookie-echo missing sctp chunk cookie-ack missing sctp chunk ecne missing sctp chunk cwr missing sctp chunk shutdown-complete exists sctp chunk i-data missing sctp chunk re-config missing sctp chunk pad missing sctp chunk asconf missing sctp chunk asconf-ack missing sctp chunk forward-tsn missing sctp chunk i-forward-tsn missing counter accept
+nft 'add rule ip filter INPUT sctp chunk data missing sctp chunk init missing sctp chunk init-ack missing sctp chunk sack missing sctp chunk heartbeat missing sctp chunk heartbeat-ack missing sctp chunk abort missing sctp chunk shutdown missing sctp chunk shutdown-ack missing sctp chunk error missing sctp chunk cookie-echo missing sctp chunk cookie-ack missing sctp chunk ecne missing sctp chunk cwr missing sctp chunk shutdown-complete exists sctp chunk i-data missing sctp chunk re-config missing sctp chunk pad missing sctp chunk asconf missing sctp chunk asconf-ack missing sctp chunk forward-tsn missing sctp chunk i-forward-tsn missing counter accept'
diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c
index a2137ab1..471bde8a 100644
--- a/extensions/libxt_set.c
+++ b/extensions/libxt_set.c
@@ -334,8 +334,7 @@ parse_counter(const char *opt)
if (!xtables_strtoul(opt, NULL, &value, 0, UINT64_MAX))
xtables_error(PARAMETER_PROBLEM,
- "Cannot parse %s as a counter value\n",
- opt);
+ "Cannot parse %s as a counter value", opt);
return (uint64_t)value;
}
@@ -354,60 +353,54 @@ set_parse_v3(int c, char **argv, int invert, unsigned int *flags,
case '0':
if (info->bytes.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --bytes-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --bytes-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--bytes-gt option cannot be inverted\n");
+ "--bytes-gt option cannot be inverted");
info->bytes.op = IPSET_COUNTER_GT;
info->bytes.value = parse_counter(optarg);
break;
case '9':
if (info->bytes.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --bytes-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --bytes-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--bytes-lt option cannot be inverted\n");
+ "--bytes-lt option cannot be inverted");
info->bytes.op = IPSET_COUNTER_LT;
info->bytes.value = parse_counter(optarg);
break;
case '8':
if (info->bytes.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --bytes-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --bytes-[eq|lt|gt] is allowed");
info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ;
info->bytes.value = parse_counter(optarg);
break;
case '7':
if (info->packets.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --packets-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --packets-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--packets-gt option cannot be inverted\n");
+ "--packets-gt option cannot be inverted");
info->packets.op = IPSET_COUNTER_GT;
info->packets.value = parse_counter(optarg);
break;
case '6':
if (info->packets.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --packets-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --packets-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--packets-lt option cannot be inverted\n");
+ "--packets-lt option cannot be inverted");
info->packets.op = IPSET_COUNTER_LT;
info->packets.value = parse_counter(optarg);
break;
case '5':
if (info->packets.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --packets-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --packets-[eq|lt|gt] is allowed");
info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ;
info->packets.value = parse_counter(optarg);
break;
@@ -418,7 +411,7 @@ set_parse_v3(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--return-nomatch flag cannot be inverted\n");
+ "--return-nomatch flag cannot be inverted");
info->flags |= IPSET_FLAG_RETURN_NOMATCH;
break;
case '2':
@@ -523,60 +516,54 @@ set_parse_v4(int c, char **argv, int invert, unsigned int *flags,
case '0':
if (info->bytes.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --bytes-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --bytes-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--bytes-gt option cannot be inverted\n");
+ "--bytes-gt option cannot be inverted");
info->bytes.op = IPSET_COUNTER_GT;
info->bytes.value = parse_counter(optarg);
break;
case '9':
if (info->bytes.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --bytes-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --bytes-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--bytes-lt option cannot be inverted\n");
+ "--bytes-lt option cannot be inverted");
info->bytes.op = IPSET_COUNTER_LT;
info->bytes.value = parse_counter(optarg);
break;
case '8':
if (info->bytes.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --bytes-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --bytes-[eq|lt|gt] is allowed");
info->bytes.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ;
info->bytes.value = parse_counter(optarg);
break;
case '7':
if (info->packets.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --packets-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --packets-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--packets-gt option cannot be inverted\n");
+ "--packets-gt option cannot be inverted");
info->packets.op = IPSET_COUNTER_GT;
info->packets.value = parse_counter(optarg);
break;
case '6':
if (info->packets.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --packets-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --packets-[eq|lt|gt] is allowed");
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--packets-lt option cannot be inverted\n");
+ "--packets-lt option cannot be inverted");
info->packets.op = IPSET_COUNTER_LT;
info->packets.value = parse_counter(optarg);
break;
case '5':
if (info->packets.op != IPSET_COUNTER_NONE)
xtables_error(PARAMETER_PROBLEM,
- "only one of the --packets-[eq|lt|gt]"
- " is allowed\n");
+ "only one of the --packets-[eq|lt|gt] is allowed");
info->packets.op = invert ? IPSET_COUNTER_NE : IPSET_COUNTER_EQ;
info->packets.value = parse_counter(optarg);
break;
@@ -587,7 +574,7 @@ set_parse_v4(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (invert)
xtables_error(PARAMETER_PROBLEM,
- "--return-nomatch flag cannot be inverted\n");
+ "--return-nomatch flag cannot be inverted");
info->flags |= IPSET_FLAG_RETURN_NOMATCH;
break;
case '2':
diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c
index 4f3341a3..37915adc 100644
--- a/extensions/libxt_statistic.c
+++ b/extensions/libxt_statistic.c
@@ -141,13 +141,19 @@ static int statistic_xlate(struct xt_xlate *xl,
switch (info->mode) {
case XT_STATISTIC_MODE_RANDOM:
- return 0;
+ xt_xlate_add(xl, "meta random & %u %s %u",
+ INT_MAX,
+ info->flags & XT_STATISTIC_INVERT ? ">=" : "<",
+ info->u.random.probability);
+ break;
case XT_STATISTIC_MODE_NTH:
xt_xlate_add(xl, "numgen inc mod %u %s%u",
info->u.nth.every + 1,
info->flags & XT_STATISTIC_INVERT ? "!= " : "",
info->u.nth.packet);
break;
+ default:
+ return 0;
}
return 1;
diff --git a/extensions/libxt_statistic.txlate b/extensions/libxt_statistic.txlate
index 4c3dea43..627120c5 100644
--- a/extensions/libxt_statistic.txlate
+++ b/extensions/libxt_statistic.txlate
@@ -1,8 +1,8 @@
iptables-translate -A OUTPUT -m statistic --mode nth --every 10 --packet 1
-nft add rule ip filter OUTPUT numgen inc mod 10 1 counter
+nft 'add rule ip filter OUTPUT numgen inc mod 10 1 counter'
iptables-translate -A OUTPUT -m statistic --mode nth ! --every 10 --packet 5
-nft add rule ip filter OUTPUT numgen inc mod 10 != 5 counter
+nft 'add rule ip filter OUTPUT numgen inc mod 10 != 5 counter'
iptables-translate -A OUTPUT -m statistic --mode random --probability 0.1
-nft # -A OUTPUT -m statistic --mode random --probability 0.1
+nft 'add rule ip filter OUTPUT meta random & 2147483647 < 214748365 counter'
diff --git a/extensions/libxt_tcp.c b/extensions/libxt_tcp.c
index 0b115cdd..f8257282 100644
--- a/extensions/libxt_tcp.c
+++ b/extensions/libxt_tcp.c
@@ -380,10 +380,9 @@ static void print_tcp_xlate(struct xt_xlate *xl, uint8_t flags)
for (i = 0; (flags & tcp_flag_names_xlate[i].flag) == 0; i++);
- if (have_flag)
- xt_xlate_add(xl, ",");
-
- xt_xlate_add(xl, "%s", tcp_flag_names_xlate[i].name);
+ xt_xlate_add(xl, "%s%s",
+ have_flag ? "," : "",
+ tcp_flag_names_xlate[i].name);
have_flag = 1;
flags &= ~tcp_flag_names_xlate[i].flag;
@@ -398,7 +397,6 @@ static int tcp_xlate(struct xt_xlate *xl,
{
const struct xt_tcp *tcpinfo =
(const struct xt_tcp *)params->match->data;
- char *space= "";
if (tcpinfo->spts[0] != 0 || tcpinfo->spts[1] != 0xffff) {
if (tcpinfo->spts[0] != tcpinfo->spts[1]) {
@@ -412,30 +410,29 @@ static int tcp_xlate(struct xt_xlate *xl,
"!= " : "",
tcpinfo->spts[0]);
}
- space = " ";
}
if (tcpinfo->dpts[0] != 0 || tcpinfo->dpts[1] != 0xffff) {
if (tcpinfo->dpts[0] != tcpinfo->dpts[1]) {
- xt_xlate_add(xl, "%stcp dport %s%u-%u", space,
+ xt_xlate_add(xl, "tcp dport %s%u-%u",
tcpinfo->invflags & XT_TCP_INV_DSTPT ?
"!= " : "",
tcpinfo->dpts[0], tcpinfo->dpts[1]);
} else {
- xt_xlate_add(xl, "%stcp dport %s%u", space,
+ xt_xlate_add(xl, "tcp dport %s%u",
tcpinfo->invflags & XT_TCP_INV_DSTPT ?
"!= " : "",
tcpinfo->dpts[0]);
}
- space = " ";
}
- /* XXX not yet implemented */
- if (tcpinfo->option || (tcpinfo->invflags & XT_TCP_INV_OPTION))
- return 0;
+ if (tcpinfo->option)
+ xt_xlate_add(xl, "tcp option %u %s", tcpinfo->option,
+ tcpinfo->invflags & XT_TCP_INV_OPTION ?
+ "missing" : "exists");
if (tcpinfo->flg_mask || (tcpinfo->invflags & XT_TCP_INV_FLAGS)) {
- xt_xlate_add(xl, "%stcp flags %s", space,
+ xt_xlate_add(xl, "tcp flags %s",
tcpinfo->invflags & XT_TCP_INV_FLAGS ? "!= ": "");
print_tcp_xlate(xl, tcpinfo->flg_cmp);
xt_xlate_add(xl, " / ");
diff --git a/extensions/libxt_tcp.txlate b/extensions/libxt_tcp.txlate
index 921d4af0..9802ddfe 100644
--- a/extensions/libxt_tcp.txlate
+++ b/extensions/libxt_tcp.txlate
@@ -1,26 +1,32 @@
iptables-translate -A INPUT -p tcp -i eth0 --sport 53 -j ACCEPT
-nft add rule ip filter INPUT iifname "eth0" tcp sport 53 counter accept
+nft 'add rule ip filter INPUT iifname "eth0" tcp sport 53 counter accept'
iptables-translate -A OUTPUT -p tcp -o eth0 --dport 53:66 -j DROP
-nft add rule ip filter OUTPUT oifname "eth0" tcp dport 53-66 counter drop
+nft 'add rule ip filter OUTPUT oifname "eth0" tcp dport 53-66 counter drop'
iptables-translate -I OUTPUT -p tcp -d 8.8.8.8 -j ACCEPT
-nft insert rule ip filter OUTPUT ip protocol tcp ip daddr 8.8.8.8 counter accept
+nft 'insert rule ip filter OUTPUT ip protocol tcp ip daddr 8.8.8.8 counter accept'
iptables-translate -I OUTPUT -p tcp --dport 1020:1023 --sport 53 -j ACCEPT
-nft insert rule ip filter OUTPUT tcp sport 53 tcp dport 1020-1023 counter accept
+nft 'insert rule ip filter OUTPUT tcp sport 53 tcp dport 1020-1023 counter accept'
iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
-nft add rule ip filter INPUT tcp flags fin / fin,ack counter drop
+nft 'add rule ip filter INPUT tcp flags fin / fin,ack counter drop'
iptables-translate -A INPUT -p tcp --syn -j ACCEPT
-nft add rule ip filter INPUT tcp flags syn / fin,syn,rst,ack counter accept
+nft 'add rule ip filter INPUT tcp flags syn / fin,syn,rst,ack counter accept'
iptables-translate -A INPUT -p tcp --syn --dport 80 -j ACCEPT
-nft add rule ip filter INPUT tcp dport 80 tcp flags syn / fin,syn,rst,ack counter accept
+nft 'add rule ip filter INPUT tcp dport 80 tcp flags syn / fin,syn,rst,ack counter accept'
iptables-translate -A INPUT -f -p tcp
-nft add rule ip filter INPUT ip frag-off & 0x1fff != 0 ip protocol tcp counter
+nft 'add rule ip filter INPUT ip frag-off & 0x1fff != 0 ip protocol tcp counter'
iptables-translate -A INPUT ! -f -p tcp --dport 22
-nft add rule ip filter INPUT ip frag-off & 0x1fff 0 tcp dport 22 counter
+nft 'add rule ip filter INPUT ip frag-off & 0x1fff 0 tcp dport 22 counter'
+
+iptables-translate -A INPUT -p tcp --tcp-option 23
+nft 'add rule ip filter INPUT tcp option 23 exists counter'
+
+iptables-translate -A INPUT -p tcp ! --tcp-option 23
+nft 'add rule ip filter INPUT tcp option 23 missing counter'
diff --git a/extensions/libxt_tcpmss.txlate b/extensions/libxt_tcpmss.txlate
index d3f1b27d..82475e67 100644
--- a/extensions/libxt_tcpmss.txlate
+++ b/extensions/libxt_tcpmss.txlate
@@ -1,11 +1,11 @@
iptables-translate -A INPUT -m tcpmss --mss 42
-nft add rule ip filter INPUT tcp option maxseg size 42 counter
+nft 'add rule ip filter INPUT tcp option maxseg size 42 counter'
iptables-translate -A INPUT -m tcpmss ! --mss 42
-nft add rule ip filter INPUT tcp option maxseg size != 42 counter
+nft 'add rule ip filter INPUT tcp option maxseg size != 42 counter'
iptables-translate -A INPUT -m tcpmss --mss 42:1024
-nft add rule ip filter INPUT tcp option maxseg size 42-1024 counter
+nft 'add rule ip filter INPUT tcp option maxseg size 42-1024 counter'
iptables-translate -A INPUT -m tcpmss ! --mss 1461:65535
-nft add rule ip filter INPUT tcp option maxseg size != 1461-65535 counter
+nft 'add rule ip filter INPUT tcp option maxseg size != 1461-65535 counter'
diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c
index d27d84ca..580861d3 100644
--- a/extensions/libxt_time.c
+++ b/extensions/libxt_time.c
@@ -466,9 +466,10 @@ static int time_xlate(struct xt_xlate *xl,
const struct xt_time_info *info =
(const struct xt_time_info *)params->match->data;
unsigned int h, m, s,
- i, sep, mask, count;
+ i, mask, count;
time_t tt_start, tt_stop;
struct tm *t_start, *t_stop;
+ const char *sep = "";
if (info->date_start != 0 ||
info->date_stop != INT_MAX) {
@@ -498,7 +499,6 @@ static int time_xlate(struct xt_xlate *xl,
if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS)
return 0;
if (info->weekdays_match != XT_TIME_ALL_WEEKDAYS) {
- sep = 0;
mask = info->weekdays_match;
count = time_count_weekdays(mask);
@@ -507,12 +507,8 @@ static int time_xlate(struct xt_xlate *xl,
xt_xlate_add(xl, "{");
for (i = 1; i <= 7; ++i)
if (mask & (1 << i)) {
- if (sep)
- xt_xlate_add(xl, ",%u", i%7);
- else {
- xt_xlate_add(xl, "%u", i%7);
- ++sep;
- }
+ xt_xlate_add(xl, "%s%u", sep, i%7);
+ sep = ", ";
}
if (count > 1)
xt_xlate_add(xl, "}");
diff --git a/extensions/libxt_time.txlate b/extensions/libxt_time.txlate
index ff4a7b88..ed64b957 100644
--- a/extensions/libxt_time.txlate
+++ b/extensions/libxt_time.txlate
@@ -1,26 +1,26 @@
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --weekdays Sa,Su -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta day {6,0} counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta day { 6, 0 } counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --timestart 12:00 -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta hour "12:00:00"-"23:59:59" counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta hour "12:00:00"-"23:59:59" counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --timestop 12:00 -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta hour "00:00:00"-"12:00:00" counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta hour "00:00:00"-"12:00:00" counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --datestart 2021 -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta time "2021-01-01 00:00:00"-"2038-01-19 03:14:07" counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta time "2021-01-01 00:00:00"-"2038-01-19 03:14:07" counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --datestop 2021 -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta time "1970-01-01 00:00:00"-"2021-01-01 00:00:00" counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta time "1970-01-01 00:00:00"-"2021-01-01 00:00:00" counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --datestop 2021-01-29T00:00:00 -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta time "1970-01-01 00:00:00"-"2021-01-29 00:00:00" counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta time "1970-01-01 00:00:00"-"2021-01-29 00:00:00" counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --datestart 2020-01-29T00:00:00 --timestart 12:00 -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta time "2020-01-29 00:00:00"-"2038-01-19 03:14:07" meta hour "12:00:00"-"23:59:59" counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta time "2020-01-29 00:00:00"-"2038-01-19 03:14:07" meta hour "12:00:00"-"23:59:59" counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --datestart 2020-01-29T00:00:00 --timestart 12:00 --timestop 19:00 --weekdays Mon,Tue,Wed,Thu,Fri -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta time "2020-01-29 00:00:00"-"2038-01-19 03:14:07" meta hour "12:00:00"-"19:00:00" meta day {1,2,3,4,5} counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta time "2020-01-29 00:00:00"-"2038-01-19 03:14:07" meta hour "12:00:00"-"19:00:00" meta day { 1, 2, 3, 4, 5 } counter reject'
iptables-translate -A INPUT -p icmp --icmp-type echo-request -m time --datestart 2020-01-29T00:00:00 --timestart 12:00 --timestop 19:00 ! --weekdays Mon,Tue,Wed,Thu,Fri -j REJECT
-nft add rule ip filter INPUT icmp type echo-request meta time "2020-01-29 00:00:00"-"2038-01-19 03:14:07" meta hour "12:00:00"-"19:00:00" meta day {6,0} counter reject
+nft 'add rule ip filter INPUT icmp type echo-request meta time "2020-01-29 00:00:00"-"2038-01-19 03:14:07" meta hour "12:00:00"-"19:00:00" meta day { 6, 0 } counter reject'
diff --git a/extensions/libxt_tos.t b/extensions/libxt_tos.t
index ccbe8009..6cceeeb4 100644
--- a/extensions/libxt_tos.t
+++ b/extensions/libxt_tos.t
@@ -4,10 +4,10 @@
-m tos --tos Maximize-Reliability;-m tos --tos 0x04/0x3f;OK
-m tos --tos Minimize-Cost;-m tos --tos 0x02/0x3f;OK
-m tos --tos Normal-Service;-m tos --tos 0x00/0x3f;OK
--m tos --tos 0xff;=;OK
--m tos ! --tos 0xff;=;OK
--m tos --tos 0x00;=;OK
--m tos --tos 0x0f;=;OK
+-m tos --tos 0xff;-m tos --tos 0xff/0xff;OK
+-m tos ! --tos 0xff;-m tos ! --tos 0xff/0xff;OK
+-m tos --tos 0x00;-m tos --tos 0x00/0xff;OK
+-m tos --tos 0x0f;-m tos --tos 0x0f/0xff;OK
-m tos --tos 0x0f/0x0f;=;OK
-m tos --tos wrong;;FAIL
-m tos;;FAIL
diff --git a/extensions/libxt_udp.c b/extensions/libxt_udp.c
index 0c7a4bc2..ba1c3eb7 100644
--- a/extensions/libxt_udp.c
+++ b/extensions/libxt_udp.c
@@ -156,7 +156,6 @@ static int udp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_udp *udpinfo = (struct xt_udp *)params->match->data;
- char *space= "";
if (udpinfo->spts[0] != 0 || udpinfo->spts[1] != 0xFFFF) {
if (udpinfo->spts[0] != udpinfo->spts[1]) {
@@ -170,17 +169,16 @@ static int udp_xlate(struct xt_xlate *xl,
"!= ": "",
udpinfo->spts[0]);
}
- space = " ";
}
if (udpinfo->dpts[0] != 0 || udpinfo->dpts[1] != 0xFFFF) {
if (udpinfo->dpts[0] != udpinfo->dpts[1]) {
- xt_xlate_add(xl,"%sudp dport %s%u-%u", space,
+ xt_xlate_add(xl,"udp dport %s%u-%u",
udpinfo->invflags & XT_UDP_INV_SRCPT ?
"!= ": "",
udpinfo->dpts[0], udpinfo->dpts[1]);
} else {
- xt_xlate_add(xl,"%sudp dport %s%u", space,
+ xt_xlate_add(xl,"udp dport %s%u",
udpinfo->invflags & XT_UDP_INV_SRCPT ?
"!= ": "",
udpinfo->dpts[0]);
diff --git a/extensions/libxt_udp.txlate b/extensions/libxt_udp.txlate
index fbca5c12..28e7ca20 100644
--- a/extensions/libxt_udp.txlate
+++ b/extensions/libxt_udp.txlate
@@ -1,11 +1,11 @@
iptables-translate -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
-nft add rule ip filter INPUT iifname "eth0" udp sport 53 counter accept
+nft 'add rule ip filter INPUT iifname "eth0" udp sport 53 counter accept'
iptables-translate -A OUTPUT -p udp -o eth0 --dport 53:66 -j DROP
-nft add rule ip filter OUTPUT oifname "eth0" udp dport 53-66 counter drop
+nft 'add rule ip filter OUTPUT oifname "eth0" udp dport 53-66 counter drop'
iptables-translate -I OUTPUT -p udp -d 8.8.8.8 -j ACCEPT
-nft insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept
+nft 'insert rule ip filter OUTPUT ip protocol udp ip daddr 8.8.8.8 counter accept'
iptables-translate -I OUTPUT -p udp --dport 1020:1023 --sport 53 -j ACCEPT
-nft insert rule ip filter OUTPUT udp sport 53 udp dport 1020-1023 counter accept
+nft 'insert rule ip filter OUTPUT udp sport 53 udp dport 1020-1023 counter accept'
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 66dceee0..e94d1fa5 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -8,6 +8,7 @@
#define NFT_SET_MAXNAMELEN NFT_NAME_MAXLEN
#define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN
#define NFT_USERDATA_MAXLEN 256
+#define NFT_OSF_MAXGENRELEN 16
/**
* enum nft_registers - nf_tables registers
@@ -47,6 +48,7 @@ enum nft_registers {
#define NFT_REG_SIZE 16
#define NFT_REG32_SIZE 4
+#define NFT_REG32_COUNT (NFT_REG32_15 - NFT_REG32_00 + 1)
/**
* enum nft_verdicts - nf_tables internal verdicts
@@ -131,7 +133,7 @@ enum nf_tables_msg_types {
* @NFTA_LIST_ELEM: list element (NLA_NESTED)
*/
enum nft_list_attributes {
- NFTA_LIST_UNPEC,
+ NFTA_LIST_UNSPEC,
NFTA_LIST_ELEM,
__NFTA_LIST_MAX
};
@@ -143,12 +145,14 @@ enum nft_list_attributes {
* @NFTA_HOOK_HOOKNUM: netfilter hook number (NLA_U32)
* @NFTA_HOOK_PRIORITY: netfilter hook priority (NLA_U32)
* @NFTA_HOOK_DEV: netdevice name (NLA_STRING)
+ * @NFTA_HOOK_DEVS: list of netdevices (NLA_NESTED)
*/
enum nft_hook_attributes {
NFTA_HOOK_UNSPEC,
NFTA_HOOK_HOOKNUM,
NFTA_HOOK_PRIORITY,
NFTA_HOOK_DEV,
+ NFTA_HOOK_DEVS,
__NFTA_HOOK_MAX
};
#define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1)
@@ -160,7 +164,10 @@ enum nft_hook_attributes {
*/
enum nft_table_flags {
NFT_TABLE_F_DORMANT = 0x1,
+ NFT_TABLE_F_OWNER = 0x2,
};
+#define NFT_TABLE_F_MASK (NFT_TABLE_F_DORMANT | \
+ NFT_TABLE_F_OWNER)
/**
* enum nft_table_attributes - nf_tables table netlink attributes
@@ -168,6 +175,8 @@ enum nft_table_flags {
* @NFTA_TABLE_NAME: name of the table (NLA_STRING)
* @NFTA_TABLE_FLAGS: bitmask of enum nft_table_flags (NLA_U32)
* @NFTA_TABLE_USE: number of chains in this table (NLA_U32)
+ * @NFTA_TABLE_USERDATA: user data (NLA_BINARY)
+ * @NFTA_TABLE_OWNER: owner of this table through netlink portID (NLA_U32)
*/
enum nft_table_attributes {
NFTA_TABLE_UNSPEC,
@@ -176,10 +185,21 @@ enum nft_table_attributes {
NFTA_TABLE_USE,
NFTA_TABLE_HANDLE,
NFTA_TABLE_PAD,
+ NFTA_TABLE_USERDATA,
+ NFTA_TABLE_OWNER,
__NFTA_TABLE_MAX
};
#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
+enum nft_chain_flags {
+ NFT_CHAIN_BASE = (1 << 0),
+ NFT_CHAIN_HW_OFFLOAD = (1 << 1),
+ NFT_CHAIN_BINDING = (1 << 2),
+};
+#define NFT_CHAIN_FLAGS (NFT_CHAIN_BASE | \
+ NFT_CHAIN_HW_OFFLOAD | \
+ NFT_CHAIN_BINDING)
+
/**
* enum nft_chain_attributes - nf_tables chain netlink attributes
*
@@ -191,6 +211,9 @@ enum nft_table_attributes {
* @NFTA_CHAIN_USE: number of references to this chain (NLA_U32)
* @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING)
* @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes)
+ * @NFTA_CHAIN_FLAGS: chain flags
+ * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32)
+ * @NFTA_CHAIN_USERDATA: user data (NLA_BINARY)
*/
enum nft_chain_attributes {
NFTA_CHAIN_UNSPEC,
@@ -203,6 +226,9 @@ enum nft_chain_attributes {
NFTA_CHAIN_TYPE,
NFTA_CHAIN_COUNTERS,
NFTA_CHAIN_PAD,
+ NFTA_CHAIN_FLAGS,
+ NFTA_CHAIN_ID,
+ NFTA_CHAIN_USERDATA,
__NFTA_CHAIN_MAX
};
#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
@@ -218,6 +244,7 @@ enum nft_chain_attributes {
* @NFTA_RULE_POSITION: numeric handle of the previous rule (NLA_U64)
* @NFTA_RULE_USERDATA: user data (NLA_BINARY, NFT_USERDATA_MAXLEN)
* @NFTA_RULE_ID: uniquely identifies a rule in a transaction (NLA_U32)
+ * @NFTA_RULE_POSITION_ID: transaction unique identifier of the previous rule (NLA_U32)
*/
enum nft_rule_attributes {
NFTA_RULE_UNSPEC,
@@ -230,6 +257,8 @@ enum nft_rule_attributes {
NFTA_RULE_USERDATA,
NFTA_RULE_PAD,
NFTA_RULE_ID,
+ NFTA_RULE_POSITION_ID,
+ NFTA_RULE_CHAIN_ID,
__NFTA_RULE_MAX
};
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
@@ -266,8 +295,10 @@ enum nft_rule_compat_attributes {
* @NFT_SET_INTERVAL: set contains intervals
* @NFT_SET_MAP: set is used as a dictionary
* @NFT_SET_TIMEOUT: set uses timeouts
- * @NFT_SET_EVAL: set contains expressions for evaluation
+ * @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects
+ * @NFT_SET_CONCAT: set contains a concatenation
+ * @NFT_SET_EXPR: set contains expressions
*/
enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1,
@@ -277,6 +308,8 @@ enum nft_set_flags {
NFT_SET_TIMEOUT = 0x10,
NFT_SET_EVAL = 0x20,
NFT_SET_OBJECT = 0x40,
+ NFT_SET_CONCAT = 0x80,
+ NFT_SET_EXPR = 0x100,
};
/**
@@ -294,15 +327,29 @@ enum nft_set_policies {
* enum nft_set_desc_attributes - set element description
*
* @NFTA_SET_DESC_SIZE: number of elements in set (NLA_U32)
+ * @NFTA_SET_DESC_CONCAT: description of field concatenation (NLA_NESTED)
*/
enum nft_set_desc_attributes {
NFTA_SET_DESC_UNSPEC,
NFTA_SET_DESC_SIZE,
+ NFTA_SET_DESC_CONCAT,
__NFTA_SET_DESC_MAX
};
#define NFTA_SET_DESC_MAX (__NFTA_SET_DESC_MAX - 1)
/**
+ * enum nft_set_field_attributes - attributes of concatenated fields
+ *
+ * @NFTA_SET_FIELD_LEN: length of single field, in bits (NLA_U32)
+ */
+enum nft_set_field_attributes {
+ NFTA_SET_FIELD_UNSPEC,
+ NFTA_SET_FIELD_LEN,
+ __NFTA_SET_FIELD_MAX
+};
+#define NFTA_SET_FIELD_MAX (__NFTA_SET_FIELD_MAX - 1)
+
+/**
* enum nft_set_attributes - nf_tables set netlink attributes
*
* @NFTA_SET_TABLE: table name (NLA_STRING)
@@ -320,6 +367,8 @@ enum nft_set_desc_attributes {
* @NFTA_SET_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*)
* @NFTA_SET_HANDLE: set handle (NLA_U64)
+ * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes)
+ * @NFTA_SET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes)
*/
enum nft_set_attributes {
NFTA_SET_UNSPEC,
@@ -339,6 +388,8 @@ enum nft_set_attributes {
NFTA_SET_PAD,
NFTA_SET_OBJ_TYPE,
NFTA_SET_HANDLE,
+ NFTA_SET_EXPR,
+ NFTA_SET_EXPRESSIONS,
__NFTA_SET_MAX
};
#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
@@ -347,9 +398,11 @@ enum nft_set_attributes {
* enum nft_set_elem_flags - nf_tables set element flags
*
* @NFT_SET_ELEM_INTERVAL_END: element ends the previous interval
+ * @NFT_SET_ELEM_CATCHALL: special catch-all element
*/
enum nft_set_elem_flags {
NFT_SET_ELEM_INTERVAL_END = 0x1,
+ NFT_SET_ELEM_CATCHALL = 0x2,
};
/**
@@ -363,6 +416,8 @@ enum nft_set_elem_flags {
* @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)
* @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING)
+ * @NFTA_SET_ELEM_KEY_END: closing key value (NLA_NESTED: nft_data)
+ * @NFTA_SET_ELEM_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes)
*/
enum nft_set_elem_attributes {
NFTA_SET_ELEM_UNSPEC,
@@ -375,6 +430,8 @@ enum nft_set_elem_attributes {
NFTA_SET_ELEM_EXPR,
NFTA_SET_ELEM_PAD,
NFTA_SET_ELEM_OBJREF,
+ NFTA_SET_ELEM_KEY_END,
+ NFTA_SET_ELEM_EXPRESSIONS,
__NFTA_SET_ELEM_MAX
};
#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
@@ -440,11 +497,13 @@ enum nft_data_attributes {
*
* @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)
* @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)
+ * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32)
*/
enum nft_verdict_attributes {
NFTA_VERDICT_UNSPEC,
NFTA_VERDICT_CODE,
NFTA_VERDICT_CHAIN,
+ NFTA_VERDICT_CHAIN_ID,
__NFTA_VERDICT_MAX
};
#define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)
@@ -478,6 +537,20 @@ enum nft_immediate_attributes {
#define NFTA_IMMEDIATE_MAX (__NFTA_IMMEDIATE_MAX - 1)
/**
+ * enum nft_bitwise_ops - nf_tables bitwise operations
+ *
+ * @NFT_BITWISE_BOOL: mask-and-xor operation used to implement NOT, AND, OR and
+ * XOR boolean operations
+ * @NFT_BITWISE_LSHIFT: left-shift operation
+ * @NFT_BITWISE_RSHIFT: right-shift operation
+ */
+enum nft_bitwise_ops {
+ NFT_BITWISE_BOOL,
+ NFT_BITWISE_LSHIFT,
+ NFT_BITWISE_RSHIFT,
+};
+
+/**
* enum nft_bitwise_attributes - nf_tables bitwise expression netlink attributes
*
* @NFTA_BITWISE_SREG: source register (NLA_U32: nft_registers)
@@ -485,16 +558,20 @@ enum nft_immediate_attributes {
* @NFTA_BITWISE_LEN: length of operands (NLA_U32)
* @NFTA_BITWISE_MASK: mask value (NLA_NESTED: nft_data_attributes)
* @NFTA_BITWISE_XOR: xor value (NLA_NESTED: nft_data_attributes)
+ * @NFTA_BITWISE_OP: type of operation (NLA_U32: nft_bitwise_ops)
+ * @NFTA_BITWISE_DATA: argument for non-boolean operations
+ * (NLA_NESTED: nft_data_attributes)
*
- * The bitwise expression performs the following operation:
+ * The bitwise expression supports boolean and shift operations. It implements
+ * the boolean operations by performing the following operation:
*
* dreg = (sreg & mask) ^ xor
*
- * which allow to express all bitwise operations:
+ * with these mask and xor values:
*
* mask xor
* NOT: 1 1
- * OR: 0 x
+ * OR: ~x x
* XOR: 1 x
* AND: x 0
*/
@@ -505,6 +582,8 @@ enum nft_bitwise_attributes {
NFTA_BITWISE_LEN,
NFTA_BITWISE_MASK,
NFTA_BITWISE_XOR,
+ NFTA_BITWISE_OP,
+ NFTA_BITWISE_DATA,
__NFTA_BITWISE_MAX
};
#define NFTA_BITWISE_MAX (__NFTA_BITWISE_MAX - 1)
@@ -631,10 +710,12 @@ enum nft_lookup_attributes {
enum nft_dynset_ops {
NFT_DYNSET_OP_ADD,
NFT_DYNSET_OP_UPDATE,
+ NFT_DYNSET_OP_DELETE,
};
enum nft_dynset_flags {
NFT_DYNSET_F_INV = (1 << 0),
+ NFT_DYNSET_F_EXPR = (1 << 1),
};
/**
@@ -648,6 +729,7 @@ enum nft_dynset_flags {
* @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64)
* @NFTA_DYNSET_EXPR: expression (NLA_NESTED: nft_expr_attributes)
* @NFTA_DYNSET_FLAGS: flags (NLA_U32)
+ * @NFTA_DYNSET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes)
*/
enum nft_dynset_attributes {
NFTA_DYNSET_UNSPEC,
@@ -660,6 +742,7 @@ enum nft_dynset_attributes {
NFTA_DYNSET_EXPR,
NFTA_DYNSET_PAD,
NFTA_DYNSET_FLAGS,
+ NFTA_DYNSET_EXPRESSIONS,
__NFTA_DYNSET_MAX,
};
#define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1)
@@ -682,10 +765,12 @@ enum nft_payload_bases {
*
* @NFT_PAYLOAD_CSUM_NONE: no checksumming
* @NFT_PAYLOAD_CSUM_INET: internet checksum (RFC 791)
+ * @NFT_PAYLOAD_CSUM_SCTP: CRC-32c, for use in SCTP header (RFC 3309)
*/
enum nft_payload_csum_types {
NFT_PAYLOAD_CSUM_NONE,
NFT_PAYLOAD_CSUM_INET,
+ NFT_PAYLOAD_CSUM_SCTP,
};
enum nft_payload_csum_flags {
@@ -727,10 +812,14 @@ enum nft_exthdr_flags {
*
* @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers
* @NFT_EXTHDR_OP_TCP: match against tcp options
+ * @NFT_EXTHDR_OP_IPV4: match against ipv4 options
+ * @NFT_EXTHDR_OP_SCTP: match against sctp chunks
*/
enum nft_exthdr_op {
NFT_EXTHDR_OP_IPV6,
NFT_EXTHDR_OP_TCPOPT,
+ NFT_EXTHDR_OP_IPV4,
+ NFT_EXTHDR_OP_SCTP,
__NFT_EXTHDR_OP_MAX
};
#define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1)
@@ -788,6 +877,15 @@ enum nft_exthdr_attributes {
* @NFT_META_CGROUP: socket control group (skb->sk->sk_classid)
* @NFT_META_PRANDOM: a 32bit pseudo-random number
* @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp)
+ * @NFT_META_IIFKIND: packet input interface kind name (dev->rtnl_link_ops->kind)
+ * @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
+ * @NFT_META_BRI_IIFPVID: packet input bridge port pvid
+ * @NFT_META_BRI_IIFVPROTO: packet input bridge vlan proto
+ * @NFT_META_TIME_NS: time since epoch (in nanoseconds)
+ * @NFT_META_TIME_DAY: day of week (from 0 = Sunday to 6 = Saturday)
+ * @NFT_META_TIME_HOUR: hour of day (in seconds)
+ * @NFT_META_SDIF: slave device interface index
+ * @NFT_META_SDIFNAME: slave device interface name
*/
enum nft_meta_keys {
NFT_META_LEN,
@@ -816,6 +914,15 @@ enum nft_meta_keys {
NFT_META_CGROUP,
NFT_META_PRANDOM,
NFT_META_SECPATH,
+ NFT_META_IIFKIND,
+ NFT_META_OIFKIND,
+ NFT_META_BRI_IIFPVID,
+ NFT_META_BRI_IIFVPROTO,
+ NFT_META_TIME_NS,
+ NFT_META_TIME_DAY,
+ NFT_META_TIME_HOUR,
+ NFT_META_SDIF,
+ NFT_META_SDIFNAME,
};
/**
@@ -825,13 +932,17 @@ enum nft_meta_keys {
* @NFT_RT_NEXTHOP4: routing nexthop for IPv4
* @NFT_RT_NEXTHOP6: routing nexthop for IPv6
* @NFT_RT_TCPMSS: fetch current path tcp mss
+ * @NFT_RT_XFRM: boolean, skb->dst->xfrm != NULL
*/
enum nft_rt_keys {
NFT_RT_CLASSID,
NFT_RT_NEXTHOP4,
NFT_RT_NEXTHOP6,
NFT_RT_TCPMSS,
+ NFT_RT_XFRM,
+ __NFT_RT_MAX
};
+#define NFT_RT_MAX (__NFT_RT_MAX - 1)
/**
* enum nft_hash_types - nf_tables hash expression types
@@ -854,6 +965,8 @@ enum nft_hash_types {
* @NFTA_HASH_SEED: seed value (NLA_U32)
* @NFTA_HASH_OFFSET: add this offset value to hash result (NLA_U32)
* @NFTA_HASH_TYPE: hash operation (NLA_U32: nft_hash_types)
+ * @NFTA_HASH_SET_NAME: name of the map to lookup (NLA_STRING)
+ * @NFTA_HASH_SET_ID: id of the map (NLA_U32)
*/
enum nft_hash_attributes {
NFTA_HASH_UNSPEC,
@@ -864,6 +977,8 @@ enum nft_hash_attributes {
NFTA_HASH_SEED,
NFTA_HASH_OFFSET,
NFTA_HASH_TYPE,
+ NFTA_HASH_SET_NAME, /* deprecated */
+ NFTA_HASH_SET_ID, /* deprecated */
__NFTA_HASH_MAX,
};
#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
@@ -899,6 +1014,39 @@ enum nft_rt_attributes {
#define NFTA_RT_MAX (__NFTA_RT_MAX - 1)
/**
+ * enum nft_socket_attributes - nf_tables socket expression netlink attributes
+ *
+ * @NFTA_SOCKET_KEY: socket key to match
+ * @NFTA_SOCKET_DREG: destination register
+ * @NFTA_SOCKET_LEVEL: cgroups2 ancestor level (only for cgroupsv2)
+ */
+enum nft_socket_attributes {
+ NFTA_SOCKET_UNSPEC,
+ NFTA_SOCKET_KEY,
+ NFTA_SOCKET_DREG,
+ NFTA_SOCKET_LEVEL,
+ __NFTA_SOCKET_MAX
+};
+#define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1)
+
+/*
+ * enum nft_socket_keys - nf_tables socket expression keys
+ *
+ * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option
+ * @NFT_SOCKET_MARK: Value of the socket mark
+ * @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0)
+ * @NFT_SOCKET_CGROUPV2: Match on cgroups version 2
+ */
+enum nft_socket_keys {
+ NFT_SOCKET_TRANSPARENT,
+ NFT_SOCKET_MARK,
+ NFT_SOCKET_WILDCARD,
+ NFT_SOCKET_CGROUPV2,
+ __NFT_SOCKET_MAX
+};
+#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)
+
+/**
* enum nft_ct_keys - nf_tables ct expression keys
*
* @NFT_CT_STATE: conntrack state (bitmask of enum ip_conntrack_info)
@@ -909,8 +1057,8 @@ enum nft_rt_attributes {
* @NFT_CT_EXPIRATION: relative conntrack expiration time in ms
* @NFT_CT_HELPER: connection tracking helper assigned to conntrack
* @NFT_CT_L3PROTOCOL: conntrack layer 3 protocol
- * @NFT_CT_SRC: conntrack layer 3 protocol source (IPv4/IPv6 address)
- * @NFT_CT_DST: conntrack layer 3 protocol destination (IPv4/IPv6 address)
+ * @NFT_CT_SRC: conntrack layer 3 protocol source (IPv4/IPv6 address, deprecated)
+ * @NFT_CT_DST: conntrack layer 3 protocol destination (IPv4/IPv6 address, deprecated)
* @NFT_CT_PROTOCOL: conntrack layer 4 protocol
* @NFT_CT_PROTO_SRC: conntrack layer 4 protocol source
* @NFT_CT_PROTO_DST: conntrack layer 4 protocol destination
@@ -920,6 +1068,11 @@ enum nft_rt_attributes {
* @NFT_CT_AVGPKT: conntrack average bytes per packet
* @NFT_CT_ZONE: conntrack zone
* @NFT_CT_EVENTMASK: ctnetlink events to be generated for this conntrack
+ * @NFT_CT_SRC_IP: conntrack layer 3 protocol source (IPv4 address)
+ * @NFT_CT_DST_IP: conntrack layer 3 protocol destination (IPv4 address)
+ * @NFT_CT_SRC_IP6: conntrack layer 3 protocol source (IPv6 address)
+ * @NFT_CT_DST_IP6: conntrack layer 3 protocol destination (IPv6 address)
+ * @NFT_CT_ID: conntrack id
*/
enum nft_ct_keys {
NFT_CT_STATE,
@@ -941,7 +1094,14 @@ enum nft_ct_keys {
NFT_CT_AVGPKT,
NFT_CT_ZONE,
NFT_CT_EVENTMASK,
+ NFT_CT_SRC_IP,
+ NFT_CT_DST_IP,
+ NFT_CT_SRC_IP6,
+ NFT_CT_DST_IP6,
+ NFT_CT_ID,
+ __NFT_CT_MAX
};
+#define NFT_CT_MAX (__NFT_CT_MAX - 1)
/**
* enum nft_ct_attributes - nf_tables ct expression netlink attributes
@@ -1002,6 +1162,24 @@ enum nft_limit_attributes {
};
#define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)
+enum nft_connlimit_flags {
+ NFT_CONNLIMIT_F_INV = (1 << 0),
+};
+
+/**
+ * enum nft_connlimit_attributes - nf_tables connlimit expression netlink attributes
+ *
+ * @NFTA_CONNLIMIT_COUNT: number of connections (NLA_U32)
+ * @NFTA_CONNLIMIT_FLAGS: flags (NLA_U32: enum nft_connlimit_flags)
+ */
+enum nft_connlimit_attributes {
+ NFTA_CONNLIMIT_UNSPEC,
+ NFTA_CONNLIMIT_COUNT,
+ NFTA_CONNLIMIT_FLAGS,
+ __NFTA_CONNLIMIT_MAX
+};
+#define NFTA_CONNLIMIT_MAX (__NFTA_CONNLIMIT_MAX - 1)
+
/**
* enum nft_counter_attributes - nf_tables counter expression netlink attributes
*
@@ -1018,6 +1196,21 @@ enum nft_counter_attributes {
#define NFTA_COUNTER_MAX (__NFTA_COUNTER_MAX - 1)
/**
+ * enum nft_last_attributes - nf_tables last expression netlink attributes
+ *
+ * @NFTA_LAST_SET: last update has been set, zero means never updated (NLA_U32)
+ * @NFTA_LAST_MSECS: milliseconds since last update (NLA_U64)
+ */
+enum nft_last_attributes {
+ NFTA_LAST_UNSPEC,
+ NFTA_LAST_SET,
+ NFTA_LAST_MSECS,
+ NFTA_LAST_PAD,
+ __NFTA_LAST_MAX
+};
+#define NFTA_LAST_MAX (__NFTA_LAST_MAX - 1)
+
+/**
* enum nft_log_attributes - nf_tables log expression netlink attributes
*
* @NFTA_LOG_GROUP: netlink group to send messages to (NLA_U32)
@@ -1040,6 +1233,33 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
+ * enum nft_log_level - nf_tables log levels
+ *
+ * @NFT_LOGLEVEL_EMERG: system is unusable
+ * @NFT_LOGLEVEL_ALERT: action must be taken immediately
+ * @NFT_LOGLEVEL_CRIT: critical conditions
+ * @NFT_LOGLEVEL_ERR: error conditions
+ * @NFT_LOGLEVEL_WARNING: warning conditions
+ * @NFT_LOGLEVEL_NOTICE: normal but significant condition
+ * @NFT_LOGLEVEL_INFO: informational
+ * @NFT_LOGLEVEL_DEBUG: debug-level messages
+ * @NFT_LOGLEVEL_AUDIT: enabling audit logging
+ */
+enum nft_log_level {
+ NFT_LOGLEVEL_EMERG,
+ NFT_LOGLEVEL_ALERT,
+ NFT_LOGLEVEL_CRIT,
+ NFT_LOGLEVEL_ERR,
+ NFT_LOGLEVEL_WARNING,
+ NFT_LOGLEVEL_NOTICE,
+ NFT_LOGLEVEL_INFO,
+ NFT_LOGLEVEL_DEBUG,
+ NFT_LOGLEVEL_AUDIT,
+ __NFT_LOGLEVEL_MAX
+};
+#define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX - 1)
+
+/**
* enum nft_queue_attributes - nf_tables queue expression netlink attributes
*
* @NFTA_QUEUE_NUM: netlink queue to send messages to (NLA_U16)
@@ -1084,6 +1304,21 @@ enum nft_quota_attributes {
#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)
/**
+ * enum nft_secmark_attributes - nf_tables secmark object netlink attributes
+ *
+ * @NFTA_SECMARK_CTX: security context (NLA_STRING)
+ */
+enum nft_secmark_attributes {
+ NFTA_SECMARK_UNSPEC,
+ NFTA_SECMARK_CTX,
+ __NFTA_SECMARK_MAX,
+};
+#define NFTA_SECMARK_MAX (__NFTA_SECMARK_MAX - 1)
+
+/* Max security context length */
+#define NFT_SECMARK_CTX_MAXLEN 256
+
+/**
* enum nft_reject_types - nf_tables reject expression reject types
*
* @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
@@ -1165,6 +1400,22 @@ enum nft_nat_attributes {
#define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1)
/**
+ * enum nft_tproxy_attributes - nf_tables tproxy expression netlink attributes
+ *
+ * NFTA_TPROXY_FAMILY: Target address family (NLA_U32: nft_registers)
+ * NFTA_TPROXY_REG_ADDR: Target address register (NLA_U32: nft_registers)
+ * NFTA_TPROXY_REG_PORT: Target port register (NLA_U32: nft_registers)
+ */
+enum nft_tproxy_attributes {
+ NFTA_TPROXY_UNSPEC,
+ NFTA_TPROXY_FAMILY,
+ NFTA_TPROXY_REG_ADDR,
+ NFTA_TPROXY_REG_PORT,
+ __NFTA_TPROXY_MAX
+};
+#define NFTA_TPROXY_MAX (__NFTA_TPROXY_MAX - 1)
+
+/**
* enum nft_masq_attributes - nf_tables masquerade expression attributes
*
* @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
@@ -1214,10 +1465,14 @@ enum nft_dup_attributes {
* enum nft_fwd_attributes - nf_tables fwd expression netlink attributes
*
* @NFTA_FWD_SREG_DEV: source register of output interface (NLA_U32: nft_register)
+ * @NFTA_FWD_SREG_ADDR: source register of destination address (NLA_U32: nft_register)
+ * @NFTA_FWD_NFPROTO: layer 3 family of source register address (NLA_U32: enum nfproto)
*/
enum nft_fwd_attributes {
NFTA_FWD_UNSPEC,
NFTA_FWD_SREG_DEV,
+ NFTA_FWD_SREG_ADDR,
+ NFTA_FWD_NFPROTO,
__NFTA_FWD_MAX
};
#define NFTA_FWD_MAX (__NFTA_FWD_MAX - 1)
@@ -1302,12 +1557,38 @@ enum nft_ct_helper_attributes {
};
#define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1)
+enum nft_ct_timeout_timeout_attributes {
+ NFTA_CT_TIMEOUT_UNSPEC,
+ NFTA_CT_TIMEOUT_L3PROTO,
+ NFTA_CT_TIMEOUT_L4PROTO,
+ NFTA_CT_TIMEOUT_DATA,
+ __NFTA_CT_TIMEOUT_MAX,
+};
+#define NFTA_CT_TIMEOUT_MAX (__NFTA_CT_TIMEOUT_MAX - 1)
+
+enum nft_ct_expectation_attributes {
+ NFTA_CT_EXPECT_UNSPEC,
+ NFTA_CT_EXPECT_L3PROTO,
+ NFTA_CT_EXPECT_L4PROTO,
+ NFTA_CT_EXPECT_DPORT,
+ NFTA_CT_EXPECT_TIMEOUT,
+ NFTA_CT_EXPECT_SIZE,
+ __NFTA_CT_EXPECT_MAX,
+};
+#define NFTA_CT_EXPECT_MAX (__NFTA_CT_EXPECT_MAX - 1)
+
#define NFT_OBJECT_UNSPEC 0
#define NFT_OBJECT_COUNTER 1
#define NFT_OBJECT_QUOTA 2
#define NFT_OBJECT_CT_HELPER 3
#define NFT_OBJECT_LIMIT 4
-#define __NFT_OBJECT_MAX 5
+#define NFT_OBJECT_CONNLIMIT 5
+#define NFT_OBJECT_TUNNEL 6
+#define NFT_OBJECT_CT_TIMEOUT 7
+#define NFT_OBJECT_SECMARK 8
+#define NFT_OBJECT_CT_EXPECT 9
+#define NFT_OBJECT_SYNPROXY 10
+#define __NFT_OBJECT_MAX 11
#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
/**
@@ -1319,6 +1600,7 @@ enum nft_ct_helper_attributes {
* @NFTA_OBJ_DATA: stateful object data (NLA_NESTED)
* @NFTA_OBJ_USE: number of references to this expression (NLA_U32)
* @NFTA_OBJ_HANDLE: object handle (NLA_U64)
+ * @NFTA_OBJ_USERDATA: user data (NLA_BINARY)
*/
enum nft_object_attributes {
NFTA_OBJ_UNSPEC,
@@ -1329,11 +1611,25 @@ enum nft_object_attributes {
NFTA_OBJ_USE,
NFTA_OBJ_HANDLE,
NFTA_OBJ_PAD,
+ NFTA_OBJ_USERDATA,
__NFTA_OBJ_MAX
};
#define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1)
/**
+ * enum nft_flowtable_flags - nf_tables flowtable flags
+ *
+ * @NFT_FLOWTABLE_HW_OFFLOAD: flowtable hardware offload is enabled
+ * @NFT_FLOWTABLE_COUNTER: enable flow counters
+ */
+enum nft_flowtable_flags {
+ NFT_FLOWTABLE_HW_OFFLOAD = 0x1,
+ NFT_FLOWTABLE_COUNTER = 0x2,
+ NFT_FLOWTABLE_MASK = (NFT_FLOWTABLE_HW_OFFLOAD |
+ NFT_FLOWTABLE_COUNTER)
+};
+
+/**
* enum nft_flowtable_attributes - nf_tables flow table netlink attributes
*
* @NFTA_FLOWTABLE_TABLE: name of the table containing the expression (NLA_STRING)
@@ -1341,6 +1637,7 @@ enum nft_object_attributes {
* @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
* @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
* @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
+ * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)
*/
enum nft_flowtable_attributes {
NFTA_FLOWTABLE_UNSPEC,
@@ -1350,6 +1647,7 @@ enum nft_flowtable_attributes {
NFTA_FLOWTABLE_USE,
NFTA_FLOWTABLE_HANDLE,
NFTA_FLOWTABLE_PAD,
+ NFTA_FLOWTABLE_FLAGS,
__NFTA_FLOWTABLE_MAX
};
#define NFTA_FLOWTABLE_MAX (__NFTA_FLOWTABLE_MAX - 1)
@@ -1371,6 +1669,42 @@ enum nft_flowtable_hook_attributes {
#define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1)
/**
+ * enum nft_osf_attributes - nftables osf expression netlink attributes
+ *
+ * @NFTA_OSF_DREG: destination register (NLA_U32: nft_registers)
+ * @NFTA_OSF_TTL: Value of the TTL osf option (NLA_U8)
+ * @NFTA_OSF_FLAGS: flags (NLA_U32)
+ */
+enum nft_osf_attributes {
+ NFTA_OSF_UNSPEC,
+ NFTA_OSF_DREG,
+ NFTA_OSF_TTL,
+ NFTA_OSF_FLAGS,
+ __NFTA_OSF_MAX,
+};
+#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
+
+enum nft_osf_flags {
+ NFT_OSF_F_VERSION = (1 << 0),
+};
+
+/**
+ * enum nft_synproxy_attributes - nf_tables synproxy expression netlink attributes
+ *
+ * @NFTA_SYNPROXY_MSS: mss value sent to the backend (NLA_U16)
+ * @NFTA_SYNPROXY_WSCALE: wscale value sent to the backend (NLA_U8)
+ * @NFTA_SYNPROXY_FLAGS: flags (NLA_U32)
+ */
+enum nft_synproxy_attributes {
+ NFTA_SYNPROXY_UNSPEC,
+ NFTA_SYNPROXY_MSS,
+ NFTA_SYNPROXY_WSCALE,
+ NFTA_SYNPROXY_FLAGS,
+ __NFTA_SYNPROXY_MAX,
+};
+#define NFTA_SYNPROXY_MAX (__NFTA_SYNPROXY_MAX - 1)
+
+/**
* enum nft_device_attributes - nf_tables device netlink attributes
*
* @NFTA_DEVICE_NAME: name of this device (NLA_STRING)
@@ -1382,6 +1716,35 @@ enum nft_devices_attributes {
};
#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1)
+/*
+ * enum nft_xfrm_attributes - nf_tables xfrm expr netlink attributes
+ *
+ * @NFTA_XFRM_DREG: destination register (NLA_U32)
+ * @NFTA_XFRM_KEY: enum nft_xfrm_keys (NLA_U32)
+ * @NFTA_XFRM_DIR: direction (NLA_U8)
+ * @NFTA_XFRM_SPNUM: index in secpath array (NLA_U32)
+ */
+enum nft_xfrm_attributes {
+ NFTA_XFRM_UNSPEC,
+ NFTA_XFRM_DREG,
+ NFTA_XFRM_KEY,
+ NFTA_XFRM_DIR,
+ NFTA_XFRM_SPNUM,
+ __NFTA_XFRM_MAX
+};
+#define NFTA_XFRM_MAX (__NFTA_XFRM_MAX - 1)
+
+enum nft_xfrm_keys {
+ NFT_XFRM_KEY_UNSPEC,
+ NFT_XFRM_KEY_DADDR_IP4,
+ NFT_XFRM_KEY_DADDR_IP6,
+ NFT_XFRM_KEY_SADDR_IP4,
+ NFT_XFRM_KEY_SADDR_IP6,
+ NFT_XFRM_KEY_REQID,
+ NFT_XFRM_KEY_SPI,
+ __NFT_XFRM_KEY_MAX,
+};
+#define NFT_XFRM_KEY_MAX (__NFT_XFRM_KEY_MAX - 1)
/**
* enum nft_trace_attributes - nf_tables trace netlink attributes
@@ -1442,6 +1805,8 @@ enum nft_trace_types {
* @NFTA_NG_MODULUS: maximum counter value (NLA_U32)
* @NFTA_NG_TYPE: operation type (NLA_U32)
* @NFTA_NG_OFFSET: offset to be added to the counter (NLA_U32)
+ * @NFTA_NG_SET_NAME: name of the map to lookup (NLA_STRING)
+ * @NFTA_NG_SET_ID: id of the map (NLA_U32)
*/
enum nft_ng_attributes {
NFTA_NG_UNSPEC,
@@ -1449,6 +1814,8 @@ enum nft_ng_attributes {
NFTA_NG_MODULUS,
NFTA_NG_TYPE,
NFTA_NG_OFFSET,
+ NFTA_NG_SET_NAME, /* deprecated */
+ NFTA_NG_SET_ID, /* deprecated */
__NFTA_NG_MAX
};
#define NFTA_NG_MAX (__NFTA_NG_MAX - 1)
@@ -1460,4 +1827,104 @@ enum nft_ng_types {
};
#define NFT_NG_MAX (__NFT_NG_MAX - 1)
+enum nft_tunnel_key_ip_attributes {
+ NFTA_TUNNEL_KEY_IP_UNSPEC,
+ NFTA_TUNNEL_KEY_IP_SRC,
+ NFTA_TUNNEL_KEY_IP_DST,
+ __NFTA_TUNNEL_KEY_IP_MAX
+};
+#define NFTA_TUNNEL_KEY_IP_MAX (__NFTA_TUNNEL_KEY_IP_MAX - 1)
+
+enum nft_tunnel_ip6_attributes {
+ NFTA_TUNNEL_KEY_IP6_UNSPEC,
+ NFTA_TUNNEL_KEY_IP6_SRC,
+ NFTA_TUNNEL_KEY_IP6_DST,
+ NFTA_TUNNEL_KEY_IP6_FLOWLABEL,
+ __NFTA_TUNNEL_KEY_IP6_MAX
+};
+#define NFTA_TUNNEL_KEY_IP6_MAX (__NFTA_TUNNEL_KEY_IP6_MAX - 1)
+
+enum nft_tunnel_opts_attributes {
+ NFTA_TUNNEL_KEY_OPTS_UNSPEC,
+ NFTA_TUNNEL_KEY_OPTS_VXLAN,
+ NFTA_TUNNEL_KEY_OPTS_ERSPAN,
+ NFTA_TUNNEL_KEY_OPTS_GENEVE,
+ __NFTA_TUNNEL_KEY_OPTS_MAX
+};
+#define NFTA_TUNNEL_KEY_OPTS_MAX (__NFTA_TUNNEL_KEY_OPTS_MAX - 1)
+
+enum nft_tunnel_opts_vxlan_attributes {
+ NFTA_TUNNEL_KEY_VXLAN_UNSPEC,
+ NFTA_TUNNEL_KEY_VXLAN_GBP,
+ __NFTA_TUNNEL_KEY_VXLAN_MAX
+};
+#define NFTA_TUNNEL_KEY_VXLAN_MAX (__NFTA_TUNNEL_KEY_VXLAN_MAX - 1)
+
+enum nft_tunnel_opts_erspan_attributes {
+ NFTA_TUNNEL_KEY_ERSPAN_UNSPEC,
+ NFTA_TUNNEL_KEY_ERSPAN_VERSION,
+ NFTA_TUNNEL_KEY_ERSPAN_V1_INDEX,
+ NFTA_TUNNEL_KEY_ERSPAN_V2_HWID,
+ NFTA_TUNNEL_KEY_ERSPAN_V2_DIR,
+ __NFTA_TUNNEL_KEY_ERSPAN_MAX
+};
+#define NFTA_TUNNEL_KEY_ERSPAN_MAX (__NFTA_TUNNEL_KEY_ERSPAN_MAX - 1)
+
+enum nft_tunnel_opts_geneve_attributes {
+ NFTA_TUNNEL_KEY_GENEVE_UNSPEC,
+ NFTA_TUNNEL_KEY_GENEVE_CLASS,
+ NFTA_TUNNEL_KEY_GENEVE_TYPE,
+ NFTA_TUNNEL_KEY_GENEVE_DATA,
+ __NFTA_TUNNEL_KEY_GENEVE_MAX
+};
+#define NFTA_TUNNEL_KEY_GENEVE_MAX (__NFTA_TUNNEL_KEY_GENEVE_MAX - 1)
+
+enum nft_tunnel_flags {
+ NFT_TUNNEL_F_ZERO_CSUM_TX = (1 << 0),
+ NFT_TUNNEL_F_DONT_FRAGMENT = (1 << 1),
+ NFT_TUNNEL_F_SEQ_NUMBER = (1 << 2),
+};
+#define NFT_TUNNEL_F_MASK (NFT_TUNNEL_F_ZERO_CSUM_TX | \
+ NFT_TUNNEL_F_DONT_FRAGMENT | \
+ NFT_TUNNEL_F_SEQ_NUMBER)
+
+enum nft_tunnel_key_attributes {
+ NFTA_TUNNEL_KEY_UNSPEC,
+ NFTA_TUNNEL_KEY_ID,
+ NFTA_TUNNEL_KEY_IP,
+ NFTA_TUNNEL_KEY_IP6,
+ NFTA_TUNNEL_KEY_FLAGS,
+ NFTA_TUNNEL_KEY_TOS,
+ NFTA_TUNNEL_KEY_TTL,
+ NFTA_TUNNEL_KEY_SPORT,
+ NFTA_TUNNEL_KEY_DPORT,
+ NFTA_TUNNEL_KEY_OPTS,
+ __NFTA_TUNNEL_KEY_MAX
+};
+#define NFTA_TUNNEL_KEY_MAX (__NFTA_TUNNEL_KEY_MAX - 1)
+
+enum nft_tunnel_keys {
+ NFT_TUNNEL_PATH,
+ NFT_TUNNEL_ID,
+ __NFT_TUNNEL_MAX
+};
+#define NFT_TUNNEL_MAX (__NFT_TUNNEL_MAX - 1)
+
+enum nft_tunnel_mode {
+ NFT_TUNNEL_MODE_NONE,
+ NFT_TUNNEL_MODE_RX,
+ NFT_TUNNEL_MODE_TX,
+ __NFT_TUNNEL_MODE_MAX
+};
+#define NFT_TUNNEL_MODE_MAX (__NFT_TUNNEL_MODE_MAX - 1)
+
+enum nft_tunnel_attributes {
+ NFTA_TUNNEL_UNSPEC,
+ NFTA_TUNNEL_KEY,
+ NFTA_TUNNEL_DREG,
+ NFTA_TUNNEL_MODE,
+ __NFTA_TUNNEL_MAX
+};
+#define NFTA_TUNNEL_MAX (__NFTA_TUNNEL_MAX - 1)
+
#endif /* _LINUX_NF_TABLES_H */
diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
index c4bbc41b..ae5d4d10 100644
--- a/include/linux/netfilter_bridge/ebt_ip.h
+++ b/include/linux/netfilter_bridge/ebt_ip.h
@@ -23,8 +23,10 @@
#define EBT_IP_PROTO 0x08
#define EBT_IP_SPORT 0x10
#define EBT_IP_DPORT 0x20
+#define EBT_IP_ICMP 0x40
+#define EBT_IP_IGMP 0x80
#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\
- EBT_IP_SPORT | EBT_IP_DPORT )
+ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP)
#define EBT_IP_MATCH "ip"
/* the same values are used for the invflags */
@@ -37,8 +39,15 @@ struct ebt_ip_info {
__u8 protocol;
__u8 bitmask;
__u8 invflags;
- __u16 sport[2];
- __u16 dport[2];
+ union {
+ __u16 sport[2];
+ __u8 icmp_type[2];
+ __u8 igmp_type[2];
+ };
+ union {
+ __u16 dport[2];
+ __u8 icmp_code[2];
+ };
};
#endif
diff --git a/include/xtables.h b/include/xtables.h
index 9eba4f61..4ffc8ec5 100644
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -211,14 +211,14 @@ struct xt_xlate_mt_params {
const void *ip;
const struct xt_entry_match *match;
int numeric;
- bool escape_quotes;
+ bool escape_quotes; /* not used anymore, retained for ABI */
};
struct xt_xlate_tg_params {
const void *ip;
const struct xt_entry_target *target;
int numeric;
- bool escape_quotes;
+ bool escape_quotes; /* not used anymore, retained for ABI */
};
/* Include file for additions: new matches and targets. */
@@ -621,8 +621,11 @@ extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int);
struct xt_xlate *xt_xlate_alloc(int size);
void xt_xlate_free(struct xt_xlate *xl);
void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
+void xt_xlate_add_nospc(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
#define xt_xlate_rule_add xt_xlate_add
+#define xt_xlate_rule_add_nospc xt_xlate_add_nospc
void xt_xlate_set_add(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
+void xt_xlate_set_add_nospc(struct xt_xlate *xl, const char *fmt, ...) __attribute__((format(printf,2,3)));
void xt_xlate_add_comment(struct xt_xlate *xl, const char *comment);
const char *xt_xlate_get_comment(struct xt_xlate *xl);
void xl_xlate_set_family(struct xt_xlate *xl, uint8_t family);
diff --git a/iptables-test.py b/iptables-test.py
index 6acaa822..dc031c2b 100755
--- a/iptables-test.py
+++ b/iptables-test.py
@@ -54,12 +54,12 @@ def print_error(reason, filename=None, lineno=None):
": line %d (%s)" % (lineno, reason), file=sys.stderr)
-def delete_rule(iptables, rule, filename, lineno):
+def delete_rule(iptables, rule, filename, lineno, netns = None):
'''
Removes an iptables rule
'''
cmd = iptables + " -D " + rule
- ret = execute_cmd(cmd, filename, lineno)
+ ret = execute_cmd(cmd, filename, lineno, netns)
if ret == 1:
reason = "cannot delete: " + iptables + " -I " + rule
print_error(reason, filename, lineno)
@@ -79,14 +79,12 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
:param res: expected result of the rule. Valid values: "OK", "FAIL"
:param filename: name of the file tested (used for print_error purposes)
:param lineno: line number being tested (used for print_error purposes)
+ :param netns: network namespace to call commands in (or None)
'''
ret = 0
cmd = iptables + " -A " + rule
- if netns:
- cmd = "ip netns exec ____iptables-container-test " + EXECUTABLE + " " + cmd
-
- ret = execute_cmd(cmd, filename, lineno)
+ ret = execute_cmd(cmd, filename, lineno, netns)
#
# report failed test
@@ -103,7 +101,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
if res == "FAIL":
reason = "should fail: " + cmd
print_error(reason, filename, lineno)
- delete_rule(iptables, rule, filename, lineno)
+ delete_rule(iptables, rule, filename, lineno, netns)
return -1
matching = 0
@@ -126,7 +124,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
command = EXECUTABLE + " " + command
if netns:
- command = "ip netns exec ____iptables-container-test " + command
+ command = "ip netns exec " + netns + " " + command
args = tokens[1:]
proc = subprocess.Popen(command, shell=True,
@@ -140,7 +138,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
if proc.returncode == -11:
reason = "iptables-save segfaults: " + cmd
print_error(reason, filename, lineno)
- delete_rule(iptables, rule, filename, lineno)
+ delete_rule(iptables, rule, filename, lineno, netns)
return -1
# find the rule
@@ -149,7 +147,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
if res == "OK":
reason = "cannot find: " + iptables + " -I " + rule
print_error(reason, filename, lineno)
- delete_rule(iptables, rule, filename, lineno)
+ delete_rule(iptables, rule, filename, lineno, netns)
return -1
else:
# do not report this error
@@ -158,7 +156,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
if res != "OK":
reason = "should not match: " + cmd
print_error(reason, filename, lineno)
- delete_rule(iptables, rule, filename, lineno)
+ delete_rule(iptables, rule, filename, lineno, netns)
return -1
# Test "ip netns del NETNS" path with rules in place
@@ -167,7 +165,7 @@ def run_test(iptables, rule, rule_save, res, filename, lineno, netns):
return delete_rule(iptables, rule, filename, lineno)
-def execute_cmd(cmd, filename, lineno):
+def execute_cmd(cmd, filename, lineno = 0, netns = None):
'''
Executes a command, checking for segfaults and returning the command exit
code.
@@ -175,11 +173,15 @@ def execute_cmd(cmd, filename, lineno):
:param cmd: string with the command to be executed
:param filename: name of the file tested (used for print_error purposes)
:param lineno: line number being tested (used for print_error purposes)
+ :param netns: network namespace to run command in
'''
global log_file
if cmd.startswith('iptables ') or cmd.startswith('ip6tables ') or cmd.startswith('ebtables ') or cmd.startswith('arptables '):
cmd = EXECUTABLE + " " + cmd
+ if netns:
+ cmd = "ip netns exec " + netns + " " + cmd
+
print("command: {}".format(cmd), file=log_file)
ret = subprocess.call(cmd, shell=True, universal_newlines=True,
stderr=subprocess.STDOUT, stdout=log_file)
@@ -220,12 +222,163 @@ def variant_res(res, variant, alt_res=None):
return alt_res
return res_inverse[res]
+def fast_run_possible(filename):
+ '''
+ Keep things simple, run only for simple test files:
+ - no external commands
+ - no multiple tables
+ - no variant-specific results
+ '''
+ table = None
+ rulecount = 0
+ for line in open(filename):
+ if line[0] in ["#", ":"] or len(line.strip()) == 0:
+ continue
+ if line[0] == "*":
+ if table or rulecount > 0:
+ return False
+ table = line.rstrip()[1:]
+ if line[0] in ["@", "%"]:
+ return False
+ if len(line.split(";")) > 3:
+ return False
+ rulecount += 1
+
+ return True
+
+def run_test_file_fast(iptables, filename, netns):
+ '''
+ Run a test file, but fast
+
+ :param filename: name of the file with the test rules
+ :param netns: network namespace to perform test run in
+ '''
+
+ f = open(filename)
+
+ rules = {}
+ table = "filter"
+ chain_array = []
+ tests = 0
+
+ for lineno, line in enumerate(f):
+ if line[0] == "#" or len(line.strip()) == 0:
+ continue
+
+ if line[0] == "*":
+ table = line.rstrip()[1:]
+ continue
+
+ if line[0] == ":":
+ chain_array = line.rstrip()[1:].split(",")
+ continue
+
+ if len(chain_array) == 0:
+ return -1
+
+ tests += 1
+
+ for chain in chain_array:
+ item = line.split(";")
+ rule = chain + " " + item[0]
+
+ if item[1] == "=":
+ rule_save = chain + " " + item[0]
+ else:
+ rule_save = chain + " " + item[1]
+
+ if iptables == EBTABLES and rule_save.find('-j') < 0:
+ rule_save += " -j CONTINUE"
+
+ res = item[2].rstrip()
+ if res != "OK":
+ rule = chain + " -t " + table + " " + item[0]
+ ret = run_test(iptables, rule, rule_save,
+ res, filename, lineno + 1, netns)
+
+ if ret < 0:
+ return -1
+ continue
+
+ if not chain in rules.keys():
+ rules[chain] = []
+ rules[chain].append((rule, rule_save))
+
+ restore_data = ["*" + table]
+ out_expect = []
+ for chain in ["PREROUTING", "INPUT", "FORWARD", "OUTPUT", "POSTROUTING"]:
+ if not chain in rules.keys():
+ continue
+ for rule in rules[chain]:
+ restore_data.append("-A " + rule[0])
+ out_expect.append("-A " + rule[1])
+ restore_data.append("COMMIT")
+
+ out_expect = "\n".join(out_expect)
+
+ # load all rules via iptables_restore
+
+ command = EXECUTABLE + " " + iptables + "-restore"
+ if netns:
+ command = "ip netns exec " + netns + " " + command
+
+ for line in restore_data:
+ print(iptables + "-restore: " + line, file=log_file)
+
+ proc = subprocess.Popen(command, shell = True, text = True,
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE)
+ restore_data = "\n".join(restore_data) + "\n"
+ out, err = proc.communicate(input = restore_data)
+
+ if proc.returncode == -11:
+ reason = iptables + "-restore segfaults: " + cmd
+ print_error(reason, filename, lineno)
+ return -1
+
+ if proc.returncode != 0:
+ print("%s-restore returned %d: %s" % (iptables, proc.returncode, err),
+ file=log_file)
+ return -1
+
+ # find all rules in iptables_save output
+
+ command = EXECUTABLE + " " + iptables + "-save"
+ if netns:
+ command = "ip netns exec " + netns + " " + command
+
+ proc = subprocess.Popen(command, shell = True,
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE)
+ out, err = proc.communicate()
+
+ if proc.returncode == -11:
+ reason = iptables + "-save segfaults: " + cmd
+ print_error(reason, filename, lineno)
+ return -1
+
+ cmd = iptables + " -F -t " + table
+ execute_cmd(cmd, filename, 0, netns)
+
+ out = out.decode('utf-8').rstrip()
+ if out.find(out_expect) < 0:
+ msg = ["dumps differ!"]
+ msg.extend(["expect: " + l for l in out_expect.split("\n")])
+ msg.extend(["got: " + l for l in out.split("\n")
+ if not l[0] in ['*', ':', '#']])
+ print("\n".join(msg), file=log_file)
+ return -1
+
+ return tests
def run_test_file(filename, netns):
'''
Runs a test file
:param filename: name of the file with the test rules
+ :param netns: network namespace to perform test run in
'''
#
# if this is not a test file, skip.
@@ -253,6 +406,14 @@ def run_test_file(filename, netns):
# default to iptables if not known prefix
iptables = IPTABLES
+ fast_failed = False
+ if fast_run_possible(filename):
+ tests = run_test_file_fast(iptables, filename, netns)
+ if tests > 0:
+ print(filename + ": " + maybe_colored('green', "OK", STDOUT_IS_TTY))
+ return tests, tests
+ fast_failed = True
+
f = open(filename)
tests = 0
@@ -262,7 +423,7 @@ def run_test_file(filename, netns):
total_test_passed = True
if netns:
- execute_cmd("ip netns add ____iptables-container-test", filename, 0)
+ execute_cmd("ip netns add " + netns, filename)
for lineno, line in enumerate(f):
if line[0] == "#" or len(line.strip()) == 0:
@@ -272,20 +433,11 @@ def run_test_file(filename, netns):
chain_array = line.rstrip()[1:].split(",")
continue
- # external non-iptables invocation, executed as is.
- if line[0] == "@":
- external_cmd = line.rstrip()[1:]
- if netns:
- external_cmd = "ip netns exec ____iptables-container-test " + external_cmd
- execute_cmd(external_cmd, filename, lineno)
- continue
-
- # external iptables invocation, executed as is.
- if line[0] == "%":
+ # external command invocation, executed as is.
+ # detects iptables commands to prefix with EXECUTABLE automatically
+ if line[0] in ["@", "%"]:
external_cmd = line.rstrip()[1:]
- if netns:
- external_cmd = "ip netns exec ____iptables-container-test " + EXECUTABLE + " " + external_cmd
- execute_cmd(external_cmd, filename, lineno)
+ execute_cmd(external_cmd, filename, lineno, netns)
continue
if line[0] == "*":
@@ -334,9 +486,12 @@ def run_test_file(filename, netns):
passed += 1
if netns:
- execute_cmd("ip netns del ____iptables-container-test", filename, 0)
+ execute_cmd("ip netns del " + netns, filename)
if total_test_passed:
- print(filename + ": " + maybe_colored('green', "OK", STDOUT_IS_TTY))
+ suffix = ""
+ if fast_failed:
+ suffix = maybe_colored('red', " but fast mode failed!", STDOUT_IS_TTY)
+ print(filename + ": " + maybe_colored('green', "OK", STDOUT_IS_TTY) + suffix)
f.close()
return tests, passed
@@ -400,7 +555,8 @@ def main():
help='Check for missing tests')
parser.add_argument('-n', '--nftables', action='store_true',
help='Test iptables-over-nftables')
- parser.add_argument('-N', '--netns', action='store_true',
+ parser.add_argument('-N', '--netns', action='store_const',
+ const='____iptables-container-test',
help='Test netnamespace path')
parser.add_argument('--no-netns', action='store_true',
help='Do not run testsuite in own network namespace')
@@ -413,10 +569,13 @@ def main():
show_missing()
return
- global EXECUTABLE
- EXECUTABLE = "xtables-legacy-multi"
+ variants = []
+ if args.legacy:
+ variants.append("legacy")
if args.nftables:
- EXECUTABLE = "xtables-nft-multi"
+ variants.append("nft")
+ if len(variants) == 0:
+ variants = [ "legacy", "nft" ]
if os.getuid() != 0:
print("You need to be root to run this, sorry", file=sys.stderr)
@@ -431,36 +590,51 @@ def main():
os.putenv("PATH", "%s/iptables:%s" % (os.path.abspath(os.path.curdir),
os.getenv("PATH")))
- test_files = 0
- tests = 0
- passed = 0
-
- # setup global var log file
- global log_file
- try:
- log_file = open(LOGFILE, 'w')
- except IOError:
- print("Couldn't open log file %s" % LOGFILE, file=sys.stderr)
- return
-
- if args.filename:
- file_list = args.filename
- else:
- file_list = [os.path.join(EXTENSIONS_PATH, i)
- for i in os.listdir(EXTENSIONS_PATH)
- if i.endswith('.t')]
- file_list.sort()
-
- for filename in file_list:
- file_tests, file_passed = run_test_file(filename, args.netns)
- if file_tests:
- tests += file_tests
- passed += file_passed
- test_files += 1
-
- print("%d test files, %d unit tests, %d passed" % (test_files, tests, passed))
- return passed - tests
-
+ total_test_files = 0
+ total_passed = 0
+ total_tests = 0
+ for variant in variants:
+ global EXECUTABLE
+ EXECUTABLE = "xtables-" + variant + "-multi"
+
+ test_files = 0
+ tests = 0
+ passed = 0
+
+ # setup global var log file
+ global log_file
+ try:
+ log_file = open(LOGFILE, 'w')
+ except IOError:
+ print("Couldn't open log file %s" % LOGFILE, file=sys.stderr)
+ return
+
+ if args.filename:
+ file_list = args.filename
+ else:
+ file_list = [os.path.join(EXTENSIONS_PATH, i)
+ for i in os.listdir(EXTENSIONS_PATH)
+ if i.endswith('.t')]
+ file_list.sort()
+
+ for filename in file_list:
+ file_tests, file_passed = run_test_file(filename, args.netns)
+ if file_tests:
+ tests += file_tests
+ passed += file_passed
+ test_files += 1
+
+ print("%s: %d test files, %d unit tests, %d passed"
+ % (variant, test_files, tests, passed))
+
+ total_passed += passed
+ total_tests += tests
+ total_test_files = max(total_test_files, test_files)
+
+ if len(variants) > 1:
+ print("total: %d test files, %d unit tests, %d passed"
+ % (total_test_files, total_tests, total_passed))
+ return total_passed - total_tests
if __name__ == '__main__':
sys.exit(main())
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index 75984cc1..345af451 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -122,6 +122,9 @@ print_match(const struct xt_entry_match *m,
printf("%s%s ", match->name, unsupported_rev);
else
printf("%s ", match->name);
+
+ if (match->next == match)
+ free(match);
} else {
if (name[0])
printf("UNKNOWN match `%s' ", name);
@@ -179,6 +182,9 @@ print_firewall(const struct ip6t_entry *fw,
tg->print(&fw->ipv6, t, format & FMT_NUMERIC);
else if (target->print)
printf(" %s%s", target->name, unsupported_rev);
+
+ if (target->next == target)
+ free(target);
} else if (t->u.target_size != sizeof(*t))
printf("[%u bytes of unknown target data] ",
(unsigned int)(t->u.target_size - sizeof(*t)));
@@ -277,40 +283,6 @@ insert_entry(const xt_chainlabel chain,
return ret;
}
-static unsigned char *
-make_delete_mask(const struct xtables_rule_match *matches,
- const struct xtables_target *target)
-{
- /* Establish mask for comparison */
- unsigned int size;
- const struct xtables_rule_match *matchp;
- unsigned char *mask, *mptr;
-
- size = sizeof(struct ip6t_entry);
- for (matchp = matches; matchp; matchp = matchp->next)
- size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
-
- mask = xtables_calloc(1, size
- + XT_ALIGN(sizeof(struct xt_entry_target))
- + target->size);
-
- memset(mask, 0xFF, sizeof(struct ip6t_entry));
- mptr = mask + sizeof(struct ip6t_entry);
-
- for (matchp = matches; matchp; matchp = matchp->next) {
- memset(mptr, 0xFF,
- XT_ALIGN(sizeof(struct xt_entry_match))
- + matchp->match->userspacesize);
- mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
- }
-
- memset(mptr, 0xFF,
- XT_ALIGN(sizeof(struct xt_entry_target))
- + target->userspacesize);
-
- return mask;
-}
-
static int
delete_entry(const xt_chainlabel chain,
struct ip6t_entry *fw,
@@ -329,7 +301,7 @@ delete_entry(const xt_chainlabel chain,
int ret = 1;
unsigned char *mask;
- mask = make_delete_mask(matches, target);
+ mask = make_delete_mask(matches, target, sizeof(*fw));
for (i = 0; i < nsaddrs; i++) {
fw->ipv6.src = saddrs[i];
fw->ipv6.smsk = smasks[i];
@@ -359,7 +331,7 @@ check_entry(const xt_chainlabel chain, struct ip6t_entry *fw,
int ret = 1;
unsigned char *mask;
- mask = make_delete_mask(matches, target);
+ mask = make_delete_mask(matches, target, sizeof(fw));
for (i = 0; i < nsaddrs; i++) {
fw->ipv6.src = saddrs[i];
fw->ipv6.smsk = smasks[i];
@@ -800,13 +772,12 @@ int do_command6(int argc, char *argv[], char **table,
#ifdef IP6T_F_GOTO
if (cs.fw6.ipv6.flags & IP6T_F_GOTO)
xtables_error(PARAMETER_PROBLEM,
- "goto '%s' is not a chain\n",
- cs.jumpto);
+ "goto '%s' is not a chain",
+ cs.jumpto);
#endif
xtables_find_target(cs.jumpto, XTF_LOAD_MUST_SUCCEED);
} else {
e = generate_entry(&cs.fw6, cs.matches, cs.target->t);
- free(cs.target->t);
}
}
@@ -908,7 +879,7 @@ int do_command6(int argc, char *argv[], char **table,
if (verbose > 1)
dump_entries6(*handle);
- xtables_rule_matches_free(&cs.matches);
+ xtables_clear_iptables_command_state(&cs);
if (e != NULL) {
free(e);
diff --git a/iptables/iptables-restore.c b/iptables/iptables-restore.c
index 4410a587..6f7ddf93 100644
--- a/iptables/iptables-restore.c
+++ b/iptables/iptables-restore.c
@@ -78,8 +78,9 @@ create_handle(const struct iptables_restore_cb *cb, const char *tablename)
}
if (!handle)
- xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize "
- "table '%s'\n", xt_params->program_name, tablename);
+ xtables_error(PARAMETER_PROBLEM,
+ "%s: unable to initialize table '%s'",
+ xt_params->program_name, tablename);
return handle;
}
@@ -184,12 +185,12 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
if (!testing) {
DEBUGP("Calling commit\n");
ret = cb->ops->commit(handle);
- cb->ops->free(handle);
- handle = NULL;
} else {
DEBUGP("Not calling commit, testing\n");
ret = 1;
}
+ cb->ops->free(handle);
+ handle = NULL;
/* Done with the current table, release the lock. */
if (lock >= 0) {
@@ -209,8 +210,8 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
DEBUGP("line %u, table '%s'\n", line, table);
if (!table)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u table name invalid\n",
- xt_params->program_name, line);
+ "%s: line %u table name invalid",
+ xt_params->program_name, line);
strncpy(curtable, table, XT_TABLE_MAXNAMELEN);
curtable[XT_TABLE_MAXNAMELEN] = '\0';
@@ -249,8 +250,8 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u chain name invalid\n",
- xt_params->program_name, line);
+ "%s: line %u chain name invalid",
+ xt_params->program_name, line);
if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
xtables_error(PARAMETER_PROBLEM,
@@ -263,16 +264,14 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
DEBUGP("Flushing existing user defined chain '%s'\n", chain);
if (!cb->ops->flush_entries(chain, handle))
xtables_error(PARAMETER_PROBLEM,
- "error flushing chain "
- "'%s':%s\n", chain,
- strerror(errno));
+ "error flushing chain '%s':%s",
+ chain, strerror(errno));
} else {
DEBUGP("Creating new chain '%s'\n", chain);
if (!cb->ops->create_chain(chain, handle))
xtables_error(PARAMETER_PROBLEM,
- "error creating chain "
- "'%s':%s\n", chain,
- strerror(errno));
+ "error creating chain '%s':%s",
+ chain, strerror(errno));
}
}
@@ -280,8 +279,8 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u policy invalid\n",
- xt_params->program_name, line);
+ "%s: line %u policy invalid",
+ xt_params->program_name, line);
if (strcmp(policy, "-") != 0) {
struct xt_counters count = {};
@@ -292,8 +291,8 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
if (!ctrs || !parse_counters(ctrs, &count))
xtables_error(PARAMETER_PROBLEM,
- "invalid policy counters "
- "for chain '%s'\n", chain);
+ "invalid policy counters for chain '%s'",
+ chain);
}
DEBUGP("Setting policy of chain %s to %s\n",
@@ -302,10 +301,9 @@ ip46tables_restore_main(const struct iptables_restore_cb *cb,
if (!cb->ops->set_policy(chain, policy, &count,
handle))
xtables_error(OTHER_PROBLEM,
- "Can't set policy `%s'"
- " on `%s' line %u: %s\n",
- policy, chain, line,
- cb->ops->strerror(errno));
+ "Can't set policy `%s' on `%s' line %u: %s",
+ policy, chain, line,
+ cb->ops->strerror(errno));
}
xtables_announce_chain(chain);
diff --git a/iptables/iptables-save.c b/iptables/iptables-save.c
index a8dded63..094adf22 100644
--- a/iptables/iptables-save.c
+++ b/iptables/iptables-save.c
@@ -61,8 +61,7 @@ for_each_table(int (*func)(struct iptables_save_cb *cb, const char *tablename),
while (fgets(tablename, sizeof(tablename), procfile)) {
if (tablename[strlen(tablename) - 1] != '\n')
xtables_error(OTHER_PROBLEM,
- "Badly formed tablename `%s'\n",
- tablename);
+ "Badly formed tablename `%s'", tablename);
tablename[strlen(tablename) - 1] = '\0';
ret &= func(cb, tablename);
}
@@ -85,7 +84,7 @@ static int do_output(struct iptables_save_cb *cb, const char *tablename)
h = cb->ops->init(tablename);
}
if (!h)
- xtables_error(OTHER_PROBLEM, "Cannot initialize: %s\n",
+ xtables_error(OTHER_PROBLEM, "Cannot initialize: %s",
cb->ops->strerror(errno));
time_t now = time(NULL);
diff --git a/iptables/iptables-xml.c b/iptables/iptables-xml.c
index 6cf059fb..396c0a12 100644
--- a/iptables/iptables-xml.c
+++ b/iptables/iptables-xml.c
@@ -210,8 +210,8 @@ saveChain(char *chain, char *policy, struct xt_counters *ctr)
{
if (nextChain >= maxChains)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u chain name invalid\n",
- prog_name, line);
+ "%s: line %u chain name invalid",
+ prog_name, line);
chains[nextChain].chain = xtables_strdup(chain);
chains[nextChain].policy = xtables_strdup(policy);
@@ -225,13 +225,13 @@ finishChains(void)
{
int c;
- for (c = 0; c < nextChain; c++)
- if (!chains[c].created) {
+ for (c = 0; c < nextChain; c++) {
+ if (!chains[c].created)
openChain(chains[c].chain, chains[c].policy,
&(chains[c].count), '/');
- free(chains[c].chain);
- free(chains[c].policy);
- }
+ free(chains[c].chain);
+ free(chains[c].policy);
+ }
nextChain = 0;
}
@@ -610,8 +610,8 @@ iptables_xml_main(int argc, char *argv[])
DEBUGP("line %u, table '%s'\n", line, table);
if (!table)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u table name invalid\n",
- prog_name, line);
+ "%s: line %u table name invalid",
+ prog_name, line);
openTable(table);
@@ -626,8 +626,8 @@ iptables_xml_main(int argc, char *argv[])
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u chain name invalid\n",
- prog_name, line);
+ "%s: line %u chain name invalid",
+ prog_name, line);
DEBUGP("Creating new chain '%s'\n", chain);
@@ -635,8 +635,8 @@ iptables_xml_main(int argc, char *argv[])
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u policy invalid\n",
- prog_name, line);
+ "%s: line %u policy invalid",
+ prog_name, line);
ctrs = strtok(NULL, " \t\n");
parse_counters(ctrs, &count);
diff --git a/iptables/iptables.c b/iptables/iptables.c
index e5207ba1..6f7b3476 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -122,6 +122,9 @@ print_match(const struct xt_entry_match *m,
printf("%s%s ", match->name, unsupported_rev);
else
printf("%s ", match->name);
+
+ if (match->next == match)
+ free(match);
} else {
if (name[0])
printf("UNKNOWN match `%s' ", name);
@@ -178,6 +181,9 @@ print_firewall(const struct ipt_entry *fw,
tg->print(&fw->ip, t, format & FMT_NUMERIC);
else if (target->print)
printf(" %s%s", target->name, unsupported_rev);
+
+ if (target->next == target)
+ free(target);
} else if (t->u.target_size != sizeof(*t))
printf("[%u bytes of unknown target data] ",
(unsigned int)(t->u.target_size - sizeof(*t)));
@@ -276,40 +282,6 @@ insert_entry(const xt_chainlabel chain,
return ret;
}
-static unsigned char *
-make_delete_mask(const struct xtables_rule_match *matches,
- const struct xtables_target *target)
-{
- /* Establish mask for comparison */
- unsigned int size;
- const struct xtables_rule_match *matchp;
- unsigned char *mask, *mptr;
-
- size = sizeof(struct ipt_entry);
- for (matchp = matches; matchp; matchp = matchp->next)
- size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
-
- mask = xtables_calloc(1, size
- + XT_ALIGN(sizeof(struct xt_entry_target))
- + target->size);
-
- memset(mask, 0xFF, sizeof(struct ipt_entry));
- mptr = mask + sizeof(struct ipt_entry);
-
- for (matchp = matches; matchp; matchp = matchp->next) {
- memset(mptr, 0xFF,
- XT_ALIGN(sizeof(struct xt_entry_match))
- + matchp->match->userspacesize);
- mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
- }
-
- memset(mptr, 0xFF,
- XT_ALIGN(sizeof(struct xt_entry_target))
- + target->userspacesize);
-
- return mask;
-}
-
static int
delete_entry(const xt_chainlabel chain,
struct ipt_entry *fw,
@@ -328,7 +300,7 @@ delete_entry(const xt_chainlabel chain,
int ret = 1;
unsigned char *mask;
- mask = make_delete_mask(matches, target);
+ mask = make_delete_mask(matches, target, sizeof(*fw));
for (i = 0; i < nsaddrs; i++) {
fw->ip.src.s_addr = saddrs[i].s_addr;
fw->ip.smsk.s_addr = smasks[i].s_addr;
@@ -358,7 +330,7 @@ check_entry(const xt_chainlabel chain, struct ipt_entry *fw,
int ret = 1;
unsigned char *mask;
- mask = make_delete_mask(matches, target);
+ mask = make_delete_mask(matches, target, sizeof(*fw));
for (i = 0; i < nsaddrs; i++) {
fw->ip.src.s_addr = saddrs[i].s_addr;
fw->ip.smsk.s_addr = smasks[i].s_addr;
@@ -795,13 +767,12 @@ int do_command4(int argc, char *argv[], char **table,
#ifdef IPT_F_GOTO
if (cs.fw.ip.flags & IPT_F_GOTO)
xtables_error(PARAMETER_PROBLEM,
- "goto '%s' is not a chain\n",
- cs.jumpto);
+ "goto '%s' is not a chain",
+ cs.jumpto);
#endif
xtables_find_target(cs.jumpto, XTF_LOAD_MUST_SUCCEED);
} else {
e = generate_entry(&cs.fw, cs.matches, cs.target->t);
- free(cs.target->t);
}
}
@@ -903,7 +874,7 @@ int do_command4(int argc, char *argv[], char **table,
if (verbose > 1)
dump_entries(*handle);
- xtables_rule_matches_free(&cs.matches);
+ xtables_clear_iptables_command_state(&cs);
if (e != NULL) {
free(e);
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index e6e4d2d8..d670cbe6 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -160,25 +160,30 @@ static int nft_arp_add(struct nft_handle *h, struct nftnl_rule *r,
return ret;
}
-static void nft_arp_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
+static void nft_arp_parse_meta(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
+ struct nftnl_expr *e,
struct iptables_command_state *cs)
{
struct arpt_entry *fw = &cs->arp;
uint8_t flags = 0;
- parse_meta(ctx, e, ctx->meta.key, fw->arp.iniface, fw->arp.iniface_mask,
+ if (parse_meta(ctx, e, reg->meta_dreg.key, fw->arp.iniface, fw->arp.iniface_mask,
fw->arp.outiface, fw->arp.outiface_mask,
- &flags);
+ &flags) == 0) {
+ fw->arp.invflags |= flags;
+ return;
+ }
- fw->arp.invflags |= flags;
+ ctx->errmsg = "Unknown arp meta key";
}
-static void parse_mask_ipv4(struct nft_xt_ctx *ctx, struct in_addr *mask)
+static void parse_mask_ipv4(const struct nft_xt_ctx_reg *reg, struct in_addr *mask)
{
- mask->s_addr = ctx->bitwise.mask[0];
+ mask->s_addr = reg->bitwise.mask[0];
}
-static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
+static bool nft_arp_parse_devaddr(const struct nft_xt_ctx_reg *reg,
struct nftnl_expr *e,
struct arpt_devaddr_info *info)
{
@@ -192,18 +197,17 @@ static bool nft_arp_parse_devaddr(struct nft_xt_ctx *ctx,
get_cmp_data(e, info->addr, ETH_ALEN, &inv);
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- memcpy(info->mask, ctx->bitwise.mask, ETH_ALEN);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ memcpy(info->mask, reg->bitwise.mask, ETH_ALEN);
+ else
memset(info->mask, 0xff,
- min(ctx->payload.len, ETH_ALEN));
- }
+ min(reg->payload.len, ETH_ALEN));
return inv;
}
static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
@@ -213,7 +217,7 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
uint8_t ar_hln;
bool inv;
- switch (ctx->payload.offset) {
+ switch (reg->payload.offset) {
case offsetof(struct arphdr, ar_hrd):
get_cmp_data(e, &ar_hrd, sizeof(ar_hrd), &inv);
fw->arp.arhrd = ar_hrd;
@@ -243,43 +247,39 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
fw->arp.invflags |= IPT_INV_ARPOP;
break;
default:
- if (ctx->payload.offset == sizeof(struct arphdr)) {
- if (nft_arp_parse_devaddr(ctx, e, &fw->arp.src_devaddr))
+ if (reg->payload.offset == sizeof(struct arphdr)) {
+ if (nft_arp_parse_devaddr(reg, e, &fw->arp.src_devaddr))
fw->arp.invflags |= IPT_INV_SRCDEVADDR;
- } else if (ctx->payload.offset == sizeof(struct arphdr) +
+ } else if (reg->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln) {
get_cmp_data(e, &addr, sizeof(addr), &inv);
fw->arp.src.s_addr = addr.s_addr;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- parse_mask_ipv4(ctx, &fw->arp.smsk);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ parse_mask_ipv4(reg, &fw->arp.smsk);
+ else
memset(&fw->arp.smsk, 0xff,
- min(ctx->payload.len,
+ min(reg->payload.len,
sizeof(struct in_addr)));
- }
if (inv)
fw->arp.invflags |= IPT_INV_SRCIP;
- } else if (ctx->payload.offset == sizeof(struct arphdr) +
+ } else if (reg->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln +
sizeof(struct in_addr)) {
- if (nft_arp_parse_devaddr(ctx, e, &fw->arp.tgt_devaddr))
+ if (nft_arp_parse_devaddr(reg, e, &fw->arp.tgt_devaddr))
fw->arp.invflags |= IPT_INV_TGTDEVADDR;
- } else if (ctx->payload.offset == sizeof(struct arphdr) +
+ } else if (reg->payload.offset == sizeof(struct arphdr) +
fw->arp.arhln +
sizeof(struct in_addr) +
fw->arp.arhln) {
get_cmp_data(e, &addr, sizeof(addr), &inv);
fw->arp.tgt.s_addr = addr.s_addr;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- parse_mask_ipv4(ctx, &fw->arp.tmsk);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ parse_mask_ipv4(reg, &fw->arp.tmsk);
+ else
memset(&fw->arp.tmsk, 0xff,
- min(ctx->payload.len,
+ min(reg->payload.len,
sizeof(struct in_addr)));
- }
if (inv)
fw->arp.invflags |= IPT_INV_DSTIP;
@@ -490,7 +490,7 @@ nft_arp_print_rule(struct nft_handle *h, struct nftnl_rule *r,
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
- nft_clear_iptables_command_state(&cs);
+ xtables_clear_iptables_command_state(&cs);
}
static bool nft_arp_is_same(const struct iptables_command_state *cs_a,
@@ -787,7 +787,7 @@ struct nft_family_ops nft_family_ops_arp = {
},
.rule_to_cs = nft_rule_to_iptables_command_state,
.init_cs = nft_arp_init_cs,
- .clear_cs = nft_clear_iptables_command_state,
+ .clear_cs = xtables_clear_iptables_command_state,
.parse_target = nft_ipv46_parse_target,
.add_entry = nft_arp_add_entry,
.delete_entry = nft_arp_delete_entry,
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index 106bcc72..e223d197 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -100,6 +100,18 @@ static int _add_action(struct nftnl_rule *r, struct iptables_command_state *cs)
return add_action(r, cs, false);
}
+static int
+nft_bridge_add_match(struct nft_handle *h, const struct ebt_entry *fw,
+ struct nftnl_rule *r, struct xt_entry_match *m)
+{
+ if (!strcmp(m->u.user.name, "802_3") &&
+ !(fw->bitmask & EBT_802_3))
+ xtables_error(PARAMETER_PROBLEM,
+ "For 802.3 DSAP/SSAP filtering the protocol must be LENGTH");
+
+ return add_match(h, r, m);
+}
+
static int nft_bridge_add(struct nft_handle *h,
struct nftnl_rule *r,
struct iptables_command_state *cs)
@@ -143,19 +155,26 @@ static int nft_bridge_add(struct nft_handle *h,
}
if ((fw->bitmask & EBT_NOPROTO) == 0) {
+ uint16_t ethproto = fw->ethproto;
uint8_t reg;
op = nft_invflags2cmp(fw->invflags, EBT_IPROTO);
add_payload(h, r, offsetof(struct ethhdr, h_proto), 2,
NFT_PAYLOAD_LL_HEADER, &reg);
- add_cmp_u16(r, fw->ethproto, op, reg);
+
+ if (fw->bitmask & EBT_802_3) {
+ op = (op == NFT_CMP_EQ ? NFT_CMP_LT : NFT_CMP_GTE);
+ ethproto = htons(0x0600);
+ }
+
+ add_cmp_u16(r, ethproto, op, reg);
}
add_compat(r, fw->ethproto, fw->invflags & EBT_IPROTO);
for (iter = cs->match_list; iter; iter = iter->next) {
if (iter->ismatch) {
- if (add_match(h, r, iter->u.match->m))
+ if (nft_bridge_add_match(h, fw, r, iter->u.match->m))
break;
} else {
if (add_target(r, iter->u.watcher->t))
@@ -170,6 +189,7 @@ static int nft_bridge_add(struct nft_handle *h,
}
static void nft_bridge_parse_meta(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
@@ -177,9 +197,17 @@ static void nft_bridge_parse_meta(struct nft_xt_ctx *ctx,
uint8_t invflags = 0;
char iifname[IFNAMSIZ] = {}, oifname[IFNAMSIZ] = {};
- parse_meta(ctx, e, ctx->meta.key, iifname, NULL, oifname, NULL, &invflags);
+ switch (reg->meta_dreg.key) {
+ case NFT_META_PROTOCOL:
+ return;
+ }
+
+ if (parse_meta(ctx, e, reg->meta_dreg.key, iifname, NULL, oifname, NULL, &invflags) < 0) {
+ ctx->errmsg = "unknown meta key";
+ return;
+ }
- switch (ctx->meta.key) {
+ switch (reg->meta_dreg.key) {
case NFT_META_BRI_IIFNAME:
if (invflags & IPT_INV_VIA_IN)
cs->eb.invflags |= EBT_ILOGICALIN;
@@ -201,21 +229,24 @@ static void nft_bridge_parse_meta(struct nft_xt_ctx *ctx,
snprintf(fw->out, sizeof(fw->out), "%s", oifname);
break;
default:
+ ctx->errmsg = "unknown bridge meta key";
break;
}
}
static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
struct ebt_entry *fw = &cs->eb;
unsigned char addr[ETH_ALEN];
unsigned short int ethproto;
+ uint8_t op;
bool inv;
int i;
- switch (ctx->payload.offset) {
+ switch (reg->payload.offset) {
case offsetof(struct ethhdr, h_dest):
get_cmp_data(e, addr, sizeof(addr), &inv);
for (i = 0; i < ETH_ALEN; i++)
@@ -223,13 +254,11 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
if (inv)
fw->invflags |= EBT_IDEST;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- memcpy(fw->destmsk, ctx->bitwise.mask, ETH_ALEN);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ memcpy(fw->destmsk, reg->bitwise.mask, ETH_ALEN);
+ else
memset(&fw->destmsk, 0xff,
- min(ctx->payload.len, ETH_ALEN));
- }
+ min(reg->payload.len, ETH_ALEN));
fw->bitmask |= EBT_IDEST;
break;
case offsetof(struct ethhdr, h_source):
@@ -238,18 +267,22 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
fw->sourcemac[i] = addr[i];
if (inv)
fw->invflags |= EBT_ISOURCE;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- memcpy(fw->sourcemsk, ctx->bitwise.mask, ETH_ALEN);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ memcpy(fw->sourcemsk, reg->bitwise.mask, ETH_ALEN);
+ else
memset(&fw->sourcemsk, 0xff,
- min(ctx->payload.len, ETH_ALEN));
- }
+ min(reg->payload.len, ETH_ALEN));
fw->bitmask |= EBT_ISOURCE;
break;
case offsetof(struct ethhdr, h_proto):
- get_cmp_data(e, &ethproto, sizeof(ethproto), &inv);
- fw->ethproto = ethproto;
+ __get_cmp_data(e, &ethproto, sizeof(ethproto), &op);
+ if (ethproto == htons(0x0600)) {
+ fw->bitmask |= EBT_802_3;
+ inv = (op == NFT_CMP_GTE);
+ } else {
+ fw->ethproto = ethproto;
+ inv = (op == NFT_CMP_NEQ);
+ }
if (inv)
fw->invflags |= EBT_IPROTO;
fw->bitmask &= ~EBT_NOPROTO;
@@ -294,49 +327,74 @@ lookup_check_iphdr_payload(uint32_t base, uint32_t offset, uint32_t len)
/* Make sure previous payload expression(s) is/are consistent and extract if
* matching on source or destination address and if matching on MAC and IP or
* only MAC address. */
-static int lookup_analyze_payloads(const struct nft_xt_ctx *ctx,
+static int lookup_analyze_payloads(struct nft_xt_ctx *ctx,
+ enum nft_registers sreg,
+ uint32_t key_len,
bool *dst, bool *ip)
{
+ const struct nft_xt_ctx_reg *reg;
int val, val2 = -1;
- if (ctx->flags & NFT_XT_CTX_PREV_PAYLOAD) {
- val = lookup_check_ether_payload(ctx->prev_payload.base,
- ctx->prev_payload.offset,
- ctx->prev_payload.len);
+ reg = nft_xt_ctx_get_sreg(ctx, sreg);
+ if (!reg)
+ return -1;
+
+ if (reg->type != NFT_XT_REG_PAYLOAD) {
+ ctx->errmsg = "lookup reg is not payload type";
+ return -1;
+ }
+
+ switch (key_len) {
+ case 12: /* ether + ipv4addr */
+ val = lookup_check_ether_payload(reg->payload.base,
+ reg->payload.offset,
+ reg->payload.len);
if (val < 0) {
DEBUGP("unknown payload base/offset/len %d/%d/%d\n",
- ctx->prev_payload.base, ctx->prev_payload.offset,
- ctx->prev_payload.len);
+ reg->payload.base, reg->payload.offset,
+ reg->payload.len);
return -1;
}
- if (!(ctx->flags & NFT_XT_CTX_PAYLOAD)) {
- DEBUGP("Previous but no current payload?\n");
+
+ sreg = nft_get_next_reg(sreg, ETH_ALEN);
+
+ reg = nft_xt_ctx_get_sreg(ctx, sreg);
+ if (!reg) {
+ ctx->errmsg = "next lookup register is invalid";
+ return -1;
+ }
+
+ if (reg->type != NFT_XT_REG_PAYLOAD) {
+ ctx->errmsg = "next lookup reg is not payload type";
return -1;
}
- val2 = lookup_check_iphdr_payload(ctx->payload.base,
- ctx->payload.offset,
- ctx->payload.len);
+
+ val2 = lookup_check_iphdr_payload(reg->payload.base,
+ reg->payload.offset,
+ reg->payload.len);
if (val2 < 0) {
DEBUGP("unknown payload base/offset/len %d/%d/%d\n",
- ctx->payload.base, ctx->payload.offset,
- ctx->payload.len);
+ reg->payload.base, reg->payload.offset,
+ reg->payload.len);
return -1;
} else if (val != val2) {
DEBUGP("mismatching payload match offsets\n");
return -1;
}
- } else if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
- val = lookup_check_ether_payload(ctx->payload.base,
- ctx->payload.offset,
- ctx->payload.len);
+ break;
+ case 6: /* ether */
+ val = lookup_check_ether_payload(reg->payload.base,
+ reg->payload.offset,
+ reg->payload.len);
if (val < 0) {
DEBUGP("unknown payload base/offset/len %d/%d/%d\n",
- ctx->payload.base, ctx->payload.offset,
- ctx->payload.len);
+ reg->payload.base, reg->payload.offset,
+ reg->payload.len);
return -1;
}
- } else {
- DEBUGP("unknown LHS of lookup expression\n");
+ break;
+ default:
+ ctx->errmsg = "unsupported lookup key length";
return -1;
}
@@ -413,14 +471,17 @@ static void nft_bridge_parse_lookup(struct nft_xt_ctx *ctx,
size_t poff, size;
uint32_t cnt;
- if (lookup_analyze_payloads(ctx, &is_dst, &have_ip))
- return;
-
s = set_from_lookup_expr(ctx, e);
if (!s)
xtables_error(OTHER_PROBLEM,
"BUG: lookup expression references unknown set");
+ if (lookup_analyze_payloads(ctx,
+ nftnl_expr_get_u32(e, NFTNL_EXPR_LOOKUP_SREG),
+ nftnl_set_get_u32(s, NFTNL_SET_KEY_LEN),
+ &is_dst, &have_ip))
+ return;
+
cnt = nftnl_set_get_u32(s, NFTNL_SET_DESC_SIZE);
for (ematch = ctx->cs->match_list; ematch; ematch = ematch->next) {
@@ -468,8 +529,6 @@ static void nft_bridge_parse_lookup(struct nft_xt_ctx *ctx,
if (set_elems_to_among_pairs(among_data->pairs + poff, s, cnt))
xtables_error(OTHER_PROBLEM,
"ebtables among pair parsing failed");
-
- ctx->flags &= ~(NFT_XT_CTX_PAYLOAD | NFT_XT_CTX_PREV_PAYLOAD);
}
static void parse_watcher(void *object, struct ebt_match **match_list,
@@ -509,12 +568,12 @@ static void nft_bridge_parse_target(struct xtables_target *t,
cs->jumpto = t->name;
}
-static void nft_rule_to_ebtables_command_state(struct nft_handle *h,
+static bool nft_rule_to_ebtables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
struct iptables_command_state *cs)
{
cs->eb.bitmask = EBT_NOPROTO;
- nft_rule_to_iptables_command_state(h, r, cs);
+ return nft_rule_to_iptables_command_state(h, r, cs);
}
static void print_iface(const char *option, const char *name, bool invert)
@@ -587,7 +646,7 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
printf("! ");
if (bitmask & EBT_802_3) {
- printf("length ");
+ printf("Length ");
return;
}
@@ -601,7 +660,7 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask)
static void __nft_bridge_save_rule(const struct iptables_command_state *cs,
unsigned int format)
{
- if (cs->eb.ethproto)
+ if (!(cs->eb.bitmask & EBT_NOPROTO))
print_protocol(cs->eb.ethproto, cs->eb.invflags & EBT_IPROTO,
cs->eb.bitmask);
if (cs->eb.bitmask & EBT_ISOURCE)
@@ -732,7 +791,6 @@ static int xlate_ebmatches(const struct iptables_command_state *cs, struct xt_xl
struct xt_xlate_mt_params mt_params = {
.ip = (const void *)&cs->eb,
.numeric = numeric,
- .escape_quotes = false,
.match = matchp->m,
};
@@ -745,7 +803,6 @@ static int xlate_ebmatches(const struct iptables_command_state *cs, struct xt_xl
struct xt_xlate_tg_params wt_params = {
.ip = (const void *)&cs->eb,
.numeric = numeric,
- .escape_quotes = false,
.target = watcherp->t,
};
@@ -776,7 +833,6 @@ static int xlate_ebaction(const struct iptables_command_state *cs, struct xt_xla
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
xt_xlate_add(xl, " return");
else if (cs->target->xlate) {
- xt_xlate_add(xl, " ");
struct xt_xlate_tg_params params = {
.ip = (const void *)&cs->eb,
.target = cs->target->t,
@@ -810,20 +866,18 @@ static void nft_bridge_xlate_mac(struct xt_xlate *xl, const char *type, bool inv
xt_xlate_add(xl, "ether %s %s", type, invert ? "!= " : "");
- xlate_mac(xl, mac);
-
if (memcmp(mask, one_msk, ETH_ALEN)) {
int i;
- xt_xlate_add(xl, " and ");
+ xt_xlate_add(xl, "and");
xlate_mac(xl, mask);
xt_xlate_add(xl, " == %02x", mac[0] & mask[0]);
for (i=1; i < ETH_ALEN; i++)
xt_xlate_add(xl, ":%02x", mac[i] & mask[i]);
+ } else {
+ xlate_mac(xl, mac);
}
-
- xt_xlate_add(xl, " ");
}
static int nft_bridge_xlate(const struct iptables_command_state *cs,
@@ -840,7 +894,10 @@ static int nft_bridge_xlate(const struct iptables_command_state *cs,
xlate_ifname(xl, "meta obrname", cs->eb.logical_out,
cs->eb.invflags & EBT_ILOGICALOUT);
- if ((cs->eb.bitmask & EBT_NOPROTO) == 0) {
+ if (cs->eb.bitmask & EBT_802_3) {
+ xt_xlate_add(xl, "ether type %s 0x0600 ",
+ cs->eb.invflags & EBT_IPROTO ? ">=" : "<");
+ } else if ((cs->eb.bitmask & EBT_NOPROTO) == 0) {
const char *implicit = NULL;
switch (ntohs(cs->eb.ethproto)) {
@@ -863,9 +920,6 @@ static int nft_bridge_xlate(const struct iptables_command_state *cs,
ntohs(cs->eb.ethproto));
}
- if (cs->eb.bitmask & EBT_802_3)
- return 0;
-
if (cs->eb.bitmask & EBT_ISOURCE)
nft_bridge_xlate_mac(xl, "saddr", cs->eb.invflags & EBT_ISOURCE,
cs->eb.sourcemac, cs->eb.sourcemsk);
diff --git a/iptables/nft-cache.c b/iptables/nft-cache.c
index 608e42a7..76e99adc 100644
--- a/iptables/nft-cache.c
+++ b/iptables/nft-cache.c
@@ -105,7 +105,8 @@ static void mnl_genid_get(struct nft_handle *h, uint32_t *genid)
return;
xtables_error(RESOURCE_PROBLEM,
- "Could not fetch rule set generation id: %s\n", nft_strerror(errno));
+ "Could not fetch rule set generation id: %s",
+ nft_strerror(errno));
}
static int nftnl_table_list_cb(const struct nlmsghdr *nlh, void *data)
@@ -141,8 +142,8 @@ static int fetch_table_cache(struct nft_handle *h)
char buf[16536];
int i, ret;
- nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
- NLM_F_DUMP, h->seq);
+ nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
+ NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nftnl_table_list_cb, h);
if (ret < 0 && errno == EINTR)
@@ -453,8 +454,8 @@ static int fetch_set_cache(struct nft_handle *h,
}
}
- nlh = nftnl_set_nlmsg_build_hdr(buf, NFT_MSG_GETSET,
- h->family, flags, h->seq);
+ nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETSET,
+ h->family, flags, h->seq);
if (s) {
nftnl_set_nlmsg_build_payload(nlh, s);
@@ -496,8 +497,8 @@ static int __fetch_chain_cache(struct nft_handle *h,
struct nlmsghdr *nlh;
int ret;
- nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
- c ? NLM_F_ACK : NLM_F_DUMP, h->seq);
+ nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
+ c ? NLM_F_ACK : NLM_F_DUMP, h->seq);
if (c)
nftnl_chain_nlmsg_build_payload(nlh, c);
@@ -591,8 +592,8 @@ static int nft_rule_list_update(struct nft_chain *nc, void *data)
nftnl_rule_set_str(rule, NFTNL_RULE_CHAIN,
nftnl_chain_get_str(c, NFTNL_CHAIN_NAME));
- nlh = nftnl_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
- NLM_F_DUMP, h->seq);
+ nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
+ NLM_F_DUMP, h->seq);
nftnl_rule_nlmsg_build_payload(nlh, rule);
ret = mnl_talk(h, nlh, nftnl_rule_list_cb, &rld);
diff --git a/iptables/nft-cmd.c b/iptables/nft-cmd.c
index fcd01bd0..f16ea0e6 100644
--- a/iptables/nft-cmd.c
+++ b/iptables/nft-cmd.c
@@ -24,6 +24,7 @@ struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
struct nft_cmd *cmd;
cmd = xtables_calloc(1, sizeof(struct nft_cmd));
+ cmd->error.lineno = h->error.lineno;
cmd->command = command;
cmd->table = xtables_strdup(table);
if (chain)
diff --git a/iptables/nft-cmd.h b/iptables/nft-cmd.h
index b5a99ef7..c0f84636 100644
--- a/iptables/nft-cmd.h
+++ b/iptables/nft-cmd.h
@@ -24,6 +24,9 @@ struct nft_cmd {
struct xt_counters counters;
const char *rename;
int counters_save;
+ struct {
+ unsigned int lineno;
+ } error;
};
struct nft_cmd *nft_cmd_new(struct nft_handle *h, int command,
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 59c4a41f..42167351 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -115,28 +115,28 @@ static bool nft_ipv4_is_same(const struct iptables_command_state *a,
b->fw.ip.iniface_mask, b->fw.ip.outiface_mask);
}
-static void get_frag(struct nft_xt_ctx *ctx, struct nftnl_expr *e, bool *inv)
+static bool get_frag(const struct nft_xt_ctx_reg *reg, struct nftnl_expr *e)
{
uint8_t op;
/* we assume correct mask and xor */
- if (!(ctx->flags & NFT_XT_CTX_BITWISE))
- return;
+ if (!reg->bitwise.set)
+ return false;
/* we assume correct data */
op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
if (op == NFT_CMP_EQ)
- *inv = true;
- else
- *inv = false;
+ return true;
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
+ return false;
}
-static void nft_ipv4_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
+static void nft_ipv4_parse_meta(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
+ struct nftnl_expr *e,
struct iptables_command_state *cs)
{
- switch (ctx->meta.key) {
+ switch (reg->meta_dreg.key) {
case NFT_META_L4PROTO:
cs->fw.ip.proto = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
@@ -146,17 +146,21 @@ static void nft_ipv4_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
break;
}
- parse_meta(ctx, e, ctx->meta.key, cs->fw.ip.iniface, cs->fw.ip.iniface_mask,
+ if (parse_meta(ctx, e, reg->meta_dreg.key, cs->fw.ip.iniface, cs->fw.ip.iniface_mask,
cs->fw.ip.outiface, cs->fw.ip.outiface_mask,
- &cs->fw.ip.invflags);
+ &cs->fw.ip.invflags) == 0)
+ return;
+
+ ctx->errmsg = "unknown ipv4 meta key";
}
-static void parse_mask_ipv4(struct nft_xt_ctx *ctx, struct in_addr *mask)
+static void parse_mask_ipv4(const struct nft_xt_ctx_reg *sreg, struct in_addr *mask)
{
- mask->s_addr = ctx->bitwise.mask[0];
+ mask->s_addr = sreg->bitwise.mask[0];
}
static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *sreg,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
@@ -164,16 +168,15 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
uint8_t proto;
bool inv;
- switch(ctx->payload.offset) {
+ switch (sreg->payload.offset) {
case offsetof(struct iphdr, saddr):
get_cmp_data(e, &addr, sizeof(addr), &inv);
cs->fw.ip.src.s_addr = addr.s_addr;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- parse_mask_ipv4(ctx, &cs->fw.ip.smsk);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
+ if (sreg->bitwise.set) {
+ parse_mask_ipv4(sreg, &cs->fw.ip.smsk);
} else {
memset(&cs->fw.ip.smsk, 0xff,
- min(ctx->payload.len, sizeof(struct in_addr)));
+ min(sreg->payload.len, sizeof(struct in_addr)));
}
if (inv)
@@ -182,13 +185,11 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
case offsetof(struct iphdr, daddr):
get_cmp_data(e, &addr, sizeof(addr), &inv);
cs->fw.ip.dst.s_addr = addr.s_addr;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- parse_mask_ipv4(ctx, &cs->fw.ip.dmsk);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (sreg->bitwise.set)
+ parse_mask_ipv4(sreg, &cs->fw.ip.dmsk);
+ else
memset(&cs->fw.ip.dmsk, 0xff,
- min(ctx->payload.len, sizeof(struct in_addr)));
- }
+ min(sreg->payload.len, sizeof(struct in_addr)));
if (inv)
cs->fw.ip.invflags |= IPT_INV_DSTIP;
@@ -201,13 +202,15 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
break;
case offsetof(struct iphdr, frag_off):
cs->fw.ip.flags |= IPT_F_FRAG;
- inv = false;
- get_frag(ctx, e, &inv);
+ inv = get_frag(sreg, e);
if (inv)
cs->fw.ip.invflags |= IPT_INV_FRAG;
break;
+ case offsetof(struct iphdr, ttl):
+ nft_parse_hl(ctx, e, cs);
+ break;
default:
- DEBUGP("unknown payload offset %d\n", ctx->payload.offset);
+ DEBUGP("unknown payload offset %d\n", sreg->payload.offset);
break;
}
}
@@ -244,7 +247,7 @@ static void nft_ipv4_print_rule(struct nft_handle *h, struct nftnl_rule *r,
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
- nft_clear_iptables_command_state(&cs);
+ xtables_clear_iptables_command_state(&cs);
}
static void nft_ipv4_save_rule(const struct iptables_command_state *cs,
@@ -451,7 +454,7 @@ struct nft_family_ops nft_family_ops_ipv4 = {
},
.parse_target = nft_ipv46_parse_target,
.rule_to_cs = nft_rule_to_iptables_command_state,
- .clear_cs = nft_clear_iptables_command_state,
+ .clear_cs = xtables_clear_iptables_command_state,
.xlate = nft_ipv4_xlate,
.add_entry = nft_ipv4_add_entry,
.delete_entry = nft_ipv4_delete_entry,
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 9a29d18b..3a373b7e 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -104,10 +104,12 @@ static bool nft_ipv6_is_same(const struct iptables_command_state *a,
b->fw6.ipv6.outiface_mask);
}
-static void nft_ipv6_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
+static void nft_ipv6_parse_meta(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
+ struct nftnl_expr *e,
struct iptables_command_state *cs)
{
- switch (ctx->meta.key) {
+ switch (reg->meta_dreg.key) {
case NFT_META_L4PROTO:
cs->fw6.ipv6.proto = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
@@ -117,17 +119,22 @@ static void nft_ipv6_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
break;
}
- parse_meta(ctx, e, ctx->meta.key, cs->fw6.ipv6.iniface,
+ if (parse_meta(ctx, e, reg->meta_dreg.key, cs->fw6.ipv6.iniface,
cs->fw6.ipv6.iniface_mask, cs->fw6.ipv6.outiface,
- cs->fw6.ipv6.outiface_mask, &cs->fw6.ipv6.invflags);
+ cs->fw6.ipv6.outiface_mask, &cs->fw6.ipv6.invflags) == 0)
+ return;
+
+ ctx->errmsg = "unknown ipv6 meta key";
}
-static void parse_mask_ipv6(struct nft_xt_ctx *ctx, struct in6_addr *mask)
+static void parse_mask_ipv6(const struct nft_xt_ctx_reg *reg,
+ struct in6_addr *mask)
{
- memcpy(mask, ctx->bitwise.mask, sizeof(struct in6_addr));
+ memcpy(mask, reg->bitwise.mask, sizeof(struct in6_addr));
}
static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *reg,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
@@ -135,17 +142,15 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
uint8_t proto;
bool inv;
- switch (ctx->payload.offset) {
+ switch (reg->payload.offset) {
case offsetof(struct ip6_hdr, ip6_src):
get_cmp_data(e, &addr, sizeof(addr), &inv);
memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr));
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- parse_mask_ipv6(ctx, &cs->fw6.ipv6.smsk);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ parse_mask_ipv6(reg, &cs->fw6.ipv6.smsk);
+ else
memset(&cs->fw6.ipv6.smsk, 0xff,
- min(ctx->payload.len, sizeof(struct in6_addr)));
- }
+ min(reg->payload.len, sizeof(struct in6_addr)));
if (inv)
cs->fw6.ipv6.invflags |= IP6T_INV_SRCIP;
@@ -153,13 +158,11 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
case offsetof(struct ip6_hdr, ip6_dst):
get_cmp_data(e, &addr, sizeof(addr), &inv);
memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr));
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- parse_mask_ipv6(ctx, &cs->fw6.ipv6.dmsk);
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
+ if (reg->bitwise.set)
+ parse_mask_ipv6(reg, &cs->fw6.ipv6.dmsk);
+ else
memset(&cs->fw6.ipv6.dmsk, 0xff,
- min(ctx->payload.len, sizeof(struct in6_addr)));
- }
+ min(reg->payload.len, sizeof(struct in6_addr)));
if (inv)
cs->fw6.ipv6.invflags |= IP6T_INV_DSTIP;
@@ -169,8 +172,11 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
cs->fw6.ipv6.proto = proto;
if (inv)
cs->fw6.ipv6.invflags |= IP6T_INV_PROTO;
+ case offsetof(struct ip6_hdr, ip6_hlim):
+ nft_parse_hl(ctx, e, cs);
+ break;
default:
- DEBUGP("unknown payload offset %d\n", ctx->payload.offset);
+ DEBUGP("unknown payload offset %d\n", reg->payload.offset);
break;
}
}
@@ -205,7 +211,7 @@ static void nft_ipv6_print_rule(struct nft_handle *h, struct nftnl_rule *r,
if (!(format & FMT_NONEWLINE))
fputc('\n', stdout);
- nft_clear_iptables_command_state(&cs);
+ xtables_clear_iptables_command_state(&cs);
}
static void nft_ipv6_save_rule(const struct iptables_command_state *cs,
@@ -417,7 +423,7 @@ struct nft_family_ops nft_family_ops_ipv6 = {
},
.parse_target = nft_ipv46_parse_target,
.rule_to_cs = nft_rule_to_iptables_command_state,
- .clear_cs = nft_clear_iptables_command_state,
+ .clear_cs = xtables_clear_iptables_command_state,
.xlate = nft_ipv6_xlate,
.add_entry = nft_ipv6_add_entry,
.delete_entry = nft_ipv6_delete_entry,
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index 74e19cca..56acbd45 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -10,6 +10,7 @@
* This code has been sponsored by Sophos Astaro <http://www.sophos.com>
*/
+#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -25,6 +26,9 @@
#include <linux/netfilter/xt_limit.h>
#include <linux/netfilter/xt_NFLOG.h>
#include <linux/netfilter/xt_mark.h>
+#include <linux/netfilter/xt_pkttype.h>
+
+#include <linux/netfilter_ipv6/ip6t_hl.h>
#include <libmnl/libmnl.h>
#include <libnftnl/rule.h>
@@ -164,6 +168,9 @@ void add_iniface(struct nft_handle *h, struct nftnl_rule *r,
if (iface[iface_len - 1] == '+') {
if (iface_len > 1)
add_cmp_ptr(r, op, iface, iface_len - 1, reg);
+ else if (op != NFT_CMP_EQ)
+ add_cmp_ptr(r, NFT_CMP_EQ, "INVAL/D",
+ strlen("INVAL/D") + 1, reg);
} else {
add_cmp_ptr(r, op, iface, iface_len + 1, reg);
}
@@ -181,6 +188,9 @@ void add_outiface(struct nft_handle *h, struct nftnl_rule *r,
if (iface[iface_len - 1] == '+') {
if (iface_len > 1)
add_cmp_ptr(r, op, iface, iface_len - 1, reg);
+ else if (op != NFT_CMP_EQ)
+ add_cmp_ptr(r, NFT_CMP_EQ, "INVAL/D",
+ strlen("INVAL/D") + 1, reg);
} else {
add_cmp_ptr(r, op, iface, iface_len + 1, reg);
}
@@ -275,7 +285,7 @@ static void parse_ifname(const char *name, unsigned int len, char *dst, unsigned
memcpy(dst, name, len);
if (name[len - 1] == '\0') {
if (mask)
- memset(mask, 0xff, len);
+ memset(mask, 0xff, strlen(name) + 1);
return;
}
@@ -296,6 +306,16 @@ nft_create_match(struct nft_xt_ctx *ctx,
struct iptables_command_state *cs,
const char *name);
+static uint32_t get_meta_mask(struct nft_xt_ctx *ctx, enum nft_registers sreg)
+{
+ struct nft_xt_ctx_reg *reg = nft_xt_ctx_get_sreg(ctx, sreg);
+
+ if (reg->bitwise.set)
+ return reg->bitwise.mask[0];
+
+ return ~0u;
+}
+
static int parse_meta_mark(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
struct xt_mark_mtinfo1 *mark;
@@ -313,16 +333,47 @@ static int parse_meta_mark(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
value = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_DATA);
mark->mark = value;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- memcpy(&mark->mask, &ctx->bitwise.mask, sizeof(mark->mask));
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- } else {
- mark->mask = 0xffffffff;
- }
+ mark->mask = get_meta_mask(ctx, nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG));
return 0;
}
+static int parse_meta_pkttype(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
+{
+ struct xt_pkttype_info *pkttype;
+ struct xtables_match *match;
+ uint8_t value;
+
+ match = nft_create_match(ctx, ctx->cs, "pkttype");
+ if (!match)
+ return -1;
+
+ pkttype = (void*)match->m->data;
+
+ if (nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP) == NFT_CMP_NEQ)
+ pkttype->invert = 1;
+
+ value = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
+ pkttype->pkttype = value;
+
+ return 0;
+}
+
+static void parse_invalid_iface(char *iface, unsigned char *mask,
+ uint8_t *invflags, uint8_t invbit)
+{
+ if (*invflags & invbit || strcmp(iface, "INVAL/D"))
+ return;
+
+ /* nft's poor "! -o +" excuse */
+ *invflags |= invbit;
+ iface[0] = '+';
+ iface[1] = '\0';
+ mask[0] = 0xff;
+ mask[1] = 0xff;
+ memset(mask + 2, 0, IFNAMSIZ - 2);
+}
+
int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
char *iniface, unsigned char *iniface_mask,
char *outiface, unsigned char *outiface_mask, uint8_t *invflags)
@@ -357,6 +408,8 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
*invflags |= IPT_INV_VIA_IN;
parse_ifname(ifname, len, iniface, iniface_mask);
+ parse_invalid_iface(iniface, iniface_mask,
+ invflags, IPT_INV_VIA_IN);
break;
case NFT_META_BRI_OIFNAME:
case NFT_META_OIFNAME:
@@ -365,10 +418,15 @@ int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
*invflags |= IPT_INV_VIA_OUT;
parse_ifname(ifname, len, outiface, outiface_mask);
+ parse_invalid_iface(outiface, outiface_mask,
+ invflags, IPT_INV_VIA_OUT);
break;
case NFT_META_MARK:
parse_meta_mark(ctx, e);
break;
+ case NFT_META_PKTTYPE:
+ parse_meta_pkttype(ctx, e);
+ break;
default:
return -1;
}
@@ -439,39 +497,61 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
ctx->h->ops->parse_match(match, ctx->cs);
}
-void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv)
+void __get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, uint8_t *op)
{
uint32_t len;
- uint8_t op;
memcpy(data, nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len), dlen);
- op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
- if (op == NFT_CMP_NEQ)
- *inv = true;
- else
- *inv = false;
+ *op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
+}
+
+void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv)
+{
+ uint8_t op;
+
+ __get_cmp_data(e, data, dlen, &op);
+ *inv = (op == NFT_CMP_NEQ);
}
-static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
+static void nft_meta_set_to_target(struct nft_xt_ctx *ctx,
+ struct nftnl_expr *e)
{
struct xtables_target *target;
+ struct nft_xt_ctx_reg *sreg;
+ enum nft_registers sregnum;
struct xt_entry_target *t;
unsigned int size;
const char *targname;
- switch (ctx->meta.key) {
+ sregnum = nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG);
+ sreg = nft_xt_ctx_get_sreg(ctx, sregnum);
+ if (!sreg)
+ return;
+
+ switch (nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY)) {
case NFT_META_NFTRACE:
- if (ctx->immediate.data[0] == 0)
+ if ((sreg->type != NFT_XT_REG_IMMEDIATE)) {
+ ctx->errmsg = "meta nftrace but reg not immediate";
+ return;
+ }
+
+ if (sreg->immediate.data[0] == 0) {
+ ctx->errmsg = "trace is cleared";
return;
+ }
+
targname = "TRACE";
break;
default:
+ ctx->errmsg = "meta sreg key not supported";
return;
}
target = xtables_find_target(targname, XTF_TRY_LOAD);
- if (target == NULL)
+ if (target == NULL) {
+ ctx->errmsg = "target TRACE not found";
return;
+ }
size = XT_ALIGN(sizeof(struct xt_entry_target)) + target->size;
@@ -487,51 +567,74 @@ static void nft_meta_set_to_target(struct nft_xt_ctx *ctx)
static void nft_parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
- ctx->meta.key = nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY);
+ struct nft_xt_ctx_reg *reg;
- if (nftnl_expr_is_set(e, NFTNL_EXPR_META_SREG) &&
- (ctx->flags & NFT_XT_CTX_IMMEDIATE) &&
- nftnl_expr_get_u32(e, NFTNL_EXPR_META_SREG) == ctx->immediate.reg) {
- ctx->flags &= ~NFT_XT_CTX_IMMEDIATE;
- nft_meta_set_to_target(ctx);
+ if (nftnl_expr_is_set(e, NFTNL_EXPR_META_SREG)) {
+ nft_meta_set_to_target(ctx, e);
return;
}
- ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG);
- ctx->flags |= NFT_XT_CTX_META;
+ reg = nft_xt_ctx_get_dreg(ctx, nftnl_expr_get_u32(e, NFTNL_EXPR_META_DREG));
+ if (!reg)
+ return;
+
+ reg->meta_dreg.key = nftnl_expr_get_u32(e, NFTNL_EXPR_META_KEY);
+ reg->type = NFT_XT_REG_META_DREG;
}
static void nft_parse_payload(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
- if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
- memcpy(&ctx->prev_payload, &ctx->payload,
- sizeof(ctx->prev_payload));
- ctx->flags |= NFT_XT_CTX_PREV_PAYLOAD;
- }
+ enum nft_registers regnum = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_DREG);
+ struct nft_xt_ctx_reg *reg = nft_xt_ctx_get_dreg(ctx, regnum);
- ctx->reg = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_DREG);
- ctx->payload.base = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_BASE);
- ctx->payload.offset = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET);
- ctx->payload.len = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_LEN);
- ctx->flags |= NFT_XT_CTX_PAYLOAD;
+ if (!reg)
+ return;
+
+ reg->type = NFT_XT_REG_PAYLOAD;
+ reg->payload.base = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_BASE);
+ reg->payload.offset = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET);
+ reg->payload.len = nftnl_expr_get_u32(e, NFTNL_EXPR_PAYLOAD_LEN);
}
static void nft_parse_bitwise(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
- uint32_t reg, len;
+ enum nft_registers sregnum = nftnl_expr_get_u32(e, NFTNL_EXPR_BITWISE_SREG);
+ enum nft_registers dregnum = nftnl_expr_get_u32(e, NFTNL_EXPR_BITWISE_DREG);
+ struct nft_xt_ctx_reg *sreg = nft_xt_ctx_get_sreg(ctx, sregnum);
+ struct nft_xt_ctx_reg *dreg = sreg;
const void *data;
+ uint32_t len;
- reg = nftnl_expr_get_u32(e, NFTNL_EXPR_BITWISE_SREG);
- if (ctx->reg && reg != ctx->reg)
+ if (!sreg)
return;
- reg = nftnl_expr_get_u32(e, NFTNL_EXPR_BITWISE_DREG);
- ctx->reg = reg;
+ if (sregnum != dregnum) {
+ dreg = nft_xt_ctx_get_sreg(ctx, dregnum); /* sreg, do NOT clear ... */
+ if (!dreg)
+ return;
+
+ *dreg = *sreg; /* .. and copy content instead */
+ }
+
data = nftnl_expr_get(e, NFTNL_EXPR_BITWISE_XOR, &len);
- memcpy(ctx->bitwise.xor, data, len);
+
+ if (len > sizeof(dreg->bitwise.xor)) {
+ ctx->errmsg = "bitwise xor too large";
+ return;
+ }
+
+ memcpy(dreg->bitwise.xor, data, len);
+
data = nftnl_expr_get(e, NFTNL_EXPR_BITWISE_MASK, &len);
- memcpy(ctx->bitwise.mask, data, len);
- ctx->flags |= NFT_XT_CTX_BITWISE;
+
+ if (len > sizeof(dreg->bitwise.mask)) {
+ ctx->errmsg = "bitwise mask too large";
+ return;
+ }
+
+ memcpy(dreg->bitwise.mask, data, len);
+
+ dreg->bitwise.set = true;
}
static struct xtables_match *
@@ -669,6 +772,35 @@ static void nft_parse_tcp_range(struct nft_xt_ctx *ctx,
}
}
+static void port_match_single_to_range(__u16 *ports, __u8 *invflags,
+ uint8_t op, int port, __u8 invflag)
+{
+ if (port < 0)
+ return;
+
+ switch (op) {
+ case NFT_CMP_NEQ:
+ *invflags |= invflag;
+ /* fallthrough */
+ case NFT_CMP_EQ:
+ ports[0] = port;
+ ports[1] = port;
+ break;
+ case NFT_CMP_LT:
+ ports[1] = max(port - 1, 1);
+ break;
+ case NFT_CMP_LTE:
+ ports[1] = port;
+ break;
+ case NFT_CMP_GT:
+ ports[0] = min(port + 1, UINT16_MAX);
+ break;
+ case NFT_CMP_GTE:
+ ports[0] = port;
+ break;
+ }
+}
+
static void nft_parse_udp(struct nft_xt_ctx *ctx,
struct iptables_command_state *cs,
int sport, int dport,
@@ -679,52 +811,10 @@ static void nft_parse_udp(struct nft_xt_ctx *ctx,
if (!udp)
return;
- if (sport >= 0) {
- switch (op) {
- case NFT_CMP_NEQ:
- udp->invflags |= XT_UDP_INV_SRCPT;
- /* fallthrough */
- case NFT_CMP_EQ:
- udp->spts[0] = sport;
- udp->spts[1] = sport;
- break;
- case NFT_CMP_LT:
- udp->spts[1] = sport > 1 ? sport - 1 : 1;
- break;
- case NFT_CMP_LTE:
- udp->spts[1] = sport;
- break;
- case NFT_CMP_GT:
- udp->spts[0] = sport < 0xffff ? sport + 1 : 0xffff;
- break;
- case NFT_CMP_GTE:
- udp->spts[0] = sport;
- break;
- }
- }
- if (dport >= 0) {
- switch (op) {
- case NFT_CMP_NEQ:
- udp->invflags |= XT_UDP_INV_DSTPT;
- /* fallthrough */
- case NFT_CMP_EQ:
- udp->dpts[0] = dport;
- udp->dpts[1] = dport;
- break;
- case NFT_CMP_LT:
- udp->dpts[1] = dport > 1 ? dport - 1 : 1;
- break;
- case NFT_CMP_LTE:
- udp->dpts[1] = dport;
- break;
- case NFT_CMP_GT:
- udp->dpts[0] = dport < 0xffff ? dport + 1 : 0xffff;
- break;
- case NFT_CMP_GTE:
- udp->dpts[0] = dport;
- break;
- }
- }
+ port_match_single_to_range(udp->spts, &udp->invflags,
+ op, sport, XT_UDP_INV_SRCPT);
+ port_match_single_to_range(udp->dpts, &udp->invflags,
+ op, dport, XT_UDP_INV_DSTPT);
}
static void nft_parse_tcp(struct nft_xt_ctx *ctx,
@@ -737,53 +827,10 @@ static void nft_parse_tcp(struct nft_xt_ctx *ctx,
if (!tcp)
return;
- if (sport >= 0) {
- switch (op) {
- case NFT_CMP_NEQ:
- tcp->invflags |= XT_TCP_INV_SRCPT;
- /* fallthrough */
- case NFT_CMP_EQ:
- tcp->spts[0] = sport;
- tcp->spts[1] = sport;
- break;
- case NFT_CMP_LT:
- tcp->spts[1] = sport > 1 ? sport - 1 : 1;
- break;
- case NFT_CMP_LTE:
- tcp->spts[1] = sport;
- break;
- case NFT_CMP_GT:
- tcp->spts[0] = sport < 0xffff ? sport + 1 : 0xffff;
- break;
- case NFT_CMP_GTE:
- tcp->spts[0] = sport;
- break;
- }
- }
-
- if (dport >= 0) {
- switch (op) {
- case NFT_CMP_NEQ:
- tcp->invflags |= XT_TCP_INV_DSTPT;
- /* fallthrough */
- case NFT_CMP_EQ:
- tcp->dpts[0] = dport;
- tcp->dpts[1] = dport;
- break;
- case NFT_CMP_LT:
- tcp->dpts[1] = dport > 1 ? dport - 1 : 1;
- break;
- case NFT_CMP_LTE:
- tcp->dpts[1] = dport;
- break;
- case NFT_CMP_GT:
- tcp->dpts[0] = dport < 0xffff ? dport + 1 : 0xffff;
- break;
- case NFT_CMP_GTE:
- tcp->dpts[0] = dport;
- break;
- }
- }
+ port_match_single_to_range(tcp->spts, &tcp->invflags,
+ op, sport, XT_TCP_INV_SRCPT);
+ port_match_single_to_range(tcp->dpts, &tcp->invflags,
+ op, dport, XT_TCP_INV_DSTPT);
}
static void nft_parse_th_port(struct nft_xt_ctx *ctx,
@@ -836,6 +883,8 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
+ struct nft_xt_ctx_reg *sreg;
+ enum nft_registers reg;
uint32_t sdport;
uint16_t port;
uint8_t proto, op;
@@ -856,7 +905,17 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
- switch(ctx->payload.offset) {
+ reg = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG);
+ sreg = nft_xt_ctx_get_sreg(ctx, reg);
+ if (!sreg)
+ return;
+
+ if (sreg->type != NFT_XT_REG_PAYLOAD) {
+ ctx->errmsg = "sgreg not payload";
+ return;
+ }
+
+ switch(sreg->payload.offset) {
case 0: /* th->sport */
switch (len) {
case 2: /* load sport only */
@@ -882,10 +941,9 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
uint8_t flags = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
uint8_t mask = ~0;
- if (ctx->flags & NFT_XT_CTX_BITWISE) {
- memcpy(&mask, &ctx->bitwise.mask, sizeof(mask));
- ctx->flags &= ~NFT_XT_CTX_BITWISE;
- }
+ if (sreg->bitwise.set)
+ memcpy(&mask, &sreg->bitwise.mask, sizeof(mask));
+
nft_parse_tcp_flags(ctx, cs, op, flags, mask);
}
return;
@@ -893,6 +951,7 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
}
static void nft_parse_transport_range(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *sreg,
struct nftnl_expr *e,
struct iptables_command_state *cs)
{
@@ -922,7 +981,7 @@ static void nft_parse_transport_range(struct nft_xt_ctx *ctx,
from = ntohs(nftnl_expr_get_u16(e, NFTNL_EXPR_RANGE_FROM_DATA));
to = ntohs(nftnl_expr_get_u16(e, NFTNL_EXPR_RANGE_TO_DATA));
- switch(ctx->payload.offset) {
+ switch (sreg->payload.offset) {
case 0:
nft_parse_th_port_range(ctx, cs, proto, from, to, -1, -1, op);
return;
@@ -935,30 +994,40 @@ static void nft_parse_transport_range(struct nft_xt_ctx *ctx,
static void nft_parse_cmp(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
+ struct nft_xt_ctx_reg *sreg;
uint32_t reg;
reg = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_SREG);
- if (ctx->reg && reg != ctx->reg)
+
+ sreg = nft_xt_ctx_get_sreg(ctx, reg);
+ if (!sreg)
return;
- if (ctx->flags & NFT_XT_CTX_META) {
- ctx->h->ops->parse_meta(ctx, e, ctx->cs);
- ctx->flags &= ~NFT_XT_CTX_META;
- }
- /* bitwise context is interpreted from payload */
- if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
- switch (ctx->payload.base) {
+ switch (sreg->type) {
+ case NFT_XT_REG_UNDEF:
+ ctx->errmsg = "cmp sreg undef";
+ break;
+ case NFT_XT_REG_META_DREG:
+ ctx->h->ops->parse_meta(ctx, sreg, e, ctx->cs);
+ break;
+ case NFT_XT_REG_PAYLOAD:
+ switch (sreg->payload.base) {
case NFT_PAYLOAD_LL_HEADER:
if (ctx->h->family == NFPROTO_BRIDGE)
- ctx->h->ops->parse_payload(ctx, e, ctx->cs);
+ ctx->h->ops->parse_payload(ctx, sreg, e, ctx->cs);
break;
case NFT_PAYLOAD_NETWORK_HEADER:
- ctx->h->ops->parse_payload(ctx, e, ctx->cs);
+ ctx->h->ops->parse_payload(ctx, sreg, e, ctx->cs);
break;
case NFT_PAYLOAD_TRANSPORT_HEADER:
nft_parse_transport(ctx, e, ctx->cs);
break;
}
+
+ break;
+ default:
+ ctx->errmsg = "cmp sreg has unknown type";
+ break;
}
}
@@ -977,18 +1046,22 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
int verdict;
if (nftnl_expr_is_set(e, NFTNL_EXPR_IMM_DATA)) {
+ struct nft_xt_ctx_reg *dreg;
const void *imm_data;
uint32_t len;
- imm_data = nftnl_expr_get_data(e, NFTNL_EXPR_IMM_DATA, &len);
+ imm_data = nftnl_expr_get(e, NFTNL_EXPR_IMM_DATA, &len);
+ dreg = nft_xt_ctx_get_dreg(ctx, nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_DREG));
+ if (!dreg)
+ return;
- if (len > sizeof(ctx->immediate.data))
+ if (len > sizeof(dreg->immediate.data))
return;
- memcpy(ctx->immediate.data, imm_data, len);
- ctx->immediate.len = len;
- ctx->immediate.reg = nftnl_expr_get_u32(e, NFTNL_EXPR_IMM_DREG);
- ctx->flags |= NFT_XT_CTX_IMMEDIATE;
+ memcpy(dreg->immediate.data, imm_data, len);
+ dreg->immediate.len = len;
+ dreg->type = NFT_XT_REG_IMMEDIATE;
+
return;
}
@@ -1125,24 +1198,33 @@ static void nft_parse_lookup(struct nft_xt_ctx *ctx, struct nft_handle *h,
static void nft_parse_range(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
{
+ struct nft_xt_ctx_reg *sreg;
uint32_t reg;
reg = nftnl_expr_get_u32(e, NFTNL_EXPR_RANGE_SREG);
- if (reg != ctx->reg)
- return;
+ sreg = nft_xt_ctx_get_sreg(ctx, reg);
- if (ctx->flags & NFT_XT_CTX_PAYLOAD) {
- switch (ctx->payload.base) {
+ switch (sreg->type) {
+ case NFT_XT_REG_UNDEF:
+ ctx->errmsg = "range sreg undef";
+ break;
+ case NFT_XT_REG_PAYLOAD:
+ switch (sreg->payload.base) {
case NFT_PAYLOAD_TRANSPORT_HEADER:
- nft_parse_transport_range(ctx, e, ctx->cs);
+ nft_parse_transport_range(ctx, sreg, e, ctx->cs);
break;
default:
+ ctx->errmsg = "range with unknown payload base";
break;
}
+ break;
+ default:
+ ctx->errmsg = "range sreg type unsupported";
+ break;
}
}
-void nft_rule_to_iptables_command_state(struct nft_handle *h,
+bool nft_rule_to_iptables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
struct iptables_command_state *cs)
{
@@ -1153,10 +1235,11 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
.h = h,
.table = nftnl_rule_get_str(r, NFTNL_RULE_TABLE),
};
+ bool ret = true;
iter = nftnl_expr_iter_create(r);
if (iter == NULL)
- return;
+ return false;
ctx.iter = iter;
expr = nftnl_expr_iter_next(iter);
@@ -1189,6 +1272,12 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
else if (strcmp(name, "range") == 0)
nft_parse_range(&ctx, expr);
+ if (ctx.errmsg) {
+ fprintf(stderr, "%s", ctx.errmsg);
+ ctx.errmsg = NULL;
+ ret = false;
+ }
+
expr = nftnl_expr_iter_next(iter);
}
@@ -1208,7 +1297,7 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
match = xtables_find_match("comment", XTF_TRY_LOAD,
&cs->matches);
if (match == NULL)
- return;
+ return false;
size = XT_ALIGN(sizeof(struct xt_entry_match))
+ match->size;
@@ -1225,20 +1314,8 @@ void nft_rule_to_iptables_command_state(struct nft_handle *h,
if (!cs->jumpto)
cs->jumpto = "";
-}
-void nft_clear_iptables_command_state(struct iptables_command_state *cs)
-{
- xtables_rule_matches_free(&cs->matches);
- if (cs->target) {
- free(cs->target->t);
- cs->target->t = NULL;
-
- if (cs->target == cs->target->next) {
- free(cs->target);
- cs->target = NULL;
- }
- }
+ return ret;
}
void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy)
@@ -1424,3 +1501,84 @@ void nft_check_xt_legacy(int family, bool is_ipt_save)
prefix, prefix, is_ipt_save ? "-save" : "");
fclose(fp);
}
+
+int nft_parse_hl(struct nft_xt_ctx *ctx,
+ struct nftnl_expr *e,
+ struct iptables_command_state *cs)
+{
+ struct xtables_match *match;
+ struct ip6t_hl_info *info;
+ uint8_t hl, mode;
+ int op;
+
+ hl = nftnl_expr_get_u8(e, NFTNL_EXPR_CMP_DATA);
+ op = nftnl_expr_get_u32(e, NFTNL_EXPR_CMP_OP);
+
+ switch (op) {
+ case NFT_CMP_NEQ:
+ mode = IP6T_HL_NE;
+ break;
+ case NFT_CMP_EQ:
+ mode = IP6T_HL_EQ;
+ break;
+ case NFT_CMP_LT:
+ mode = IP6T_HL_LT;
+ break;
+ case NFT_CMP_GT:
+ mode = IP6T_HL_GT;
+ break;
+ case NFT_CMP_LTE:
+ mode = IP6T_HL_LT;
+ if (hl == 255)
+ return -1;
+ hl++;
+ break;
+ case NFT_CMP_GTE:
+ mode = IP6T_HL_GT;
+ if (hl == 0)
+ return -1;
+ hl--;
+ break;
+ default:
+ return -1;
+ }
+
+ /* ipt_ttl_info and ip6t_hl_info have same layout,
+ * IPT_TTL_x and IP6T_HL_x are aliases as well, so
+ * just use HL for both ipv4 and ipv6.
+ */
+ switch (ctx->h->family) {
+ case NFPROTO_IPV4:
+ match = nft_create_match(ctx, ctx->cs, "ttl");
+ break;
+ case NFPROTO_IPV6:
+ match = nft_create_match(ctx, ctx->cs, "hl");
+ break;
+ default:
+ return -1;
+ }
+
+ if (!match)
+ return -1;
+
+ info = (void*)match->m->data;
+ info->hop_limit = hl;
+ info->mode = mode;
+
+ return 0;
+}
+
+enum nft_registers nft_get_next_reg(enum nft_registers reg, size_t size)
+{
+ /* convert size to NETLINK_ALIGN-sized chunks */
+ size = (size + NETLINK_ALIGN - 1) / NETLINK_ALIGN;
+
+ /* map 16byte reg to 4byte one */
+ if (reg < __NFT_REG_MAX)
+ reg = NFT_REG32_00 + (reg - 1) * NFT_REG_SIZE / NFT_REG32_SIZE;
+
+ reg += size;
+ assert(reg <= NFT_REG32_15);
+
+ return reg;
+}
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index b0404904..07d39131 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -38,13 +38,36 @@ struct xtables_args;
struct nft_handle;
struct xt_xlate;
-enum {
- NFT_XT_CTX_PAYLOAD = (1 << 0),
- NFT_XT_CTX_META = (1 << 1),
- NFT_XT_CTX_BITWISE = (1 << 2),
- NFT_XT_CTX_IMMEDIATE = (1 << 3),
- NFT_XT_CTX_PREV_PAYLOAD = (1 << 4),
- NFT_XT_CTX_RANGE = (1 << 5),
+enum nft_ctx_reg_type {
+ NFT_XT_REG_UNDEF,
+ NFT_XT_REG_PAYLOAD,
+ NFT_XT_REG_IMMEDIATE,
+ NFT_XT_REG_META_DREG,
+};
+
+struct nft_xt_ctx_reg {
+ enum nft_ctx_reg_type type:8;
+
+ union {
+ struct {
+ uint32_t base;
+ uint32_t offset;
+ uint32_t len;
+ } payload;
+ struct {
+ uint32_t data[4];
+ uint8_t len;
+ } immediate;
+ struct {
+ uint32_t key;
+ } meta_dreg;
+ };
+
+ struct {
+ uint32_t mask[4];
+ uint32_t xor[4];
+ bool set;
+ } bitwise;
};
struct nft_xt_ctx {
@@ -58,25 +81,50 @@ struct nft_xt_ctx {
struct xt_udp *udp;
} tcpudp;
- uint32_t reg;
- struct {
- uint32_t base;
- uint32_t offset;
- uint32_t len;
- } payload, prev_payload;
- struct {
- uint32_t key;
- } meta;
- struct {
- uint32_t data[4];
- uint32_t len, reg;
- } immediate;
- struct {
- uint32_t mask[4];
- uint32_t xor[4];
- } bitwise;
+ struct nft_xt_ctx_reg regs[1 + 16];
+
+ const char *errmsg;
};
+static inline struct nft_xt_ctx_reg *nft_xt_ctx_get_sreg(struct nft_xt_ctx *ctx, enum nft_registers reg)
+{
+ switch (reg) {
+ case NFT_REG_VERDICT:
+ return &ctx->regs[0];
+ case NFT_REG_1:
+ return &ctx->regs[1];
+ case NFT_REG_2:
+ return &ctx->regs[5];
+ case NFT_REG_3:
+ return &ctx->regs[9];
+ case NFT_REG_4:
+ return &ctx->regs[13];
+ case NFT_REG32_00...NFT_REG32_15:
+ return &ctx->regs[reg - NFT_REG32_00];
+ default:
+ ctx->errmsg = "Unknown register requested";
+ break;
+ }
+
+ return NULL;
+}
+
+static inline void nft_xt_reg_clear(struct nft_xt_ctx_reg *r)
+{
+ r->type = 0;
+ r->bitwise.set = false;
+}
+
+static inline struct nft_xt_ctx_reg *nft_xt_ctx_get_dreg(struct nft_xt_ctx *ctx, enum nft_registers reg)
+{
+ struct nft_xt_ctx_reg *r = nft_xt_ctx_get_sreg(ctx, reg);
+
+ if (r)
+ nft_xt_reg_clear(r);
+
+ return r;
+}
+
struct nft_family_ops {
int (*add)(struct nft_handle *h, struct nftnl_rule *r,
struct iptables_command_state *cs);
@@ -84,9 +132,13 @@ struct nft_family_ops {
const struct iptables_command_state *cs_b);
void (*print_payload)(struct nftnl_expr *e,
struct nftnl_expr_iter *iter);
- void (*parse_meta)(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
+ void (*parse_meta)(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *sreg,
+ struct nftnl_expr *e,
struct iptables_command_state *cs);
- void (*parse_payload)(struct nft_xt_ctx *ctx, struct nftnl_expr *e,
+ void (*parse_payload)(struct nft_xt_ctx *ctx,
+ const struct nft_xt_ctx_reg *sreg,
+ struct nftnl_expr *e,
struct iptables_command_state *cs);
void (*parse_lookup)(struct nft_xt_ctx *ctx, struct nftnl_expr *e);
void (*set_goto_flag)(struct iptables_command_state *cs);
@@ -107,7 +159,7 @@ struct nft_family_ops {
void (*parse_target)(struct xtables_target *t,
struct iptables_command_state *cs);
void (*init_cs)(struct iptables_command_state *cs);
- void (*rule_to_cs)(struct nft_handle *h, const struct nftnl_rule *r,
+ bool (*rule_to_cs)(struct nft_handle *h, const struct nftnl_rule *r,
struct iptables_command_state *cs);
void (*clear_cs)(struct iptables_command_state *cs);
int (*xlate)(const struct iptables_command_state *cs,
@@ -159,11 +211,11 @@ bool is_same_interfaces(const char *a_iniface, const char *a_outiface,
int parse_meta(struct nft_xt_ctx *ctx, struct nftnl_expr *e, uint8_t key,
char *iniface, unsigned char *iniface_mask, char *outiface,
unsigned char *outiface_mask, uint8_t *invflags);
+void __get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, uint8_t *op);
void get_cmp_data(struct nftnl_expr *e, void *data, size_t dlen, bool *inv);
-void nft_rule_to_iptables_command_state(struct nft_handle *h,
+bool nft_rule_to_iptables_command_state(struct nft_handle *h,
const struct nftnl_rule *r,
struct iptables_command_state *cs);
-void nft_clear_iptables_command_state(struct iptables_command_state *cs);
void print_matches_and_target(struct iptables_command_state *cs,
unsigned int format);
void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy);
@@ -212,7 +264,14 @@ void xtables_restore_parse(struct nft_handle *h,
void nft_check_xt_legacy(int family, bool is_ipt_save);
+int nft_parse_hl(struct nft_xt_ctx *ctx, struct nftnl_expr *e, struct iptables_command_state *cs);
+
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))
+/* simplified nftables:include/netlink.h, netlink_padded_len() */
+#define NETLINK_ALIGN 4
+
+enum nft_registers nft_get_next_reg(enum nft_registers reg, size_t size);
+
#endif
diff --git a/iptables/nft.c b/iptables/nft.c
index ee003511..430888e8 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1133,9 +1133,6 @@ gen_lookup(uint32_t sreg, const char *set_name, uint32_t set_id, uint32_t flags)
return e;
}
-/* simplified nftables:include/netlink.h, netlink_padded_len() */
-#define NETLINK_ALIGN 4
-
/* from nftables:include/datatype.h, TYPE_BITS */
#define CONCAT_TYPE_BITS 6
@@ -1167,7 +1164,7 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
type = type << CONCAT_TYPE_BITS | NFT_DATATYPE_IPADDR;
len += sizeof(struct in_addr) + NETLINK_ALIGN - 1;
len &= ~(NETLINK_ALIGN - 1);
- flags = NFT_SET_INTERVAL;
+ flags = NFT_SET_INTERVAL | NFT_SET_CONCAT;
}
s = add_anon_set(h, table, flags, type, len, cnt);
@@ -1208,8 +1205,9 @@ static int __add_nft_among(struct nft_handle *h, const char *table,
nftnl_rule_add_expr(r, e);
if (ip) {
+ reg = nft_get_next_reg(reg, ETH_ALEN);
e = __gen_payload(NFT_PAYLOAD_NETWORK_HEADER, ip_addr_off[dst],
- sizeof(struct in_addr), NFT_REG32_02);
+ sizeof(struct in_addr), reg);
if (!e)
return -ENOMEM;
nftnl_rule_add_expr(r, e);
@@ -1750,15 +1748,16 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table,
return 1;
}
-void
+bool
nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
enum nft_rule_print type, unsigned int format)
{
const char *chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN);
struct iptables_command_state cs = {};
struct nft_family_ops *ops = h->ops;
+ bool ret;
- ops->rule_to_cs(h, r, &cs);
+ ret = ops->rule_to_cs(h, r, &cs);
if (!(format & (FMT_NOCOUNTS | FMT_C_COUNTS)))
printf("[%llu:%llu] ", (unsigned long long)cs.counters.pcnt,
@@ -1779,6 +1778,8 @@ nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
if (ops->clear_cs)
ops->clear_cs(&cs);
+
+ return ret;
}
static bool nft_rule_is_policy_rule(struct nftnl_rule *r)
@@ -1889,6 +1890,7 @@ int nft_chain_save(struct nft_chain *nc, void *data)
struct nft_rule_save_data {
struct nft_handle *h;
unsigned int format;
+ unsigned int errors;
};
static int nft_rule_save_cb(struct nft_chain *c, void *data)
@@ -1903,7 +1905,11 @@ static int nft_rule_save_cb(struct nft_chain *c, void *data)
r = nftnl_rule_iter_next(iter);
while (r != NULL) {
- nft_rule_print_save(d->h, r, NFT_RULE_APPEND, d->format);
+ bool ret = nft_rule_print_save(d->h, r, NFT_RULE_APPEND, d->format);
+
+ if (!ret)
+ d->errors++;
+
r = nftnl_rule_iter_next(iter);
}
@@ -1921,6 +1927,9 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format)
ret = nft_chain_foreach(h, table, nft_rule_save_cb, &d);
+ if (ret == 0 && d.errors)
+ xtables_error(VERSION_PROBLEM, "Cannot decode all rules provided by kernel");
+
/* the core expects 1 for success and 0 for error */
return ret == 0 ? 1 : 0;
}
@@ -2343,15 +2352,18 @@ static bool nft_rule_cmp(struct nft_handle *h, struct nftnl_rule *r,
struct nftnl_rule *rule)
{
struct iptables_command_state _cs = {}, this = {}, *cs = &_cs;
- bool ret = false;
+ bool ret = false, ret_this, ret_that;
- h->ops->rule_to_cs(h, r, &this);
- h->ops->rule_to_cs(h, rule, cs);
+ ret_this = h->ops->rule_to_cs(h, r, &this);
+ ret_that = h->ops->rule_to_cs(h, rule, cs);
DEBUGP("comparing with... ");
#ifdef DEBUG_DEL
nft_rule_print_save(h, r, NFT_RULE_APPEND, 0);
#endif
+ if (!ret_this || !ret_that)
+ DEBUGP("Cannot convert rules: %d %d\n", ret_this, ret_that);
+
if (!h->ops->is_same(cs, &this))
goto out;
@@ -2862,10 +2874,11 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain,
goto error;
}
- nft_rule_to_iptables_command_state(h, r, &cs);
-
+ h->ops->rule_to_cs(h, r, &cs);
cs.counters.pcnt = cs.counters.bcnt = 0;
new_rule = nft_rule_new(h, chain, table, &cs);
+ h->ops->clear_cs(&cs);
+
if (!new_rule)
return 1;
@@ -2893,8 +2906,8 @@ static void nft_compat_table_batch_add(struct nft_handle *h, uint16_t type,
{
struct nlmsghdr *nlh;
- nlh = nftnl_table_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
- type, h->family, flags, seq);
+ nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
+ type, h->family, flags, seq);
nftnl_table_nlmsg_build_payload(nlh, table);
nft_table_print_debug(h, table, nlh);
}
@@ -2938,8 +2951,8 @@ static void nft_compat_chain_batch_add(struct nft_handle *h, uint16_t type,
{
struct nlmsghdr *nlh;
- nlh = nftnl_chain_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
- type, h->family, flags, seq);
+ nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
+ type, h->family, flags, seq);
nftnl_chain_nlmsg_build_payload(nlh, chain);
nft_chain_print_debug(h, chain, nlh);
}
@@ -2950,8 +2963,8 @@ static void nft_compat_rule_batch_add(struct nft_handle *h, uint16_t type,
{
struct nlmsghdr *nlh;
- nlh = nftnl_rule_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
- type, h->family, flags, seq);
+ nlh = nftnl_nlmsg_build_hdr(nftnl_batch_buffer(h->batch),
+ type, h->family, flags, seq);
nftnl_rule_nlmsg_build_payload(nlh, rule);
nft_rule_print_debug(h, rule, nlh);
}
@@ -3360,6 +3373,8 @@ static int nft_prepare(struct nft_handle *h)
nft_cache_build(h);
list_for_each_entry_safe(cmd, next, &h->cmd_list, head) {
+ h->error.lineno = cmd->error.lineno;
+
switch (cmd->command) {
case NFT_COMPAT_TABLE_FLUSH:
ret = nft_table_flush(h, cmd->table);
@@ -3857,6 +3872,6 @@ void nft_assert_table_compatible(struct nft_handle *h,
chain = "";
}
xtables_error(OTHER_PROBLEM,
- "%s%s%stable `%s' is incompatible, use 'nft' tool.\n",
+ "%s%s%stable `%s' is incompatible, use 'nft' tool.",
pfx, chain, sfx, table);
}
diff --git a/iptables/nft.h b/iptables/nft.h
index 68b0910c..caff1fde 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -203,7 +203,7 @@ enum nft_rule_print {
NFT_RULE_DEL,
};
-void nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
+bool nft_rule_print_save(struct nft_handle *h, const struct nftnl_rule *r,
enum nft_rule_print type, unsigned int format);
uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag);
diff --git a/iptables/tests/shell/run-tests.sh b/iptables/tests/shell/run-tests.sh
index 7878760f..7a80af34 100755
--- a/iptables/tests/shell/run-tests.sh
+++ b/iptables/tests/shell/run-tests.sh
@@ -122,7 +122,8 @@ EOF
if [ "$VALGRIND" == "y" ]; then
tmpd=$(mktemp -d)
msg_info "writing valgrind logs to $tmpd"
- chmod a+rx $tmpd
+ # let nobody write logs, too (././testcases/iptables/0008-unprivileged_0)
+ chmod 777 $tmpd
printscript "$XTABLES_NFT_MULTI" "$tmpd" >${tmpd}/xtables-nft-multi
printscript "$XTABLES_LEGACY_MULTI" "$tmpd" >${tmpd}/xtables-legacy-multi
trap "rm ${tmpd}/xtables-*-multi" EXIT
diff --git a/iptables/tests/shell/testcases/chain/0006rename-segfault_0 b/iptables/tests/shell/testcases/chain/0006rename-segfault_0
new file mode 100755
index 00000000..c10a8006
--- /dev/null
+++ b/iptables/tests/shell/testcases/chain/0006rename-segfault_0
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Cover for a bug in libiptc:
+# - the chain 'node-98-tmp' is the last in the list sorted by name
+# - there are 81 chains in total, so three chain index buckets
+# - the last index bucket contains only the 'node-98-tmp' chain
+# => rename temporarily removes it from the bucket, leaving a NULL bucket
+# behind which is dereferenced later when inserting the chain again with new
+# name again
+
+(
+ echo "*filter"
+ for chain in node-1 node-10 node-101 node-102 node-104 node-107 node-11 node-12 node-13 node-14 node-15 node-16 node-17 node-18 node-19 node-2 node-20 node-21 node-22 node-23 node-25 node-26 node-27 node-28 node-29 node-3 node-30 node-31 node-32 node-33 node-34 node-36 node-37 node-39 node-4 node-40 node-41 node-42 node-43 node-44 node-45 node-46 node-47 node-48 node-49 node-5 node-50 node-51 node-53 node-54 node-55 node-56 node-57 node-58 node-59 node-6 node-60 node-61 node-62 node-63 node-64 node-65 node-66 node-68 node-69 node-7 node-70 node-71 node-74 node-75 node-76 node-8 node-80 node-81 node-86 node-89 node-9 node-92 node-93 node-95 node-98-tmp; do
+ echo ":$chain - [0:0]"
+ done
+ echo "COMMIT"
+) | $XT_MULTI iptables-restore
+$XT_MULTI iptables -E node-98-tmp node-98
+exit $?
diff --git a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
index ccdef19c..1091a4e8 100755
--- a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
+++ b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0
@@ -13,8 +13,8 @@ $XT_MULTI ebtables -A INPUT -p IPv4 -i lo -j ACCEPT
$XT_MULTI ebtables -P FORWARD DROP
$XT_MULTI ebtables -A OUTPUT -s ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff -j DROP
$XT_MULTI ebtables -N foo
-$XT_MULTI ebtables -A foo --802_3-sap 0x23 -j ACCEPT
-$XT_MULTI ebtables -A foo --802_3-sap 0xaa --802_3-type 0x1337 -j ACCEPT
+$XT_MULTI ebtables -A foo -p length --802_3-sap 0x23 -j ACCEPT
+$XT_MULTI ebtables -A foo -p length --802_3-sap 0xaa --802_3-type 0x1337 -j ACCEPT
#$XT_MULTI ebtables -A foo --among-dst fe:ed:ba:be:00:01,fe:ed:ba:be:00:02,fe:ed:ba:be:00:03 -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-gratuitous -j ACCEPT
$XT_MULTI ebtables -A foo -p ARP --arp-opcode Request -j ACCEPT
@@ -44,7 +44,7 @@ $XT_MULTI ebtables -A foo --pkttype-type multicast -j ACCEPT
$XT_MULTI ebtables -A foo --stp-type config -j ACCEPT
#$XT_MULTI ebtables -A foo --vlan-id 42 -j ACCEPT
-$XT_MULTI ebtables -A foo --802_3-sap 0x23 --limit 100 -j ACCEPT
+$XT_MULTI ebtables -A foo -p length --802_3-sap 0x23 --limit 100 -j ACCEPT
$XT_MULTI ebtables -A foo --pkttype-type multicast --log
$XT_MULTI ebtables -A foo --pkttype-type multicast --limit 100 -j ACCEPT
@@ -75,8 +75,8 @@ DUMP='*filter
-A INPUT -p IPv4 -i lo -j ACCEPT
-A FORWARD -j foo
-A OUTPUT -s Broadcast -j DROP
--A foo --802_3-sap 0x23 -j ACCEPT
--A foo --802_3-sap 0xaa --802_3-type 0x1337 -j ACCEPT
+-A foo -p Length --802_3-sap 0x23 -j ACCEPT
+-A foo -p Length --802_3-sap 0xaa --802_3-type 0x1337 -j ACCEPT
-A foo -p ARP --arp-gratuitous -j ACCEPT
-A foo -p ARP --arp-op Request -j ACCEPT
-A foo -p ARP --arp-ip-src 10.0.0.1 -j ACCEPT
@@ -91,13 +91,13 @@ DUMP='*filter
-A foo -p IPv6 --ip6-dst feed:babe::/64 -j ACCEPT
-A foo -p IPv6 --ip6-proto tcp -j ACCEPT
-A foo --limit 100/sec --limit-burst 42 -j ACCEPT
--A foo --log-level notice --log-prefix "" -j CONTINUE
+-A foo --log-level notice -j CONTINUE
-A foo -j mark --mark-set 0x23 --mark-target ACCEPT
-A foo --nflog-group 1 -j CONTINUE
-A foo --pkttype-type multicast -j ACCEPT
-A foo --stp-type config -j ACCEPT
--A foo --802_3-sap 0x23 --limit 100/sec --limit-burst 5 -j ACCEPT
--A foo --pkttype-type multicast --log-level notice --log-prefix "" -j CONTINUE
+-A foo -p Length --802_3-sap 0x23 --limit 100/sec --limit-burst 5 -j ACCEPT
+-A foo --pkttype-type multicast --log-level notice -j CONTINUE
-A foo --pkttype-type multicast --limit 100/sec --limit-burst 5 -j ACCEPT
*nat
:PREROUTING ACCEPT
diff --git a/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0 b/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0
index 63891c1b..7554ef85 100755
--- a/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0
+++ b/iptables/tests/shell/testcases/ebtables/0003-ebtables-restore-defaults_0
@@ -24,7 +24,7 @@ EXPECT='*filter
-A FORWARD --limit 100/sec --limit-burst 42 -j ACCEPT
-A FORWARD --limit 1000/sec --limit-burst 5 -j ACCEPT
-A FORWARD --log-level notice --log-prefix "foobar" -j CONTINUE
--A FORWARD --log-level notice --log-prefix "" -j CONTINUE'
+-A FORWARD --log-level notice -j CONTINUE'
$XT_MULTI ebtables --init-table
$XT_MULTI ebtables-restore <<<$DUMP
diff --git a/iptables/tests/shell/testcases/ebtables/0006-flush_0 b/iptables/tests/shell/testcases/ebtables/0006-flush_0
new file mode 100755
index 00000000..5d714529
--- /dev/null
+++ b/iptables/tests/shell/testcases/ebtables/0006-flush_0
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+set -e
+
+# there is no legacy backend to test
+[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
+
+RULESET='*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+-A FORWARD --among-dst fe:ed:ba:be:13:37=10.0.0.1 -j ACCEPT
+-A OUTPUT --among-src c0:ff:ee:90:0:0=192.168.0.1 -j DROP
+*nat
+:PREROUTING ACCEPT
+:OUTPUT ACCEPT
+:POSTROUTING ACCEPT
+-A OUTPUT --among-src c0:ff:ee:90:90:90=192.168.0.1 -j DROP'
+
+$XT_MULTI ebtables-restore <<<$RULESET
+diff -u <(echo -e "$RULESET") <($XT_MULTI ebtables-save | grep -v '^#')
+
+RULESET='*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+-A FORWARD --among-dst fe:ed:ba:be:13:37=10.0.0.1 -j ACCEPT
+-A OUTPUT --among-src c0:ff:ee:90:0:0=192.168.0.1 -j DROP
+*nat
+:PREROUTING ACCEPT
+:OUTPUT ACCEPT
+:POSTROUTING ACCEPT'
+
+$XT_MULTI ebtables -t nat -F
+diff -u <(echo -e "$RULESET") <($XT_MULTI ebtables-save | grep -v '^#')
+
+RULESET='*filter
+:INPUT ACCEPT
+:FORWARD ACCEPT
+:OUTPUT ACCEPT
+*nat
+:PREROUTING ACCEPT
+:OUTPUT ACCEPT
+:POSTROUTING ACCEPT'
+
+$XT_MULTI ebtables -t filter -F
+diff -u <(echo -e "$RULESET") <($XT_MULTI ebtables-save | grep -v '^#')
diff --git a/iptables/tests/shell/testcases/ebtables/0008-ebtables-among_0 b/iptables/tests/shell/testcases/ebtables/0008-ebtables-among_0
new file mode 100755
index 00000000..b5df9725
--- /dev/null
+++ b/iptables/tests/shell/testcases/ebtables/0008-ebtables-among_0
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+case "$XT_MULTI" in
+*xtables-nft-multi)
+ ;;
+*)
+ echo "skip $XT_MULTI"
+ exit 0
+ ;;
+esac
+
+sfx=$(mktemp -u "XXXXXXXX")
+nsa="nsa-$sfx"
+nsb="nsb-$sfx"
+nsc="nsc-$sfx"
+
+cleanup()
+{
+ ip netns del "$nsa"
+ ip netns del "$nsb"
+ ip netns del "$nsc"
+}
+
+trap cleanup EXIT
+
+assert_fail()
+{
+ if [ $1 -eq 0 ]; then
+ echo "FAILED: $2"
+ exit 1
+ fi
+}
+
+assert_pass()
+{
+ if [ $1 -ne 0 ]; then
+ echo "FAILED: $2"
+ exit 2
+ fi
+}
+
+ip netns add "$nsa"
+ip netns add "$nsb"
+ip netns add "$nsc"
+
+ip link add name c_b netns "$nsc" type veth peer name b_c netns "$nsb"
+ip link add name s_b netns "$nsa" type veth peer name b_s netns "$nsb"
+ip netns exec "$nsb" ip link add name br0 type bridge
+
+ip -net "$nsb" link set b_c up
+ip netns exec "$nsb" ip link set b_s up
+ip netns exec "$nsb" ip addr add 10.167.11.254/24 dev br0
+ip netns exec "$nsb" ip link set br0 up
+ip netns exec "$nsb" ip link set b_c master br0
+ip netns exec "$nsb" ip link set b_s master br0
+ip netns exec "$nsc" ip addr add 10.167.11.2/24 dev c_b
+ip netns exec "$nsc" ip link set c_b up
+ip -net "$nsa" addr add 10.167.11.1/24 dev s_b
+ip -net "$nsa" link set s_b up
+
+ip netns exec "$nsc" ping -q 10.167.11.1 -c1 >/dev/null || exit 1
+
+bf_bridge_mac1=`ip netns exec "$nsb" cat /sys/class/net/b_s/address`
+bf_bridge_mac0=`ip netns exec "$nsb" cat /sys/class/net/b_c/address`
+bf_client_mac1=`ip netns exec "$nsc" cat /sys/class/net/c_b/address`
+bf_server_mac1=`ip netns exec "$nsa" cat /sys/class/net/s_b/address`
+
+bf_server_ip1="10.167.11.1"
+bf_bridge_ip0="10.167.11.254"
+bf_client_ip1="10.167.11.2"
+pktsize=64
+
+# --among-src [mac,IP]
+ip netns exec "$nsb" $XT_MULTI ebtables -F
+ip netns exec "$nsb" $XT_MULTI ebtables -A FORWARD -p ip --ip-dst $bf_server_ip1 --among-src $bf_bridge_mac0=$bf_bridge_ip0,$bf_client_mac1=$bf_client_ip1 -j DROP > /dev/null
+ip netns exec "$nsc" ping -q $bf_server_ip1 -c 1 -s $pktsize -W 1 >/dev/null
+assert_fail $? "--among-src [match]"
+
+# ip netns exec "$nsb" $XT_MULTI ebtables -L --Ln --Lc
+
+ip netns exec "$nsb" $XT_MULTI ebtables -F
+ip netns exec "$nsb" $XT_MULTI ebtables -A FORWARD -p ip --ip-dst $bf_server_ip1 --among-src ! $bf_bridge_mac0=$bf_bridge_ip0,$bf_client_mac1=$bf_client_ip1 -j DROP > /dev/null
+ip netns exec "$nsc" ping $bf_server_ip1 -c 1 -s $pktsize -W 1 >/dev/null
+assert_pass $? "--among-src [not match]"
+
+# --among-dst [mac,IP]
+ip netns exec "$nsb" $XT_MULTI ebtables -F
+ip netns exec "$nsb" $XT_MULTI ebtables -A FORWARD -p ip --ip-src $bf_client_ip1 --among-dst $bf_client_mac1=$bf_client_ip1,$bf_server_mac1=$bf_server_ip1 -j DROP > /dev/null
+ip netns exec "$nsc" ping -q $bf_server_ip1 -c 1 -s $pktsize -W 1 > /dev/null
+assert_fail $? "--among-dst [match]"
+
+# --among-dst ! [mac,IP]
+ip netns exec "$nsb" $XT_MULTI ebtables -F
+ip netns exec "$nsb" $XT_MULTI ebtables -A FORWARD -p ip --ip-src $bf_client_ip1 --among-dst ! $bf_client_mac1=$bf_client_ip1,$bf_server_mac1=$bf_server_ip1 -j DROP > /dev/null
+ip netns exec "$nsc" ping -q $bf_server_ip1 -c 1 -s $pktsize -W 1 > /dev/null
+assert_pass $? "--among-dst [not match]"
+
+exit 0
diff --git a/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0 b/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0
index 2a1518d6..cc18a94b 100755
--- a/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0
+++ b/iptables/tests/shell/testcases/ip6tables/0002-verbose-output_0
@@ -12,7 +12,7 @@ VOUT2='ACCEPT all opt -- in eth2 out eth3 feed:babe::4 -> feed:babe::5'
RULE3='-p icmpv6 -m icmp6 --icmpv6-type no-route'
VOUT3=' ipv6-icmp opt -- in * out * ::/0 -> ::/0 ipv6-icmptype 1 code 0'
RULE4='-m dst --dst-len 42 -m rt --rt-type 23'
-VOUT4=' all opt -- in * out * ::/0 -> ::/0 dst length:42 rt type:23'
+VOUT4=' all opt -- in * out * ::/0 -> ::/0 dst length:42 rt type:23'
RULE5='-m frag --fragid 1337 -j LOG'
VOUT5='LOG all opt -- in * out * ::/0 -> ::/0 frag id:1337 LOG flags 0 level 4'
@@ -36,7 +36,7 @@ Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
0 0 ACCEPT 0 -- eth2 eth3 feed:babe::1 feed:babe::2
0 0 ACCEPT 0 -- eth2 eth3 feed:babe::4 feed:babe::5
0 0 58 -- * * ::/0 ::/0 ipv6-icmptype 1 code 0
- 0 0 0 -- * * ::/0 ::/0 dst length:42 rt type:23
+ 0 0 0 -- * * ::/0 ::/0 dst length:42 rt type:23
0 0 LOG 0 -- * * ::/0 ::/0 frag id:1337 LOG flags 0 level 4
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
diff --git a/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt b/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt
new file mode 100644
index 00000000..73d7108c
--- /dev/null
+++ b/iptables/tests/shell/testcases/nft-only/0010-iptables-nft-save.txt
@@ -0,0 +1,26 @@
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+-A INPUT -s 1.2.3.4/32 -p tcp -m tcp --dport 23 -j ACCEPT
+-A INPUT -s 1.2.3.0/24 -d 0.0.0.0/32 -p udp -m udp --dport 67:69 -j DROP
+-A INPUT -s 1.0.0.0/8 -d 0.0.0.0/32 -p tcp -m tcp --sport 1024:65535 --dport 443 --tcp-flags SYN,ACK SYN -j ACCEPT
+-A INPUT -p tcp -m tcp --dport 443 ! --tcp-flags SYN NONE -m comment --comment "checks if SYN bit is set"
+-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "same as iptables --syn"
+-A INPUT -p tcp -m tcp --tcp-flags SYN SYN
+-A INPUT -p tcp -m tcp ! --tcp-flags SYN,ACK SYN,ACK
+-A INPUT -d 0.0.0.0/1 -m ttl --ttl-eq 1 -j DROP
+-A INPUT -d 0.0.0.0/2 -m ttl --ttl-gt 2 -j ACCEPT
+-A INPUT -d 0.0.0.0/3 -m ttl --ttl-lt 254 -j ACCEPT
+-A INPUT -d 0.0.0.0/4 -m ttl ! --ttl-eq 255 -j DROP
+-A INPUT -d 8.0.0.0/5 -p icmp -j ACCEPT
+-A INPUT -d 8.0.0.0/6 -p icmp -j ACCEPT
+-A INPUT -d 10.0.0.0/7 -p icmp -j ACCEPT
+-A INPUT -m pkttype --pkt-type broadcast -j ACCEPT
+-A INPUT -m pkttype ! --pkt-type unicast -j DROP
+-A INPUT -p tcp
+-A INPUT -d 0.0.0.0/1 -p udp
+-A FORWARD -m limit --limit 10/day
+-A FORWARD -p udp -m udp --dport 42
+-A FORWARD -i lo -o lo+ -j NFLOG --nflog-prefix "should use NFLOG" --nflog-group 1 --nflog-size 123 --nflog-threshold 42
+COMMIT
diff --git a/iptables/tests/shell/testcases/nft-only/0010-native-delinearize_0 b/iptables/tests/shell/testcases/nft-only/0010-native-delinearize_0
new file mode 100755
index 00000000..7859e76c
--- /dev/null
+++ b/iptables/tests/shell/testcases/nft-only/0010-native-delinearize_0
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+[[ $XT_MULTI == *xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; }
+nft -v >/dev/null || exit 0
+
+set -e
+
+unshare -n bash -c "nft -f $(dirname $0)/0010-nft-native.txt;
+ diff -u -Z $(dirname $0)/0010-iptables-nft-save.txt <($XT_MULTI iptables-save | grep -v '^#')"
diff --git a/iptables/tests/shell/testcases/nft-only/0010-nft-native.txt b/iptables/tests/shell/testcases/nft-only/0010-nft-native.txt
new file mode 100644
index 00000000..d37ce873
--- /dev/null
+++ b/iptables/tests/shell/testcases/nft-only/0010-nft-native.txt
@@ -0,0 +1,41 @@
+table ip filter {
+ chain INPUT {
+ type filter hook input priority filter; policy accept;
+
+ ip saddr 1.2.3.4 tcp dport 23 accept
+ ip saddr 1.2.3.0/24 ip daddr 0.0.0.0 udp dport 67-69 drop
+
+ ip saddr 1.0.0.0/8 ip daddr 0.0.0.0 tcp sport 1024-65535 tcp dport 443 tcp flags syn / syn,ack accept
+ tcp dport 443 tcp flags syn comment "checks if SYN bit is set"
+ tcp flags syn / syn,rst,ack,fin comment "same as iptables --syn"
+ tcp flags & syn == syn
+ tcp flags & (syn | ack) != (syn | ack )
+
+ ip daddr 0.0.0.0/1 ip ttl 1 drop
+ ip daddr 0.0.0.0/2 ip ttl > 2 accept
+ ip daddr 0.0.0.0/3 ip ttl < 254 accept
+ ip daddr 0.0.0.0/4 ip ttl != 255 drop
+
+ ip daddr 8.0.0.0/5 icmp type 1 accept
+ ip daddr 8.0.0.0/6 icmp type 2 icmp code port-unreachable accept
+ ip daddr 10.0.0.0/7 icmp type echo-request accept
+
+ meta pkttype broadcast accept
+ meta pkttype != host drop
+
+ ip saddr 0.0.0.0/0 ip protocol tcp
+ ip daddr 0.0.0.0/1 ip protocol udp
+ }
+
+ chain FORWARD {
+ type filter hook forward priority filter;
+ limit rate 10/day counter
+ udp dport 42 counter
+
+ # FIXME: can't dissect plain syslog
+ # meta iif "lo" log prefix "just doing a log" level alert flags tcp sequence,options
+
+ # iif, not iifname, and wildcard
+ meta iif "lo" oifname "lo*" log group 1 prefix "should use NFLOG" queue-threshold 42 snaplen 123
+ }
+}
diff --git a/iptables/xshared.c b/iptables/xshared.c
index 69515789..f93529b1 100644
--- a/iptables/xshared.c
+++ b/iptables/xshared.c
@@ -400,15 +400,15 @@ bool tokenize_rule_counters(char **bufferp, char **pcntp, char **bcntp, int line
ptr = strchr(buffer, ']');
if (!ptr)
- xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line);
+ xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]", line);
pcnt = strtok(buffer+1, ":");
if (!pcnt)
- xtables_error(PARAMETER_PROBLEM, "Bad line %u: need :\n", line);
+ xtables_error(PARAMETER_PROBLEM, "Bad line %u: need :", line);
bcnt = strtok(NULL, "]");
if (!bcnt)
- xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]\n", line);
+ xtables_error(PARAMETER_PROBLEM, "Bad line %u: need ]", line);
*pcntp = pcnt;
*bcntp = bcnt;
@@ -433,10 +433,10 @@ void add_argv(struct argv_store *store, const char *what, int quoted)
if (store->argc + 1 >= MAX_ARGC)
xtables_error(PARAMETER_PROBLEM,
- "Parser cannot handle more arguments\n");
+ "Parser cannot handle more arguments");
if (!what)
xtables_error(PARAMETER_PROBLEM,
- "Trying to store NULL argument\n");
+ "Trying to store NULL argument");
store->argv[store->argc] = xtables_strdup(what);
store->argvattr[store->argc] = quoted;
@@ -900,8 +900,7 @@ static char cmd2char(int option)
;
if (i >= ARRAY_SIZE(cmdflags))
xtables_error(OTHER_PROBLEM,
- "cmd2char(): Invalid command number %u.\n",
- 1 << i);
+ "cmd2char(): Invalid command number %u.", 1 << i);
return cmdflags[i];
}
@@ -911,8 +910,8 @@ static void add_command(unsigned int *cmd, const int newcmd,
if (invert)
xtables_error(PARAMETER_PROBLEM, "unexpected '!' flag");
if (*cmd & (~othercmds))
- xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
- cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
+ xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c",
+ cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
*cmd |= newcmd;
}
@@ -979,9 +978,8 @@ static void generic_opt_check(int command, int options)
if (!(options & (1<<i))) {
if (commands_v_options[j][i] == '+')
xtables_error(PARAMETER_PROBLEM,
- "You need to supply the `-%c' "
- "option for this command\n",
- optflags[i]);
+ "You need to supply the `-%c' option for this command",
+ optflags[i]);
} else {
if (commands_v_options[j][i] != 'x')
legal = 1;
@@ -991,8 +989,8 @@ static void generic_opt_check(int command, int options)
}
if (legal == -1)
xtables_error(PARAMETER_PROBLEM,
- "Illegal option `-%c' with this command\n",
- optflags[i]);
+ "Illegal option `-%c' with this command",
+ optflags[i]);
}
}
@@ -1060,12 +1058,12 @@ void assert_valid_chain_name(const char *chainname)
if (*chainname == '-' || *chainname == '!')
xtables_error(PARAMETER_PROBLEM,
- "chain name not allowed to start with `%c'\n",
+ "chain name not allowed to start with `%c'",
*chainname);
if (xtables_find_target(chainname, XTF_TRY_LOAD))
xtables_error(PARAMETER_PROBLEM,
- "chain name may not clash with target name\n");
+ "chain name may not clash with target name");
for (ptr = chainname; *ptr; ptr++)
if (isspace(*ptr))
@@ -1358,6 +1356,23 @@ static const char *optstring_lookup(int family)
return "";
}
+void xtables_clear_iptables_command_state(struct iptables_command_state *cs)
+{
+ xtables_rule_matches_free(&cs->matches);
+ if (cs->target) {
+ free(cs->target->t);
+ cs->target->t = NULL;
+
+ free(cs->target->udata);
+ cs->target->udata = NULL;
+
+ if (cs->target == cs->target->next) {
+ free(cs->target);
+ cs->target = NULL;
+ }
+ }
+}
+
void do_parse(int argc, char *argv[],
struct xt_cmd_parse *p, struct iptables_command_state *cs,
struct xtables_args *args)
@@ -1528,6 +1543,9 @@ void do_parse(int argc, char *argv[],
XTF_TRY_LOAD, &cs->matches);
xtables_printhelp(cs->matches);
+ xtables_clear_iptables_command_state(cs);
+ xtables_free_opts(1);
+ xtables_fini();
exit(0);
/*
@@ -2000,3 +2018,37 @@ void ipv6_post_parse(int command, struct iptables_command_state *cs,
"! not allowed with multiple"
" source or destination IP addresses");
}
+
+unsigned char *
+make_delete_mask(const struct xtables_rule_match *matches,
+ const struct xtables_target *target,
+ size_t entry_size)
+{
+ /* Establish mask for comparison */
+ unsigned int size = entry_size;
+ const struct xtables_rule_match *matchp;
+ unsigned char *mask, *mptr;
+
+ for (matchp = matches; matchp; matchp = matchp->next)
+ size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
+
+ mask = xtables_calloc(1, size
+ + XT_ALIGN(sizeof(struct xt_entry_target))
+ + target->size);
+
+ memset(mask, 0xFF, entry_size);
+ mptr = mask + entry_size;
+
+ for (matchp = matches; matchp; matchp = matchp->next) {
+ memset(mptr, 0xFF,
+ XT_ALIGN(sizeof(struct xt_entry_match))
+ + matchp->match->userspacesize);
+ mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
+ }
+
+ memset(mptr, 0xFF,
+ XT_ALIGN(sizeof(struct xt_entry_target))
+ + target->userspacesize);
+
+ return mask;
+}
diff --git a/iptables/xshared.h b/iptables/xshared.h
index 1a019a7c..0ed9f3c2 100644
--- a/iptables/xshared.h
+++ b/iptables/xshared.h
@@ -37,6 +37,11 @@ enum {
OPT_OPCODE = 1 << 15,
OPT_H_TYPE = 1 << 16,
OPT_P_TYPE = 1 << 17,
+ /* below are for ebtables only */
+ OPT_LOGICALIN = 1 << 18,
+ OPT_LOGICALOUT = 1 << 19,
+ OPT_COMMAND = 1 << 20,
+ OPT_ZERO = 1 << 21,
};
enum {
@@ -125,6 +130,8 @@ struct iptables_command_state {
bool restore;
};
+void xtables_clear_iptables_command_state(struct iptables_command_state *cs);
+
typedef int (*mainfunc_t)(int, char **);
struct subcommand {
@@ -288,4 +295,8 @@ void ipv6_post_parse(int command, struct iptables_command_state *cs,
extern char *arp_opcodes[];
#define ARP_NUMOPCODES 9
+unsigned char *make_delete_mask(const struct xtables_rule_match *matches,
+ const struct xtables_target *target,
+ size_t entry_size);
+
#endif /* IPTABLES_XSHARED_H */
diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c
index 86177024..13b6b864 100644
--- a/iptables/xtables-eb-translate.c
+++ b/iptables/xtables-eb-translate.c
@@ -156,17 +156,17 @@ static int nft_rule_eb_xlate_add(struct nft_handle *h, const struct xt_cmd_parse
const struct iptables_command_state *cs, bool append)
{
struct xt_xlate *xl = xt_xlate_alloc(10240);
+ const char *tick = cs->restore ? "" : "'";
int ret;
- if (append) {
- xt_xlate_add(xl, "add rule bridge %s %s ", p->table, p->chain);
- } else {
- xt_xlate_add(xl, "insert rule bridge %s %s ", p->table, p->chain);
- }
+ xt_xlate_add(xl, "%s%s rule bridge %s %s ", tick,
+ append ? "add" : "insert", p->table, p->chain);
ret = h->ops->xlate(cs, xl);
if (ret)
- printf("%s\n", xt_xlate_get(xl));
+ printf("%s%s\n", xt_xlate_get(xl), tick);
+ else
+ printf("%s ", tick);
xt_xlate_free(xl);
return ret;
@@ -294,7 +294,7 @@ print_zero:
"Multiple commands are not allowed");
if (exec_style == EXEC_STYLE_DAEMON)
xtables_error(PARAMETER_PROBLEM,
- "%s %s\n", prog_name, prog_vers);
+ "%s %s", prog_name, prog_vers);
printf("%s %s\n", prog_name, prog_vers);
exit(0);
case 'h':
diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c
index b986fd9e..7214a767 100644
--- a/iptables/xtables-eb.c
+++ b/iptables/xtables-eb.c
@@ -157,22 +157,6 @@ int ebt_get_current_chain(const char *chain)
/* Checks whether a command has already been specified */
#define OPT_COMMANDS (flags & OPT_COMMAND || flags & OPT_ZERO)
-#define OPT_COMMAND 0x01
-#define OPT_TABLE 0x02
-#define OPT_IN 0x04
-#define OPT_OUT 0x08
-#define OPT_JUMP 0x10
-#define OPT_PROTOCOL 0x20
-#define OPT_SOURCE 0x40
-#define OPT_DEST 0x80
-#define OPT_ZERO 0x100
-#define OPT_LOGICALIN 0x200
-#define OPT_LOGICALOUT 0x400
-#define OPT_KERNELDATA 0x800 /* This value is also defined in ebtablesd.c */
-#define OPT_COUNT 0x1000 /* This value is also defined in libebtc.c */
-#define OPT_CNT_INCR 0x2000 /* This value is also defined in libebtc.c */
-#define OPT_CNT_DECR 0x4000 /* This value is also defined in libebtc.c */
-
/* Default command line options. Do not mess around with the already
* assigned numbers unless you know what you are doing */
struct option ebt_original_options[] =
@@ -214,6 +198,7 @@ struct option ebt_original_options[] =
{ "delete-chain" , optional_argument, 0, 'X' },
{ "init-table" , no_argument , 0, 11 },
{ "concurrent" , no_argument , 0, 13 },
+ { "check" , required_argument, 0, 14 },
{ 0 }
};
@@ -746,6 +731,7 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table,
case 'N': /* Make a user defined chain */
case 'E': /* Rename chain */
case 'X': /* Delete chain */
+ case 14: /* check a rule */
/* We allow -N chainname -P policy */
if (command == 'N' && c == 'P') {
command = c;
@@ -897,11 +883,13 @@ print_zero:
}
break;
case 't': /* Table */
- ebt_check_option2(&flags, OPT_TABLE);
if (restore && table_set)
xtables_error(PARAMETER_PROBLEM,
- "The -t option cannot be used in %s.\n",
+ "The -t option cannot be used in %s.",
xt_params->program_name);
+ else if (table_set)
+ xtables_error(PARAMETER_PROBLEM,
+ "Multiple use of same option not allowed");
if (!nft_table_builtin_find(h, optarg))
xtables_error(VERSION_PROBLEM,
"table '%s' does not exist",
@@ -921,11 +909,12 @@ print_zero:
if (!OPT_COMMANDS)
xtables_error(PARAMETER_PROBLEM,
"No command specified");
- if (command != 'A' && command != 'D' && command != 'I' && command != 'C')
+ if (command != 'A' && command != 'D' &&
+ command != 'I' && command != 'C' && command != 14)
xtables_error(PARAMETER_PROBLEM,
"Command and option do not match");
if (c == 'i') {
- ebt_check_option2(&flags, OPT_IN);
+ ebt_check_option2(&flags, OPT_VIANAMEIN);
if (selected_chain > 2 && selected_chain < NF_BR_BROUTING)
xtables_error(PARAMETER_PROBLEM,
"Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains");
@@ -945,7 +934,7 @@ print_zero:
ebtables_parse_interface(optarg, cs.eb.logical_in);
break;
} else if (c == 'o') {
- ebt_check_option2(&flags, OPT_OUT);
+ ebt_check_option2(&flags, OPT_VIANAMEOUT);
if (selected_chain < 2 || selected_chain == NF_BR_BROUTING)
xtables_error(PARAMETER_PROBLEM,
"Use -o only in OUTPUT, FORWARD and POSTROUTING chains");
@@ -982,7 +971,7 @@ print_zero:
cs.eb.bitmask |= EBT_SOURCEMAC;
break;
} else if (c == 'd') {
- ebt_check_option2(&flags, OPT_DEST);
+ ebt_check_option2(&flags, OPT_DESTINATION);
if (ebt_check_inverse2(optarg, argc, argv))
cs.eb.invflags |= EBT_IDEST;
@@ -993,7 +982,7 @@ print_zero:
cs.eb.bitmask |= EBT_DESTMAC;
break;
} else if (c == 'c') {
- ebt_check_option2(&flags, OPT_COUNT);
+ ebt_check_option2(&flags, OPT_COUNTERS);
if (ebt_check_inverse2(optarg, argc, argv))
xtables_error(PARAMETER_PROBLEM,
"Unexpected '!' after -c");
@@ -1102,7 +1091,7 @@ print_zero:
argv[optind]);
if (command != 'A' && command != 'I' &&
- command != 'D' && command != 'C')
+ command != 'D' && command != 'C' && command != 14)
xtables_error(PARAMETER_PROBLEM,
"Extensions only for -A, -I, -D and -C");
}
@@ -1123,7 +1112,7 @@ print_zero:
/* Do the final checks */
if (command == 'A' || command == 'I' ||
- command == 'D' || command == 'C') {
+ command == 'D' || command == 'C' || command == 14) {
for (xtrm_i = cs.matches; xtrm_i; xtrm_i = xtrm_i->next)
xtables_option_mfcall(xtrm_i->match);
@@ -1175,6 +1164,9 @@ print_zero:
} else if (command == 'D') {
ret = delete_entry(h, chain, *table, &cs, rule_nr - 1,
rule_nr_end, flags & OPT_VERBOSE);
+ } else if (command == 14) {
+ ret = nft_cmd_rule_check(h, chain, *table,
+ &cs, flags & OPT_VERBOSE);
} /*else if (replace->command == 'C') {
ebt_change_counters(replace, new_entry, rule_nr, rule_nr_end, &(new_entry->cnt_surplus), chcounter);
if (ebt_errormsg[0] != '\0')
diff --git a/iptables/xtables-monitor.c b/iptables/xtables-monitor.c
index a1eba2f4..cf2729d8 100644
--- a/iptables/xtables-monitor.c
+++ b/iptables/xtables-monitor.c
@@ -227,7 +227,7 @@ static void trace_print_rule(const struct nftnl_trace *nlt, struct cb_arg *args)
exit(EXIT_FAILURE);
}
- nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, 0, 0);
+ nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, 0, 0);
nftnl_rule_set_u32(r, NFTNL_RULE_FAMILY, family);
nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c
index 1363f96a..abe56374 100644
--- a/iptables/xtables-restore.c
+++ b/iptables/xtables-restore.c
@@ -115,14 +115,14 @@ static void xtables_restore_parse_line(struct nft_handle *h,
DEBUGP("line %u, table '%s'\n", line, table);
if (!table)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u table name invalid\n",
- xt_params->program_name, line);
+ "%s: line %u table name invalid",
+ xt_params->program_name, line);
state->curtable = nft_table_builtin_find(h, table);
if (!state->curtable)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u table name '%s' invalid\n",
- xt_params->program_name, line, table);
+ "%s: line %u table name '%s' invalid",
+ xt_params->program_name, line, table);
if (p->tablename && (strcmp(p->tablename, table) != 0))
return;
@@ -152,8 +152,8 @@ static void xtables_restore_parse_line(struct nft_handle *h,
DEBUGP("line %u, chain '%s'\n", line, chain);
if (!chain)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u chain name invalid\n",
- xt_params->program_name, line);
+ "%s: line %u chain name invalid",
+ xt_params->program_name, line);
xtables_announce_chain(chain);
assert_valid_chain_name(chain);
@@ -162,8 +162,8 @@ static void xtables_restore_parse_line(struct nft_handle *h,
DEBUGP("line %u, policy '%s'\n", line, policy);
if (!policy)
xtables_error(PARAMETER_PROBLEM,
- "%s: line %u policy invalid\n",
- xt_params->program_name, line);
+ "%s: line %u policy invalid",
+ xt_params->program_name, line);
if (nft_chain_builtin_find(state->curtable, chain)) {
if (counters) {
@@ -172,15 +172,15 @@ static void xtables_restore_parse_line(struct nft_handle *h,
if (!ctrs || !parse_counters(ctrs, &count))
xtables_error(PARAMETER_PROBLEM,
- "invalid policy counters for chain '%s'\n",
- chain);
+ "invalid policy counters for chain '%s'",
+ chain);
}
if (cb->chain_set &&
cb->chain_set(h, state->curtable->name,
chain, policy, &count) < 0) {
xtables_error(OTHER_PROBLEM,
- "Can't set policy `%s' on `%s' line %u: %s\n",
+ "Can't set policy `%s' on `%s' line %u: %s",
policy, chain, line,
strerror(errno));
}
@@ -189,13 +189,13 @@ static void xtables_restore_parse_line(struct nft_handle *h,
} else if (cb->chain_restore(h, chain, state->curtable->name) < 0 &&
errno != EEXIST) {
xtables_error(PARAMETER_PROBLEM,
- "cannot create chain '%s' (%s)\n",
+ "cannot create chain '%s' (%s)",
chain, strerror(errno));
} else if (h->family == NFPROTO_BRIDGE &&
!ebt_cmd_user_chain_policy(h, state->curtable->name,
chain, policy)) {
xtables_error(OTHER_PROBLEM,
- "Can't set policy `%s' on `%s' line %u: %s\n",
+ "Can't set policy `%s' on `%s' line %u: %s",
policy, chain, line,
strerror(errno));
}
@@ -249,8 +249,11 @@ static void xtables_restore_parse_line(struct nft_handle *h,
(strcmp(p->tablename, state->curtable->name) != 0))
return;
if (!ret) {
- fprintf(stderr, "%s: line %u failed\n",
- xt_params->program_name, line);
+ fprintf(stderr, "%s: line %u failed",
+ xt_params->program_name, h->error.lineno);
+ if (errno)
+ fprintf(stderr, ": %s.", nft_strerror(errno));
+ fprintf(stderr, "\n");
exit(1);
}
}
diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c
index d1e87f16..22b2fbc8 100644
--- a/iptables/xtables-translate.c
+++ b/iptables/xtables-translate.c
@@ -41,7 +41,9 @@ void xlate_ifname(struct xt_xlate *xl, const char *nftmeta, const char *ifname,
for (i = 0, j = 0; i < ifaclen + 1; i++, j++) {
switch (ifname[i]) {
case '*':
- iface[j++] = '\\';
+ /* asterisk is non-special mid-string */
+ if (i == ifaclen - 1)
+ iface[j++] = '\\';
/* fall through */
default:
iface[j] = ifname[i];
@@ -83,12 +85,10 @@ int xlate_action(const struct iptables_command_state *cs, bool goto_set,
else if (strcmp(cs->jumpto, XTC_LABEL_RETURN) == 0)
xt_xlate_add(xl, " return");
else if (cs->target->xlate) {
- xt_xlate_add(xl, " ");
struct xt_xlate_tg_params params = {
.ip = (const void *)&cs->fw,
.target = cs->target->t,
.numeric = numeric,
- .escape_quotes = !cs->restore,
};
ret = cs->target->xlate(xl, &params);
}
@@ -115,17 +115,12 @@ int xlate_matches(const struct iptables_command_state *cs, struct xt_xlate *xl)
.ip = (const void *)&cs->fw,
.match = matchp->match->m,
.numeric = numeric,
- .escape_quotes = !cs->restore,
};
if (!matchp->match->xlate)
return 0;
ret = matchp->match->xlate(xl, &params);
-
- if (strcmp(matchp->match->name, "comment") != 0)
- xt_xlate_add(xl, " ");
-
if (!ret)
break;
}
@@ -155,6 +150,7 @@ static int nft_rule_xlate_add(struct nft_handle *h,
bool append)
{
struct xt_xlate *xl = xt_xlate_alloc(10240);
+ const char *tick = cs->restore ? "" : "'";
const char *set;
int ret;
@@ -165,21 +161,20 @@ static int nft_rule_xlate_add(struct nft_handle *h,
set = xt_xlate_set_get(xl);
if (set[0]) {
- printf("add set %s %s %s\n", family2str[h->family], p->table,
- xt_xlate_set_get(xl));
+ printf("%sadd set %s %s %s%s\n",
+ tick, family2str[h->family], p->table,
+ xt_xlate_set_get(xl), tick);
if (!cs->restore && p->command != CMD_NONE)
printf("nft ");
}
- if (append) {
- printf("add rule %s %s %s ",
- family2str[h->family], p->table, p->chain);
- } else {
- printf("insert rule %s %s %s ",
- family2str[h->family], p->table, p->chain);
- }
- printf("%s\n", xt_xlate_rule_get(xl));
+ printf("%s%s rule %s %s %s ",
+ tick,
+ append ? "add" : "insert",
+ family2str[h->family], p->table, p->chain);
+
+ printf("%s%s\n", xt_xlate_rule_get(xl), tick);
err_out:
xt_xlate_free(xl);
@@ -341,7 +336,7 @@ static int do_command_xlate(struct nft_handle *h, int argc, char *argv[],
exit(1);
}
- nft_clear_iptables_command_state(&cs);
+ h->ops->clear_cs(&cs);
if (h->family == AF_INET) {
free(args.s.addr.v4);
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 70924176..22d6ea58 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -262,7 +262,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table,
*table = p.table;
- nft_clear_iptables_command_state(&cs);
+ h->ops->clear_cs(&cs);
free(args.s.addr.ptr);
free(args.s.mask.ptr);
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
index ceeb017b..f9b7779e 100644
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -606,6 +606,15 @@ static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handl
if (index_ptr == &c->list) { /* Chain used as index ptr */
+ /* If this is the last chain in the list, its index bucket just
+ * became empty. Adjust the size to avoid a NULL-pointer deref
+ * later.
+ */
+ if (next == &h->chains) {
+ h->chain_index_sz--;
+ return 0;
+ }
+
/* See if its possible to avoid a rebuild, by shifting
* to next pointer. Its possible if the next pointer
* is located in the same index bucket.
@@ -2545,8 +2554,8 @@ TC_COMMIT(struct xtc_handle *handle)
+ sizeof(STRUCT_COUNTERS) * new_number;
/* These are the old counters we will get from kernel */
- repl->counters = malloc(sizeof(STRUCT_COUNTERS)
- * handle->info.num_entries);
+ repl->counters = calloc(handle->info.num_entries,
+ sizeof(STRUCT_COUNTERS));
if (!repl->counters) {
errno = ENOMEM;
goto out_free_repl;
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index 479dbae0..e3e444ac 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -2490,16 +2490,39 @@ void xt_xlate_free(struct xt_xlate *xl)
free(xl);
}
+static bool isbrace(char c)
+{
+ switch (c) {
+ case '(':
+ case ')':
+ case '{':
+ case '}':
+ case '[':
+ case ']':
+ return true;
+ }
+ return false;
+}
+
static void __xt_xlate_add(struct xt_xlate *xl, enum xt_xlate_type type,
- const char *fmt, va_list ap)
+ bool space, const char *fmt, va_list ap)
{
struct xt_xlate_buf *buf = &xl->buf[type];
+ char tmpbuf[1024] = "";
int len;
- len = vsnprintf(buf->data + buf->off, buf->rem, fmt, ap);
- if (len < 0 || len >= buf->rem)
+ len = vsnprintf(tmpbuf, 1024, fmt, ap);
+ if (len < 0 || len >= buf->rem - 1)
xtables_error(RESOURCE_PROBLEM, "OOM");
+ if (space && buf->off &&
+ !isspace(buf->data[buf->off - 1]) &&
+ (isalnum(tmpbuf[0]) || isbrace(tmpbuf[0]))) {
+ buf->data[buf->off] = ' ';
+ buf->off++;
+ buf->rem--;
+ }
+ sprintf(buf->data + buf->off, "%s", tmpbuf);
buf->rem -= len;
buf->off += len;
}
@@ -2509,7 +2532,16 @@ void xt_xlate_rule_add(struct xt_xlate *xl, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- __xt_xlate_add(xl, XT_XLATE_RULE, fmt, ap);
+ __xt_xlate_add(xl, XT_XLATE_RULE, true, fmt, ap);
+ va_end(ap);
+}
+
+void xt_xlate_rule_add_nospc(struct xt_xlate *xl, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __xt_xlate_add(xl, XT_XLATE_RULE, false, fmt, ap);
va_end(ap);
}
@@ -2518,7 +2550,16 @@ void xt_xlate_set_add(struct xt_xlate *xl, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- __xt_xlate_add(xl, XT_XLATE_SET, fmt, ap);
+ __xt_xlate_add(xl, XT_XLATE_SET, true, fmt, ap);
+ va_end(ap);
+}
+
+void xt_xlate_set_add_nospc(struct xt_xlate *xl, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ __xt_xlate_add(xl, XT_XLATE_SET, false, fmt, ap);
va_end(ap);
}
@@ -2545,7 +2586,12 @@ uint8_t xt_xlate_get_family(struct xt_xlate *xl)
const char *xt_xlate_get(struct xt_xlate *xl)
{
- return xl->buf[XT_XLATE_RULE].data;
+ struct xt_xlate_buf *buf = &xl->buf[XT_XLATE_RULE];
+
+ while (buf->off && isspace(buf->data[buf->off - 1]))
+ buf->data[--buf->off] = '\0';
+
+ return buf->data;
}
const char *xt_xlate_set_get(struct xt_xlate *xl)
diff --git a/libxtables/xtoptions.c b/libxtables/xtoptions.c
index 8174a560..b16bbfbe 100644
--- a/libxtables/xtoptions.c
+++ b/libxtables/xtoptions.c
@@ -924,7 +924,7 @@ void xtables_option_tpcall(unsigned int c, char **argv, bool invert,
cb.entry = xtables_option_lookup(t->x6_options, c);
if (cb.entry == NULL)
xtables_error(OTHER_PROBLEM,
- "Extension does not know id %u\n", c);
+ "Extension does not know id %u", c);
cb.arg = optarg;
cb.invert = invert;
cb.ext_name = t->name;
@@ -960,7 +960,7 @@ void xtables_option_mpcall(unsigned int c, char **argv, bool invert,
cb.entry = xtables_option_lookup(m->x6_options, c);
if (cb.entry == NULL)
xtables_error(OTHER_PROBLEM,
- "Extension does not know id %u\n", c);
+ "Extension does not know id %u", c);
cb.arg = optarg;
cb.invert = invert;
cb.ext_name = m->name;
diff --git a/xlate-test.py b/xlate-test.py
index 03bef7e2..4f037ef6 100755
--- a/xlate-test.py
+++ b/xlate-test.py
@@ -7,6 +7,13 @@ import shlex
import argparse
from subprocess import Popen, PIPE
+def run_proc(args, shell = False, input = None):
+ """A simple wrapper around Popen, returning (rc, stdout, stderr)"""
+ process = Popen(args, text = True, shell = shell,
+ stdin = PIPE, stdout = PIPE, stderr = PIPE)
+ output, error = process.communicate(input)
+ return (process.returncode, output, error)
+
keywords = ("iptables-translate", "ip6tables-translate", "ebtables-translate")
xtables_nft_multi = 'xtables-nft-multi'
@@ -33,45 +40,142 @@ def green(string):
return colors["green"] + string + colors["end"]
+def test_one_xlate(name, sourceline, expected, result):
+ rc, output, error = run_proc([xtables_nft_multi] + shlex.split(sourceline))
+ if rc != 0:
+ result.append(name + ": " + red("Error: ") + "iptables-translate failure")
+ result.append(error)
+ return False
+
+ translation = output.rstrip(" \n")
+ if translation != expected:
+ result.append(name + ": " + red("Fail"))
+ result.append(magenta("src: ") + sourceline.rstrip(" \n"))
+ result.append(magenta("exp: ") + expected)
+ result.append(magenta("res: ") + translation + "\n")
+ return False
+
+ return True
+
+def test_one_replay(name, sourceline, expected, result):
+ global args
+
+ searchline = None
+ if sourceline.find(';') >= 0:
+ sourceline, searchline = sourceline.split(';')
+
+ srcwords = sourceline.split()
+
+ srccmd = srcwords[0]
+ ipt = srccmd.split('-')[0]
+ table_idx = -1
+ chain_idx = -1
+ table_name = "filter"
+ chain_name = None
+ for idx in range(1, len(srcwords)):
+ if srcwords[idx] in ["-A", "-I", "--append", "--insert"]:
+ chain_idx = idx
+ chain_name = srcwords[idx + 1]
+ elif srcwords[idx] in ["-t", "--table"]:
+ table_idx = idx
+ table_name = srcwords[idx + 1]
+
+ if not chain_name:
+ return True # nothing to do?
+
+ if searchline is None:
+ # adjust sourceline as required
+ checkcmd = srcwords[:]
+ checkcmd[0] = ipt
+ checkcmd[chain_idx] = "--check"
+ else:
+ checkcmd = [ipt, "-t", table_name]
+ checkcmd += ["--check", chain_name, searchline]
+
+ fam = ""
+ if srccmd.startswith("ip6"):
+ fam = "ip6 "
+ elif srccmd.startswith("ebt"):
+ fam = "bridge "
+
+ expected = [ l.removeprefix("nft ").strip(" '") for l in expected.split("\n") ]
+ nft_input = [
+ "flush ruleset",
+ "add table " + fam + table_name,
+ "add chain " + fam + table_name + " " + chain_name,
+ ] + expected
+
+ rc, output, error = run_proc([args.nft, "-f", "-"], shell = False, input = "\n".join(nft_input))
+ if rc != 0:
+ result.append(name + ": " + red("Replay Fail"))
+ result.append(args.nft + " call failed: " + error.rstrip('\n'))
+ for line in nft_input:
+ result.append(magenta("input: ") + line)
+ return False
+
+ rc, output, error = run_proc([xtables_nft_multi] + checkcmd)
+ if rc != 0:
+ result.append(name + ": " + red("Check Fail"))
+ result.append(magenta("check: ") + " ".join(checkcmd))
+ result.append(magenta("error: ") + error)
+ rc, output, error = run_proc([xtables_nft_multi, ipt + "-save"])
+ for l in output.split("\n"):
+ result.append(magenta("ipt: ") + l)
+ rc, output, error = run_proc([args.nft, "list", "ruleset"])
+ for l in output.split("\n"):
+ result.append(magenta("nft: ") + l)
+ return False
+
+ return True
+
+
def run_test(name, payload):
global xtables_nft_multi
+ global args
+
test_passed = True
tests = passed = failed = errors = 0
result = []
line = payload.readline()
while line:
- if line.startswith(keywords):
- sourceline = line
+ if not line.startswith(keywords):
+ line = payload.readline()
+ continue
+
+ sourceline = replayline = line.rstrip("\n")
+ if line.find(';') >= 0:
+ sourceline = line.split(';')[0]
+
+ expected = payload.readline().rstrip(" \n")
+ next_expected = payload.readline()
+ if next_expected.startswith("nft"):
+ expected += "\n" + next_expected.rstrip(" \n")
+ line = payload.readline()
+ else:
+ line = next_expected
+
+ tests += 1
+ if test_one_xlate(name, sourceline, expected, result):
+ passed += 1
+ else:
+ errors += 1
+ test_passed = False
+ continue
+
+ if args.replay:
tests += 1
- process = Popen([ xtables_nft_multi ] + shlex.split(line), stdout=PIPE, stderr=PIPE)
- (output, error) = process.communicate()
- if process.returncode == 0:
- translation = output.decode("utf-8").rstrip(" \n")
- expected = payload.readline().rstrip(" \n")
- next_expected = payload.readline()
- if next_expected.startswith("nft"):
- expected += "\n" + next_expected.rstrip(" \n")
- line = payload.readline()
- else:
- line = next_expected
- if translation != expected:
- test_passed = False
- failed += 1
- result.append(name + ": " + red("Fail"))
- result.append(magenta("src: ") + sourceline.rstrip(" \n"))
- result.append(magenta("exp: ") + expected)
- result.append(magenta("res: ") + translation + "\n")
- else:
- passed += 1
+ if test_one_replay(name, replayline, expected, result):
+ passed += 1
else:
- test_passed = False
errors += 1
- result.append(name + ": " + red("Error: ") + "iptables-translate failure")
- result.append(error.decode("utf-8"))
- line = payload.readline()
- else:
- line = payload.readline()
+ test_passed = False
+
+ rc, output, error = run_proc([args.nft, "flush", "ruleset"])
+ if rc != 0:
+ result.append(name + ": " + red("Fail"))
+ result.append("nft flush ruleset call failed: " + error)
+
if (passed == tests) and not args.test:
print(name + ": " + green("OK"))
if not test_passed:
@@ -93,8 +197,44 @@ def load_test_files():
return (test_files, total_tests, total_passed, total_failed, total_error)
+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
+
+
def main():
global xtables_nft_multi
+
+ if args.replay:
+ if os.getuid() != 0:
+ print("Replay test requires root, sorry", file=sys.stderr)
+ return
+ if 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"))
xtables_nft_multi = os.path.abspath(os.path.curdir) \
@@ -126,6 +266,12 @@ def main():
parser = argparse.ArgumentParser()
parser.add_argument('-H', '--host', action='store_true',
help='Run tests against installed binaries')
+parser.add_argument('-R', '--replay', action='store_true',
+ help='Replay tests to check iptables-nft parser')
+parser.add_argument('-n', '--nft', type=str, default='nft',
+ help='Replay using given nft binary (default: \'%(default)s\')')
+parser.add_argument('--no-netns', action='store_true',
+ help='Do not run testsuite in own network namespace')
parser.add_argument("test", nargs="?", help="run only the specified test file")
args = parser.parse_args()
sys.exit(main())