From 029dc76efd6de0bac7422c7a63948c537afbae69 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 01 2019 21:26:06 +0000 Subject: import iptables-1.8.2-12.el8 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4fbf74f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/iptables-1.8.2.tar.bz2 diff --git a/.iptables.metadata b/.iptables.metadata new file mode 100644 index 0000000..d3ab801 --- /dev/null +++ b/.iptables.metadata @@ -0,0 +1 @@ +215c4ef4c6cd29ef0dd265b4fa5ec51a4f930c92 SOURCES/iptables-1.8.2.tar.bz2 diff --git a/SOURCES/0001-Add-iptables-test.py-testsuite-from-v1.8.2.patch b/SOURCES/0001-Add-iptables-test.py-testsuite-from-v1.8.2.patch new file mode 100644 index 0000000..778357d --- /dev/null +++ b/SOURCES/0001-Add-iptables-test.py-testsuite-from-v1.8.2.patch @@ -0,0 +1,2642 @@ +From 2297d219cc3c5150c015ce52df5c96894dd6e3d6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Jun 2019 22:12:15 +0200 +Subject: [PATCH] Add iptables-test.py testsuite from v1.8.2 + +Content gathered via: +| git co v1.8.2 -- iptables-test.py extensions/\*.t + +Signed-off-by: Phil Sutter +--- + extensions/iptables.t | 6 + + extensions/libarpt_CLASSIFY.t | 4 + + extensions/libarpt_MARK.t | 4 + + extensions/libarpt_mangle.t | 5 + + extensions/libarpt_standard.t | 14 ++ + extensions/libebt_802_3.t | 3 + + extensions/libebt_arp.t | 12 + + extensions/libebt_arpreply.t | 4 + + extensions/libebt_dnat.t | 5 + + extensions/libebt_ip.t | 13 ++ + extensions/libebt_ip6.t | 15 ++ + extensions/libebt_log.t | 6 + + extensions/libebt_mark.t | 5 + + extensions/libebt_mark_m.t | 6 + + extensions/libebt_nflog.t | 5 + + extensions/libebt_pkttype.t | 13 ++ + extensions/libebt_redirect.t | 4 + + extensions/libebt_snat.t | 4 + + extensions/libebt_standard.t | 11 + + extensions/libebt_stp.t | 13 ++ + extensions/libebt_vlan.t | 13 ++ + extensions/libip6t_DNAT.t | 16 ++ + extensions/libip6t_DNPT.t | 7 + + extensions/libip6t_HL.t | 10 + + extensions/libip6t_LOG.t | 12 + + extensions/libip6t_MASQUERADE.t | 9 + + extensions/libip6t_NETMAP.t | 4 + + extensions/libip6t_REDIRECT.t | 6 + + extensions/libip6t_REJECT.t | 11 + + extensions/libip6t_SNAT.t | 11 + + extensions/libip6t_SNPT.t | 7 + + extensions/libip6t_ah.t | 15 ++ + extensions/libip6t_dst.t | 5 + + extensions/libip6t_eui64.t | 8 + + extensions/libip6t_frag.t | 13 ++ + extensions/libip6t_hbh.t | 5 + + extensions/libip6t_hl.t | 8 + + extensions/libip6t_icmp6.t | 6 + + extensions/libip6t_ipv6header.t | 4 + + extensions/libip6t_mh.t | 6 + + extensions/libip6t_rt.t | 5 + + extensions/libip6t_srh.t | 28 +++ + extensions/libip6t_standard.t | 5 + + extensions/libipt_CLUSTERIP.t | 4 + + extensions/libipt_DNAT.t | 16 ++ + extensions/libipt_ECN.t | 5 + + extensions/libipt_LOG.t | 12 + + extensions/libipt_MASQUERADE.t | 9 + + extensions/libipt_NETMAP.t | 4 + + extensions/libipt_REDIRECT.t | 6 + + extensions/libipt_REJECT.t | 9 + + extensions/libipt_SNAT.t | 11 + + extensions/libipt_TTL.t | 10 + + extensions/libipt_ah.t | 13 ++ + extensions/libipt_icmp.t | 15 ++ + extensions/libipt_realm.t | 4 + + extensions/libipt_ttl.t | 15 ++ + extensions/libxt_AUDIT.t | 6 + + extensions/libxt_CHECKSUM.t | 4 + + extensions/libxt_CLASSIFY.t | 9 + + extensions/libxt_CONNMARK.t | 7 + + extensions/libxt_CONNSECMARK.t | 5 + + extensions/libxt_CT.t | 20 ++ + extensions/libxt_DSCP.t | 11 + + extensions/libxt_HMARK.t | 8 + + extensions/libxt_IDLETIMER.t | 4 + + extensions/libxt_LED.t | 4 + + extensions/libxt_MARK.t | 7 + + extensions/libxt_NFLOG.t | 24 ++ + extensions/libxt_NFQUEUE.t | 16 ++ + extensions/libxt_NOTRACK.t | 4 + + extensions/libxt_RATEEST.t | 2 + + extensions/libxt_SET.t | 3 + + extensions/libxt_SYNPROXY.t | 3 + + extensions/libxt_TCPMSS.t | 6 + + extensions/libxt_TCPOPTSTRIP.t | 8 + + extensions/libxt_TEE.t | 4 + + extensions/libxt_TOS.t | 16 ++ + extensions/libxt_TPROXY.t | 5 + + extensions/libxt_TRACE.t | 3 + + extensions/libxt_addrtype.t | 17 ++ + extensions/libxt_bpf.t | 2 + + extensions/libxt_cgroup.t | 8 + + extensions/libxt_cluster.t | 10 + + extensions/libxt_comment.t | 12 + + extensions/libxt_connbytes.t | 21 ++ + extensions/libxt_connlabel.t | 18 ++ + extensions/libxt_connlimit.t | 16 ++ + extensions/libxt_connmark.t | 9 + + extensions/libxt_conntrack.t | 27 +++ + extensions/libxt_cpu.t | 6 + + extensions/libxt_dccp.t | 30 +++ + extensions/libxt_dscp.t | 10 + + extensions/libxt_ecn.t | 5 + + extensions/libxt_esp.t | 8 + + extensions/libxt_hashlimit.t | 33 +++ + extensions/libxt_helper.t | 6 + + extensions/libxt_ipcomp.t | 3 + + extensions/libxt_iprange.t | 11 + + extensions/libxt_length.t | 10 + + extensions/libxt_limit.t | 6 + + extensions/libxt_mac.t | 5 + + extensions/libxt_mark.t | 7 + + extensions/libxt_multiport.t | 23 ++ + extensions/libxt_nfacct.t | 10 + + extensions/libxt_osf.t | 4 + + extensions/libxt_owner.t | 12 + + extensions/libxt_physdev.t | 14 ++ + extensions/libxt_pkttype.t | 6 + + extensions/libxt_policy.t | 8 + + extensions/libxt_quota.t | 7 + + extensions/libxt_rateest.t | 16 ++ + extensions/libxt_recent.t | 11 + + extensions/libxt_rpfilter.t | 4 + + extensions/libxt_sctp.t | 29 +++ + extensions/libxt_set.t | 4 + + extensions/libxt_socket.t | 8 + + extensions/libxt_standard.t | 11 + + extensions/libxt_state.t | 6 + + extensions/libxt_statistic.t | 8 + + extensions/libxt_string.t | 18 ++ + extensions/libxt_tcp.t | 26 +++ + extensions/libxt_tcpmss.t | 6 + + extensions/libxt_time.t | 4 + + extensions/libxt_tos.t | 13 ++ + extensions/libxt_u32.t | 2 + + extensions/libxt_udp.t | 22 ++ + iptables-test.py | 373 ++++++++++++++++++++++++++++++++ + 128 files changed, 1603 insertions(+) + create mode 100644 extensions/iptables.t + create mode 100644 extensions/libarpt_CLASSIFY.t + create mode 100644 extensions/libarpt_MARK.t + create mode 100644 extensions/libarpt_mangle.t + create mode 100644 extensions/libarpt_standard.t + create mode 100644 extensions/libebt_802_3.t + create mode 100644 extensions/libebt_arp.t + create mode 100644 extensions/libebt_arpreply.t + create mode 100644 extensions/libebt_dnat.t + create mode 100644 extensions/libebt_ip.t + create mode 100644 extensions/libebt_ip6.t + create mode 100644 extensions/libebt_log.t + create mode 100644 extensions/libebt_mark.t + create mode 100644 extensions/libebt_mark_m.t + create mode 100644 extensions/libebt_nflog.t + create mode 100644 extensions/libebt_pkttype.t + create mode 100644 extensions/libebt_redirect.t + create mode 100644 extensions/libebt_snat.t + create mode 100644 extensions/libebt_standard.t + create mode 100644 extensions/libebt_stp.t + create mode 100644 extensions/libebt_vlan.t + create mode 100644 extensions/libip6t_DNAT.t + create mode 100644 extensions/libip6t_DNPT.t + create mode 100644 extensions/libip6t_HL.t + create mode 100644 extensions/libip6t_LOG.t + create mode 100644 extensions/libip6t_MASQUERADE.t + create mode 100644 extensions/libip6t_NETMAP.t + create mode 100644 extensions/libip6t_REDIRECT.t + create mode 100644 extensions/libip6t_REJECT.t + create mode 100644 extensions/libip6t_SNAT.t + create mode 100644 extensions/libip6t_SNPT.t + create mode 100644 extensions/libip6t_ah.t + create mode 100644 extensions/libip6t_dst.t + create mode 100644 extensions/libip6t_eui64.t + create mode 100644 extensions/libip6t_frag.t + create mode 100644 extensions/libip6t_hbh.t + create mode 100644 extensions/libip6t_hl.t + create mode 100644 extensions/libip6t_icmp6.t + create mode 100644 extensions/libip6t_ipv6header.t + create mode 100644 extensions/libip6t_mh.t + create mode 100644 extensions/libip6t_rt.t + create mode 100644 extensions/libip6t_srh.t + create mode 100644 extensions/libip6t_standard.t + create mode 100644 extensions/libipt_CLUSTERIP.t + create mode 100644 extensions/libipt_DNAT.t + create mode 100644 extensions/libipt_ECN.t + create mode 100644 extensions/libipt_LOG.t + create mode 100644 extensions/libipt_MASQUERADE.t + create mode 100644 extensions/libipt_NETMAP.t + create mode 100644 extensions/libipt_REDIRECT.t + create mode 100644 extensions/libipt_REJECT.t + create mode 100644 extensions/libipt_SNAT.t + create mode 100644 extensions/libipt_TTL.t + create mode 100644 extensions/libipt_ah.t + create mode 100644 extensions/libipt_icmp.t + create mode 100644 extensions/libipt_realm.t + create mode 100644 extensions/libipt_ttl.t + create mode 100644 extensions/libxt_AUDIT.t + create mode 100644 extensions/libxt_CHECKSUM.t + create mode 100644 extensions/libxt_CLASSIFY.t + create mode 100644 extensions/libxt_CONNMARK.t + create mode 100644 extensions/libxt_CONNSECMARK.t + create mode 100644 extensions/libxt_CT.t + create mode 100644 extensions/libxt_DSCP.t + create mode 100644 extensions/libxt_HMARK.t + create mode 100644 extensions/libxt_IDLETIMER.t + create mode 100644 extensions/libxt_LED.t + create mode 100644 extensions/libxt_MARK.t + create mode 100644 extensions/libxt_NFLOG.t + create mode 100644 extensions/libxt_NFQUEUE.t + create mode 100644 extensions/libxt_NOTRACK.t + create mode 100644 extensions/libxt_RATEEST.t + create mode 100644 extensions/libxt_SET.t + create mode 100644 extensions/libxt_SYNPROXY.t + create mode 100644 extensions/libxt_TCPMSS.t + create mode 100644 extensions/libxt_TCPOPTSTRIP.t + create mode 100644 extensions/libxt_TEE.t + create mode 100644 extensions/libxt_TOS.t + create mode 100644 extensions/libxt_TPROXY.t + create mode 100644 extensions/libxt_TRACE.t + create mode 100644 extensions/libxt_addrtype.t + create mode 100644 extensions/libxt_bpf.t + create mode 100644 extensions/libxt_cgroup.t + create mode 100644 extensions/libxt_cluster.t + create mode 100644 extensions/libxt_comment.t + create mode 100644 extensions/libxt_connbytes.t + create mode 100644 extensions/libxt_connlabel.t + create mode 100644 extensions/libxt_connlimit.t + create mode 100644 extensions/libxt_connmark.t + create mode 100644 extensions/libxt_conntrack.t + create mode 100644 extensions/libxt_cpu.t + create mode 100644 extensions/libxt_dccp.t + create mode 100644 extensions/libxt_dscp.t + create mode 100644 extensions/libxt_ecn.t + create mode 100644 extensions/libxt_esp.t + create mode 100644 extensions/libxt_hashlimit.t + create mode 100644 extensions/libxt_helper.t + create mode 100644 extensions/libxt_ipcomp.t + create mode 100644 extensions/libxt_iprange.t + create mode 100644 extensions/libxt_length.t + create mode 100644 extensions/libxt_limit.t + create mode 100644 extensions/libxt_mac.t + create mode 100644 extensions/libxt_mark.t + create mode 100644 extensions/libxt_multiport.t + create mode 100644 extensions/libxt_nfacct.t + create mode 100644 extensions/libxt_osf.t + create mode 100644 extensions/libxt_owner.t + create mode 100644 extensions/libxt_physdev.t + create mode 100644 extensions/libxt_pkttype.t + create mode 100644 extensions/libxt_policy.t + create mode 100644 extensions/libxt_quota.t + create mode 100644 extensions/libxt_rateest.t + create mode 100644 extensions/libxt_recent.t + create mode 100644 extensions/libxt_rpfilter.t + create mode 100644 extensions/libxt_sctp.t + create mode 100644 extensions/libxt_set.t + create mode 100644 extensions/libxt_socket.t + create mode 100644 extensions/libxt_standard.t + create mode 100644 extensions/libxt_state.t + create mode 100644 extensions/libxt_statistic.t + create mode 100644 extensions/libxt_string.t + create mode 100644 extensions/libxt_tcp.t + create mode 100644 extensions/libxt_tcpmss.t + create mode 100644 extensions/libxt_time.t + create mode 100644 extensions/libxt_tos.t + create mode 100644 extensions/libxt_u32.t + create mode 100644 extensions/libxt_udp.t + create mode 100755 iptables-test.py + +diff --git a/extensions/iptables.t b/extensions/iptables.t +new file mode 100644 +index 0000000000000..b4b6d677abab1 +--- /dev/null ++++ b/extensions/iptables.t +@@ -0,0 +1,6 @@ ++:FORWARD ++-i alongifacename0;=;OK ++-i thisinterfaceistoolong0;;FAIL ++-i eth+ -o alongifacename+;=;OK ++! -i eth0;=;OK ++! -o eth+;=;OK +diff --git a/extensions/libarpt_CLASSIFY.t b/extensions/libarpt_CLASSIFY.t +new file mode 100644 +index 0000000000000..c30480d2b160c +--- /dev/null ++++ b/extensions/libarpt_CLASSIFY.t +@@ -0,0 +1,4 @@ ++:OUTPUT ++-o lo --destination-mac 11:22:33:44:55:66;-o lo --dst-mac 11:22:33:44:55:66;OK ++--dst-mac Broadcast ;--dst-mac ff:ff:ff:ff:ff:ff;OK ++! -o eth+ -d 1.2.3.4/24 -j CLASSIFY --set-class 0000:0000;! -o eth+ -d 1.2.3.0/24 --h-length 6 --h-type 1 -j CLASSIFY --set-class 0000:0000;OK +diff --git a/extensions/libarpt_MARK.t b/extensions/libarpt_MARK.t +new file mode 100644 +index 0000000000000..cb4c2cb630357 +--- /dev/null ++++ b/extensions/libarpt_MARK.t +@@ -0,0 +1,4 @@ ++:INPUT,OUTPUT ++-d 0.0.0.0/8 -j MARK --set-mark 0x1;-d 0.0.0.0/8 --h-length 6 --h-type 1 -j MARK --set-xmark 0x1/0xffffffff;OK ++-s ! 0.0.0.0 -j MARK --and-mark 0x17;! -s 0.0.0.0 --h-length 6 --h-type 1 -j MARK --set-xmark 0x0/0xffffffe8;OK ++-s 0.0.0.0 -j MARK --or-mark 0x17;-s 0.0.0.0 --h-length 6 --h-type 1 -j MARK --set-xmark 0x17/0x17;OK +diff --git a/extensions/libarpt_mangle.t b/extensions/libarpt_mangle.t +new file mode 100644 +index 0000000000000..1d4c3977d2a4c +--- /dev/null ++++ b/extensions/libarpt_mangle.t +@@ -0,0 +1,5 @@ ++:OUTPUT ++-s 1.2.3.4 -j mangle --mangle-ip-s 1.2.3.5;-s 1.2.3.4 --h-length 6 --h-type 1 -j mangle --mangle-ip-s 1.2.3.5;OK ++-d 1.2.3.4 -j mangle --mangle-ip-d 1.2.3.5;-d 1.2.3.4 --h-length 6 --h-type 1 -j mangle --mangle-ip-d 1.2.3.5;OK ++-d 1.2.3.4 --h-length 6 --h-type 1 -j mangle --mangle-mac-d 00:01:02:03:04:05;=;OK ++-d 1.2.3.4 -j mangle --mangle-mac-s 00:01:02:03:04:05;=;FAIL +diff --git a/extensions/libarpt_standard.t b/extensions/libarpt_standard.t +new file mode 100644 +index 0000000000000..bef682afec374 +--- /dev/null ++++ b/extensions/libarpt_standard.t +@@ -0,0 +1,14 @@ ++:INPUT ++-s 192.168.0.1;=;OK ++-s 0.0.0.0/8;=;OK ++-s ! 0.0.0.0;! -s 0.0.0.0;OK ++-d 192.168.0.1;=;OK ++! -d 0.0.0.0;=;OK ++-d 0.0.0.0/24;=;OK ++-i lo;=;OK ++! -i lo;=;OK ++-i ppp+;=;OK ++! -i ppp+;=;OK ++-i lo --destination-mac 11:22:33:44:55:66;-i lo --dst-mac 11:22:33:44:55:66;OK ++--source-mac Unicast;--src-mac 00:00:00:00:00:00/01:00:00:00:00:00;OK ++! --src-mac Multicast;! --src-mac 01:00:00:00:00:00/01:00:00:00:00:00;OK +diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t +new file mode 100644 +index 0000000000000..61081bd6983a8 +--- /dev/null ++++ b/extensions/libebt_802_3.t +@@ -0,0 +1,3 @@ ++:INPUT,FORWARD,OUTPUT ++! --802_3-sap 0x0a -j CONTINUE;=;OK ++--802_3-type 0x000a -j RETURN;=;OK +diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t +new file mode 100644 +index 0000000000000..a05ab12dc566f +--- /dev/null ++++ b/extensions/libebt_arp.t +@@ -0,0 +1,12 @@ ++:INPUT,FORWARD,OUTPUT ++-p ARP --arp-op Request;=;OK ++-p ARP ! --arp-htype 1;=;OK ++-p ARP --arp-ptype 0x2;=;OK ++-p ARP --arp-ip-src 1.2.3.4;=;OK ++-p ARP ! --arp-ip-dst 1.2.3.4;=;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-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 ++--arp-htype 1;=;FAIL +diff --git a/extensions/libebt_arpreply.t b/extensions/libebt_arpreply.t +new file mode 100644 +index 0000000000000..6734501a106b5 +--- /dev/null ++++ b/extensions/libebt_arpreply.t +@@ -0,0 +1,4 @@ ++:PREROUTING ++*nat ++-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff --arpreply-target ACCEPT;=;OK ++-p ARP -i foo -j arpreply --arpreply-mac de:ad:00:be:ee:ff;=;OK +diff --git a/extensions/libebt_dnat.t b/extensions/libebt_dnat.t +new file mode 100644 +index 0000000000000..9428d237850fb +--- /dev/null ++++ b/extensions/libebt_dnat.t +@@ -0,0 +1,5 @@ ++:PREROUTING ++*nat ++-i someport -j dnat --to-dst de:ad:0:be:ee:ff;-i someport -j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT;OK ++-j dnat --to-dst de:ad:00:be:ee:ff --dnat-target ACCEPT;=;OK ++-j dnat --to-dst de:ad:00:be:ee:ff --dnat-target CONTINUE;=;OK +diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t +new file mode 100644 +index 0000000000000..01a91a7385fcc +--- /dev/null ++++ b/extensions/libebt_ip.t +@@ -0,0 +1,13 @@ ++:INPUT,FORWARD,OUTPUT ++-p ip --ip-src ! 192.168.0.0/24 -j ACCEPT;-p IPv4 ! --ip-src 192.168.0.0/24 -j ACCEPT;OK ++-p IPv4 --ip-dst 10.0.0.1;=;OK ++-p IPv4 --ip-tos 0xFF;=;OK ++-p IPv4 ! --ip-tos 0xFF;=;OK ++-p IPv4 --ip-proto tcp --ip-dport 22;=;OK ++-p IPv4 --ip-proto udp --ip-sport 1024:65535;=;OK ++-p IPv4 --ip-proto 253;=;OK ++-p IPv4 --ip-proto icmp --ip-icmp-type echo-request;=;OK ++-p IPv4 --ip-proto icmp --ip-icmp-type 1/1;=;OK ++-p ip --ip-protocol icmp --ip-icmp-type ! 1:10;-p IPv4 --ip-proto icmp ! --ip-icmp-type 1:10/0:255 -j CONTINUE;OK ++--ip-proto icmp --ip-icmp-type 1/1;=;FAIL ++! -p ip --ip-proto icmp --ip-icmp-type 1/1;=;FAIL +diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t +new file mode 100644 +index 0000000000000..6b3221ea58f62 +--- /dev/null ++++ b/extensions/libebt_ip6.t +@@ -0,0 +1,15 @@ ++:INPUT,FORWARD,OUTPUT ++-p ip6 ! --ip6-src dead::beef/64 -j ACCEPT;-p IPv6 ! --ip6-src dead::/64 -j ACCEPT;OK ++-p IPv6 --ip6-dst dead:beef::/64 -j ACCEPT;=;OK ++-p IPv6 --ip6-dst f00:ba::;=;OK ++-p IPv6 --ip6-tclass 0xFF;=;OK ++-p IPv6 --ip6-proto tcp --ip6-dport 22;=;OK ++-p IPv6 --ip6-proto tcp ! --ip6-dport 22;=;OK ++-p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;OK ++-p IPv6 --ip6-proto 253;=;OK ++-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request -j CONTINUE;=;OK ++-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request;=;OK ++-p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1;-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type communication-prohibited -j CONTINUE;OK ++-p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;OK ++--ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL ++! -p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL +diff --git a/extensions/libebt_log.t b/extensions/libebt_log.t +new file mode 100644 +index 0000000000000..a0df6169112a0 +--- /dev/null ++++ b/extensions/libebt_log.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++--log;=;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 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_mark.t b/extensions/libebt_mark.t +new file mode 100644 +index 0000000000000..2d8f9d7a972ad +--- /dev/null ++++ b/extensions/libebt_mark.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++-j mark --mark-set 1;-j mark --mark-set 0x1 --mark-target ACCEPT;OK ++-j mark --mark-or 0xa --mark-target CONTINUE;=;OK ++-j mark --mark-and 0x1 --mark-target RETURN;=;OK ++-j mark --mark-xor 0x1 --mark-target CONTINUE;=;OK +diff --git a/extensions/libebt_mark_m.t b/extensions/libebt_mark_m.t +new file mode 100644 +index 0000000000000..9ad41704fbb82 +--- /dev/null ++++ b/extensions/libebt_mark_m.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++--mark 42;--mark 0x2a;OK ++--mark ! 42;! --mark 0x2a;OK ++--mark 42/0xff;--mark 0x2a/0xff;OK ++! --mark 0x1/0xff;=;OK ++--mark /0x2;=;OK +diff --git a/extensions/libebt_nflog.t b/extensions/libebt_nflog.t +new file mode 100644 +index 0000000000000..f867df303fa95 +--- /dev/null ++++ b/extensions/libebt_nflog.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++--nflog;=;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_pkttype.t b/extensions/libebt_pkttype.t +new file mode 100644 +index 0000000000000..f870f5c7f05c4 +--- /dev/null ++++ b/extensions/libebt_pkttype.t +@@ -0,0 +1,13 @@ ++:INPUT,FORWARD,OUTPUT ++--pkttype-type host;=;OK ++! --pkttype-type host;=;OK ++--pkttype-type broadcast;=;OK ++! --pkttype-type broadcast;=;OK ++--pkttype-type multicast;=;OK ++! --pkttype-type multicast;=;OK ++--pkttype-type otherhost;=;OK ++! --pkttype-type otherhost;=;OK ++--pkttype-type outgoing;=;OK ++! --pkttype-type outgoing;=;OK ++--pkttype-type loopback;=;OK ++! --pkttype-type loopback;=;OK +diff --git a/extensions/libebt_redirect.t b/extensions/libebt_redirect.t +new file mode 100644 +index 0000000000000..23858afa3b588 +--- /dev/null ++++ b/extensions/libebt_redirect.t +@@ -0,0 +1,4 @@ ++:PREROUTING ++*nat ++-j redirect;=;OK ++-j redirect --redirect-target RETURN;=;OK +diff --git a/extensions/libebt_snat.t b/extensions/libebt_snat.t +new file mode 100644 +index 0000000000000..639b13f300c9d +--- /dev/null ++++ b/extensions/libebt_snat.t +@@ -0,0 +1,4 @@ ++:POSTROUTING ++*nat ++-o someport -j snat --to-source a:b:c:d:e:f;-o someport -j snat --to-src 0a:0b:0c:0d:0e:0f --snat-target ACCEPT;OK ++-o someport+ -j snat --to-src de:ad:00:be:ee:ff --snat-target CONTINUE;=;OK +diff --git a/extensions/libebt_standard.t b/extensions/libebt_standard.t +new file mode 100644 +index 0000000000000..72081fd6575a0 +--- /dev/null ++++ b/extensions/libebt_standard.t +@@ -0,0 +1,11 @@ ++:INPUT,FORWARD,OUTPUT ++-d de:ad:be:ef:00:00;=;OK ++-s 0:0:0:0:0:0;-s 00:00:00:00:00:00;OK ++-d 00:00:00:00:00:00;=;OK ++-s de:ad:be:ef:0:00 -j RETURN;-s de:ad:be:ef:00:00 -j RETURN;OK ++-d de:ad:be:ef:00:00 -j CONTINUE;=;OK ++-d de:ad:be:ef:0:00/ff:ff:ff:ff:0:0 -j DROP;-d de:ad:be:ef:00:00/ff:ff:ff:ff:00:00 -j DROP;OK ++-p ARP -j ACCEPT;=;OK ++! -p ARP -j ACCEPT;=;OK ++-p 0 -j ACCEPT;=;FAIL ++! -p 0 -j ACCEPT;=;FAIL +diff --git a/extensions/libebt_stp.t b/extensions/libebt_stp.t +new file mode 100644 +index 0000000000000..0c6b77b91454b +--- /dev/null ++++ b/extensions/libebt_stp.t +@@ -0,0 +1,13 @@ ++: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-addr 0d:ea:d0:0b:ee:f0;=;OK ++--stp-root-cost 1;=;OK ++--stp-sender-prio 1;=;OK ++--stp-sender-addr de:ad:be:ef:00:00;=;OK ++--stp-port 1;=;OK ++--stp-msg-age 1;=;OK ++--stp-max-age 1;=;OK ++--stp-hello-time 1;=;OK ++--stp-forward-delay 1;=;OK +diff --git a/extensions/libebt_vlan.t b/extensions/libebt_vlan.t +new file mode 100644 +index 0000000000000..106374cd9cb80 +--- /dev/null ++++ b/extensions/libebt_vlan.t +@@ -0,0 +1,13 @@ ++:INPUT,FORWARD,OUTPUT ++-p 802_1Q --vlan-id 42;=;OK ++-p 802_1Q ! --vlan-id 42;=;OK ++-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 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 ++--vlan-id 2;=;FAIL ++--vlan-prio 1;=;FAIL +diff --git a/extensions/libip6t_DNAT.t b/extensions/libip6t_DNAT.t +new file mode 100644 +index 0000000000000..ec7d61f418cfe +--- /dev/null ++++ b/extensions/libip6t_DNAT.t +@@ -0,0 +1,16 @@ ++:PREROUTING ++*nat ++-j DNAT --to-destination dead::beef;=;OK ++-j DNAT --to-destination dead::beef-dead::fee7;=;OK ++-j DNAT --to-destination [dead::beef]:1025-65535;;FAIL ++-j DNAT --to-destination [dead::beef] --to-destination [dead::fee7];;FAIL ++-p tcp -j DNAT --to-destination [dead::beef]:1025-65535;=;OK ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535;=;OK ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65536;;FAIL ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1025-65535 --to-destination [dead::beef-dead::fee8]:1025-65535;;FAIL ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/1000;=;OK ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/3000;=;OK ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/65535;=;OK ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/0;;FAIL ++-p tcp -j DNAT --to-destination [dead::beef-dead::fee7]:1000-2000/65536;;FAIL ++-j DNAT;;FAIL +diff --git a/extensions/libip6t_DNPT.t b/extensions/libip6t_DNPT.t +new file mode 100644 +index 0000000000000..0406dc90d2c6e +--- /dev/null ++++ b/extensions/libip6t_DNPT.t +@@ -0,0 +1,7 @@ ++:PREROUTING ++*mangle ++-j DNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK ++-j DNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL ++-j DNPT --src-pfx dead::/64;;FAIL ++-j DNPT --dst-pfx dead::/64;;FAIL ++-j DNPT;;FAIL +diff --git a/extensions/libip6t_HL.t b/extensions/libip6t_HL.t +new file mode 100644 +index 0000000000000..4e529f883b2c5 +--- /dev/null ++++ b/extensions/libip6t_HL.t +@@ -0,0 +1,10 @@ ++:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j HL --hl-set 42;=;OK ++-j HL --hl-inc 1;=;OK ++-j HL --hl-dec 1;=;OK ++-j HL --hl-set 256;;FAIL ++-j HL --hl-inc 0;;FAIL ++-j HL --hl-dec 0;;FAIL ++-j HL --hl-dec 1 --hl-inc 1;;FAIL ++-j HL --hl-set --hl-inc 1;;FAIL +diff --git a/extensions/libip6t_LOG.t b/extensions/libip6t_LOG.t +new file mode 100644 +index 0000000000000..fbf5118b2382a +--- /dev/null ++++ b/extensions/libip6t_LOG.t +@@ -0,0 +1,12 @@ ++:INPUT,FORWARD,OUTPUT ++-j LOG;-j LOG;OK ++-j LOG --log-prefix "test: ";=;OK ++-j LOG --log-prefix "test: " --log-level 1;=;OK ++# iptables displays the log-level output using the number; not the string ++-j LOG --log-prefix "test: " --log-level alert;-j LOG --log-prefix "test: " --log-level 1;OK ++-j LOG --log-prefix "test: " --log-tcp-sequence;=;OK ++-j LOG --log-prefix "test: " --log-tcp-options;=;OK ++-j LOG --log-prefix "test: " --log-ip-options;=;OK ++-j LOG --log-prefix "test: " --log-uid;=;OK ++-j LOG --log-prefix "test: " --log-level bad;;FAIL ++-j LOG --log-prefix;;FAIL +diff --git a/extensions/libip6t_MASQUERADE.t b/extensions/libip6t_MASQUERADE.t +new file mode 100644 +index 0000000000000..e25d2a04ab7b0 +--- /dev/null ++++ b/extensions/libip6t_MASQUERADE.t +@@ -0,0 +1,9 @@ ++:POSTROUTING ++*nat ++-j MASQUERADE;=;OK ++-j MASQUERADE --random;=;OK ++-j MASQUERADE --random-fully;=;OK ++-p tcp -j MASQUERADE --to-ports 1024;=;OK ++-p udp -j MASQUERADE --to-ports 1024-65535;=;OK ++-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL ++-p udp -j MASQUERADE --to-ports -1;;FAIL +diff --git a/extensions/libip6t_NETMAP.t b/extensions/libip6t_NETMAP.t +new file mode 100644 +index 0000000000000..043562d261243 +--- /dev/null ++++ b/extensions/libip6t_NETMAP.t +@@ -0,0 +1,4 @@ ++:PREROUTING,INPUT,OUTPUT,POSTROUTING ++*nat ++-j NETMAP --to dead::/64;=;OK ++-j NETMAP --to dead::beef;=;OK +diff --git a/extensions/libip6t_REDIRECT.t b/extensions/libip6t_REDIRECT.t +new file mode 100644 +index 0000000000000..a0fb0ed19a5ea +--- /dev/null ++++ b/extensions/libip6t_REDIRECT.t +@@ -0,0 +1,6 @@ ++:PREROUTING,OUTPUT ++*nat ++-p tcp -j REDIRECT --to-ports 42;=;OK ++-p udp -j REDIRECT --to-ports 42-1234;=;OK ++-p tcp -j REDIRECT --to-ports 42-1234 --random;=;OK ++-j REDIRECT --to-ports 42;;FAIL +diff --git a/extensions/libip6t_REJECT.t b/extensions/libip6t_REJECT.t +new file mode 100644 +index 0000000000000..d2b337d7ebdeb +--- /dev/null ++++ b/extensions/libip6t_REJECT.t +@@ -0,0 +1,11 @@ ++:INPUT,FORWARD,OUTPUT ++-j REJECT;=;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 ++-j REJECT --reject-with icmp6-addr-unreachable;=;OK ++-j REJECT --reject-with icmp6-port-unreachable;=;OK ++-j REJECT --reject-with icmp6-policy-fail;=;OK ++-j REJECT --reject-with icmp6-reject-route;=;OK ++-p tcp -j REJECT --reject-with tcp-reset;=;OK ++-j REJECT --reject-with tcp-reset;;FAIL +diff --git a/extensions/libip6t_SNAT.t b/extensions/libip6t_SNAT.t +new file mode 100644 +index 0000000000000..d188a6bb3d559 +--- /dev/null ++++ b/extensions/libip6t_SNAT.t +@@ -0,0 +1,11 @@ ++:POSTROUTING ++*nat ++-j SNAT --to-source dead::beef;=;OK ++-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 ++-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 ++-p tcp -j SNAT --to-source [dead::beef-dead::fee7]:1025-65535 --to-source [dead::beef-dead::fee8]:1025-65535;;FAIL ++-j SNAT;;FAIL +diff --git a/extensions/libip6t_SNPT.t b/extensions/libip6t_SNPT.t +new file mode 100644 +index 0000000000000..7ed6d0c95bb35 +--- /dev/null ++++ b/extensions/libip6t_SNPT.t +@@ -0,0 +1,7 @@ ++:INPUT,POSTROUTING ++*mangle ++-j SNPT --src-pfx dead::/64 --dst-pfx 1c3::/64;=;OK ++-j SNPT --src-pfx dead::beef --dst-pfx 1c3::/64;;FAIL ++-j SNPT --src-pfx dead::/64;;FAIL ++-j SNPT --dst-pfx dead::/64;;FAIL ++-j SNPT;;FAIL +diff --git a/extensions/libip6t_ah.t b/extensions/libip6t_ah.t +new file mode 100644 +index 0000000000000..c1898d44cf193 +--- /dev/null ++++ b/extensions/libip6t_ah.t +@@ -0,0 +1,15 @@ ++:INPUT,FORWARD,OUTPUT ++-m ah --ahspi 0;=;OK ++-m ah --ahspi 4294967295;=;OK ++-m ah --ahspi 0:4294967295;-m ah;OK ++-m ah ! --ahspi 0;=;OK ++# ERROR: should fail: iptables -A FORWARD -t mangle -j CLASSIFY --set-class 1:-1 ++# -m ah --ahres;=;OK ++# ERROR: line 7 (cannot find: ip6tables -I INPUT -m ah --ahlen 32 ++# -m ah --ahlen 32;=;OK ++-m ah --ahspi -1;;FAIL ++-m ah --ahspi 4294967296;;FAIL ++-m ah --ahspi invalid;;FAIL ++-m ah --ahspi 0:invalid;;FAIL ++-m ah --ahspi;;FAIL ++-m ah;=;OK +diff --git a/extensions/libip6t_dst.t b/extensions/libip6t_dst.t +new file mode 100644 +index 0000000000000..0b0013b57fc0b +--- /dev/null ++++ b/extensions/libip6t_dst.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++-m dst --dst-len 0;=;OK ++-m dst --dst-opts 149:92,12:12,123:12;=;OK ++-m dst ! --dst-len 42;=;OK ++-m dst --dst-len 42 --dst-opts 149:92,12:12,123:12;=;OK +diff --git a/extensions/libip6t_eui64.t b/extensions/libip6t_eui64.t +new file mode 100644 +index 0000000000000..e5aaaacef48bf +--- /dev/null ++++ b/extensions/libip6t_eui64.t +@@ -0,0 +1,8 @@ ++:PREROUTING ++*raw ++-m eui64;=;OK ++:INPUT,FORWARD ++*filter ++-m eui64;=;OK ++:OUTPUT ++-m eui64;;FAIL +diff --git a/extensions/libip6t_frag.t b/extensions/libip6t_frag.t +new file mode 100644 +index 0000000000000..299fa03f8845b +--- /dev/null ++++ b/extensions/libip6t_frag.t +@@ -0,0 +1,13 @@ ++:INPUT,FORWARD,OUTPUT ++-m frag --fragid 1:42;=;OK ++-m frag --fraglen 42;=;OK ++-m frag --fragres;=;OK ++-m frag --fragfirst;=;OK ++-m frag --fragmore;=;OK ++-m frag --fraglast;=;OK ++-m frag ! --fragid 1 ! --fraglen 42 --fragres --fragfirst;=;OK ++-m frag --fragfirst --fragmore;=;OK ++-m frag --fragfirst --fraglast;=;OK ++-m frag --fraglast --fragmore;;FAIL ++-d ff02::fb/128 -p udp -m udp --dport 5353 -m frag --fragmore;=;OK ++-d fe80::/64 -p udp --dport 546 -m frag --fraglast;-d fe80::/64 -p udp -m udp --dport 546 -m frag --fraglast;OK +diff --git a/extensions/libip6t_hbh.t b/extensions/libip6t_hbh.t +new file mode 100644 +index 0000000000000..4b58f25a1301a +--- /dev/null ++++ b/extensions/libip6t_hbh.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++-m hbh;=;OK ++-m hbh --hbh-len 42;=;OK ++-m hbh ! --hbh-len 42;=;OK ++-m hbh --hbh-len 42 --hbh-opts 1:2,23:42,4:6,8:10,42,23,4:5;=;OK +diff --git a/extensions/libip6t_hl.t b/extensions/libip6t_hl.t +new file mode 100644 +index 0000000000000..b02816afb827b +--- /dev/null ++++ b/extensions/libip6t_hl.t +@@ -0,0 +1,8 @@ ++:INPUT,FORWARD,OUTPUT ++-m hl;;FAIL ++-m hl --hl-eq 42;=;OK ++-m hl ! --hl-eq 42;=;OK ++-m hl --hl-lt 42;=;OK ++-m hl --hl-gt 42;=;OK ++-m hl --hl-gt 42 --hl-eq 42;;FAIL ++-m hl --hl-gt;;FAIL +diff --git a/extensions/libip6t_icmp6.t b/extensions/libip6t_icmp6.t +new file mode 100644 +index 0000000000000..028cfc16ede24 +--- /dev/null ++++ b/extensions/libip6t_icmp6.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m icmpv6;;FAIL ++-p ipv6-icmp -m icmp6 --icmpv6-type 1/0;=;OK ++-p ipv6-icmp -m icmp6 --icmpv6-type 2;=;OK ++# cannot use option twice: ++-p ipv6-icmp -m icmp6 --icmpv6-type no-route --icmpv6-type packet-too-big;;FAIL +diff --git a/extensions/libip6t_ipv6header.t b/extensions/libip6t_ipv6header.t +new file mode 100644 +index 0000000000000..67fa47998ee09 +--- /dev/null ++++ b/extensions/libip6t_ipv6header.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-m ipv6header --header hop-by-hop;=;OK ++-m ipv6header --header hop-by-hop --soft;=;OK ++-m ipv6header --header ipv6-nonxt;=;OK +diff --git a/extensions/libip6t_mh.t b/extensions/libip6t_mh.t +new file mode 100644 +index 0000000000000..6b76d13d0a00f +--- /dev/null ++++ b/extensions/libip6t_mh.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m mh;;FAIL ++-p mobility-header -m mh;=;OK ++-p mobility-header -m mh --mh-type 1;=;OK ++-p mobility-header -m mh ! --mh-type 4;=;OK ++-p mobility-header -m mh --mh-type 4:123;=;OK +diff --git a/extensions/libip6t_rt.t b/extensions/libip6t_rt.t +new file mode 100644 +index 0000000000000..3c7b2d981324a +--- /dev/null ++++ b/extensions/libip6t_rt.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++-m rt --rt-type 0 --rt-segsleft 1:23 --rt-len 42 --rt-0-res;=;OK ++-m rt --rt-type 0 ! --rt-segsleft 1:23 ! --rt-len 42 --rt-0-res;=;OK ++-m rt ! --rt-type 1 ! --rt-segsleft 12:23 ! --rt-len 42;=;OK ++-m rt;=;OK +diff --git a/extensions/libip6t_srh.t b/extensions/libip6t_srh.t +new file mode 100644 +index 0000000000000..07b540319233e +--- /dev/null ++++ b/extensions/libip6t_srh.t +@@ -0,0 +1,28 @@ ++:INPUT,FORWARD,OUTPUT ++-m srh --srh-next-hdr 17;=;OK ++-m srh --srh-hdr-len-eq 8;=;OK ++-m srh --srh-hdr-len-gt 8;=;OK ++-m srh --srh-hdr-len-lt 8;=;OK ++-m srh --srh-segs-left-eq 1;=;OK ++-m srh --srh-segs-left-gt 1;=;OK ++-m srh --srh-segs-left-lt 1;=;OK ++-m srh --srh-last-entry-eq 4;=;OK ++-m srh --srh-last-entry-gt 4;=;OK ++-m srh --srh-last-entry-lt 4;=;OK ++-m srh --srh-tag 0;=;OK ++-m srh ! --srh-next-hdr 17;=;OK ++-m srh ! --srh-hdr-len-eq 8;=;OK ++-m srh ! --srh-hdr-len-gt 8;=;OK ++-m srh ! --srh-hdr-len-lt 8;=;OK ++-m srh ! --srh-segs-left-eq 1;=;OK ++-m srh ! --srh-segs-left-gt 1;=;OK ++-m srh ! --srh-segs-left-lt 1;=;OK ++-m srh ! --srh-last-entry-eq 4;=;OK ++-m srh ! --srh-last-entry-gt 4;=;OK ++-m srh ! --srh-last-entry-lt 4;=;OK ++-m srh ! --srh-tag 0;=;OK ++-m srh --srh-next-hdr 17 --srh-segs-left-eq 1 --srh-last-entry-eq 4 --srh-tag 0;=;OK ++-m srh ! --srh-next-hdr 17 ! --srh-segs-left-eq 0 --srh-tag 0;=;OK ++-m srh --srh-psid A::/64 --srh-nsid B:: --srh-lsid C::/0;;OK ++-m srh ! --srh-psid A::/64 ! --srh-nsid B:: ! --srh-lsid C::/0;;OK ++-m srh;=;OK +diff --git a/extensions/libip6t_standard.t b/extensions/libip6t_standard.t +new file mode 100644 +index 0000000000000..a528af10ea152 +--- /dev/null ++++ b/extensions/libip6t_standard.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++-s ::/128;=;OK ++! -d ::;! -d ::/128;OK ++! -s ::;! -s ::/128;OK ++-s ::/64;=;OK +diff --git a/extensions/libipt_CLUSTERIP.t b/extensions/libipt_CLUSTERIP.t +new file mode 100644 +index 0000000000000..5af555e005c1d +--- /dev/null ++++ b/extensions/libipt_CLUSTERIP.t +@@ -0,0 +1,4 @@ ++:INPUT ++-d 10.31.3.236/32 -i lo -j CLUSTERIP --new --hashmode sourceip --clustermac 01:AA:7B:47:F7:D7 --total-nodes 2 --local-node 0 --hash-init 1;=;FAIL ++-d 10.31.3.236/32 -i lo -j CLUSTERIP --new --hashmode sourceip --clustermac 01:AA:7B:47:F7:D7 --total-nodes 2 --local-node 1 --hash-init 1;=;OK ++-d 10.31.3.236/32 -i lo -j CLUSTERIP --new --hashmode sourceip --clustermac 01:AA:7B:47:F7:D7 --total-nodes 2 --local-node 2 --hash-init 1;=;OK +diff --git a/extensions/libipt_DNAT.t b/extensions/libipt_DNAT.t +new file mode 100644 +index 0000000000000..1c4413b9b3bb5 +--- /dev/null ++++ b/extensions/libipt_DNAT.t +@@ -0,0 +1,16 @@ ++:PREROUTING ++*nat ++-j DNAT --to-destination 1.1.1.1;=;OK ++-j DNAT --to-destination 1.1.1.1-1.1.1.10;=;OK ++-j DNAT --to-destination 1.1.1.1:1025-65535;;FAIL ++-j DNAT --to-destination 1.1.1.1 --to-destination 2.2.2.2;;FAIL ++-p tcp -j DNAT --to-destination 1.1.1.1:1025-65535;=;OK ++-p tcp -j DNAT --to-destination 1.1.1.1-1.1.1.10:1025-65535;=;OK ++-p tcp -j DNAT --to-destination 1.1.1.1-1.1.1.10:1025-65536;;FAIL ++-p tcp -j DNAT --to-destination 1.1.1.1-1.1.1.10:1025-65535 --to-destination 2.2.2.2-2.2.2.20:1025-65535;;FAIL ++-p tcp -j DNAT --to-destination 1.1.1.1:1000-2000/1000;=;OK ++-p tcp -j DNAT --to-destination 1.1.1.1:1000-2000/3000;=;OK ++-p tcp -j DNAT --to-destination 1.1.1.1:1000-2000/65535;=;OK ++-p tcp -j DNAT --to-destination 1.1.1.1:1000-2000/0;;FAIL ++-p tcp -j DNAT --to-destination 1.1.1.1:1000-2000/65536;;FAIL ++-j DNAT;;FAIL +diff --git a/extensions/libipt_ECN.t b/extensions/libipt_ECN.t +new file mode 100644 +index 0000000000000..2e09205212e7f +--- /dev/null ++++ b/extensions/libipt_ECN.t +@@ -0,0 +1,5 @@ ++:PREROUTING,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j ECN;;FAIL ++-p tcp -j ECN;;FAIL ++-p tcp -j ECN --ecn-tcp-remove;=;OK +diff --git a/extensions/libipt_LOG.t b/extensions/libipt_LOG.t +new file mode 100644 +index 0000000000000..fbf5118b2382a +--- /dev/null ++++ b/extensions/libipt_LOG.t +@@ -0,0 +1,12 @@ ++:INPUT,FORWARD,OUTPUT ++-j LOG;-j LOG;OK ++-j LOG --log-prefix "test: ";=;OK ++-j LOG --log-prefix "test: " --log-level 1;=;OK ++# iptables displays the log-level output using the number; not the string ++-j LOG --log-prefix "test: " --log-level alert;-j LOG --log-prefix "test: " --log-level 1;OK ++-j LOG --log-prefix "test: " --log-tcp-sequence;=;OK ++-j LOG --log-prefix "test: " --log-tcp-options;=;OK ++-j LOG --log-prefix "test: " --log-ip-options;=;OK ++-j LOG --log-prefix "test: " --log-uid;=;OK ++-j LOG --log-prefix "test: " --log-level bad;;FAIL ++-j LOG --log-prefix;;FAIL +diff --git a/extensions/libipt_MASQUERADE.t b/extensions/libipt_MASQUERADE.t +new file mode 100644 +index 0000000000000..e25d2a04ab7b0 +--- /dev/null ++++ b/extensions/libipt_MASQUERADE.t +@@ -0,0 +1,9 @@ ++:POSTROUTING ++*nat ++-j MASQUERADE;=;OK ++-j MASQUERADE --random;=;OK ++-j MASQUERADE --random-fully;=;OK ++-p tcp -j MASQUERADE --to-ports 1024;=;OK ++-p udp -j MASQUERADE --to-ports 1024-65535;=;OK ++-p udp -j MASQUERADE --to-ports 1024-65536;;FAIL ++-p udp -j MASQUERADE --to-ports -1;;FAIL +diff --git a/extensions/libipt_NETMAP.t b/extensions/libipt_NETMAP.t +new file mode 100644 +index 0000000000000..31924b985cd6f +--- /dev/null ++++ b/extensions/libipt_NETMAP.t +@@ -0,0 +1,4 @@ ++:PREROUTING,INPUT,OUTPUT,POSTROUTING ++*nat ++-j NETMAP --to 1.2.3.0/24;=;OK ++-j NETMAP --to 1.2.3.4;=;OK +diff --git a/extensions/libipt_REDIRECT.t b/extensions/libipt_REDIRECT.t +new file mode 100644 +index 0000000000000..a0fb0ed19a5ea +--- /dev/null ++++ b/extensions/libipt_REDIRECT.t +@@ -0,0 +1,6 @@ ++:PREROUTING,OUTPUT ++*nat ++-p tcp -j REDIRECT --to-ports 42;=;OK ++-p udp -j REDIRECT --to-ports 42-1234;=;OK ++-p tcp -j REDIRECT --to-ports 42-1234 --random;=;OK ++-j REDIRECT --to-ports 42;;FAIL +diff --git a/extensions/libipt_REJECT.t b/extensions/libipt_REJECT.t +new file mode 100644 +index 0000000000000..5b26b1076b5b2 +--- /dev/null ++++ b/extensions/libipt_REJECT.t +@@ -0,0 +1,9 @@ ++:INPUT,FORWARD,OUTPUT ++-j REJECT;=;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 ++-j REJECT --reject-with icmp-proto-unreachable;=;OK ++-j REJECT --reject-with icmp-net-prohibited;=;OK ++-j REJECT --reject-with icmp-host-prohibited;=;OK ++-j REJECT --reject-with icmp-admin-prohibited;=;OK +diff --git a/extensions/libipt_SNAT.t b/extensions/libipt_SNAT.t +new file mode 100644 +index 0000000000000..186e1cb82c3f3 +--- /dev/null ++++ b/extensions/libipt_SNAT.t +@@ -0,0 +1,11 @@ ++:POSTROUTING ++*nat ++-j SNAT --to-source 1.1.1.1;=;OK ++-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 ++-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 ++-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65535 --to-source 2.2.2.2-2.2.2.20:1025-65535;;FAIL ++-j SNAT;;FAIL +diff --git a/extensions/libipt_TTL.t b/extensions/libipt_TTL.t +new file mode 100644 +index 0000000000000..36809792a4b92 +--- /dev/null ++++ b/extensions/libipt_TTL.t +@@ -0,0 +1,10 @@ ++:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j TTL --ttl-set 42;=;OK ++-j TTL --ttl-inc 1;=;OK ++-j TTL --ttl-dec 1;=;OK ++-j TTL --ttl-set 256;;FAIL ++-j TTL --ttl-inc 0;;FAIL ++-j TTL --ttl-dec 0;;FAIL ++-j TTL --ttl-dec 1 --ttl-inc 1;;FAIL ++-j TTL --ttl-set --ttl-inc 1;;FAIL +diff --git a/extensions/libipt_ah.t b/extensions/libipt_ah.t +new file mode 100644 +index 0000000000000..cd853865638e8 +--- /dev/null ++++ b/extensions/libipt_ah.t +@@ -0,0 +1,13 @@ ++:INPUT,FORWARD,OUTPUT ++-p ah -m ah --ahspi 0;=;OK ++-p ah -m ah --ahspi 4294967295;=;OK ++-p ah -m ah --ahspi 0:4294967295;-p ah -m ah;OK ++-p ah -m ah ! --ahspi 0;=;OK ++-p ah -m ah --ahspi -1;;FAIL ++-p ah -m ah --ahspi 4294967296;;FAIL ++-p ah -m ah --ahspi invalid;;FAIL ++-p ah -m ah --ahspi 0:invalid;;FAIL ++-m ah --ahspi 0;;FAIL ++-m ah --ahspi;;FAIL ++-m ah;;FAIL ++-p ah -m ah;=;OK +diff --git a/extensions/libipt_icmp.t b/extensions/libipt_icmp.t +new file mode 100644 +index 0000000000000..f4ba65c27f032 +--- /dev/null ++++ b/extensions/libipt_icmp.t +@@ -0,0 +1,15 @@ ++:INPUT,FORWARD,OUTPUT ++-p icmp -m icmp --icmp-type any;=;OK ++# output uses the number, better use the name? ++# ERROR: cannot find: iptables -I INPUT -p icmp -m icmp --icmp-type echo-reply ++# -p icmp -m icmp --icmp-type echo-reply;=;OK ++# output uses the number, better use the name? ++# ERROR: annot find: iptables -I INPUT -p icmp -m icmp --icmp-type destination-unreachable ++# -p icmp -m icmp --icmp-type destination-unreachable;=;OK ++# it does not acccept name/name, should we accept this? ++# ERROR: cannot load: iptables -A INPUT -p icmp -m icmp --icmp-type destination-unreachable/network-unreachable ++# -p icmp -m icmp --icmp-type destination-unreachable/network-unreachable;=;OK ++-m icmp;;FAIL ++# we accept "iptables -I INPUT -p tcp -m tcp", why not this below? ++# ERROR: cannot load: iptables -A INPUT -p icmp -m icmp ++# -p icmp -m icmp;=;OK +diff --git a/extensions/libipt_realm.t b/extensions/libipt_realm.t +new file mode 100644 +index 0000000000000..ca66640766983 +--- /dev/null ++++ b/extensions/libipt_realm.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-m realm --realm 0x1/0x2a;=;OK ++-m realm --realm 0x2a;=;OK ++-m realm;;FAIL +diff --git a/extensions/libipt_ttl.t b/extensions/libipt_ttl.t +new file mode 100644 +index 0000000000000..ebe5b3a21a268 +--- /dev/null ++++ b/extensions/libipt_ttl.t +@@ -0,0 +1,15 @@ ++:INPUT,FORWARD,OUTPUT ++-m ttl --ttl-eq 0;=;OK ++-m ttl --ttl-eq 255;=;OK ++-m ttl ! --ttl-eq 0;=;OK ++-m ttl ! --ttl-eq 255;=;OK ++-m ttl --ttl-gt 0;=;OK ++# not possible have anything greater than 255, TTL is 8-bit long ++# ERROR: should fail: iptables -A INPUT -m ttl --ttl-gt 255 ++## -m ttl --ttl-gt 255;;FAIL ++# not possible have anything below 0 ++# ERROR: should fail: iptables -A INPUT -m ttl --ttl-lt 0 ++## -m ttl --ttl-lt 0;;FAIL ++-m ttl --ttl-eq 256;;FAIL ++-m ttl --ttl-eq -1;;FAIL ++-m ttl;;FAIL +diff --git a/extensions/libxt_AUDIT.t b/extensions/libxt_AUDIT.t +new file mode 100644 +index 0000000000000..97575b0eb1ce8 +--- /dev/null ++++ b/extensions/libxt_AUDIT.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-j AUDIT --type accept;=;OK ++-j AUDIT --type drop;=;OK ++-j AUDIT --type reject;=;OK ++-j AUDIT;;FAIL ++-j AUDIT --type wrong;;FAIL +diff --git a/extensions/libxt_CHECKSUM.t b/extensions/libxt_CHECKSUM.t +new file mode 100644 +index 0000000000000..9451ad86489b2 +--- /dev/null ++++ b/extensions/libxt_CHECKSUM.t +@@ -0,0 +1,4 @@ ++:PREROUTING,FORWARD,POSTROUTING ++*mangle ++-j CHECKSUM --checksum-fill;=;OK ++-j CHECKSUM;;FAIL +diff --git a/extensions/libxt_CLASSIFY.t b/extensions/libxt_CLASSIFY.t +new file mode 100644 +index 0000000000000..7b3ddbf75039e +--- /dev/null ++++ b/extensions/libxt_CLASSIFY.t +@@ -0,0 +1,9 @@ ++:FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j CLASSIFY --set-class 0000:ffff;=;OK ++# maximum handle accepted by tc is 0xffff ++# ERROR : should fail: iptables -A FORWARD -t mangle -j CLASSIFY --set-class 0000:ffffffff ++# -j CLASSIFY --set-class 0000:ffffffff;;FAIL ++# ERROR: should fail: iptables -A FORWARD -t mangle -j CLASSIFY --set-class 1:-1 ++# -j CLASSIFY --set-class 1:-1;;FAIL ++-j CLASSIFY;;FAIL +diff --git a/extensions/libxt_CONNMARK.t b/extensions/libxt_CONNMARK.t +new file mode 100644 +index 0000000000000..79a838fefaa14 +--- /dev/null ++++ b/extensions/libxt_CONNMARK.t +@@ -0,0 +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;;FAIL +diff --git a/extensions/libxt_CONNSECMARK.t b/extensions/libxt_CONNSECMARK.t +new file mode 100644 +index 0000000000000..2751b255cd273 +--- /dev/null ++++ b/extensions/libxt_CONNSECMARK.t +@@ -0,0 +1,5 @@ ++:PREROUTING,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j CONNSECMARK --restore;=;OK ++-j CONNSECMARK --save;=;OK ++-j CONNSECMARK;;FAIL +diff --git a/extensions/libxt_CT.t b/extensions/libxt_CT.t +new file mode 100644 +index 0000000000000..3c28534e8169e +--- /dev/null ++++ b/extensions/libxt_CT.t +@@ -0,0 +1,20 @@ ++:PREROUTING,OUTPUT ++*raw ++-j CT --notrack;=;OK ++-j CT --ctevents new,related,destroy,reply,assured,protoinfo,helper,mark;=;OK ++-j CT --expevents new;=;OK ++# ERROR: cannot find: iptables -I PREROUTING -t raw -j CT --zone 0 ++# -j CT --zone 0;=;OK ++-j CT --zone 65535;=;OK ++-j CT --zone 65536;;FAIL ++-j CT --zone -1;;FAIL ++# ERROR: should fail: iptables -A PREROUTING -t raw -j CT ++# -j CT;;FAIL ++@nfct timeout add test inet tcp ESTABLISHED 100 ++# cannot load: iptables -A PREROUTING -t raw -j CT --timeout test ++# -j CT --timeout test;=;OK ++@nfct timeout del test ++@nfct helper add rpc inet tcp ++# cannot load: iptables -A PREROUTING -t raw -j CT --helper rpc ++# -j CT --helper rpc;=;OK ++@nfct helper del rpc +diff --git a/extensions/libxt_DSCP.t b/extensions/libxt_DSCP.t +new file mode 100644 +index 0000000000000..fcc55986dbcd7 +--- /dev/null ++++ b/extensions/libxt_DSCP.t +@@ -0,0 +1,11 @@ ++:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j DSCP --set-dscp 0;=;OK ++-j DSCP --set-dscp 0x3f;=;OK ++-j DSCP --set-dscp -1;;FAIL ++-j DSCP --set-dscp 0x40;;FAIL ++-j DSCP --set-dscp 0x3f --set-dscp-class CS0;;FAIL ++-j DSCP --set-dscp-class CS0;-j DSCP --set-dscp 0x00;OK ++-j DSCP --set-dscp-class BE;-j DSCP --set-dscp 0x00;OK ++-j DSCP --set-dscp-class EF;-j DSCP --set-dscp 0x2e;OK ++-j DSCP;;FAIL +diff --git a/extensions/libxt_HMARK.t b/extensions/libxt_HMARK.t +new file mode 100644 +index 0000000000000..3bcf1dada5d02 +--- /dev/null ++++ b/extensions/libxt_HMARK.t +@@ -0,0 +1,8 @@ ++:INPUT,FORWARD,OUTPUT ++-j HMARK;;FAIL ++-j HMARK --hmark-src-prefix 32 --hmark-rnd 0x00000004 --hmark-mod 42;=;OK ++-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-sport-mask 0xffff --hmark-dport-mask 0xffff --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK ++-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-spi-mask 0x00000004 --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK ++-j HMARK --hmark-src-prefix 1 --hmark-dst-prefix 2 --hmark-sport-mask 0x0003 --hmark-dport-mask 0x0004 --hmark-proto-mask 0x05 --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct;=;OK ++# cannot mix in spi mask: ++-j HMARK --hmark-src-prefix 32 --hmark-dst-prefix 32 --hmark-sport-mask 0xffff --hmark-dport-mask 0xffff --hmark-proto-mask 0xffff --hmark-rnd 0x00000004 --hmark-mod 42 --hmark-offset 1 --hmark-tuple ct --hmark-spi-mask 4;;FAIL +diff --git a/extensions/libxt_IDLETIMER.t b/extensions/libxt_IDLETIMER.t +new file mode 100644 +index 0000000000000..6afd92c1a1c88 +--- /dev/null ++++ b/extensions/libxt_IDLETIMER.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-j IDLETIMER --timeout;;FAIL ++-j IDLETIMER --timeout 42;;FAIL ++-j IDLETIMER --timeout 42 --label foo;=;OK +diff --git a/extensions/libxt_LED.t b/extensions/libxt_LED.t +new file mode 100644 +index 0000000000000..1f6705f464b1d +--- /dev/null ++++ b/extensions/libxt_LED.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-j LED;;FAIL ++-j LED --led-trigger-id "foo";=;OK ++-j LED --led-trigger-id "foo" --led-delay 42 --led-always-blink;=;OK +diff --git a/extensions/libxt_MARK.t b/extensions/libxt_MARK.t +new file mode 100644 +index 0000000000000..9d1aa7d7d58a4 +--- /dev/null ++++ b/extensions/libxt_MARK.t +@@ -0,0 +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 4294967296;;FAIL ++-j MARK --set-xmark -1;;FAIL ++-j MARK;;FAIL +diff --git a/extensions/libxt_NFLOG.t b/extensions/libxt_NFLOG.t +new file mode 100644 +index 0000000000000..933fa22160e59 +--- /dev/null ++++ b/extensions/libxt_NFLOG.t +@@ -0,0 +1,24 @@ ++:INPUT,FORWARD,OUTPUT ++-j NFLOG --nflog-group 1;=;OK ++-j NFLOG --nflog-group 65535;=;OK ++-j NFLOG --nflog-group 65536;;FAIL ++-j NFLOG --nflog-group 0;-j NFLOG;OK ++-j NFLOG --nflog-range 1;=;OK ++-j NFLOG --nflog-range 4294967295;=;OK ++-j NFLOG --nflog-range 4294967296;;FAIL ++-j NFLOG --nflog-range -1;;FAIL ++-j NFLOG --nflog-size 0;=;OK ++-j NFLOG --nflog-size 1;=;OK ++-j NFLOG --nflog-size 4294967295;=;OK ++-j NFLOG --nflog-size 4294967296;;FAIL ++-j NFLOG --nflog-size -1;;FAIL ++# ERROR: cannot find: iptables -I INPUT -j NFLOG --nflog-prefix xxxxxx [...] ++# -j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;=;OK ++# ERROR: should fail: iptables -A INPUT -j NFLOG --nflog-prefix xxxxxxx [...] ++# -j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;;FAIL ++-j NFLOG --nflog-threshold 1;=;OK ++# ERROR: line 13 (should fail: iptables -A INPUT -j NFLOG --nflog-threshold 0 ++# -j NFLOG --nflog-threshold 0;;FAIL ++-j NFLOG --nflog-threshold 65535;=;OK ++-j NFLOG --nflog-threshold 65536;;FAIL ++-j NFLOG;=;OK +diff --git a/extensions/libxt_NFQUEUE.t b/extensions/libxt_NFQUEUE.t +new file mode 100644 +index 0000000000000..b51b19fd435f7 +--- /dev/null ++++ b/extensions/libxt_NFQUEUE.t +@@ -0,0 +1,16 @@ ++:INPUT,FORWARD,OUTPUT ++-j NFQUEUE;=;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:65536;;FAIL ++-j NFQUEUE --queue-balance -1:65535;;FAIL ++-j NFQUEUE --queue-num 10 --queue-bypass;=;OK ++-j NFQUEUE --queue-balance 0:6 --queue-cpu-fanout --queue-bypass;-j NFQUEUE --queue-balance 0:6 --queue-bypass --queue-cpu-fanout;OK ++-j NFQUEUE --queue-bypass --queue-balance 0:6 --queue-cpu-fanout;-j NFQUEUE --queue-balance 0:6 --queue-bypass --queue-cpu-fanout;OK ++-j NFQUEUE --queue-balance 0:6 --queue-bypass;=;OK ++-j NFQUEUE --queue-bypass;-j NFQUEUE --queue-num 0 --queue-bypass;OK +diff --git a/extensions/libxt_NOTRACK.t b/extensions/libxt_NOTRACK.t +new file mode 100644 +index 0000000000000..585be82d56ecb +--- /dev/null ++++ b/extensions/libxt_NOTRACK.t +@@ -0,0 +1,4 @@ ++:PREROUTING,OUTPUT ++*raw ++# ERROR: cannot find: iptables -I PREROUTING -t raw -j NOTRACK ++#-j NOTRACK;=;OK +diff --git a/extensions/libxt_RATEEST.t b/extensions/libxt_RATEEST.t +new file mode 100644 +index 0000000000000..c2b6bb34e7aa2 +--- /dev/null ++++ b/extensions/libxt_RATEEST.t +@@ -0,0 +1,2 @@ ++:INPUT,FORWARD,OUTPUT ++-j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms;=;OK +diff --git a/extensions/libxt_SET.t b/extensions/libxt_SET.t +new file mode 100644 +index 0000000000000..30c27ca319176 +--- /dev/null ++++ b/extensions/libxt_SET.t +@@ -0,0 +1,3 @@ ++:INPUT,FORWARD,OUTPUT ++# fails: foo does not exist ++-j SET --add-set foo src,dst;;FAIL +diff --git a/extensions/libxt_SYNPROXY.t b/extensions/libxt_SYNPROXY.t +new file mode 100644 +index 0000000000000..dd8b0e769f568 +--- /dev/null ++++ b/extensions/libxt_SYNPROXY.t +@@ -0,0 +1,3 @@ ++:INPUT,FORWARD ++-j SYNPROXY --sack-perm --timestamp --mss 1460 --wscale 9;;FAIL ++-p tcp -m tcp --dport 42 -m conntrack --ctstate INVALID,UNTRACKED -j SYNPROXY --sack-perm --timestamp --wscale 9 --mss 1460;=;OK +diff --git a/extensions/libxt_TCPMSS.t b/extensions/libxt_TCPMSS.t +new file mode 100644 +index 0000000000000..553a3452e4876 +--- /dev/null ++++ b/extensions/libxt_TCPMSS.t +@@ -0,0 +1,6 @@ ++:FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j TCPMSS;;FAIL ++-p tcp -j TCPMSS --set-mss 42;;FAIL ++-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --set-mss 42;=;OK ++-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --clamp-mss-to-pmtu;=;OK +diff --git a/extensions/libxt_TCPOPTSTRIP.t b/extensions/libxt_TCPOPTSTRIP.t +new file mode 100644 +index 0000000000000..b5c7a109e5b91 +--- /dev/null ++++ b/extensions/libxt_TCPOPTSTRIP.t +@@ -0,0 +1,8 @@ ++:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j TCPOPTSTRIP;;FAIL ++-p tcp -j TCPOPTSTRIP;=;OK ++-p tcp -j TCPOPTSTRIP --strip-options 2,3,4,5,6,7;=;OK ++-p tcp -j TCPOPTSTRIP --strip-options 0;;FAIL ++-p tcp -j TCPOPTSTRIP --strip-options 1;;FAIL ++-p tcp -j TCPOPTSTRIP --strip-options 1,2;;FAIL +diff --git a/extensions/libxt_TEE.t b/extensions/libxt_TEE.t +new file mode 100644 +index 0000000000000..ce8b103e0dc24 +--- /dev/null ++++ b/extensions/libxt_TEE.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-j TEE --gateway 1.1.1.1;=;OK ++-j TEE ! --gateway 1.1.1.1;;FAIL ++-j TEE;;FAIL +diff --git a/extensions/libxt_TOS.t b/extensions/libxt_TOS.t +new file mode 100644 +index 0000000000000..ae8531cc582e2 +--- /dev/null ++++ b/extensions/libxt_TOS.t +@@ -0,0 +1,16 @@ ++:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING ++*mangle ++-j TOS --set-tos 0x1f;=;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 --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 ++-j TOS;;FAIL +diff --git a/extensions/libxt_TPROXY.t b/extensions/libxt_TPROXY.t +new file mode 100644 +index 0000000000000..12f82b1fae76a +--- /dev/null ++++ b/extensions/libxt_TPROXY.t +@@ -0,0 +1,5 @@ ++:PREROUTING ++*mangle ++-j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;;FAIL ++-p udp -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;=;OK ++-p tcp -m tcp --dport 2342 -j TPROXY --on-port 12345 --on-ip 10.0.0.1 --tproxy-mark 0x23/0xff;=;OK +diff --git a/extensions/libxt_TRACE.t b/extensions/libxt_TRACE.t +new file mode 100644 +index 0000000000000..cadb7330174e5 +--- /dev/null ++++ b/extensions/libxt_TRACE.t +@@ -0,0 +1,3 @@ ++:PREROUTING,OUTPUT ++*raw ++-j TRACE;=;OK +diff --git a/extensions/libxt_addrtype.t b/extensions/libxt_addrtype.t +new file mode 100644 +index 0000000000000..390a63f0fa232 +--- /dev/null ++++ b/extensions/libxt_addrtype.t +@@ -0,0 +1,17 @@ ++:INPUT,FORWARD,OUTPUT ++-m addrtype;;FAIL ++-m addrtype --src-type wrong;;FAIL ++-m addrtype --src-type UNSPEC;=;OK ++-m addrtype --dst-type UNSPEC;=;OK ++-m addrtype --src-type LOCAL --dst-type LOCAL;=;OK ++-m addrtype --dst-type UNSPEC;=;OK ++-m addrtype --limit-iface-in;;FAIL ++-m addrtype --limit-iface-out;;FAIL ++-m addrtype --limit-iface-in --limit-iface-out;;FAIL ++-m addrtype --src-type LOCAL --limit-iface-in --limit-iface-out;;FAIL ++:INPUT ++-m addrtype --src-type LOCAL --limit-iface-in;=;OK ++-m addrtype --dst-type LOCAL --limit-iface-in;=;OK ++:OUTPUT ++-m addrtype --src-type LOCAL --limit-iface-out;=;OK ++-m addrtype --dst-type LOCAL --limit-iface-out;=;OK +diff --git a/extensions/libxt_bpf.t b/extensions/libxt_bpf.t +new file mode 100644 +index 0000000000000..80361ad52e713 +--- /dev/null ++++ b/extensions/libxt_bpf.t +@@ -0,0 +1,2 @@ ++:INPUT,FORWARD,OUTPUT ++-m bpf --bytecode "4,48 0 0 9,21 0 1 6,6 0 0 1,6 0 0 0";=;OK +diff --git a/extensions/libxt_cgroup.t b/extensions/libxt_cgroup.t +new file mode 100644 +index 0000000000000..72c8e37708e95 +--- /dev/null ++++ b/extensions/libxt_cgroup.t +@@ -0,0 +1,8 @@ ++:INPUT,OUTPUT,POSTROUTING ++*mangle ++-m cgroup --cgroup 1;=;OK ++-m cgroup ! --cgroup 1;=;OK ++-m cgroup --path "/";=;OK ++-m cgroup ! --path "/";=;OK ++-m cgroup --cgroup 1 --path "/";;FAIL ++-m cgroup ;;FAIL +diff --git a/extensions/libxt_cluster.t b/extensions/libxt_cluster.t +new file mode 100644 +index 0000000000000..ac608244833f2 +--- /dev/null ++++ b/extensions/libxt_cluster.t +@@ -0,0 +1,10 @@ ++:PREROUTING,FORWARD,POSTROUTING ++*mangle ++-m cluster;;FAIL ++-m cluster --cluster-total-nodes 3;;FAIL ++-m cluster --cluster-total-nodes 2 --cluster-local-node 2;;FAIL ++-m cluster --cluster-total-nodes 2 --cluster-local-node 3 --cluster-hash-seed;;FAIL ++# ++# outputs --cluster-local-nodemask instead of --cluster-local-node ++# ++-m cluster --cluster-total-nodes 2 --cluster-local-node 2 --cluster-hash-seed 0xfeedcafe;-m cluster --cluster-local-nodemask 0x00000002 --cluster-total-nodes 2 --cluster-hash-seed 0xfeedcafe;OK +diff --git a/extensions/libxt_comment.t b/extensions/libxt_comment.t +new file mode 100644 +index 0000000000000..f12cd66841e7f +--- /dev/null ++++ b/extensions/libxt_comment.t +@@ -0,0 +1,12 @@ ++:INPUT,FORWARD,OUTPUT ++-m comment;;FAIL ++-m comment --comment;;FAIL ++# ++# it fails with 256 characters ++# ++# should fail: iptables -A INPUT -m comment --comment xxxxxxxxxxxxxxxxx [....] ++# -m comment --comment xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;;FAIL ++# ++# success with 255 characters ++# ++-m comment --comment xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;=;OK +diff --git a/extensions/libxt_connbytes.t b/extensions/libxt_connbytes.t +new file mode 100644 +index 0000000000000..6b24e266c1a04 +--- /dev/null ++++ b/extensions/libxt_connbytes.t +@@ -0,0 +1,21 @@ ++:INPUT,FORWARD,OUTPUT ++-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir original;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir reply;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode packets --connbytes-dir both;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode bytes --connbytes-dir original;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode bytes --connbytes-dir reply;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode bytes --connbytes-dir both;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir original;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir reply;=;OK ++-m connbytes --connbytes 0:1000 --connbytes-mode avgpkt --connbytes-dir both;=;OK ++-m connbytes --connbytes -1:0 --connbytes-mode packets --connbytes-dir original;;FAIL ++-m connbytes --connbytes 0:-1 --connbytes-mode packets --connbytes-dir original;;FAIL ++# ERROR: cannot find: iptables -I INPUT -m connbytes --connbytes 0:18446744073709551615 --connbytes-mode avgpkt --connbytes-dir both ++# -m connbytes --connbytes 0:18446744073709551615 --connbytes-mode avgpkt --connbytes-dir both;=;OK ++-m connbytes --connbytes 0:18446744073709551616 --connbytes-mode avgpkt --connbytes-dir both;;FAIL ++-m connbytes --connbytes 0:1000 --connbytes-mode wrong --connbytes-dir both;;FAIL ++-m connbytes --connbytes 0:1000 --connbytes-dir original;;FAIL ++-m connbytes --connbytes 0:1000 --connbytes-mode packets;;FAIL ++-m connbytes --connbytes-dir original;;FAIL ++-m connbytes --connbytes 0:1000;;FAIL ++-m connbytes;;FAIL +diff --git a/extensions/libxt_connlabel.t b/extensions/libxt_connlabel.t +new file mode 100644 +index 0000000000000..aad1032b5a8bb +--- /dev/null ++++ b/extensions/libxt_connlabel.t +@@ -0,0 +1,18 @@ ++:INPUT,FORWARD,OUTPUT ++# Backup the connlabel.conf, then add some label maps for test ++@[ -f /etc/xtables/connlabel.conf ] && mv /etc/xtables/connlabel.conf /tmp/connlabel.conf.bak ++@mkdir -p /etc/xtables ++@echo "40 bit40" > /etc/xtables/connlabel.conf ++@echo "41 bit41" >> /etc/xtables/connlabel.conf ++@echo "128 bit128" >> /etc/xtables/connlabel.conf ++-m connlabel --label "bit40";=;OK ++-m connlabel ! --label "bit40";=;OK ++-m connlabel --label "bit41" --set;=;OK ++-m connlabel ! --label "bit41" --set;=;OK ++-m connlabel --label "bit128";;FAIL ++@echo > /etc/xtables/connlabel.conf ++-m connlabel --label "abc";;FAIL ++@rm -f /etc/xtables/connlabel.conf ++-m connlabel --label "abc";;FAIL ++# Restore the original connlabel.conf ++@[ -f /tmp/connlabel.conf.bak ] && mv /tmp/connlabel.conf.bak /etc/xtables/connlabel.conf +diff --git a/extensions/libxt_connlimit.t b/extensions/libxt_connlimit.t +new file mode 100644 +index 0000000000000..c7ea61e95fbc8 +--- /dev/null ++++ b/extensions/libxt_connlimit.t +@@ -0,0 +1,16 @@ ++: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 -1;;FAIL ++-m connlimit --connlimit-above 0;=;OK ++-m connlimit --connlimit-above 4294967295;=;OK ++-m connlimit --connlimit-above 4294967296;;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 ++-m connlimit --connlimit-above 10 --connlimit-daddr;-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-daddr;OK ++-m connlimit --connlimit-above 10 --connlimit-saddr --connlimit-daddr;;FAIL ++-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-saddr;=;OK ++-m connlimit --connlimit-above 10 --connlimit-mask 32 --connlimit-daddr;=;OK ++-m connlimit;;FAIL +diff --git a/extensions/libxt_connmark.t b/extensions/libxt_connmark.t +new file mode 100644 +index 0000000000000..4dd7d9af265a5 +--- /dev/null ++++ b/extensions/libxt_connmark.t +@@ -0,0 +1,9 @@ ++:PREROUTING,FORWARD,OUTPUT,POSTROUTING ++*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 -1;;FAIL ++-m connmark --mark 0xfffffffff;;FAIL ++-m connmark;;FAIL +diff --git a/extensions/libxt_conntrack.t b/extensions/libxt_conntrack.t +new file mode 100644 +index 0000000000000..db53147532afd +--- /dev/null ++++ b/extensions/libxt_conntrack.t +@@ -0,0 +1,27 @@ ++:INPUT,FORWARD,OUTPUT ++-m conntrack --ctstate NEW;=;OK ++-m conntrack --ctstate NEW,ESTABLISHED;=;OK ++-m conntrack --ctstate NEW,RELATED,ESTABLISHED;=;OK ++-m conntrack --ctstate INVALID;=;OK ++-m conntrack --ctstate UNTRACKED;=;OK ++-m conntrack --ctstate SNAT,DNAT;=;OK ++-m conntrack --ctstate wrong;;FAIL ++# should we convert this to output "tcp" instead of 6? ++-m conntrack --ctproto tcp;-m conntrack --ctproto 6;OK ++-m conntrack --ctorigsrc 1.1.1.1;=;OK ++-m conntrack --ctorigdst 1.1.1.1;=;OK ++-m conntrack --ctreplsrc 1.1.1.1;=;OK ++-m conntrack --ctrepldst 1.1.1.1;=;OK ++-m conntrack --ctexpire 0;=;OK ++-m conntrack --ctexpire 4294967295;=;OK ++-m conntrack --ctexpire 0:4294967295;=;OK ++-m conntrack --ctexpire 42949672956;;FAIL ++-m conntrack --ctexpire -1;;FAIL ++-m conntrack --ctdir ORIGINAL;=;OK ++-m conntrack --ctdir REPLY;=;OK ++-m conntrack --ctstatus NONE;=;OK ++-m conntrack --ctstatus CONFIRMED;=;OK ++-m conntrack --ctstatus ASSURED;=;OK ++-m conntrack --ctstatus EXPECTED;=;OK ++-m conntrack --ctstatus SEEN_REPLY;=;OK ++-m conntrack;;FAIL +diff --git a/extensions/libxt_cpu.t b/extensions/libxt_cpu.t +new file mode 100644 +index 0000000000000..f5adb45db7424 +--- /dev/null ++++ b/extensions/libxt_cpu.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m cpu --cpu 0;=;OK ++-m cpu ! --cpu 0;=;OK ++-m cpu --cpu 4294967295;=;OK ++-m cpu --cpu 4294967296;;FAIL ++-m cpu;;FAIL +diff --git a/extensions/libxt_dccp.t b/extensions/libxt_dccp.t +new file mode 100644 +index 0000000000000..f60b480fb6fc7 +--- /dev/null ++++ b/extensions/libxt_dccp.t +@@ -0,0 +1,30 @@ ++:INPUT,FORWARD,OUTPUT ++-p dccp -m dccp --sport 1;=;OK ++-p dccp -m dccp --sport 65535;=;OK ++-p dccp -m dccp --dport 1;=;OK ++-p dccp -m dccp --dport 65535;=;OK ++-p dccp -m dccp --sport 1:1023;=;OK ++-p dccp -m dccp --sport 1024:65535;=;OK ++-p dccp -m dccp --sport 1024:;-p dccp -m dccp --sport 1024:65535;OK ++-p dccp -m dccp ! --sport 1;=;OK ++-p dccp -m dccp ! --sport 65535;=;OK ++-p dccp -m dccp ! --dport 1;=;OK ++-p dccp -m dccp ! --dport 65535;=;OK ++-p dccp -m dccp --sport 1 --dport 65535;=;OK ++-p dccp -m dccp --sport 65535 --dport 1;=;OK ++-p dccp -m dccp ! --sport 1 --dport 65535;=;OK ++-p dccp -m dccp ! --sport 65535 --dport 1;=;OK ++# ERROR: should fail: iptables -A INPUT -p dccp -m dccp --sport 65536 ++# -p dccp -m dccp --sport 65536;;FAIL ++-p dccp -m dccp --sport -1;;FAIL ++-p dccp -m dccp --dport -1;;FAIL ++-p dccp -m dccp --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,RESET,SYNC,SYNCACK,INVALID;=;OK ++-p dccp -m dccp ! --dccp-types REQUEST,RESPONSE,DATA,ACK,DATAACK,CLOSEREQ,CLOSE,RESET,SYNC,SYNCACK,INVALID;=;OK ++# DCCP option 0 is valid, see http://tools.ietf.org/html/rfc4340#page-29 ++# ERROR: cannot load: iptables -A INPUT -p dccp -m dccp --dccp-option 0 ++#-p dccp -m dccp --dccp-option 0;=;OK ++-p dccp -m dccp --dccp-option 255;=;OK ++-p dccp -m dccp --dccp-option 256;;FAIL ++-p dccp -m dccp --dccp-option -1;;FAIL ++# should we accept this below? ++-p dccp -m dccp;=;OK +diff --git a/extensions/libxt_dscp.t b/extensions/libxt_dscp.t +new file mode 100644 +index 0000000000000..38d7f04e18698 +--- /dev/null ++++ b/extensions/libxt_dscp.t +@@ -0,0 +1,10 @@ ++:INPUT,FORWARD,OUTPUT ++-m dscp --dscp 0;=;OK ++-m dscp --dscp 0x3f;=;OK ++-m dscp --dscp -1;;FAIL ++-m dscp --dscp 0x40;;FAIL ++-m dscp --dscp 0x3f --dscp-class CS0;;FAIL ++-m dscp --dscp-class CS0;-m dscp --dscp 0x00;OK ++-m dscp --dscp-class BE;-m dscp --dscp 0x00;OK ++-m dscp --dscp-class EF;-m dscp --dscp 0x2e;OK ++-m dscp;;FAIL +diff --git a/extensions/libxt_ecn.t b/extensions/libxt_ecn.t +new file mode 100644 +index 0000000000000..b32aea306dcae +--- /dev/null ++++ b/extensions/libxt_ecn.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD,OUTPUT ++-m ecn --ecn-tcp-cwr;;FAIL ++-p tcp -m ecn --ecn-tcp-cwr;=;OK ++-p tcp -m ecn --ecn-tcp-ece --ecn-tcp-cwr --ecn-ip-ect 2;=;OK ++-p tcp -m ecn ! --ecn-tcp-ece ! --ecn-tcp-cwr ! --ecn-ip-ect 2;=;OK +diff --git a/extensions/libxt_esp.t b/extensions/libxt_esp.t +new file mode 100644 +index 0000000000000..92c5779f860f1 +--- /dev/null ++++ b/extensions/libxt_esp.t +@@ -0,0 +1,8 @@ ++:INPUT,FORWARD,OUTPUT ++-p esp -m esp --espspi 0;=;OK ++-p esp -m esp --espspi :32;-p esp -m esp --espspi 0:32;OK ++-p esp -m esp --espspi 0:4294967295;-p esp -m esp;OK ++-p esp -m esp ! --espspi 0:4294967294;=;OK ++-p esp -m esp --espspi -1;;FAIL ++-p esp -m esp;=;OK ++-m esp;;FAIL +diff --git a/extensions/libxt_hashlimit.t b/extensions/libxt_hashlimit.t +new file mode 100644 +index 0000000000000..ccd0d1e6a2a1a +--- /dev/null ++++ b/extensions/libxt_hashlimit.t +@@ -0,0 +1,33 @@ ++:INPUT,FORWARD,OUTPUT ++-m hashlimit --hashlimit-above 1/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-above 1000000/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-above 1/min --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-above 1/hour --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++# kernel says "xt_hashlimit: overflow, try lower: 864000000/5" ++-m hashlimit --hashlimit-above 1/day --hashlimit-burst 5 --hashlimit-name mini1;;FAIL ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-upto 1000000/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-upto 1/min --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++# kernel says "xt_hashlimit: overflow, try lower: 864000000/5" ++-m hashlimit --hashlimit-upto 1/day --hashlimit-burst 5 --hashlimit-name mini1;;FAIL ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode srcip --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-max 2000 --hashlimit-htable-expire 2000;=;OK ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-max 2000 --hashlimit-htable-gcinterval 60000 --hashlimit-htable-expire 2000;=;OK ++-m hashlimit --hashlimit-upto 1/sec --hashlimit-name mini1;-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-name mini1;OK ++-m hashlimit --hashlimit-upto 4kb/s --hashlimit-burst 400kb --hashlimit-name mini5;=;OK ++-m hashlimit --hashlimit-upto 10mb/s --hashlimit-name mini6;=;OK ++-m hashlimit --hashlimit-upto 123456b/s --hashlimit-burst 1mb --hashlimit-name mini7;=;OK ++# should work, it says "iptables v1.4.15: burst cannot be smaller than 96b" ++# ERROR: cannot load: iptables -A INPUT -m hashlimit --hashlimit-upto 96b/s --hashlimit-burst 5 --hashlimit-name mini1 ++# -m hashlimit --hashlimit-upto 96b/s --hashlimit-burst 5 --hashlimit-name mini1;=;OK ++-m hashlimit --hashlimit-name mini1;;FAIL ++-m hashlimit --hashlimit-upto 1/sec;;FAIL ++-m hashlimit;;FAIL ++-m hashlimit --hashlimit-upto 40/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name syn-flood;=;OK ++-m hashlimit --hashlimit-upto 40/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name rate1 --hashlimit-rate-match;=;OK ++-m hashlimit --hashlimit-upto 40mb/s --hashlimit-mode srcip --hashlimit-name rate2 --hashlimit-rate-match;=;OK ++-m hashlimit --hashlimit-upto 40/sec --hashlimit-burst 20 --hashlimit-mode srcip --hashlimit-name rate3 --hashlimit-rate-match --hashlimit-rate-interval 10;=;OK ++-m hashlimit --hashlimit-upto 40mb/s --hashlimit-mode srcip --hashlimit-name rate4 --hashlimit-rate-match --hashlimit-rate-interval 10;=;OK +diff --git a/extensions/libxt_helper.t b/extensions/libxt_helper.t +new file mode 100644 +index 0000000000000..8c8420ac5693a +--- /dev/null ++++ b/extensions/libxt_helper.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m helper --helper ftp;=;OK ++# should be OK? ++# ERROR: should fail: iptables -A INPUT -m helper --helper wrong ++# -m helper --helper wrong;;FAIL ++-m helper;;FAIL +diff --git a/extensions/libxt_ipcomp.t b/extensions/libxt_ipcomp.t +new file mode 100644 +index 0000000000000..8546ba9ce416f +--- /dev/null ++++ b/extensions/libxt_ipcomp.t +@@ -0,0 +1,3 @@ ++:INPUT,OUTPUT ++-p ipcomp -m ipcomp --ipcompspi 18 -j DROP;=;OK ++-p ipcomp -m ipcomp ! --ipcompspi 18 -j ACCEPT;=;OK +diff --git a/extensions/libxt_iprange.t b/extensions/libxt_iprange.t +new file mode 100644 +index 0000000000000..6fd98be656028 +--- /dev/null ++++ b/extensions/libxt_iprange.t +@@ -0,0 +1,11 @@ ++:INPUT,FORWARD,OUTPUT ++-m iprange --src-range 1.1.1.1-1.1.1.10;=;OK ++-m iprange ! --src-range 1.1.1.1-1.1.1.10;=;OK ++-m iprange --dst-range 1.1.1.1-1.1.1.10;=;OK ++-m iprange ! --dst-range 1.1.1.1-1.1.1.10;=;OK ++# it shows -A INPUT -m iprange --src-range 1.1.1.1-1.1.1.1, should we support this? ++# ERROR: should fail: iptables -A INPUT -m iprange --src-range 1.1.1.1 ++# -m iprange --src-range 1.1.1.1;;FAIL ++# ERROR: should fail: iptables -A INPUT -m iprange --dst-range 1.1.1.1 ++#-m iprange --dst-range 1.1.1.1;;FAIL ++-m iprange;;FAIL +diff --git a/extensions/libxt_length.t b/extensions/libxt_length.t +new file mode 100644 +index 0000000000000..0b6624ee069f6 +--- /dev/null ++++ b/extensions/libxt_length.t +@@ -0,0 +1,10 @@ ++:INPUT,FORWARD,OUTPUT ++-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 0:65535;=;OK ++-m length ! --length 0:65535;=;OK ++-m length --length 0:65536;;FAIL ++-m length --length -1:65535;;FAIL ++-m length;;FAIL +diff --git a/extensions/libxt_limit.t b/extensions/libxt_limit.t +new file mode 100644 +index 0000000000000..b0af6538a9c05 +--- /dev/null ++++ b/extensions/libxt_limit.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m limit --limit 1/sec;=;OK ++-m limit --limit 1/min;=;OK ++-m limit --limit 1000/hour;=;OK ++-m limit --limit 1000/day;=;OK ++-m limit --limit 1/sec --limit-burst 1;=;OK +diff --git a/extensions/libxt_mac.t b/extensions/libxt_mac.t +new file mode 100644 +index 0000000000000..a5ec81d80e23d +--- /dev/null ++++ b/extensions/libxt_mac.t +@@ -0,0 +1,5 @@ ++:INPUT,FORWARD ++-m mac --mac-source 42:01:02:03:04:05;=;OK ++-m mac --mac-source 42:01:02:03:04;=;FAIL ++-m mac --mac-source 42:01:02:03:04:05:06;=;FAIL ++-m mac;;FAIL +diff --git a/extensions/libxt_mark.t b/extensions/libxt_mark.t +new file mode 100644 +index 0000000000000..7c005379f6d64 +--- /dev/null ++++ b/extensions/libxt_mark.t +@@ -0,0 +1,7 @@ ++:INPUT,FORWARD,OUTPUT ++-m mark --mark 0xfeedcafe/0xfeedcafe;=;OK ++-m mark --mark 0;=;OK ++-m mark --mark 4294967295;-m mark --mark 0xffffffff;OK ++-m mark --mark 4294967296;;FAIL ++-m mark --mark -1;;FAIL ++-m mark;;FAIL +diff --git a/extensions/libxt_multiport.t b/extensions/libxt_multiport.t +new file mode 100644 +index 0000000000000..e9b80a4ee376b +--- /dev/null ++++ b/extensions/libxt_multiport.t +@@ -0,0 +1,23 @@ ++:INPUT,FORWARD,OUTPUT ++-p tcp -m multiport --sports 53,1024:65535;=;OK ++-p tcp -m multiport --dports 53,1024:65535;=;OK ++-p udp -m multiport --sports 53,1024:65535;=;OK ++-p udp -m multiport --dports 53,1024:65535;=;OK ++-p udp -m multiport --ports 53,1024:65535;=;OK ++-p udp -m multiport --ports 53,1024:65535;=;OK ++-p sctp -m multiport --sports 53,1024:65535;=;OK ++-p sctp -m multiport --dports 53,1024:65535;=;OK ++-p dccp -m multiport --sports 53,1024:65535;=;OK ++-p dccp -m multiport --dports 53,1024:65535;=;OK ++-p udplite -m multiport --sports 53,1024:65535;=;OK ++-p udplite -m multiport --dports 53,1024:65535;=;OK ++-p tcp -m multiport --sports 1024:65536;;FAIL ++-p udp -m multiport --sports 1024:65536;;FAIL ++-p tcp -m multiport --ports 1024:65536;;FAIL ++-p udp -m multiport --ports 1024:65536;;FAIL ++-p tcp -m multiport --ports 1,2,3,4,6,7,8,9,10,11,12,13,14,15;=;OK ++# fix manpage, it says "up to 15 ports supported" ++# ERROR: should fail: iptables -A INPUT -p tcp -m multiport --ports 1,2,3,4,6,7,8,9,10,11,12,13,14,15,16 ++# -p tcp -m multiport --ports 1,2,3,4,6,7,8,9,10,11,12,13,14,15,16;;FAIL ++-p tcp --multiport;;FAIL ++-m multiport;;FAIL +diff --git a/extensions/libxt_nfacct.t b/extensions/libxt_nfacct.t +new file mode 100644 +index 0000000000000..3419b4cebfebf +--- /dev/null ++++ b/extensions/libxt_nfacct.t +@@ -0,0 +1,10 @@ ++:INPUT,FORWARD,OUTPUT ++@nfacct add test ++# ++# extra space in iptables-save output, fix it ++# ++# ERROR: cannot load: iptables -A INPUT -m nfacct --nfacct-name test ++#-m nfacct --nfacct-name test;=;OK ++-m nfacct --nfacct-name wrong;;FAIL ++-m nfacct;;FAIL ++@nfacct del test +diff --git a/extensions/libxt_osf.t b/extensions/libxt_osf.t +new file mode 100644 +index 0000000000000..ede6d32c7cc4c +--- /dev/null ++++ b/extensions/libxt_osf.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD ++-m osf --genre linux --ttl 0 --log 0;;FAIL ++-p tcp -m osf --genre linux --ttl 0 --log 0;=;OK ++-p tcp -m osf --genre linux --ttl 3 --log 0;;FAIL +diff --git a/extensions/libxt_owner.t b/extensions/libxt_owner.t +new file mode 100644 +index 0000000000000..aec30b655e9a5 +--- /dev/null ++++ b/extensions/libxt_owner.t +@@ -0,0 +1,12 @@ ++:OUTPUT,POSTROUTING ++*mangle ++-m owner --uid-owner root;-m owner --uid-owner 0;OK ++-m owner --uid-owner 0-10;=;OK ++-m owner --gid-owner root;-m owner --gid-owner 0;OK ++-m owner --gid-owner 0-10;=;OK ++-m owner --uid-owner root --gid-owner root;-m owner --uid-owner 0 --gid-owner 0;OK ++-m owner --uid-owner 0-10 --gid-owner 0-10;=;OK ++-m owner ! --uid-owner root;-m owner ! --uid-owner 0;OK ++-m owner --socket-exists;=;OK ++:INPUT ++-m owner --uid-owner root;;FAIL +diff --git a/extensions/libxt_physdev.t b/extensions/libxt_physdev.t +new file mode 100644 +index 0000000000000..1fab7e1920d25 +--- /dev/null ++++ b/extensions/libxt_physdev.t +@@ -0,0 +1,14 @@ ++:INPUT,FORWARD ++-m physdev --physdev-in lo;=;OK ++-m physdev --physdev-is-in --physdev-in lo;=;OK ++:OUTPUT,FORWARD ++# xt_physdev: using --physdev-out in the OUTPUT, FORWARD and POSTROUTING chains for non-bridged traffic is not supported anymore. ++# ERROR: should fail: iptables -A FORWARD -m physdev --physdev-out lo ++#-m physdev --physdev-out lo;;FAIL ++# ERROR: cannot load: iptables -A OUTPUT -m physdev --physdev-is-out --physdev-out lo ++#-m physdev --physdev-is-out --physdev-out lo;=;OK ++:FORWARD ++-m physdev --physdev-in lo --physdev-is-bridged;=;OK ++:POSTROUTING ++*mangle ++-m physdev --physdev-out lo --physdev-is-bridged;=;OK +diff --git a/extensions/libxt_pkttype.t b/extensions/libxt_pkttype.t +new file mode 100644 +index 0000000000000..d93baeaf24ec3 +--- /dev/null ++++ b/extensions/libxt_pkttype.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m pkttype --pkt-type unicast;=;OK ++-m pkttype --pkt-type broadcast;=;OK ++-m pkttype --pkt-type multicast;=;OK ++-m pkttype --pkt-type wrong;;FAIL ++-m pkttype;;FAIL +diff --git a/extensions/libxt_policy.t b/extensions/libxt_policy.t +new file mode 100644 +index 0000000000000..6524122bcf793 +--- /dev/null ++++ b/extensions/libxt_policy.t +@@ -0,0 +1,8 @@ ++:INPUT,FORWARD ++-m policy --dir in --pol ipsec;=;OK ++-m policy --dir in --pol ipsec --proto ipcomp;=;OK ++-m policy --dir in --pol ipsec --strict;;FAIL ++-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto ipcomp;=;OK ++-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --mode tunnel --tunnel-dst 10.0.0.0/8 --tunnel-src 10.0.0.0/8 --next --reqid 2;=;OK ++-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --tunnel-dst 10.0.0.0/8;;FAIL ++-m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto ipcomp --mode tunnel --tunnel-dst 10.0.0.0/8 --tunnel-src 10.0.0.0/8 --next --reqid 2;=;OK +diff --git a/extensions/libxt_quota.t b/extensions/libxt_quota.t +new file mode 100644 +index 0000000000000..c568427974f84 +--- /dev/null ++++ b/extensions/libxt_quota.t +@@ -0,0 +1,7 @@ ++:INPUT,FORWARD,OUTPUT ++-m quota --quota 0;=;OK ++-m quota ! --quota 0;=;OK ++-m quota --quota 18446744073709551615;=;OK ++-m quota ! --quota 18446744073709551615;=;OK ++-m quota --quota 18446744073709551616;;FAIL ++-m quota;;FAIL +diff --git a/extensions/libxt_rateest.t b/extensions/libxt_rateest.t +new file mode 100644 +index 0000000000000..c5158614f46a3 +--- /dev/null ++++ b/extensions/libxt_rateest.t +@@ -0,0 +1,16 @@ ++:INPUT,FORWARD,OUTPUT ++%iptables -I INPUT -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms ++-m rateest --rateest RE1 --rateest-lt --rateest-bps 8bit;=;OK ++-m rateest --rateest RE1 --rateest-eq --rateest-pps 5;=;OK ++-m rateest --rateest RE1 --rateest-gt --rateest-bps 5kbit;-m rateest --rateest RE1 --rateest-gt --rateest-bps 5000bit;OK ++-m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-lt --rateest-bps2 16bit;=;OK ++%iptables -I INPUT -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms ++-m rateest --rateest1 RE1 --rateest-lt --rateest-bps --rateest2 RE2;=;OK ++-m rateest --rateest-delta --rateest1 RE1 --rateest-pps1 0 --rateest-lt --rateest-pps2 42 --rateest2 RE2;=;OK ++-m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-eq --rateest-bps2 16bit;=;OK ++-m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-gt --rateest-bps2 16bit;=;OK ++-m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-lt --rateest-pps2 9;=;OK ++-m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-eq --rateest-pps2 9;=;OK ++-m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-gt --rateest-pps2 9;=;OK ++%iptables -D INPUT -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms ++%iptables -D INPUT -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms +diff --git a/extensions/libxt_recent.t b/extensions/libxt_recent.t +new file mode 100644 +index 0000000000000..9a83918ea5835 +--- /dev/null ++++ b/extensions/libxt_recent.t +@@ -0,0 +1,11 @@ ++:INPUT,FORWARD,OUTPUT ++-m recent --set;=;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 --set --rttl;;FAIL ++-m recent --rcheck --hitcount 999 --name foo --mask 255.255.255.255 --rsource;;FAIL ++# nonsensical, but all should load successfully: ++-m recent --rcheck --hitcount 3 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource;=;OK ++-m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 4 --name foo --mask 255.255.255.255 --rsource;=;OK ++-m recent --rcheck --hitcount 8 --name foo --mask 255.255.255.255 --rsource -m recent --rcheck --hitcount 12 --name foo --mask 255.255.255.255 --rsource;=;OK +diff --git a/extensions/libxt_rpfilter.t b/extensions/libxt_rpfilter.t +new file mode 100644 +index 0000000000000..390268f35bce0 +--- /dev/null ++++ b/extensions/libxt_rpfilter.t +@@ -0,0 +1,4 @@ ++:PREROUTING ++*mangle ++-m rpfilter;=;OK ++-m rpfilter --loose --validmark --accept-local --invert;=;OK +diff --git a/extensions/libxt_sctp.t b/extensions/libxt_sctp.t +new file mode 100644 +index 0000000000000..4016e4fb1880e +--- /dev/null ++++ b/extensions/libxt_sctp.t +@@ -0,0 +1,29 @@ ++:INPUT,FORWARD,OUTPUT ++-p sctp -m sctp --sport 1;=;OK ++-p sctp -m sctp --sport 65535;=;OK ++-p sctp -m sctp --sport 1:65535;=;OK ++-p sctp -m sctp --sport -1;;FAIL ++-p sctp -m sctp --sport 65536;;FAIL ++-p sctp -m sctp --dport 1;=;OK ++-p sctp -m sctp --dport 1:65535;=;OK ++-p sctp -m sctp --dport 65535;=;OK ++-p sctp -m sctp --dport -1;;FAIL ++-p sctp -m sctp --dport 65536;;FAIL ++-p sctp -m sctp --chunk-types all DATA;=;OK ++-p sctp -m sctp --chunk-types all INIT;=;OK ++-p sctp -m sctp --chunk-types all INIT_ACK;=;OK ++-p sctp -m sctp --chunk-types all SACK;=;OK ++-p sctp -m sctp --chunk-types all HEARTBEAT;=;OK ++-p sctp -m sctp --chunk-types all HEARTBEAT_ACK;=;OK ++-p sctp -m sctp --chunk-types all ABORT;=;OK ++-p sctp -m sctp --chunk-types all SHUTDOWN;=;OK ++-p sctp -m sctp --chunk-types all SHUTDOWN_ACK;=;OK ++-p sctp -m sctp --chunk-types all ERROR;=;OK ++-p sctp -m sctp --chunk-types all COOKIE_ECHO;=;OK ++-p sctp -m sctp --chunk-types all COOKIE_ACK;=;OK ++-p sctp -m sctp --chunk-types all ECN_ECNE;=;OK ++-p sctp -m sctp --chunk-types all ECN_CWR;=;OK ++-p sctp -m sctp --chunk-types all ASCONF;=;OK ++-p sctp -m sctp --chunk-types all ASCONF_ACK;=;OK ++-p sctp -m sctp --chunk-types all FORWARD_TSN;=;OK ++-p sctp -m sctp --chunk-types all SHUTDOWN_COMPLETE;=;OK +diff --git a/extensions/libxt_set.t b/extensions/libxt_set.t +new file mode 100644 +index 0000000000000..dd9e9f175b5f8 +--- /dev/null ++++ b/extensions/libxt_set.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-m set --match-set foo;;FAIL ++# fails: foo does not exist ++-m set --match-set foo src,dst;;FAIL +diff --git a/extensions/libxt_socket.t b/extensions/libxt_socket.t +new file mode 100644 +index 0000000000000..fe4eb3e4ba2d2 +--- /dev/null ++++ b/extensions/libxt_socket.t +@@ -0,0 +1,8 @@ ++:PREROUTING,INPUT ++*mangle ++-m socket;=;OK ++-m socket --transparent --nowildcard;=;OK ++-m socket --transparent --nowildcard --restore-skmark;=;OK ++-m socket --transparent --restore-skmark;=;OK ++-m socket --nowildcard --restore-skmark;=;OK ++-m socket --restore-skmark;=;OK +diff --git a/extensions/libxt_standard.t b/extensions/libxt_standard.t +new file mode 100644 +index 0000000000000..4313f7b7bac9d +--- /dev/null ++++ b/extensions/libxt_standard.t +@@ -0,0 +1,11 @@ ++:INPUT,FORWARD,OUTPUT ++-s 127.0.0.1/32 -d 0.0.0.0/8 -j DROP;=;OK ++! -s 0.0.0.0 -j ACCEPT;! -s 0.0.0.0/32 -j ACCEPT;OK ++! -d 0.0.0.0/32 -j ACCEPT;=;OK ++-s 0.0.0.0/24 -j RETURN;=;OK ++-p tcp -j ACCEPT;=;OK ++! -p udp -j ACCEPT;=;OK ++-j DROP;=;OK ++-j ACCEPT;=;OK ++-j RETURN;=;OK ++! -p 0 -j ACCEPT;=;FAIL +diff --git a/extensions/libxt_state.t b/extensions/libxt_state.t +new file mode 100644 +index 0000000000000..8e4bce3f96e34 +--- /dev/null ++++ b/extensions/libxt_state.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m state --state INVALID;=;OK ++-m state --state NEW,RELATED;=;OK ++-m state --state UNTRACKED;=;OK ++-m state wrong;;FAIL ++-m state;;FAIL +diff --git a/extensions/libxt_statistic.t b/extensions/libxt_statistic.t +new file mode 100644 +index 0000000000000..bb6673dae5e4a +--- /dev/null ++++ b/extensions/libxt_statistic.t +@@ -0,0 +1,8 @@ ++:INPUT,FORWARD,OUTPUT ++-m statistic;;FAIL ++-m statistic --mode random ! --probability 0.50000000000;=;OK ++-m statistic --mode random ! --probability 1.1;;FAIL ++-m statistic --probability 1;;FAIL ++-m statistic --mode nth ! --every 5 --packet 2;=;OK ++-m statistic --mode nth ! --every 5;;FAIL ++-m statistic --mode nth ! --every 5 --packet 5;;FAIL +diff --git a/extensions/libxt_string.t b/extensions/libxt_string.t +new file mode 100644 +index 0000000000000..d68f099d966c6 +--- /dev/null ++++ b/extensions/libxt_string.t +@@ -0,0 +1,18 @@ ++:INPUT,FORWARD,OUTPUT ++# ERROR: cannot find: iptables -I INPUT -m string --algo bm --string "test" ++# -m string --algo bm --string "test";=;OK ++# ERROR: cannot find: iptables -I INPUT -m string --algo kmp --string "test") ++# -m string --algo kmp --string "test";=;OK ++# ERROR: cannot find: iptables -I INPUT -m string --algo kmp ! --string "test" ++# -m string --algo kmp ! --string "test";=;OK ++# cannot find: iptables -I INPUT -m string --algo bm --string "xxxxxxxxxxx" ....] ++# -m string --algo bm --string "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";=;OK ++# ERROR: cannot load: iptables -A INPUT -m string --algo bm --string "xxxx" ++# -m string --algo bm --string "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";=;OK ++# ERROR: cannot load: iptables -A INPUT -m string --algo bm --hexstring "|0a0a0a0a|" ++# -m string --algo bm --hexstring "|0a0a0a0a|";=;OK ++# ERROR: cannot find: iptables -I INPUT -m string --algo bm --from 0 --to 65535 --string "test" ++# -m string --algo bm --from 0 --to 65535 --string "test";=;OK ++-m string --algo wrong;;FAIL ++-m string --algo bm;;FAIL ++-m string;;FAIL +diff --git a/extensions/libxt_tcp.t b/extensions/libxt_tcp.t +new file mode 100644 +index 0000000000000..b0e8006e51869 +--- /dev/null ++++ b/extensions/libxt_tcp.t +@@ -0,0 +1,26 @@ ++:INPUT,FORWARD,OUTPUT ++-p tcp -m tcp --sport 1;=;OK ++-p tcp -m tcp --sport 65535;=;OK ++-p tcp -m tcp --dport 1;=;OK ++-p tcp -m tcp --dport 65535;=;OK ++-p tcp -m tcp --sport 1:1023;=;OK ++-p tcp -m tcp --sport 1024:65535;=;OK ++-p tcp -m tcp --sport 1024:;-p tcp -m tcp --sport 1024:65535;OK ++-p tcp -m tcp ! --sport 1;=;OK ++-p tcp -m tcp ! --sport 65535;=;OK ++-p tcp -m tcp ! --dport 1;=;OK ++-p tcp -m tcp ! --dport 65535;=;OK ++-p tcp -m tcp --sport 1 --dport 65535;=;OK ++-p tcp -m tcp --sport 65535 --dport 1;=;OK ++-p tcp -m tcp ! --sport 1 --dport 65535;=;OK ++-p tcp -m tcp ! --sport 65535 --dport 1;=;OK ++-p tcp -m tcp --sport 65536;;FAIL ++-p tcp -m tcp --sport -1;;FAIL ++-p tcp -m tcp --dport -1;;FAIL ++-p tcp -m tcp --syn;-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN;OK ++-p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN;=;OK ++-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG SYN;=;OK ++-p tcp -m tcp ! --tcp-flags FIN,SYN,RST,PSH,ACK,URG SYN;=;OK ++-p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG RST;=;OK ++# should we accept this below? ++-p tcp -m tcp;=;OK +diff --git a/extensions/libxt_tcpmss.t b/extensions/libxt_tcpmss.t +new file mode 100644 +index 0000000000000..2b415957ffd00 +--- /dev/null ++++ b/extensions/libxt_tcpmss.t +@@ -0,0 +1,6 @@ ++:INPUT,FORWARD,OUTPUT ++-m tcpmss --mss 42;;FAIL ++-p tcp -m tcpmss --mss 42;=;OK ++-p tcp -m tcpmss --mss 42:12345;=;OK ++-p tcp -m tcpmss --mss 42:65536;;FAIL ++-p tcp -m tcpmss --mss 65535:1000;;FAIL +diff --git a/extensions/libxt_time.t b/extensions/libxt_time.t +new file mode 100644 +index 0000000000000..673af09b21fe2 +--- /dev/null ++++ b/extensions/libxt_time.t +@@ -0,0 +1,4 @@ ++:INPUT,FORWARD,OUTPUT ++-m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --kerneltz;=;OK ++-m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05;=;OK ++-m time --timestart 02:00:00 --timestop 03:00:00 --datestart 1970-01-01T02:00:00 --datestop 1970-01-01T03:00:00;=;OK +diff --git a/extensions/libxt_tos.t b/extensions/libxt_tos.t +new file mode 100644 +index 0000000000000..ccbe80099bdd9 +--- /dev/null ++++ b/extensions/libxt_tos.t +@@ -0,0 +1,13 @@ ++:INPUT,FORWARD,OUTPUT ++-m tos --tos Minimize-Delay;-m tos --tos 0x10/0x3f;OK ++-m tos --tos Maximize-Throughput;-m tos --tos 0x08/0x3f;OK ++-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 0x0f/0x0f;=;OK ++-m tos --tos wrong;;FAIL ++-m tos;;FAIL +diff --git a/extensions/libxt_u32.t b/extensions/libxt_u32.t +new file mode 100644 +index 0000000000000..0d9be47a10e84 +--- /dev/null ++++ b/extensions/libxt_u32.t +@@ -0,0 +1,2 @@ ++:INPUT,FORWARD,OUTPUT ++-m u32 --u32 "0x0=0x0&&0x0=0x1";=;OK +diff --git a/extensions/libxt_udp.t b/extensions/libxt_udp.t +new file mode 100644 +index 0000000000000..1b4d3dd625759 +--- /dev/null ++++ b/extensions/libxt_udp.t +@@ -0,0 +1,22 @@ ++:INPUT,OUTPUT,FORWARD ++-p udp -m udp --sport 1;=;OK ++-p udp -m udp --sport 65535;=;OK ++-p udp -m udp --dport 1;=;OK ++-p udp -m udp --dport 65535;=;OK ++-p udp -m udp --sport 1:1023;=;OK ++-p udp -m udp --sport 1024:65535;=;OK ++-p udp -m udp --sport 1024:;-p udp -m udp --sport 1024:65535;OK ++-p udp -m udp ! --sport 1;=;OK ++-p udp -m udp ! --sport 65535;=;OK ++-p udp -m udp ! --dport 1;=;OK ++-p udp -m udp ! --dport 65535;=;OK ++-p udp -m udp --sport 1 --dport 65535;=;OK ++-p udp -m udp --sport 65535 --dport 1;=;OK ++-p udp -m udp ! --sport 1 --dport 65535;=;OK ++-p udp -m udp ! --sport 65535 --dport 1;=;OK ++# ERRROR: should fail: iptables -A INPUT -p udp -m udp --sport 65536 ++# -p udp -m udp --sport 65536;;FAIL ++-p udp -m udp --sport -1;;FAIL ++-p udp -m udp --dport -1;;FAIL ++# should we accept this below? ++-p udp -m udp;=;OK +diff --git a/iptables-test.py b/iptables-test.py +new file mode 100755 +index 0000000000000..532dee7c9000f +--- /dev/null ++++ b/iptables-test.py +@@ -0,0 +1,373 @@ ++#!/usr/bin/python ++# ++# (C) 2012-2013 by Pablo Neira Ayuso ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This software has been sponsored by Sophos Astaro ++# ++ ++import sys ++import os ++import subprocess ++import argparse ++ ++IPTABLES = "iptables" ++IP6TABLES = "ip6tables" ++ARPTABLES = "arptables" ++EBTABLES = "ebtables" ++ ++IPTABLES_SAVE = "iptables-save" ++IP6TABLES_SAVE = "ip6tables-save" ++ARPTABLES_SAVE = "arptables-save" ++EBTABLES_SAVE = "ebtables-save" ++#IPTABLES_SAVE = ['xtables-save','-4'] ++#IP6TABLES_SAVE = ['xtables-save','-6'] ++ ++EXTENSIONS_PATH = "extensions" ++LOGFILE="/tmp/iptables-test.log" ++log_file = None ++ ++ ++class Colors: ++ HEADER = '\033[95m' ++ BLUE = '\033[94m' ++ GREEN = '\033[92m' ++ YELLOW = '\033[93m' ++ RED = '\033[91m' ++ ENDC = '\033[0m' ++ ++ ++def print_error(reason, filename=None, lineno=None): ++ ''' ++ Prints an error with nice colors, indicating file and line number. ++ ''' ++ print (filename + ": " + Colors.RED + "ERROR" + ++ Colors.ENDC + ": line %d (%s)" % (lineno, reason)) ++ ++ ++def delete_rule(iptables, rule, filename, lineno): ++ ''' ++ Removes an iptables rule ++ ''' ++ cmd = iptables + " -D " + rule ++ ret = execute_cmd(cmd, filename, lineno) ++ if ret == 1: ++ reason = "cannot delete: " + iptables + " -I " + rule ++ print_error(reason, filename, lineno) ++ return -1 ++ ++ return 0 ++ ++ ++def run_test(iptables, rule, rule_save, res, filename, lineno, netns): ++ ''' ++ Executes an unit test. Returns the output of delete_rule(). ++ ++ Parameters: ++ :param iptables: string with the iptables command to execute ++ :param rule: string with iptables arguments for the rule to test ++ :param rule_save: string to find the rule in the output of iptables -save ++ :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) ++ ''' ++ ret = 0 ++ ++ cmd = iptables + " -A " + rule ++ if netns: ++ cmd = "ip netns exec ____iptables-container-test " + EXECUTEABLE + " " + cmd ++ ++ ret = execute_cmd(cmd, filename, lineno) ++ ++ # ++ # report failed test ++ # ++ if ret: ++ if res == "OK": ++ reason = "cannot load: " + cmd ++ print_error(reason, filename, lineno) ++ return -1 ++ else: ++ # do not report this error ++ return 0 ++ else: ++ if res == "FAIL": ++ reason = "should fail: " + cmd ++ print_error(reason, filename, lineno) ++ delete_rule(iptables, rule, filename, lineno) ++ return -1 ++ ++ matching = 0 ++ splitted = iptables.split(" ") ++ if len(splitted) == 2: ++ if splitted[1] == '-4': ++ command = IPTABLES_SAVE ++ elif splitted[1] == '-6': ++ command = IP6TABLES_SAVE ++ elif len(splitted) == 1: ++ if splitted[0] == IPTABLES: ++ command = IPTABLES_SAVE ++ elif splitted[0] == IP6TABLES: ++ command = IP6TABLES_SAVE ++ elif splitted[0] == ARPTABLES: ++ command = ARPTABLES_SAVE ++ elif splitted[0] == EBTABLES: ++ command = EBTABLES_SAVE ++ ++ path = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE ++ command = path + " " + command ++ ++ if netns: ++ command = "ip netns exec ____iptables-container-test " + command ++ ++ args = splitted[1:] ++ proc = subprocess.Popen(command, shell=True, ++ stdin=subprocess.PIPE, ++ stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++ out, err = proc.communicate() ++ ++ # ++ # check for segfaults ++ # ++ if proc.returncode == -11: ++ reason = "iptables-save segfaults: " + cmd ++ print_error(reason, filename, lineno) ++ delete_rule(iptables, rule, filename, lineno) ++ return -1 ++ ++ # find the rule ++ matching = out.find(rule_save) ++ if matching < 0: ++ reason = "cannot find: " + iptables + " -I " + rule ++ print_error(reason, filename, lineno) ++ delete_rule(iptables, rule, filename, lineno) ++ return -1 ++ ++ # Test "ip netns del NETNS" path with rules in place ++ if netns: ++ return 0 ++ ++ return delete_rule(iptables, rule, filename, lineno) ++ ++def execute_cmd(cmd, filename, lineno): ++ ''' ++ Executes a command, checking for segfaults and returning the command exit ++ code. ++ ++ :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) ++ ''' ++ global log_file ++ if cmd.startswith('iptables ') or cmd.startswith('ip6tables ') or cmd.startswith('ebtables ') or cmd.startswith('arptables '): ++ cmd = os.path.abspath(os.path.curdir) + "/iptables/" + EXECUTEABLE + " " + cmd ++ ++ print >> log_file, "command: %s" % cmd ++ ret = subprocess.call(cmd, shell=True, universal_newlines=True, ++ stderr=subprocess.STDOUT, stdout=log_file) ++ log_file.flush() ++ ++ # generic check for segfaults ++ if ret == -11: ++ reason = "command segfaults: " + cmd ++ print_error(reason, filename, lineno) ++ return ret ++ ++ ++def run_test_file(filename, netns): ++ ''' ++ Runs a test file ++ ++ :param filename: name of the file with the test rules ++ ''' ++ # ++ # if this is not a test file, skip. ++ # ++ if not filename.endswith(".t"): ++ return 0, 0 ++ ++ if "libipt_" in filename: ++ iptables = IPTABLES ++ elif "libip6t_" in filename: ++ iptables = IP6TABLES ++ elif "libxt_" in filename: ++ iptables = IPTABLES ++ elif "libarpt_" in filename: ++ # only supported with nf_tables backend ++ if EXECUTEABLE != "xtables-nft-multi": ++ return 0, 0 ++ iptables = ARPTABLES ++ elif "libebt_" in filename: ++ # only supported with nf_tables backend ++ if EXECUTEABLE != "xtables-nft-multi": ++ return 0, 0 ++ iptables = EBTABLES ++ else: ++ # default to iptables if not known prefix ++ iptables = IPTABLES ++ ++ f = open(filename) ++ ++ tests = 0 ++ passed = 0 ++ table = "" ++ total_test_passed = True ++ ++ if netns: ++ execute_cmd("ip netns add ____iptables-container-test", filename, 0) ++ ++ for lineno, line in enumerate(f): ++ if line[0] == "#": ++ continue ++ ++ if line[0] == ":": ++ 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_cmd = line.rstrip()[1:] ++ if netns: ++ external_cmd = "ip netns exec ____iptables-container-test " + EXECUTEABLE + " " + external_cmd ++ execute_cmd(external_cmd, filename, lineno) ++ continue ++ ++ if line[0] == "*": ++ table = line.rstrip()[1:] ++ continue ++ ++ if len(chain_array) == 0: ++ print "broken test, missing chain, leaving" ++ sys.exit() ++ ++ test_passed = True ++ tests += 1 ++ ++ for chain in chain_array: ++ item = line.split(";") ++ if table == "": ++ rule = chain + " " + item[0] ++ else: ++ rule = chain + " -t " + table + " " + item[0] ++ ++ if item[1] == "=": ++ rule_save = chain + " " + item[0] ++ else: ++ rule_save = chain + " " + item[1] ++ ++ res = item[2].rstrip() ++ ret = run_test(iptables, rule, rule_save, ++ res, filename, lineno + 1, netns) ++ ++ if ret < 0: ++ test_passed = False ++ total_test_passed = False ++ break ++ ++ if test_passed: ++ passed += 1 ++ ++ if netns: ++ execute_cmd("ip netns del ____iptables-container-test", filename, 0) ++ if total_test_passed: ++ print filename + ": " + Colors.GREEN + "OK" + Colors.ENDC ++ ++ f.close() ++ return tests, passed ++ ++ ++def show_missing(): ++ ''' ++ Show the list of missing test files ++ ''' ++ file_list = os.listdir(EXTENSIONS_PATH) ++ testfiles = [i for i in file_list if i.endswith('.t')] ++ libfiles = [i for i in file_list ++ if i.startswith('lib') and i.endswith('.c')] ++ ++ def test_name(x): ++ return x[0:-2] + '.t' ++ missing = [test_name(i) for i in libfiles ++ if not test_name(i) in testfiles] ++ ++ print '\n'.join(missing) ++ ++ ++# ++# main ++# ++def main(): ++ parser = argparse.ArgumentParser(description='Run iptables tests') ++ parser.add_argument('filename', nargs='?', ++ metavar='path/to/file.t', ++ help='Run only this test') ++ parser.add_argument('-l', '--legacy', action='store_true', ++ help='Test iptables-legacy') ++ parser.add_argument('-m', '--missing', action='store_true', ++ 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', ++ help='Test netnamespace path') ++ args = parser.parse_args() ++ ++ # ++ # show list of missing test files ++ # ++ if args.missing: ++ show_missing() ++ return ++ ++ global EXECUTEABLE ++ EXECUTEABLE = "xtables-legacy-multi" ++ if args.nftables: ++ EXECUTEABLE = "xtables-nft-multi" ++ ++ if os.getuid() != 0: ++ print "You need to be root to run this, sorry" ++ return ++ ++ os.putenv("XTABLES_LIBDIR", os.path.abspath(EXTENSIONS_PATH)) ++ 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 ++ return ++ ++ file_list = [os.path.join(EXTENSIONS_PATH, i) ++ for i in os.listdir(EXTENSIONS_PATH)] ++ if args.filename: ++ file_list = [args.filename] ++ 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)) ++ ++ ++if __name__ == '__main__': ++ main() +-- +2.21.0 + diff --git a/SOURCES/0002-iptables-apply-Use-mktemp-instead-of-tempfile.patch b/SOURCES/0002-iptables-apply-Use-mktemp-instead-of-tempfile.patch new file mode 100644 index 0000000..640bffc --- /dev/null +++ b/SOURCES/0002-iptables-apply-Use-mktemp-instead-of-tempfile.patch @@ -0,0 +1,35 @@ +From 7fe7c604d819d0b827f2abce253280b38a374cf1 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 17 Sep 2018 11:39:50 +0200 +Subject: [PATCH] iptables-apply: Use mktemp instead of tempfile + +Signed-off-by: Phil Sutter +--- + iptables/iptables-apply | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/iptables/iptables-apply b/iptables/iptables-apply +index 819ca4a459c42..a685b6bbcd7dc 100755 +--- a/iptables/iptables-apply ++++ b/iptables/iptables-apply +@@ -111,7 +111,7 @@ if [[ ! -r "$FILE" ]]; then + exit 2 + fi + +-COMMANDS=(tempfile "$SAVE" "$RESTORE") ++COMMANDS=(mktemp "$SAVE" "$RESTORE") + + for cmd in "${COMMANDS[@]}"; do + if ! command -v $cmd >/dev/null; then +@@ -122,7 +122,7 @@ done + + umask 0700 + +-TMPFILE=$(tempfile -p iptap) ++TMPFILE=$(mktemp) + trap "rm -f $TMPFILE" EXIT HUP INT QUIT ILL TRAP ABRT BUS \ + FPE USR1 SEGV USR2 PIPE ALRM TERM + +-- +2.21.0 + diff --git a/SOURCES/0003-extensions-format-security-fixes-in-libip-6-t_icmp.patch b/SOURCES/0003-extensions-format-security-fixes-in-libip-6-t_icmp.patch new file mode 100644 index 0000000..cfefe78 --- /dev/null +++ b/SOURCES/0003-extensions-format-security-fixes-in-libip-6-t_icmp.patch @@ -0,0 +1,61 @@ +From 7e63dd95957a264d15eefdda3ea9449a6c72eb86 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Adam=20Go=C5=82=C4=99biowski?= +Date: Wed, 14 Nov 2018 07:35:28 +0100 +Subject: [PATCH] extensions: format-security fixes in libip[6]t_icmp +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 61d6c3834de3 ("xtables: add 'printf' attribute to xlate_add") +introduced support for gcc feature to check format string against passed +argument. This commit adds missing bits to extenstions's libipt_icmp.c +and libip6t_icmp6.c that were causing build to fail. + +Fixes: 61d6c3834de3 ("xtables: add 'printf' attribute to xlate_add") +Signed-off-by: Adam Gołębiowski +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 907e429d7548157016cd51aba4adc5d0c7d9f816) +Signed-off-by: Phil Sutter +--- + extensions/libip6t_icmp6.c | 4 ++-- + extensions/libipt_icmp.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c +index 45a71875722c4..cc7bfaeb72fd7 100644 +--- a/extensions/libip6t_icmp6.c ++++ b/extensions/libip6t_icmp6.c +@@ -230,7 +230,7 @@ static unsigned int type_xlate_print(struct xt_xlate *xl, unsigned int icmptype, + type_name = icmp6_type_xlate(icmptype); + + if (type_name) { +- xt_xlate_add(xl, type_name); ++ xt_xlate_add(xl, "%s", type_name); + } else { + for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i) + if (icmpv6_codes[i].type == icmptype && +@@ -239,7 +239,7 @@ static unsigned int type_xlate_print(struct xt_xlate *xl, unsigned int icmptype, + break; + + if (i != ARRAY_SIZE(icmpv6_codes)) +- xt_xlate_add(xl, icmpv6_codes[i].name); ++ xt_xlate_add(xl, "%s", icmpv6_codes[i].name); + else + return 0; + } +diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c +index 5418997668d4c..e76257c54708c 100644 +--- a/extensions/libipt_icmp.c ++++ b/extensions/libipt_icmp.c +@@ -236,7 +236,7 @@ static unsigned int type_xlate_print(struct xt_xlate *xl, unsigned int icmptype, + if (icmp_codes[i].type == icmptype && + icmp_codes[i].code_min == code_min && + icmp_codes[i].code_max == code_max) { +- xt_xlate_add(xl, icmp_codes[i].name); ++ xt_xlate_add(xl, "%s", icmp_codes[i].name); + return 1; + } + } +-- +2.21.0 + diff --git a/SOURCES/0004-arptables-nft-use-generic-expression-parsing-functio.patch b/SOURCES/0004-arptables-nft-use-generic-expression-parsing-functio.patch new file mode 100644 index 0000000..e48e653 --- /dev/null +++ b/SOURCES/0004-arptables-nft-use-generic-expression-parsing-functio.patch @@ -0,0 +1,190 @@ +From abf79e364e9ef2dc355eb52d07d160b1f6c0f8c4 Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Sun, 18 Nov 2018 12:31:33 +0100 +Subject: [PATCH] arptables-nft: use generic expression parsing function + +since commit d9c6a5d0977a6d8bbe772dbc31a2c4f58eec1708 +("xtables: merge {ip,arp}tables_command_state structs") arptables +uses the shared representation. + +With only minor changes (e.g., use generic counters in command_state), +in print/save functions we can use the shared nftnl expression parser +too. + +arptables-legacy prints (-L) the jump target first, i.e.: +-j MARK -d 0.0.0.0/8 --h-length 6 ... + +... so keep that here too. + +Signed-off-by: Florian Westphal +(cherry picked from commit aa5d3c5b16e94036ac0dc6d44194db7b009ced53) +Signed-off-by: Phil Sutter +--- + extensions/libarpt_standard.t | 4 +- + iptables/nft-arp.c | 92 ++++------------------------------- + 2 files changed, 12 insertions(+), 84 deletions(-) + +diff --git a/extensions/libarpt_standard.t b/extensions/libarpt_standard.t +index bef682afec374..195865929c8d3 100644 +--- a/extensions/libarpt_standard.t ++++ b/extensions/libarpt_standard.t +@@ -5,8 +5,8 @@ + -d 192.168.0.1;=;OK + ! -d 0.0.0.0;=;OK + -d 0.0.0.0/24;=;OK +--i lo;=;OK +-! -i lo;=;OK ++-i lo -j DROP;-i lo --h-length 6 --h-type 1 -j DROP;OK ++! -i lo -j ACCEPT;! -i lo --h-length 6 --h-type 1 -j ACCEPT;OK + -i ppp+;=;OK + ! -i ppp+;=;OK + -i lo --destination-mac 11:22:33:44:55:66;-i lo --dst-mac 11:22:33:44:55:66;OK +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index 1a98996f94bda..37850bd328b71 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -412,56 +412,6 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx, + } + } + +-static void nft_arp_rule_to_cs(const struct nftnl_rule *r, +- struct iptables_command_state *cs) +-{ +- struct nftnl_expr_iter *iter; +- struct nftnl_expr *expr; +- int family = nftnl_rule_get_u32(r, NFTNL_RULE_FAMILY); +- struct nft_xt_ctx ctx = { +- .cs = cs, +- .family = family, +- }; +- +- iter = nftnl_expr_iter_create(r); +- if (iter == NULL) +- return; +- +- ctx.iter = iter; +- expr = nftnl_expr_iter_next(iter); +- while (expr != NULL) { +- const char *name = +- nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); +- +- if (strcmp(name, "counter") == 0) +- nft_parse_counter(expr, &ctx.cs->arp.counters); +- else if (strcmp(name, "payload") == 0) +- nft_parse_payload(&ctx, expr); +- else if (strcmp(name, "meta") == 0) +- nft_parse_meta(&ctx, expr); +- else if (strcmp(name, "bitwise") == 0) +- nft_parse_bitwise(&ctx, expr); +- else if (strcmp(name, "cmp") == 0) +- nft_parse_cmp(&ctx, expr); +- else if (strcmp(name, "immediate") == 0) +- nft_parse_immediate(&ctx, expr); +- else if (strcmp(name, "target") == 0) +- nft_parse_target(&ctx, expr); +- +- expr = nftnl_expr_iter_next(iter); +- } +- +- nftnl_expr_iter_destroy(iter); +- +- if (cs->jumpto != NULL) +- return; +- +- if (cs->target != NULL && cs->target->name != NULL) +- cs->target = xtables_find_target(cs->target->name, XTF_TRY_LOAD); +- else +- cs->jumpto = ""; +-} +- + static void nft_arp_print_header(unsigned int format, const char *chain, + const char *pol, + const struct xt_counters *counters, +@@ -627,14 +577,6 @@ after_devdst: + } + } + +-static void nft_arp_save_counters(const void *data) +-{ +- const struct iptables_command_state *cs = data; +- +- printf("[%llu:%llu] ", (unsigned long long)cs->arp.counters.pcnt, +- (unsigned long long)cs->arp.counters.bcnt); +-} +- + static void + nft_arp_save_rule(const void *data, unsigned int format) + { +@@ -643,17 +585,7 @@ nft_arp_save_rule(const void *data, unsigned int format) + format |= FMT_NUMERIC; + + nft_arp_print_rule_details(&cs->arp, format); +- +- if (cs->jumpto != NULL && strcmp(cs->jumpto, "") != 0) { +- printf("-j %s", cs->jumpto); +- } else if (cs->target) { +- printf("-j %s", cs->target->name); +- if (cs->target->save != NULL) +- cs->target->save(&cs->arp, cs->target->t); +- } +- +- if (!(format & FMT_NONEWLINE)) +- fputc('\n', stdout); ++ save_matches_and_target(cs, false, &cs->arp, format); + } + + static void +@@ -664,22 +596,18 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) + if (format & FMT_LINENUMBERS) + printf("%u ", num); + +- nft_arp_rule_to_cs(r, &cs); ++ nft_rule_to_iptables_command_state(r, &cs); + ++ if (cs.jumpto) ++ printf("-j %s ", cs.jumpto); + nft_arp_print_rule_details(&cs.arp, format); +- +- if (cs.jumpto != NULL && strcmp(cs.jumpto, "") != 0) { +- printf("-j %s", cs.jumpto); +- } else if (cs.target) { +- printf("-j %s", cs.target->name); +- cs.target->print(&cs.arp, cs.target->t, format & FMT_NUMERIC); +- } ++ print_matches_and_target(&cs, format); + + if (!(format & FMT_NOCOUNTS)) { + printf(", pcnt="); +- xtables_print_num(cs.arp.counters.pcnt, format); ++ xtables_print_num(cs.counters.pcnt, format); + printf("-- bcnt="); +- xtables_print_num(cs.arp.counters.bcnt, format); ++ xtables_print_num(cs.counters.bcnt, format); + } + + if (!(format & FMT_NONEWLINE)) +@@ -720,7 +648,7 @@ static bool nft_arp_rule_find(struct nft_family_ops *ops, struct nftnl_rule *r, + struct iptables_command_state this = {}; + + /* Delete by matching rule case */ +- nft_arp_rule_to_cs(r, &this); ++ nft_rule_to_iptables_command_state(r, &this); + + if (!nft_arp_is_same(&cs->arp, &this.arp)) + return false; +@@ -751,10 +679,10 @@ struct nft_family_ops nft_family_ops_arp = { + .print_header = nft_arp_print_header, + .print_rule = nft_arp_print_rule, + .save_rule = nft_arp_save_rule, +- .save_counters = nft_arp_save_counters, ++ .save_counters = save_counters, + .save_chain = nft_arp_save_chain, + .post_parse = NULL, +- .rule_to_cs = nft_arp_rule_to_cs, ++ .rule_to_cs = nft_rule_to_iptables_command_state, + .clear_cs = nft_clear_iptables_command_state, + .rule_find = nft_arp_rule_find, + .parse_target = nft_ipv46_parse_target, +-- +2.21.0 + diff --git a/SOURCES/0005-xtables-Don-t-use-native-nftables-comments.patch b/SOURCES/0005-xtables-Don-t-use-native-nftables-comments.patch new file mode 100644 index 0000000..e990de2 --- /dev/null +++ b/SOURCES/0005-xtables-Don-t-use-native-nftables-comments.patch @@ -0,0 +1,143 @@ +From b7556207b12decbe4e79bf218ec5bff073a04ad2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 27 Nov 2018 20:07:11 +0100 +Subject: [PATCH] xtables: Don't use native nftables comments + +The problem with converting libxt_comment into nftables comment is that +rules change when parsing from kernel due to comment match being moved +to the end of the match list. And since match ordering matters, the rule +may not be found anymore when checking or deleting. Apart from that, +iptables-nft didn't support multiple comments per rule anymore. This is +a compatibility issue without technical reason. + +Leave conversion from nftables comment to libxt_comment in place so we +don't break running systems during an update. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit ccf154d7420c07b6e6febc1c3b8b31d2bd1adbe6) +Signed-off-by: Phil Sutter +--- + extensions/libxt_comment.t | 2 ++ + iptables/nft-ipv4.c | 14 +++----------- + iptables/nft-ipv6.c | 14 +++----------- + iptables/nft.c | 27 --------------------------- + iptables/nft.h | 1 - + 5 files changed, 8 insertions(+), 50 deletions(-) + +diff --git a/extensions/libxt_comment.t b/extensions/libxt_comment.t +index f12cd66841e7f..f0c8fb999401b 100644 +--- a/extensions/libxt_comment.t ++++ b/extensions/libxt_comment.t +@@ -1,6 +1,8 @@ + :INPUT,FORWARD,OUTPUT + -m comment;;FAIL + -m comment --comment;;FAIL ++-p tcp -m tcp --dport 22 -m comment --comment foo;=;OK ++-p tcp -m comment --comment foo -m tcp --dport 22;=;OK + # + # it fails with 256 characters + # +diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c +index ffb439b4a1128..4497eb9b9347c 100644 +--- a/iptables/nft-ipv4.c ++++ b/iptables/nft-ipv4.c +@@ -77,17 +77,9 @@ static int nft_ipv4_add(struct nftnl_rule *r, void *data) + add_compat(r, cs->fw.ip.proto, cs->fw.ip.invflags & XT_INV_PROTO); + + for (matchp = cs->matches; matchp; matchp = matchp->next) { +- /* Use nft built-in comments support instead of comment match */ +- if (strcmp(matchp->match->name, "comment") == 0) { +- ret = add_comment(r, (char *)matchp->match->m->data); +- if (ret < 0) +- goto try_match; +- } else { +-try_match: +- ret = add_match(r, matchp->match->m); +- if (ret < 0) +- return ret; +- } ++ ret = add_match(r, matchp->match->m); ++ if (ret < 0) ++ return ret; + } + + /* Counters need to me added before the target, otherwise they are +diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c +index 7bacee4ab3a21..cacb1c9e141f2 100644 +--- a/iptables/nft-ipv6.c ++++ b/iptables/nft-ipv6.c +@@ -66,17 +66,9 @@ static int nft_ipv6_add(struct nftnl_rule *r, void *data) + add_compat(r, cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags & XT_INV_PROTO); + + for (matchp = cs->matches; matchp; matchp = matchp->next) { +- /* Use nft built-in comments support instead of comment match */ +- if (strcmp(matchp->match->name, "comment") == 0) { +- ret = add_comment(r, (char *)matchp->match->m->data); +- if (ret < 0) +- goto try_match; +- } else { +-try_match: +- ret = add_match(r, matchp->match->m); +- if (ret < 0) +- return ret; +- } ++ ret = add_match(r, matchp->match->m); ++ if (ret < 0) ++ return ret; + } + + /* Counters need to me added before the target, otherwise they are +diff --git a/iptables/nft.c b/iptables/nft.c +index e8538d38e0109..6863d851e44c2 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1107,33 +1107,6 @@ enum udata_type { + }; + #define UDATA_TYPE_MAX (__UDATA_TYPE_MAX - 1) + +-int add_comment(struct nftnl_rule *r, const char *comment) +-{ +- struct nftnl_udata_buf *udata; +- uint32_t len; +- +- if (nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len)) +- return -EALREADY; +- +- udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN); +- if (!udata) +- return -ENOMEM; +- +- if (strnlen(comment, 255) == 255) +- return -ENOSPC; +- +- if (!nftnl_udata_put_strz(udata, UDATA_TYPE_COMMENT, comment)) +- return -ENOMEM; +- +- nftnl_rule_set_data(r, NFTNL_RULE_USERDATA, +- nftnl_udata_buf_data(udata), +- nftnl_udata_buf_len(udata)); +- +- nftnl_udata_buf_free(udata); +- +- return 0; +-} +- + static int parse_udata_cb(const struct nftnl_udata *attr, void *data) + { + unsigned char *value = nftnl_udata_get(attr); +diff --git a/iptables/nft.h b/iptables/nft.h +index 9b4ba5f9a63eb..052105fc6f3cd 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -116,7 +116,6 @@ int add_match(struct nftnl_rule *r, struct xt_entry_match *m); + int add_target(struct nftnl_rule *r, struct xt_entry_target *t); + int add_jumpto(struct nftnl_rule *r, const char *name, int verdict); + int add_action(struct nftnl_rule *r, struct iptables_command_state *cs, bool goto_set); +-int add_comment(struct nftnl_rule *r, const char *comment); + char *get_comment(const void *data, uint32_t data_len); + + enum nft_rule_print { +-- +2.21.0 + diff --git a/SOURCES/0006-xtables-Introduce-per-table-chain-caches.patch b/SOURCES/0006-xtables-Introduce-per-table-chain-caches.patch new file mode 100644 index 0000000..96b32c3 --- /dev/null +++ b/SOURCES/0006-xtables-Introduce-per-table-chain-caches.patch @@ -0,0 +1,592 @@ +From a09e8ae2a1e2ff589af839ad3460493fc04306d7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 15 Nov 2018 14:53:02 +0100 +Subject: [PATCH] xtables: Introduce per table chain caches + +Being able to omit the previously obligatory table name check when +iterating over the chain cache might help restore performance with large +rulesets in xtables-save and -restore. + +There is one subtle quirk in the code: flush_chain_cache() did free the +global chain cache if not called with a table name but didn't if a table +name was given even if it emptied the chain cache. In other places, +chain_cache being non-NULL prevented a cache update from happening, so +this patch establishes the same behaviour (for each individual chain +cache) since otherwise unexpected cache updates lead to weird problems. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit c58ecf9f8bcb7619a27ef8ffaddf847a562475a5) +Signed-off-by: Phil Sutter +--- + iptables/nft-shared.h | 3 +- + iptables/nft.c | 160 +++++++++++++++++-------------------- + iptables/nft.h | 10 ++- + iptables/xtables-restore.c | 16 ++-- + iptables/xtables-save.c | 12 +-- + 5 files changed, 95 insertions(+), 106 deletions(-) + +diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h +index e3ecdb4d23df3..9a61d8d2863e3 100644 +--- a/iptables/nft-shared.h ++++ b/iptables/nft-shared.h +@@ -251,7 +251,8 @@ struct nftnl_chain_list; + + struct nft_xt_restore_cb { + void (*table_new)(struct nft_handle *h, const char *table); +- struct nftnl_chain_list *(*chain_list)(struct nft_handle *h); ++ struct nftnl_chain_list *(*chain_list)(struct nft_handle *h, ++ const char *table); + void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable, + const char *chain); + int (*chain_user_flush)(struct nft_handle *h, +diff --git a/iptables/nft.c b/iptables/nft.c +index 6863d851e44c2..36529048a0ca6 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -673,15 +673,17 @@ nft_chain_builtin_find(struct builtin_table *t, const char *chain) + static void nft_chain_builtin_init(struct nft_handle *h, + struct builtin_table *table) + { +- struct nftnl_chain_list *list = nft_chain_list_get(h); ++ struct nftnl_chain_list *list = nft_chain_list_get(h, table->name); + struct nftnl_chain *c; + int i; + ++ if (!list) ++ return; ++ + /* Initialize built-in chains if they don't exist yet */ + for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) { + +- c = nft_chain_list_find(list, table->name, +- table->chains[i].name); ++ c = nft_chain_list_find(list, table->chains[i].name); + if (c != NULL) + continue; + +@@ -782,27 +784,33 @@ static void flush_rule_cache(struct nft_handle *h, const char *tablename) + + static int __flush_chain_cache(struct nftnl_chain *c, void *data) + { +- const char *tablename = data; +- +- if (!strcmp(nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), tablename)) { +- nftnl_chain_list_del(c); +- nftnl_chain_free(c); +- } ++ nftnl_chain_list_del(c); ++ nftnl_chain_free(c); + + return 0; + } + + static void flush_chain_cache(struct nft_handle *h, const char *tablename) + { +- if (!h->chain_cache) +- return; ++ int i; + +- if (tablename) { +- nftnl_chain_list_foreach(h->chain_cache, __flush_chain_cache, +- (void *)tablename); +- } else { +- nftnl_chain_list_free(h->chain_cache); +- h->chain_cache = NULL; ++ for (i = 0; i < NFT_TABLE_MAX; i++) { ++ if (h->tables[i].name == NULL) ++ continue; ++ ++ if (tablename && strcmp(h->tables[i].name, tablename)) ++ continue; ++ ++ if (h->tables[i].chain_cache) { ++ if (tablename) { ++ nftnl_chain_list_foreach(h->tables[i].chain_cache, ++ __flush_chain_cache, NULL); ++ break; ++ } else { ++ nftnl_chain_list_free(h->tables[i].chain_cache); ++ h->tables[i].chain_cache = NULL; ++ } ++ } + } + } + +@@ -1244,8 +1252,9 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type, + + static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data) + { ++ struct nft_handle *h = data; ++ struct builtin_table *t; + struct nftnl_chain *c; +- struct nftnl_chain_list *list = data; + + c = nftnl_chain_alloc(); + if (c == NULL) +@@ -1254,7 +1263,18 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data) + if (nftnl_chain_nlmsg_parse(nlh, c) < 0) + goto out; + +- nftnl_chain_list_add_tail(c, list); ++ t = nft_table_builtin_find(h, ++ nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE)); ++ if (!t) ++ goto out; ++ ++ if (!t->chain_cache) { ++ t->chain_cache = nftnl_chain_list_alloc(); ++ if (!t->chain_cache) ++ goto out; ++ } ++ ++ nftnl_chain_list_add_tail(c, t->chain_cache); + + return MNL_CB_OK; + out: +@@ -1263,35 +1283,34 @@ err: + return MNL_CB_OK; + } + +-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h) ++struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, ++ const char *table) + { + char buf[16536]; + struct nlmsghdr *nlh; +- struct nftnl_chain_list *list; ++ struct builtin_table *t; + int ret; + +- if (h->chain_cache) +- return h->chain_cache; +-retry: +- list = nftnl_chain_list_alloc(); +- if (list == NULL) { +- errno = ENOMEM; ++ t = nft_table_builtin_find(h, table); ++ if (!t) + return NULL; +- } + ++ if (t->chain_cache) ++ return t->chain_cache; ++retry: + nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, + NLM_F_DUMP, h->seq); + +- ret = mnl_talk(h, nlh, nftnl_chain_list_cb, list); ++ ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h); + if (ret < 0 && errno == EINTR) { + assert(nft_restart(h) >= 0); +- nftnl_chain_list_free(list); + goto retry; + } + +- h->chain_cache = list; ++ if (!t->chain_cache) ++ t->chain_cache = nftnl_chain_list_alloc(); + +- return list; ++ return t->chain_cache; + } + + static const char *policy_name[NF_ACCEPT+1] = { +@@ -1299,8 +1318,7 @@ static const char *policy_name[NF_ACCEPT+1] = { + [NF_ACCEPT] = "ACCEPT", + }; + +-int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, +- const char *table) ++int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) + { + struct nftnl_chain_list_iter *iter; + struct nft_family_ops *ops; +@@ -1314,13 +1332,8 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *chain_table = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *policy = NULL; + +- if (strcmp(table, chain_table) != 0) +- goto next; +- + if (nft_chain_builtin(c)) { + uint32_t pol = NF_ACCEPT; + +@@ -1331,7 +1344,7 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, + + if (ops->save_chain) + ops->save_chain(c, policy); +-next: ++ + c = nftnl_chain_list_iter_next(iter); + } + +@@ -1502,7 +1515,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + + nft_fn = nft_rule_flush; + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, table); + if (list == NULL) { + ret = 1; + goto err; +@@ -1516,21 +1529,16 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *table_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + +- if (strcmp(table, table_name) != 0) +- goto next; +- + if (chain != NULL && strcmp(chain, chain_name) != 0) + goto next; + + if (verbose) + fprintf(stdout, "Flushing chain `%s'\n", chain_name); + +- __nft_rule_flush(h, table_name, chain_name); ++ __nft_rule_flush(h, table, chain_name); + + if (chain != NULL) + break; +@@ -1546,6 +1554,7 @@ err: + + int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table) + { ++ struct nftnl_chain_list *list; + struct nftnl_chain *c; + int ret; + +@@ -1564,9 +1573,9 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl + + ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); + +- nft_chain_list_get(h); +- +- nftnl_chain_list_add(c, h->chain_cache); ++ list = nft_chain_list_get(h, table); ++ if (list) ++ nftnl_chain_list_add(c, list); + + /* the core expects 1 for success and 0 for error */ + return ret == 0 ? 1 : 0; +@@ -1588,7 +1597,7 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, + + nft_fn = nft_chain_user_del; + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, table); + if (list == NULL) + goto err; + +@@ -1598,8 +1607,6 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *table_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + +@@ -1607,9 +1614,6 @@ int nft_chain_user_del(struct nft_handle *h, const char *chain, + if (nft_chain_builtin(c)) + goto next; + +- if (strcmp(table, table_name) != 0) +- goto next; +- + if (chain != NULL && strcmp(chain, chain_name) != 0) + goto next; + +@@ -1644,8 +1648,7 @@ err: + } + + struct nftnl_chain * +-nft_chain_list_find(struct nftnl_chain_list *list, +- const char *table, const char *chain) ++nft_chain_list_find(struct nftnl_chain_list *list, const char *chain) + { + struct nftnl_chain_list_iter *iter; + struct nftnl_chain *c; +@@ -1656,14 +1659,9 @@ nft_chain_list_find(struct nftnl_chain_list *list, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *table_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + +- if (strcmp(table, table_name) != 0) +- goto next; +- + if (strcmp(chain, chain_name) != 0) + goto next; + +@@ -1681,11 +1679,11 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain) + { + struct nftnl_chain_list *list; + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, table); + if (list == NULL) + return NULL; + +- return nft_chain_list_find(list, table, chain); ++ return nft_chain_list_find(list, chain); + } + + bool nft_chain_exists(struct nft_handle *h, +@@ -2297,7 +2295,9 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + return 1; + } + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, table); ++ if (!list) ++ goto err; /* XXX: return 0 instead? */ + + iter = nftnl_chain_list_iter_create(list); + if (iter == NULL) +@@ -2308,8 +2308,6 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *chain_table = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + uint32_t policy = +@@ -2326,8 +2324,6 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM)) + basechain = true; + +- if (strcmp(table, chain_table) != 0) +- goto next; + if (chain) { + if (strcmp(chain, chain_name) != 0) + goto next; +@@ -2442,7 +2438,9 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + return 0; + } + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, table); ++ if (!list) ++ goto err; /* XXX: correct? */ + + /* Dump policies and custom chains first */ + if (!rulenum) +@@ -2460,13 +2458,9 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *chain_table = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + +- if (strcmp(table, chain_table) != 0) +- goto next; + if (chain && strcmp(chain, chain_name) != 0) + goto next; + +@@ -3045,7 +3039,7 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, + struct nftnl_chain *c; + int ret = 0; + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, table); + if (list == NULL) + goto err; + +@@ -3057,11 +3051,6 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, + while (c != NULL) { + const char *chain_name = + nftnl_chain_get(c, NFTNL_CHAIN_NAME); +- const char *chain_table = +- nftnl_chain_get(c, NFTNL_CHAIN_TABLE); +- +- if (strcmp(table, chain_table) != 0) +- goto next; + + if (chain != NULL && strcmp(chain, chain_name) != 0) + goto next; +@@ -3202,7 +3191,7 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename + struct nftnl_chain *chain; + int ret = 0; + +- list = nft_chain_list_get(h); ++ list = nft_chain_list_get(h, tablename); + if (list == NULL) + return -1; + +@@ -3212,12 +3201,7 @@ static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename + + chain = nftnl_chain_list_iter_next(iter); + while (chain != NULL) { +- const char *chain_table; +- +- chain_table = nftnl_chain_get_str(chain, NFTNL_CHAIN_TABLE); +- +- if (strcmp(chain_table, tablename) || +- !nft_chain_builtin(chain)) ++ if (!nft_chain_builtin(chain)) + goto next; + + ret = nft_is_chain_compatible(h, chain); +diff --git a/iptables/nft.h b/iptables/nft.h +index 052105fc6f3cd..6229221bd51f7 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -25,6 +25,7 @@ struct builtin_table { + const char *name; + struct builtin_chain chains[NF_INET_NUMHOOKS]; + bool initialized; ++ struct nftnl_chain_list *chain_cache; + }; + + struct nft_handle { +@@ -38,7 +39,6 @@ struct nft_handle { + struct list_head err_list; + struct nft_family_ops *ops; + struct builtin_table *tables; +- struct nftnl_chain_list *chain_cache; + struct nftnl_rule_list *rule_cache; + bool restore; + int8_t config_done; +@@ -78,9 +78,11 @@ struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *t + struct nftnl_chain; + + int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters); +-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h); +-struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, const char *table, const char *chain); +-int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, const char *table); ++struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, ++ const char *table); ++struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, ++ const char *chain); ++int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list); + int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); + int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); + int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list, +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index f529774054215..a46a92955a01a 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -56,11 +56,12 @@ static void print_usage(const char *name, const char *version) + " [ --ipv6 ]\n", name); + } + +-static struct nftnl_chain_list *get_chain_list(struct nft_handle *h) ++static struct nftnl_chain_list *get_chain_list(struct nft_handle *h, ++ const char *table) + { + struct nftnl_chain_list *chain_list; + +- chain_list = nft_chain_list_get(h); ++ chain_list = nft_chain_list_get(h, table); + if (chain_list == NULL) + xtables_error(OTHER_PROBLEM, "cannot retrieve chain list\n"); + +@@ -72,7 +73,7 @@ static void chain_delete(struct nftnl_chain_list *clist, const char *curtable, + { + struct nftnl_chain *chain_obj; + +- chain_obj = nft_chain_list_find(clist, curtable, chain); ++ chain_obj = nft_chain_list_find(clist, chain); + /* This chain has been found, delete from list. Later + * on, unvisited chains will be purged out. + */ +@@ -112,9 +113,6 @@ void xtables_restore_parse(struct nft_handle *h, + + line = 0; + +- if (cb->chain_list) +- chain_list = cb->chain_list(h); +- + /* Grab standard input. */ + while (fgets(buffer, sizeof(buffer), p->in)) { + int ret = 0; +@@ -165,6 +163,9 @@ void xtables_restore_parse(struct nft_handle *h, + if (p->tablename && (strcmp(p->tablename, table) != 0)) + continue; + ++ if (cb->chain_list) ++ chain_list = cb->chain_list(h, table); ++ + if (noflush == 0) { + DEBUGP("Cleaning all chains of table '%s'\n", + table); +@@ -197,8 +198,7 @@ void xtables_restore_parse(struct nft_handle *h, + if (cb->chain_del) + cb->chain_del(chain_list, curtable->name, + chain); +- } else if (nft_chain_list_find(chain_list, +- curtable->name, chain)) { ++ } else if (nft_chain_list_find(chain_list, chain)) { + chain_exists = true; + /* Apparently -n still flushes existing user + * defined chains that are redefined. Otherwise, +diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c +index bed3ee0318995..d121d50e180ff 100644 +--- a/iptables/xtables-save.c ++++ b/iptables/xtables-save.c +@@ -73,7 +73,9 @@ __do_output(struct nft_handle *h, const char *tablename, bool counters) + return 0; + } + +- chain_list = nft_chain_list_get(h); ++ chain_list = nft_chain_list_get(h, tablename); ++ if (!chain_list) ++ return 0; + + time_t now = time(NULL); + +@@ -83,7 +85,7 @@ __do_output(struct nft_handle *h, const char *tablename, bool counters) + + /* Dump out chain names first, + * thereby preventing dependency conflicts */ +- nft_chain_save(h, chain_list, tablename); ++ nft_chain_save(h, chain_list); + nft_rule_save(h, tablename, counters ? 0 : FMT_NOCOUNTS); + + now = time(NULL); +@@ -257,7 +259,7 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters + return 0; + } + +- chain_list = nft_chain_list_get(h); ++ chain_list = nft_chain_list_get(h, tablename); + + if (first) { + now = time(NULL); +@@ -272,7 +274,7 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters + + /* Dump out chain names first, + * thereby preventing dependency conflicts */ +- nft_chain_save(h, chain_list, tablename); ++ nft_chain_save(h, chain_list); + nft_rule_save(h, tablename, format); + printf("\n"); + return 0; +@@ -399,7 +401,7 @@ int xtables_arp_save_main(int argc, char **argv) + } + + printf("*filter\n"); +- nft_chain_save(&h, nft_chain_list_get(&h), "filter"); ++ nft_chain_save(&h, nft_chain_list_get(&h, "filter")); + nft_rule_save(&h, "filter", show_counters ? 0 : FMT_NOCOUNTS); + printf("\n"); + nft_fini(&h); +-- +2.21.0 + diff --git a/SOURCES/0007-nft-add-type-field-to-builtin_table.patch b/SOURCES/0007-nft-add-type-field-to-builtin_table.patch new file mode 100644 index 0000000..da765c3 --- /dev/null +++ b/SOURCES/0007-nft-add-type-field-to-builtin_table.patch @@ -0,0 +1,99 @@ +From 312897725486bf4a3014076f3659cc1d8ce294ce Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Sat, 17 Nov 2018 18:10:15 +0100 +Subject: [PATCH] nft: add type field to builtin_table + +Use enum nft_table_type to set the new type field in the structure that +define tables. + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 9847abe6fbb91621f6494df8243ff96f04efdc4a) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 8 ++++++++ + iptables/nft.h | 1 + + 2 files changed, 9 insertions(+) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 36529048a0ca6..f0a60e1f568af 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -379,6 +379,7 @@ static int batch_rule_add(struct nft_handle *h, enum obj_update_type type, + struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + [NFT_TABLE_RAW] = { + .name = "raw", ++ .type = NFT_TABLE_RAW, + .chains = { + { + .name = "PREROUTING", +@@ -396,6 +397,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + }, + [NFT_TABLE_MANGLE] = { + .name = "mangle", ++ .type = NFT_TABLE_MANGLE, + .chains = { + { + .name = "PREROUTING", +@@ -431,6 +433,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + }, + [NFT_TABLE_FILTER] = { + .name = "filter", ++ .type = NFT_TABLE_FILTER, + .chains = { + { + .name = "INPUT", +@@ -454,6 +457,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + }, + [NFT_TABLE_SECURITY] = { + .name = "security", ++ .type = NFT_TABLE_SECURITY, + .chains = { + { + .name = "INPUT", +@@ -477,6 +481,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + }, + [NFT_TABLE_NAT] = { + .name = "nat", ++ .type = NFT_TABLE_NAT, + .chains = { + { + .name = "PREROUTING", +@@ -511,6 +516,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + struct builtin_table xtables_arp[NFT_TABLE_MAX] = { + [NFT_TABLE_FILTER] = { + .name = "filter", ++ .type = NFT_TABLE_FILTER, + .chains = { + { + .name = "INPUT", +@@ -533,6 +539,7 @@ struct builtin_table xtables_arp[NFT_TABLE_MAX] = { + struct builtin_table xtables_bridge[NFT_TABLE_MAX] = { + [NFT_TABLE_FILTER] = { + .name = "filter", ++ .type = NFT_TABLE_FILTER, + .chains = { + { + .name = "INPUT", +@@ -556,6 +563,7 @@ struct builtin_table xtables_bridge[NFT_TABLE_MAX] = { + }, + [NFT_TABLE_NAT] = { + .name = "nat", ++ .type = NFT_TABLE_NAT, + .chains = { + { + .name = "PREROUTING", +diff --git a/iptables/nft.h b/iptables/nft.h +index 6229221bd51f7..85c894e80e02e 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -23,6 +23,7 @@ struct builtin_chain { + + struct builtin_table { + const char *name; ++ enum nft_table_type type; + struct builtin_chain chains[NF_INET_NUMHOOKS]; + bool initialized; + struct nftnl_chain_list *chain_cache; +-- +2.21.0 + diff --git a/SOURCES/0008-nft-move-chain_cache-back-to-struct-nft_handle.patch b/SOURCES/0008-nft-move-chain_cache-back-to-struct-nft_handle.patch new file mode 100644 index 0000000..75f8802 --- /dev/null +++ b/SOURCES/0008-nft-move-chain_cache-back-to-struct-nft_handle.patch @@ -0,0 +1,106 @@ +From 48455efdfbee0df02c724a594cf8af8c440ded7d Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Sat, 17 Nov 2018 18:16:45 +0100 +Subject: [PATCH] nft: move chain_cache back to struct nft_handle + +Place this back into the structure that stores the state information. + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 1847d9db753825b0bd1cd450b549f4e39f7bcc31) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 26 +++++++++++++------------- + iptables/nft.h | 4 +++- + 2 files changed, 16 insertions(+), 14 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index f0a60e1f568af..fdb4ead55a873 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -809,14 +809,14 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename) + if (tablename && strcmp(h->tables[i].name, tablename)) + continue; + +- if (h->tables[i].chain_cache) { ++ if (h->table[i].chain_cache) { + if (tablename) { +- nftnl_chain_list_foreach(h->tables[i].chain_cache, ++ nftnl_chain_list_foreach(h->table[i].chain_cache, + __flush_chain_cache, NULL); + break; + } else { +- nftnl_chain_list_free(h->tables[i].chain_cache); +- h->tables[i].chain_cache = NULL; ++ nftnl_chain_list_free(h->table[i].chain_cache); ++ h->table[i].chain_cache = NULL; + } + } + } +@@ -1276,13 +1276,13 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data) + if (!t) + goto out; + +- if (!t->chain_cache) { +- t->chain_cache = nftnl_chain_list_alloc(); +- if (!t->chain_cache) ++ if (!h->table[t->type].chain_cache) { ++ h->table[t->type].chain_cache = nftnl_chain_list_alloc(); ++ if (!h->table[t->type].chain_cache) + goto out; + } + +- nftnl_chain_list_add_tail(c, t->chain_cache); ++ nftnl_chain_list_add_tail(c, h->table[t->type].chain_cache); + + return MNL_CB_OK; + out: +@@ -1303,8 +1303,8 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + if (!t) + return NULL; + +- if (t->chain_cache) +- return t->chain_cache; ++ if (h->table[t->type].chain_cache) ++ return h->table[t->type].chain_cache; + retry: + nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, + NLM_F_DUMP, h->seq); +@@ -1315,10 +1315,10 @@ retry: + goto retry; + } + +- if (!t->chain_cache) +- t->chain_cache = nftnl_chain_list_alloc(); ++ if (!h->table[t->type].chain_cache) ++ h->table[t->type].chain_cache = nftnl_chain_list_alloc(); + +- return t->chain_cache; ++ return h->table[t->type].chain_cache; + } + + static const char *policy_name[NF_ACCEPT+1] = { +diff --git a/iptables/nft.h b/iptables/nft.h +index 85c894e80e02e..1c028206221c4 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -26,7 +26,6 @@ struct builtin_table { + enum nft_table_type type; + struct builtin_chain chains[NF_INET_NUMHOOKS]; + bool initialized; +- struct nftnl_chain_list *chain_cache; + }; + + struct nft_handle { +@@ -40,6 +39,9 @@ struct nft_handle { + struct list_head err_list; + struct nft_family_ops *ops; + struct builtin_table *tables; ++ struct { ++ struct nftnl_chain_list *chain_cache; ++ } table[NFT_TABLE_MAX]; + struct nftnl_rule_list *rule_cache; + bool restore; + int8_t config_done; +-- +2.21.0 + diff --git a/SOURCES/0009-nft-move-initialize-to-struct-nft_handle.patch b/SOURCES/0009-nft-move-initialize-to-struct-nft_handle.patch new file mode 100644 index 0000000..9bacf4d --- /dev/null +++ b/SOURCES/0009-nft-move-initialize-to-struct-nft_handle.patch @@ -0,0 +1,91 @@ +From 6186853420f23e500e0b9a234cc446697cca16a7 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Sat, 17 Nov 2018 18:38:30 +0100 +Subject: [PATCH] nft: move initialize to struct nft_handle + +Move this to the structure that stores, stateful information. Introduce +nft_table_initialized() and use it. + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 5016d1eb84f951d84f5a0c18f994f40677ad0643) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 14 ++++++++++---- + iptables/nft.h | 2 +- + 2 files changed, 11 insertions(+), 5 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index fdb4ead55a873..9b479307a2fbc 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -587,13 +587,19 @@ struct builtin_table xtables_bridge[NFT_TABLE_MAX] = { + }, + }; + ++static bool nft_table_initialized(const struct nft_handle *h, ++ enum nft_table_type type) ++{ ++ return h->table[type].initialized; ++} ++ + static int nft_table_builtin_add(struct nft_handle *h, + struct builtin_table *_t) + { + struct nftnl_table *t; + int ret; + +- if (_t->initialized) ++ if (nft_table_initialized(h, _t->type)) + return 0; + + t = nftnl_table_alloc(); +@@ -707,7 +713,7 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table) + if (t == NULL) + return -1; + +- if (t->initialized) ++ if (nft_table_initialized(h, t->type)) + return 0; + + if (nft_table_builtin_add(h, t) < 0) +@@ -715,7 +721,7 @@ static int nft_xt_builtin_init(struct nft_handle *h, const char *table) + + nft_chain_builtin_init(h, t); + +- t->initialized = true; ++ h->table[t->type].initialized = true; + + return 0; + } +@@ -1875,7 +1881,7 @@ static int __nft_table_flush(struct nft_handle *h, const char *table) + + _t = nft_table_builtin_find(h, table); + assert(_t); +- _t->initialized = false; ++ h->table[_t->type].initialized = false; + + flush_chain_cache(h, table); + flush_rule_cache(h, table); +diff --git a/iptables/nft.h b/iptables/nft.h +index 1c028206221c4..b9ba66b110042 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -25,7 +25,6 @@ struct builtin_table { + const char *name; + enum nft_table_type type; + struct builtin_chain chains[NF_INET_NUMHOOKS]; +- bool initialized; + }; + + struct nft_handle { +@@ -41,6 +40,7 @@ struct nft_handle { + struct builtin_table *tables; + struct { + struct nftnl_chain_list *chain_cache; ++ bool initialized; + } table[NFT_TABLE_MAX]; + struct nftnl_rule_list *rule_cache; + bool restore; +-- +2.21.0 + diff --git a/SOURCES/0010-xtables-constify-struct-builtin_table-and-struct-bui.patch b/SOURCES/0010-xtables-constify-struct-builtin_table-and-struct-bui.patch new file mode 100644 index 0000000..1118c3c --- /dev/null +++ b/SOURCES/0010-xtables-constify-struct-builtin_table-and-struct-bui.patch @@ -0,0 +1,287 @@ +From e73749ba27388068af05e78ed6cb03b1824182c0 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Sat, 17 Nov 2018 18:25:58 +0100 +Subject: [PATCH] xtables: constify struct builtin_table and struct + builtin_chain + +These definitions should be const, propagate this to all existing users. + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 3c7ea26c85b95a4c62355c359030d6bbdf2f8df0) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 42 ++++++++++++++++++------------------ + iptables/nft.h | 14 ++++++------ + iptables/xtables-restore.c | 4 ++-- + iptables/xtables-save.c | 2 +- + iptables/xtables-translate.c | 2 +- + 5 files changed, 32 insertions(+), 32 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 9b479307a2fbc..7b6fb2b10686d 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -376,7 +376,7 @@ static int batch_rule_add(struct nft_handle *h, enum obj_update_type type, + return batch_add(h, type, r); + } + +-struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { ++const struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + [NFT_TABLE_RAW] = { + .name = "raw", + .type = NFT_TABLE_RAW, +@@ -513,7 +513,7 @@ struct builtin_table xtables_ipv4[NFT_TABLE_MAX] = { + + #include + +-struct builtin_table xtables_arp[NFT_TABLE_MAX] = { ++const struct builtin_table xtables_arp[NFT_TABLE_MAX] = { + [NFT_TABLE_FILTER] = { + .name = "filter", + .type = NFT_TABLE_FILTER, +@@ -536,7 +536,7 @@ struct builtin_table xtables_arp[NFT_TABLE_MAX] = { + + #include + +-struct builtin_table xtables_bridge[NFT_TABLE_MAX] = { ++const struct builtin_table xtables_bridge[NFT_TABLE_MAX] = { + [NFT_TABLE_FILTER] = { + .name = "filter", + .type = NFT_TABLE_FILTER, +@@ -594,7 +594,7 @@ static bool nft_table_initialized(const struct nft_handle *h, + } + + static int nft_table_builtin_add(struct nft_handle *h, +- struct builtin_table *_t) ++ const struct builtin_table *_t) + { + struct nftnl_table *t; + int ret; +@@ -614,8 +614,8 @@ static int nft_table_builtin_add(struct nft_handle *h, + } + + static struct nftnl_chain * +-nft_chain_builtin_alloc(struct builtin_table *table, +- struct builtin_chain *chain, int policy) ++nft_chain_builtin_alloc(const struct builtin_table *table, ++ const struct builtin_chain *chain, int policy) + { + struct nftnl_chain *c; + +@@ -634,8 +634,8 @@ nft_chain_builtin_alloc(struct builtin_table *table, + } + + static void nft_chain_builtin_add(struct nft_handle *h, +- struct builtin_table *table, +- struct builtin_chain *chain) ++ const struct builtin_table *table, ++ const struct builtin_chain *chain) + { + struct nftnl_chain *c; + +@@ -647,7 +647,7 @@ static void nft_chain_builtin_add(struct nft_handle *h, + } + + /* find if built-in table already exists */ +-struct builtin_table * ++const struct builtin_table * + nft_table_builtin_find(struct nft_handle *h, const char *table) + { + int i; +@@ -668,8 +668,8 @@ nft_table_builtin_find(struct nft_handle *h, const char *table) + } + + /* find if built-in chain already exists */ +-struct builtin_chain * +-nft_chain_builtin_find(struct builtin_table *t, const char *chain) ++const struct builtin_chain * ++nft_chain_builtin_find(const struct builtin_table *t, const char *chain) + { + int i; + bool found = false; +@@ -685,7 +685,7 @@ nft_chain_builtin_find(struct builtin_table *t, const char *chain) + } + + static void nft_chain_builtin_init(struct nft_handle *h, +- struct builtin_table *table) ++ const struct builtin_table *table) + { + struct nftnl_chain_list *list = nft_chain_list_get(h, table->name); + struct nftnl_chain *c; +@@ -707,7 +707,7 @@ static void nft_chain_builtin_init(struct nft_handle *h, + + static int nft_xt_builtin_init(struct nft_handle *h, const char *table) + { +- struct builtin_table *t; ++ const struct builtin_table *t; + + t = nft_table_builtin_find(h, table); + if (t == NULL) +@@ -750,7 +750,7 @@ static int nft_restart(struct nft_handle *h) + return 0; + } + +-int nft_init(struct nft_handle *h, struct builtin_table *t) ++int nft_init(struct nft_handle *h, const struct builtin_table *t) + { + h->nl = mnl_socket_open(NETLINK_NETFILTER); + if (h->nl == NULL) +@@ -852,8 +852,8 @@ static struct nftnl_chain *nft_chain_new(struct nft_handle *h, + const struct xt_counters *counters) + { + struct nftnl_chain *c; +- struct builtin_table *_t; +- struct builtin_chain *_c; ++ const struct builtin_table *_t; ++ const struct builtin_chain *_c; + + _t = nft_table_builtin_find(h, table); + if (!_t) { +@@ -1267,7 +1267,7 @@ nft_rule_print_save(const struct nftnl_rule *r, enum nft_rule_print type, + static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data) + { + struct nft_handle *h = data; +- struct builtin_table *t; ++ const struct builtin_table *t; + struct nftnl_chain *c; + + c = nftnl_chain_alloc(); +@@ -1302,7 +1302,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + { + char buf[16536]; + struct nlmsghdr *nlh; +- struct builtin_table *t; ++ const struct builtin_table *t; + int ret; + + t = nft_table_builtin_find(h, table); +@@ -1703,7 +1703,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain) + bool nft_chain_exists(struct nft_handle *h, + const char *table, const char *chain) + { +- struct builtin_table *t = nft_table_builtin_find(h, table); ++ const struct builtin_table *t = nft_table_builtin_find(h, table); + + /* xtables does not support custom tables */ + if (!t) +@@ -1868,7 +1868,7 @@ int nft_for_each_table(struct nft_handle *h, + + static int __nft_table_flush(struct nft_handle *h, const char *table) + { +- struct builtin_table *_t; ++ const struct builtin_table *_t; + struct nftnl_table *t; + + t = nftnl_table_alloc(); +@@ -3166,7 +3166,7 @@ static int nft_is_chain_compatible(const struct nft_handle *h, + const struct nftnl_chain *chain) + { + const char *table, *name, *type, *cur_table; +- struct builtin_chain *chains; ++ const struct builtin_chain *chains; + int i, j, prio; + enum nf_inet_hooks hook; + +diff --git a/iptables/nft.h b/iptables/nft.h +index b9ba66b110042..bf60ab3943659 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -37,7 +37,7 @@ struct nft_handle { + struct nftnl_batch *batch; + struct list_head err_list; + struct nft_family_ops *ops; +- struct builtin_table *tables; ++ const struct builtin_table *tables; + struct { + struct nftnl_chain_list *chain_cache; + bool initialized; +@@ -52,14 +52,14 @@ struct nft_handle { + } error; + }; + +-extern struct builtin_table xtables_ipv4[NFT_TABLE_MAX]; +-extern struct builtin_table xtables_arp[NFT_TABLE_MAX]; +-extern struct builtin_table xtables_bridge[NFT_TABLE_MAX]; ++extern const struct builtin_table xtables_ipv4[NFT_TABLE_MAX]; ++extern const struct builtin_table xtables_arp[NFT_TABLE_MAX]; ++extern const struct builtin_table xtables_bridge[NFT_TABLE_MAX]; + + int mnl_talk(struct nft_handle *h, struct nlmsghdr *nlh, + int (*cb)(const struct nlmsghdr *nlh, void *data), + void *data); +-int nft_init(struct nft_handle *h, struct builtin_table *t); ++int nft_init(struct nft_handle *h, const struct builtin_table *t); + void nft_fini(struct nft_handle *h); + + /* +@@ -73,7 +73,7 @@ bool nft_table_find(struct nft_handle *h, const char *tablename); + int nft_table_purge_chains(struct nft_handle *h, const char *table, struct nftnl_chain_list *list); + int nft_table_flush(struct nft_handle *h, const char *table); + void nft_table_new(struct nft_handle *h, const char *table); +-struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table); ++const struct builtin_table *nft_table_builtin_find(struct nft_handle *h, const char *table); + + /* + * Operations with chains. +@@ -92,7 +92,7 @@ int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list, + const char *chain, const char *table); + int nft_chain_user_rename(struct nft_handle *h, const char *chain, const char *table, const char *newname); + int nft_chain_zero_counters(struct nft_handle *h, const char *chain, const char *table, bool verbose); +-struct builtin_chain *nft_chain_builtin_find(struct builtin_table *t, const char *chain); ++const struct builtin_chain *nft_chain_builtin_find(const struct builtin_table *t, const char *chain); + bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain); + + /* +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index a46a92955a01a..642876d6c70ac 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -105,9 +105,9 @@ void xtables_restore_parse(struct nft_handle *h, + struct nft_xt_restore_cb *cb, + int argc, char *argv[]) + { ++ const struct builtin_table *curtable = NULL; + char buffer[10240]; + int in_table = 0; +- struct builtin_table *curtable = NULL; + const struct xtc_ops *ops = &xtc_ops; + struct nftnl_chain_list *chain_list = NULL; + +@@ -359,7 +359,7 @@ void xtables_restore_parse(struct nft_handle *h, + static int + xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + { +- struct builtin_table *tables; ++ const struct builtin_table *tables; + struct nft_handle h = { + .family = family, + .restore = true, +diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c +index d121d50e180ff..414a864b6196b 100644 +--- a/iptables/xtables-save.c ++++ b/iptables/xtables-save.c +@@ -122,7 +122,7 @@ do_output(struct nft_handle *h, const char *tablename, bool counters) + static int + xtables_save_main(int family, const char *progname, int argc, char *argv[]) + { +- struct builtin_table *tables; ++ const struct builtin_table *tables; + const char *tablename = NULL; + bool dump = false; + struct nft_handle h = { +diff --git a/iptables/xtables-translate.c b/iptables/xtables-translate.c +index 849c53f30e155..e1d2a7d6cce88 100644 +--- a/iptables/xtables-translate.c ++++ b/iptables/xtables-translate.c +@@ -426,7 +426,7 @@ static int xtables_xlate_main_common(struct nft_handle *h, + int family, + const char *progname) + { +- struct builtin_table *tables; ++ const struct builtin_table *tables; + int ret; + + xtables_globals.program_name = progname; +-- +2.21.0 + diff --git a/SOURCES/0011-nft-Simplify-nftnl_rule_list_chain_save.patch b/SOURCES/0011-nft-Simplify-nftnl_rule_list_chain_save.patch new file mode 100644 index 0000000..3604d25 --- /dev/null +++ b/SOURCES/0011-nft-Simplify-nftnl_rule_list_chain_save.patch @@ -0,0 +1,60 @@ +From 014b6acbb382f42dd20577fa1ff6e013526a57d5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:02 +0100 +Subject: [PATCH] nft: Simplify nftnl_rule_list_chain_save() + +Since there are per table chain caches, The chain list passed to that +function is comprised of chains belonging to the right table only. +Therefore the table name check can safely be skipped. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 71f9e474d467dd59582d7a3920eded9613b99000) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 7b6fb2b10686d..9d20eb0eac2db 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2381,8 +2381,7 @@ list_save(struct nftnl_rule *r, unsigned int num, unsigned int format) + + static int + nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain, +- const char *table, struct nftnl_chain_list *list, +- int counters) ++ struct nftnl_chain_list *list, int counters) + { + struct nftnl_chain_list_iter *iter; + struct nftnl_chain *c; +@@ -2393,15 +2392,12 @@ nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain, + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *chain_table = +- nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + uint32_t policy = + nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); + +- if (strcmp(table, chain_table) != 0 || +- (chain && strcmp(chain, chain_name) != 0)) ++ if (chain && strcmp(chain, chain_name) != 0) + goto next; + + /* this is a base chain */ +@@ -2458,7 +2454,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + + /* Dump policies and custom chains first */ + if (!rulenum) +- nftnl_rule_list_chain_save(h, chain, table, list, counters); ++ nftnl_rule_list_chain_save(h, chain, list, counters); + + /* Now dump out rules in this table */ + iter = nftnl_chain_list_iter_create(list); +-- +2.21.0 + diff --git a/SOURCES/0012-nft-Review-unclear-return-points.patch b/SOURCES/0012-nft-Review-unclear-return-points.patch new file mode 100644 index 0000000..395f42d --- /dev/null +++ b/SOURCES/0012-nft-Review-unclear-return-points.patch @@ -0,0 +1,43 @@ +From d54baa487a93f54d192de82704e1fba9675fcadc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:03 +0100 +Subject: [PATCH] nft: Review unclear return points + +When converting to per table chain caches, these two error returns were +marked for review but apparently forgotten. Make sure error condition is +propagated when returning at those points. + +Fixes: c58ecf9f8bcb7 ("xtables: Introduce per table chain caches") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 7e09582a57440f13796bdd5bd70466ef0913345b) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 9d20eb0eac2db..1fca1f17147f6 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2311,7 +2311,7 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + + list = nft_chain_list_get(h, table); + if (!list) +- goto err; /* XXX: return 0 instead? */ ++ return 0; + + iter = nftnl_chain_list_iter_create(list); + if (iter == NULL) +@@ -2450,7 +2450,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + + list = nft_chain_list_get(h, table); + if (!list) +- goto err; /* XXX: correct? */ ++ goto err; + + /* Dump policies and custom chains first */ + if (!rulenum) +-- +2.21.0 + diff --git a/SOURCES/0013-xtables-restore-Review-chain-handling.patch b/SOURCES/0013-xtables-restore-Review-chain-handling.patch new file mode 100644 index 0000000..826c3a8 --- /dev/null +++ b/SOURCES/0013-xtables-restore-Review-chain-handling.patch @@ -0,0 +1,172 @@ +From 757b84e866dc1f288c54ad5ca9868b1765da3948 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:04 +0100 +Subject: [PATCH] xtables-restore: Review chain handling + +There is no need to "delete" (actually, remove from cache) a chain if +noflush wasn't given: While handling the corresponding table line, +'table_flush' callback has already taken care of that. + +This .chain_del indirection is not required since d1eb4d587297 +("iptables-compat: chains are purge out already from table flush"). + +Streamlining the code further, move syntax checks to the top. If these +concede, there are three cases to distinguish: + +A) Given chain name matches a builtin one in current table, so assume it + exists already and just set policy and counters. + +B) Noflush was given and the (custom) chain exists already, flush it. + +C) Custom chain was either flushed (noflush not given) or didn't exist + before, create it. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 9523b2e9dee3d9b4439214092c496542ce9f434e) +Signed-off-by: Phil Sutter +--- + iptables/nft-shared.h | 2 -- + iptables/xtables-restore.c | 68 +++++++++++--------------------------- + 2 files changed, 19 insertions(+), 51 deletions(-) + +diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h +index 9a61d8d2863e3..17fff984ba312 100644 +--- a/iptables/nft-shared.h ++++ b/iptables/nft-shared.h +@@ -253,8 +253,6 @@ struct nft_xt_restore_cb { + void (*table_new)(struct nft_handle *h, const char *table); + struct nftnl_chain_list *(*chain_list)(struct nft_handle *h, + const char *table); +- void (*chain_del)(struct nftnl_chain_list *clist, const char *curtable, +- const char *chain); + int (*chain_user_flush)(struct nft_handle *h, + struct nftnl_chain_list *clist, + const char *table, const char *chain); +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index 642876d6c70ac..4e00ed86be06d 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -68,21 +68,6 @@ static struct nftnl_chain_list *get_chain_list(struct nft_handle *h, + return chain_list; + } + +-static void chain_delete(struct nftnl_chain_list *clist, const char *curtable, +- const char *chain) +-{ +- struct nftnl_chain *chain_obj; +- +- chain_obj = nft_chain_list_find(clist, chain); +- /* This chain has been found, delete from list. Later +- * on, unvisited chains will be purged out. +- */ +- if (chain_obj != NULL) { +- nftnl_chain_list_del(chain_obj); +- nftnl_chain_free(chain_obj); +- } +-} +- + struct nft_xt_restore_cb restore_cb = { + .chain_list = get_chain_list, + .commit = nft_commit, +@@ -90,7 +75,6 @@ struct nft_xt_restore_cb restore_cb = { + .table_new = nft_table_new, + .table_flush = nft_table_flush, + .chain_user_flush = nft_chain_user_flush, +- .chain_del = chain_delete, + .do_command = do_commandx, + .chain_set = nft_chain_set, + .chain_user_add = nft_chain_user_add, +@@ -183,7 +167,6 @@ void xtables_restore_parse(struct nft_handle *h, + /* New chain. */ + char *policy, *chain = NULL; + struct xt_counters count = {}; +- bool chain_exists = false; + + chain = strtok(buffer+1, " \t\n"); + DEBUGP("line %u, chain '%s'\n", line, chain); +@@ -194,21 +177,6 @@ void xtables_restore_parse(struct nft_handle *h, + exit(1); + } + +- if (noflush == 0) { +- if (cb->chain_del) +- cb->chain_del(chain_list, curtable->name, +- chain); +- } else if (nft_chain_list_find(chain_list, chain)) { +- chain_exists = true; +- /* Apparently -n still flushes existing user +- * defined chains that are redefined. Otherwise, +- * leave them as is. +- */ +- if (cb->chain_user_flush) +- cb->chain_user_flush(h, chain_list, +- curtable->name, chain); +- } +- + if (strlen(chain) >= XT_EXTENSION_MAXNAMELEN) + xtables_error(PARAMETER_PROBLEM, + "Invalid chain name `%s' " +@@ -246,24 +214,28 @@ void xtables_restore_parse(struct nft_handle *h, + } + DEBUGP("Setting policy of chain %s to %s\n", + chain, policy); +- ret = 1; + +- } else { +- if (!chain_exists && +- cb->chain_user_add && +- cb->chain_user_add(h, chain, +- curtable->name) < 0) { +- if (errno == EEXIST) +- continue; ++ } else if (noflush && ++ nftnl_chain_list_lookup_byname(chain_list, chain)) { ++ /* Apparently -n still flushes existing user ++ * defined chains that are redefined. Otherwise, ++ * leave them as is. ++ */ ++ if (cb->chain_user_flush) ++ cb->chain_user_flush(h, chain_list, ++ curtable->name, chain); ++ } else if (cb->chain_user_add && ++ cb->chain_user_add(h, chain, ++ curtable->name) < 0) { ++ if (errno == EEXIST) ++ continue; + +- xtables_error(PARAMETER_PROBLEM, +- "cannot create chain " +- "'%s' (%s)\n", chain, +- strerror(errno)); +- } +- continue; ++ xtables_error(PARAMETER_PROBLEM, ++ "cannot create chain " ++ "'%s' (%s)\n", chain, ++ strerror(errno)); + } +- ++ ret = 1; + } else if (in_table) { + int a; + char *pcnt = NULL; +@@ -496,7 +468,6 @@ struct nft_xt_restore_cb ebt_restore_cb = { + .table_new = nft_table_new, + .table_flush = nft_table_flush, + .chain_user_flush = nft_chain_user_flush, +- .chain_del = chain_delete, + .do_command = do_commandeb, + .chain_set = nft_chain_set, + .chain_user_add = nft_chain_user_add, +@@ -542,7 +513,6 @@ struct nft_xt_restore_cb arp_restore_cb = { + .table_new = nft_table_new, + .table_flush = nft_table_flush, + .chain_user_flush = nft_chain_user_flush, +- .chain_del = chain_delete, + .do_command = do_commandarp, + .chain_set = nft_chain_set, + .chain_user_add = nft_chain_user_add, +-- +2.21.0 + diff --git a/SOURCES/0014-nft-Review-is_-_compatible-routines.patch b/SOURCES/0014-nft-Review-is_-_compatible-routines.patch new file mode 100644 index 0000000..b35c248 --- /dev/null +++ b/SOURCES/0014-nft-Review-is_-_compatible-routines.patch @@ -0,0 +1,233 @@ +From 109b8f2d637b5e4b1a6ff6994297203834e4e77a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:05 +0100 +Subject: [PATCH] nft: Review is_*_compatible() routines + +- Call to nft_table_builtin_find() in nft_is_table_compatible() is not + needed, as it is repeated in the latter call to nft_chain_list_get() + by nft_are_chains_compatible(). + +- Turn nft_is_chain_compatible(), nft_is_rule_compatible() and + nft_is_expr_compatible() into callbacks for use with respective + foreach functions. + +- nft_are_chains_compatible() is not needed anymore due to foreach + function use. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit e774b15299c271a4c7570899591cf1b7960477ea) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 153 ++++++++++++++++++------------------------------- + 1 file changed, 55 insertions(+), 98 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 1fca1f17147f6..5032c718b33a9 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -3115,7 +3115,7 @@ static const char *supported_exprs[NFT_COMPAT_EXPR_MAX] = { + }; + + +-static int nft_is_expr_compatible(const struct nftnl_expr *expr) ++static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data) + { + const char *name = nftnl_expr_get_str(expr, NFTNL_EXPR_NAME); + int i; +@@ -3130,138 +3130,95 @@ static int nft_is_expr_compatible(const struct nftnl_expr *expr) + nftnl_expr_get_u32(expr, NFTNL_EXPR_LIMIT_FLAGS) == 0) + return 0; + +- return 1; ++ return -1; + } + +-static bool nft_is_rule_compatible(struct nftnl_rule *rule) +-{ +- struct nftnl_expr_iter *iter; +- struct nftnl_expr *expr; +- bool compatible = false; +- +- iter = nftnl_expr_iter_create(rule); +- if (iter == NULL) +- return false; ++struct nft_is_rule_compatible_data { ++ const char *tablename; ++}; + +- expr = nftnl_expr_iter_next(iter); +- while (expr != NULL) { +- if (nft_is_expr_compatible(expr) == 0) { +- expr = nftnl_expr_iter_next(iter); +- continue; +- } ++static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data) ++{ ++ const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE); ++ struct nft_is_rule_compatible_data *d = data; + +- compatible = true; +- break; +- } ++ /* ignore rules belonging to a different table */ ++ if (strcmp(table, d->tablename)) ++ return 0; + +- nftnl_expr_iter_destroy(iter); +- return compatible; ++ return nftnl_expr_foreach(rule, nft_is_expr_compatible, NULL); + } + +-static int nft_is_chain_compatible(const struct nft_handle *h, +- const struct nftnl_chain *chain) ++static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) + { +- const char *table, *name, *type, *cur_table; +- const struct builtin_chain *chains; +- int i, j, prio; ++ const struct builtin_chain *chains = NULL, *chain = NULL; ++ const char *table, *name, *type; ++ struct nft_handle *h = data; + enum nf_inet_hooks hook; ++ int i, prio; + +- table = nftnl_chain_get(chain, NFTNL_CHAIN_TABLE); +- name = nftnl_chain_get(chain, NFTNL_CHAIN_NAME); +- type = nftnl_chain_get(chain, NFTNL_CHAIN_TYPE); +- prio = nftnl_chain_get_u32(chain, NFTNL_CHAIN_PRIO); +- hook = nftnl_chain_get_u32(chain, NFTNL_CHAIN_HOOKNUM); ++ if (!nft_chain_builtin(c)) ++ return 0; + ++ /* find chain's table in builtin tables */ ++ table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); + for (i = 0; i < NFT_TABLE_MAX; i++) { +- cur_table = h->tables[i].name; +- chains = h->tables[i].chains; ++ const char *cur_table = h->tables[i].name; + +- if (!cur_table || strcmp(table, cur_table) != 0) ++ if (!cur_table || strcmp(cur_table, table)) + continue; + +- for (j = 0; j < NF_INET_NUMHOOKS && chains[j].name; j++) { +- if (strcmp(name, chains[j].name) != 0) +- continue; +- +- if (strcmp(type, chains[j].type) == 0 && +- prio == chains[j].prio && +- hook == chains[j].hook) +- return 0; +- break; +- } ++ chains = h->tables[i].chains; ++ break; + } +- +- return 1; +-} +- +-static int nft_are_chains_compatible(struct nft_handle *h, const char *tablename) +-{ +- struct nftnl_chain_list *list; +- struct nftnl_chain_list_iter *iter; +- struct nftnl_chain *chain; +- int ret = 0; +- +- list = nft_chain_list_get(h, tablename); +- if (list == NULL) +- return -1; +- +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) ++ if (!chains) + return -1; + +- chain = nftnl_chain_list_iter_next(iter); +- while (chain != NULL) { +- if (!nft_chain_builtin(chain)) +- goto next; ++ /* find chain in builtin chain list */ ++ name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); ++ for (i = 0; i < NF_INET_NUMHOOKS && chains[i].name; i++) { ++ if (strcmp(name, chains[i].name)) ++ continue; + +- ret = nft_is_chain_compatible(h, chain); +- if (ret != 0) +- break; +-next: +- chain = nftnl_chain_list_iter_next(iter); ++ chain = &chains[i]; ++ break; + } ++ if (!chain) ++ return -1; + +- nftnl_chain_list_iter_destroy(iter); ++ /* compare properties */ ++ type = nftnl_chain_get_str(c, NFTNL_CHAIN_TYPE); ++ prio = nftnl_chain_get_u32(c, NFTNL_CHAIN_PRIO); ++ hook = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM); ++ if (strcmp(type, chain->type) || ++ prio != chain->prio || ++ hook != chain->hook) ++ return -1; + +- return ret; ++ return 0; + } + + bool nft_is_table_compatible(struct nft_handle *h, const char *tablename) + { ++ struct nft_is_rule_compatible_data rcd = { ++ .tablename = tablename ++ }; ++ struct nftnl_chain_list *clist; + struct nftnl_rule_list *list; +- struct nftnl_rule_list_iter *iter; +- struct nftnl_rule *rule; +- int ret = 0; + +- if (!nft_table_builtin_find(h, tablename)) ++ clist = nft_chain_list_get(h, tablename); ++ if (clist == NULL) + return false; + +- ret = nft_are_chains_compatible(h, tablename); +- if (ret != 0) ++ if (nftnl_chain_list_foreach(clist, nft_is_chain_compatible, h)) + return false; + + list = nft_rule_list_get(h); + if (list == NULL) + return true; + +- iter = nftnl_rule_list_iter_create(list); +- if (iter == NULL) +- return true; +- +- rule = nftnl_rule_list_iter_next(iter); +- while (rule != NULL) { +- const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE); +- +- if (strcmp(table, tablename)) +- goto next_rule; +- +- ret = nft_is_rule_compatible(rule); +- if (ret != 0) +- break; +-next_rule: +- rule = nftnl_rule_list_iter_next(iter); +- } ++ if (nftnl_rule_list_foreach(list, nft_is_rule_compatible, &rcd)) ++ return false; + +- nftnl_rule_list_iter_destroy(iter); +- return ret == 0; ++ return true; + } +-- +2.21.0 + diff --git a/SOURCES/0015-nft-Reduce-__nft_rule_del-signature.patch b/SOURCES/0015-nft-Reduce-__nft_rule_del-signature.patch new file mode 100644 index 0000000..b044125 --- /dev/null +++ b/SOURCES/0015-nft-Reduce-__nft_rule_del-signature.patch @@ -0,0 +1,51 @@ +From 0e260c69746ea4ff101b6f66bf40de8426cfccbd Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:06 +0100 +Subject: [PATCH] nft: Reduce __nft_rule_del() signature + +The function does not use passed struct nftnl_rule_list, so remove it +from its parameters. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 9975b6da9f926994bcea8ae788e47aab4b5b235e) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 5032c718b33a9..befd9f4dd9026 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1946,8 +1946,7 @@ void nft_table_new(struct nft_handle *h, const char *table) + nft_xt_builtin_init(h, table); + } + +-static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule_list *list, +- struct nftnl_rule *r) ++static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r) + { + int ret; + +@@ -2046,7 +2045,7 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, + + r = nft_rule_find(h, list, chain, table, data, -1); + if (r != NULL) { +- ret =__nft_rule_del(h, list, r); ++ ret =__nft_rule_del(h, r); + if (ret < 0) + errno = ENOMEM; + if (verbose) +@@ -2151,7 +2150,7 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain, + r = nft_rule_find(h, list, chain, table, NULL, rulenum); + if (r != NULL) { + DEBUGP("deleting rule by number %d\n", rulenum); +- ret = __nft_rule_del(h, list, r); ++ ret = __nft_rule_del(h, r); + if (ret < 0) + errno = ENOMEM; + } else +-- +2.21.0 + diff --git a/SOURCES/0016-nft-Reduce-indenting-level-in-flush_chain_cache.patch b/SOURCES/0016-nft-Reduce-indenting-level-in-flush_chain_cache.patch new file mode 100644 index 0000000..ddcd2fb --- /dev/null +++ b/SOURCES/0016-nft-Reduce-indenting-level-in-flush_chain_cache.patch @@ -0,0 +1,60 @@ +From 3614b4bee283ea6d08207ccc5e2efa3ebfad321c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:07 +0100 +Subject: [PATCH] nft: Reduce indenting level in flush_chain_cache() + +Instead of doing all in one go, make two separate decisions: + +1) If table has no chain cache, either continue or return depending on + whether we're flushing for a specific table. + +2) With chain cache present, flushing strategy once more depends on + whether we're flushing for a specific table: If given, just remove + all rules and return. If not, free the cache and set to NULL (so that + it will be repopulated later), then continue the loop. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit d4b0d248cc057e39608c7c1c1203dd3f1ea96645) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index befd9f4dd9026..997d7bc58fd00 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -815,16 +815,20 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename) + if (tablename && strcmp(h->tables[i].name, tablename)) + continue; + +- if (h->table[i].chain_cache) { +- if (tablename) { +- nftnl_chain_list_foreach(h->table[i].chain_cache, +- __flush_chain_cache, NULL); +- break; +- } else { +- nftnl_chain_list_free(h->table[i].chain_cache); +- h->table[i].chain_cache = NULL; +- } ++ if (!h->table[i].chain_cache) { ++ if (tablename) ++ return; ++ continue; + } ++ ++ if (tablename) { ++ nftnl_chain_list_foreach(h->table[i].chain_cache, ++ __flush_chain_cache, NULL); ++ return; ++ } ++ ++ nftnl_chain_list_free(h->table[i].chain_cache); ++ h->table[i].chain_cache = NULL; + } + } + +-- +2.21.0 + diff --git a/SOURCES/0017-nft-Simplify-per-table-chain-cache-update.patch b/SOURCES/0017-nft-Simplify-per-table-chain-cache-update.patch new file mode 100644 index 0000000..ff29396 --- /dev/null +++ b/SOURCES/0017-nft-Simplify-per-table-chain-cache-update.patch @@ -0,0 +1,86 @@ +From eafa37433c920c6613bd351017d31cfd6e4cc397 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:08 +0100 +Subject: [PATCH] nft: Simplify per table chain cache update + +Previously, each table's chain cache was potentially unallocated until +nftnl_chain_list_cb() saw a chain for it. This means such callback had to +check the chain_cache pointer for each chain belonging to that table. + +In addition to the above, nft_chain_list_get() had to cover for the +possibility that a given table didn't have any chains at all in kernel, +so check requested table's chain cache once more and allocate it if +NULL. + +Instead, simply iterate over all tables and preallocate their chain +caches prior to requesting the chain list from kernel. The only caveat +is to flush the chain cache completely before retrying in case of EINTR. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 402dac2190e6011d4f4ad81c2992b7126b3d79d9) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 997d7bc58fd00..7d08a0884adde 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1286,12 +1286,6 @@ static int nftnl_chain_list_cb(const struct nlmsghdr *nlh, void *data) + if (!t) + goto out; + +- if (!h->table[t->type].chain_cache) { +- h->table[t->type].chain_cache = nftnl_chain_list_alloc(); +- if (!h->table[t->type].chain_cache) +- goto out; +- } +- + nftnl_chain_list_add_tail(c, h->table[t->type].chain_cache); + + return MNL_CB_OK; +@@ -1307,7 +1301,7 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + char buf[16536]; + struct nlmsghdr *nlh; + const struct builtin_table *t; +- int ret; ++ int i, ret; + + t = nft_table_builtin_find(h, table); + if (!t) +@@ -1316,18 +1310,27 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + if (h->table[t->type].chain_cache) + return h->table[t->type].chain_cache; + retry: ++ for (i = 0; i < NFT_TABLE_MAX; i++) { ++ enum nft_table_type type = h->tables[i].type; ++ ++ if (!h->tables[i].name) ++ continue; ++ ++ h->table[type].chain_cache = nftnl_chain_list_alloc(); ++ if (!h->table[type].chain_cache) ++ return NULL; ++ } ++ + nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, + NLM_F_DUMP, h->seq); + + ret = mnl_talk(h, nlh, nftnl_chain_list_cb, h); + if (ret < 0 && errno == EINTR) { + assert(nft_restart(h) >= 0); ++ flush_chain_cache(h, NULL); + goto retry; + } + +- if (!h->table[t->type].chain_cache) +- h->table[t->type].chain_cache = nftnl_chain_list_alloc(); +- + return h->table[t->type].chain_cache; + } + +-- +2.21.0 + diff --git a/SOURCES/0018-nft-Simplify-nft_rule_insert-a-bit.patch b/SOURCES/0018-nft-Simplify-nft_rule_insert-a-bit.patch new file mode 100644 index 0000000..38240fe --- /dev/null +++ b/SOURCES/0018-nft-Simplify-nft_rule_insert-a-bit.patch @@ -0,0 +1,49 @@ +From 8ae498f20e89ae11f8cbde9a16e0e5397a274a8c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:09 +0100 +Subject: [PATCH] nft: Simplify nft_rule_insert() a bit + +Fetch rule list right on top instead of in each branch separately. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 88bd4f28878bc7d41daa23098d68bf1bf6f5cea2) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 7d08a0884adde..469448f42cd6d 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2091,8 +2091,8 @@ nft_rule_add(struct nft_handle *h, const char *chain, + int nft_rule_insert(struct nft_handle *h, const char *chain, + const char *table, void *data, int rulenum, bool verbose) + { ++ struct nftnl_rule_list *list = nft_rule_list_get(h); + struct nftnl_rule *r, *new_rule; +- struct nftnl_rule_list *list; + uint64_t handle = 0; + + /* If built-in chains don't exist for this table, create them */ +@@ -2102,7 +2102,6 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, + nft_fn = nft_rule_insert; + + if (rulenum > 0) { +- list = nft_rule_list_get(h); + if (list == NULL) + goto err; + +@@ -2123,8 +2122,6 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, + + handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE); + DEBUGP("adding after rule handle %"PRIu64"\n", handle); +- } else { +- nft_rule_list_get(h); + } + + new_rule = nft_rule_add(h, chain, table, data, handle, verbose); +-- +2.21.0 + diff --git a/SOURCES/0019-nft-Introduce-fetch_chain_cache.patch b/SOURCES/0019-nft-Introduce-fetch_chain_cache.patch new file mode 100644 index 0000000..17868d1 --- /dev/null +++ b/SOURCES/0019-nft-Introduce-fetch_chain_cache.patch @@ -0,0 +1,76 @@ +From 0e72e49c0f220a9223de85574b878114bf8ceff3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:10 +0100 +Subject: [PATCH] nft: Introduce fetch_chain_cache() + +Move chain cache population from nft_chain_list_get() into a dedicated +function. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 8bae620abf9ac81794acca43d305ca74f15a13ff) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 469448f42cd6d..b425577798679 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1295,20 +1295,12 @@ err: + return MNL_CB_OK; + } + +-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, +- const char *table) ++static int fetch_chain_cache(struct nft_handle *h) + { + char buf[16536]; + struct nlmsghdr *nlh; +- const struct builtin_table *t; + int i, ret; + +- t = nft_table_builtin_find(h, table); +- if (!t) +- return NULL; +- +- if (h->table[t->type].chain_cache) +- return h->table[t->type].chain_cache; + retry: + for (i = 0; i < NFT_TABLE_MAX; i++) { + enum nft_table_type type = h->tables[i].type; +@@ -1318,7 +1310,7 @@ retry: + + h->table[type].chain_cache = nftnl_chain_list_alloc(); + if (!h->table[type].chain_cache) +- return NULL; ++ return -1; + } + + nlh = nftnl_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family, +@@ -1331,6 +1323,21 @@ retry: + goto retry; + } + ++ return ret; ++} ++ ++struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, ++ const char *table) ++{ ++ const struct builtin_table *t; ++ ++ t = nft_table_builtin_find(h, table); ++ if (!t) ++ return NULL; ++ ++ if (!h->table[t->type].chain_cache) ++ fetch_chain_cache(h); ++ + return h->table[t->type].chain_cache; + } + +-- +2.21.0 + diff --git a/SOURCES/0020-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch b/SOURCES/0020-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch new file mode 100644 index 0000000..5fbb973 --- /dev/null +++ b/SOURCES/0020-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch @@ -0,0 +1,149 @@ +From e3624bf4de451c53a3b42e1b83adab3051c03500 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:11 +0100 +Subject: [PATCH] nft: Move nft_rule_list_get() above nft_chain_list_get() + +Later when introducing per chain rule caches, nft_rule_list_get() will +be removed. But nftnl_rule_list_cb() which it uses will be reused to +update each chain's rule cache from inside nftnl_chain_list_get(), so +move both into position. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit eb13831f1c41c0efa626ab85d4448fb8ce4c87a2) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 110 ++++++++++++++++++++++++------------------------- + 1 file changed, 55 insertions(+), 55 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index b425577798679..1840561f2e531 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1326,61 +1326,6 @@ retry: + return ret; + } + +-struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, +- const char *table) +-{ +- const struct builtin_table *t; +- +- t = nft_table_builtin_find(h, table); +- if (!t) +- return NULL; +- +- if (!h->table[t->type].chain_cache) +- fetch_chain_cache(h); +- +- return h->table[t->type].chain_cache; +-} +- +-static const char *policy_name[NF_ACCEPT+1] = { +- [NF_DROP] = "DROP", +- [NF_ACCEPT] = "ACCEPT", +-}; +- +-int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) +-{ +- struct nftnl_chain_list_iter *iter; +- struct nft_family_ops *ops; +- struct nftnl_chain *c; +- +- ops = nft_family_ops_lookup(h->family); +- +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) +- return 0; +- +- c = nftnl_chain_list_iter_next(iter); +- while (c != NULL) { +- const char *policy = NULL; +- +- if (nft_chain_builtin(c)) { +- uint32_t pol = NF_ACCEPT; +- +- if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY)) +- pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); +- policy = policy_name[pol]; +- } +- +- if (ops->save_chain) +- ops->save_chain(c, policy); +- +- c = nftnl_chain_list_iter_next(iter); +- } +- +- nftnl_chain_list_iter_destroy(iter); +- +- return 1; +-} +- + static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data) + { + struct nftnl_rule *r; +@@ -1437,6 +1382,61 @@ retry: + return list; + } + ++struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, ++ const char *table) ++{ ++ const struct builtin_table *t; ++ ++ t = nft_table_builtin_find(h, table); ++ if (!t) ++ return NULL; ++ ++ if (!h->table[t->type].chain_cache) ++ fetch_chain_cache(h); ++ ++ return h->table[t->type].chain_cache; ++} ++ ++static const char *policy_name[NF_ACCEPT+1] = { ++ [NF_DROP] = "DROP", ++ [NF_ACCEPT] = "ACCEPT", ++}; ++ ++int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) ++{ ++ struct nftnl_chain_list_iter *iter; ++ struct nft_family_ops *ops; ++ struct nftnl_chain *c; ++ ++ ops = nft_family_ops_lookup(h->family); ++ ++ iter = nftnl_chain_list_iter_create(list); ++ if (iter == NULL) ++ return 0; ++ ++ c = nftnl_chain_list_iter_next(iter); ++ while (c != NULL) { ++ const char *policy = NULL; ++ ++ if (nft_chain_builtin(c)) { ++ uint32_t pol = NF_ACCEPT; ++ ++ if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY)) ++ pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); ++ policy = policy_name[pol]; ++ } ++ ++ if (ops->save_chain) ++ ops->save_chain(c, policy); ++ ++ c = nftnl_chain_list_iter_next(iter); ++ } ++ ++ nftnl_chain_list_iter_destroy(iter); ++ ++ return 1; ++} ++ + int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) + { + struct nftnl_rule_list *list; +-- +2.21.0 + diff --git a/SOURCES/0021-xtables-Implement-per-chain-rule-cache.patch b/SOURCES/0021-xtables-Implement-per-chain-rule-cache.patch new file mode 100644 index 0000000..c12a69a --- /dev/null +++ b/SOURCES/0021-xtables-Implement-per-chain-rule-cache.patch @@ -0,0 +1,802 @@ +From 56521a8270d740184510f660492e2c9f8588afbf Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:12 +0100 +Subject: [PATCH] xtables: Implement per chain rule cache + +Use recently introduced support for rules inside chains in libnftnl to +introduce a rule cache per chain instead of a global one. + +A tricky bit is to decide if cache should be updated or not. Previously, +the global rule cache was populated just once and then reused unless +being flushed completely (via call to flush_rule_cache() with +NULL-pointer table argument). Resemble this behaviour by introducing a +boolean indicating cache status and fetch rules for all chains when +updating the chain cache in nft_chain_list_get(). + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 947c51c95edbbf08d6b3c105177ac5cfa238aade) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 386 +++++++++++++++++++++---------------------------- + iptables/nft.h | 2 +- + 2 files changed, 166 insertions(+), 222 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 1840561f2e531..842ed2b805bee 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -772,28 +772,15 @@ int nft_init(struct nft_handle *h, const struct builtin_table *t) + + static int __flush_rule_cache(struct nftnl_rule *r, void *data) + { +- const char *tablename = data; +- +- if (!strcmp(nftnl_rule_get_str(r, NFTNL_RULE_TABLE), tablename)) { +- nftnl_rule_list_del(r); +- nftnl_rule_free(r); +- } ++ nftnl_rule_list_del(r); ++ nftnl_rule_free(r); + + return 0; + } + +-static void flush_rule_cache(struct nft_handle *h, const char *tablename) ++static void flush_rule_cache(struct nftnl_chain *c) + { +- if (!h->rule_cache) +- return; +- +- if (tablename) { +- nftnl_rule_list_foreach(h->rule_cache, __flush_rule_cache, +- (void *)tablename); +- } else { +- nftnl_rule_list_free(h->rule_cache); +- h->rule_cache = NULL; +- } ++ nftnl_rule_foreach(c, __flush_rule_cache, NULL); + } + + static int __flush_chain_cache(struct nftnl_chain *c, void *data) +@@ -830,12 +817,12 @@ static void flush_chain_cache(struct nft_handle *h, const char *tablename) + nftnl_chain_list_free(h->table[i].chain_cache); + h->table[i].chain_cache = NULL; + } ++ h->have_cache = false; + } + + void nft_fini(struct nft_handle *h) + { + flush_chain_cache(h, NULL); +- flush_rule_cache(h, NULL); + mnl_socket_close(h->nl); + } + +@@ -1195,12 +1182,14 @@ err: + return NULL; + } + +-static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h); ++static struct nftnl_chain * ++nft_chain_find(struct nft_handle *h, const char *table, const char *chain); + + int + nft_rule_append(struct nft_handle *h, const char *chain, const char *table, + void *data, uint64_t handle, bool verbose) + { ++ struct nftnl_chain *c; + struct nftnl_rule *r; + int type; + +@@ -1228,10 +1217,9 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); + +- if (!nft_rule_list_get(h)) +- return 0; +- +- nftnl_rule_list_add_tail(r, h->rule_cache); ++ c = nft_chain_find(h, table, chain); ++ if (c) ++ nftnl_chain_rule_add_tail(r, c); + + return 1; + } +@@ -1328,58 +1316,75 @@ retry: + + static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data) + { ++ struct nftnl_chain *c = data; + struct nftnl_rule *r; +- struct nftnl_rule_list *list = data; + + r = nftnl_rule_alloc(); + if (r == NULL) +- goto err; +- +- if (nftnl_rule_nlmsg_parse(nlh, r) < 0) +- goto out; ++ return MNL_CB_OK; + +- nftnl_rule_list_add_tail(r, list); ++ if (nftnl_rule_nlmsg_parse(nlh, r) < 0) { ++ nftnl_rule_free(r); ++ return MNL_CB_OK; ++ } + +- return MNL_CB_OK; +-out: +- nftnl_rule_free(r); +- nftnl_rule_list_free(list); +-err: ++ nftnl_chain_rule_add_tail(r, c); + return MNL_CB_OK; + } + +-static struct nftnl_rule_list *nft_rule_list_get(struct nft_handle *h) ++static int nft_rule_list_update(struct nftnl_chain *c, void *data) + { ++ struct nft_handle *h = data; + char buf[16536]; + struct nlmsghdr *nlh; +- struct nftnl_rule_list *list; ++ struct nftnl_rule *rule; + int ret; + +- if (h->rule_cache) +- return h->rule_cache; ++ rule = nftnl_rule_alloc(); ++ if (!rule) ++ return -1; + +-retry: +- list = nftnl_rule_list_alloc(); +- if (list == NULL) +- return 0; ++ nftnl_rule_set_str(rule, NFTNL_RULE_TABLE, ++ nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE)); ++ nftnl_rule_set_str(rule, NFTNL_RULE_CHAIN, ++ nftnl_chain_get_str(c, NFTNL_CHAIN_NAME)); + ++retry: + nlh = nftnl_rule_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, list); ++ ret = mnl_talk(h, nlh, nftnl_rule_list_cb, c); + if (ret < 0) { ++ flush_rule_cache(c); ++ + if (errno == EINTR) { + assert(nft_restart(h) >= 0); +- nftnl_rule_list_free(list); + goto retry; + } +- +- nftnl_rule_list_free(list); +- return NULL; ++ nftnl_rule_free(rule); ++ return -1; + } + +- h->rule_cache = list; +- return list; ++ nftnl_rule_free(rule); ++ return 0; ++} ++ ++static int fetch_rule_cache(struct nft_handle *h) ++{ ++ int i; ++ ++ for (i = 0; i < NFT_TABLE_MAX; i++) { ++ enum nft_table_type type = h->tables[i].type; ++ ++ if (!h->tables[i].name) ++ continue; ++ ++ if (nftnl_chain_list_foreach(h->table[type].chain_cache, ++ nft_rule_list_update, h)) ++ return -1; ++ } ++ return 0; + } + + struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, +@@ -1391,8 +1396,11 @@ struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + if (!t) + return NULL; + +- if (!h->table[t->type].chain_cache) ++ if (!h->have_cache) { + fetch_chain_cache(h); ++ fetch_rule_cache(h); ++ h->have_cache = true; ++ } + + return h->table[t->type].chain_cache; + } +@@ -1437,38 +1445,54 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) + return 1; + } + +-int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) ++static int nft_chain_save_rules(struct nft_handle *h, ++ struct nftnl_chain *c, unsigned int format) + { +- struct nftnl_rule_list *list; +- struct nftnl_rule_list_iter *iter; ++ struct nftnl_rule_iter *iter; + struct nftnl_rule *r; + +- list = nft_rule_list_get(h); +- if (list == NULL) +- return 0; +- +- iter = nftnl_rule_list_iter_create(list); ++ iter = nftnl_rule_iter_create(c); + if (iter == NULL) +- return 0; ++ return 1; + +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + while (r != NULL) { +- const char *rule_table = +- nftnl_rule_get_str(r, NFTNL_RULE_TABLE); ++ nft_rule_print_save(r, NFT_RULE_APPEND, format); ++ r = nftnl_rule_iter_next(iter); ++ } + +- if (strcmp(table, rule_table) != 0) +- goto next; ++ nftnl_rule_iter_destroy(iter); ++ return 0; ++} + +- nft_rule_print_save(r, NFT_RULE_APPEND, format); ++int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) ++{ ++ struct nftnl_chain_list_iter *iter; ++ struct nftnl_chain_list *list; ++ struct nftnl_chain *c; ++ int ret = 0; + +-next: +- r = nftnl_rule_list_iter_next(iter); ++ list = nft_chain_list_get(h, table); ++ if (!list) ++ return 0; ++ ++ iter = nftnl_chain_list_iter_create(list); ++ if (!iter) ++ return 0; ++ ++ c = nftnl_chain_list_iter_next(iter); ++ while (c) { ++ ret = nft_chain_save_rules(h, c, format); ++ if (ret != 0) ++ break; ++ ++ c = nftnl_chain_list_iter_next(iter); + } + +- nftnl_rule_list_iter_destroy(iter); ++ nftnl_chain_list_iter_destroy(iter); + + /* the core expects 1 for success and 0 for error */ +- return 1; ++ return ret == 0 ? 1 : 0; + } + + static void +@@ -1567,6 +1591,7 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + fprintf(stdout, "Flushing chain `%s'\n", chain_name); + + __nft_rule_flush(h, table, chain_name); ++ flush_rule_cache(c); + + if (chain != NULL) + break; +@@ -1574,7 +1599,6 @@ next: + c = nftnl_chain_list_iter_next(iter); + } + nftnl_chain_list_iter_destroy(iter); +- flush_rule_cache(h, table); + err: + /* the core expects 1 for success and 0 for error */ + return ret == 0 ? 1 : 0; +@@ -1898,7 +1922,6 @@ static int __nft_table_flush(struct nft_handle *h, const char *table) + h->table[_t->type].initialized = false; + + flush_chain_cache(h, table); +- flush_rule_cache(h, table); + + return 0; + } +@@ -1939,12 +1962,6 @@ next: + t = nftnl_table_list_iter_next(iter); + } + +- if (!h->rule_cache) { +- h->rule_cache = nftnl_rule_list_alloc(); +- if (h->rule_cache == NULL) +- return -1; +- } +- + err_table_iter: + nftnl_table_list_iter_destroy(iter); + err_table_list: +@@ -1975,31 +1992,19 @@ static int __nft_rule_del(struct nft_handle *h, struct nftnl_rule *r) + } + + static struct nftnl_rule * +-nft_rule_find(struct nft_handle *h, struct nftnl_rule_list *list, +- const char *chain, const char *table, void *data, int rulenum) ++nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulenum) + { + struct nftnl_rule *r; +- struct nftnl_rule_list_iter *iter; ++ struct nftnl_rule_iter *iter; + int rule_ctr = 0; + bool found = false; + +- iter = nftnl_rule_list_iter_create(list); ++ iter = nftnl_rule_iter_create(c); + if (iter == NULL) + return 0; + +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + while (r != NULL) { +- const char *rule_table = +- nftnl_rule_get_str(r, NFTNL_RULE_TABLE); +- const char *rule_chain = +- nftnl_rule_get_str(r, NFTNL_RULE_CHAIN); +- +- if (strcmp(table, rule_table) != 0 || +- strcmp(chain, rule_chain) != 0) { +- DEBUGP("different chain / table\n"); +- goto next; +- } +- + if (rulenum >= 0) { + /* Delete by rule number case */ + if (rule_ctr == rulenum) { +@@ -2012,11 +2017,10 @@ nft_rule_find(struct nft_handle *h, struct nftnl_rule_list *list, + break; + } + rule_ctr++; +-next: +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + } + +- nftnl_rule_list_iter_destroy(iter); ++ nftnl_rule_iter_destroy(iter); + + return found ? r : NULL; + } +@@ -2024,16 +2028,16 @@ next: + int nft_rule_check(struct nft_handle *h, const char *chain, + const char *table, void *data, bool verbose) + { +- struct nftnl_rule_list *list; ++ struct nftnl_chain *c; + struct nftnl_rule *r; + + nft_fn = nft_rule_check; + +- list = nft_rule_list_get(h); +- if (list == NULL) ++ c = nft_chain_find(h, table, chain); ++ if (!c) + return 0; + +- r = nft_rule_find(h, list, chain, table, data, -1); ++ r = nft_rule_find(h, c, data, -1); + if (r == NULL) { + errno = ENOENT; + return 0; +@@ -2048,16 +2052,18 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, + const char *table, void *data, bool verbose) + { + int ret = 0; ++ struct nftnl_chain *c; + struct nftnl_rule *r; +- struct nftnl_rule_list *list; + + nft_fn = nft_rule_delete; + +- list = nft_rule_list_get(h); +- if (list == NULL) ++ c = nft_chain_find(h, table, chain); ++ if (!c) { ++ errno = ENOENT; + return 0; ++ } + +- r = nft_rule_find(h, list, chain, table, data, -1); ++ r = nft_rule_find(h, c, data, -1); + if (r != NULL) { + ret =__nft_rule_del(h, r); + if (ret < 0) +@@ -2098,8 +2104,8 @@ nft_rule_add(struct nft_handle *h, const char *chain, + int nft_rule_insert(struct nft_handle *h, const char *chain, + const char *table, void *data, int rulenum, bool verbose) + { +- struct nftnl_rule_list *list = nft_rule_list_get(h); + struct nftnl_rule *r, *new_rule; ++ struct nftnl_chain *c; + uint64_t handle = 0; + + /* If built-in chains don't exist for this table, create them */ +@@ -2108,17 +2114,19 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, + + nft_fn = nft_rule_insert; + +- if (rulenum > 0) { +- if (list == NULL) +- goto err; ++ c = nft_chain_find(h, table, chain); ++ if (!c) { ++ errno = ENOENT; ++ goto err; ++ } + +- r = nft_rule_find(h, list, chain, table, data, rulenum); ++ if (rulenum > 0) { ++ r = nft_rule_find(h, c, data, rulenum); + if (r == NULL) { + /* special case: iptables allows to insert into + * rule_count + 1 position. + */ +- r = nft_rule_find(h, list, chain, table, data, +- rulenum - 1); ++ r = nft_rule_find(h, c, data, rulenum - 1); + if (r != NULL) + return nft_rule_append(h, chain, table, data, + 0, verbose); +@@ -2136,9 +2144,9 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, + goto err; + + if (handle) +- nftnl_rule_list_insert_at(new_rule, r); ++ nftnl_chain_rule_insert_at(new_rule, r); + else +- nftnl_rule_list_add(new_rule, h->rule_cache); ++ nftnl_chain_rule_add(new_rule, c); + + return 1; + err: +@@ -2149,16 +2157,18 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain, + const char *table, int rulenum, bool verbose) + { + int ret = 0; ++ struct nftnl_chain *c; + struct nftnl_rule *r; +- struct nftnl_rule_list *list; + + nft_fn = nft_rule_delete_num; + +- list = nft_rule_list_get(h); +- if (list == NULL) ++ c = nft_chain_find(h, table, chain); ++ if (!c) { ++ errno = ENOENT; + return 0; ++ } + +- r = nft_rule_find(h, list, chain, table, NULL, rulenum); ++ r = nft_rule_find(h, c, NULL, rulenum); + if (r != NULL) { + DEBUGP("deleting rule by number %d\n", rulenum); + ret = __nft_rule_del(h, r); +@@ -2174,16 +2184,18 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, + const char *table, void *data, int rulenum, bool verbose) + { + int ret = 0; ++ struct nftnl_chain *c; + struct nftnl_rule *r; +- struct nftnl_rule_list *list; + + nft_fn = nft_rule_replace; + +- list = nft_rule_list_get(h); +- if (list == NULL) ++ c = nft_chain_find(h, table, chain); ++ if (!c) { ++ errno = ENOENT; + return 0; ++ } + +- r = nft_rule_find(h, list, chain, table, data, rulenum); ++ r = nft_rule_find(h, c, data, rulenum); + if (r != NULL) { + DEBUGP("replacing rule with handle=%llu\n", + (unsigned long long) +@@ -2201,35 +2213,21 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, + } + + static int +-__nft_rule_list(struct nft_handle *h, const char *chain, const char *table, ++__nft_rule_list(struct nft_handle *h, struct nftnl_chain *c, + int rulenum, unsigned int format, + void (*cb)(struct nftnl_rule *r, unsigned int num, + unsigned int format)) + { +- struct nftnl_rule_list *list; +- struct nftnl_rule_list_iter *iter; ++ struct nftnl_rule_iter *iter; + struct nftnl_rule *r; + int rule_ctr = 0; + +- list = nft_rule_list_get(h); +- if (list == NULL) +- return 0; +- +- iter = nftnl_rule_list_iter_create(list); ++ iter = nftnl_rule_iter_create(c); + if (iter == NULL) + return 0; + +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + while (r != NULL) { +- const char *rule_table = +- nftnl_rule_get_str(r, NFTNL_RULE_TABLE); +- const char *rule_chain = +- nftnl_rule_get_str(r, NFTNL_RULE_CHAIN); +- +- if (strcmp(table, rule_table) != 0 || +- strcmp(chain, rule_chain) != 0) +- goto next; +- + rule_ctr++; + + if (rulenum > 0 && rule_ctr != rulenum) { +@@ -2242,46 +2240,30 @@ __nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + break; + + next: +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + } + +- nftnl_rule_list_iter_destroy(iter); ++ nftnl_rule_iter_destroy(iter); + return 1; + } + +-static int nft_rule_count(struct nft_handle *h, +- const char *chain, const char *table) ++static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c) + { +- struct nftnl_rule_list_iter *iter; +- struct nftnl_rule_list *list; ++ struct nftnl_rule_iter *iter; + struct nftnl_rule *r; + int rule_ctr = 0; + +- list = nft_rule_list_get(h); +- if (list == NULL) +- return 0; +- +- iter = nftnl_rule_list_iter_create(list); ++ iter = nftnl_rule_iter_create(c); + if (iter == NULL) + return 0; + +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + while (r != NULL) { +- const char *rule_table = +- nftnl_rule_get_str(r, NFTNL_RULE_TABLE); +- const char *rule_chain = +- nftnl_rule_get_str(r, NFTNL_RULE_CHAIN); +- +- if (strcmp(table, rule_table) != 0 || +- strcmp(chain, rule_chain) != 0) +- goto next; +- + rule_ctr++; +-next: +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + } + +- nftnl_rule_list_iter_destroy(iter); ++ nftnl_rule_iter_destroy(iter); + return rule_ctr; + } + +@@ -2314,8 +2296,11 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + } + + if (chain && rulenum) { +- __nft_rule_list(h, chain, table, +- rulenum, format, ops->print_rule); ++ c = nft_chain_find(h, table, chain); ++ if (!c) ++ return 0; ++ ++ __nft_rule_list(h, c, rulenum, format, ops->print_rule); + return 1; + } + +@@ -2358,12 +2343,11 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + if (found) + printf("\n"); + +- entries = nft_rule_count(h, chain_name, table); ++ entries = nft_rule_count(h, c); + ops->print_header(format, chain_name, policy_name[policy], + &ctrs, basechain, refs - entries, entries); + +- __nft_rule_list(h, chain_name, table, +- rulenum, format, ops->print_rule); ++ __nft_rule_list(h, c, rulenum, format, ops->print_rule); + + found = true; + +@@ -2484,8 +2468,7 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + if (chain && strcmp(chain, chain_name) != 0) + goto next; + +- ret = __nft_rule_list(h, chain_name, table, rulenum, +- format, list_save); ++ ret = __nft_rule_list(h, c, rulenum, format, list_save); + + /* we printed the chain we wanted, stop processing. */ + if (chain) +@@ -2503,17 +2486,17 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, + const char *table, int rulenum) + { + struct iptables_command_state cs = {}; +- struct nftnl_rule_list *list; ++ struct nftnl_chain *c; + struct nftnl_rule *r; + int ret = 0; + + nft_fn = nft_rule_delete; + +- list = nft_rule_list_get(h); +- if (list == NULL) ++ c = nft_chain_find(h, table, chain); ++ if (!c) + return 0; + +- r = nft_rule_find(h, list, chain, table, NULL, rulenum); ++ r = nft_rule_find(h, c, NULL, rulenum); + if (r == NULL) { + errno = ENOENT; + ret = 1; +@@ -2982,38 +2965,19 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename, + static void nft_chain_zero_rule_counters(struct nft_handle *h, + struct nftnl_chain *c) + { +- struct nftnl_rule_list_iter *iter; +- struct nftnl_rule_list *list; +- const char *table_name; +- const char *chain_name; ++ struct nftnl_rule_iter *iter; + struct nftnl_rule *r; + +- list = nft_rule_list_get(h); +- if (list == NULL) +- return; +- iter = nftnl_rule_list_iter_create(list); ++ iter = nftnl_rule_iter_create(c); + if (iter == NULL) + return; + +- table_name = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); +- chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + while (r != NULL) { + struct nftnl_expr_iter *ei; +- const char *table_chain; +- const char *rule_chain; + struct nftnl_expr *e; + bool zero_needed; + +- table_chain = nftnl_rule_get_str(r, NFTNL_RULE_TABLE); +- if (strcmp(table_chain, table_name)) +- goto next; +- +- rule_chain = nftnl_rule_get_str(r, NFTNL_RULE_CHAIN); +- if (strcmp(rule_chain, chain_name)) +- goto next; +- + ei = nftnl_expr_iter_create(r); + if (!ei) + break; +@@ -3044,11 +3008,10 @@ static void nft_chain_zero_rule_counters(struct nft_handle *h, + nftnl_rule_unset(r, NFTNL_RULE_POSITION); + batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r); + } +-next: +- r = nftnl_rule_list_iter_next(iter); ++ r = nftnl_rule_iter_next(iter); + } + +- nftnl_rule_list_iter_destroy(iter); ++ nftnl_rule_iter_destroy(iter); + } + + int nft_chain_zero_counters(struct nft_handle *h, const char *chain, +@@ -3143,19 +3106,8 @@ static int nft_is_expr_compatible(struct nftnl_expr *expr, void *data) + return -1; + } + +-struct nft_is_rule_compatible_data { +- const char *tablename; +-}; +- + static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data) + { +- const char *table = nftnl_rule_get_str(rule, NFTNL_RULE_TABLE); +- struct nft_is_rule_compatible_data *d = data; +- +- /* ignore rules belonging to a different table */ +- if (strcmp(table, d->tablename)) +- return 0; +- + return nftnl_expr_foreach(rule, nft_is_expr_compatible, NULL); + } + +@@ -3167,6 +3119,9 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) + enum nf_inet_hooks hook; + int i, prio; + ++ if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL)) ++ return -1; ++ + if (!nft_chain_builtin(c)) + return 0; + +@@ -3210,11 +3165,7 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) + + bool nft_is_table_compatible(struct nft_handle *h, const char *tablename) + { +- struct nft_is_rule_compatible_data rcd = { +- .tablename = tablename +- }; + struct nftnl_chain_list *clist; +- struct nftnl_rule_list *list; + + clist = nft_chain_list_get(h, tablename); + if (clist == NULL) +@@ -3223,12 +3174,5 @@ bool nft_is_table_compatible(struct nft_handle *h, const char *tablename) + if (nftnl_chain_list_foreach(clist, nft_is_chain_compatible, h)) + return false; + +- list = nft_rule_list_get(h); +- if (list == NULL) +- return true; +- +- if (nftnl_rule_list_foreach(list, nft_is_rule_compatible, &rcd)) +- return false; +- + return true; + } +diff --git a/iptables/nft.h b/iptables/nft.h +index bf60ab3943659..6568257feddc7 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -42,7 +42,7 @@ struct nft_handle { + struct nftnl_chain_list *chain_cache; + bool initialized; + } table[NFT_TABLE_MAX]; +- struct nftnl_rule_list *rule_cache; ++ bool have_cache; + bool restore; + int8_t config_done; + +-- +2.21.0 + diff --git a/SOURCES/0022-nft-Drop-nft_chain_list_find.patch b/SOURCES/0022-nft-Drop-nft_chain_list_find.patch new file mode 100644 index 0000000..0fca0cc --- /dev/null +++ b/SOURCES/0022-nft-Drop-nft_chain_list_find.patch @@ -0,0 +1,89 @@ +From 4255a54501f8588b4bd346cd36379cccd6e0abc7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:13 +0100 +Subject: [PATCH] nft: Drop nft_chain_list_find() + +Replace the function by nftnl_chain_list_lookup_byname() as provided by +libnftnl. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 63dc7a0d86a1b86b10c5e04dd910497b9d8fcfaf) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 31 ++----------------------------- + iptables/nft.h | 2 -- + 2 files changed, 2 insertions(+), 31 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 842ed2b805bee..883fb3db2c671 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -697,7 +697,7 @@ static void nft_chain_builtin_init(struct nft_handle *h, + /* Initialize built-in chains if they don't exist yet */ + for (i=0; i < NF_INET_NUMHOOKS && table->chains[i].name != NULL; i++) { + +- c = nft_chain_list_find(list, table->chains[i].name); ++ c = nftnl_chain_list_lookup_byname(list, table->chains[i].name); + if (c != NULL) + continue; + +@@ -1699,33 +1699,6 @@ err: + return ret == 0 ? 1 : 0; + } + +-struct nftnl_chain * +-nft_chain_list_find(struct nftnl_chain_list *list, const char *chain) +-{ +- struct nftnl_chain_list_iter *iter; +- struct nftnl_chain *c; +- +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) +- return NULL; +- +- c = nftnl_chain_list_iter_next(iter); +- while (c != NULL) { +- const char *chain_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- +- if (strcmp(chain, chain_name) != 0) +- goto next; +- +- nftnl_chain_list_iter_destroy(iter); +- return c; +-next: +- c = nftnl_chain_list_iter_next(iter); +- } +- nftnl_chain_list_iter_destroy(iter); +- return NULL; +-} +- + static struct nftnl_chain * + nft_chain_find(struct nft_handle *h, const char *table, const char *chain) + { +@@ -1735,7 +1708,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain) + if (list == NULL) + return NULL; + +- return nft_chain_list_find(list, chain); ++ return nftnl_chain_list_lookup_byname(list, chain); + } + + bool nft_chain_exists(struct nft_handle *h, +diff --git a/iptables/nft.h b/iptables/nft.h +index 6568257feddc7..dfdffd69342db 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -83,8 +83,6 @@ struct nftnl_chain; + int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters); + struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, + const char *table); +-struct nftnl_chain *nft_chain_list_find(struct nftnl_chain_list *list, +- const char *chain); + int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list); + int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); + int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); +-- +2.21.0 + diff --git a/SOURCES/0023-xtables-Optimize-flushing-a-specific-chain.patch b/SOURCES/0023-xtables-Optimize-flushing-a-specific-chain.patch new file mode 100644 index 0000000..172140d --- /dev/null +++ b/SOURCES/0023-xtables-Optimize-flushing-a-specific-chain.patch @@ -0,0 +1,85 @@ +From 0497d24ecbc4414274bbfa33762de90b28c57be9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:14 +0100 +Subject: [PATCH] xtables: Optimize flushing a specific chain + +If a chain name is given to nft_rule_flush(), make use of +nftnl_chain_list_lookup_byname(). + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 196841c9597eff536b59655b60df088ee1929904) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 883fb3db2c671..a23acbcc9b100 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1496,10 +1496,14 @@ int nft_rule_save(struct nft_handle *h, const char *table, unsigned int format) + } + + static void +-__nft_rule_flush(struct nft_handle *h, const char *table, const char *chain) ++__nft_rule_flush(struct nft_handle *h, const char *table, ++ const char *chain, bool verbose) + { + struct nftnl_rule *r; + ++ if (verbose) ++ fprintf(stdout, "Flushing chain `%s'\n", chain); ++ + r = nftnl_rule_alloc(); + if (r == NULL) + return; +@@ -1533,7 +1537,7 @@ static int __nft_chain_user_flush(struct nftnl_chain *c, void *data) + return 0; + + if (!nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) +- __nft_rule_flush(h, table, chain); ++ __nft_rule_flush(h, table, chain, false); + + return 0; + } +@@ -1573,6 +1577,16 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + goto err; + } + ++ if (chain) { ++ c = nftnl_chain_list_lookup_byname(list, chain); ++ if (!c) ++ return 0; ++ ++ __nft_rule_flush(h, table, chain, verbose); ++ flush_rule_cache(c); ++ return 1; ++ } ++ + iter = nftnl_chain_list_iter_create(list); + if (iter == NULL) { + ret = 1; +@@ -1584,18 +1598,8 @@ int nft_rule_flush(struct nft_handle *h, const char *chain, const char *table, + const char *chain_name = + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); + +- if (chain != NULL && strcmp(chain, chain_name) != 0) +- goto next; +- +- if (verbose) +- fprintf(stdout, "Flushing chain `%s'\n", chain_name); +- +- __nft_rule_flush(h, table, chain_name); ++ __nft_rule_flush(h, table, chain_name, verbose); + flush_rule_cache(c); +- +- if (chain != NULL) +- break; +-next: + c = nftnl_chain_list_iter_next(iter); + } + nftnl_chain_list_iter_destroy(iter); +-- +2.21.0 + diff --git a/SOURCES/0024-xtables-Optimize-nft_chain_zero_counters.patch b/SOURCES/0024-xtables-Optimize-nft_chain_zero_counters.patch new file mode 100644 index 0000000..850d8a3 --- /dev/null +++ b/SOURCES/0024-xtables-Optimize-nft_chain_zero_counters.patch @@ -0,0 +1,136 @@ +From 25eff54c9a82ad816f7a4c274d39daf2e1aaf3a7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:15 +0100 +Subject: [PATCH] xtables: Optimize nft_chain_zero_counters() + +If a chain name was given, make use of nftnl_chain_list_lookup_byname(). +Streamline nft_chain_zero_rule_counters() to be suitable for calling +from nftnl_chain_list_foreach(). + +There is an unrelated optimization in here, too: Add batch job +NFT_COMPAT_CHAIN_ZERO only if it is a base chain. Since user-defined +chains don't have counters, there is no need to do anything for them. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit a6ce0c65d3a390bfff16e834c18650beedecf40c) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 72 +++++++++++++++++++++++++------------------------- + 1 file changed, 36 insertions(+), 36 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index a23acbcc9b100..9951bf3212197 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2939,15 +2939,36 @@ int nft_xtables_config_load(struct nft_handle *h, const char *filename, + return h->config_done; + } + +-static void nft_chain_zero_rule_counters(struct nft_handle *h, +- struct nftnl_chain *c) ++struct chain_zero_data { ++ struct nft_handle *handle; ++ bool verbose; ++}; ++ ++static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data) + { ++ struct chain_zero_data *d = data; ++ struct nft_handle *h = d->handle; + struct nftnl_rule_iter *iter; + struct nftnl_rule *r; ++ int ret = 0; ++ ++ if (d->verbose) ++ fprintf(stdout, "Zeroing chain `%s'\n", ++ nftnl_chain_get_str(c, NFTNL_CHAIN_NAME)); ++ ++ if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) { ++ /* zero base chain counters. */ ++ nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0); ++ nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0); ++ nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); ++ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c); ++ if (ret) ++ return -1; ++ } + + iter = nftnl_rule_iter_create(c); + if (iter == NULL) +- return; ++ return -1; + + r = nftnl_rule_iter_next(iter); + while (r != NULL) { +@@ -2989,13 +3010,17 @@ static void nft_chain_zero_rule_counters(struct nft_handle *h, + } + + nftnl_rule_iter_destroy(iter); ++ return 0; + } + + int nft_chain_zero_counters(struct nft_handle *h, const char *chain, + const char *table, bool verbose) + { + struct nftnl_chain_list *list; +- struct nftnl_chain_list_iter *iter; ++ struct chain_zero_data d = { ++ .handle = h, ++ .verbose = verbose, ++ }; + struct nftnl_chain *c; + int ret = 0; + +@@ -3003,41 +3028,16 @@ int nft_chain_zero_counters(struct nft_handle *h, const char *chain, + if (list == NULL) + goto err; + +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) +- goto err; +- +- c = nftnl_chain_list_iter_next(iter); +- while (c != NULL) { +- const char *chain_name = +- nftnl_chain_get(c, NFTNL_CHAIN_NAME); +- +- if (chain != NULL && strcmp(chain, chain_name) != 0) +- goto next; +- +- if (verbose) +- fprintf(stdout, "Zeroing chain `%s'\n", chain_name); +- +- if (nftnl_chain_is_set(c, NFTNL_CHAIN_HOOKNUM)) { +- /* zero base chain counters. */ +- nftnl_chain_set_u64(c, NFTNL_CHAIN_PACKETS, 0); +- nftnl_chain_set_u64(c, NFTNL_CHAIN_BYTES, 0); +- } +- +- nft_chain_zero_rule_counters(h, c); +- +- nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); +- +- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_ZERO, c); ++ if (chain) { ++ c = nftnl_chain_list_lookup_byname(list, chain); ++ if (!c) ++ return 0; + +- if (chain != NULL) +- break; +-next: +- c = nftnl_chain_list_iter_next(iter); ++ ret = __nft_chain_zero_counters(c, &d); ++ goto err; + } + +- nftnl_chain_list_iter_destroy(iter); +- ++ ret = nftnl_chain_list_foreach(list, __nft_chain_zero_counters, &d); + err: + /* the core expects 1 for success and 0 for error */ + return ret == 0 ? 1 : 0; +-- +2.21.0 + diff --git a/SOURCES/0025-tests-Extend-verbose-output-and-return-code-tests.patch b/SOURCES/0025-tests-Extend-verbose-output-and-return-code-tests.patch new file mode 100644 index 0000000..ab0c60e --- /dev/null +++ b/SOURCES/0025-tests-Extend-verbose-output-and-return-code-tests.patch @@ -0,0 +1,79 @@ +From 9cc2fc0be5adc8f828fc8fd62951f7773148b7f0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:16 +0100 +Subject: [PATCH] tests: Extend verbose output and return code tests + +Recent changes to chain flush and zero routines incorporate proper error +propagation so trying to flush or zero a non-existent chain results in +an error. This is consistent with iptables-legacy, extend tests to make +sure it stays this way. + +Also extend verbose output test to make these recent changes didn't mess +it up. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit e80f7fe56e4c64e05da426418bc2fae7ca221c49) +Signed-off-by: Phil Sutter +--- + .../shell/testcases/iptables/0002-verbose-output_0 | 13 +++++++++---- + .../shell/testcases/iptables/0004-return-codes_0 | 6 ++++++ + 2 files changed, 15 insertions(+), 4 deletions(-) + +diff --git a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 +index 2e8059536ea7b..b1ef91f61f481 100755 +--- a/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 ++++ b/iptables/tests/shell/testcases/iptables/0002-verbose-output_0 +@@ -29,23 +29,28 @@ Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) + + diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI iptables -v -n -L) + ++[[ -z $($XT_MULTI iptables -v -N foobar) ]] || exit 1 ++ + diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI iptables -v -D FORWARD $RULE1) + diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI iptables -v -D FORWARD $RULE2) + + EXPECT="Flushing chain \`INPUT' + Flushing chain \`FORWARD' +-Flushing chain \`OUTPUT'" ++Flushing chain \`OUTPUT' ++Flushing chain \`foobar'" + + diff -u <(echo -e "$EXPECT") <($XT_MULTI iptables -v -F) + + EXPECT="Zeroing chain \`INPUT' + Zeroing chain \`FORWARD' +-Zeroing chain \`OUTPUT'" ++Zeroing chain \`OUTPUT' ++Zeroing chain \`foobar'" + + diff -u <(echo -e "$EXPECT") <($XT_MULTI iptables -v -Z) + + diff -u <(echo "Flushing chain \`OUTPUT'") <($XT_MULTI iptables -v -F OUTPUT) + diff -u <(echo "Zeroing chain \`OUTPUT'") <($XT_MULTI iptables -v -Z OUTPUT) ++diff -u <(echo "Flushing chain \`foobar'") <($XT_MULTI iptables -v -F foobar) ++diff -u <(echo "Zeroing chain \`foobar'") <($XT_MULTI iptables -v -Z foobar) + +-$XT_MULTI iptables -N foo +-diff -u <(echo "Deleting chain \`foo'") <($XT_MULTI iptables -v -X foo) ++diff -u <(echo "Deleting chain \`foobar'") <($XT_MULTI iptables -v -X foobar) +diff --git a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 b/iptables/tests/shell/testcases/iptables/0004-return-codes_0 +index 5b6e1f6f1bc7a..9d2493992bd69 100755 +--- a/iptables/tests/shell/testcases/iptables/0004-return-codes_0 ++++ b/iptables/tests/shell/testcases/iptables/0004-return-codes_0 +@@ -23,6 +23,12 @@ cmd 1 iptables -N foo + # iptables-nft allows this - bug or feature? + #cmd 2 iptables -N "invalid name" + ++# test chain flushing/zeroing ++cmd 0 iptables -F foo ++cmd 0 iptables -Z foo ++cmd 1 iptables -F bar ++cmd 1 iptables -Z bar ++ + # test chain rename + cmd 0 iptables -E foo bar + cmd 1 iptables -E foo bar +-- +2.21.0 + diff --git a/SOURCES/0026-xtables-Optimize-user-defined-chain-deletion.patch b/SOURCES/0026-xtables-Optimize-user-defined-chain-deletion.patch new file mode 100644 index 0000000..4f47354 --- /dev/null +++ b/SOURCES/0026-xtables-Optimize-user-defined-chain-deletion.patch @@ -0,0 +1,134 @@ +From c9db6c26efce63e052b1a35ba1f4d529c2294c93 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:17 +0100 +Subject: [PATCH] xtables: Optimize user-defined chain deletion + +Make use of nftnl_chain_list_lookup_byname() if a chain name was given. +Move the actual chain deleting code into a callback suitable for passing +to nftnl_chain_list_foreach(). + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 0b950ed4549308ef23ffc7561567df86c90cfed9) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 89 ++++++++++++++++++++++++++------------------------ + 1 file changed, 46 insertions(+), 43 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 9951bf3212197..162d91e82115b 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1642,63 +1642,66 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl + #define NLM_F_NONREC 0x100 /* Do not delete recursively */ + #endif + ++struct chain_user_del_data { ++ struct nft_handle *handle; ++ bool verbose; ++ int builtin_err; ++}; ++ ++static int __nft_chain_user_del(struct nftnl_chain *c, void *data) ++{ ++ struct chain_user_del_data *d = data; ++ struct nft_handle *h = d->handle; ++ int ret; ++ ++ /* don't delete built-in chain */ ++ if (nft_chain_builtin(c)) ++ return d->builtin_err; ++ ++ if (d->verbose) ++ fprintf(stdout, "Deleting chain `%s'\n", ++ nftnl_chain_get_str(c, NFTNL_CHAIN_NAME)); ++ ++ ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); ++ if (ret) ++ return -1; ++ ++ nftnl_chain_list_del(c); ++ return 0; ++} ++ + int nft_chain_user_del(struct nft_handle *h, const char *chain, + const char *table, bool verbose) + { ++ struct chain_user_del_data d = { ++ .handle = h, ++ .verbose = verbose, ++ }; + struct nftnl_chain_list *list; +- struct nftnl_chain_list_iter *iter; + struct nftnl_chain *c; + int ret = 0; +- int deleted_ctr = 0; + + nft_fn = nft_chain_user_del; + + list = nft_chain_list_get(h, table); + if (list == NULL) +- goto err; +- +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) +- goto err; +- +- c = nftnl_chain_list_iter_next(iter); +- while (c != NULL) { +- const char *chain_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- +- /* don't delete built-in chain */ +- if (nft_chain_builtin(c)) +- goto next; +- +- if (chain != NULL && strcmp(chain, chain_name) != 0) +- goto next; +- +- if (verbose) +- fprintf(stdout, "Deleting chain `%s'\n", chain); +- +- ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); +- +- if (ret < 0) +- break; +- +- deleted_ctr++; +- nftnl_chain_list_del(c); +- +- if (chain != NULL) +- break; +-next: +- c = nftnl_chain_list_iter_next(iter); +- } +- +- nftnl_chain_list_iter_destroy(iter); +-err: ++ return 0; + +- /* chain not found */ +- if (chain != NULL && deleted_ctr == 0) { +- ret = -1; +- errno = ENOENT; ++ if (chain) { ++ c = nftnl_chain_list_lookup_byname(list, chain); ++ if (!c) { ++ errno = ENOENT; ++ return 0; ++ } ++ d.builtin_err = -2; ++ ret = __nft_chain_user_del(c, &d); ++ if (ret == -2) ++ errno = EINVAL; ++ goto out; + } + ++ ret = nftnl_chain_list_foreach(list, __nft_chain_user_del, &d); ++out: + /* the core expects 1 for success and 0 for error */ + return ret == 0 ? 1 : 0; + } +-- +2.21.0 + diff --git a/SOURCES/0027-xtables-Optimize-list-command-with-given-chain.patch b/SOURCES/0027-xtables-Optimize-list-command-with-given-chain.patch new file mode 100644 index 0000000..88c160f --- /dev/null +++ b/SOURCES/0027-xtables-Optimize-list-command-with-given-chain.patch @@ -0,0 +1,139 @@ +From 8b38ab8ead7829569ab6a3c9fa7a193d568b707a Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:18 +0100 +Subject: [PATCH] xtables: Optimize list command with given chain + +Make use of nftnl_chain_list_lookup_byname() even if not listing a +specific rule. Introduce __nft_print_header() to consolidate chain value +extraction for printing with ops->print_header(). + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 11cbd7291f37fbfd5ebe6ffa1730f7d198ed2ac0) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 78 +++++++++++++++++++++----------------------------- + 1 file changed, 32 insertions(+), 46 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 162d91e82115b..e1c997836cb97 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2247,6 +2247,24 @@ static int nft_rule_count(struct nft_handle *h, struct nftnl_chain *c) + return rule_ctr; + } + ++static void __nft_print_header(struct nft_handle *h, ++ const struct nft_family_ops *ops, ++ struct nftnl_chain *c, unsigned int format) ++{ ++ const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); ++ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); ++ bool basechain = !!nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM); ++ uint32_t refs = nftnl_chain_get_u32(c, NFTNL_CHAIN_USE); ++ uint32_t entries = nft_rule_count(h, c); ++ struct xt_counters ctrs = { ++ .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS), ++ .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES), ++ }; ++ ++ ops->print_header(format, chain_name, policy_name[policy], ++ &ctrs, basechain, refs - entries, entries); ++} ++ + int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + int rulenum, unsigned int format) + { +@@ -2275,75 +2293,43 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + return 0; + } + +- if (chain && rulenum) { +- c = nft_chain_find(h, table, chain); ++ list = nft_chain_list_get(h, table); ++ if (!list) ++ return 0; ++ ++ if (chain) { ++ c = nftnl_chain_list_lookup_byname(list, chain); + if (!c) + return 0; + ++ if (!rulenum) { ++ if (ops->print_table_header) ++ ops->print_table_header(table); ++ __nft_print_header(h, ops, c, format); ++ } + __nft_rule_list(h, c, rulenum, format, ops->print_rule); + return 1; + } + +- list = nft_chain_list_get(h, table); +- if (!list) +- return 0; +- + iter = nftnl_chain_list_iter_create(list); + if (iter == NULL) +- goto err; ++ return 0; + +- if (!chain && ops->print_table_header) ++ if (ops->print_table_header) + ops->print_table_header(table); + + c = nftnl_chain_list_iter_next(iter); + while (c != NULL) { +- const char *chain_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- uint32_t policy = +- nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); +- uint32_t refs = +- nftnl_chain_get_u32(c, NFTNL_CHAIN_USE); +- struct xt_counters ctrs = { +- .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS), +- .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES), +- }; +- bool basechain = false; +- uint32_t entries; +- +- if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM)) +- basechain = true; +- +- if (chain) { +- if (strcmp(chain, chain_name) != 0) +- goto next; +- else if (ops->print_table_header) +- ops->print_table_header(table); +- } +- + if (found) + printf("\n"); + +- entries = nft_rule_count(h, c); +- ops->print_header(format, chain_name, policy_name[policy], +- &ctrs, basechain, refs - entries, entries); +- ++ __nft_print_header(h, ops, c, format); + __nft_rule_list(h, c, rulenum, format, ops->print_rule); + + found = true; +- +- /* we printed the chain we wanted, stop processing. */ +- if (chain) +- break; +- +-next: + c = nftnl_chain_list_iter_next(iter); + } +- + nftnl_chain_list_iter_destroy(iter); +-err: +- if (chain && !found) +- return 0; +- + return 1; + } + +-- +2.21.0 + diff --git a/SOURCES/0028-xtables-Optimize-list-rules-command-with-given-chain.patch b/SOURCES/0028-xtables-Optimize-list-rules-command-with-given-chain.patch new file mode 100644 index 0000000..50971b9 --- /dev/null +++ b/SOURCES/0028-xtables-Optimize-list-rules-command-with-given-chain.patch @@ -0,0 +1,158 @@ +From 23ef58d88034cdd5c972b9392944a772cccd61f9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:19 +0100 +Subject: [PATCH] xtables: Optimize list rules command with given chain + +If a chain name was given, make use of nftnl_chain_list_lookup_byname(). + +Likewise in nftnl_rule_list_chain_save(), but introduce +__nftnl_rule_list_chain_save() suitable for passing to +nftnl_chain_list_foreach(). + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 6b1871914e4f3717c7e6324727b80cf1d5d985b1) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 93 +++++++++++++++++++++++--------------------------- + 1 file changed, 43 insertions(+), 50 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index e1c997836cb97..e0455eabda77a 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2339,46 +2339,44 @@ list_save(struct nftnl_rule *r, unsigned int num, unsigned int format) + nft_rule_print_save(r, NFT_RULE_APPEND, format); + } + ++static int __nftnl_rule_list_chain_save(struct nftnl_chain *c, void *data) ++{ ++ const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); ++ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); ++ int *counters = data; ++ ++ if (!nft_chain_builtin(c)) { ++ printf("-N %s\n", chain_name); ++ return 0; ++ } ++ ++ /* this is a base chain */ ++ ++ printf("-P %s %s", chain_name, policy_name[policy]); ++ if (*counters) ++ printf(" -c %"PRIu64" %"PRIu64, ++ nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS), ++ nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES)); ++ printf("\n"); ++ return 0; ++} ++ + static int + nftnl_rule_list_chain_save(struct nft_handle *h, const char *chain, + struct nftnl_chain_list *list, int counters) + { +- struct nftnl_chain_list_iter *iter; + struct nftnl_chain *c; + +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) +- return 0; +- +- c = nftnl_chain_list_iter_next(iter); +- while (c != NULL) { +- const char *chain_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- uint32_t policy = +- nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); +- +- if (chain && strcmp(chain, chain_name) != 0) +- goto next; ++ if (chain) { ++ c = nftnl_chain_list_lookup_byname(list, chain); ++ if (!c) ++ return 0; + +- /* this is a base chain */ +- if (nft_chain_builtin(c)) { +- printf("-P %s %s", chain_name, policy_name[policy]); +- +- if (counters) { +- printf(" -c %"PRIu64" %"PRIu64"\n", +- nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS), +- nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES)); +- } else +- printf("\n"); +- } else { +- printf("-N %s\n", chain_name); +- } +-next: +- c = nftnl_chain_list_iter_next(iter); ++ __nftnl_rule_list_chain_save(c, &counters); ++ return 1; + } + +- nftnl_chain_list_iter_destroy(iter); +- ++ nftnl_chain_list_foreach(list, __nftnl_rule_list_chain_save, &counters); + return 1; + } + +@@ -2410,41 +2408,36 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + + list = nft_chain_list_get(h, table); + if (!list) +- goto err; ++ return 0; + + /* Dump policies and custom chains first */ + if (!rulenum) + nftnl_rule_list_chain_save(h, chain, list, counters); + +- /* Now dump out rules in this table */ +- iter = nftnl_chain_list_iter_create(list); +- if (iter == NULL) +- goto err; +- + if (counters < 0) + format = FMT_C_COUNTS; + else if (counters == 0) + format = FMT_NOCOUNTS; + +- c = nftnl_chain_list_iter_next(iter); +- while (c != NULL) { +- const char *chain_name = +- nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); ++ if (chain) { ++ c = nftnl_chain_list_lookup_byname(list, chain); ++ if (!c) ++ return 0; + +- if (chain && strcmp(chain, chain_name) != 0) +- goto next; ++ return __nft_rule_list(h, c, rulenum, format, list_save); ++ } + +- ret = __nft_rule_list(h, c, rulenum, format, list_save); ++ /* Now dump out rules in this table */ ++ iter = nftnl_chain_list_iter_create(list); ++ if (iter == NULL) ++ return 0; + +- /* we printed the chain we wanted, stop processing. */ +- if (chain) +- break; +-next: ++ c = nftnl_chain_list_iter_next(iter); ++ while (c != NULL) { ++ ret = __nft_rule_list(h, c, rulenum, format, list_save); + c = nftnl_chain_list_iter_next(iter); + } +- + nftnl_chain_list_iter_destroy(iter); +-err: + return ret; + } + +-- +2.21.0 + diff --git a/SOURCES/0029-nft-Make-use-of-nftnl_rule_lookup_byindex.patch b/SOURCES/0029-nft-Make-use-of-nftnl_rule_lookup_byindex.patch new file mode 100644 index 0000000..43af7dd --- /dev/null +++ b/SOURCES/0029-nft-Make-use-of-nftnl_rule_lookup_byindex.patch @@ -0,0 +1,76 @@ +From 4af07f53926f4bf65caa3804adbadb726e3dc301 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 20 Dec 2018 16:09:20 +0100 +Subject: [PATCH] nft: Make use of nftnl_rule_lookup_byindex() + +Use the function where suitable to potentially speedup rule cache lookup +by rule number. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 039b04896521026d1cb52d60dbacb6ee5226c02d) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index e0455eabda77a..1fd3837f2d334 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1976,27 +1976,21 @@ nft_rule_find(struct nft_handle *h, struct nftnl_chain *c, void *data, int rulen + { + struct nftnl_rule *r; + struct nftnl_rule_iter *iter; +- int rule_ctr = 0; + bool found = false; + ++ if (rulenum >= 0) ++ /* Delete by rule number case */ ++ return nftnl_rule_lookup_byindex(c, rulenum); ++ + iter = nftnl_rule_iter_create(c); + if (iter == NULL) + return 0; + + r = nftnl_rule_iter_next(iter); + while (r != NULL) { +- if (rulenum >= 0) { +- /* Delete by rule number case */ +- if (rule_ctr == rulenum) { +- found = true; +- break; +- } +- } else { +- found = h->ops->rule_find(h->ops, r, data); +- if (found) +- break; +- } +- rule_ctr++; ++ found = h->ops->rule_find(h->ops, r, data); ++ if (found) ++ break; + r = nftnl_rule_iter_next(iter); + } + +@@ -2202,6 +2196,17 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c, + struct nftnl_rule *r; + int rule_ctr = 0; + ++ if (rulenum > 0) { ++ r = nftnl_rule_lookup_byindex(c, rulenum - 1); ++ if (!r) ++ /* iptables-legacy returns 0 when listing for ++ * valid chain but invalid rule number ++ */ ++ return 1; ++ cb(r, rulenum, format); ++ return 1; ++ } ++ + iter = nftnl_rule_iter_create(c); + if (iter == NULL) + return 0; +-- +2.21.0 + diff --git a/SOURCES/0030-nft-Simplify-nft_is_chain_compatible.patch b/SOURCES/0030-nft-Simplify-nft_is_chain_compatible.patch new file mode 100644 index 0000000..cfd7001 --- /dev/null +++ b/SOURCES/0030-nft-Simplify-nft_is_chain_compatible.patch @@ -0,0 +1,80 @@ +From b8d3fdae853c391312b2a0be533fd4a91bf80e8e Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sun, 30 Dec 2018 20:06:08 +0100 +Subject: [PATCH] nft: Simplify nft_is_chain_compatible() + +Make use of nft_{table,chain}_builtin_find() instead of open-coding the +list traversal. Since code is pretty obvious now, drop the comments +added earlier. + +Fixes: e774b15299c27 ("nft: Review is_*_compatible() routines") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit fae77a24634365b18687a5f09357dbf4aaee2bc0) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 34 +++++++++------------------------- + 1 file changed, 9 insertions(+), 25 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 1fd3837f2d334..25e538b7e35d7 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -3077,11 +3077,12 @@ static int nft_is_rule_compatible(struct nftnl_rule *rule, void *data) + + static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) + { +- const struct builtin_chain *chains = NULL, *chain = NULL; +- const char *table, *name, *type; ++ const struct builtin_table *table; ++ const struct builtin_chain *chain; ++ const char *tname, *cname, *type; + struct nft_handle *h = data; + enum nf_inet_hooks hook; +- int i, prio; ++ int prio; + + if (nftnl_rule_foreach(c, nft_is_rule_compatible, NULL)) + return -1; +@@ -3089,33 +3090,16 @@ static int nft_is_chain_compatible(struct nftnl_chain *c, void *data) + if (!nft_chain_builtin(c)) + return 0; + +- /* find chain's table in builtin tables */ +- table = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); +- for (i = 0; i < NFT_TABLE_MAX; i++) { +- const char *cur_table = h->tables[i].name; +- +- if (!cur_table || strcmp(cur_table, table)) +- continue; +- +- chains = h->tables[i].chains; +- break; +- } +- if (!chains) ++ tname = nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE); ++ table = nft_table_builtin_find(h, tname); ++ if (!table) + return -1; + +- /* find chain in builtin chain list */ +- name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- for (i = 0; i < NF_INET_NUMHOOKS && chains[i].name; i++) { +- if (strcmp(name, chains[i].name)) +- continue; +- +- chain = &chains[i]; +- break; +- } ++ cname = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); ++ chain = nft_chain_builtin_find(table, cname); + if (!chain) + return -1; + +- /* compare properties */ + type = nftnl_chain_get_str(c, NFTNL_CHAIN_TYPE); + prio = nftnl_chain_get_u32(c, NFTNL_CHAIN_PRIO); + hook = nftnl_chain_get_u32(c, NFTNL_CHAIN_HOOKNUM); +-- +2.21.0 + diff --git a/SOURCES/0031-nft-Simplify-flush_chain_cache.patch b/SOURCES/0031-nft-Simplify-flush_chain_cache.patch new file mode 100644 index 0000000..9df21bb --- /dev/null +++ b/SOURCES/0031-nft-Simplify-flush_chain_cache.patch @@ -0,0 +1,66 @@ +From 1ad5112b216c46fdf799fa7c8fbf6508f0f4afc9 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sun, 30 Dec 2018 20:06:09 +0100 +Subject: [PATCH] nft: Simplify flush_chain_cache() + +With all the checks for 'tablename' being non-NULL, this code was rather +stupid and really hard to read. And the fix is indeed quite simple: If a +table name was given, use nft_table_builtin_find() and just flush its +chain cache. Otherwise iterate over all builtin tables without any +conditionals for 'tablename'. + +Fixes: d4b0d248cc057 ("nft: Reduce indenting level in flush_chain_cache()") +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 4441b7da7995ed87741164ef39e99f1065eb9637) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 24 +++++++++++------------- + 1 file changed, 11 insertions(+), 13 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 25e538b7e35d7..dafb879ebd6f0 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -793,27 +793,25 @@ static int __flush_chain_cache(struct nftnl_chain *c, void *data) + + static void flush_chain_cache(struct nft_handle *h, const char *tablename) + { ++ const struct builtin_table *table; + int i; + ++ if (tablename) { ++ table = nft_table_builtin_find(h, tablename); ++ if (!table || !h->table[table->type].chain_cache) ++ return; ++ nftnl_chain_list_foreach(h->table[table->type].chain_cache, ++ __flush_chain_cache, NULL); ++ return; ++ } ++ + for (i = 0; i < NFT_TABLE_MAX; i++) { + if (h->tables[i].name == NULL) + continue; + +- if (tablename && strcmp(h->tables[i].name, tablename)) ++ if (!h->table[i].chain_cache) + continue; + +- if (!h->table[i].chain_cache) { +- if (tablename) +- return; +- continue; +- } +- +- if (tablename) { +- nftnl_chain_list_foreach(h->table[i].chain_cache, +- __flush_chain_cache, NULL); +- return; +- } +- + nftnl_chain_list_free(h->table[i].chain_cache); + h->table[i].chain_cache = NULL; + } +-- +2.21.0 + diff --git a/SOURCES/0032-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch b/SOURCES/0032-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch new file mode 100644 index 0000000..7031d52 --- /dev/null +++ b/SOURCES/0032-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch @@ -0,0 +1,68 @@ +From 276b4dba9aa9d52cafe8df2546050d4591ac5b01 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sun, 30 Dec 2018 20:06:10 +0100 +Subject: [PATCH] xtables: Set errno in nft_rule_check() if chain not found + +With this, the explicit check for chain existence can be removed from +xtables.c since all related commands do this now. + +Note that this effectively changes the error message printed by +iptables-nft when given a non-existing chain, but the new error +message(s) conform with those printed by legacy iptables. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 41358d474357a39d616302c03cd7f943e19969a2) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 12 +++++++----- + iptables/xtables.c | 4 ---- + 2 files changed, 7 insertions(+), 9 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index dafb879ebd6f0..1ce1ecdd276be 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2007,17 +2007,19 @@ int nft_rule_check(struct nft_handle *h, const char *chain, + + c = nft_chain_find(h, table, chain); + if (!c) +- return 0; ++ goto fail_enoent; + + r = nft_rule_find(h, c, data, -1); +- if (r == NULL) { +- errno = ENOENT; +- return 0; +- } ++ if (r == NULL) ++ goto fail_enoent; ++ + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); + + return 1; ++fail_enoent: ++ errno = ENOENT; ++ return 0; + } + + int nft_rule_delete(struct nft_handle *h, const char *chain, +diff --git a/iptables/xtables.c b/iptables/xtables.c +index 24a6e234bcf4b..da11e8cc159a0 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -1064,10 +1064,6 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], + p->chain); + } + +- if (!p->xlate && !nft_chain_exists(h, p->table, p->chain)) +- xtables_error(OTHER_PROBLEM, +- "Chain '%s' does not exist", p->chain); +- + if (!p->xlate && !cs->target && strlen(cs->jumpto) > 0 && + !nft_chain_exists(h, p->table, cs->jumpto)) + xtables_error(PARAMETER_PROBLEM, +-- +2.21.0 + diff --git a/SOURCES/0033-xtables-Speed-up-chain-deletion-in-large-rulesets.patch b/SOURCES/0033-xtables-Speed-up-chain-deletion-in-large-rulesets.patch new file mode 100644 index 0000000..a6373e7 --- /dev/null +++ b/SOURCES/0033-xtables-Speed-up-chain-deletion-in-large-rulesets.patch @@ -0,0 +1,34 @@ +From 27bc424993e8138e26d7db1d7f902baaf269dd7c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 12 Dec 2018 20:04:12 +0100 +Subject: [PATCH] xtables: Speed up chain deletion in large rulesets + +Kernel prefers to identify chain by handle if it was given which causes +manual traversal of the chain list. In contrast, chain lookup by name in +kernel makes use of a hash table so is considerably faster. Force this +code path by removing the cached chain's handle when removing it. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit a5f517a41d72794fae3d1332e6e0e413a5cd16c1) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 1ce1ecdd276be..9c0ad9a2d054f 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1660,6 +1660,8 @@ static int __nft_chain_user_del(struct nftnl_chain *c, void *data) + fprintf(stdout, "Deleting chain `%s'\n", + nftnl_chain_get_str(c, NFTNL_CHAIN_NAME)); + ++ /* XXX This triggers a fast lookup from the kernel. */ ++ nftnl_chain_unset(c, NFTNL_CHAIN_HANDLE); + ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_DEL, c); + if (ret) + return -1; +-- +2.21.0 + diff --git a/SOURCES/0034-arptables-nft-Fix-listing-rules-without-target.patch b/SOURCES/0034-arptables-nft-Fix-listing-rules-without-target.patch new file mode 100644 index 0000000..56f8f1b --- /dev/null +++ b/SOURCES/0034-arptables-nft-Fix-listing-rules-without-target.patch @@ -0,0 +1,32 @@ +From 922b572f262469c9332ea9a7f18808033129b017 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:50 +0100 +Subject: [PATCH] arptables-nft: Fix listing rules without target + +Don't try to print cs.jumpto if it is an empty string, otherwise listing +(and verbose output) contains '-j' flag without argument. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 043bf38bc9ee020bbf1a9789773050d47f83b807) +Signed-off-by: Phil Sutter +--- + iptables/nft-arp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index 37850bd328b71..56021223bdbe6 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -598,7 +598,7 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) + + nft_rule_to_iptables_command_state(r, &cs); + +- if (cs.jumpto) ++ if (strlen(cs.jumpto)) + printf("-j %s ", cs.jumpto); + nft_arp_print_rule_details(&cs.arp, format); + print_matches_and_target(&cs, format); +-- +2.21.0 + diff --git a/SOURCES/0035-arptables-nft-Fix-MARK-target-parsing-and-printing.patch b/SOURCES/0035-arptables-nft-Fix-MARK-target-parsing-and-printing.patch new file mode 100644 index 0000000..68c76c7 --- /dev/null +++ b/SOURCES/0035-arptables-nft-Fix-MARK-target-parsing-and-printing.patch @@ -0,0 +1,155 @@ +From 0b6b93e52f2a862c23206f9ad9fc48aadc06fbd2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:51 +0100 +Subject: [PATCH] arptables-nft: Fix MARK target parsing and printing + +Legacy arptables parses mark values in hex no matter if prefixed with +'0x' or not. Sadly, this is not easily achievable with guided option +parser. Hence fall back to the old 'parse' callback. The introduced +target definition is valid only for revision 2, but that's consistent +with legacy arptables. + +When printing, use --set-mark option instead of --set-xmark. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit f7fa88020f3bc4ec646ce2a48731a1f5fa2aa0a9) +Signed-off-by: Phil Sutter +--- + extensions/libxt_MARK.c | 95 +++++++++++++++++++ + .../arptables/0001-arptables-save-restore_0 | 2 +- + 2 files changed, 96 insertions(+), 1 deletion(-) + +diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c +index 43aa977924b12..b765af6c35304 100644 +--- a/extensions/libxt_MARK.c ++++ b/extensions/libxt_MARK.c +@@ -1,3 +1,4 @@ ++#include + #include + #include + #include +@@ -245,6 +246,87 @@ static void mark_tg_save(const void *ip, const struct xt_entry_target *target) + printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask); + } + ++static void mark_tg_arp_save(const void *ip, const struct xt_entry_target *target) ++{ ++ const struct xt_mark_tginfo2 *info = (const void *)target->data; ++ ++ if (info->mark == 0) ++ printf(" --and-mark %x", (unsigned int)(uint32_t)~info->mask); ++ else if (info->mark == info->mask) ++ printf(" --or-mark %x", info->mark); ++ else ++ printf(" --set-mark %x", info->mark); ++} ++ ++static void mark_tg_arp_print(const void *ip, ++ const struct xt_entry_target *target, int numeric) ++{ ++ mark_tg_arp_save(ip, target); ++} ++ ++#define MARK_OPT 1 ++#define AND_MARK_OPT 2 ++#define OR_MARK_OPT 3 ++ ++static struct option mark_tg_arp_opts[] = { ++ { .name = "set-mark", .has_arg = required_argument, .flag = 0, .val = MARK_OPT }, ++ { .name = "and-mark", .has_arg = required_argument, .flag = 0, .val = AND_MARK_OPT }, ++ { .name = "or-mark", .has_arg = required_argument, .flag = 0, .val = OR_MARK_OPT }, ++ { .name = NULL} ++}; ++ ++static int ++mark_tg_arp_parse(int c, char **argv, int invert, unsigned int *flags, ++ const void *entry, struct xt_entry_target **target) ++{ ++ struct xt_mark_tginfo2 *info = ++ (struct xt_mark_tginfo2 *)(*target)->data; ++ int i; ++ ++ switch (c) { ++ case MARK_OPT: ++ if (sscanf(argv[optind-1], "%x", &i) != 1) { ++ xtables_error(PARAMETER_PROBLEM, ++ "Bad mark value `%s'", optarg); ++ return 0; ++ } ++ info->mark = i; ++ if (*flags) ++ xtables_error(PARAMETER_PROBLEM, ++ "MARK: Can't specify --set-mark twice"); ++ *flags = 1; ++ break; ++ case AND_MARK_OPT: ++ if (sscanf(argv[optind-1], "%x", &i) != 1) { ++ xtables_error(PARAMETER_PROBLEM, ++ "Bad mark value `%s'", optarg); ++ return 0; ++ } ++ info->mark = 0; ++ info->mask = ~i; ++ if (*flags) ++ xtables_error(PARAMETER_PROBLEM, ++ "MARK: Can't specify --and-mark twice"); ++ *flags = 1; ++ break; ++ case OR_MARK_OPT: ++ if (sscanf(argv[optind-1], "%x", &i) != 1) { ++ xtables_error(PARAMETER_PROBLEM, ++ "Bad mark value `%s'", optarg); ++ return 0; ++ } ++ info->mark = info->mask = i; ++ if (*flags) ++ xtables_error(PARAMETER_PROBLEM, ++ "MARK: Can't specify --or-mark twice"); ++ *flags = 1; ++ break; ++ default: ++ return 0; ++ } ++ return 1; ++} ++ + static int mark_tg_xlate(struct xt_xlate *xl, + const struct xt_xlate_tg_params *params) + { +@@ -335,6 +417,19 @@ static struct xtables_target mark_tg_reg[] = { + .x6_options = mark_tg_opts, + .xlate = mark_tg_xlate, + }, ++ { ++ .version = XTABLES_VERSION, ++ .name = "MARK", ++ .revision = 2, ++ .family = NFPROTO_ARP, ++ .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)), ++ .help = mark_tg_help, ++ .print = mark_tg_arp_print, ++ .save = mark_tg_arp_save, ++ .parse = mark_tg_arp_parse, ++ .extra_opts = mark_tg_arp_opts, ++ }, + }; + + void _init(void) +diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +index 73b3b0cf88e18..f8629551b0ba9 100755 +--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 ++++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +@@ -47,7 +47,7 @@ DUMP='*filter + -A OUTPUT -o eth432 --h-length 6 --opcode 1 --h-type 1 -j CLASSIFY --set-class feed:babe + -A foo -i lo --h-length 6 --h-type 1 -j ACCEPT + -A foo --h-length 6 --h-type 1 -j ACCEPT +--A foo --h-length 6 --h-type 1 -j MARK --set-xmark 0x3039/0xffffffff ++-A foo --h-length 6 --h-type 1 -j MARK --set-mark 12345 + -A foo --h-length 6 --opcode 1 --h-type 1 -j ACCEPT + -A foo --h-length 6 --h-type 1 --proto-type 0x800 -j ACCEPT + -A foo -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 -j ACCEPT +-- +2.21.0 + diff --git a/SOURCES/0036-arptables-nft-Fix-CLASSIFY-target-printing.patch b/SOURCES/0036-arptables-nft-Fix-CLASSIFY-target-printing.patch new file mode 100644 index 0000000..a2a9671 --- /dev/null +++ b/SOURCES/0036-arptables-nft-Fix-CLASSIFY-target-printing.patch @@ -0,0 +1,99 @@ +From fabed9f23311cdf42180613123309307b5c6add5 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:52 +0100 +Subject: [PATCH] arptables-nft: Fix CLASSIFY target printing + +In legacy arptables, CLASSIFY target is not printed with fixed hex +number lengths. Counter this by introducing a dedicated target +definition for NFPROTO_ARP only having own print/save callbacks. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 756bea26a3dad89c467c703725ce6d3c6b29c871) +Signed-off-by: Phil Sutter +--- + extensions/libxt_CLASSIFY.c | 59 +++++++++++++++++++++++++++++-------- + 1 file changed, 46 insertions(+), 13 deletions(-) + +diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c +index f90082dc7c50e..75aaf0c41b61a 100644 +--- a/extensions/libxt_CLASSIFY.c ++++ b/extensions/libxt_CLASSIFY.c +@@ -73,6 +73,24 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target) + TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority)); + } + ++static void ++CLASSIFY_arp_save(const void *ip, const struct xt_entry_target *target) ++{ ++ const struct xt_classify_target_info *clinfo = ++ (const struct xt_classify_target_info *)target->data; ++ ++ printf(" --set-class %x:%x", ++ TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority)); ++} ++ ++static void ++CLASSIFY_arp_print(const void *ip, ++ const struct xt_entry_target *target, ++ int numeric) ++{ ++ CLASSIFY_arp_save(ip, target); ++} ++ + static int CLASSIFY_xlate(struct xt_xlate *xl, + const struct xt_xlate_tg_params *params) + { +@@ -98,21 +116,36 @@ static int CLASSIFY_xlate(struct xt_xlate *xl, + return 1; + } + +-static struct xtables_target classify_target = { +- .family = NFPROTO_UNSPEC, +- .name = "CLASSIFY", +- .version = XTABLES_VERSION, +- .size = XT_ALIGN(sizeof(struct xt_classify_target_info)), +- .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)), +- .help = CLASSIFY_help, +- .print = CLASSIFY_print, +- .save = CLASSIFY_save, +- .x6_parse = CLASSIFY_parse, +- .x6_options = CLASSIFY_opts, +- .xlate = CLASSIFY_xlate, ++static struct xtables_target classify_tg_reg[] = { ++ { ++ .family = NFPROTO_UNSPEC, ++ .name = "CLASSIFY", ++ .version = XTABLES_VERSION, ++ .size = XT_ALIGN(sizeof(struct xt_classify_target_info)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)), ++ .help = CLASSIFY_help, ++ .print = CLASSIFY_print, ++ .save = CLASSIFY_save, ++ .x6_parse = CLASSIFY_parse, ++ .x6_options = CLASSIFY_opts, ++ .xlate = CLASSIFY_xlate, ++ }, ++ { ++ .family = NFPROTO_ARP, ++ .name = "CLASSIFY", ++ .version = XTABLES_VERSION, ++ .size = XT_ALIGN(sizeof(struct xt_classify_target_info)), ++ .userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)), ++ .help = CLASSIFY_help, ++ .print = CLASSIFY_arp_print, ++ .save = CLASSIFY_arp_save, ++ .x6_parse = CLASSIFY_parse, ++ .x6_options = CLASSIFY_opts, ++ .xlate = CLASSIFY_xlate, ++ } + }; + + void _init(void) + { +- xtables_register_target(&classify_target); ++ xtables_register_targets(classify_tg_reg, ARRAY_SIZE(classify_tg_reg)); + } +-- +2.21.0 + diff --git a/SOURCES/0037-arptables-nft-Remove-space-between-cnt-and-value.patch b/SOURCES/0037-arptables-nft-Remove-space-between-cnt-and-value.patch new file mode 100644 index 0000000..b60ec8f --- /dev/null +++ b/SOURCES/0037-arptables-nft-Remove-space-between-cnt-and-value.patch @@ -0,0 +1,35 @@ +From 44e633b17e257f1915c4b33d9249f2e45f0a39cc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:53 +0100 +Subject: [PATCH] arptables-nft: Remove space between *cnt= and value + +When printing rule counters, call xtables_print_num() with FMT_NOTABLE +bit set to avoid spaces between equal sign and value. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 9421327926a529ec8300d37f3be8a6cfab701786) +Signed-off-by: Phil Sutter +--- + iptables/nft-arp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index 56021223bdbe6..f357fc4a43c4c 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -605,9 +605,9 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) + + if (!(format & FMT_NOCOUNTS)) { + printf(", pcnt="); +- xtables_print_num(cs.counters.pcnt, format); ++ xtables_print_num(cs.counters.pcnt, format | FMT_NOTABLE); + printf("-- bcnt="); +- xtables_print_num(cs.counters.bcnt, format); ++ xtables_print_num(cs.counters.bcnt, format | FMT_NOTABLE); + } + + if (!(format & FMT_NONEWLINE)) +-- +2.21.0 + diff --git a/SOURCES/0038-arptables-nft-save-Fix-position-of-j-option.patch b/SOURCES/0038-arptables-nft-save-Fix-position-of-j-option.patch new file mode 100644 index 0000000..d812306 --- /dev/null +++ b/SOURCES/0038-arptables-nft-save-Fix-position-of-j-option.patch @@ -0,0 +1,296 @@ +From f521f424e5ab298d0dd2146677ea4f0170a9dfd0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:54 +0100 +Subject: [PATCH] arptables-nft-save: Fix position of -j option + +Legacy arptables-save (just like arptables itself) prints verdict as +first option, then matches and finally any target options. + +To achieve this without introducing double/trailing spaces everywhere, +integrate target ('-j') option printing into +nft_arp_print_rule_details() and make it print separating whitespace +before each option. + +In nft_arp_save_rule(), replace the call to save_matches_and_target() by +by a direct call to cs->target->save() since the former prints '-j' +option itself. Since there are no match extensions in arptables, any +other code from that function is not needed. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 2c3f7a2cd6fd8325b3a84e280cce945c6c20b87f) +Signed-off-by: Phil Sutter +--- + iptables/nft-arp.c | 65 +++++++++++-------- + .../arptables/0001-arptables-save-restore_0 | 32 ++++----- + .../0002-arptables-restore-defaults_0 | 6 +- + 3 files changed, 58 insertions(+), 45 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index f357fc4a43c4c..2cbdf23214049 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -434,14 +434,21 @@ static void nft_arp_print_header(unsigned int format, const char *chain, + } + } + +-static void nft_arp_print_rule_details(const struct arpt_entry *fw, ++static void nft_arp_print_rule_details(const struct iptables_command_state *cs, + unsigned int format) + { ++ const struct arpt_entry *fw = &cs->arp; + char buf[BUFSIZ]; + char iface[IFNAMSIZ+2]; ++ const char *sep = ""; + int print_iface = 0; + int i; + ++ if (strlen(cs->jumpto)) { ++ printf("%s-j %s", sep, cs->jumpto); ++ sep = " "; ++ } ++ + iface[0] = '\0'; + + if (fw->arp.iniface[0] != '\0') { +@@ -453,9 +460,11 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw, + if (format & FMT_NUMERIC) strcat(iface, "*"); + else strcat(iface, "any"); + } +- if (print_iface) +- printf("%s-i %s ", fw->arp.invflags & ARPT_INV_VIA_IN ? ++ if (print_iface) { ++ printf("%s%s-i %s", sep, fw->arp.invflags & ARPT_INV_VIA_IN ? + "! " : "", iface); ++ sep = " "; ++ } + + print_iface = 0; + iface[0] = '\0'; +@@ -469,12 +478,14 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw, + if (format & FMT_NUMERIC) strcat(iface, "*"); + else strcat(iface, "any"); + } +- if (print_iface) +- printf("%s-o %s ", fw->arp.invflags & ARPT_INV_VIA_OUT ? ++ if (print_iface) { ++ printf("%s%s-o %s", sep, fw->arp.invflags & ARPT_INV_VIA_OUT ? + "! " : "", iface); ++ sep = " "; ++ } + + if (fw->arp.smsk.s_addr != 0L) { +- printf("%s", fw->arp.invflags & ARPT_INV_SRCIP ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCIP + ? "! " : ""); + if (format & FMT_NUMERIC) + sprintf(buf, "%s", addr_to_dotted(&(fw->arp.src))); +@@ -482,7 +493,8 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw, + sprintf(buf, "%s", addr_to_anyname(&(fw->arp.src))); + strncat(buf, mask_to_dotted(&(fw->arp.smsk)), + sizeof(buf) - strlen(buf) - 1); +- printf("-s %s ", buf); ++ printf("-s %s", buf); ++ sep = " "; + } + + for (i = 0; i < ARPT_DEV_ADDR_LEN_MAX; i++) +@@ -490,16 +502,16 @@ static void nft_arp_print_rule_details(const struct arpt_entry *fw, + break; + if (i == ARPT_DEV_ADDR_LEN_MAX) + goto after_devsrc; +- printf("%s", fw->arp.invflags & ARPT_INV_SRCDEVADDR ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_SRCDEVADDR + ? "! " : ""); + printf("--src-mac "); + print_mac_and_mask((unsigned char *)fw->arp.src_devaddr.addr, + (unsigned char *)fw->arp.src_devaddr.mask, ETH_ALEN); +- printf(" "); ++ sep = " "; + after_devsrc: + + if (fw->arp.tmsk.s_addr != 0L) { +- printf("%s", fw->arp.invflags & ARPT_INV_TGTIP ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTIP + ? "! " : ""); + if (format & FMT_NUMERIC) + sprintf(buf, "%s", addr_to_dotted(&(fw->arp.tgt))); +@@ -507,7 +519,8 @@ after_devsrc: + sprintf(buf, "%s", addr_to_anyname(&(fw->arp.tgt))); + strncat(buf, mask_to_dotted(&(fw->arp.tmsk)), + sizeof(buf) - strlen(buf) - 1); +- printf("-d %s ", buf); ++ printf("-d %s", buf); ++ sep = " "; + } + + for (i = 0; i arp.invflags & ARPT_INV_TGTDEVADDR ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_TGTDEVADDR + ? "! " : ""); + printf("--dst-mac "); + print_mac_and_mask((unsigned char *)fw->arp.tgt_devaddr.addr, + (unsigned char *)fw->arp.tgt_devaddr.mask, ETH_ALEN); +- printf(" "); ++ sep = " "; + + after_devdst: + + if (fw->arp.arhln_mask != 0) { +- printf("%s", fw->arp.invflags & ARPT_INV_ARPHLN ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHLN + ? "! " : ""); + printf("--h-length %d", fw->arp.arhln); + if (fw->arp.arhln_mask != 255) + printf("/%d", fw->arp.arhln_mask); +- printf(" "); ++ sep = " "; + } + + if (fw->arp.arpop_mask != 0) { + int tmp = ntohs(fw->arp.arpop); + +- printf("%s", fw->arp.invflags & ARPT_INV_ARPOP ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPOP + ? "! " : ""); + if (tmp <= NUMOPCODES && !(format & FMT_NUMERIC)) + printf("--opcode %s", opcodes[tmp-1]); +@@ -545,13 +558,13 @@ after_devdst: + + if (fw->arp.arpop_mask != 65535) + printf("/%d", ntohs(fw->arp.arpop_mask)); +- printf(" "); ++ sep = " "; + } + + if (fw->arp.arhrd_mask != 0) { + uint16_t tmp = ntohs(fw->arp.arhrd); + +- printf("%s", fw->arp.invflags & ARPT_INV_ARPHRD ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHRD + ? "! " : ""); + if (tmp == 1 && !(format & FMT_NUMERIC)) + printf("--h-type %s", "Ethernet"); +@@ -559,13 +572,13 @@ after_devdst: + printf("--h-type %u", tmp); + if (fw->arp.arhrd_mask != 65535) + printf("/%d", ntohs(fw->arp.arhrd_mask)); +- printf(" "); ++ sep = " "; + } + + if (fw->arp.arpro_mask != 0) { + int tmp = ntohs(fw->arp.arpro); + +- printf("%s", fw->arp.invflags & ARPT_INV_ARPPRO ++ printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPPRO + ? "! " : ""); + if (tmp == 0x0800 && !(format & FMT_NUMERIC)) + printf("--proto-type %s", "IPv4"); +@@ -573,7 +586,7 @@ after_devdst: + printf("--proto-type 0x%x", tmp); + if (fw->arp.arpro_mask != 65535) + printf("/%x", ntohs(fw->arp.arpro_mask)); +- printf(" "); ++ sep = " "; + } + } + +@@ -584,8 +597,10 @@ nft_arp_save_rule(const void *data, unsigned int format) + + format |= FMT_NUMERIC; + +- nft_arp_print_rule_details(&cs->arp, format); +- save_matches_and_target(cs, false, &cs->arp, format); ++ nft_arp_print_rule_details(cs, format); ++ if (cs->target && cs->target->save) ++ cs->target->save(&cs->fw, cs->target->t); ++ printf("\n"); + } + + static void +@@ -598,9 +613,7 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) + + nft_rule_to_iptables_command_state(r, &cs); + +- if (strlen(cs.jumpto)) +- printf("-j %s ", cs.jumpto); +- nft_arp_print_rule_details(&cs.arp, format); ++ nft_arp_print_rule_details(&cs, format); + print_matches_and_target(&cs, format); + + if (!(format & FMT_NOCOUNTS)) { +diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +index f8629551b0ba9..0664e3b38d5e8 100755 +--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 ++++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +@@ -35,22 +35,22 @@ DUMP='*filter + :INPUT ACCEPT + :OUTPUT DROP + :foo - +--A INPUT -s 10.0.0.0/8 --h-length 6 --h-type 1 -j ACCEPT +--A INPUT -d 192.168.123.1 --h-length 6 --h-type 1 -j ACCEPT +--A INPUT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 -j ACCEPT +--A INPUT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 -j ACCEPT +--A INPUT --h-length 6 --h-type 1 -j foo +--A INPUT --h-length 6 --h-type 1 +--A OUTPUT -o lo --h-length 6 --h-type 1 -j ACCEPT +--A OUTPUT -o eth134 --h-length 6 --h-type 1 -j mangle --mangle-ip-s 10.0.0.1 +--A OUTPUT -o eth432 --h-length 6 --h-type 1 -j CLASSIFY --set-class feed:babe +--A OUTPUT -o eth432 --h-length 6 --opcode 1 --h-type 1 -j CLASSIFY --set-class feed:babe +--A foo -i lo --h-length 6 --h-type 1 -j ACCEPT +--A foo --h-length 6 --h-type 1 -j ACCEPT +--A foo --h-length 6 --h-type 1 -j MARK --set-mark 12345 +--A foo --h-length 6 --opcode 1 --h-type 1 -j ACCEPT +--A foo --h-length 6 --h-type 1 --proto-type 0x800 -j ACCEPT +--A foo -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 -j ACCEPT ++-A INPUT -j ACCEPT -s 10.0.0.0/8 --h-length 6 --h-type 1 ++-A INPUT -j ACCEPT -d 192.168.123.1 --h-length 6 --h-type 1 ++-A INPUT -j ACCEPT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 ++-A INPUT -j ACCEPT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 ++-A INPUT -j foo --h-length 6 --h-type 1 ++-A INPUT --h-length 6 --h-type 1 ++-A OUTPUT -j ACCEPT -o lo --h-length 6 --h-type 1 ++-A OUTPUT -j mangle -o eth134 --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1 ++-A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --h-type 1 --set-class feed:babe ++-A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --opcode 1 --h-type 1 --set-class feed:babe ++-A foo -j ACCEPT -i lo --h-length 6 --h-type 1 ++-A foo -j ACCEPT --h-length 6 --h-type 1 ++-A foo -j MARK --h-length 6 --h-type 1 --set-mark 12345 ++-A foo -j ACCEPT --h-length 6 --opcode 1 --h-type 1 ++-A foo -j ACCEPT --h-length 6 --h-type 1 --proto-type 0x800 ++-A foo -j ACCEPT -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 + ' + + diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save) +diff --git a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 +index ee17da0023b82..d742c3d506305 100755 +--- a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 ++++ b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 +@@ -11,7 +11,7 @@ set -e + DUMP='*filter + :OUTPUT ACCEPT + -A OUTPUT -j mangle --mangle-ip-s 10.0.0.1 +--A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-d 10.0.0.2 ++-A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2 + ' + + # note how mangle-ip-s is unset in second rule +@@ -19,8 +19,8 @@ DUMP='*filter + EXPECT='*filter + :INPUT ACCEPT + :OUTPUT ACCEPT +--A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-s 10.0.0.1 +--A OUTPUT --h-length 6 --h-type 1 -j mangle --mangle-ip-d 10.0.0.2 ++-A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1 ++-A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2 + ' + + $XT_MULTI arptables -F +-- +2.21.0 + diff --git a/SOURCES/0039-arptables-nft-Don-t-print-default-h-len-h-type-value.patch b/SOURCES/0039-arptables-nft-Don-t-print-default-h-len-h-type-value.patch new file mode 100644 index 0000000..83234ca --- /dev/null +++ b/SOURCES/0039-arptables-nft-Don-t-print-default-h-len-h-type-value.patch @@ -0,0 +1,116 @@ +From 3013545255719fcda031c227570c498c4fc7cc35 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:55 +0100 +Subject: [PATCH] arptables-nft: Don't print default h-len/h-type values + +Default values for --h-len and --h-type being printed for rules where +user didn't provide them is unexpected and confusing. The drawback is +the opposite: If user provided either of them with their default value, +they are later omitted when listing rules. Though since unlike legacy +arptables we can't distinguish between not specified and specified with +default value, we can't fix both - so choose to optimize for the more +likely case. + +Fixes: 5aecb2d8bfdda ("arptables: pre-init hlen and ethertype") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 84331e3ed3f8eb9d53c00c221113ad16b209968a) +Signed-off-by: Phil Sutter +--- + iptables/nft-arp.c | 4 +-- + .../arptables/0001-arptables-save-restore_0 | 32 +++++++++---------- + .../0002-arptables-restore-defaults_0 | 6 ++-- + 3 files changed, 21 insertions(+), 21 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index 2cbdf23214049..37b0985377bef 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -537,7 +537,7 @@ after_devsrc: + + after_devdst: + +- if (fw->arp.arhln_mask != 0) { ++ if (fw->arp.arhln_mask != 255 || fw->arp.arhln != 6) { + printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHLN + ? "! " : ""); + printf("--h-length %d", fw->arp.arhln); +@@ -561,7 +561,7 @@ after_devdst: + sep = " "; + } + +- if (fw->arp.arhrd_mask != 0) { ++ if (fw->arp.arhrd_mask != 65535 || fw->arp.arhrd != htons(1)) { + uint16_t tmp = ntohs(fw->arp.arhrd); + + printf("%s%s", sep, fw->arp.invflags & ARPT_INV_ARPHRD +diff --git a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +index 0664e3b38d5e8..e10f61cc8f95b 100755 +--- a/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 ++++ b/iptables/tests/shell/testcases/arptables/0001-arptables-save-restore_0 +@@ -35,22 +35,22 @@ DUMP='*filter + :INPUT ACCEPT + :OUTPUT DROP + :foo - +--A INPUT -j ACCEPT -s 10.0.0.0/8 --h-length 6 --h-type 1 +--A INPUT -j ACCEPT -d 192.168.123.1 --h-length 6 --h-type 1 +--A INPUT -j ACCEPT --src-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 +--A INPUT -j ACCEPT --dst-mac fe:ed:ba:be:00:01 --h-length 6 --h-type 1 +--A INPUT -j foo --h-length 6 --h-type 1 +--A INPUT --h-length 6 --h-type 1 +--A OUTPUT -j ACCEPT -o lo --h-length 6 --h-type 1 +--A OUTPUT -j mangle -o eth134 --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1 +--A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --h-type 1 --set-class feed:babe +--A OUTPUT -j CLASSIFY -o eth432 --h-length 6 --opcode 1 --h-type 1 --set-class feed:babe +--A foo -j ACCEPT -i lo --h-length 6 --h-type 1 +--A foo -j ACCEPT --h-length 6 --h-type 1 +--A foo -j MARK --h-length 6 --h-type 1 --set-mark 12345 +--A foo -j ACCEPT --h-length 6 --opcode 1 --h-type 1 +--A foo -j ACCEPT --h-length 6 --h-type 1 --proto-type 0x800 +--A foo -j ACCEPT -i lo --h-length 6 --opcode 1 --h-type 1 --proto-type 0x800 ++-A INPUT -j ACCEPT -s 10.0.0.0/8 ++-A INPUT -j ACCEPT -d 192.168.123.1 ++-A INPUT -j ACCEPT --src-mac fe:ed:ba:be:00:01 ++-A INPUT -j ACCEPT --dst-mac fe:ed:ba:be:00:01 ++-A INPUT -j foo ++-A INPUT ++-A OUTPUT -j ACCEPT -o lo ++-A OUTPUT -j mangle -o eth134 --mangle-ip-s 10.0.0.1 ++-A OUTPUT -j CLASSIFY -o eth432 --set-class feed:babe ++-A OUTPUT -j CLASSIFY -o eth432 --opcode 1 --set-class feed:babe ++-A foo -j ACCEPT -i lo ++-A foo -j ACCEPT ++-A foo -j MARK --set-mark 12345 ++-A foo -j ACCEPT --opcode 1 ++-A foo -j ACCEPT --proto-type 0x800 ++-A foo -j ACCEPT -i lo --opcode 1 --proto-type 0x800 + ' + + diff -u <(echo -e "$DUMP") <($XT_MULTI arptables-save) +diff --git a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 +index d742c3d506305..b2ed95e87bb40 100755 +--- a/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 ++++ b/iptables/tests/shell/testcases/arptables/0002-arptables-restore-defaults_0 +@@ -11,7 +11,7 @@ set -e + DUMP='*filter + :OUTPUT ACCEPT + -A OUTPUT -j mangle --mangle-ip-s 10.0.0.1 +--A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2 ++-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2 + ' + + # note how mangle-ip-s is unset in second rule +@@ -19,8 +19,8 @@ DUMP='*filter + EXPECT='*filter + :INPUT ACCEPT + :OUTPUT ACCEPT +--A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-s 10.0.0.1 +--A OUTPUT -j mangle --h-length 6 --h-type 1 --mangle-ip-d 10.0.0.2 ++-A OUTPUT -j mangle --mangle-ip-s 10.0.0.1 ++-A OUTPUT -j mangle --mangle-ip-d 10.0.0.2 + ' + + $XT_MULTI arptables -F +-- +2.21.0 + diff --git a/SOURCES/0040-tests-shell-Add-arptables-nft-verbose-output-test.patch b/SOURCES/0040-tests-shell-Add-arptables-nft-verbose-output-test.patch new file mode 100644 index 0000000..1543610 --- /dev/null +++ b/SOURCES/0040-tests-shell-Add-arptables-nft-verbose-output-test.patch @@ -0,0 +1,90 @@ +From bf2b28732579e44bf4c77869be586ee7d73bdabb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 31 Jan 2019 16:12:56 +0100 +Subject: [PATCH] tests: shell: Add arptables-nft verbose output test + +With arptables-nft output being in a very good state now, add a test to +ensure it stays that way. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 3d8f261c565a024c13d627b18a0fcafc76de8f2c) +Signed-off-by: Phil Sutter +--- + .../arptables/0003-arptables-verbose-output_0 | 64 +++++++++++++++++++ + 1 file changed, 64 insertions(+) + create mode 100755 iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 + +diff --git a/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 +new file mode 100755 +index 0000000000000..35126fa7d717c +--- /dev/null ++++ b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 +@@ -0,0 +1,64 @@ ++#!/bin/bash ++ ++set -e ++set -x ++ ++# there is no legacy backend to test ++[[ $XT_MULTI == */xtables-nft-multi ]] || { echo "skip $XT_MULTI"; exit 0; } ++ ++$XT_MULTI arptables -N foo ++ ++# check verbose output matches expectations ++ ++RULE1='-i eth23 -j ACCEPT' ++VOUT1='-j ACCEPT -i eth23 -o *' ++ ++RULE2='-i eth23' ++VOUT2='-i eth23 -o *' ++ ++RULE3='-i eth23 -j MARK --set-mark 42' ++VOUT3='-j MARK -i eth23 -o * --set-mark 42' ++ ++RULE4='-o eth23 -j CLASSIFY --set-class 23:42' ++VOUT4='-j CLASSIFY -i * -o eth23 --set-class 23:42' ++ ++RULE5='-o eth23 -j foo' ++VOUT5='-j foo -i * -o eth23' ++ ++RULE6='-o eth23 -j mangle --mangle-ip-s 10.0.0.1' ++VOUT6='-j mangle -i * -o eth23 --mangle-ip-s 10.0.0.1' ++ ++diff -u -Z <(echo -e "$VOUT1") <($XT_MULTI arptables -v -A INPUT $RULE1) ++diff -u -Z <(echo -e "$VOUT2") <($XT_MULTI arptables -v -A INPUT $RULE2) ++diff -u -Z <(echo -e "$VOUT3") <($XT_MULTI arptables -v -A INPUT $RULE3) ++diff -u -Z <(echo -e "$VOUT4") <($XT_MULTI arptables -v -A OUTPUT $RULE4) ++diff -u -Z <(echo -e "$VOUT5") <($XT_MULTI arptables -v -A OUTPUT $RULE5) ++diff -u -Z <(echo -e "$VOUT6") <($XT_MULTI arptables -v -A foo $RULE6) ++ ++EXPECT='Chain INPUT (policy ACCEPT 0 packets, 0 bytes) ++-j ACCEPT -i eth23 -o *, pcnt=0 -- bcnt=0 ++-i eth23 -o *, pcnt=0 -- bcnt=0 ++-j MARK -i eth23 -o * --set-mark 42, pcnt=0 -- bcnt=0 ++ ++Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes) ++-j CLASSIFY -i * -o eth23 --set-class 23:42, pcnt=0 -- bcnt=0 ++-j foo -i * -o eth23, pcnt=0 -- bcnt=0 ++ ++Chain foo (1 references) ++-j mangle -i * -o eth23 --mangle-ip-s 10.0.0.1, pcnt=0 -- bcnt=0' ++ ++diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI arptables -v -n -L) ++ ++EXPECT='*filter ++:INPUT ACCEPT ++:OUTPUT ACCEPT ++:foo - ++-A INPUT -j ACCEPT -i eth23 ++-A INPUT -i eth23 ++-A INPUT -j MARK -i eth23 --set-mark 42 ++-A OUTPUT -j CLASSIFY -o eth23 --set-class 23:42 ++-A OUTPUT -j foo -o eth23 ++-A foo -j mangle -o eth23 --mangle-ip-s 10.0.0.1 ++' ++ ++diff -u -Z <(echo -e "$EXPECT") <($XT_MULTI arptables-save) +-- +2.21.0 + diff --git a/SOURCES/0041-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch b/SOURCES/0041-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch new file mode 100644 index 0000000..dd26985 --- /dev/null +++ b/SOURCES/0041-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch @@ -0,0 +1,40 @@ +From 2fb13e8bdc9649c3910c6c1341dc4dd483767c0c Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 1 Feb 2019 17:06:18 +0100 +Subject: [PATCH] arptables-nft: Set h-type/h-length masks by default, too + +These masks are not used in nftables backend, but mangle extension +checks arhln_mask value to make sure --h-length was given (which is +implicitly the case). + +Fixes: 5aecb2d8bfdda ("arptables: pre-init hlen and ethertype") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit a1da179b0ff3783badca352a42808f4398dd1a98) +Signed-off-by: Phil Sutter +--- + iptables/xtables-arp.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c +index 819e7e6c94034..2dce1a52f16fd 100644 +--- a/iptables/xtables-arp.c ++++ b/iptables/xtables-arp.c +@@ -909,8 +909,12 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table, + { + struct iptables_command_state cs = { + .jumpto = "", +- .arp.arp.arhln = 6, +- .arp.arp.arhrd = htons(ARPHRD_ETHER), ++ .arp.arp = { ++ .arhln = 6, ++ .arhln_mask = 255, ++ .arhrd = htons(ARPHRD_ETHER), ++ .arhrd_mask = 65535, ++ }, + }; + int invert = 0; + unsigned int nsaddrs = 0, ndaddrs = 0; +-- +2.21.0 + diff --git a/SOURCES/0042-nft-Add-new-builtin-chains-to-cache-immediately.patch b/SOURCES/0042-nft-Add-new-builtin-chains-to-cache-immediately.patch new file mode 100644 index 0000000..4d2ba27 --- /dev/null +++ b/SOURCES/0042-nft-Add-new-builtin-chains-to-cache-immediately.patch @@ -0,0 +1,95 @@ +From e3dacaff9e1d6f5be93afeb705cd24b38c8ff6f2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 15 Jan 2019 23:23:03 +0100 +Subject: [PATCH] nft: Add new builtin chains to cache immediately + +Newly created builtin chains missing from cache was the sole reason for +the immediate calls to nft_commit(). With nft_chain_builtin_add() +inserting the new chain into the table's chain list, this is not needed +anymore. Just make sure batch_obj_del() doesn't free the payload of +NFT_COMPAT_CHAIN_ADD jobs since it contains the new chain which has +been added to cache. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 2b801fc515ae094d04207e840ed191196292b968) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 30 +++++++++--------------------- + 1 file changed, 9 insertions(+), 21 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 9c0ad9a2d054f..c2af1a6fd0985 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -644,6 +644,7 @@ static void nft_chain_builtin_add(struct nft_handle *h, + return; + + batch_chain_add(h, NFT_COMPAT_CHAIN_ADD, c); ++ nftnl_chain_list_add_tail(c, h->table[table->type].chain_cache); + } + + /* find if built-in table already exists */ +@@ -1216,8 +1217,11 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, + h->ops->print_rule(r, 0, FMT_PRINT_RULE); + + c = nft_chain_find(h, table, chain); +- if (c) +- nftnl_chain_rule_add_tail(r, c); ++ if (!c) { ++ errno = ENOENT; ++ return 0; ++ } ++ nftnl_chain_rule_add_tail(r, c); + + return 1; + } +@@ -2282,16 +2286,8 @@ int nft_rule_list(struct nft_handle *h, const char *chain, const char *table, + bool found = false; + + /* If built-in chains don't exist for this table, create them */ +- if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) { ++ if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) + nft_xt_builtin_init(h, table); +- /* Force table and chain creation, otherwise first iptables -L +- * lists no table/chains. +- */ +- if (!list_empty(&h->obj_list)) { +- nft_commit(h); +- flush_chain_cache(h, NULL); +- } +- } + + ops = nft_family_ops_lookup(h->family); + +@@ -2397,16 +2393,8 @@ int nft_rule_list_save(struct nft_handle *h, const char *chain, + int ret = 0; + + /* If built-in chains don't exist for this table, create them */ +- if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) { ++ if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) + nft_xt_builtin_init(h, table); +- /* Force table and chain creation, otherwise first iptables -L +- * lists no table/chains. +- */ +- if (!list_empty(&h->obj_list)) { +- nft_commit(h); +- flush_chain_cache(h, NULL); +- } +- } + + if (!nft_is_table_compatible(h, table)) { + xtables_error(OTHER_PROBLEM, "table `%s' is incompatible, use 'nft' tool.\n", table); +@@ -2525,8 +2513,8 @@ static void batch_obj_del(struct nft_handle *h, struct obj_update *o) + break; + case NFT_COMPAT_CHAIN_ZERO: + case NFT_COMPAT_CHAIN_USER_ADD: +- break; + case NFT_COMPAT_CHAIN_ADD: ++ break; + case NFT_COMPAT_CHAIN_USER_DEL: + case NFT_COMPAT_CHAIN_USER_FLUSH: + case NFT_COMPAT_CHAIN_UPDATE: +-- +2.21.0 + diff --git a/SOURCES/0043-xtables-Fix-position-of-replaced-rules-in-cache.patch b/SOURCES/0043-xtables-Fix-position-of-replaced-rules-in-cache.patch new file mode 100644 index 0000000..3f2f7e6 --- /dev/null +++ b/SOURCES/0043-xtables-Fix-position-of-replaced-rules-in-cache.patch @@ -0,0 +1,168 @@ +From 892eaf39a4bd14ad25e55e5c0d4ef3dc163183da Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 15 Jan 2019 23:23:04 +0100 +Subject: [PATCH] xtables: Fix position of replaced rules in cache + +When replacing a rule, the replacement was simply appended to the +chain's rule list. Instead, insert it where the rule it replaces was. + +This also fixes for zero counters command to remove the old rule from +cache. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 5ca9acf51adf9dcc8e0d82cd8f5b9b2514f900ee) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 34 +++++++++++++++++----------------- + iptables/nft.h | 2 +- + iptables/xtables-arp.c | 2 +- + iptables/xtables-eb.c | 2 +- + iptables/xtables.c | 4 ++-- + 5 files changed, 22 insertions(+), 22 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index c2af1a6fd0985..76764fde4e9fb 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1186,7 +1186,7 @@ nft_chain_find(struct nft_handle *h, const char *table, const char *chain); + + int + nft_rule_append(struct nft_handle *h, const char *chain, const char *table, +- void *data, uint64_t handle, bool verbose) ++ void *data, struct nftnl_rule *ref, bool verbose) + { + struct nftnl_chain *c; + struct nftnl_rule *r; +@@ -1202,8 +1202,9 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, + if (r == NULL) + return 0; + +- if (handle > 0) { +- nftnl_rule_set(r, NFTNL_RULE_HANDLE, &handle); ++ if (ref) { ++ nftnl_rule_set_u64(r, NFTNL_RULE_HANDLE, ++ nftnl_rule_get_u64(ref, NFTNL_RULE_HANDLE)); + type = NFT_COMPAT_RULE_REPLACE; + } else + type = NFT_COMPAT_RULE_APPEND; +@@ -1216,12 +1217,17 @@ nft_rule_append(struct nft_handle *h, const char *chain, const char *table, + if (verbose) + h->ops->print_rule(r, 0, FMT_PRINT_RULE); + +- c = nft_chain_find(h, table, chain); +- if (!c) { +- errno = ENOENT; +- return 0; ++ if (ref) { ++ nftnl_chain_rule_insert_at(r, ref); ++ nftnl_chain_rule_del(r); ++ } else { ++ c = nft_chain_find(h, table, chain); ++ if (!c) { ++ errno = ENOENT; ++ return 0; ++ } ++ nftnl_chain_rule_add_tail(r, c); + } +- nftnl_chain_rule_add_tail(r, c); + + return 1; + } +@@ -2109,7 +2115,7 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, + r = nft_rule_find(h, c, data, rulenum - 1); + if (r != NULL) + return nft_rule_append(h, chain, table, data, +- 0, verbose); ++ NULL, verbose); + + errno = ENOENT; + goto err; +@@ -2181,11 +2187,7 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, + (unsigned long long) + nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE)); + +- nftnl_rule_list_del(r); +- +- ret = nft_rule_append(h, chain, table, data, +- nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE), +- verbose); ++ ret = nft_rule_append(h, chain, table, data, r, verbose); + } else + errno = ENOENT; + +@@ -2461,9 +2463,7 @@ int nft_rule_zero_counters(struct nft_handle *h, const char *chain, + + cs.counters.pcnt = cs.counters.bcnt = 0; + +- ret = nft_rule_append(h, chain, table, &cs, +- nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE), +- false); ++ ret = nft_rule_append(h, chain, table, &cs, r, false); + + error: + return ret; +diff --git a/iptables/nft.h b/iptables/nft.h +index dfdffd69342db..97d73c8b534be 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -98,7 +98,7 @@ bool nft_chain_exists(struct nft_handle *h, const char *table, const char *chain + */ + struct nftnl_rule; + +-int nft_rule_append(struct nft_handle *h, const char *chain, const char *table, void *data, uint64_t handle, bool verbose); ++int nft_rule_append(struct nft_handle *h, const char *chain, const char *table, void *data, struct nftnl_rule *ref, bool verbose); + int nft_rule_insert(struct nft_handle *h, const char *chain, const char *table, void *data, int rulenum, bool verbose); + int nft_rule_check(struct nft_handle *h, const char *chain, const char *table, void *data, bool verbose); + int nft_rule_delete(struct nft_handle *h, const char *chain, const char *table, void *data, bool verbose); +diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c +index 2dce1a52f16fd..18cdced627c55 100644 +--- a/iptables/xtables-arp.c ++++ b/iptables/xtables-arp.c +@@ -825,7 +825,7 @@ append_entry(struct nft_handle *h, + for (j = 0; j < ndaddrs; j++) { + cs->arp.arp.tgt.s_addr = daddrs[j].s_addr; + if (append) { +- ret = nft_rule_append(h, chain, table, cs, 0, ++ ret = nft_rule_append(h, chain, table, cs, NULL, + verbose); + } else { + ret = nft_rule_insert(h, chain, table, cs, +diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c +index 871891442e431..4c52c29aa4817 100644 +--- a/iptables/xtables-eb.c ++++ b/iptables/xtables-eb.c +@@ -171,7 +171,7 @@ append_entry(struct nft_handle *h, + int ret = 1; + + if (append) +- ret = nft_rule_append(h, chain, table, cs, 0, verbose); ++ ret = nft_rule_append(h, chain, table, cs, NULL, verbose); + else + ret = nft_rule_insert(h, chain, table, cs, rule_nr, verbose); + +diff --git a/iptables/xtables.c b/iptables/xtables.c +index da11e8cc159a0..d0167e6396975 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -406,7 +406,7 @@ add_entry(const char *chain, + + if (append) { + ret = nft_rule_append(h, chain, table, +- cs, 0, ++ cs, NULL, + verbose); + } else { + ret = nft_rule_insert(h, chain, table, +@@ -426,7 +426,7 @@ add_entry(const char *chain, + &d.mask.v6[j], sizeof(struct in6_addr)); + if (append) { + ret = nft_rule_append(h, chain, table, +- cs, 0, ++ cs, NULL, + verbose); + } else { + ret = nft_rule_insert(h, chain, table, +-- +2.21.0 + diff --git a/SOURCES/0044-xtables-Fix-for-inserting-rule-at-wrong-position.patch b/SOURCES/0044-xtables-Fix-for-inserting-rule-at-wrong-position.patch new file mode 100644 index 0000000..ae350d0 --- /dev/null +++ b/SOURCES/0044-xtables-Fix-for-inserting-rule-at-wrong-position.patch @@ -0,0 +1,282 @@ +From 3c0eab01c78ff0215cafc124fd76d67f39f2b4ca Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 15 Jan 2019 23:23:05 +0100 +Subject: [PATCH] xtables: Fix for inserting rule at wrong position + +iptables-restore allows to insert rules at a certain position which is +problematic for iptables-nft to realize since rule position is not +determined by number but handle of previous or following rule and in +case the rules surrounding the new one are new as well, they don't have +a handle to refer to yet. + +Fix this by making use of NFTNL_RULE_POSITION_ID attribute: When +inserting before a rule which does not have a handle, refer to it using +its NFTNL_RULE_ID value. If the latter doesn't exist either, assign a +new one to it. + +The last used rule ID value is tracked in a new field of struct +nft_handle which is incremented before each use. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 7ea0b7d809229973d950ed99845bdd0b2eb4cbb7) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 30 +++-- + iptables/nft.h | 1 + + .../ipt-restore/0003-restore-ordering_0 | 117 ++++++++++++++++++ + .../testcases/iptables/0005-rule-replace_0 | 38 ++++++ + 4 files changed, 176 insertions(+), 10 deletions(-) + create mode 100755 iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0 + create mode 100755 iptables/tests/shell/testcases/iptables/0005-rule-replace_0 + +diff --git a/iptables/nft.c b/iptables/nft.c +index 76764fde4e9fb..2fa973cf03975 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2065,16 +2065,30 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, + static struct nftnl_rule * + nft_rule_add(struct nft_handle *h, const char *chain, + const char *table, struct iptables_command_state *cs, +- uint64_t handle, bool verbose) ++ struct nftnl_rule *ref, bool verbose) + { + struct nftnl_rule *r; ++ uint64_t ref_id; + + r = nft_rule_new(h, chain, table, cs); + if (r == NULL) + return NULL; + +- if (handle > 0) +- nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, handle); ++ if (ref) { ++ ref_id = nftnl_rule_get_u64(ref, NFTNL_RULE_HANDLE); ++ if (ref_id > 0) { ++ nftnl_rule_set_u64(r, NFTNL_RULE_POSITION, ref_id); ++ DEBUGP("adding after rule handle %"PRIu64"\n", ref_id); ++ } else { ++ ref_id = nftnl_rule_get_u32(ref, NFTNL_RULE_ID); ++ if (!ref_id) { ++ ref_id = ++h->rule_id; ++ nftnl_rule_set_u32(ref, NFTNL_RULE_ID, ref_id); ++ } ++ nftnl_rule_set_u32(r, NFTNL_RULE_POSITION_ID, ref_id); ++ DEBUGP("adding after rule ID %"PRIu64"\n", ref_id); ++ } ++ } + + if (batch_rule_add(h, NFT_COMPAT_RULE_INSERT, r) < 0) { + nftnl_rule_free(r); +@@ -2090,9 +2104,8 @@ nft_rule_add(struct nft_handle *h, const char *chain, + int nft_rule_insert(struct nft_handle *h, const char *chain, + const char *table, void *data, int rulenum, bool verbose) + { +- struct nftnl_rule *r, *new_rule; ++ struct nftnl_rule *r = NULL, *new_rule; + struct nftnl_chain *c; +- uint64_t handle = 0; + + /* If built-in chains don't exist for this table, create them */ + if (nft_xtables_config_load(h, XTABLES_CONFIG_DEFAULT, 0) < 0) +@@ -2120,16 +2133,13 @@ int nft_rule_insert(struct nft_handle *h, const char *chain, + errno = ENOENT; + goto err; + } +- +- handle = nftnl_rule_get_u64(r, NFTNL_RULE_HANDLE); +- DEBUGP("adding after rule handle %"PRIu64"\n", handle); + } + +- new_rule = nft_rule_add(h, chain, table, data, handle, verbose); ++ new_rule = nft_rule_add(h, chain, table, data, r, verbose); + if (!new_rule) + goto err; + +- if (handle) ++ if (r) + nftnl_chain_rule_insert_at(new_rule, r); + else + nftnl_chain_rule_add(new_rule, c); +diff --git a/iptables/nft.h b/iptables/nft.h +index 97d73c8b534be..0726923a63dd4 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -32,6 +32,7 @@ struct nft_handle { + struct mnl_socket *nl; + uint32_t portid; + uint32_t seq; ++ uint32_t rule_id; + struct list_head obj_list; + int obj_list_num; + struct nftnl_batch *batch; +diff --git a/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0 b/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0 +new file mode 100755 +index 0000000000000..51f2422e15259 +--- /dev/null ++++ b/iptables/tests/shell/testcases/ipt-restore/0003-restore-ordering_0 +@@ -0,0 +1,117 @@ ++#!/bin/bash ++ ++# Make sure iptables-restore does the right thing ++# when encountering INSERT rules with index. ++ ++set -e ++ ++# show rules, drop uninteresting policy settings ++ipt_show() { ++ $XT_MULTI iptables -S | grep -v '^-P' ++} ++ ++# basic issue reproducer ++ ++$XT_MULTI iptables-restore < +Date: Fri, 1 Feb 2019 19:17:50 +0100 +Subject: [PATCH] xtables: Fix for crash when comparing rules with standard + target + +When parsing an nftnl_rule with a standard verdict, +nft_rule_to_iptables_command_state() initialized cs->target but didn't +care about cs->target->t. When later comparing that rule to another, +compare_targets() crashed due to unconditional access to t's fields. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit a880cc28358a32f96467e248266973b6ab83f080) +Signed-off-by: Phil Sutter +--- + iptables/nft-shared.c | 23 +++++++++++++++---- + .../testcases/iptables/0005-delete-rules_0 | 7 ++++++ + iptables/xtables.c | 4 +++- + 3 files changed, 29 insertions(+), 5 deletions(-) + create mode 100755 iptables/tests/shell/testcases/iptables/0005-delete-rules_0 + +diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c +index 7b8ca5e4becaf..dfc1c803cb68d 100644 +--- a/iptables/nft-shared.c ++++ b/iptables/nft-shared.c +@@ -660,19 +660,34 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, + match->m = m; + } + +- if (cs->target != NULL) ++ if (cs->target != NULL) { + cs->jumpto = cs->target->name; +- else if (cs->jumpto != NULL) ++ } else if (cs->jumpto != NULL) { ++ struct xt_entry_target *t; ++ uint32_t size; ++ + cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); +- else ++ if (!cs->target) ++ return; ++ ++ size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size; ++ t = xtables_calloc(1, size); ++ t->u.target_size = size; ++ t->u.user.revision = cs->target->revision; ++ strcpy(t->u.user.name, cs->jumpto); ++ cs->target->t = t; ++ } else { + cs->jumpto = ""; ++ } + } + + void nft_clear_iptables_command_state(struct iptables_command_state *cs) + { + xtables_rule_matches_free(&cs->matches); +- if (cs->target) ++ if (cs->target) { + free(cs->target->t); ++ cs->target->t = NULL; ++ } + } + + void print_header(unsigned int format, const char *chain, const char *pol, +diff --git a/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 +new file mode 100755 +index 0000000000000..9312fd53c3437 +--- /dev/null ++++ b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 +@@ -0,0 +1,7 @@ ++#!/bin/bash ++ ++# test for crash when comparing rules with standard target ++ ++$XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j DROP ++$XT_MULTI iptables -D FORWARD -i eth23 -o eth42 -j REJECT ++[[ $? -eq 1 ]] || exit 1 +diff --git a/iptables/xtables.c b/iptables/xtables.c +index d0167e6396975..eaa9fedeb03bb 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -1185,8 +1185,10 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table, + *table = p.table; + + xtables_rule_matches_free(&cs.matches); +- if (cs.target) ++ if (cs.target) { + free(cs.target->t); ++ cs.target->t = NULL; ++ } + + if (h->family == AF_INET) { + free(args.s.addr.v4); +-- +2.21.0 + diff --git a/SOURCES/0046-xtables-Fix-for-false-positive-rule-matching.patch b/SOURCES/0046-xtables-Fix-for-false-positive-rule-matching.patch new file mode 100644 index 0000000..14a94dc --- /dev/null +++ b/SOURCES/0046-xtables-Fix-for-false-positive-rule-matching.patch @@ -0,0 +1,258 @@ +From 27b68bd11b99429d1b830dbe76fc0148b5a24a16 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 4 Feb 2019 21:52:53 +0100 +Subject: [PATCH] xtables: Fix for false-positive rule matching + +When comparing two rules with non-standard targets, differences in +targets' payloads wasn't respected. + +The cause is a rather hideous one: Unlike xtables_find_match(), +xtables_find_target() did not care whether the found target was already +in use or not, so the same target instance was assigned to both rules +and therefore payload comparison happened over the same memory location. + +With legacy iptables it is not possible to reuse a target: The only case +where two rules (i.e., iptables_command_state instances) could exist at +the same time is when comparing rules, but that's handled using libiptc. + +The above change clashes with ebtables-nft's reuse of target objects: +While input parsing still just assigns the object from xtables_targets +list, rule conversion from nftnl to iptables_command_state allocates new +data. To fix this, make ebtables-nft input parsing use the common +command_jump() routine instead of its own simplified copy. In turn, this +also eliminates the ebtables-nft-specific variants of parse_target(), +though with a slight change of behaviour: Names of user-defined chains +are no longer allowed to contain up to 31 but merely 28 characters. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 148131f20421046fea028e638581e938ec985783) +Signed-off-by: Phil Sutter +--- + iptables/nft-bridge.c | 10 ++++ + iptables/nft-bridge.h | 2 - + iptables/nft-shared.c | 5 ++ + .../testcases/iptables/0005-delete-rules_0 | 7 +++ + iptables/xtables-eb-translate.c | 24 +--------- + iptables/xtables-eb.c | 47 +------------------ + libxtables/xtables.c | 18 ++++++- + 7 files changed, 41 insertions(+), 72 deletions(-) + +diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c +index ad583a60c424d..140fcf0a31b84 100644 +--- a/iptables/nft-bridge.c ++++ b/iptables/nft-bridge.c +@@ -45,6 +45,16 @@ void ebt_cs_clean(struct iptables_command_state *cs) + free(m); + m = nm; + } ++ ++ if (cs->target) { ++ free(cs->target->t); ++ cs->target->t = NULL; ++ ++ if (cs->target == cs->target->next) { ++ free(cs->target); ++ cs->target = NULL; ++ } ++ } + } + + static void ebt_print_mac(const unsigned char *mac) +diff --git a/iptables/nft-bridge.h b/iptables/nft-bridge.h +index de52cd7195bbb..d90066f1030a2 100644 +--- a/iptables/nft-bridge.h ++++ b/iptables/nft-bridge.h +@@ -32,7 +32,6 @@ int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mas + */ + + #define EBT_TABLE_MAXNAMELEN 32 +-#define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN + #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN + + /* verdicts >0 are "branches" */ +@@ -122,6 +121,5 @@ void ebt_add_match(struct xtables_match *m, + void ebt_add_watcher(struct xtables_target *watcher, + struct iptables_command_state *cs); + int ebt_command_default(struct iptables_command_state *cs); +-struct xtables_target *ebt_command_jump(const char *jumpto); + + #endif +diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c +index dfc1c803cb68d..ce40787f92f7d 100644 +--- a/iptables/nft-shared.c ++++ b/iptables/nft-shared.c +@@ -687,6 +687,11 @@ void nft_clear_iptables_command_state(struct iptables_command_state *cs) + if (cs->target) { + free(cs->target->t); + cs->target->t = NULL; ++ ++ if (cs->target == cs->target->next) { ++ free(cs->target); ++ cs->target = NULL; ++ } + } + } + +diff --git a/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 +index 9312fd53c3437..5038cbce5a5cf 100755 +--- a/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 ++++ b/iptables/tests/shell/testcases/iptables/0005-delete-rules_0 +@@ -5,3 +5,10 @@ + $XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j DROP + $XT_MULTI iptables -D FORWARD -i eth23 -o eth42 -j REJECT + [[ $? -eq 1 ]] || exit 1 ++ ++# test incorrect deletion of rules with deviating payload ++# in non-standard target ++ ++$XT_MULTI iptables -A FORWARD -i eth23 -o eth42 -j MARK --set-mark 23 ++$XT_MULTI iptables -D FORWARD -i eth23 -o eth42 -j MARK --set-mark 42 ++[[ $? -eq 1 ]] || exit 1 +diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c +index f98c385555eb1..0fe14d2d0db32 100644 +--- a/iptables/xtables-eb-translate.c ++++ b/iptables/xtables-eb-translate.c +@@ -64,27 +64,6 @@ static int parse_rule_number(const char *rule) + return rule_nr; + } + +-static const char * +-parse_target(const char *targetname) +-{ +- const char *ptr; +- +- if (strlen(targetname) < 1) +- xtables_error(PARAMETER_PROBLEM, +- "Invalid target name (too short)"); +- +- if (strlen(targetname)+1 > EBT_CHAIN_MAXNAMELEN) +- xtables_error(PARAMETER_PROBLEM, +- "Invalid target '%s' (%d chars max)", +- targetname, EBT_CHAIN_MAXNAMELEN); +- +- for (ptr = targetname; *ptr; ptr++) +- if (isspace(*ptr)) +- xtables_error(PARAMETER_PROBLEM, +- "Invalid target name `%s'", targetname); +- return targetname; +-} +- + static int get_current_chain(const char *chain) + { + if (strcmp(chain, "PREROUTING") == 0) +@@ -411,8 +390,7 @@ print_zero: + break; + } else if (c == 'j') { + ebt_check_option2(&flags, OPT_JUMP); +- cs.jumpto = parse_target(optarg); +- cs.target = ebt_command_jump(cs.jumpto); ++ command_jump(&cs); + break; + } else if (c == 's') { + ebt_check_option2(&flags, OPT_SOURCE); +diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c +index 4c52c29aa4817..55cb0fe204748 100644 +--- a/iptables/xtables-eb.c ++++ b/iptables/xtables-eb.c +@@ -139,27 +139,6 @@ static int parse_rule_number(const char *rule) + return rule_nr; + } + +-static const char * +-parse_target(const char *targetname) +-{ +- const char *ptr; +- +- if (strlen(targetname) < 1) +- xtables_error(PARAMETER_PROBLEM, +- "Invalid target name (too short)"); +- +- if (strlen(targetname)+1 > EBT_CHAIN_MAXNAMELEN) +- xtables_error(PARAMETER_PROBLEM, +- "Invalid target '%s' (%d chars max)", +- targetname, EBT_CHAIN_MAXNAMELEN); +- +- for (ptr = targetname; *ptr; ptr++) +- if (isspace(*ptr)) +- xtables_error(PARAMETER_PROBLEM, +- "Invalid target name `%s'", targetname); +- return targetname; +-} +- + static int + append_entry(struct nft_handle *h, + const char *chain, +@@ -376,29 +355,6 @@ static struct option *merge_options(struct option *oldopts, + return merge; + } + +-/* +- * More glue code. +- */ +-struct xtables_target *ebt_command_jump(const char *jumpto) +-{ +- struct xtables_target *target; +- unsigned int verdict; +- +- /* Standard target? */ +- if (!ebt_fill_target(jumpto, &verdict)) +- jumpto = "standard"; +- +- /* For ebtables, all targets are preloaded. Hence it is either in +- * xtables_targets or a custom chain to jump to, in which case +- * returning NULL is fine. */ +- for (target = xtables_targets; target; target = target->next) { +- if (!strcmp(target->name, jumpto)) +- break; +- } +- +- return target; +-} +- + static void print_help(const struct xtables_target *t, + const struct xtables_rule_match *m, const char *table) + { +@@ -1066,8 +1022,7 @@ print_zero: + } else if (c == 'j') { + ebt_check_option2(&flags, OPT_JUMP); + if (strcmp(optarg, "CONTINUE") != 0) { +- cs.jumpto = parse_target(optarg); +- cs.target = ebt_command_jump(cs.jumpto); ++ command_jump(&cs); + } + break; + } else if (c == 's') { +diff --git a/libxtables/xtables.c b/libxtables/xtables.c +index ea9bb102c8eb4..895f6988eaf57 100644 +--- a/libxtables/xtables.c ++++ b/libxtables/xtables.c +@@ -756,8 +756,24 @@ xtables_find_target(const char *name, enum xtables_tryload tryload) + } + + for (ptr = xtables_targets; ptr; ptr = ptr->next) { +- if (extension_cmp(name, ptr->name, ptr->family)) ++ if (extension_cmp(name, ptr->name, ptr->family)) { ++ struct xtables_target *clone; ++ ++ /* First target of this type: */ ++ if (ptr->t == NULL) ++ break; ++ ++ /* Second and subsequent clones */ ++ clone = xtables_malloc(sizeof(struct xtables_target)); ++ memcpy(clone, ptr, sizeof(struct xtables_target)); ++ clone->udata = NULL; ++ clone->tflags = 0; ++ /* This is a clone: */ ++ clone->next = clone; ++ ++ ptr = clone; + break; ++ } + } + + #ifndef NO_SHARED_LIBS +-- +2.21.0 + diff --git a/SOURCES/0047-ebtables-Fix-rule-listing-with-counters.patch b/SOURCES/0047-ebtables-Fix-rule-listing-with-counters.patch new file mode 100644 index 0000000..c166da4 --- /dev/null +++ b/SOURCES/0047-ebtables-Fix-rule-listing-with-counters.patch @@ -0,0 +1,75 @@ +From b321a8af45e3040ae46091fef2c35d5533ab83bc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 21 Jan 2019 17:43:34 +0100 +Subject: [PATCH] ebtables: Fix rule listing with counters + +This is a partial revert of commit 583b27eabcad6 ("ebtables-save: add -c +option, using xtables-style counters") which broke ruleset listing with +'--Lc' flag turned on: + +| # ebtables-nft -L --Lc +| Bridge table: filter +| +| Bridge chain: INPUT, entries: 0, policy: ACCEPT +| +| Bridge chain: FORWARD, entries: 2, policy: ACCEPT +| -j foo +| , pcnt = 0 -- bcnt = 0-j ACCEPT +| , pcnt = 0 -- bcnt = 0 +| Bridge chain: OUTPUT, entries: 0, policy: ACCEPT +| +| Bridge chain: foo, entries: 1, policy: RETURN +| -j ACCEPT +| , pcnt = 0 -- bcnt = 0% + +(That percentage sign means no newline after last line of output and +doesn't belong to ebtables-nft's output.) + +Problem was that nft_bridge_print_rule() printed the counters after +nft_bridge_save_rule() had already printed the newline character. + +Note also that there is no need to remove FMT_EBT_SAVE bit from 'format' +variable: It is set only by ebtables-nft-save which doesn't call +nft_bridge_print_rule(). + +Fixes: 583b27eabcad6 ("ebtables-save: add -c option, using xtables-style counters") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 32ebc39f71e8107d6069a9f6fba8338a2823889d) +Signed-off-by: Phil Sutter +--- + iptables/nft-bridge.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c +index 140fcf0a31b84..43b3e3e9649b8 100644 +--- a/iptables/nft-bridge.c ++++ b/iptables/nft-bridge.c +@@ -479,6 +479,11 @@ static void nft_bridge_save_rule(const void *data, unsigned int format) + (uint64_t)cs->counters.pcnt, + (uint64_t)cs->counters.bcnt); + ++ if (!(format & FMT_NOCOUNTS)) ++ printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"", ++ (uint64_t)cs->counters.pcnt, ++ (uint64_t)cs->counters.bcnt); ++ + if (!(format & FMT_NONEWLINE)) + fputc('\n', stdout); + } +@@ -492,11 +497,7 @@ static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num, + printf("%d ", num); + + nft_rule_to_ebtables_command_state(r, &cs); +- nft_bridge_save_rule(&cs, format & ~FMT_EBT_SAVE); +- if (!(format & FMT_NOCOUNTS)) +- printf(" , pcnt = %"PRIu64" -- bcnt = %"PRIu64"", +- (uint64_t)cs.counters.pcnt, +- (uint64_t)cs.counters.bcnt); ++ nft_bridge_save_rule(&cs, format); + ebt_cs_clean(&cs); + } + +-- +2.21.0 + diff --git a/SOURCES/0048-Revert-ebtables-use-extrapositioned-negation-consist.patch b/SOURCES/0048-Revert-ebtables-use-extrapositioned-negation-consist.patch new file mode 100644 index 0000000..3564535 --- /dev/null +++ b/SOURCES/0048-Revert-ebtables-use-extrapositioned-negation-consist.patch @@ -0,0 +1,534 @@ +From af890b239555d52c269d224ada6382381320585d Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 5 Feb 2019 18:18:02 +0100 +Subject: [PATCH] Revert "ebtables: use extrapositioned negation consistently" + +This reverts commit 5f508b76a0cebaf91965ffa678089222e2d47964. + +While attempts at unifying syntax between arp-, eb- and iptables-nft +increase the opportunity for more code-sharing, they are problematic +when it comes to compatibility. Accepting the old syntax on input helps, +but due to the fact that neither arptables nor ebtables support --check +command we must expect for users to test existence of a rule by +comparing input with output. If that happens in a script, deviating from +the old syntax in output has a high chance of breaking it. + +Therefore revert Florian's patch changing inversion character position +in output and review the old code for consistency - the only thing +changed on top of the actual revert is ebtables' own copy of +print_iface() to make it adhere to the intrapositioned negation scheme +used throughout ebtables. + +Added extension tests by the reverted commit have been kept. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 35b22e82fa62e10950d8e0fa53a755d4abadf346) +Signed-off-by: Phil Sutter +--- + extensions/libebt_802_3.c | 4 ++-- + extensions/libebt_802_3.t | 2 +- + extensions/libebt_arp.c | 14 +++++++------- + extensions/libebt_arp.t | 8 ++++---- + extensions/libebt_ip.c | 16 ++++++++-------- + extensions/libebt_ip.t | 6 +++--- + extensions/libebt_ip6.c | 14 +++++++------- + extensions/libebt_ip6.t | 6 +++--- + extensions/libebt_mark_m.c | 2 +- + extensions/libebt_mark_m.t | 4 ++-- + extensions/libebt_pkttype.c | 5 +---- + extensions/libebt_pkttype.t | 13 +++++++------ + extensions/libebt_standard.t | 4 ++-- + extensions/libebt_stp.c | 5 ++--- + extensions/libebt_vlan.c | 13 ++++--------- + extensions/libebt_vlan.t | 10 +++++----- + iptables/nft-bridge.c | 6 +++--- + 17 files changed, 62 insertions(+), 70 deletions(-) + +diff --git a/extensions/libebt_802_3.c b/extensions/libebt_802_3.c +index 9e91d05262591..f05d02ead5a4a 100644 +--- a/extensions/libebt_802_3.c ++++ b/extensions/libebt_802_3.c +@@ -98,15 +98,15 @@ static void br802_3_print(const void *ip, const struct xt_entry_match *match, + struct ebt_802_3_info *info = (struct ebt_802_3_info *)match->data; + + if (info->bitmask & EBT_802_3_SAP) { ++ printf("--802_3-sap "); + if (info->invflags & EBT_802_3_SAP) + printf("! "); +- printf("--802_3-sap "); + printf("0x%.2x ", info->sap); + } + if (info->bitmask & EBT_802_3_TYPE) { ++ printf("--802_3-type "); + if (info->invflags & EBT_802_3_TYPE) + printf("! "); +- printf("--802_3-type "); + printf("0x%.4x ", ntohs(info->type)); + } + } +diff --git a/extensions/libebt_802_3.t b/extensions/libebt_802_3.t +index 61081bd6983a8..ddfb2f0a72baf 100644 +--- a/extensions/libebt_802_3.t ++++ b/extensions/libebt_802_3.t +@@ -1,3 +1,3 @@ + :INPUT,FORWARD,OUTPUT +-! --802_3-sap 0x0a -j CONTINUE;=;OK ++--802_3-sap ! 0x0a -j CONTINUE;=;OK + --802_3-type 0x000a -j RETURN;=;OK +diff --git a/extensions/libebt_arp.c b/extensions/libebt_arp.c +index c1b0ab1db0cf1..a062b7e7e5864 100644 +--- a/extensions/libebt_arp.c ++++ b/extensions/libebt_arp.c +@@ -338,51 +338,51 @@ static void brarp_print(const void *ip, const struct xt_entry_match *match, int + + if (arpinfo->bitmask & EBT_ARP_OPCODE) { + int opcode = ntohs(arpinfo->opcode); ++ printf("--arp-op "); + if (arpinfo->invflags & EBT_ARP_OPCODE) + printf("! "); +- printf("--arp-op "); + if (opcode > 0 && opcode <= ARRAY_SIZE(opcodes)) + printf("%s ", opcodes[opcode - 1]); + else + printf("%d ", opcode); + } + if (arpinfo->bitmask & EBT_ARP_HTYPE) { ++ printf("--arp-htype "); + if (arpinfo->invflags & EBT_ARP_HTYPE) + printf("! "); +- printf("--arp-htype "); + printf("%d ", ntohs(arpinfo->htype)); + } + if (arpinfo->bitmask & EBT_ARP_PTYPE) { ++ printf("--arp-ptype "); + if (arpinfo->invflags & EBT_ARP_PTYPE) + printf("! "); +- printf("--arp-ptype "); + printf("0x%x ", ntohs(arpinfo->ptype)); + } + if (arpinfo->bitmask & EBT_ARP_SRC_IP) { ++ printf("--arp-ip-src "); + if (arpinfo->invflags & EBT_ARP_SRC_IP) + printf("! "); +- printf("--arp-ip-src "); + printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->saddr), + xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->smsk)); + } + if (arpinfo->bitmask & EBT_ARP_DST_IP) { ++ printf("--arp-ip-dst "); + if (arpinfo->invflags & EBT_ARP_DST_IP) + printf("! "); +- printf("--arp-ip-dst "); + printf("%s%s ", xtables_ipaddr_to_numeric((const struct in_addr*) &arpinfo->daddr), + xtables_ipmask_to_numeric((const struct in_addr*)&arpinfo->dmsk)); + } + if (arpinfo->bitmask & EBT_ARP_SRC_MAC) { ++ printf("--arp-mac-src "); + if (arpinfo->invflags & EBT_ARP_SRC_MAC) + printf("! "); +- printf("--arp-mac-src "); + xtables_print_mac_and_mask(arpinfo->smaddr, arpinfo->smmsk); + printf(" "); + } + if (arpinfo->bitmask & EBT_ARP_DST_MAC) { ++ printf("--arp-mac-dst "); + if (arpinfo->invflags & EBT_ARP_DST_MAC) + printf("! "); +- printf("--arp-mac-dst "); + xtables_print_mac_and_mask(arpinfo->dmaddr, arpinfo->dmmsk); + printf(" "); + } +diff --git a/extensions/libebt_arp.t b/extensions/libebt_arp.t +index a05ab12dc566f..14ff0f097cfd8 100644 +--- a/extensions/libebt_arp.t ++++ b/extensions/libebt_arp.t +@@ -1,11 +1,11 @@ + :INPUT,FORWARD,OUTPUT + -p ARP --arp-op Request;=;OK +--p ARP ! --arp-htype 1;=;OK ++-p ARP --arp-htype ! 1;=;OK + -p ARP --arp-ptype 0x2;=;OK + -p ARP --arp-ip-src 1.2.3.4;=;OK +--p ARP ! --arp-ip-dst 1.2.3.4;=;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-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-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_ip.c b/extensions/libebt_ip.c +index d48704fe1c802..acb9bfcdbbd9f 100644 +--- a/extensions/libebt_ip.c ++++ b/extensions/libebt_ip.c +@@ -472,35 +472,35 @@ static void brip_print(const void *ip, const struct xt_entry_match *match, + struct in_addr *addrp, *maskp; + + if (info->bitmask & EBT_IP_SOURCE) { ++ printf("--ip-src "); + if (info->invflags & EBT_IP_SOURCE) + printf("! "); +- printf("--ip-src "); + addrp = (struct in_addr *)&info->saddr; + maskp = (struct in_addr *)&info->smsk; + printf("%s%s ", xtables_ipaddr_to_numeric(addrp), + xtables_ipmask_to_numeric(maskp)); + } + if (info->bitmask & EBT_IP_DEST) { ++ printf("--ip-dst "); + if (info->invflags & EBT_IP_DEST) + printf("! "); +- printf("--ip-dst "); + addrp = (struct in_addr *)&info->daddr; + maskp = (struct in_addr *)&info->dmsk; + printf("%s%s ", xtables_ipaddr_to_numeric(addrp), + xtables_ipmask_to_numeric(maskp)); + } + if (info->bitmask & EBT_IP_TOS) { ++ printf("--ip-tos "); + if (info->invflags & EBT_IP_TOS) + printf("! "); +- printf("--ip-tos "); + printf("0x%02X ", info->tos); + } + if (info->bitmask & EBT_IP_PROTO) { + struct protoent *pe; + ++ printf("--ip-proto "); + if (info->invflags & EBT_IP_PROTO) + printf("! "); +- printf("--ip-proto "); + pe = getprotobynumber(info->protocol); + if (pe == NULL) { + printf("%d ", info->protocol); +@@ -509,28 +509,28 @@ static void brip_print(const void *ip, const struct xt_entry_match *match, + } + } + if (info->bitmask & EBT_IP_SPORT) { ++ printf("--ip-sport "); + if (info->invflags & EBT_IP_SPORT) + printf("! "); +- printf("--ip-sport "); + print_port_range(info->sport); + } + if (info->bitmask & EBT_IP_DPORT) { ++ printf("--ip-dport "); + if (info->invflags & EBT_IP_DPORT) + printf("! "); +- printf("--ip-dport "); + print_port_range(info->dport); + } + if (info->bitmask & EBT_IP_ICMP) { ++ printf("--ip-icmp-type "); + if (info->invflags & EBT_IP_ICMP) + printf("! "); +- printf("--ip-icmp-type "); + ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes), + info->icmp_type, info->icmp_code); + } + if (info->bitmask & EBT_IP_IGMP) { ++ printf("--ip-igmp-type "); + if (info->invflags & EBT_IP_IGMP) + printf("! "); +- printf("--ip-igmp-type "); + ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types), + info->igmp_type, NULL); + } +diff --git a/extensions/libebt_ip.t b/extensions/libebt_ip.t +index 01a91a7385fcc..8be5dfbb22309 100644 +--- a/extensions/libebt_ip.t ++++ b/extensions/libebt_ip.t +@@ -1,13 +1,13 @@ + :INPUT,FORWARD,OUTPUT +--p ip --ip-src ! 192.168.0.0/24 -j ACCEPT;-p IPv4 ! --ip-src 192.168.0.0/24 -j ACCEPT;OK ++-p ip --ip-src ! 192.168.0.0/24 -j ACCEPT;-p IPv4 --ip-src ! 192.168.0.0/24 -j ACCEPT;OK + -p IPv4 --ip-dst 10.0.0.1;=;OK + -p IPv4 --ip-tos 0xFF;=;OK +--p IPv4 ! --ip-tos 0xFF;=;OK ++-p IPv4 --ip-tos ! 0xFF;=;OK + -p IPv4 --ip-proto tcp --ip-dport 22;=;OK + -p IPv4 --ip-proto udp --ip-sport 1024:65535;=;OK + -p IPv4 --ip-proto 253;=;OK + -p IPv4 --ip-proto icmp --ip-icmp-type echo-request;=;OK + -p IPv4 --ip-proto icmp --ip-icmp-type 1/1;=;OK +--p ip --ip-protocol icmp --ip-icmp-type ! 1:10;-p IPv4 --ip-proto icmp ! --ip-icmp-type 1:10/0:255 -j CONTINUE;OK ++-p ip --ip-protocol icmp --ip-icmp-type ! 1:10;-p IPv4 --ip-proto icmp --ip-icmp-type ! 1:10/0:255 -j CONTINUE;OK + --ip-proto icmp --ip-icmp-type 1/1;=;FAIL + ! -p ip --ip-proto icmp --ip-icmp-type 1/1;=;FAIL +diff --git a/extensions/libebt_ip6.c b/extensions/libebt_ip6.c +index b727764903ffa..b8a5a5d8c3a92 100644 +--- a/extensions/libebt_ip6.c ++++ b/extensions/libebt_ip6.c +@@ -399,31 +399,31 @@ static void brip6_print(const void *ip, const struct xt_entry_match *match, + struct ebt_ip6_info *ipinfo = (struct ebt_ip6_info *)match->data; + + if (ipinfo->bitmask & EBT_IP6_SOURCE) { ++ printf("--ip6-src "); + if (ipinfo->invflags & EBT_IP6_SOURCE) + printf("! "); +- printf("--ip6-src "); + printf("%s", xtables_ip6addr_to_numeric(&ipinfo->saddr)); + printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->smsk)); + } + if (ipinfo->bitmask & EBT_IP6_DEST) { ++ printf("--ip6-dst "); + if (ipinfo->invflags & EBT_IP6_DEST) + printf("! "); +- printf("--ip6-dst "); + printf("%s", xtables_ip6addr_to_numeric(&ipinfo->daddr)); + printf("%s ", xtables_ip6mask_to_numeric(&ipinfo->dmsk)); + } + if (ipinfo->bitmask & EBT_IP6_TCLASS) { ++ printf("--ip6-tclass "); + if (ipinfo->invflags & EBT_IP6_TCLASS) + printf("! "); +- printf("--ip6-tclass "); + printf("0x%02X ", ipinfo->tclass); + } + if (ipinfo->bitmask & EBT_IP6_PROTO) { + struct protoent *pe; + ++ printf("--ip6-proto "); + if (ipinfo->invflags & EBT_IP6_PROTO) + printf("! "); +- printf("--ip6-proto "); + pe = getprotobynumber(ipinfo->protocol); + if (pe == NULL) { + printf("%d ", ipinfo->protocol); +@@ -432,21 +432,21 @@ static void brip6_print(const void *ip, const struct xt_entry_match *match, + } + } + if (ipinfo->bitmask & EBT_IP6_SPORT) { ++ printf("--ip6-sport "); + if (ipinfo->invflags & EBT_IP6_SPORT) + printf("! "); +- printf("--ip6-sport "); + print_port_range(ipinfo->sport); + } + if (ipinfo->bitmask & EBT_IP6_DPORT) { ++ printf("--ip6-dport "); + if (ipinfo->invflags & EBT_IP6_DPORT) + printf("! "); +- printf("--ip6-dport "); + print_port_range(ipinfo->dport); + } + if (ipinfo->bitmask & EBT_IP6_ICMP6) { ++ printf("--ip6-icmp-type "); + if (ipinfo->invflags & EBT_IP6_ICMP6) + printf("! "); +- printf("--ip6-icmp-type "); + print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code); + } + } +diff --git a/extensions/libebt_ip6.t b/extensions/libebt_ip6.t +index 6b3221ea58f62..fa1038af25649 100644 +--- a/extensions/libebt_ip6.t ++++ b/extensions/libebt_ip6.t +@@ -1,15 +1,15 @@ + :INPUT,FORWARD,OUTPUT +--p ip6 ! --ip6-src dead::beef/64 -j ACCEPT;-p IPv6 ! --ip6-src dead::/64 -j ACCEPT;OK ++-p ip6 --ip6-src ! dead::beef/64 -j ACCEPT;-p IPv6 --ip6-src ! dead::/64 -j ACCEPT;OK + -p IPv6 --ip6-dst dead:beef::/64 -j ACCEPT;=;OK + -p IPv6 --ip6-dst f00:ba::;=;OK + -p IPv6 --ip6-tclass 0xFF;=;OK + -p IPv6 --ip6-proto tcp --ip6-dport 22;=;OK +--p IPv6 --ip6-proto tcp ! --ip6-dport 22;=;OK ++-p IPv6 --ip6-proto tcp --ip6-dport ! 22;=;OK + -p IPv6 --ip6-proto udp --ip6-sport 1024:65535;=;OK + -p IPv6 --ip6-proto 253;=;OK + -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request -j CONTINUE;=;OK + -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type echo-request;=;OK + -p ip6 --ip6-protocol icmpv6 --ip6-icmp-type 1/1;-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type communication-prohibited -j CONTINUE;OK +--p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;OK ++-p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type ! 1:10/0:255;=;OK + --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL + ! -p IPv6 --ip6-proto ipv6-icmp ! --ip6-icmp-type 1:10/0:255;=;FAIL +diff --git a/extensions/libebt_mark_m.c b/extensions/libebt_mark_m.c +index 64ad926f19959..2462d0af7d0bc 100644 +--- a/extensions/libebt_mark_m.c ++++ b/extensions/libebt_mark_m.c +@@ -86,9 +86,9 @@ static void brmark_m_print(const void *ip, const struct xt_entry_match *match, + { + struct ebt_mark_m_info *info = (struct ebt_mark_m_info *)match->data; + ++ printf("--mark "); + if (info->invert) + printf("! "); +- printf("--mark "); + if (info->bitmask == EBT_MARK_OR) + printf("/0x%lx ", info->mask); + else if (info->mask != 0xffffffff) +diff --git a/extensions/libebt_mark_m.t b/extensions/libebt_mark_m.t +index 9ad41704fbb82..00035427f8b6e 100644 +--- a/extensions/libebt_mark_m.t ++++ b/extensions/libebt_mark_m.t +@@ -1,6 +1,6 @@ + :INPUT,FORWARD,OUTPUT + --mark 42;--mark 0x2a;OK +---mark ! 42;! --mark 0x2a;OK ++--mark ! 42;--mark ! 0x2a;OK + --mark 42/0xff;--mark 0x2a/0xff;OK +-! --mark 0x1/0xff;=;OK ++--mark ! 0x1/0xff;=;OK + --mark /0x2;=;OK +diff --git a/extensions/libebt_pkttype.c b/extensions/libebt_pkttype.c +index 265674d19bde6..4e2d19de7983b 100644 +--- a/extensions/libebt_pkttype.c ++++ b/extensions/libebt_pkttype.c +@@ -75,10 +75,7 @@ static void brpkttype_print(const void *ip, const struct xt_entry_match *match, + { + struct ebt_pkttype_info *pt = (struct ebt_pkttype_info *)match->data; + +- if (pt->invert) +- printf("! "); +- +- printf("--pkttype-type "); ++ printf("--pkttype-type %s", pt->invert ? "! " : ""); + + if (pt->pkt_type < ARRAY_SIZE(classes)) + printf("%s ", classes[pt->pkt_type]); +diff --git a/extensions/libebt_pkttype.t b/extensions/libebt_pkttype.t +index f870f5c7f05c4..e3b95ded4903e 100644 +--- a/extensions/libebt_pkttype.t ++++ b/extensions/libebt_pkttype.t +@@ -1,13 +1,14 @@ + :INPUT,FORWARD,OUTPUT ++! --pkttype-type host;--pkttype-type ! host -j CONTINUE;OK + --pkttype-type host;=;OK +-! --pkttype-type host;=;OK ++--pkttype-type ! host;=;OK + --pkttype-type broadcast;=;OK +-! --pkttype-type broadcast;=;OK ++--pkttype-type ! broadcast;=;OK + --pkttype-type multicast;=;OK +-! --pkttype-type multicast;=;OK ++--pkttype-type ! multicast;=;OK + --pkttype-type otherhost;=;OK +-! --pkttype-type otherhost;=;OK ++--pkttype-type ! otherhost;=;OK + --pkttype-type outgoing;=;OK +-! --pkttype-type outgoing;=;OK ++--pkttype-type ! outgoing;=;OK + --pkttype-type loopback;=;OK +-! --pkttype-type loopback;=;OK ++--pkttype-type ! loopback;=;OK +diff --git a/extensions/libebt_standard.t b/extensions/libebt_standard.t +index 72081fd6575a0..0d678fb23c439 100644 +--- a/extensions/libebt_standard.t ++++ b/extensions/libebt_standard.t +@@ -6,6 +6,6 @@ + -d de:ad:be:ef:00:00 -j CONTINUE;=;OK + -d de:ad:be:ef:0:00/ff:ff:ff:ff:0:0 -j DROP;-d de:ad:be:ef:00:00/ff:ff:ff:ff:00:00 -j DROP;OK + -p ARP -j ACCEPT;=;OK +-! -p ARP -j ACCEPT;=;OK ++-p ! ARP -j ACCEPT;=;OK + -p 0 -j ACCEPT;=;FAIL +-! -p 0 -j ACCEPT;=;FAIL ++-p ! 0 -j ACCEPT;=;FAIL +diff --git a/extensions/libebt_stp.c b/extensions/libebt_stp.c +index 33e4c8d9c615d..06cf93b8d8449 100644 +--- a/extensions/libebt_stp.c ++++ b/extensions/libebt_stp.c +@@ -307,9 +307,8 @@ static void brstp_print(const void *ip, const struct xt_entry_match *match, + for (i = 0; i < STP_NUMOPS; i++) { + if (!(stpinfo->bitmask & (1 << i))) + continue; +- if (stpinfo->invflags & (1 << i)) +- printf("! "); +- printf("--%s ", brstp_opts[i].name); ++ printf("--%s %s", brstp_opts[i].name, ++ (stpinfo->invflags & (1 << i)) ? "! " : ""); + if (EBT_STP_TYPE == (1 << i)) { + if (stpinfo->type == BPDU_TYPE_CONFIG) + printf("%s", BPDU_TYPE_CONFIG_STRING); +diff --git a/extensions/libebt_vlan.c b/extensions/libebt_vlan.c +index 4a2eb7126895e..a2a9dcce531ce 100644 +--- a/extensions/libebt_vlan.c ++++ b/extensions/libebt_vlan.c +@@ -108,19 +108,14 @@ static void brvlan_print(const void *ip, const struct xt_entry_match *match, + struct ebt_vlan_info *vlaninfo = (struct ebt_vlan_info *) match->data; + + if (vlaninfo->bitmask & EBT_VLAN_ID) { +- if (vlaninfo->invflags & EBT_VLAN_ID) +- printf("! "); +- printf("--vlan-id %d ", vlaninfo->id); ++ printf("--vlan-id %s%d ", (vlaninfo->invflags & EBT_VLAN_ID) ? "! " : "", vlaninfo->id); + } + if (vlaninfo->bitmask & EBT_VLAN_PRIO) { +- if (vlaninfo->invflags & EBT_VLAN_PRIO) +- printf("! "); +- printf("--vlan-prio %d ", vlaninfo->prio); ++ printf("--vlan-prio %s%d ", (vlaninfo->invflags & EBT_VLAN_PRIO) ? "! " : "", vlaninfo->prio); + } + if (vlaninfo->bitmask & EBT_VLAN_ENCAP) { +- if (vlaninfo->invflags & EBT_VLAN_ENCAP) +- printf("! "); +- printf("--vlan-encap %4.4X ", ntohs(vlaninfo->encap)); ++ printf("--vlan-encap %s", (vlaninfo->invflags & EBT_VLAN_ENCAP) ? "! " : ""); ++ printf("%4.4X ", ntohs(vlaninfo->encap)); + } + } + +diff --git a/extensions/libebt_vlan.t b/extensions/libebt_vlan.t +index 106374cd9cb80..81c795854fca0 100644 +--- a/extensions/libebt_vlan.t ++++ b/extensions/libebt_vlan.t +@@ -1,13 +1,13 @@ + :INPUT,FORWARD,OUTPUT + -p 802_1Q --vlan-id 42;=;OK +--p 802_1Q ! --vlan-id 42;=;OK ++-p 802_1Q --vlan-id ! 42;=;OK + -p 802_1Q --vlan-prio 1;=;OK +--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 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 ++-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 + --vlan-id 2;=;FAIL + --vlan-prio 1;=;FAIL +diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c +index 43b3e3e9649b8..2b79ca951cd92 100644 +--- a/iptables/nft-bridge.c ++++ b/iptables/nft-bridge.c +@@ -344,7 +344,7 @@ static void nft_rule_to_ebtables_command_state(const struct nftnl_rule *r, + static void print_iface(const char *option, const char *name, bool invert) + { + if (*name) +- printf("%s%s %s ", invert ? "! " : "", option, name); ++ printf("%s%s %s ", option, invert ? " !" : "", name); + } + + static void nft_bridge_print_table_header(const char *tablename) +@@ -389,9 +389,9 @@ static void print_mac(char option, const unsigned char *mac, + const unsigned char *mask, + bool invert) + { ++ printf("-%c ", option); + if (invert) + printf("! "); +- printf("-%c ", option); + ebt_print_mac_and_mask(mac, mask); + printf(" "); + } +@@ -406,9 +406,9 @@ static void print_protocol(uint16_t ethproto, bool invert, unsigned int bitmask) + if (bitmask & EBT_NOPROTO) + return; + ++ printf("-p "); + if (invert) + printf("! "); +- printf("-p "); + + if (bitmask & EBT_802_3) { + printf("length "); +-- +2.21.0 + diff --git a/SOURCES/0049-arptables-Support-set-counters-option.patch b/SOURCES/0049-arptables-Support-set-counters-option.patch new file mode 100644 index 0000000..24dae96 --- /dev/null +++ b/SOURCES/0049-arptables-Support-set-counters-option.patch @@ -0,0 +1,42 @@ +From a4412aa91dff87ab27e4ad6e27f2a6c03ed0b5fb Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 22 Nov 2018 20:50:13 +0100 +Subject: [PATCH] arptables: Support --set-counters option + +Relevant code for this was already present (short option '-c'), just the +long option definition was missing. + +While being at it, add '-c' to help text. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit b0466ae6fbc0a93b69591171c54aa79063e23f3d) +Signed-off-by: Phil Sutter +--- + iptables/xtables-arp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c +index 18cdced627c55..85bcc841b21f5 100644 +--- a/iptables/xtables-arp.c ++++ b/iptables/xtables-arp.c +@@ -144,6 +144,7 @@ static struct option original_opts[] = { + { "help", 2, 0, 'h' }, + { "line-numbers", 0, 0, '0' }, + { "modprobe", 1, 0, 'M' }, ++ { "set-counters", 1, 0, 'c' }, + { 0 } + }; + +@@ -481,7 +482,7 @@ exit_printhelp(void) + " --line-numbers print line numbers when listing\n" + " --exact -x expand numbers (display exact values)\n" + " --modprobe= try to insert modules using this command\n" +-" --set-counters PKTS BYTES set the counter during insert/append\n" ++" --set-counters -c PKTS BYTES set the counter during insert/append\n" + "[!] --version -V print package version.\n"); + printf(" opcode strings: \n"); + for (i = 0; i < NUMOPCODES; i++) +-- +2.21.0 + diff --git a/SOURCES/0050-xshared-Explicitly-pass-target-to-command_jump.patch b/SOURCES/0050-xshared-Explicitly-pass-target-to-command_jump.patch new file mode 100644 index 0000000..040fd49 --- /dev/null +++ b/SOURCES/0050-xshared-Explicitly-pass-target-to-command_jump.patch @@ -0,0 +1,136 @@ +From 715e2fa36e08f0ee800347d8abea039e5347b1dc Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 5 Feb 2019 17:01:42 +0100 +Subject: [PATCH] xshared: Explicitly pass target to command_jump() + +The use of global 'optarg' variable inside that function is a mess, but +most importantly it limits its applicability to input parsers. Fix this +by having it take the option argument as a parameter. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 932d5c3fb94acc499c8a6264e354ab1e33316b72) +Signed-off-by: Phil Sutter +--- + iptables/ip6tables.c | 2 +- + iptables/iptables.c | 2 +- + iptables/xshared.c | 4 ++-- + iptables/xshared.h | 2 +- + iptables/xtables-arp.c | 2 +- + iptables/xtables-eb-translate.c | 2 +- + iptables/xtables-eb.c | 2 +- + iptables/xtables.c | 2 +- + 8 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c +index fe089de4c85d7..050afa9a36458 100644 +--- a/iptables/ip6tables.c ++++ b/iptables/ip6tables.c +@@ -1441,7 +1441,7 @@ int do_command6(int argc, char *argv[], char **table, + case 'j': + set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags, + cs.invert); +- command_jump(&cs); ++ command_jump(&cs, optarg); + break; + + +diff --git a/iptables/iptables.c b/iptables/iptables.c +index f8041f56ce70d..38c4bfe8ecf5c 100644 +--- a/iptables/iptables.c ++++ b/iptables/iptables.c +@@ -1421,7 +1421,7 @@ int do_command4(int argc, char *argv[], char **table, + case 'j': + set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags, + cs.invert); +- command_jump(&cs); ++ command_jump(&cs, optarg); + break; + + +diff --git a/iptables/xshared.c b/iptables/xshared.c +index b16f5fa68e569..fb186fb1ac657 100644 +--- a/iptables/xshared.c ++++ b/iptables/xshared.c +@@ -653,12 +653,12 @@ const char *xt_parse_target(const char *targetname) + return targetname; + } + +-void command_jump(struct iptables_command_state *cs) ++void command_jump(struct iptables_command_state *cs, const char *jumpto) + { + struct option *opts = xt_params->opts; + size_t size; + +- cs->jumpto = xt_parse_target(optarg); ++ cs->jumpto = xt_parse_target(jumpto); + /* TRY_LOAD (may be chain name) */ + cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD); + +diff --git a/iptables/xshared.h b/iptables/xshared.h +index db499f29236ed..fd1f96bad1b98 100644 +--- a/iptables/xshared.h ++++ b/iptables/xshared.h +@@ -176,6 +176,6 @@ void print_ifaces(const char *iniface, const char *outiface, uint8_t invflags, + + void command_match(struct iptables_command_state *cs); + const char *xt_parse_target(const char *targetname); +-void command_jump(struct iptables_command_state *cs); ++void command_jump(struct iptables_command_state *cs, const char *jumpto); + + #endif /* IPTABLES_XSHARED_H */ +diff --git a/iptables/xtables-arp.c b/iptables/xtables-arp.c +index 85bcc841b21f5..4a873b15c6833 100644 +--- a/iptables/xtables-arp.c ++++ b/iptables/xtables-arp.c +@@ -1161,7 +1161,7 @@ int do_commandarp(struct nft_handle *h, int argc, char *argv[], char **table, + case 'j': + set_option(&options, OPT_JUMP, &cs.arp.arp.invflags, + invert); +- command_jump(&cs); ++ command_jump(&cs, optarg); + break; + + case 'i': +diff --git a/iptables/xtables-eb-translate.c b/iptables/xtables-eb-translate.c +index 0fe14d2d0db32..96b2730fa97ed 100644 +--- a/iptables/xtables-eb-translate.c ++++ b/iptables/xtables-eb-translate.c +@@ -390,7 +390,7 @@ print_zero: + break; + } else if (c == 'j') { + ebt_check_option2(&flags, OPT_JUMP); +- command_jump(&cs); ++ command_jump(&cs, optarg); + break; + } else if (c == 's') { + ebt_check_option2(&flags, OPT_SOURCE); +diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c +index 55cb0fe204748..21344843a365a 100644 +--- a/iptables/xtables-eb.c ++++ b/iptables/xtables-eb.c +@@ -1022,7 +1022,7 @@ print_zero: + } else if (c == 'j') { + ebt_check_option2(&flags, OPT_JUMP); + if (strcmp(optarg, "CONTINUE") != 0) { +- command_jump(&cs); ++ command_jump(&cs, optarg); + } + break; + } else if (c == 's') { +diff --git a/iptables/xtables.c b/iptables/xtables.c +index eaa9fedeb03bb..1d777554076d7 100644 +--- a/iptables/xtables.c ++++ b/iptables/xtables.c +@@ -820,7 +820,7 @@ void do_parse(struct nft_handle *h, int argc, char *argv[], + case 'j': + set_option(&cs->options, OPT_JUMP, &cs->fw.ip.invflags, + cs->invert); +- command_jump(cs); ++ command_jump(cs, optarg); + break; + + +-- +2.21.0 + diff --git a/SOURCES/0051-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch b/SOURCES/0051-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch new file mode 100644 index 0000000..96d588d --- /dev/null +++ b/SOURCES/0051-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch @@ -0,0 +1,72 @@ +From e78321d1a719a5dc1b340292fc1971d4daf7e472 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 7 Feb 2019 22:08:53 +0100 +Subject: [PATCH] nft: Don't assume NFTNL_RULE_USERDATA holds a comment + +If this rule attribute is present but does not contain a comment, +get_comment() returns NULL which is then fed into strncpy() causing a +crash. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit d1df0a36b0486c780211cfa574301132bf55f194) +Signed-off-by: Phil Sutter +--- + iptables/nft-shared.c | 39 ++++++++++++++++++++++----------------- + 1 file changed, 22 insertions(+), 17 deletions(-) + +diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c +index ce40787f92f7d..fc484b49e2318 100644 +--- a/iptables/nft-shared.c ++++ b/iptables/nft-shared.c +@@ -639,25 +639,30 @@ void nft_rule_to_iptables_command_state(const struct nftnl_rule *r, + if (nftnl_rule_is_set(r, NFTNL_RULE_USERDATA)) { + const void *data; + uint32_t len, size; +- struct xtables_match *match; +- struct xt_entry_match *m; ++ const char *comment; + + data = nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len); +- match = xtables_find_match("comment", XTF_TRY_LOAD, +- &cs->matches); +- if (match == NULL) +- return; +- +- size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size; +- m = xtables_calloc(1, size); +- +- strncpy((char *)m->data, get_comment(data, len), +- match->size - 1); +- m->u.match_size = size; +- m->u.user.revision = 0; +- strcpy(m->u.user.name, match->name); +- +- match->m = m; ++ comment = get_comment(data, len); ++ if (comment) { ++ struct xtables_match *match; ++ struct xt_entry_match *m; ++ ++ match = xtables_find_match("comment", XTF_TRY_LOAD, ++ &cs->matches); ++ if (match == NULL) ++ return; ++ ++ size = XT_ALIGN(sizeof(struct xt_entry_match)) ++ + match->size; ++ m = xtables_calloc(1, size); ++ ++ strncpy((char *)m->data, comment, match->size - 1); ++ m->u.match_size = size; ++ m->u.user.revision = 0; ++ strcpy(m->u.user.name, match->name); ++ ++ match->m = m; ++ } + } + + if (cs->target != NULL) { +-- +2.21.0 + diff --git a/SOURCES/0052-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch b/SOURCES/0052-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch new file mode 100644 index 0000000..157825f --- /dev/null +++ b/SOURCES/0052-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch @@ -0,0 +1,41 @@ +From d418438f72d340866be241ca3867cf3ce3e04cf8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 7 Feb 2019 22:08:54 +0100 +Subject: [PATCH] nft: Introduce UDATA_TYPE_EBTABLES_POLICY + +This will be used later to identify ebtables user-defined chain policy +rules. + +Signed-off-by: Phil Sutter +Acked-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +(cherry picked from commit b06cc4e0f67f4beba7560fc329d20f108c87b5fb) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 2fa973cf03975..6129afdbad281 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -1115,6 +1115,7 @@ int add_counters(struct nftnl_rule *r, uint64_t packets, uint64_t bytes) + + enum udata_type { + UDATA_TYPE_COMMENT, ++ UDATA_TYPE_EBTABLES_POLICY, + __UDATA_TYPE_MAX, + }; + #define UDATA_TYPE_MAX (__UDATA_TYPE_MAX - 1) +@@ -1131,6 +1132,8 @@ static int parse_udata_cb(const struct nftnl_udata *attr, void *data) + if (value[len - 1] != '\0') + return -1; + break; ++ case UDATA_TYPE_EBTABLES_POLICY: ++ break; + default: + return 0; + } +-- +2.21.0 + diff --git a/SOURCES/0053-ebtables-nft-Support-user-defined-chain-policies.patch b/SOURCES/0053-ebtables-nft-Support-user-defined-chain-policies.patch new file mode 100644 index 0000000..1110b8e --- /dev/null +++ b/SOURCES/0053-ebtables-nft-Support-user-defined-chain-policies.patch @@ -0,0 +1,506 @@ +From bbbebb7449605e62a0901b8d81ea2ed45044088b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 7 Feb 2019 22:08:55 +0100 +Subject: [PATCH] ebtables-nft: Support user-defined chain policies + +Legacy ebtables supports policies for user-defined chains - and what's +worse, they default to ACCEPT unlike anywhere else. So lack of support +for this braindead feature in ebtables-nft is actually a change of +behaviour which very likely affects all ebtables users out there. + +The solution implemented here uses an implicit (and transparent) last +rule in all user-defined ebtables-nft chains with policy other than +RETURN. This rule is identified by an nft comment +"XTABLES_EB_INTERNAL_POLICY_RULE" (since commit ccf154d7420c0 ("xtables: +Don't use native nftables comments") nft comments are not used +otherwise). + +To minimize interference with existing code, this policy rule is removed +from chains during cache population and the policy is saved in +NFTNL_CHAIN_POLICY attribute. When committing changes to the kernel, +nft_commit() traverses through the list of chains and (re-)creates +policy rules if required. + +In ebtables-nft-restore, table flushes are problematic. To avoid weird +kernel error responses, introduce a custom 'table_flush' callback which +removes any pending policy rule add/remove jobs prior to creating the +NFT_COMPAT_TABLE_FLUSH one. + +I've hidden all this mess behind checks for h->family, so hopefully +impact on {ip,ip6,arp}tables-nft should be negligible. + +Signed-off-by: Phil Sutter +Acked-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +(cherry picked from commit aff1162b3e4b7ef805425a40306044c7d7dddc67) +Signed-off-by: Phil Sutter +--- + iptables/nft-bridge.c | 2 +- + iptables/nft.c | 228 +++++++++++++++++- + iptables/nft.h | 4 + + .../ebtables/0002-ebtables-save-restore_0 | 7 + + iptables/xtables-eb.c | 20 +- + iptables/xtables-restore.c | 23 +- + 6 files changed, 265 insertions(+), 19 deletions(-) + +diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c +index 2b79ca951cd92..a51792ef03ae1 100644 +--- a/iptables/nft-bridge.c ++++ b/iptables/nft-bridge.c +@@ -358,7 +358,7 @@ static void nft_bridge_print_header(unsigned int format, const char *chain, + bool basechain, uint32_t refs, uint32_t entries) + { + printf("Bridge chain: %s, entries: %u, policy: %s\n", +- chain, entries, basechain ? pol : "RETURN"); ++ chain, entries, pol ?: "RETURN"); + } + + static void print_matches_and_watchers(const struct iptables_command_state *cs, +diff --git a/iptables/nft.c b/iptables/nft.c +index 6129afdbad281..4fdc789d99928 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -55,6 +55,7 @@ + #include "nft.h" + #include "xshared.h" /* proto_to_name */ + #include "nft-shared.h" ++#include "nft-bridge.h" /* EBT_NOPROTO */ + #include "xtables-config-parser.h" + + static void *nft_fn; +@@ -1325,6 +1326,87 @@ retry: + return ret; + } + ++static bool nft_rule_is_policy_rule(struct nftnl_rule *r) ++{ ++ const struct nftnl_udata *tb[UDATA_TYPE_MAX + 1] = {}; ++ const void *data; ++ uint32_t len; ++ ++ if (!nftnl_rule_is_set(r, NFTNL_RULE_USERDATA)) ++ return false; ++ ++ data = nftnl_rule_get_data(r, NFTNL_RULE_USERDATA, &len); ++ if (nftnl_udata_parse(data, len, parse_udata_cb, tb) < 0) ++ return NULL; ++ ++ if (!tb[UDATA_TYPE_EBTABLES_POLICY] || ++ nftnl_udata_get_u32(tb[UDATA_TYPE_EBTABLES_POLICY]) != 1) ++ return false; ++ ++ return true; ++} ++ ++static struct nftnl_rule *nft_chain_last_rule(struct nftnl_chain *c) ++{ ++ struct nftnl_rule *r = NULL, *last; ++ struct nftnl_rule_iter *iter; ++ ++ iter = nftnl_rule_iter_create(c); ++ if (!iter) ++ return NULL; ++ ++ do { ++ last = r; ++ r = nftnl_rule_iter_next(iter); ++ } while (r); ++ nftnl_rule_iter_destroy(iter); ++ ++ return last; ++} ++ ++static void nft_bridge_chain_postprocess(struct nft_handle *h, ++ struct nftnl_chain *c) ++{ ++ struct nftnl_rule *last = nft_chain_last_rule(c); ++ struct nftnl_expr_iter *iter; ++ struct nftnl_expr *expr; ++ int verdict; ++ ++ if (!last || !nft_rule_is_policy_rule(last)) ++ return; ++ ++ iter = nftnl_expr_iter_create(last); ++ if (!iter) ++ return; ++ ++ expr = nftnl_expr_iter_next(iter); ++ if (!expr || ++ strcmp("counter", nftnl_expr_get_str(expr, NFTNL_EXPR_NAME))) ++ goto out_iter; ++ ++ expr = nftnl_expr_iter_next(iter); ++ if (!expr || ++ strcmp("immediate", nftnl_expr_get_str(expr, NFTNL_EXPR_NAME)) || ++ !nftnl_expr_is_set(expr, NFTNL_EXPR_IMM_VERDICT)) ++ goto out_iter; ++ ++ verdict = nftnl_expr_get_u32(expr, NFTNL_EXPR_IMM_VERDICT); ++ switch (verdict) { ++ case NF_ACCEPT: ++ case NF_DROP: ++ break; ++ default: ++ goto out_iter; ++ } ++ ++ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, verdict); ++ if (batch_rule_add(h, NFT_COMPAT_RULE_DELETE, last) < 0) ++ fprintf(stderr, "Failed to delete old policy rule\n"); ++ nftnl_chain_rule_del(last); ++out_iter: ++ nftnl_expr_iter_destroy(iter); ++} ++ + static int nftnl_rule_list_cb(const struct nlmsghdr *nlh, void *data) + { + struct nftnl_chain *c = data; +@@ -1378,6 +1460,10 @@ retry: + } + + nftnl_rule_free(rule); ++ ++ if (h->family == NFPROTO_BRIDGE) ++ nft_bridge_chain_postprocess(h, c); ++ + return 0; + } + +@@ -1443,6 +1529,15 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) + if (nftnl_chain_get(c, NFTNL_CHAIN_POLICY)) + pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); + policy = policy_name[pol]; ++ } else if (h->family == NFPROTO_BRIDGE) { ++ if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) { ++ uint32_t pol; ++ ++ pol = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); ++ policy = policy_name[pol]; ++ } else { ++ policy = "RETURN"; ++ } + } + + if (ops->save_chain) +@@ -1637,6 +1732,8 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl + + nftnl_chain_set(c, NFTNL_CHAIN_TABLE, (char *)table); + nftnl_chain_set(c, NFTNL_CHAIN_NAME, (char *)chain); ++ if (h->family == NFPROTO_BRIDGE) ++ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, NF_ACCEPT); + + ret = batch_chain_add(h, NFT_COMPAT_CHAIN_USER_ADD, c); + +@@ -2278,7 +2375,6 @@ static void __nft_print_header(struct nft_handle *h, + struct nftnl_chain *c, unsigned int format) + { + const char *chain_name = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); +- uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); + bool basechain = !!nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM); + uint32_t refs = nftnl_chain_get_u32(c, NFTNL_CHAIN_USE); + uint32_t entries = nft_rule_count(h, c); +@@ -2286,8 +2382,12 @@ static void __nft_print_header(struct nft_handle *h, + .pcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS), + .bcnt = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES), + }; ++ const char *pname = NULL; + +- ops->print_header(format, chain_name, policy_name[policy], ++ if (nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) ++ pname = policy_name[nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY)]; ++ ++ ops->print_header(format, chain_name, pname, + &ctrs, basechain, refs - entries, entries); + } + +@@ -2671,8 +2771,111 @@ static int nft_action(struct nft_handle *h, int action) + return ret == 0 ? 1 : 0; + } + ++static int ebt_add_policy_rule(struct nftnl_chain *c, void *data) ++{ ++ uint32_t policy = nftnl_chain_get_u32(c, NFTNL_CHAIN_POLICY); ++ struct iptables_command_state cs = { ++ .eb.bitmask = EBT_NOPROTO, ++ }; ++ struct nftnl_udata_buf *udata; ++ struct nft_handle *h = data; ++ struct nftnl_rule *r; ++ const char *pname; ++ ++ if (nftnl_chain_get(c, NFTNL_CHAIN_HOOKNUM)) ++ return 0; /* ignore base chains */ ++ ++ if (!nftnl_chain_is_set(c, NFTNL_CHAIN_POLICY)) ++ return 0; ++ ++ nftnl_chain_unset(c, NFTNL_CHAIN_POLICY); ++ ++ switch (policy) { ++ case NFT_RETURN: ++ return 0; /* return policy is default for nft chains */ ++ case NF_ACCEPT: ++ pname = "ACCEPT"; ++ break; ++ case NF_DROP: ++ pname = "DROP"; ++ break; ++ default: ++ return -1; ++ } ++ ++ command_jump(&cs, pname); ++ ++ r = nft_rule_new(h, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME), ++ nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), &cs); ++ if (!r) ++ return -1; ++ ++ udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN); ++ if (!udata) ++ return -1; ++ ++ if (!nftnl_udata_put_u32(udata, UDATA_TYPE_EBTABLES_POLICY, 1)) ++ return -1; ++ ++ nftnl_rule_set_data(r, NFTNL_RULE_USERDATA, ++ nftnl_udata_buf_data(udata), ++ nftnl_udata_buf_len(udata)); ++ nftnl_udata_buf_free(udata); ++ ++ if (batch_rule_add(h, NFT_COMPAT_RULE_APPEND, r) < 0) { ++ nftnl_rule_free(r); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int ebt_set_user_chain_policy(struct nft_handle *h, const char *table, ++ const char *chain, const char *policy) ++{ ++ struct nftnl_chain *c = nft_chain_find(h, table, chain); ++ int pval; ++ ++ if (!c) ++ return 0; ++ ++ if (!strcmp(policy, "DROP")) ++ pval = NF_DROP; ++ else if (!strcmp(policy, "ACCEPT")) ++ pval = NF_ACCEPT; ++ else if (!strcmp(policy, "RETURN")) ++ pval = NFT_RETURN; ++ else ++ return 0; ++ ++ nftnl_chain_set_u32(c, NFTNL_CHAIN_POLICY, pval); ++ return 1; ++} ++ ++static void nft_bridge_commit_prepare(struct nft_handle *h) ++{ ++ const struct builtin_table *t; ++ struct nftnl_chain_list *list; ++ int i; ++ ++ for (i = 0; i < NFT_TABLE_MAX; i++) { ++ t = &h->tables[i]; ++ ++ if (!t->name) ++ continue; ++ ++ list = h->table[t->type].chain_cache; ++ if (!list) ++ continue; ++ ++ nftnl_chain_list_foreach(list, ebt_add_policy_rule, h); ++ } ++} ++ + int nft_commit(struct nft_handle *h) + { ++ if (h->family == NFPROTO_BRIDGE) ++ nft_bridge_commit_prepare(h); + return nft_action(h, NFT_COMPAT_COMMIT); + } + +@@ -2681,6 +2884,27 @@ int nft_abort(struct nft_handle *h) + return nft_action(h, NFT_COMPAT_ABORT); + } + ++int nft_abort_policy_rule(struct nft_handle *h, const char *table) ++{ ++ struct obj_update *n, *tmp; ++ ++ list_for_each_entry_safe(n, tmp, &h->obj_list, head) { ++ if (n->type != NFT_COMPAT_RULE_APPEND && ++ n->type != NFT_COMPAT_RULE_DELETE) ++ continue; ++ ++ if (strcmp(table, ++ nftnl_rule_get_str(n->rule, NFTNL_RULE_TABLE))) ++ continue; ++ ++ if (!nft_rule_is_policy_rule(n->rule)) ++ continue; ++ ++ batch_obj_del(h, n); ++ } ++ return 0; ++} ++ + int nft_compatible_revision(const char *name, uint8_t rev, int opt) + { + struct mnl_socket *nl; +diff --git a/iptables/nft.h b/iptables/nft.h +index 0726923a63dd4..56dc207608855 100644 +--- a/iptables/nft.h ++++ b/iptables/nft.h +@@ -137,6 +137,7 @@ uint32_t nft_invflags2cmp(uint32_t invflags, uint32_t flag); + */ + int nft_commit(struct nft_handle *h); + int nft_abort(struct nft_handle *h); ++int nft_abort_policy_rule(struct nft_handle *h, const char *table); + + /* + * revision compatibility. +@@ -203,4 +204,7 @@ void nft_rule_to_arpt_entry(struct nftnl_rule *r, struct arpt_entry *fw); + + bool nft_is_table_compatible(struct nft_handle *h, const char *name); + ++int ebt_set_user_chain_policy(struct nft_handle *h, const char *table, ++ const char *chain, const char *policy); ++ + #endif +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 b23c1ee18c8ae..080ba49a4974d 100755 +--- a/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 ++++ b/iptables/tests/shell/testcases/ebtables/0002-ebtables-save-restore_0 +@@ -50,6 +50,9 @@ $XT_MULTI ebtables -A foo --pkttype-type multicast --limit 100 -j ACCEPT + + $XT_MULTI ebtables -A FORWARD -j foo + ++$XT_MULTI ebtables -N bar ++$XT_MULTI ebtables -P bar RETURN ++ + $XT_MULTI ebtables -t nat -A PREROUTING --redirect-target ACCEPT + #$XT_MULTI ebtables -t nat -A PREROUTING --to-src fe:ed:ba:be:00:01 + +@@ -59,6 +62,8 @@ $XT_MULTI ebtables -t nat -P OUTPUT DROP + $XT_MULTI ebtables -t nat -A POSTROUTING -j ACCEPT + #$XT_MULTI ebtables -t nat -A POSTROUTING --to-dst fe:ed:ba:be:00:01 --dnat-target ACCEPT + ++$XT_MULTI ebtables -t nat -N nat_foo -P DROP ++ + # compare against stored ebtables dump + + DUMP='*filter +@@ -66,6 +71,7 @@ DUMP='*filter + :FORWARD DROP + :OUTPUT ACCEPT + :foo ACCEPT ++:bar RETURN + -A INPUT -p IPv4 -i lo -j ACCEPT + -A FORWARD -j foo + -A OUTPUT -s Broadcast -j DROP +@@ -98,6 +104,7 @@ DUMP='*filter + :PREROUTING ACCEPT + :OUTPUT DROP + :POSTROUTING ACCEPT ++:nat_foo DROP + -A PREROUTING -j redirect + -A OUTPUT -j ACCEPT + -A POSTROUTING -j ACCEPT +diff --git a/iptables/xtables-eb.c b/iptables/xtables-eb.c +index 21344843a365a..d0f0026e9c538 100644 +--- a/iptables/xtables-eb.c ++++ b/iptables/xtables-eb.c +@@ -811,7 +811,6 @@ int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table, + case 'E': /* Rename chain */ + case 'X': /* Delete chain */ + /* We allow -N chainname -P policy */ +- /* XXX: Not in ebtables-compat */ + if (command == 'N' && c == 'P') { + command = c; + optind--; /* No table specified */ +@@ -1236,17 +1235,16 @@ print_zero: + + if (command == 'P') { + if (selected_chain < 0) { +- xtables_error(PARAMETER_PROBLEM, +- "Policy %s not allowed for user defined chains", +- policy); +- } +- if (strcmp(policy, "RETURN") == 0) { +- xtables_error(PARAMETER_PROBLEM, +- "Policy RETURN only allowed for user defined chains"); ++ ret = ebt_set_user_chain_policy(h, *table, chain, policy); ++ } else { ++ if (strcmp(policy, "RETURN") == 0) { ++ xtables_error(PARAMETER_PROBLEM, ++ "Policy RETURN only allowed for user defined chains"); ++ } ++ ret = nft_chain_set(h, *table, chain, policy, NULL); ++ if (ret < 0) ++ xtables_error(PARAMETER_PROBLEM, "Wrong policy"); + } +- ret = nft_chain_set(h, *table, chain, policy, NULL); +- if (ret < 0) +- xtables_error(PARAMETER_PROBLEM, "Wrong policy"); + } else if (command == 'L') { + ret = list_rules(h, chain, *table, rule_nr, + 0, +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index 4e00ed86be06d..6e6daffc9a1df 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -226,14 +226,20 @@ void xtables_restore_parse(struct nft_handle *h, + curtable->name, chain); + } else if (cb->chain_user_add && + cb->chain_user_add(h, chain, +- curtable->name) < 0) { +- if (errno == EEXIST) +- continue; +- ++ curtable->name) < 0 && ++ errno != EEXIST) { + xtables_error(PARAMETER_PROBLEM, + "cannot create chain " + "'%s' (%s)\n", chain, + strerror(errno)); ++ } else if (h->family == NFPROTO_BRIDGE && ++ !ebt_set_user_chain_policy(h, curtable->name, ++ chain, policy)) { ++ xtables_error(OTHER_PROBLEM, ++ "Can't set policy `%s'" ++ " on `%s' line %u: %s\n", ++ policy, chain, line, ++ ops->strerror(errno)); + } + ret = 1; + } else if (in_table) { +@@ -462,11 +468,18 @@ int xtables_ip6_restore_main(int argc, char *argv[]) + argc, argv); + } + ++static int ebt_table_flush(struct nft_handle *h, const char *table) ++{ ++ /* drop any pending policy rule add/removal jobs */ ++ nft_abort_policy_rule(h, table); ++ return nft_table_flush(h, table); ++} ++ + struct nft_xt_restore_cb ebt_restore_cb = { + .chain_list = get_chain_list, + .commit = nft_commit, + .table_new = nft_table_new, +- .table_flush = nft_table_flush, ++ .table_flush = ebt_table_flush, + .chain_user_flush = nft_chain_user_flush, + .do_command = do_commandeb, + .chain_set = nft_chain_set, +-- +2.21.0 + diff --git a/SOURCES/0054-extensions-libipt_realm-Document-allowed-realm-value.patch b/SOURCES/0054-extensions-libipt_realm-Document-allowed-realm-value.patch new file mode 100644 index 0000000..15e133f --- /dev/null +++ b/SOURCES/0054-extensions-libipt_realm-Document-allowed-realm-value.patch @@ -0,0 +1,30 @@ +From 8b69d66b21f3699ee64c572bfba5df033ce768e0 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Mon, 3 Dec 2018 14:52:28 +0100 +Subject: [PATCH] extensions: libipt_realm: Document allowed realm values + +Older versions of iptables allowed for negative realm values by accident +(they would be cast to unsigned). While this was clearly a bug, document +the fixed behaviour. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 290d76b443bf24999d9caacb3fdd027d6e7112a1) +Signed-off-by: Phil Sutter +--- + extensions/libipt_realm.man | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/extensions/libipt_realm.man b/extensions/libipt_realm.man +index a40b1adc72ba2..72dff9b2e4212 100644 +--- a/extensions/libipt_realm.man ++++ b/extensions/libipt_realm.man +@@ -5,3 +5,5 @@ setups involving dynamic routing protocols like BGP. + Matches a given realm number (and optionally mask). If not a number, value + can be a named realm from /etc/iproute2/rt_realms (mask can not be used in + that case). ++Both value and mask are four byte unsigned integers and may be specified in ++decimal, hex (by prefixing with "0x") or octal (if a leading zero is given). +-- +2.21.0 + diff --git a/SOURCES/0055-extensions-TRACE-Point-at-xtables-monitor-in-documen.patch b/SOURCES/0055-extensions-TRACE-Point-at-xtables-monitor-in-documen.patch new file mode 100644 index 0000000..83d5163 --- /dev/null +++ b/SOURCES/0055-extensions-TRACE-Point-at-xtables-monitor-in-documen.patch @@ -0,0 +1,51 @@ +From 39808343b03078f992bc5e831ccdd843312f0714 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 18 Dec 2018 12:16:30 +0100 +Subject: [PATCH] extensions: TRACE: Point at xtables-monitor in documentation + +With iptables-nft, logging of trace events is different from legacy. +Explain why and hint at how to receive events in this case. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 9ac39888722ee9c7e97d9b8cb9eb4f33b582130a) +Signed-off-by: Phil Sutter +--- + extensions/libxt_TRACE.man | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/extensions/libxt_TRACE.man b/extensions/libxt_TRACE.man +index 8d590a52e26f8..5187a8d22802f 100644 +--- a/extensions/libxt_TRACE.man ++++ b/extensions/libxt_TRACE.man +@@ -1,13 +1,20 @@ + This target marks packets so that the kernel will log every rule which match +-the packets as those traverse the tables, chains, rules. ++the packets as those traverse the tables, chains, rules. It can only be used in ++the ++.BR raw ++table. + .PP +-A logging backend, such as ip(6)t_LOG or nfnetlink_log, must be loaded for this +-to be visible. ++With iptables-legacy, a logging backend, such as ip(6)t_LOG or nfnetlink_log, ++must be loaded for this to be visible. + The packets are logged with the string prefix: + "TRACE: tablename:chainname:type:rulenum " where type can be "rule" for + plain rule, "return" for implicit rule at the end of a user defined chain + and "policy" for the policy of the built in chains. +-.br +-It can only be used in the +-.BR raw +-table. ++.PP ++With iptables-nft, the target is translated into nftables' ++.B "meta nftrace" ++expression. Hence the kernel sends trace events via netlink to userspace where ++they may be displayed using ++.B "xtables-monitor --trace" ++command. For details, refer to ++.BR xtables-monitor (8). +-- +2.21.0 + diff --git a/SOURCES/0056-xtables-Catch-errors-when-zeroing-rule-rounters.patch b/SOURCES/0056-xtables-Catch-errors-when-zeroing-rule-rounters.patch new file mode 100644 index 0000000..3d9de2c --- /dev/null +++ b/SOURCES/0056-xtables-Catch-errors-when-zeroing-rule-rounters.patch @@ -0,0 +1,33 @@ +From 4a6f89b263a62f078e73cbc01d09330a217a23c7 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sat, 15 Dec 2018 19:25:04 +0100 +Subject: [PATCH] xtables: Catch errors when zeroing rule rounters + +Covscan complained about call to batch_rule_add() not being checked. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 4c54c892443c20a1d0e1212d541da0e81647058a) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 4fdc789d99928..2d527358cc7f2 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -3218,7 +3218,9 @@ static int __nft_chain_zero_counters(struct nftnl_chain *c, void *data) + * rule based on its handle only. + */ + nftnl_rule_unset(r, NFTNL_RULE_POSITION); +- batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r); ++ ret = batch_rule_add(h, NFT_COMPAT_RULE_REPLACE, r); ++ if (ret) ++ return -1; + } + r = nftnl_rule_iter_next(iter); + } +-- +2.21.0 + diff --git a/SOURCES/0057-xtables-save-Fix-table-not-found-error-message.patch b/SOURCES/0057-xtables-save-Fix-table-not-found-error-message.patch new file mode 100644 index 0000000..97b81f8 --- /dev/null +++ b/SOURCES/0057-xtables-save-Fix-table-not-found-error-message.patch @@ -0,0 +1,37 @@ +From a63cf723111d323afab642e6f6b12a5da660fd5b Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 7 Feb 2019 22:13:31 +0100 +Subject: [PATCH] xtables-save: Fix table not found error message + +First of all, this error message should not appear on stdout, otherwise +it may end in dump files. Next, with completely empty ruleset, even +valid table names cause errors. To avoid this, continue operation if the +not found table is a builtin one. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 2478b6cbb8112f940cec61ec1e62a598472d33d0) +Signed-off-by: Phil Sutter +--- + iptables/xtables-save.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c +index 414a864b6196b..87ebb913f33b7 100644 +--- a/iptables/xtables-save.c ++++ b/iptables/xtables-save.c +@@ -105,8 +105,9 @@ do_output(struct nft_handle *h, const char *tablename, bool counters) + return !!ret; + } + +- if (!nft_table_find(h, tablename)) { +- printf("Table `%s' does not exist\n", tablename); ++ if (!nft_table_find(h, tablename) && ++ !nft_table_builtin_find(h, tablename)) { ++ fprintf(stderr, "Table `%s' does not exist\n", tablename); + return 1; + } + +-- +2.21.0 + diff --git a/SOURCES/0058-arptables-nft-fix-decoding-of-hlen-on-bigendian-plat.patch b/SOURCES/0058-arptables-nft-fix-decoding-of-hlen-on-bigendian-plat.patch new file mode 100644 index 0000000..38a0a5c --- /dev/null +++ b/SOURCES/0058-arptables-nft-fix-decoding-of-hlen-on-bigendian-plat.patch @@ -0,0 +1,49 @@ +From dc38548e6f745bcfb141324b36307dbfa941eabd Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Fri, 22 Feb 2019 13:26:05 +0100 +Subject: [PATCH] arptables-nft: fix decoding of hlen on bigendian platforms + +The existing test fail with: +extensions/libarpt_standard.t: ERROR: line 2 (cannot find: arptables -I INPUT -s 192.168.0.1) + +... because hlen is 0 instead of expected "6". +The rule is correct, i.e. this is a decode/display bug: arp_hlen is +specified as 'unsigned short' instead of uint8_t. + +On LSB systems, this doesn't matter but on MSB the value then is '0x600' +instead of '0x006' which becomes 0 when assignment to the u8 header field. + +Signed-off-by: Florian Westphal +Acked-by: Phil Sutter +(cherry picked from commit d68672a641439b72bccfcb39d50f26fe3f915c19) +Signed-off-by: Phil Sutter +--- + iptables/nft-arp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index 37b0985377bef..b436570291b7c 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -338,7 +338,8 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx, + struct iptables_command_state *cs = data; + struct arpt_entry *fw = &cs->arp; + struct in_addr addr; +- unsigned short int ar_hrd, ar_pro, ar_op, ar_hln; ++ uint16_t ar_hrd, ar_pro, ar_op; ++ uint8_t ar_hln; + bool inv; + + switch (ctx->payload.offset) { +@@ -364,7 +365,7 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx, + fw->arp.invflags |= ARPT_INV_ARPOP; + break; + case offsetof(struct arphdr, ar_hln): +- get_cmp_data(e, &ar_hln, sizeof(ar_op), &inv); ++ get_cmp_data(e, &ar_hln, sizeof(ar_hln), &inv); + fw->arp.arhln = ar_hln; + fw->arp.arhln_mask = 0xff; + if (inv) +-- +2.21.0 + diff --git a/SOURCES/0059-extensions-libip6t_mh-fix-bogus-translation-error.patch b/SOURCES/0059-extensions-libip6t_mh-fix-bogus-translation-error.patch new file mode 100644 index 0000000..aa3d991 --- /dev/null +++ b/SOURCES/0059-extensions-libip6t_mh-fix-bogus-translation-error.patch @@ -0,0 +1,32 @@ +From a1e2de039a97f5ee8f5d7ebd34c82ff48c0fa345 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Mon, 19 Nov 2018 14:09:20 +0100 +Subject: [PATCH] extensions: libip6t_mh: fix bogus translation error + + libip6t_mh.txlate: Fail + src: ip6tables-translate -A INPUT -p mh --mh-type 1 -j ACCEPT + exp: nft add rule ip6 filter INPUT meta l4proto 135 mh type 1 counter accept + res: nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1 counter accept + +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 5839d7fe62ff667af7132fc7d589b386951f27b3) +Signed-off-by: Phil Sutter +--- + extensions/libip6t_mh.txlate | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/extensions/libip6t_mh.txlate b/extensions/libip6t_mh.txlate +index ccc07c3d5ecb1..f5d638c09ca8a 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 135 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 135 mh type 1-3 counter accept ++nft add rule ip6 filter INPUT meta l4proto mobility-header mh type 1-3 counter accept +-- +2.21.0 + diff --git a/SOURCES/0060-xtables-save-Point-at-existing-man-page-in-help-text.patch b/SOURCES/0060-xtables-save-Point-at-existing-man-page-in-help-text.patch new file mode 100644 index 0000000..c3c691e --- /dev/null +++ b/SOURCES/0060-xtables-save-Point-at-existing-man-page-in-help-text.patch @@ -0,0 +1,50 @@ +From 8a192868ba7dd55a0465f07d8fb42d26dff566d3 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 13 Mar 2019 20:46:17 +0100 +Subject: [PATCH] xtables-save: Point at existing man page in help text + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 934479aa1f1576afba97b137a101a60d8534370c) +Signed-off-by: Phil Sutter +--- + iptables/xtables-save.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c +index 87ebb913f33b7..2cc5a7c7540be 100644 +--- a/iptables/xtables-save.c ++++ b/iptables/xtables-save.c +@@ -187,7 +187,8 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[]) + exit(0); + default: + fprintf(stderr, +- "Look at manual page `xtables-save.8' for more information.\n"); ++ "Look at manual page `%s.8' for more information.\n", ++ prog_name); + exit(1); + } + } +@@ -333,7 +334,8 @@ int xtables_eb_save_main(int argc_, char *argv_[]) + exit(0); + default: + fprintf(stderr, +- "Look at manual page `xtables-save.8' for more information.\n"); ++ "Look at manual page `%s.8' for more information.\n", ++ prog_name); + exit(1); + } + } +@@ -380,7 +382,8 @@ int xtables_arp_save_main(int argc, char **argv) + exit(0); + default: + fprintf(stderr, +- "Look at manual page `xtables-save.8' for more information.\n"); ++ "Look at manual page `%s.8' for more information.\n", ++ prog_name); + exit(1); + } + } +-- +2.21.0 + diff --git a/SOURCES/0061-xtables-restore-Fix-program-names-in-help-texts.patch b/SOURCES/0061-xtables-restore-Fix-program-names-in-help-texts.patch new file mode 100644 index 0000000..7d2b4f3 --- /dev/null +++ b/SOURCES/0061-xtables-restore-Fix-program-names-in-help-texts.patch @@ -0,0 +1,86 @@ +From 4c351ba82a79b2781fc580f3f5473da0e5a276b8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Sat, 8 Jun 2019 19:34:13 +0200 +Subject: [PATCH] xtables-restore: Fix program names in help texts + +Avoid referring to wrong or even non-existent commands: + +* When calling xtables_restore_main(), pass the actual program name + taken from argv[0]. +* Use 'prog_name' in unknown parameter and help output instead of + 'xtables-restore' which probably doesn't exist. +* While being at it, fix false whitespace in help text. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit ac531b4681d1a0309a738d7bc3408fc2270eaa03) + +Conflicts: + iptables/xtables-restore.c +-> missing commit 093cec72e7f77 ("src: replace IPTABLES_VERSION by PACKAGE_VERSION") + +Signed-off-by: Phil Sutter +--- + iptables/xtables-restore.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/iptables/xtables-restore.c b/iptables/xtables-restore.c +index 6e6daffc9a1df..7c2759a3c5932 100644 +--- a/iptables/xtables-restore.c ++++ b/iptables/xtables-restore.c +@@ -7,6 +7,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -51,7 +52,7 @@ static void print_usage(const char *name, const char *version) + " [ --help ]\n" + " [ --noflush ]\n" + " [ --table= ]\n" +- " [ --modprobe= ]\n" ++ " [ --modprobe= ]\n" + " [ --ipv4 ]\n" + " [ --ipv6 ]\n", name); + } +@@ -376,8 +377,7 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + p.testing = 1; + break; + case 'h': +- print_usage("xtables-restore", +- IPTABLES_VERSION); ++ print_usage(prog_name, IPTABLES_VERSION); + exit(0); + case 'n': + noflush = 1; +@@ -402,7 +402,8 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + break; + default: + fprintf(stderr, +- "Try `xtables-restore -h' for more information.\n"); ++ "Try `%s -h' for more information.\n", ++ prog_name); + exit(1); + } + } +@@ -458,13 +459,13 @@ xtables_restore_main(int family, const char *progname, int argc, char *argv[]) + + int xtables_ip4_restore_main(int argc, char *argv[]) + { +- return xtables_restore_main(NFPROTO_IPV4, "iptables-restore", ++ return xtables_restore_main(NFPROTO_IPV4, basename(*argv), + argc, argv); + } + + int xtables_ip6_restore_main(int argc, char *argv[]) + { +- return xtables_restore_main(NFPROTO_IPV6, "ip6tables-restore", ++ return xtables_restore_main(NFPROTO_IPV6, basename(*argv), + argc, argv); + } + +-- +2.21.0 + diff --git a/SOURCES/0062-extensions-AUDIT-Document-ineffective-type-option.patch b/SOURCES/0062-extensions-AUDIT-Document-ineffective-type-option.patch new file mode 100644 index 0000000..a22d248 --- /dev/null +++ b/SOURCES/0062-extensions-AUDIT-Document-ineffective-type-option.patch @@ -0,0 +1,37 @@ +From 31695c75575f3998ac0c5d466d0b85276289a730 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 21 Feb 2019 15:38:47 +0100 +Subject: [PATCH] extensions: AUDIT: Document ineffective --type option + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit dffb5ec2a8c7f91351e2a1029a757cb1f41f2d02) +Signed-off-by: Phil Sutter +--- + extensions/libxt_AUDIT.man | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/extensions/libxt_AUDIT.man b/extensions/libxt_AUDIT.man +index cd796967c431a..4f5562e8ca425 100644 +--- a/extensions/libxt_AUDIT.man ++++ b/extensions/libxt_AUDIT.man +@@ -3,12 +3,14 @@ It can be used to record accepted, dropped, and rejected packets. See + auditd(8) for additional details. + .TP + \fB\-\-type\fP {\fBaccept\fP|\fBdrop\fP|\fBreject\fP} +-Set type of audit record. ++Set type of audit record. Starting with linux-4.12, this option has no effect ++on generated audit messages anymore. It is still accepted by iptables for ++compatibility reasons, but ignored. + .PP + Example: + .IP + iptables \-N AUDIT_DROP + .IP +-iptables \-A AUDIT_DROP \-j AUDIT \-\-type drop ++iptables \-A AUDIT_DROP \-j AUDIT + .IP + iptables \-A AUDIT_DROP \-j DROP +-- +2.21.0 + diff --git a/SOURCES/0063-utils-Add-a-manpage-for-nfbpf_compile.patch b/SOURCES/0063-utils-Add-a-manpage-for-nfbpf_compile.patch new file mode 100644 index 0000000..43b158a --- /dev/null +++ b/SOURCES/0063-utils-Add-a-manpage-for-nfbpf_compile.patch @@ -0,0 +1,140 @@ +From b3d9e7d73221e1f7efe9bd7052e85163e5de65aa Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 16 Jan 2019 22:47:59 +0100 +Subject: [PATCH] utils: Add a manpage for nfbpf_compile + +Content is rather sparse, but still better than no manpage at all. + +Cc: Willem de Bruijn +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 032dc4a18ab86173847b6016baf0819ccd7641c5) +Signed-off-by: Phil Sutter +--- + configure.ac | 3 +- + utils/.gitignore | 1 + + utils/Makefile.am | 3 +- + utils/nfbpf_compile.8.in | 70 ++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 75 insertions(+), 2 deletions(-) + create mode 100644 utils/nfbpf_compile.8.in + +diff --git a/configure.ac b/configure.ac +index 448ec918fd89b..e6c9832fa43ba 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -252,7 +252,8 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile + libxtables/Makefile utils/Makefile + include/xtables-version.h include/iptables/internal.h + iptables/xtables-monitor.8 +- utils/nfnl_osf.8]) ++ utils/nfnl_osf.8 ++ utils/nfbpf_compile.8]) + AC_OUTPUT + + +diff --git a/utils/.gitignore b/utils/.gitignore +index 7c6afbf4e6a52..6300812b1701b 100644 +--- a/utils/.gitignore ++++ b/utils/.gitignore +@@ -1,3 +1,4 @@ + /nfnl_osf + /nfnl_osf.8 + /nfbpf_compile ++/nfbpf_compile.8 +diff --git a/utils/Makefile.am b/utils/Makefile.am +index 80029e303ff3b..d09a69749b85f 100644 +--- a/utils/Makefile.am ++++ b/utils/Makefile.am +@@ -17,6 +17,7 @@ nfnl_osf_LDADD = ${libnfnetlink_LIBS} + endif + + if ENABLE_BPFC ++man_MANS += nfbpf_compile.8 + sbin_PROGRAMS += nfbpf_compile + nfbpf_compile_LDADD = -lpcap + endif +@@ -26,4 +27,4 @@ sbin_PROGRAMS += nfsynproxy + nfsynproxy_LDADD = -lpcap + endif + +-CLEANFILES = nfnl_osf.8 ++CLEANFILES = nfnl_osf.8 nfbpf_compile.8 +diff --git a/utils/nfbpf_compile.8.in b/utils/nfbpf_compile.8.in +new file mode 100644 +index 0000000000000..d02979a5143ef +--- /dev/null ++++ b/utils/nfbpf_compile.8.in +@@ -0,0 +1,70 @@ ++.TH NFBPF_COMPILE 8 "" "@PACKAGE_STRING@" "@PACKAGE_STRING@" ++ ++.SH NAME ++nfbpf_compile \- generate bytecode for use with xt_bpf ++.SH SYNOPSIS ++ ++.ad l ++.in +8 ++.ti -8 ++.B nfbpf_compile ++[ ++.I LLTYPE ++] ++.I PROGRAM ++ ++.ti -8 ++.I LLTYPE ++:= { ++.BR EN10MB " | " RAW " | " SLIP " | " ++.I ... ++} ++ ++.SH DESCRIPTION ++The ++.B nfbpf_compile ++utility aids in generating BPF byte code suitable for passing to ++the iptables ++.B bpf ++match. ++ ++.SH OPTIONS ++ ++.TP ++.I LLTYPE ++Link-layer header type to operate on. This is a name as defined in ++.RB < pcap/dlt.h > ++but with the leading ++.B DLT_ ++prefix stripped. For use with iptables, ++.B RAW ++should be the right choice (it's also the default if not specified). ++ ++.TP ++.I PROGRAM ++The BPF expression to compile, see ++.BR pcap-filter (7) ++for a description of the language. ++ ++.SH EXIT STATUS ++The program returns 0 on success, 1 otherwise. ++ ++.SH EXAMPLE ++Match incoming TCP packets with size bigger than 100 bytes: ++.P ++.in +8 ++.EE ++bpf=$(nfbpf_compile 'tcp and greater 100') ++.br ++iptables -A INPUT -m bpf --bytecode "$bpf" -j ACCEPT ++.RE ++.P ++The description of ++.B bpf ++match in ++.BR iptables-extensions (8) ++lists a few more examples. ++ ++.SH SEE ALSO ++.BR iptables-extensions (8), ++.BR pcap-filter (7) +-- +2.21.0 + diff --git a/SOURCES/arptables-helper b/SOURCES/arptables-helper new file mode 100644 index 0000000..4039e7d --- /dev/null +++ b/SOURCES/arptables-helper @@ -0,0 +1,89 @@ +#!/bin/bash +# config: /etc/sysconfig/arptables + +# Source 'em up +. /etc/init.d/functions + +ARPTABLES_CONFIG=/etc/sysconfig/arptables + +flush_delete_chains() { + echo -n $"Flushing all chains: " + if arptables -F; then + success + else + failure + fi + echo + + echo -n $"Removing user defined chains: " + if arptables -X; then + success + else + failure + fi + echo +} + +start() { + if [ ! -x /usr/sbin/arptables ]; then + exit 4 + fi + + # don't do squat if we don't have the config file + if [ -f $ARPTABLES_CONFIG ]; then + # If we don't clear these first, we might be adding to + # pre-existing rules. + flush_delete_chains + + arptables -Z + + echo -n $"Applying arptables firewall rules: " + /usr/sbin/arptables-restore < $ARPTABLES_CONFIG && \ + success || \ + failure + echo + touch /var/lock/subsys/arptables + else + failure + echo + echo $"Configuration file /etc/sysconfig/arptables missing" + exit 6 + fi +} + +stop() { + flush_delete_chains + echo -n $"Resetting built-in chains to the default ACCEPT policy:" + arptables -P INPUT ACCEPT && \ + arptables -P OUTPUT ACCEPT && \ + success || \ + failure + echo + rm -f /var/lock/subsys/arptables +} + +case "$1" in +start) + start + ;; + +stop) + stop + ;; + +restart|reload) + # "restart" is really just "start" as this isn't a daemon, + # and "start" clears any pre-defined rules anyway. + # This is really only here to make those who expect it happy + start + ;; + +condrestart|try-restart|force-reload) + [ -e /var/lock/subsys/arptables ] && start + ;; + +*) + exit 2 +esac + +exit 0 diff --git a/SOURCES/arptables.8 b/SOURCES/arptables.8 new file mode 100644 index 0000000..6a5e21d --- /dev/null +++ b/SOURCES/arptables.8 @@ -0,0 +1,330 @@ +.TH ARPTABLES 8 "November 2011" +.\" +.\" Man page originally written by Jochen Friedrich , +.\" maintained by Bart De Schuymer. +.\" It is based on the iptables man page. +.\" +.\" Iptables page by Herve Eychenne March 2000. +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.\" +.SH NAME +arptables \- ARP table administration +.SH SYNOPSIS +.BR "arptables " [ "-t table" ] " -" [ AD ] " chain rule-specification " [ options ] +.br +.BR "arptables " [ "-t table" ] " -" [ RI ] " chain rulenum rule-specification " [ options ] +.br +.BR "arptables " [ "-t table" ] " -D chain rulenum " [ options ] +.br +.BR "arptables " [ "-t table" ] " -" [ "LFZ" ] " " [ chain ] " " [ options ] +.br +.BR "arptables " [ "-t table" ] " -" [ "NX" ] " chain" +.br +.BR "arptables " [ "-t table" ] " -E old-chain-name new-chain-name" +.br +.BR "arptables " [ "-t table" ] " -P chain target " [ options ] +.SH DESCRIPTION +.B arptables +is a user space tool, it is used to set up and maintain the +tables of ARP rules in the Linux kernel. These rules inspect +the ARP frames which they see. +.B arptables +is analogous to the +.B iptables +user space tool, but +.B arptables +is less complicated. + +.SS CHAINS +The kernel table is used to divide functionality into +different sets of rules. Each set of rules is called a chain. +Each chain is an ordered list of rules that can match ARP frames. If a +rule matches an ARP frame, then a processing specification tells +what to do with that matching frame. The processing specification is +called a 'target'. However, if the frame does not match the current +rule in the chain, then the next rule in the chain is examined and so forth. +The user can create new (user-defined) chains which can be used as the 'target' of a rule. + +.SS TARGETS +A firewall rule specifies criteria for an ARP frame and a frame +processing specification called a target. When a frame matches a rule, +then the next action performed by the kernel is specified by the target. +The target can be one of these values: +.IR ACCEPT , +.IR DROP , +.IR CONTINUE , +.IR RETURN , +an 'extension' (see below) or a user-defined chain. +.PP +.I ACCEPT +means to let the frame through. +.I DROP +means the frame has to be dropped. +.I CONTINUE +means the next rule has to be checked. This can be handy to know how many +frames pass a certain point in the chain or to log those frames. +.I RETURN +means stop traversing this chain and resume at the next rule in the +previous (calling) chain. +For the extension targets please see the +.B "TARGET EXTENSIONS" +section of this man page. +.SS TABLES +There is only one ARP table in the Linux +kernel. The table is +.BR filter. +You can drop the '-t filter' argument to the arptables command. +The -t argument must be the +first argument on the arptables command line, if used. +.TP +.B "-t, --table" +.br +.BR filter , +is the only table and contains two built-in chains: +.B INPUT +(for frames destined for the host) and +.B OUTPUT +(for locally-generated frames). +.br +.br +.SH ARPTABLES COMMAND LINE ARGUMENTS +After the initial arptables command line argument, the remaining +arguments can be divided into several different groups. These groups +are commands, miscellaneous commands, rule-specifications, match-extensions, +and watcher-extensions. +.SS COMMANDS +The arptables command arguments specify the actions to perform on the table +defined with the -t argument. If you do not use the -t argument to name +a table, the commands apply to the default filter table. +With the exception of the +.B "-Z" +command, only one command may be used on the command line at a time. +.TP +.B "-A, --append" +Append a rule to the end of the selected chain. +.TP +.B "-D, --delete" +Delete the specified rule from the selected chain. There are two ways to +use this command. The first is by specifying an interval of rule numbers +to delete, syntax: start_nr[:end_nr]. Using negative numbers is allowed, for more +details about using negative numbers, see the -I command. The second usage is by +specifying the complete rule as it would have been specified when it was added. +.TP +.B "-I, --insert" +Insert the specified rule into the selected chain at the specified rule number. +If the current number of rules equals N, then the specified number can be +between -N and N+1. For a positive number i, it holds that i and i-N-1 specify the +same place in the chain where the rule should be inserted. The number 0 specifies +the place past the last rule in the chain and using this number is therefore +equivalent with using the -A command. +.TP +.B "-R, --replace" +Replaces the specified rule into the selected chain at the specified rule number. +If the current number of rules equals N, then the specified number can be +between 1 and N. i specifies the place in the chain where the rule should be replaced. +.TP +.B "-P, --policy" +Set the policy for the chain to the given target. The policy can be +.BR ACCEPT ", " DROP " or " RETURN . +.TP +.B "-F, --flush" +Flush the selected chain. If no chain is selected, then every chain will be +flushed. Flushing the chain does not change the policy of the +chain, however. +.TP +.B "-Z, --zero" +Set the counters of the selected chain to zero. If no chain is selected, all the counters +are set to zero. The +.B "-Z" +command can be used in conjunction with the +.B "-L" +command. +When both the +.B "-Z" +and +.B "-L" +commands are used together in this way, the rule counters are printed on the screen +before they are set to zero. +.TP +.B "-L, --list" +List all rules in the selected chain. If no chain is selected, all chains +are listed. +.TP +.B "-N, --new-chain" +Create a new user-defined chain with the given name. The number of +user-defined chains is unlimited. A user-defined chain name has maximum +length of 31 characters. +.TP +.B "-X, --delete-chain" +Delete the specified user-defined chain. There must be no remaining references +to the specified chain, otherwise +.B arptables +will refuse to delete it. If no chain is specified, all user-defined +chains that aren't referenced will be removed. +.TP +.B "-E, --rename-chain" +Rename the specified chain to a new name. Besides renaming a user-defined +chain, you may rename a standard chain name to a name that suits your +taste. For example, if you like PREBRIDGING more than PREROUTING, +then you can use the -E command to rename the PREROUTING chain. If you do +rename one of the standard +.B arptables +chain names, please be sure to mention +this fact should you post a question on the +.B arptables +mailing lists. +It would be wise to use the standard name in your post. Renaming a standard +.B arptables +chain in this fashion has no effect on the structure or function +of the +.B arptables +kernel table. + +.SS MISCELLANOUS COMMANDS +.TP +.B "-V, --version" +Show the version of the arptables userspace program. +.TP +.B "-h, --help" +Give a brief description of the command syntax. +.TP +.BR "-j, --jump " "\fItarget\fP" +The target of the rule. This is one of the following values: +.BR ACCEPT , +.BR DROP , +.BR CONTINUE , +.BR RETURN , +a target extension (see +.BR "TARGET EXTENSIONS" ")" +or a user-defined chain name. +.TP +.BI "-c, --set-counters " "PKTS BYTES" +This enables the administrator to initialize the packet and byte +counters of a rule (during +.B INSERT, +.B APPEND, +.B REPLACE +operations). + +.SS RULE-SPECIFICATIONS +The following command line arguments make up a rule specification (as used +in the add and delete commands). A "!" option before the specification +inverts the test for that specification. Apart from these standard rule +specifications there are some other command line arguments of interest. +.TP +.BR "-s, --source-ip " "[!] \fIaddress\fP[/\fImask]\fP" +The Source IP specification. +.TP +.BR "-d, --destination-ip " "[!] \fIaddress\fP[/\fImask]\fP" +The Destination IP specification. +.TP +.BR "--source-mac " "[!] \fIaddress\fP[/\fImask\fP]" +The source mac address. Both mask and address are written as 6 hexadecimal +numbers separated by colons. +.TP +.BR "--destination-mac " "[!] \fIaddress\fP[/\fImask\fP]" +The destination mac address. Both mask and address are written as 6 hexadecimal +numbers separated by colons. +.TP +.BR "-i, --in-interface " "[!] \fIname\fP" +The interface via which a frame is received (for the +.B INPUT +chain). The flag +.B --in-if +is an alias for this option. +.TP +.BR "-o, --out-interface " "[!] \fIname\fP" +The interface via which a frame is going to be sent (for the +.B OUTPUT +chain). The flag +.B --out-if +is an alias for this option. +.TP +.BR "-l, --h-length " "\fIlength\fP[/\fImask\fP]" +The hardware length (nr of bytes) +.TP +.BR "--opcode " "\fIcode\fP[/\fImask\fP] +The operation code (2 bytes). Available values are: +.BR 1 = Request +.BR 2 = Reply +.BR 3 = Request_Reverse +.BR 4 = Reply_Reverse +.BR 5 = DRARP_Request +.BR 6 = DRARP_Reply +.BR 7 = DRARP_Error +.BR 8 = InARP_Request +.BR 9 = ARP_NAK . +.TP +.BR "--h-type " "\fItype\fP[/\fImask\fP]" +The hardware type (2 bytes, hexadecimal). Available values are: +.BR 1 = Ethernet . +.TP +.BR "--proto-type " "\fItype\fP[/\fImask\fP]" +The protocol type (2 bytes). Available values are: +.BR 0x800 = IPv4 . + +.SS TARGET-EXTENSIONS +.B arptables +extensions are precompiled into the userspace tool. So there is no need +to explicitly load them with a -m option like in +.BR iptables . +However, these +extensions deal with functionality supported by supplemental kernel modules. +.SS mangle +.TP +.BR "--mangle-ip-s IP address" +Mangles Source IP Address to given value. +.TP +.BR "--mangle-ip-d IP address" +Mangles Destination IP Address to given value. +.TP +.BR "--mangle-mac-s MAC address" +Mangles Source MAC Address to given value. +.TP +.BR "--mangle-mac-d MAC address" +Mangles Destination MAC Address to given value. +.TP +.BR "--mangle-target target " +Target of ARP mangle operation +.BR "" ( DROP ", " CONTINUE " or " ACCEPT " -- default is " ACCEPT ). +.SS CLASSIFY +This module allows you to set the skb->priority value (and thus clas- +sify the packet into a specific CBQ class). + +.TP +.BR "--set-class major:minor" + +Set the major and minor class value. The values are always +interpreted as hexadecimal even if no 0x prefix is given. + +.SH NOTES +In this nft-based version of +.BR arptables , +support for +.B FORWARD +chain has not been implemented. Since ARP packets are "forwarded" only by Linux +bridges, the same may be achieved using +.B FORWARD +chain in +.BR ebtables . + +.SH MAILINGLISTS +.BR "" "See " http://netfilter.org/mailinglists.html +.SH SEE ALSO +.BR xtables-nft "(8), " iptables "(8), " ebtables "(8), " arp "(8), " rarp "(8), " ifconfig "(8), " route (8) +.PP +.BR "" "See " http://ebtables.sf.net diff --git a/SOURCES/arptables.service b/SOURCES/arptables.service new file mode 100644 index 0000000..df6c7d6 --- /dev/null +++ b/SOURCES/arptables.service @@ -0,0 +1,12 @@ +[Unit] +Description=Automates a packet filtering firewall with arptables +After=network.target + +[Service] +Type=oneshot +ExecStart=/usr/libexec/arptables-helper start +ExecStop=/usr/libexec/arptables-helper stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/ebtables-config b/SOURCES/ebtables-config new file mode 100644 index 0000000..69d9289 --- /dev/null +++ b/SOURCES/ebtables-config @@ -0,0 +1,11 @@ +# Save current firewall rules on stop. +# Value: yes|no, default: no +# Saves all firewall rules if firewall gets stopped +# (e.g. on system shutdown). +EBTABLES_SAVE_ON_STOP="no" + +# Save (and restore) rule counters. +# Value: yes|no, default: no +# Save rule counters when saving a kernel table to a file. If the +# rule counters were saved, they will be restored when restoring the table. +EBTABLES_SAVE_COUNTER="no" diff --git a/SOURCES/ebtables.8 b/SOURCES/ebtables.8 new file mode 100644 index 0000000..67201b6 --- /dev/null +++ b/SOURCES/ebtables.8 @@ -0,0 +1,1096 @@ +.TH EBTABLES 8 "December 2011" +.\" +.\" Man page written by Bart De Schuymer +.\" It is based on the iptables man page. +.\" +.\" The man page was edited, February 25th 2003, by +.\" Greg Morgan <" dr_kludge_at_users_sourceforge_net > +.\" +.\" Iptables page by Herve Eychenne March 2000. +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.\" +.SH NAME +ebtables-nft \- Ethernet bridge frame table administration +.SH SYNOPSIS +.BR "ebtables " [ -t " table ] " - [ ACDI "] chain rule specification [match extensions] [watcher extensions] target" +.br +.BR "ebtables " [ -t " table ] " -P " chain " ACCEPT " | " DROP " | " RETURN +.br +.BR "ebtables " [ -t " table ] " -F " [chain]" +.br +.BR "ebtables " [ -t " table ] " -Z " [chain]" +.br +.BR "ebtables " [ -t " table ] " -L " [" -Z "] [chain] [ [" --Ln "] | [" --Lx "] ] [" --Lc "] [" --Lmac2 ] +.br +.BR "ebtables " [ -t " table ] " -N " chain [" "-P ACCEPT " | " DROP " | " RETURN" ] +.br +.BR "ebtables " [ -t " table ] " -X " [chain]" +.br +.BR "ebtables " [ -t " table ] " -E " old-chain-name new-chain-name" +.br +.BR "ebtables " [ -t " table ] " --init-table +.br +.BR "ebtables " [ -t " table ] [" --atomic-file " file] " --atomic-commit +.br +.BR "ebtables " [ -t " table ] [" --atomic-file " file] " --atomic-init +.br +.BR "ebtables " [ -t " table ] [" --atomic-file " file] " --atomic-save +.br +.SH DESCRIPTION +.B ebtables +is an application program used to set up and maintain the +tables of rules (inside the Linux kernel) that inspect +Ethernet frames. +It is analogous to the +.B iptables +application, but less complicated, due to the fact that the Ethernet protocol +is much simpler than the IP protocol. +.SS CHAINS +There are two ebtables-nft tables with built-in chains in the +Linux kernel. These tables are used to divide functionality into +different sets of rules. Each set of rules is called a chain. +Each chain is an ordered list of rules that can match Ethernet frames. If a +rule matches an Ethernet frame, then a processing specification tells +what to do with that matching frame. The processing specification is +called a 'target'. However, if the frame does not match the current +rule in the chain, then the next rule in the chain is examined and so forth. +The user can create new (user-defined) chains that can be used as the 'target' +of a rule. User-defined chains are very useful to get better performance +over the linear traversal of the rules and are also essential for structuring +the filtering rules into well-organized and maintainable sets of rules. +.SS TARGETS +A firewall rule specifies criteria for an Ethernet frame and a frame +processing specification called a target. When a frame matches a rule, +then the next action performed by the kernel is specified by the target. +The target can be one of these values: +.BR ACCEPT , +.BR DROP , +.BR CONTINUE , +.BR RETURN , +an 'extension' (see below) or a jump to a user-defined chain. +.PP +.B ACCEPT +means to let the frame through. +.B DROP +means the frame has to be dropped. +.B CONTINUE +means the next rule has to be checked. This can be handy, f.e., to know how many +frames pass a certain point in the chain, to log those frames or to apply multiple +targets on a frame. +.B RETURN +means stop traversing this chain and resume at the next rule in the +previous (calling) chain. +For the extension targets please refer to the +.B "TARGET EXTENSIONS" +section of this man page. +.SS TABLES +As stated earlier, there are two ebtables-nft tables in the Linux +kernel. The table names are +.BR filter " and " nat . +Of these two tables, +the filter table is the default table that the command operates on. +If you are working with the filter table, then you can drop the '-t filter' +argument to the ebtables command. However, you will need to provide +the -t argument for +.B nat +table. Moreover, the -t argument must be the +first argument on the ebtables command line, if used. +.TP +.B "-t, --table" +.br +.B filter +is the default table and contains three built-in chains: +.B INPUT +(for frames destined for the bridge itself, on the level of the MAC destination address), +.B OUTPUT +(for locally-generated or (b)routed frames) and +.B FORWARD +(for frames being forwarded by the bridge). +.br +.br +.B nat +is mostly used to change the mac addresses and contains three built-in chains: +.B PREROUTING +(for altering frames as soon as they come in), +.B OUTPUT +(for altering locally generated or (b)routed frames before they are bridged) and +.B POSTROUTING +(for altering frames as they are about to go out). A small note on the naming +of chains PREROUTING and POSTROUTING: it would be more accurate to call them +PREFORWARDING and POSTFORWARDING, but for all those who come from the +iptables world to ebtables it is easier to have the same names. Note that you +can change the name +.BR "" ( -E ) +if you don't like the default. +.SH EBTABLES COMMAND LINE ARGUMENTS +After the initial ebtables '-t table' command line argument, the remaining +arguments can be divided into several groups. These groups +are commands, miscellaneous commands, rule specifications, match extensions, +watcher extensions and target extensions. +.SS COMMANDS +The ebtables command arguments specify the actions to perform on the table +defined with the -t argument. If you do not use the -t argument to name +a table, the commands apply to the default filter table. +Only one command may be used on the command line at a time, except when +the commands +.BR -L " and " -Z +are combined, the commands +.BR -N " and " -P +are combined, or when +.B --atomic-file +is used. +.TP +.B "-A, --append" +Append a rule to the end of the selected chain. +.TP +.B "-D, --delete" +Delete the specified rule or rules from the selected chain. There are two ways to +use this command. The first is by specifying an interval of rule numbers +to delete (directly after +.BR -D ). +Syntax: \fIstart_nr\fP[\fI:end_nr\fP] (use +.B -L --Ln +to list the rules with their rule number). When \fIend_nr\fP is omitted, all rules starting +from \fIstart_nr\fP are deleted. Using negative numbers is allowed, for more +details about using negative numbers, see the +.B -I +command. The second usage is by +specifying the complete rule as it would have been specified when it was added. Only +the first encountered rule that is the same as this specified rule, in other +words the matching rule with the lowest (positive) rule number, is deleted. +.TP +.B "-C, --change-counters" +Change the counters of the specified rule or rules from the selected chain. There are two ways to +use this command. The first is by specifying an interval of rule numbers +to do the changes on (directly after +.BR -C ). +Syntax: \fIstart_nr\fP[\fI:end_nr\fP] (use +.B -L --Ln +to list the rules with their rule number). The details are the same as for the +.BR -D " command. The second usage is by" +specifying the complete rule as it would have been specified when it was added. Only +the counters of the first encountered rule that is the same as this specified rule, in other +words the matching rule with the lowest (positive) rule number, are changed. +In the first usage, the counters are specified directly after the interval specification, +in the second usage directly after +.BR -C . +First the packet counter is specified, then the byte counter. If the specified counters start +with a '+', the counter values are added to the respective current counter values. +If the specified counters start with a '-', the counter values are decreased from the respective +current counter values. No bounds checking is done. If the counters don't start with '+' or '-', +the current counters are changed to the specified counters. +.TP +.B "-I, --insert" +Insert the specified rule into the selected chain at the specified rule number. If the +rule number is not specified, the rule is added at the head of the chain. +If the current number of rules equals +.IR N , +then the specified number can be +between +.IR -N " and " N+1 . +For a positive number +.IR i , +it holds that +.IR i " and " i-N-1 +specify the same place in the chain where the rule should be inserted. The rule number +0 specifies the place past the last rule in the chain and using this number is therefore +equivalent to using the +.BR -A " command." +Rule numbers structly smaller than 0 can be useful when more than one rule needs to be inserted +in a chain. +.TP +.B "-P, --policy" +Set the policy for the chain to the given target. The policy can be +.BR ACCEPT ", " DROP " or " RETURN . +.TP +.B "-F, --flush" +Flush the selected chain. If no chain is selected, then every chain will be +flushed. Flushing a chain does not change the policy of the +chain, however. +.TP +.B "-Z, --zero" +Set the counters of the selected chain to zero. If no chain is selected, all the counters +are set to zero. The +.B "-Z" +command can be used in conjunction with the +.B "-L" +command. +When both the +.B "-Z" +and +.B "-L" +commands are used together in this way, the rule counters are printed on the screen +before they are set to zero. +.TP +.B "-L, --list" +List all rules in the selected chain. If no chain is selected, all chains +are listed. +.br +The following options change the output of the +.B "-L" +command. +.br +.B "--Ln" +.br +Places the rule number in front of every rule. This option is incompatible with the +.BR --Lx " option." +.br +.B "--Lc" +.br +Shows the counters at the end of each rule displayed by the +.B "-L" +command. Both a frame counter (pcnt) and a byte counter (bcnt) are displayed. +The frame counter shows how many frames have matched the specific rule, the byte +counter shows the sum of the frame sizes of these matching frames. Using this option +.BR "" "in combination with the " --Lx " option causes the counters to be written out" +.BR "" "in the '" -c " ' option format." +.br +.B "--Lx" +.br +Changes the output so that it produces a set of ebtables commands that construct +the contents of the chain, when specified. +If no chain is specified, ebtables commands to construct the contents of the +table are given, including commands for creating the user-defined chains (if any). +You can use this set of commands in an ebtables boot or reload +script. For example the output could be used at system startup. +The +.B "--Lx" +option is incompatible with the +.B "--Ln" +listing option. Using the +.BR --Lx " option together with the " --Lc " option will cause the counters to be written out" +.BR "" "in the '" -c " ' option format." +.br +.B "--Lmac2" +.br +Shows all MAC addresses with the same length, adding leading zeroes +if necessary. The default representation omits leading zeroes in the addresses. +.TP +.B "-N, --new-chain" +Create a new user-defined chain with the given name. The number of +user-defined chains is limited only by the number of possible chain names. +A user-defined chain name has a maximum +length of 31 characters. The standard policy of the user-defined chain is +ACCEPT. The policy of the new chain can be initialized to a different standard +target by using the +.B -P +command together with the +.B -N +command. In this case, the chain name does not have to be specified for the +.B -P +command. +.TP +.B "-X, --delete-chain" +Delete the specified user-defined chain. There must be no remaining references (jumps) +to the specified chain, otherwise ebtables will refuse to delete it. If no chain is +specified, all user-defined chains that aren't referenced will be removed. +.TP +.B "-E, --rename-chain" +Rename the specified chain to a new name. Besides renaming a user-defined +chain, you can rename a standard chain to a name that suits your +taste. For example, if you like PREFORWARDING more than PREROUTING, +then you can use the -E command to rename the PREROUTING chain. If you do +rename one of the standard ebtables chain names, please be sure to mention +this fact should you post a question on the ebtables mailing lists. +It would be wise to use the standard name in your post. Renaming a standard +ebtables chain in this fashion has no effect on the structure or functioning +of the ebtables kernel table. +.TP +.B "--init-table" +Replace the current table data by the initial table data. +.TP +.B "--atomic-init" +Copy the kernel's initial data of the table to the specified +file. This can be used as the first action, after which rules are added +to the file. The file can be specified using the +.B --atomic-file +command or through the +.IR EBTABLES_ATOMIC_FILE " environment variable." +.TP +.B "--atomic-save" +Copy the kernel's current data of the table to the specified +file. This can be used as the first action, after which rules are added +to the file. The file can be specified using the +.B --atomic-file +command or through the +.IR EBTABLES_ATOMIC_FILE " environment variable." +.TP +.B "--atomic-commit" +Replace the kernel table data with the data contained in the specified +file. This is a useful command that allows you to load all your rules of a +certain table into the kernel at once, saving the kernel a lot of precious +time and allowing atomic updates of the tables. The file which contains +the table data is constructed by using either the +.B "--atomic-init" +or the +.B "--atomic-save" +command to generate a starting file. After that, using the +.B "--atomic-file" +command when constructing rules or setting the +.IR EBTABLES_ATOMIC_FILE " environment variable" +allows you to extend the file and build the complete table before +committing it to the kernel. This command can be very useful in boot scripts +to populate the ebtables tables in a fast way. +.SS MISCELLANOUS COMMANDS +.TP +.B "-V, --version" +Show the version of the ebtables userspace program. +.TP +.BR "-h, --help " "[\fIlist of module names\fP]" +Give a brief description of the command syntax. Here you can also specify +names of extensions and ebtables will try to write help about those +extensions. E.g. +.IR "ebtables -h snat log ip arp" . +Specify +.I list_extensions +to list all extensions supported by the userspace +utility. +.TP +.BR "-j, --jump " "\fItarget\fP" +The target of the rule. This is one of the following values: +.BR ACCEPT , +.BR DROP , +.BR CONTINUE , +.BR RETURN , +a target extension (see +.BR "TARGET EXTENSIONS" ")" +or a user-defined chain name. +.TP +.B --atomic-file "\fIfile\fP" +Let the command operate on the specified +.IR file . +The data of the table to +operate on will be extracted from the file and the result of the operation +will be saved back into the file. If specified, this option should come +before the command specification. An alternative that should be preferred, +is setting the +.IR EBTABLES_ATOMIC_FILE " environment variable." +.TP +.B -M, --modprobe "\fIprogram\fP" +When talking to the kernel, use this +.I program +to try to automatically load missing kernel modules. +.TP +.B --concurrent +Use a file lock to support concurrent scripts updating the ebtables kernel tables. + +.SS +RULE SPECIFICATIONS +The following command line arguments make up a rule specification (as used +in the add and delete commands). A "!" option before the specification +inverts the test for that specification. Apart from these standard rule +specifications there are some other command line arguments of interest. +See both the +.BR "MATCH EXTENSIONS" +and the +.BR "WATCHER EXTENSIONS" +below. +.TP +.BR "-p, --protocol " "[!] \fIprotocol\fP" +The protocol that was responsible for creating the frame. This can be a +hexadecimal number, above +.IR 0x0600 , +a name (e.g. +.I ARP +) or +.BR LENGTH . +The protocol field of the Ethernet frame can be used to denote the +length of the header (802.2/802.3 networks). When the value of that field is +below or equals +.IR 0x0600 , +the value equals the size of the header and shouldn't be used as a +protocol number. Instead, all frames where the protocol field is used as +the length field are assumed to be of the same 'protocol'. The protocol +name used in ebtables for these frames is +.BR LENGTH . +.br +The file +.B /etc/ethertypes +can be used to show readable +characters instead of hexadecimal numbers for the protocols. For example, +.I 0x0800 +will be represented by +.IR IPV4 . +The use of this file is not case sensitive. +See that file for more information. The flag +.B --proto +is an alias for this option. +.TP +.BR "-i, --in-interface " "[!] \fIname\fP" +The interface (bridge port) via which a frame is received (this option is useful in the +.BR INPUT , +.BR FORWARD , +.BR PREROUTING " and " BROUTING +chains). If the interface name ends with '+', then +any interface name that begins with this name (disregarding '+') will match. +The flag +.B --in-if +is an alias for this option. +.TP +.BR "--logical-in " "[!] \fIname\fP" +The (logical) bridge interface via which a frame is received (this option is useful in the +.BR INPUT , +.BR FORWARD , +.BR PREROUTING " and " BROUTING +chains). +If the interface name ends with '+', then +any interface name that begins with this name (disregarding '+') will match. +.TP +.BR "-o, --out-interface " "[!] \fIname\fP" +The interface (bridge port) via which a frame is going to be sent (this option is useful in the +.BR OUTPUT , +.B FORWARD +and +.B POSTROUTING +chains). If the interface name ends with '+', then +any interface name that begins with this name (disregarding '+') will match. +The flag +.B --out-if +is an alias for this option. +.TP +.BR "--logical-out " "[!] \fIname\fP" +The (logical) bridge interface via which a frame is going to be sent (this option +is useful in the +.BR OUTPUT , +.B FORWARD +and +.B POSTROUTING +chains). +If the interface name ends with '+', then +any interface name that begins with this name (disregarding '+') will match. +.TP +.BR "-s, --source " "[!] \fIaddress\fP[/\fImask\fP]" +The source MAC address. Both mask and address are written as 6 hexadecimal +numbers separated by colons. Alternatively one can specify Unicast, +Multicast, Broadcast or BGA (Bridge Group Address): +.br +.IR "Unicast" "=00:00:00:00:00:00/01:00:00:00:00:00," +.IR "Multicast" "=01:00:00:00:00:00/01:00:00:00:00:00," +.IR "Broadcast" "=ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff or" +.IR "BGA" "=01:80:c2:00:00:00/ff:ff:ff:ff:ff:ff." +Note that a broadcast +address will also match the multicast specification. The flag +.B --src +is an alias for this option. +.TP +.BR "-d, --destination " "[!] \fIaddress\fP[/\fImask\fP]" +The destination MAC address. See +.B -s +(above) for more details on MAC addresses. The flag +.B --dst +is an alias for this option. +.TP +.BR "-c, --set-counter " "\fIpcnt bcnt\fP" +If used with +.BR -A " or " -I ", then the packet and byte counters of the new rule will be set to +.IR pcnt ", resp. " bcnt ". +If used with the +.BR -C " or " -D " commands, only rules with a packet and byte count equal to" +.IR pcnt ", resp. " bcnt " will match." + +.SS MATCH EXTENSIONS +Ebtables extensions are dynamically loaded into the userspace tool, +there is therefore no need to explicitly load them with a +-m option like is done in iptables. +These extensions deal with functionality supported by kernel modules supplemental to +the core ebtables code. +.SS 802_3 +Specify 802.3 DSAP/SSAP fields or SNAP type. The protocol must be specified as +.IR "LENGTH " "(see the option " " -p " above). +.TP +.BR "--802_3-sap " "[!] \fIsap\fP" +DSAP and SSAP are two one byte 802.3 fields. The bytes are always +equal, so only one byte (hexadecimal) is needed as an argument. +.TP +.BR "--802_3-type " "[!] \fItype\fP" +If the 802.3 DSAP and SSAP values are 0xaa then the SNAP type field must +be consulted to determine the payload protocol. This is a two byte +(hexadecimal) argument. Only 802.3 frames with DSAP/SSAP 0xaa are +checked for type. +.SS among +Match a MAC address or MAC/IP address pair versus a list of MAC addresses +and MAC/IP address pairs. +A list entry has the following format: +.IR xx:xx:xx:xx:xx:xx[=ip.ip.ip.ip][,] ". Multiple" +list entries are separated by a comma, specifying an IP address corresponding to +the MAC address is optional. Multiple MAC/IP address pairs with the same MAC address +but different IP address (and vice versa) can be specified. If the MAC address doesn't +match any entry from the list, the frame doesn't match the rule (unless "!" was used). +.TP +.BR "--among-dst " "[!] \fIlist\fP" +Compare the MAC destination to the given list. If the Ethernet frame has type +.IR IPv4 " or " ARP , +then comparison with MAC/IP destination address pairs from the +list is possible. +.TP +.BR "--among-src " "[!] \fIlist\fP" +Compare the MAC source to the given list. If the Ethernet frame has type +.IR IPv4 " or " ARP , +then comparison with MAC/IP source address pairs from the list +is possible. +.TP +.BR "--among-dst-file " "[!] \fIfile\fP" +Same as +.BR --among-dst " but the list is read in from the specified file." +.TP +.BR "--among-src-file " "[!] \fIfile\fP" +Same as +.BR --among-src " but the list is read in from the specified file." +.SS arp +Specify (R)ARP fields. The protocol must be specified as +.IR ARP " or " RARP . +.TP +.BR "--arp-opcode " "[!] \fIopcode\fP" +The (R)ARP opcode (decimal or a string, for more details see +.BR "ebtables -h arp" ). +.TP +.BR "--arp-htype " "[!] \fIhardware type\fP" +The hardware type, this can be a decimal or the string +.I Ethernet +(which sets +.I type +to 1). Most (R)ARP packets have Eternet as hardware type. +.TP +.BR "--arp-ptype " "[!] \fIprotocol type\fP" +The protocol type for which the (r)arp is used (hexadecimal or the string +.IR IPv4 , +denoting 0x0800). +Most (R)ARP packets have protocol type IPv4. +.TP +.BR "--arp-ip-src " "[!] \fIaddress\fP[/\fImask\fP]" +The (R)ARP IP source address specification. +.TP +.BR "--arp-ip-dst " "[!] \fIaddress\fP[/\fImask\fP]" +The (R)ARP IP destination address specification. +.TP +.BR "--arp-mac-src " "[!] \fIaddress\fP[/\fImask\fP]" +The (R)ARP MAC source address specification. +.TP +.BR "--arp-mac-dst " "[!] \fIaddress\fP[/\fImask\fP]" +The (R)ARP MAC destination address specification. +.TP +.BR "" "[!]" " --arp-gratuitous" +Checks for ARP gratuitous packets: checks equality of IPv4 source +address and IPv4 destination address inside the ARP header. +.SS ip +Specify IPv4 fields. The protocol must be specified as +.IR IPv4 . +.TP +.BR "--ip-source " "[!] \fIaddress\fP[/\fImask\fP]" +The source IP address. +The flag +.B --ip-src +is an alias for this option. +.TP +.BR "--ip-destination " "[!] \fIaddress\fP[/\fImask\fP]" +The destination IP address. +The flag +.B --ip-dst +is an alias for this option. +.TP +.BR "--ip-tos " "[!] \fItos\fP" +The IP type of service, in hexadecimal numbers. +.BR IPv4 . +.TP +.BR "--ip-protocol " "[!] \fIprotocol\fP" +The IP protocol. +The flag +.B --ip-proto +is an alias for this option. +.TP +.BR "--ip-source-port " "[!] \fIport1\fP[:\fIport2\fP]" +The source port or port range for the IP protocols 6 (TCP), 17 +(UDP), 33 (DCCP) or 132 (SCTP). The +.B --ip-protocol +option must be specified as +.IR TCP ", " UDP ", " DCCP " or " SCTP . +If +.IR port1 " is omitted, " 0:port2 " is used; if " port2 " is omitted but a colon is specified, " port1:65535 " is used." +The flag +.B --ip-sport +is an alias for this option. +.TP +.BR "--ip-destination-port " "[!] \fIport1\fP[:\fIport2\fP]" +The destination port or port range for ip protocols 6 (TCP), 17 +(UDP), 33 (DCCP) or 132 (SCTP). The +.B --ip-protocol +option must be specified as +.IR TCP ", " UDP ", " DCCP " or " SCTP . +If +.IR port1 " is omitted, " 0:port2 " is used; if " port2 " is omitted but a colon is specified, " port1:65535 " is used." +The flag +.B --ip-dport +is an alias for this option. +.SS ip6 +Specify IPv6 fields. The protocol must be specified as +.IR IPv6 . +.TP +.BR "--ip6-source " "[!] \fIaddress\fP[/\fImask\fP]" +The source IPv6 address. +The flag +.B --ip6-src +is an alias for this option. +.TP +.BR "--ip6-destination " "[!] \fIaddress\fP[/\fImask\fP]" +The destination IPv6 address. +The flag +.B --ip6-dst +is an alias for this option. +.TP +.BR "--ip6-tclass " "[!] \fItclass\fP" +The IPv6 traffic class, in hexadecimal numbers. +.TP +.BR "--ip6-protocol " "[!] \fIprotocol\fP" +The IP protocol. +The flag +.B --ip6-proto +is an alias for this option. +.TP +.BR "--ip6-source-port " "[!] \fIport1\fP[:\fIport2\fP]" +The source port or port range for the IPv6 protocols 6 (TCP), 17 +(UDP), 33 (DCCP) or 132 (SCTP). The +.B --ip6-protocol +option must be specified as +.IR TCP ", " UDP ", " DCCP " or " SCTP . +If +.IR port1 " is omitted, " 0:port2 " is used; if " port2 " is omitted but a colon is specified, " port1:65535 " is used." +The flag +.B --ip6-sport +is an alias for this option. +.TP +.BR "--ip6-destination-port " "[!] \fIport1\fP[:\fIport2\fP]" +The destination port or port range for IPv6 protocols 6 (TCP), 17 +(UDP), 33 (DCCP) or 132 (SCTP). The +.B --ip6-protocol +option must be specified as +.IR TCP ", " UDP ", " DCCP " or " SCTP . +If +.IR port1 " is omitted, " 0:port2 " is used; if " port2 " is omitted but a colon is specified, " port1:65535 " is used." +The flag +.B --ip6-dport +is an alias for this option. +.TP +.BR "--ip6-icmp-type " "[!] {\fItype\fP[:\fItype\fP]/\fIcode\fP[:\fIcode\fP]|\fItypename\fP}" +Specify ipv6\-icmp type and code to match. +Ranges for both type and code are supported. Type and code are +separated by a slash. Valid numbers for type and range are 0 to 255. +To match a single type including all valid codes, symbolic names can +be used instead of numbers. The list of known type names is shown by the command +.nf + ebtables \-\-help ip6 +.fi +This option is only valid for \-\-ip6-prococol ipv6-icmp. +.SS limit +This module matches at a limited rate using a token bucket filter. +A rule using this extension will match until this limit is reached. +It can be used with the +.B --log +watcher to give limited logging, for example. Its use is the same +as the limit match of iptables. +.TP +.BR "--limit " "[\fIvalue\fP]" +Maximum average matching rate: specified as a number, with an optional +.IR /second ", " /minute ", " /hour ", or " /day " suffix; the default is " 3/hour . +.TP +.BR "--limit-burst " "[\fInumber\fP]" +Maximum initial number of packets to match: this number gets recharged by +one every time the limit specified above is not reached, up to this +number; the default is +.IR 5 . +.SS mark_m +.TP +.BR "--mark " "[!] [\fIvalue\fP][/\fImask\fP]" +Matches frames with the given unsigned mark value. If a +.IR value " and " mask " are specified, the logical AND of the mark value of the frame and" +the user-specified +.IR mask " is taken before comparing it with the" +user-specified mark +.IR value ". When only a mark " +.IR value " is specified, the packet" +only matches when the mark value of the frame equals the user-specified +mark +.IR value . +If only a +.IR mask " is specified, the logical" +AND of the mark value of the frame and the user-specified +.IR mask " is taken and the frame matches when the result of this logical AND is" +non-zero. Only specifying a +.IR mask " is useful to match multiple mark values." +.SS pkttype +.TP +.BR "--pkttype-type " "[!] \fItype\fP" +Matches on the Ethernet "class" of the frame, which is determined by the +generic networking code. Possible values: +.IR broadcast " (MAC destination is the broadcast address)," +.IR multicast " (MAC destination is a multicast address)," +.IR host " (MAC destination is the receiving network device), or " +.IR otherhost " (none of the above)." +.SS stp +Specify stp BPDU (bridge protocol data unit) fields. The destination +address +.BR "" ( -d ") must be specified as the bridge group address" +.IR "" ( BGA ). +For all options for which a range of values can be specified, it holds that +if the lower bound is omitted (but the colon is not), then the lowest possible lower bound +for that option is used, while if the upper bound is omitted (but the colon again is not), the +highest possible upper bound for that option is used. +.TP +.BR "--stp-type " "[!] \fItype\fP" +The BPDU type (0-255), recognized non-numerical types are +.IR config ", denoting a configuration BPDU (=0), and" +.IR tcn ", denothing a topology change notification BPDU (=128)." +.TP +.BR "--stp-flags " "[!] \fIflag\fP" +The BPDU flag (0-255), recognized non-numerical flags are +.IR topology-change ", denoting the topology change flag (=1), and" +.IR topology-change-ack ", denoting the topology change acknowledgement flag (=128)." +.TP +.BR "--stp-root-prio " "[!] [\fIprio\fP][:\fIprio\fP]" +The root priority (0-65535) range. +.TP +.BR "--stp-root-addr " "[!] [\fIaddress\fP][/\fImask\fP]" +The root mac address, see the option +.BR -s " for more details." +.TP +.BR "--stp-root-cost " "[!] [\fIcost\fP][:\fIcost\fP]" +The root path cost (0-4294967295) range. +.TP +.BR "--stp-sender-prio " "[!] [\fIprio\fP][:\fIprio\fP]" +The BPDU's sender priority (0-65535) range. +.TP +.BR "--stp-sender-addr " "[!] [\fIaddress\fP][/\fImask\fP]" +The BPDU's sender mac address, see the option +.BR -s " for more details." +.TP +.BR "--stp-port " "[!] [\fIport\fP][:\fIport\fP]" +The port identifier (0-65535) range. +.TP +.BR "--stp-msg-age " "[!] [\fIage\fP][:\fIage\fP]" +The message age timer (0-65535) range. +.TP +.BR "--stp-max-age " "[!] [\fIage\fP][:\fIage\fP]" +The max age timer (0-65535) range. +.TP +.BR "--stp-hello-time " "[!] [\fItime\fP][:\fItime\fP]" +The hello time timer (0-65535) range. +.TP +.BR "--stp-forward-delay " "[!] [\fIdelay\fP][:\fIdelay\fP]" +The forward delay timer (0-65535) range. +.SS vlan +Specify 802.1Q Tag Control Information fields. +The protocol must be specified as +.IR 802_1Q " (0x8100)." +.TP +.BR "--vlan-id " "[!] \fIid\fP" +The VLAN identifier field (VID). Decimal number from 0 to 4095. +.TP +.BR "--vlan-prio " "[!] \fIprio\fP" +The user priority field, a decimal number from 0 to 7. +The VID should be set to 0 ("null VID") or unspecified +(in the latter case the VID is deliberately set to 0). +.TP +.BR "--vlan-encap " "[!] \fItype\fP" +The encapsulated Ethernet frame type/length. +Specified as a hexadecimal +number from 0x0000 to 0xFFFF or as a symbolic name +from +.BR /etc/ethertypes . + +.SS WATCHER EXTENSIONS +Watchers only look at frames passing by, they don't modify them nor decide +to accept the frames or not. These watchers only +see the frame if the frame matches the rule, and they see it before the +target is executed. +.SS log +The log watcher writes descriptive data about a frame to the syslog. +.TP +.B "--log" +.br +Log with the default loggin options: log-level= +.IR info , +log-prefix="", no ip logging, no arp logging. +.TP +.B --log-level "\fIlevel\fP" +.br +Defines the logging level. For the possible values, see +.BR "ebtables -h log" . +The default level is +.IR info . +.TP +.BR --log-prefix " \fItext\fP" +.br +Defines the prefix +.I text +to be printed at the beginning of the line with the logging information. +.TP +.B --log-ip +.br +Will log the ip information when a frame made by the ip protocol matches +the rule. The default is no ip information logging. +.TP +.B --log-ip6 +.br +Will log the ipv6 information when a frame made by the ipv6 protocol matches +the rule. The default is no ipv6 information logging. +.TP +.B --log-arp +.br +Will log the (r)arp information when a frame made by the (r)arp protocols +matches the rule. The default is no (r)arp information logging. +.SS nflog +The nflog watcher passes the packet to the loaded logging backend +in order to log the packet. This is usually used in combination with +nfnetlink_log as logging backend, which will multicast the packet +through a +.IR netlink +socket to the specified multicast group. One or more userspace processes +may subscribe to the group to receive the packets. +.TP +.B "--nflog" +.br +Log with the default logging options +.TP +.B --nflog-group "\fInlgroup\fP" +.br +The netlink group (1 - 2^32-1) to which packets are (only applicable for +nfnetlink_log). The default value is 1. +.TP +.B --nflog-prefix "\fIprefix\fP" +.br +A prefix string to include in the log message, up to 30 characters +long, useful for distinguishing messages in the logs. +.TP +.B --nflog-range "\fIsize\fP" +.br +The number of bytes to be copied to userspace (only applicable for +nfnetlink_log). nfnetlink_log instances may specify their own +range, this option overrides it. +.TP +.B --nflog-threshold "\fIsize\fP" +.br +Number of packets to queue inside the kernel before sending them +to userspace (only applicable for nfnetlink_log). Higher values +result in less overhead per packet, but increase delay until the +packets reach userspace. The default value is 1. +.SS ulog +The ulog watcher passes the packet to a userspace +logging daemon using netlink multicast sockets. This differs +from the log watcher in the sense that the complete packet is +sent to userspace instead of a descriptive text and that +netlink multicast sockets are used instead of the syslog. +This watcher enables parsing of packets with userspace programs, the +physical bridge in and out ports are also included in the netlink messages. +The ulog watcher module accepts 2 parameters when the module is loaded +into the kernel (e.g. with modprobe): +.B nlbufsiz +specifies how big the buffer for each netlink multicast +group is. If you say +.IR nlbufsiz=8192 , +for example, up to eight kB of packets will +get accumulated in the kernel until they are sent to userspace. It is +not possible to allocate more than 128kB. Please also keep in mind that +this buffer size is allocated for each nlgroup you are using, so the +total kernel memory usage increases by that factor. The default is 4096. +.B flushtimeout +specifies after how many hundredths of a second the queue should be +flushed, even if it is not full yet. The default is 10 (one tenth of +a second). +.TP +.B "--ulog" +.br +Use the default settings: ulog-prefix="", ulog-nlgroup=1, +ulog-cprange=4096, ulog-qthreshold=1. +.TP +.B --ulog-prefix "\fItext\fP" +.br +Defines the prefix included with the packets sent to userspace. +.TP +.BR --ulog-nlgroup " \fIgroup\fP" +.br +Defines which netlink group number to use (a number from 1 to 32). +Make sure the netlink group numbers used for the iptables ULOG +target differ from those used for the ebtables ulog watcher. +The default group number is 1. +.TP +.BR --ulog-cprange " \fIrange\fP" +.br +Defines the maximum copy range to userspace, for packets matching the +rule. The default range is 0, which means the maximum copy range is +given by +.BR nlbufsiz . +A maximum copy range larger than +128*1024 is meaningless as the packets sent to userspace have an upper +size limit of 128*1024. +.TP +.BR --ulog-qthreshold " \fIthreshold\fP" +.br +Queue at most +.I threshold +number of packets before sending them to +userspace with a netlink socket. Note that packets can be sent to +userspace before the queue is full, this happens when the ulog +kernel timer goes off (the frequency of this timer depends on +.BR flushtimeout ). +.SS TARGET EXTENSIONS +.SS arpreply +The +.B arpreply +target can be used in the +.BR PREROUTING " chain of the " nat " table." +If this target sees an ARP request it will automatically reply +with an ARP reply. The used MAC address for the reply can be specified. +The protocol must be specified as +.IR ARP . +When the ARP message is not an ARP request or when the ARP request isn't +for an IP address on an Ethernet network, it is ignored by this target +.BR "" ( CONTINUE ). +When the ARP request is malformed, it is dropped +.BR "" ( DROP ). +.TP +.BR "--arpreply-mac " "\fIaddress\fP" +Specifies the MAC address to reply with: the Ethernet source MAC and the +ARP payload source MAC will be filled in with this address. +.TP +.BR "--arpreply-target " "\fItarget\fP" +Specifies the standard target. After sending the ARP reply, the rule still +has to give a standard target so ebtables knows what to do with the ARP request. +The default target +.BR "" "is " DROP . +.SS dnat +The +.B dnat +target can only be used in the +.BR PREROUTING " and " OUTPUT " chains of the " nat " table." +It specifies that the destination MAC address has to be changed. +.TP +.BR "--to-destination " "\fIaddress\fP" +.br +Change the destination MAC address to the specified +.IR address . +The flag +.B --to-dst +is an alias for this option. +.TP +.BR "--dnat-target " "\fItarget\fP" +.br +Specifies the standard target. After doing the dnat, the rule still has to +give a standard target so ebtables knows what to do with the dnated frame. +The default target is +.BR ACCEPT . +Making it +.BR CONTINUE " could let you use" +multiple target extensions on the same frame. Making it +.BR DROP " only makes" +sense in the +.BR BROUTING " chain but using the " redirect " target is more logical there. " RETURN " is also allowed. Note that using " RETURN +in a base chain is not allowed (for obvious reasons). +.SS mark +.BR "" "The " mark " target can be used in every chain of every table. It is possible" +to use the marking of a frame/packet in both ebtables and iptables, +if the bridge-nf code is compiled into the kernel. Both put the marking at the +same place. This allows for a form of communication between ebtables and iptables. +.TP +.BR "--mark-set " "\fIvalue\fP" +.br +Mark the frame with the specified non-negative +.IR value . +.TP +.BR "--mark-or " "\fIvalue\fP" +.br +Or the frame with the specified non-negative +.IR value . +.TP +.BR "--mark-and " "\fIvalue\fP" +.br +And the frame with the specified non-negative +.IR value . +.TP +.BR "--mark-xor " "\fIvalue\fP" +.br +Xor the frame with the specified non-negative +.IR value . +.TP +.BR "--mark-target " "\fItarget\fP" +.br +Specifies the standard target. After marking the frame, the rule +still has to give a standard target so ebtables knows what to do. +The default target is +.BR ACCEPT ". Making it " CONTINUE " can let you do other" +things with the frame in subsequent rules of the chain. +.SS redirect +The +.B redirect +target will change the MAC target address to that of the bridge device the +frame arrived on. This target can only be used in the +.BR PREROUTING " chain of the " nat " table." +The MAC address of the bridge is used as destination address." +.TP +.BR "--redirect-target " "\fItarget\fP" +.br +Specifies the standard target. After doing the MAC redirect, the rule +still has to give a standard target so ebtables knows what to do. +The default target is +.BR ACCEPT ". Making it " CONTINUE " could let you use" +multiple target extensions on the same frame. Making it +.BR DROP " in the " BROUTING " chain will let the frames be routed. " RETURN " is also allowed. Note" +.BR "" "that using " RETURN " in a base chain is not allowed." +.SS snat +The +.B snat +target can only be used in the +.BR POSTROUTING " chain of the " nat " table." +It specifies that the source MAC address has to be changed. +.TP +.BR "--to-source " "\fIaddress\fP" +.br +Changes the source MAC address to the specified +.IR address ". The flag" +.B --to-src +is an alias for this option. +.TP +.BR "--snat-target " "\fItarget\fP" +.br +Specifies the standard target. After doing the snat, the rule still has +to give a standard target so ebtables knows what to do. +.BR "" "The default target is " ACCEPT ". Making it " CONTINUE " could let you use" +.BR "" "multiple target extensions on the same frame. Making it " DROP " doesn't" +.BR "" "make sense, but you could do that too. " RETURN " is also allowed. Note" +.BR "" "that using " RETURN " in a base chain is not allowed." +.br +.TP +.BR "--snat-arp " +.br +Also change the hardware source address inside the arp header if the packet is an +arp message and the hardware address length in the arp header is 6 bytes. +.br +.SH FILES +.I /etc/ethertypes +.I /run/ebtables.lock +.SH ENVIRONMENT VARIABLES +.I EBTABLES_ATOMIC_FILE +.SH MAILINGLISTS +.BR "" "See " http://netfilter.org/mailinglists.html +.SH BUGS +The version of ebtables this man page ships with does not support the +.B broute +table. Also there is no support for the +.B among +match. And finally, this list is probably not complete. +.SH SEE ALSO +.BR xtables-nft "(8), " iptables "(8), " brctl "(8), " ifconfig "(8), " route (8) +.PP +.BR "" "See " http://ebtables.sf.net diff --git a/SOURCES/ebtables.service b/SOURCES/ebtables.service new file mode 100644 index 0000000..e0b0162 --- /dev/null +++ b/SOURCES/ebtables.service @@ -0,0 +1,11 @@ +[Unit] +Description=Ethernet Bridge Filtering tables + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/libexec/ebtables start +ExecStop=/usr/libexec/ebtables stop + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/ebtables.systemd b/SOURCES/ebtables.systemd new file mode 100644 index 0000000..c31ddc0 --- /dev/null +++ b/SOURCES/ebtables.systemd @@ -0,0 +1,71 @@ +#!/bin/bash + +RETVAL=0 +EBTCONF=/etc/sysconfig/ebtables + +initialize() { + # Initialize $TYPE tables + echo -n $" $TYPE tables: " + if [ -r /etc/sysconfig/ebtables.$TYPE ]; then + /sbin/ebtables -t $TYPE --atomic-file /etc/sysconfig/ebtables.$TYPE --atomic-commit > /dev/null || RETVAL=1 + else + echo -n "not configured" + fi + if [ $RETVAL -eq 0 ]; then + echo -n $"[ OK ]" + echo -ne "\r" + else + echo -n $"[FAILED]" + echo -ne "\r" + fi +} + +case $1 in + start) + if [[ -r $EBTCONF ]]; then + ebtables-restore <$EBTCONF + RETVAL=$? + else + echo -n "not configured" + fi + if [ $RETVAL -eq 0 ]; then + echo -n $"[ OK ]" + echo -ne "\r" + else + echo -n $"[FAILED]" + echo -ne "\r" + fi + ;; + stop) + [[ $EBTABLES_SAVE_ON_STOP == "yes" ]] && $0 save + /sbin/ebtables --init-table + RETVAL=$? + + if [ $RETVAL -eq 0 ]; then + echo -n $"[ OK ]" + echo -ne "\r" + else + echo -n $"[FAILED]" + echo -ne "\r" + fi + ;; + save) + echo -n $"Saving Ethernet bridge filtering (ebtables): " + ebtables-save >$EBTCONF + RETVAL=$? + + if [ $RETVAL -eq 0 ]; then + echo -n $"[ OK ]" + echo -ne "\r" + else + echo -n $"[FAILED]" + echo -ne "\r" + fi + ;; + *) + echo "usage: ${0##*/} {start|stop|save}" >&2 + exit 1 + ;; +esac + +# vim:set ts=2 sw=2 ft=sh et: diff --git a/SOURCES/iptables-config b/SOURCES/iptables-config new file mode 100644 index 0000000..3d7e176 --- /dev/null +++ b/SOURCES/iptables-config @@ -0,0 +1,59 @@ +# Load additional iptables modules (nat helpers) +# Default: -none- +# Space separated list of nat helpers (e.g. 'ip_nat_ftp ip_nat_irc'), which +# are loaded after the firewall rules are applied. Options for the helpers are +# stored in /etc/modprobe.conf. +IPTABLES_MODULES="" + +# Save current firewall rules on stop. +# Value: yes|no, default: no +# Saves all firewall rules to /etc/sysconfig/iptables if firewall gets stopped +# (e.g. on system shutdown). +IPTABLES_SAVE_ON_STOP="no" + +# Save current firewall rules on restart. +# Value: yes|no, default: no +# Saves all firewall rules to /etc/sysconfig/iptables if firewall gets +# restarted. +IPTABLES_SAVE_ON_RESTART="no" + +# Save (and restore) rule and chain counter. +# Value: yes|no, default: no +# Save counters for rules and chains to /etc/sysconfig/iptables if +# 'service iptables save' is called or on stop or restart if SAVE_ON_STOP or +# SAVE_ON_RESTART is enabled. +IPTABLES_SAVE_COUNTER="no" + +# Numeric status output +# Value: yes|no, default: yes +# Print IP addresses and port numbers in numeric format in the status output. +IPTABLES_STATUS_NUMERIC="yes" + +# Verbose status output +# Value: yes|no, default: yes +# Print info about the number of packets and bytes plus the "input-" and +# "outputdevice" in the status output. +IPTABLES_STATUS_VERBOSE="no" + +# Status output with numbered lines +# Value: yes|no, default: yes +# Print a counter/number for every rule in the status output. +IPTABLES_STATUS_LINENUMBERS="yes" + +# Reload sysctl settings on start and restart +# Default: -none- +# Space separated list of sysctl items which are to be reloaded on start. +# List items will be matched by fgrep. +#IPTABLES_SYSCTL_LOAD_LIST=".nf_conntrack .bridge-nf" + +# Set wait option for iptables-restore calls in seconds +# Default: 600 +# Set to 0 to deactivate the wait. +#IPTABLES_RESTORE_WAIT=600 + +# Set wait interval option for iptables-restore calls in microseconds +# Default: 1000000 +# Set to 100000 to try to get the lock every 100000 microseconds, 10 times a +# second. +# Only usable with IPTABLES_RESTORE_WAIT > 0 +#IPTABLES_RESTORE_WAIT_INTERVAL=1000000 diff --git a/SOURCES/iptables.init b/SOURCES/iptables.init new file mode 100755 index 0000000..6b391fd --- /dev/null +++ b/SOURCES/iptables.init @@ -0,0 +1,374 @@ +#!/bin/bash +# +# iptables Start iptables firewall +# +# chkconfig: 2345 08 92 +# description: Starts, stops and saves iptables firewall +# +# config: /etc/sysconfig/iptables +# config: /etc/sysconfig/iptables-config +# +### BEGIN INIT INFO +# Provides: iptables +# Required-Start: +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: start and stop iptables firewall +# Description: Start, stop and save iptables firewall +### END INIT INFO + +# Source function library. +. /etc/init.d/functions + +IPTABLES=iptables +IPTABLES_DATA=/etc/sysconfig/$IPTABLES +IPTABLES_FALLBACK_DATA=${IPTABLES_DATA}.fallback +IPTABLES_CONFIG=/etc/sysconfig/${IPTABLES}-config +IPV=${IPTABLES%tables} # ip for ipv4 | ip6 for ipv6 +[ "$IPV" = "ip" ] && _IPV="ipv4" || _IPV="ipv6" +VAR_SUBSYS_IPTABLES=/var/lock/subsys/$IPTABLES + +# only usable for root +if [ $EUID != 0 ]; then + echo -n $"${IPTABLES}: Only usable by root."; warning; echo + exit 4 +fi + +if [ ! -x /sbin/$IPTABLES ]; then + echo -n $"${IPTABLES}: /sbin/$IPTABLES does not exist."; warning; echo + exit 5 +fi + +# Default firewall configuration: +IPTABLES_MODULES="" +IPTABLES_SAVE_ON_STOP="no" +IPTABLES_SAVE_ON_RESTART="no" +IPTABLES_SAVE_COUNTER="no" +IPTABLES_STATUS_NUMERIC="yes" +IPTABLES_STATUS_VERBOSE="no" +IPTABLES_STATUS_LINENUMBERS="yes" +IPTABLES_SYSCTL_LOAD_LIST="" +IPTABLES_RESTORE_WAIT=600 +IPTABLES_RESTORE_WAIT_INTERVAL=1000000 + +# Load firewall configuration. +[ -f "$IPTABLES_CONFIG" ] && . "$IPTABLES_CONFIG" + +# explicitly omit security table from this list as +# it should be reserved for SELinux use +NF_TABLES="raw mangle filter nat" + + +flush_n_delete() { + # Flush firewall rules and delete chains. + echo -n $"${IPTABLES}: Flushing firewall rules: " + ret=0 + # For all tables + for i in $NF_TABLES; do + # Flush firewall rules. + $IPTABLES -t $i -F; + let ret+=$?; + + # Delete firewall chains. + $IPTABLES -t $i -X; + let ret+=$?; + + # Set counter to zero. + $IPTABLES -t $i -Z; + let ret+=$?; + done + + [ $ret -eq 0 ] && success || failure + echo + return $ret +} + +set_policy() { + # Set policy for configured tables. + policy=$1 + echo -n $"${IPTABLES}: Setting chains to policy $policy: " + ret=0 + for i in $NF_TABLES; do + echo -n "$i " + case "$i" in + raw) + $IPTABLES -t raw -P PREROUTING $policy \ + && $IPTABLES -t raw -P OUTPUT $policy \ + || let ret+=1 + ;; + filter) + $IPTABLES -t filter -P INPUT $policy \ + && $IPTABLES -t filter -P OUTPUT $policy \ + && $IPTABLES -t filter -P FORWARD $policy \ + || let ret+=1 + ;; + nat) + $IPTABLES -t nat -P PREROUTING $policy \ + && $IPTABLES -t nat -P POSTROUTING $policy \ + && $IPTABLES -t nat -P OUTPUT $policy \ + || let ret+=1 + ;; + mangle) + $IPTABLES -t mangle -P PREROUTING $policy \ + && $IPTABLES -t mangle -P POSTROUTING $policy \ + && $IPTABLES -t mangle -P INPUT $policy \ + && $IPTABLES -t mangle -P OUTPUT $policy \ + && $IPTABLES -t mangle -P FORWARD $policy \ + || let ret+=1 + ;; + *) + let ret+=1 + ;; + esac + done + + [ $ret -eq 0 ] && success || failure + echo + return $ret +} + +load_sysctl() { + # load matched sysctl values + if [ -n "$IPTABLES_SYSCTL_LOAD_LIST" ]; then + echo -n $"Loading sysctl settings: " + ret=0 + for item in $IPTABLES_SYSCTL_LOAD_LIST; do + fgrep -hs $item /etc/sysctl.d/* | sysctl -p - >/dev/null + let ret+=$?; + done + [ $ret -eq 0 ] && success || failure + echo + fi + return $ret +} + +start() { + # Do not start if there is no config file. + if [ ! -f "$IPTABLES_DATA" ]; then + echo -n $"${IPTABLES}: No config file."; warning; echo + return 6 + fi + + # check if ipv6 module load is deactivated + if [ "${_IPV}" = "ipv6" ] \ + && grep -qIsE "^install[[:space:]]+${_IPV}[[:space:]]+/bin/(true|false)" /etc/modprobe.conf /etc/modprobe.d/* ; then + echo $"${IPTABLES}: ${_IPV} is disabled." + return 150 + fi + + echo -n $"${IPTABLES}: Applying firewall rules: " + + OPT= + [ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c" + if [ $IPTABLES_RESTORE_WAIT -ne 0 ]; then + OPT="${OPT} --wait ${IPTABLES_RESTORE_WAIT}" + if [ $IPTABLES_RESTORE_WAIT_INTERVAL -lt 1000000 ]; then + OPT="${OPT} --wait-interval ${IPTABLES_RESTORE_WAIT_INTERVAL}" + fi + fi + + $IPTABLES-restore $OPT $IPTABLES_DATA + if [ $? -eq 0 ]; then + success; echo + else + failure; echo; + if [ -f "$IPTABLES_FALLBACK_DATA" ]; then + echo -n $"${IPTABLES}: Applying firewall fallback rules: " + $IPTABLES-restore $OPT $IPTABLES_FALLBACK_DATA + if [ $? -eq 0 ]; then + success; echo + else + failure; echo; return 1 + fi + else + return 1 + fi + fi + + # Load additional modules (helpers) + if [ -n "$IPTABLES_MODULES" ]; then + echo -n $"${IPTABLES}: Loading additional modules: " + ret=0 + for mod in $IPTABLES_MODULES; do + echo -n "$mod " + modprobe $mod > /dev/null 2>&1 + let ret+=$?; + done + [ $ret -eq 0 ] && success || failure + echo + fi + + # Load sysctl settings + load_sysctl + + touch $VAR_SUBSYS_IPTABLES + return $ret +} + +stop() { + # Set default chain policy to ACCEPT, in order to not break shutdown + # on systems where the default policy is DROP and root device is + # network-based (i.e.: iSCSI, NFS) + set_policy ACCEPT + # And then, flush the rules and delete chains + flush_n_delete + + rm -f $VAR_SUBSYS_IPTABLES + return $ret +} + +save() { + echo -n $"${IPTABLES}: Saving firewall rules to $IPTABLES_DATA: " + + OPT= + [ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c" + + ret=0 + TMP_FILE=$(/bin/mktemp -q $IPTABLES_DATA.XXXXXX) \ + && chmod 600 "$TMP_FILE" \ + && $IPTABLES-save $OPT > $TMP_FILE 2>/dev/null \ + && size=$(stat -c '%s' $TMP_FILE) && [ $size -gt 0 ] \ + || ret=1 + if [ $ret -eq 0 ]; then + if [ -e $IPTABLES_DATA ]; then + cp -f $IPTABLES_DATA $IPTABLES_DATA.save \ + && chmod 600 $IPTABLES_DATA.save \ + && restorecon $IPTABLES_DATA.save \ + || ret=1 + fi + if [ $ret -eq 0 ]; then + mv -f $TMP_FILE $IPTABLES_DATA \ + && chmod 600 $IPTABLES_DATA \ + && restorecon $IPTABLES_DATA \ + || ret=1 + fi + fi + rm -f $TMP_FILE + [ $ret -eq 0 ] && success || failure + echo + return $ret +} + +status() { + if [ ! -f "$VAR_SUBSYS_IPTABLES" ]; then + echo $"${IPTABLES}: Firewall is not running." + return 3 + fi + + NUM= + [ "x$IPTABLES_STATUS_NUMERIC" = "xyes" ] && NUM="-n" + VERBOSE= + [ "x$IPTABLES_STATUS_VERBOSE" = "xyes" ] && VERBOSE="--verbose" + COUNT= + [ "x$IPTABLES_STATUS_LINENUMBERS" = "xyes" ] && COUNT="--line-numbers" + + for table in $NF_TABLES; do + echo $"Table: $table" + $IPTABLES -t $table --list $NUM $VERBOSE $COUNT && echo + done + + return 0 +} + +reload() { + # Do not reload if there is no config file. + if [ ! -f "$IPTABLES_DATA" ]; then + echo -n $"${IPTABLES}: No config file."; warning; echo + return 6 + fi + + # check if ipv6 module load is deactivated + if [ "${_IPV}" = "ipv6" ] \ + && grep -qIsE "^install[[:space:]]+${_IPV}[[:space:]]+/bin/(true|false)" /etc/modprobe.conf /etc/modprobe.d/* ; then + echo $"${IPTABLES}: ${_IPV} is disabled." + return 150 + fi + + echo -n $"${IPTABLES}: Trying to reload firewall rules: " + + OPT= + [ "x$IPTABLES_SAVE_COUNTER" = "xyes" ] && OPT="-c" + if [ $IPTABLES_RESTORE_WAIT -ne 0 ]; then + OPT="${OPT} --wait ${IPTABLES_RESTORE_WAIT}" + if [ $IPTABLES_RESTORE_WAIT_INTERVAL -lt 1000000 ]; then + OPT="${OPT} --wait-interval ${IPTABLES_RESTORE_WAIT_INTERVAL}" + fi + fi + + $IPTABLES-restore $OPT $IPTABLES_DATA + if [ $? -eq 0 ]; then + success; echo + else + failure; echo; echo "Firewall rules are not changed."; return 1 + fi + + # Load additional modules (helpers) + if [ -n "$IPTABLES_MODULES" ]; then + echo -n $"${IPTABLES}: Loading additional modules: " + ret=0 + for mod in $IPTABLES_MODULES; do + echo -n "$mod " + modprobe $mod > /dev/null 2>&1 + let ret+=$?; + done + [ $ret -eq 0 ] && success || failure + echo + fi + + # Load sysctl settings + load_sysctl + + return $ret +} + +restart() { + [ "x$IPTABLES_SAVE_ON_RESTART" = "xyes" ] && save + stop + start +} + + +case "$1" in + start) + [ -f "$VAR_SUBSYS_IPTABLES" ] && exit 0 + start + RETVAL=$? + ;; + stop) + [ "x$IPTABLES_SAVE_ON_STOP" = "xyes" ] && save + stop + RETVAL=$? + ;; + restart|force-reload) + restart + RETVAL=$? + ;; + reload) + [ -e "$VAR_SUBSYS_IPTABLES" ] && reload + RETVAL=$? + ;; + condrestart|try-restart) + [ ! -e "$VAR_SUBSYS_IPTABLES" ] && exit 0 + restart + RETVAL=$? + ;; + status) + status + RETVAL=$? + ;; + panic) + set_policy DROP + RETVAL=$? + ;; + save) + save + RETVAL=$? + ;; + *) + echo $"Usage: ${IPTABLES} {start|stop|reload|restart|condrestart|status|panic|save}" + RETVAL=2 + ;; +esac + +exit $RETVAL diff --git a/SOURCES/iptables.service b/SOURCES/iptables.service new file mode 100644 index 0000000..6722c7a --- /dev/null +++ b/SOURCES/iptables.service @@ -0,0 +1,18 @@ +[Unit] +Description=IPv4 firewall with iptables +After=syslog.target +AssertPathExists=/etc/sysconfig/iptables + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/libexec/iptables/iptables.init start +ExecReload=/usr/libexec/iptables/iptables.init reload +ExecStop=/usr/libexec/iptables/iptables.init stop +Environment=BOOTUP=serial +Environment=CONSOLETYPE=serial +StandardOutput=syslog +StandardError=syslog + +[Install] +WantedBy=basic.target diff --git a/SOURCES/sysconfig_ip6tables b/SOURCES/sysconfig_ip6tables new file mode 100644 index 0000000..34b8b87 --- /dev/null +++ b/SOURCES/sysconfig_ip6tables @@ -0,0 +1,15 @@ +# sample configuration for ip6tables service +# you can edit this manually or use system-config-firewall +# please do not ask us to add additional ports/services to this default configuration +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p ipv6-icmp -j ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT +-A INPUT -d fe80::/64 -p udp -m udp --dport 546 -m state --state NEW -j ACCEPT +-A INPUT -j REJECT --reject-with icmp6-adm-prohibited +-A FORWARD -j REJECT --reject-with icmp6-adm-prohibited +COMMIT diff --git a/SOURCES/sysconfig_iptables b/SOURCES/sysconfig_iptables new file mode 100644 index 0000000..5183250 --- /dev/null +++ b/SOURCES/sysconfig_iptables @@ -0,0 +1,14 @@ +# sample configuration for iptables service +# you can edit this manually or use system-config-firewall +# please do not ask us to add additional ports/services to this default configuration +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p icmp -j ACCEPT +-A INPUT -i lo -j ACCEPT +-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT +-A INPUT -j REJECT --reject-with icmp-host-prohibited +-A FORWARD -j REJECT --reject-with icmp-host-prohibited +COMMIT diff --git a/SPECS/iptables.spec b/SPECS/iptables.spec new file mode 100644 index 0000000..7f70aea --- /dev/null +++ b/SPECS/iptables.spec @@ -0,0 +1,1604 @@ +# install init scripts to /usr/libexec with systemd +%global script_path %{_libexecdir}/iptables + +# service legacy actions (RHBZ#748134) +%global legacy_actions %{_libexecdir}/initscripts/legacy-actions + +Name: iptables +Summary: Tools for managing Linux kernel packet filtering capabilities +Version: 1.8.2 +Release: 12%{?dist} +Source: http://www.netfilter.org/projects/iptables/files/%{name}-%{version}.tar.bz2 +Source1: iptables.init +Source2: iptables-config +Source3: iptables.service +Source4: sysconfig_iptables +Source5: sysconfig_ip6tables +Source6: arptables.service +Source7: arptables-helper +Source8: ebtables.systemd +Source9: ebtables.service +Source10: ebtables-config +Source11: ebtables.8 +Source12: arptables.8 +Patch1: 0001-Add-iptables-test.py-testsuite-from-v1.8.2.patch +Patch2: 0002-iptables-apply-Use-mktemp-instead-of-tempfile.patch +Patch3: 0003-extensions-format-security-fixes-in-libip-6-t_icmp.patch +Patch4: 0004-arptables-nft-use-generic-expression-parsing-functio.patch +Patch5: 0005-xtables-Don-t-use-native-nftables-comments.patch +Patch6: 0006-xtables-Introduce-per-table-chain-caches.patch +Patch7: 0007-nft-add-type-field-to-builtin_table.patch +Patch8: 0008-nft-move-chain_cache-back-to-struct-nft_handle.patch +Patch9: 0009-nft-move-initialize-to-struct-nft_handle.patch +Patch10: 0010-xtables-constify-struct-builtin_table-and-struct-bui.patch +Patch11: 0011-nft-Simplify-nftnl_rule_list_chain_save.patch +Patch12: 0012-nft-Review-unclear-return-points.patch +Patch13: 0013-xtables-restore-Review-chain-handling.patch +Patch14: 0014-nft-Review-is_-_compatible-routines.patch +Patch15: 0015-nft-Reduce-__nft_rule_del-signature.patch +Patch16: 0016-nft-Reduce-indenting-level-in-flush_chain_cache.patch +Patch17: 0017-nft-Simplify-per-table-chain-cache-update.patch +Patch18: 0018-nft-Simplify-nft_rule_insert-a-bit.patch +Patch19: 0019-nft-Introduce-fetch_chain_cache.patch +Patch20: 0020-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch +Patch21: 0021-xtables-Implement-per-chain-rule-cache.patch +Patch22: 0022-nft-Drop-nft_chain_list_find.patch +Patch23: 0023-xtables-Optimize-flushing-a-specific-chain.patch +Patch24: 0024-xtables-Optimize-nft_chain_zero_counters.patch +Patch25: 0025-tests-Extend-verbose-output-and-return-code-tests.patch +Patch26: 0026-xtables-Optimize-user-defined-chain-deletion.patch +Patch27: 0027-xtables-Optimize-list-command-with-given-chain.patch +Patch28: 0028-xtables-Optimize-list-rules-command-with-given-chain.patch +Patch29: 0029-nft-Make-use-of-nftnl_rule_lookup_byindex.patch +Patch30: 0030-nft-Simplify-nft_is_chain_compatible.patch +Patch31: 0031-nft-Simplify-flush_chain_cache.patch +Patch32: 0032-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch +Patch33: 0033-xtables-Speed-up-chain-deletion-in-large-rulesets.patch +Patch34: 0034-arptables-nft-Fix-listing-rules-without-target.patch +Patch35: 0035-arptables-nft-Fix-MARK-target-parsing-and-printing.patch +Patch36: 0036-arptables-nft-Fix-CLASSIFY-target-printing.patch +Patch37: 0037-arptables-nft-Remove-space-between-cnt-and-value.patch +Patch38: 0038-arptables-nft-save-Fix-position-of-j-option.patch +Patch39: 0039-arptables-nft-Don-t-print-default-h-len-h-type-value.patch +Patch40: 0040-tests-shell-Add-arptables-nft-verbose-output-test.patch +Patch41: 0041-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch +Patch42: 0042-nft-Add-new-builtin-chains-to-cache-immediately.patch +Patch43: 0043-xtables-Fix-position-of-replaced-rules-in-cache.patch +Patch44: 0044-xtables-Fix-for-inserting-rule-at-wrong-position.patch +Patch45: 0045-xtables-Fix-for-crash-when-comparing-rules-with-stan.patch +Patch46: 0046-xtables-Fix-for-false-positive-rule-matching.patch +Patch47: 0047-ebtables-Fix-rule-listing-with-counters.patch +Patch48: 0048-Revert-ebtables-use-extrapositioned-negation-consist.patch +Patch49: 0049-arptables-Support-set-counters-option.patch +Patch50: 0050-xshared-Explicitly-pass-target-to-command_jump.patch +Patch51: 0051-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch +Patch52: 0052-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch +Patch53: 0053-ebtables-nft-Support-user-defined-chain-policies.patch +Patch54: 0054-extensions-libipt_realm-Document-allowed-realm-value.patch +Patch55: 0055-extensions-TRACE-Point-at-xtables-monitor-in-documen.patch +Patch56: 0056-xtables-Catch-errors-when-zeroing-rule-rounters.patch +Patch57: 0057-xtables-save-Fix-table-not-found-error-message.patch +Patch58: 0058-arptables-nft-fix-decoding-of-hlen-on-bigendian-plat.patch +Patch59: 0059-extensions-libip6t_mh-fix-bogus-translation-error.patch +Patch60: 0060-xtables-save-Point-at-existing-man-page-in-help-text.patch +Patch61: 0061-xtables-restore-Fix-program-names-in-help-texts.patch +Patch62: 0062-extensions-AUDIT-Document-ineffective-type-option.patch +Patch63: 0063-utils-Add-a-manpage-for-nfbpf_compile.patch + +URL: http://www.netfilter.org/ +# pf.os: ISC license +# iptables-apply: Artistic Licence 2.0 +License: GPLv2 and Artistic 2.0 and ISC + +# libnetfilter_conntrack is needed for xt_connlabel +BuildRequires: pkgconfig(libnetfilter_conntrack) +# libnfnetlink-devel is requires for nfnl_osf +BuildRequires: pkgconfig(libnfnetlink) +BuildRequires: libselinux-devel +BuildRequires: kernel-headers +BuildRequires: systemd +# libmnl, libnftnl, bison, flex for nftables +BuildRequires: bison +BuildRequires: flex +BuildRequires: gcc +BuildRequires: pkgconfig(libmnl) >= 1.0 +BuildRequires: pkgconfig(libnftnl) >= 1.1.1-4 +# libpcap-devel for nfbpf_compile +BuildRequires: libpcap-devel +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool +Requires: %{name}-libs%{?_isa} = %{version}-%{release} +%if 0%{?fedora} > 24 +Conflicts: setup < 2.10.4-1 +%endif + +%description +The iptables utility controls the network packet filtering code in the +Linux kernel. If you need to set up firewalls and/or IP masquerading, +you should either install nftables or this package. + +Note: This package contains the nftables-based variants of iptables and +ip6tables, which are drop-in replacements of the legacy tools. + +%package libs +Summary: iptables libraries +Group: System Environment/Base + +%description libs +iptables libraries. + +Please remember that libip*tc libraries do neither have a stable API nor a real so version. + +For more information about this, please have a look at + + http://www.netfilter.org/documentation/FAQ/netfilter-faq-4.html#ss4.5 + + +%package devel +Summary: Development package for iptables +Group: System Environment/Base +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: iptables-libs = %{version}-%{release} +Requires: pkgconfig + +%description devel +iptables development headers and libraries. + +The iptc libraries are marked as not public by upstream. The interface is not +stable and may change with every new version. It is therefore unsupported. + +%package services +Summary: iptables and ip6tables services for iptables +Group: System Environment/Base +Requires: %{name} = %{version}-%{release} +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +# obsolete old main package +Obsoletes: %{name} < 1.4.16.1 +# obsolete ipv6 sub package +Obsoletes: %{name}-ipv6 < 1.4.11.1 + +%description services +iptables services for IPv4 and IPv6 + +This package provides the services iptables and ip6tables that have been split +out of the base package since they are not active by default anymore. + +%package utils +Summary: iptables and ip6tables services for iptables +Group: System Environment/Base +Requires: %{name} = %{version}-%{release} + +%description utils +Utils for iptables. + +Currently only provides nfnl_osf with the pf.os database. + +%package arptables +Summary: User space tool to set up tables of ARP rules in kernel +Group: System Environment/Base +Requires: %{name} = %{version}-%{release} +Obsoletes: arptables +Provides: arptables + +%description arptables +The arptables tool is used to set up and maintain +the tables of ARP rules in the Linux kernel. These rules inspect +the ARP frames which they see. arptables is analogous to the iptables +user space tool, but is less complicated. + +Note: This package contains the nftables-based variant of arptables, a drop-in +replacement of the legacy tool. + +%package ebtables +Summary: Ethernet Bridge frame table administration tool +Group: System Environment/Base +Requires: %{name} = %{version}-%{release} +Obsoletes: ebtables +Provides: ebtables + +%description ebtables +Ethernet bridge tables is a firewalling tool to transparently filter network +traffic passing a bridge. The filtering possibilities are limited to link +layer filtering and some basic filtering on higher network layers. + +This tool is the userspace control for the bridge and ebtables kernel +components (built by default in RHEL kernels). + +The ebtables tool can be used together with the other Linux filtering tools, +like iptables. There are no known incompatibility issues. + +Note: This package contains the nftables-based variant of ebtables, a drop-in +replacement of the legacy tool. + +%prep +%autosetup -p1 + +%build +./autogen.sh +CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing " \ +%configure --enable-devel --enable-bpf-compiler --with-kernel=/usr --with-kbuild=/usr --with-ksource=/usr + +# do not use rpath +sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool +sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool + +rm -f include/linux/types.h + +make %{?_smp_mflags} V=1 + +%install +make install DESTDIR=%{buildroot} +# remove la file(s) +rm -f %{buildroot}/%{_libdir}/*.la + +# install ip*tables.h header files +install -m 644 include/ip*tables.h %{buildroot}%{_includedir}/ +install -d -m 755 %{buildroot}%{_includedir}/iptables +install -m 644 include/iptables/internal.h %{buildroot}%{_includedir}/iptables/ + +# install ipulog header file +install -d -m 755 %{buildroot}%{_includedir}/libipulog/ +install -m 644 include/libipulog/*.h %{buildroot}%{_includedir}/libipulog/ + +# install init scripts and configuration files +install -d -m 755 %{buildroot}%{script_path} +install -c -m 755 %{SOURCE1} %{buildroot}%{script_path}/iptables.init +sed -e 's;iptables;ip6tables;g' -e 's;IPTABLES;IP6TABLES;g' < %{SOURCE1} > ip6tables.init +install -c -m 755 ip6tables.init %{buildroot}%{script_path}/ip6tables.init +install -d -m 755 %{buildroot}%{_sysconfdir}/sysconfig +install -c -m 600 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/iptables-config +sed -e 's;iptables;ip6tables;g' -e 's;IPTABLES;IP6TABLES;g' < %{SOURCE2} > ip6tables-config +install -c -m 600 ip6tables-config %{buildroot}%{_sysconfdir}/sysconfig/ip6tables-config +install -c -m 600 %{SOURCE4} %{buildroot}%{_sysconfdir}/sysconfig/iptables +install -c -m 600 %{SOURCE5} %{buildroot}%{_sysconfdir}/sysconfig/ip6tables + +# install systemd service files +install -d -m 755 %{buildroot}/%{_unitdir} +install -c -m 644 %{SOURCE3} %{buildroot}/%{_unitdir} +sed -e 's;iptables;ip6tables;g' -e 's;IPv4;IPv6;g' -e 's;/usr/libexec/ip6tables;/usr/libexec/iptables;g' < %{SOURCE3} > ip6tables.service +install -c -m 644 ip6tables.service %{buildroot}/%{_unitdir} + +# install legacy actions for service command +install -d %{buildroot}/%{legacy_actions}/iptables +install -d %{buildroot}/%{legacy_actions}/ip6tables + +cat << EOF > %{buildroot}/%{legacy_actions}/iptables/save +#!/bin/bash +exec %{script_path}/iptables.init save +EOF +chmod 755 %{buildroot}/%{legacy_actions}/iptables/save +sed -e 's;iptables.init;ip6tables.init;g' -e 's;IPTABLES;IP6TABLES;g' < %{buildroot}/%{legacy_actions}/iptables/save > ip6tabes.save-legacy +install -c -m 755 ip6tabes.save-legacy %{buildroot}/%{legacy_actions}/ip6tables/save + +cat << EOF > %{buildroot}/%{legacy_actions}/iptables/panic +#!/bin/bash +exec %{script_path}/iptables.init panic +EOF +chmod 755 %{buildroot}/%{legacy_actions}/iptables/panic +sed -e 's;iptables.init;ip6tables.init;g' -e 's;IPTABLES;IP6TABLES;g' < %{buildroot}/%{legacy_actions}/iptables/panic > ip6tabes.panic-legacy +install -c -m 755 ip6tabes.panic-legacy %{buildroot}/%{legacy_actions}/ip6tables/panic + +# install iptables-apply with man page +install -m 755 iptables/iptables-apply %{buildroot}%{_sbindir}/ +install -m 644 iptables/iptables-apply.8 %{buildroot}%{_mandir}/man8/ + +%if 0%{?fedora} > 24 +# Remove /etc/ethertypes (now part of setup) +rm -f %{buildroot}%{_sysconfdir}/ethertypes +%endif + +# drop all legacy tools +rm -f %{buildroot}%{_sbindir}/*legacy* +rm -f %{buildroot}%{_bindir}/iptables-xml +rm -f %{buildroot}%{_mandir}/man1/iptables-xml* +rm -f %{buildroot}%{_mandir}/man8/xtables-legacy* + +# rename nft versions to standard name +pfx=%{buildroot}%{_sbindir}/iptables +for pfx in %{buildroot}%{_sbindir}/{iptables,ip6tables,arptables,ebtables}; do + mv $pfx-nft $pfx + mv $pfx-nft-restore $pfx-restore + mv $pfx-nft-save $pfx-save +done + +# extra sources for arptables +install -p -D -m 644 %{SOURCE6} %{buildroot}%{_unitdir}/arptables.service +mkdir -p %{buildroot}%{_libexecdir}/ +install -p -D -m 755 %{SOURCE7} %{buildroot}%{_libexecdir}/ +mkdir -p %{buildroot}%{_sysconfdir}/sysconfig +echo '# Configure prior to use' > %{buildroot}%{_sysconfdir}/sysconfig/arptables +install -m0644 %{SOURCE12} %{buildroot}%{_mandir}/man8/arptables.8 + +# extra sources for ebtables +install -p %{SOURCE9} %{buildroot}%{_unitdir}/ +install -m0755 %{SOURCE8} %{buildroot}%{_libexecdir}/ebtables +install -m0600 %{SOURCE10} %{buildroot}%{_sysconfdir}/sysconfig/ebtables-config +touch %{buildroot}%{_sysconfdir}/sysconfig/ebtables +install -m0644 %{SOURCE11} %{buildroot}%{_mandir}/man8/ebtables.8 + + +%if 0%{?rhel} +%pre +for p in %{_sysconfdir}/alternatives/{iptables,ip6tables}.*; do + if [ -h "$p" ]; then + ipt=$(readlink "$p") + echo "Removing alternatives for ${p##*/} with path $ipt" + %{_sbindir}/alternatives --remove "${p##*/}" "$ipt" + fi +done +%endif + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%post services +%systemd_post iptables.service ip6tables.service + +%preun services +%systemd_preun iptables.service ip6tables.service + +%postun services +/sbin/ldconfig +%systemd_postun iptables.service ip6tables.service + +%post arptables +%systemd_post arptables.service + +%preun arptables +%systemd_preun arptables.service + +%postun arptables +%systemd_postun arptables.service + +%post ebtables +%systemd_post ebtables.service + +%preun ebtables +%systemd_preun ebtables.service + +%postun ebtables +%systemd_postun_with_restart ebtables.service + +%files +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc INCOMPATIBILITIES +%config(noreplace) %{_sysconfdir}/sysconfig/iptables-config +%config(noreplace) %{_sysconfdir}/sysconfig/ip6tables-config +%if 0%{?fedora} <= 24 +%{_sysconfdir}/ethertypes +%endif +%{_sbindir}/iptables +%{_sbindir}/iptables-apply +%{_sbindir}/iptables-restore +%{_sbindir}/iptables-restore-translate +%{_sbindir}/iptables-save +%{_sbindir}/iptables-translate +%{_sbindir}/ip6tables +%{_sbindir}/ip6tables-restore +%{_sbindir}/ip6tables-restore-translate +%{_sbindir}/ip6tables-save +%{_sbindir}/ip6tables-translate +%{_sbindir}/xtables-monitor +%{_sbindir}/xtables-nft-multi +%doc %{_mandir}/man8/iptables* +%doc %{_mandir}/man8/ip6tables* +%doc %{_mandir}/man8/xtables-monitor* +%doc %{_mandir}/man8/xtables-nft* +%doc %{_mandir}/man8/xtables-translate* +%dir %{_libdir}/xtables +%{_libdir}/xtables/libarpt* +%{_libdir}/xtables/libebt* +%{_libdir}/xtables/libipt* +%{_libdir}/xtables/libip6t* +%{_libdir}/xtables/libxt* + +%files libs +%{_libdir}/libip*tc.so.* +%{_libdir}/libxtables.so.* + +%files devel +%dir %{_includedir}/iptables +%{_includedir}/iptables/*.h +%{_includedir}/*.h +%dir %{_includedir}/libiptc +%{_includedir}/libiptc/*.h +%dir %{_includedir}/libipulog +%{_includedir}/libipulog/*.h +%{_libdir}/libip*tc.so +%{_libdir}/libxtables.so +%{_libdir}/pkgconfig/libiptc.pc +%{_libdir}/pkgconfig/libip4tc.pc +%{_libdir}/pkgconfig/libip6tc.pc +%{_libdir}/pkgconfig/xtables.pc + +%files services +%dir %{script_path} +%{script_path}/iptables.init +%{script_path}/ip6tables.init +%config(noreplace) %{_sysconfdir}/sysconfig/iptables +%config(noreplace) %{_sysconfdir}/sysconfig/ip6tables +%{_unitdir}/iptables.service +%{_unitdir}/ip6tables.service +%dir %{legacy_actions}/iptables +%{legacy_actions}/iptables/save +%{legacy_actions}/iptables/panic +%dir %{legacy_actions}/ip6tables +%{legacy_actions}/ip6tables/save +%{legacy_actions}/ip6tables/panic + +%files utils +%{_sbindir}/nfnl_osf +%{_sbindir}/nfbpf_compile +%dir %{_datadir}/xtables +%{_datadir}/xtables/pf.os +%doc %{_mandir}/man8/nfnl_osf* +%doc %{_mandir}/man8/nfbpf_compile* + +%files arptables +%{_sbindir}/arptables* +%{_libexecdir}/arptables-helper +%{_unitdir}/arptables.service +%config(noreplace) %{_sysconfdir}/sysconfig/arptables +%doc %{_mandir}/man8/arptables.8* + +%files ebtables +%{_sbindir}/ebtables* +%{_libexecdir}/ebtables +%{_unitdir}/ebtables.service +%config(noreplace) %{_sysconfdir}/sysconfig/ebtables-config +%ghost %{_sysconfdir}/sysconfig/ebtables +%doc %{_mandir}/man8/ebtables.8* + +%changelog +* Wed Jun 12 2019 Phil Sutter - 1.8.2-12 +- Add iptables-test.py testsuite to sources +- extensions: libip6t_mh: fix bogus translation error +- extensions: AUDIT: Document ineffective --type option +- xtables-restore: Fix program names in help texts +- xtables-save: Point at existing man page in help text +- utils: Add a manpage for nfbpf_compile +- Mark man pages in base package as documentation files + +* Thu May 23 2019 Phil Sutter - 1.8.2-11 +- Enable verbose output when building + +* Thu May 09 2019 Phil Sutter - 1.8.2-10 +- arptables-nft: fix decoding of hlen on bigendian platforms +- xtables-save: Fix table not found error message +- xtables: Catch errors when zeroing rule rounters +- extensions: TRACE: Point at xtables-monitor in documentation +- extensions: libipt_realm: Document allowed realm values + +* Fri Feb 08 2019 Phil Sutter - 1.8.2-9 +- ebtables-nft: Support user-defined chain policies + +* Thu Feb 07 2019 Phil Sutter - 1.8.2-8 +- arptables.8: Document --set-counters option + +* Thu Feb 07 2019 Phil Sutter - 1.8.2-7 +- arptables: Support --set-counters option + +* Fri Feb 01 2019 Phil Sutter - 1.8.2-6 +- Improve performance with large rulesets +- Fix for changes in arptables output +- Fix for inserting rules at wrong position +- Fix segfault when comparing rules with standard target +- Fix ebtables output for negated values +- Document missing arptables FORWARD chain + +* Tue Dec 18 2018 Phil Sutter - 1.8.2-5 +- Drop change to test snippet not included in tarball from Patch4 + +* Tue Dec 18 2018 Phil Sutter - 1.8.2-4 +- Fix iptables init script for nftables-backend +- Drop references to unsupported broute table from ebtables man page +- xtables: Don't use native nftables comments + +* Thu Dec 06 2018 Phil Sutter - 1.8.2-3 +- Drop change to test snippet not included in tarball from Patch3 + +* Thu Dec 06 2018 Phil Sutter - 1.8.2-2 +- Point out that nftables-variants are installed in package description +- Fix for deleting arptables rules by referencing them + +* Thu Dec 06 2018 Phil Sutter - 1.8.2-1 +- Rebase onto upstream version 1.8.2 + +* Thu Oct 25 2018 Phil Sutter - 1.8.1-2 +- Add upstream fixes to 1.8.1 release + +* Thu Oct 25 2018 Phil Sutter - 1.8.1-1 +- Rebase onto upstream version 1.8.1 + +* Thu Sep 27 2018 Phil Sutter - 1.8.0-11 +- Fix for covscan warnings in init scripts + +* Wed Sep 26 2018 Phil Sutter - 1.8.0-10 +- Fix short name of Artistic Licence + +* Wed Sep 26 2018 Phil Sutter - 1.8.0-9 +- Add further fixes for issues identified by covscan +- Fix for bogus "is incompatible" warnings +- Fix layout in License tag +- Replace "Fedora" with "RHEL" in description +- Make devel sub-package depend on libs sub-package + +* Mon Sep 17 2018 Phil Sutter - 1.8.0-8 +- Fix issues identified by covscan +- xtables-restore: Fix flushing referenced custom chains +- xtables: Accept --wait in iptables-nft-restore + +* Mon Sep 03 2018 Phil Sutter - 1.8.0-7 +- xtables: Align return codes with legacy iptables +- xtables: Drop use of IP6T_F_PROTO + +* Wed Aug 29 2018 Phil Sutter - 1.8.0-6 +- xtables: Fix for deleting rules with comment + +* Fri Aug 24 2018 Phil Sutter - 1.8.0-5 +- xtables: Use meta l4proto for -p match +- ebtables: Fix for listing of non-existent chains +- xtables: Fix for no output in iptables-nft -S + +* Sat Aug 18 2018 Phil Sutter - 1.8.0-4 +- xtables: Fix for segfault in iptables-nft +- ebtables: Fix entries count in chain listing +- Use %%autosetup macro in %%prep + +* Fri Aug 17 2018 Phil Sutter - 1.8.0-3 +- xtables: Make 'iptables -S nonexisting' return non-zero + +* Fri Aug 10 2018 Phil Sutter - 1.8.0-2 +- Rebase onto upstream master commit 514de4801b731db4712 +- Add arptables and ebtables sub-packages + +* Wed Jul 11 2018 Phil Sutter - 1.8.0-1 +- New upstream version 1.8.0 +- Drop compat sub-package +- Use nft tool versions, drop legacy ones + +* Thu Mar 01 2018 Phil Sutter - 1.6.2-2 +- Kill module unloading support +- Support /etc/sysctl.d +- Don't restart services after package update +- Add support for --wait options to restore commands + +* Wed Feb 21 2018 Michael Cronenworth - 1.6.2-1 +- New upstream version 1.6.2 + http://www.netfilter.org/projects/iptables/files/changes-iptables-1.6.2.txt + +* Wed Feb 07 2018 Fedora Release Engineering - 1.6.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sun Oct 22 2017 Kevin Fenzi - 1.6.1-5 +- Rebuild for new libnftnl + +* Wed Aug 02 2017 Fedora Release Engineering - 1.6.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 1.6.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Fri Feb 10 2017 Fedora Release Engineering - 1.6.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Feb 02 2017 Thomas Woerner - 1.6.1-1 +- New upstream version 1.6.1 with enhanced translation to nft support and + several fixes (RHBZ#1417323) + http://netfilter.org/projects/iptables/files/changes-iptables-1.6.1.txt +- Enable parallel build again + +* Thu Feb 02 2017 Petr Šabata - 1.6.0-4 +- Disabling parallel build to avoid build issues with xtables +- See http://patchwork.alpinelinux.org/patch/1787/ for reference +- This should be fixed in 1.6.1; parallel build can be restored after the + update + +* Mon Dec 19 2016 Thomas Woerner - 1.6.0-3 +- Dropped bad provides for iptables in services sub package (RHBZ#1327786) + +* Fri Jul 22 2016 Thomas Woerner - 1.6.0-2 +- /etc/ethertypes has been moved into the setup package for F-25+. + (RHBZ#1329256) + +* Wed Apr 13 2016 Thomas Woerner - 1.6.0-1 +- New upstream version 1.6.0 with nft-compat support and lots of fixes (RHBZ#1292990) + Upstream changelog: + http://netfilter.org/projects/iptables/files/changes-iptables-1.6.0.txt +- New libs sub package containing libxtables and unstable libip*tc libraries (RHBZ#1323161) +- Using scripts form RHEL-7 (RHBZ#1240366) +- New compat sub package for nftables compatibility +- Install iptables-apply (RHBZ#912047) +- Fixed module uninstall (RHBZ#1324101) +- Incorporated changes by Petr Pisar +- Enabled bpf compiler (RHBZ#1170227) Thanks to Yanko Kaneti for the patch + +* Thu Feb 04 2016 Fedora Release Engineering - 1.4.21-16 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jun 17 2015 Fedora Release Engineering - 1.4.21-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Mon Dec 01 2014 Jiri Popelka - 1.4.21-14 +- add dhcpv6-client to /etc/sysconfig/ip6tables (RHBZ#1169036) + +* Mon Nov 03 2014 Jiri Popelka - 1.4.21-13 +- iptables.init: use /run/lock/subsys/ instead of /var/lock/subsys/ (RHBZ#1159573) + +* Mon Sep 29 2014 Jiri Popelka - 1.4.21-12 +- ip[6]tables.init: change shebang from /bin/sh to /bin/bash (RHBZ#1147272) + +* Sat Aug 16 2014 Fedora Release Engineering - 1.4.21-11 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jul 12 2014 Tom Callaway - 1.4.21-10 +- fix license handling + +* Sat Jun 07 2014 Fedora Release Engineering - 1.4.21-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Wed Mar 12 2014 Jiri Popelka - 1.4.21-8 +- add missing reload and panic actions +- BuildRequires: pkgconfig(x) instead of x-devel +- no need to specify file mode bits twice (in %%install and %%files) + +* Sun Jan 19 2014 Ville Skyttä - 1.4.21-7 +- Don't order services after syslog.target. + +* Wed Jan 15 2014 Thomas Woerner 1.4.21-6 +- Enable connlabel support again, needs libnetfilter_conntrack + +* Wed Jan 15 2014 Thomas Woerner 1.4.21-6 +- fixed update from RHEL-6 to RHEL-7 (RHBZ#1043901) + +* Tue Jan 14 2014 Jiri Popelka - 1.4.21-5 +- chmod /etc/sysconfig/ip[6]tables 755 -> 600 + +* Fri Jan 10 2014 Jiri Popelka - 1.4.21-4 +- drop virtual provide for xtables.so.9 +- add default /etc/sysconfig/ip[6]tables (RHBZ#1034494) + +* Thu Jan 09 2014 Jiri Popelka - 1.4.21-3 +- no need to support the pre-systemd things +- use systemd macros (#850166) +- remove scriptlets for migrating to a systemd unit from a SysV initscripts +- ./configure -> %%configure +- spec clean up +- fix self-obsoletion + +* Thu Jan 9 2014 Thomas Woerner 1.4.21-2 +- fixed system hang at shutdown if root device is network based (RHBZ#1007934) + Thanks to Rodrigo A B Freire for the patch + +* Thu Jan 9 2014 Thomas Woerner 1.4.21-1 +- no connlabel.conf upstream anymore +- new version 1.4.21 + - doc: clarify DEBUG usage macro + - iptables: use autoconf to process .in man pages + - extensions: libipt_ULOG: man page should mention NFLOG as replacement + - extensions: libxt_connlabel: use libnetfilter_conntrack + - Introduce a new revision for the set match with the counters support + - libxt_CT: Add the "NOTRACK" alias + - libip6t_mh: Correct command to list named mh types in manpage + - extensions: libxt_DNAT, libxt_REDIRECT, libxt_NETMAP, libxt_SNAT, libxt_MASQUERADE, libxt_LOG: rename IPv4 manpage and tell about IPv6 support + - extensions: libxt_LED: fix parsing of delay + - ip{6}tables-restore: fix breakage due to new locking approach + - libxt_recent: restore minimum value for --seconds + - iptables-xml: fix parameter parsing (similar to 2165f38) + - extensions: add copyright statements + - xtables: improve get_modprobe handling + - ip[6]tables: Add locking to prevent concurrent instances + - iptables: Fix connlabel.conf install location + - ip6tables: don't print out /128 + - libip6t_LOG: target output is different to libipt_LOG + - build: additional include path required after UAPI changes + - iptables: iptables-xml: Fix various parsing bugs + - libxt_recent: restore reap functionality to recent module + - build: fail in configure on missing dependency with --enable-bpf-compiler + - extensions: libxt_NFQUEUE: add --queue-cpu-fanout parameter + - extensions: libxt_set, libxt_SET: check the set family too + - ip6tables: Use consistent exit code for EAGAIN + - iptables: libxt_hashlimit.man: correct address + - iptables: libxt_conntrack.man extraneous commas + - iptables: libip(6)t_REJECT.man default icmp types + - iptables: iptables-xm1.1 correct man section + - iptables: libxt_recent.{c,man} dead URL + - iptables: libxt_string.man add examples + - extensions: libxt_LOG: use generic syslog reference in manpage + - iptables: extensions/GNUMakefile.in use CPPFLAGS + - iptables: correctly reference generated file + - ip[6]tables: fix incorrect alignment in commands_v_options + - build: add software version to manpage first line at configure stage + - extensions: libxt_cluster: add note on arptables-jf + - utils: nfsynproxy: fix error while compiling the BPF filter + - extensions: add SYNPROXY extension + - utils: add nfsynproxy tool + - iptables: state match incompatibilty across versions + - libxtables: xtables_ipmask_to_numeric incorrect with non-CIDR masks + - iptables: improve chain name validation + - iptables: spurious error in load_extension + - xtables: trivial spelling fix + +* Sun Dec 22 2013 Ville Skyttä - 1.4.19.1-2 +- Drop INSTALL from docs, escape macros in %%changelog. + +* Wed Jul 31 2013 Thomas Woerner 1.4.19.1-1 +- new version 1.4.19.1 + - libxt_NFQUEUE: fix bypass option documentation + - extensions: add connlabel match + - extensions: add connlabel match + - ip[6]tables: show --protocol instead of --proto in usage + - libxt_recent: Fix missing space in manpage for --mask option + - extensions: libxt_multiport: Update manpage to list valid protocols + - utils: nfnl_osf: use the right nfnetlink lib + - libip6t_NETMAP: Use xtables_ip6mask_to_cidr and get rid of libip6tc dependency + - Revert "build: resolve link failure for ip6t_NETMAP" + - libxt_osf: fix missing --ttl and --log in save output + - libxt_osf: fix bad location for location in --genre + - libip6t_SNPT: add manpage + - libip6t_DNPT: add manpage + - utils: updates .gitignore to include nfbpf_compile + - extensions: libxt_bpf: clarify --bytecode argument + - libxtables: fix parsing of dotted network mask format + - build: bump version to 1.4.19 + - libxt_conntrack: fix state match alias state parsing + - extensions: add libxt_bpf extension + - utils: nfbpf_compile + - doc: mention SNAT in INPUT chain since kernel 2.6.36 +- fixed changelog date weekdays where needed + +* Mon Mar 4 2013 Thomas Woerner 1.4.18-1 +- new version 1.4.18 + - lots of documentation changes + - Introduce match/target aliases + - Add the "state" alias to the "conntrack" match + - iptables: remove unused leftover definitions + - libxtables: add xtables_rule_matches_free + - libxtables: add xtables_print_num + - extensions: libip6t_DNPT: fix wording in DNPT target + - extension: libip6t_DNAT: allow port DNAT without address + - extensions: libip6t_DNAT: set IPv6 DNAT --to-destination + - extensions: S/DNPT: add missing save function +- changes of 1.4.17: + - libxt_time: add support to ignore day transition + - Convert the NAT targets to use the kernel supplied nf_nat.h header + - extensions: add IPv6 MASQUERADE extension + - extensions: add IPv6 SNAT extension + - extensions: add IPv6 DNAT target + - extensions: add IPv6 REDIRECT extension + - extensions: add IPv6 NETMAP extension + - extensions: add NPT extension + - extensions: libxt_statistic: Fix save output + +* Thu Feb 14 2013 Fedora Release Engineering - 1.4.16.2-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Jan 16 2013 Ville Skyttä - 1.4.16.2-6 +- Own unowned -services libexec dirs (#894464, Michael Scherer). +- Fix -services unit file permissions (#732936, Michal Schmidt). + +* Thu Nov 8 2012 Thomas Woerner 1.4.16.2-5 +- fixed path of ip6tables.init in ip6tables.service + +* Fri Nov 2 2012 Thomas Woerner 1.4.16.2-4 +- fixed missing services for update of pre F-18 installations (rhbz#867960) + - provide and obsolete old main package in services sub package + - provide and obsolete old ipv6 sub package (pre F-17) in services sub package + +* Sun Oct 14 2012 Dan Horák 1.4.16.2-3 +- fix the compat provides for all 64-bit arches + +* Fri Oct 12 2012 Thomas Woerner 1.4.16.2-2 +- new sub package services providing the systemd services (RHBZ#862922) +- new sub package utils: provides nfnl_osf and the pf.os database +- using %%{_libexecdir}/iptables as script path for the original init scripts +- added service iptables save funcitonality using the new way provided by + initscripts 9.37.1 (RHBZ#748134) +- added virtual provide for libxtables.so.7 + +* Mon Oct 8 2012 Thomas Woerner 1.4.16.2-1 +- new version 1.4.16.2 + - build: support for automake-1.12 + - build: separate AC variable replacements from xtables.h + - build: have `make clean` remove dep files too + - doc: grammatical updates to libxt_SET + - doc: clean up interpunction in state list for xt_conntrack + - doc: deduplicate extension descriptions into a new manpage + - doc: trim "state" manpage and reference conntrack instead + - doc: have NOTRACK manpage point to CT instead + - doc: mention iptables-apply in the SEE ALSO sections + - extensions: libxt_addrtype: fix type in help message + - include: add missing linux/netfilter_ipv4/ip_queue.h + - iptables: fix wrong error messages + - iptables: support for match aliases + - iptables: support for target aliases + - iptables-restore: warn about -t in rule lines + - ip[6]tables-restore: cleanup to reduce one level of indentation + - libip6t_frag: match any frag id by default + - libxtables: consolidate preference logic + - libxt_devgroup: consolidate devgroup specification parsing + - libxt_devgroup: guard against negative numbers + - libxt_LED: guard against negative numbers + - libxt_NOTRACK: replace as an alias to CT --notrack + - libxt_state: replace as an alias to xt_conntrack + - libxt_tcp: print space before, not after "flags:" + - libxt_u32: do bounds checking for @'s operands + - libxt_*limit: avoid division by zero + - Merge branch 'master' of git://git.inai.de/iptables + - Merge remote-tracking branch 'nf/stable' + - New set match revision with --return-nomatch flag support +- dropped fixrestore patch, upstream + +* Wed Aug 1 2012 Thomas Woerner 1.4.15-1 +- new version 1.4.15 + - extensions: add HMARK target + - iptables-restore: fix parameter parsing (shows up with gcc-4.7) + - iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7) + - libxtables: add xtables_ip[6]mask_to_cidr + - libxt_devgroup: add man page snippet + - libxt_hashlimit: add support for byte-based operation + - libxt_recent: add --mask netmask + - libxt_recent: remove unused variable + - libxt_HMARK: correct a number of errors introduced by Pablo's rework + - libxt_HMARK: fix ct case example + - libxt_HMARK: fix output of iptables -L + - Revert "iptables-restore: move code to add_param_to_argv, cleanup (fix gcc-4.7)" + +* Wed Jul 18 2012 Thomas Woerner 1.4.14-3 +- added fixrestore patch submitted to upstream by fryasu (nfbz#774) + (RHBZ#825796) + +* Wed Jul 18 2012 Thomas Woerner 1.4.14-2 +- disabled libipq, removed upstream, not provided by kernel anymore + +* Wed Jul 18 2012 Thomas Woerner 1.4.14-1 +- new version 1.4.14 + - extensions: add IPv6 capable ECN match extension + - extensions: add nfacct match + - extensions: add rpfilter module + - extensions: libxt_rateest: output all options in save hook + - iptables: missing free() in function cache_add_entry() + - iptables: missing free() in function delete_entry() + - libiptc: fix retry path in TC_INIT + - libiptc: Returns the position the entry was inserted + - libipt_ULOG: fix --ulog-cprange + - libxt_CT: add --timeout option + - ip(6)tables-restore: make sure argv is NULL terminated + - Revert "libiptc: Returns the position the entry was inserted" + - src: mark newly opened fds as FD_CLOEXEC (close on exec) + - tests: add rateest match rules +- dropped patch5 (cloexec), merged upstream + +* Mon Apr 23 2012 Thomas Woerner 1.4.12.2-5 +- reenable iptables default services + +* Wed Feb 29 2012 Harald Hoyer 1.4.12.2-4 +- install everything in /usr + https://fedoraproject.org/wiki/Features/UsrMove + +* Thu Feb 16 2012 Thomas Woerner 1.4.12.2-3 +- fixed auto enable check for Fedora > 16 and added rhel > 6 check + +* Wed Feb 15 2012 Thomas Woerner 1.4.12.2-2 +- disabled autostart and auto enable for iptables.service and ip6tables.service + for Fedora > 16 + +* Mon Jan 16 2012 Thomas Woerner 1.4.12.2-1 +- new version 1.4.12.2 with new pkgconfig/libip4tc.pc and pkgconfig/libip6tc.pc + - build: make check stage not fail when building statically + - build: restore build order of modules + - build: scan for unreferenced symbols + - build: sort file list before build + - doc: clarification on the meaning of -p 0 + - doc: document iptables-restore's -T option + - doc: fix undesired newline in ip6tables-restore(8) + - ip6tables-restore: implement missing -T option + - iptables: move kernel version find routing into libxtables + - libiptc: provide separate pkgconfig files + - libipt_SAME: set PROTO_RANDOM on all ranges + - libxtables: Fix file descriptor leak in xtables_lmap_init on error + - libxt_connbytes: fix handling of --connbytes FROM + - libxt_CONNSECMARK: fix spacing in output + - libxt_conntrack: improve error message on parsing violation + - libxt_NFQUEUE: fix --queue-bypass ipt-save output + - libxt_RATEEST: link with -lm + - libxt_statistic: link with -lm + - Merge branch 'stable' + - Merge branch 'stable' of git://dev.medozas.de/iptables + - nfnl_osf: add missing libnfnetlink_CFLAGS to compile process + - xtoptions: fill in fallback value for nvals + - xtoptions: simplify xtables_parse_interface + +* Fri Jan 13 2012 Fedora Release Engineering - 1.4.12.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Dec 12 2011 Thomas Woerner 1.4.12.1-1 +- new version 1.4.12.1 with new pkgconfig/libipq.pc + - build: abort autogen on subcommand failure + - build: strengthen check for overlong lladdr components + - build: workaround broken linux-headers on RHEL-5 + - doc: clarify libxt_connlimit defaults + - doc: fix typo in libxt_TRACE + - extensions: use multi-target registration + - libip6t_dst: restore setting IP6T_OPTS_LEN flag + - libip6t_frag: restore inversion support + - libip6t_hbh: restore setting IP6T_OPTS_LEN flag + - libipq: add pkgconfig file + - libipt_ttl: document that negation is available + - libxt_conntrack: fix --ctproto 0 output + - libxt_conntrack: remove one misleading comment + - libxt_dccp: fix deprecated intrapositional ordering of ! + - libxt_dccp: fix random output of ! on --dccp-option + - libxt_dccp: provide man pages options in short help too + - libxt_dccp: restore missing XTOPT_INVERT tags for options + - libxt_dccp: spell out option name on save + - libxt_dscp: restore inversion support + - libxt_hashlimit: default htable-expire must be in milliseconds + - libxt_hashlimit: observe new default gc-expire time when saving + - libxt_hashlimit: remove inversion from hashlimit rev 0 + - libxt_owner: restore inversion support + - libxt_physdev: restore inversion support + - libxt_policy: remove superfluous inversion + - libxt_set: put differing variable names in directly + - libxt_set: update man page about kernel support on the feature + - libxt_string: define _GNU_SOURCE for strnlen + - libxt_string: escape the escaping char too + - libxt_string: fix space around arguments + - libxt_string: replace hex codes by char equivalents + - libxt_string: simplify hex output routine + - libxt_tcp: always print the mask parts + - libxt_TCPMSS: restore build with IPv6-less libcs + - libxt_TOS: update linux kernel version list for backported fix + - libxt_u32: fix missing allowance for inversion + - src: remove unused IPTABLES_MULTI define + - tests: add negation tests for libxt_statistic + - xtoptions: flag use of XTOPT_POINTER without XTOPT_PUT +- removed include/linux/types.h before build to be able to compile + +* Tue Jul 26 2011 Thomas Woerner 1.4.12-2 +- dropped temporary provide again + +* Tue Jul 26 2011 Thomas Woerner 1.4.12-1.1 +- added temporary provides for libxtables.so.6 to be able to rebuild iproute, + which is part of the standard build environment + +* Mon Jul 25 2011 Thomas Woerner 1.4.12-1 +- new version 1.4.12 with support of all new features of kernel 3.0 + - build: attempt to fix building under Linux 2.4 + - build: bump soversion for recent data structure change + - build: install modules in arch-dependent location + - doc: fix group range in libxt_NFLOG's man + - doc: fix version string in ip6tables.8 + - doc: include matches/targets in manpage again + - doc: mention multiple verbosity flags + - doc: the -m option cannot be inverted + - extensions: support for per-extension instance global variable space + - iptables-apply: select default rule file depending on call name + - iptables: consolidate target/match init call + - iptables: Coverity: DEADCODE + - iptables: Coverity: NEGATIVE_RETURNS + - iptables: Coverity: RESOURCE_LEAK + - iptables: Coverity: REVERSE_INULL + - iptables: Coverity: VARARGS + - iptables: restore negation for -f + - libip6t_HL: fix option names from ttl -> hl + - libipt_LOG: fix ignoring all but last flags + - libxtables: ignore whitespace in the multiaddress argument parser + - libxtables: properly reject empty hostnames + - libxtables: set clone's initial data to NULL + - libxt_conntrack: move more data into the xt_option_entry + - libxt_conntrack: restore network-byte order for v1,v2 + - libxt_hashlimit: use a more obvious expiry value by default + - libxt_rateest: abolish global variables + - libxt_RATEEST: abolish global variables + - libxt_RATEEST: fix userspacesize field + - libxt_RATEEST: use guided option parser + - libxt_state: fix regression about inversion of main option + - option: remove last traces of intrapositional negation +- complete changelog: + http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.12.txt + +* Thu Jul 21 2011 Thomas Woerner 1.4.11.1-4 +- merged ipv6 sub package into main package +- renamed init scripts to /usr/libexec/ip*tables.init + +* Fri Jul 15 2011 Thomas Woerner 1.4.11.1-3 +- added support for native systemd file (rhbz#694738) + - new iptables.service file + - additional requires + - moved sysv init scripts to /usr/libexec + - added new post, preun and postun scripts and triggers + +* Tue Jul 12 2011 Thomas Woerner 1.4.11.1-2 +- dropped temporary provide again +- enabled smp build + +* Tue Jul 12 2011 Thomas Woerner 1.4.11.1-1.1 +- added temporary provides for libxtables.so.5 to be able to rebuild iproute, + which is part of the standard build environment + +* Mon Jul 11 2011 Thomas Woerner 1.4.11.1-1 +- new version 1.4.11.1, bug and doc fix release for 1.4.11 + +* Tue Jun 7 2011 Thomas Woerner 1.4.11-1 +- new version 1.4.11 with all new features of 2.6.37-39 (not usable) + - lots of changes and bugfixes for base and extensions + - complete changelog: + http://www.netfilter.org/projects/iptables/files/changes-iptables-1.4.11.txt + +* Wed Feb 09 2011 Fedora Release Engineering - 1.4.10-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Mon Jan 10 2011 Thomas Woerner 1.4.10-1 +- new version 1.4.10 with all new features of 2.6.36 + - all: consistent syntax use in struct option + - build: fix static linking + - doc: let man(1) autoalign the text in xt_cpu + - doc: remove extra empty line from xt_cpu + - doc: minimal spelling updates to xt_cpu + - doc: consistent use of markup + - extensions: libxt_quota: don't ignore the quota value on deletion + - extensions: REDIRECT: add random help + - extensions: add xt_cpu match + - extensions: add idletimer xt target extension + - extensions: libxt_IDLETIMER: use xtables_param_act when checking options + - extensions: libxt_CHECKSUM extension + - extensions: libipt_LOG/libip6t_LOG: support macdecode option + - extensions: fix compilation of the new CHECKSUM target + - extensions: libxt_ipvs: user-space lib for netfilter matcher xt_ipvs + - iptables-xml: resolve compiler warnings + - iptables: limit chain name length to be consistent with targets + - libiptc: add Libs.private to pkgconfig files + - libiptc: build with -Wl,--no-as-needed + - xtables: remove unnecessary cast +- dropped xt_CHECKSUM, added upstream + +* Tue Oct 12 2010 Thomas Woerner 1.4.9-2 +- added xt_CHECKSUM patch from Michael S. Tsirkin (rhbz#612587) + +* Wed Aug 4 2010 Thomas Woerner 1.4.9-1 +- new version 1.4.9 with all new features of 2.6.35 + - doc: xt_hashlimit: fix a typo + - doc: xt_LED: nroff formatting requirements + - doc: xt_string: correct copy-and-pasting in manpage + - extensions: add the LED target + - extensions: libxt_quota.c: Support option negation + - extensions: libxt_rateest: fix bps options for iptables-save + - extensions: libxt_rateest: fix typo in the man page + - extensions: REDIRECT: add random help + - includes: sync header files from Linux 2.6.35-rc1 + - libxt_conntrack: do print netmask + - libxt_hashlimit: always print burst value + - libxt_set: new revision added + - utils: add missing include flags to Makefile + - xtables: another try at chain name length checking + - xtables: remove xtables_set_revision function + - xt_quota: also document negation + - xt_sctp: Trace DATA chunk that supports SACK-IMMEDIATELY extension + - xt_sctp: support FORWARD_TSN chunk type + +* Fri Jul 2 2010 Thomas Woerner 1.4.8-1 +- new version 1.4.8 all new features of 2.6.34 (rhbz#) + - extensions: REDIRECT: fix --to-ports parser + - iptables: add noreturn attribute to exit_tryhelp() + - extensions: MASQUERADE: fix --to-ports parser + - libxt_comment: avoid use of IPv4-specific examples + - libxt_CT: add a manpage + - iptables: correctly check for too-long chain/target/match names + - doc: libxt_MARK: no longer restricted to mangle table + - doc: remove claim that TCPMSS is limited to mangle + - libxt_recent: add a missing space in output + - doc: add manpage for libxt_osf + - libxt_osf: import nfnl_osf program + - extensions: add support for xt_TEE + - CT: fix --ctevents parsing + - extensions: add CT extension + - libxt_CT: print conntrack zone in ->print/->save + - xtables: fix compilation when debugging is enabled + - libxt_conntrack: document --ctstate UNTRACKED + - iprange: fix xt_iprange v0 parsing + +* Wed Mar 24 2010 Thomas Woerner 1.4.7-2 +- added default values for IPTABLES_STATUS_VERBOSE and + IPTABLES_STATUS_LINENUMBERS in init script +- added missing lsb keywords Required-Start and Required-Stop to init script + +* Fri Mar 5 2010 Thomas Woerner 1.4.7-1 +- new version 1.4.7 with support for all new features of 2.6.33 (rhbz#570767) + - libip4tc: Add static qualifier to dump_entry() + - libipq: build as shared library + - recent: reorder cases in code (cosmetic cleanup) + - several man page and documentation fixes + - policy: fix error message showing wrong option + - includes: header updates + - Lift restrictions on interface names +- fixed license and moved iptables-xml into base package according to review + +* Wed Jan 27 2010 Thomas Woerner 1.4.6-2 +- moved libip*tc and libxtables libs to /lib[64], added symlinks for .so libs + to /usr/lib[64] for compatibility (rhbz#558796) + +* Wed Jan 13 2010 Thomas Woerner 1.4.6-1 +- new version 1.4.6 with support for all new features of 2.6.32 + - several man page fixes + - Support for nommu arches + - realm: remove static initializations + - libiptc: remove unused functions + - libiptc: avoid strict-aliasing warnings + - iprange: do accept non-ranges for xt_iprange v1 + - iprange: warn on reverse range + - iprange: roll address parsing into a loop + - iprange: do accept non-ranges for xt_iprange v1 (log) + - iprange: warn on reverse range (log) + - libiptc: fix wrong maptype of base chain counters on restore + - iptables: fix undersized deletion mask creation + - style: reduce indent in xtables_check_inverse + - libxtables: hand argv to xtables_check_inverse + - iptables/extensions: make bundled options work again + - CONNMARK: print mark rules with mask 0xffffffff as set instead of xset + - iptables: take masks into consideration for replace command + - doc: explain experienced --hitcount limit + - doc: name resolution clarification + - iptables: expose option to zero packet/byte counters for a specific rule + - build: restore --disable-ipv6 functionality on system w/o v6 headers + - MARK: print mark rules with mask 0xffffffff as --set-mark instead of --set-xmark + - DNAT: fix incorrect check during parsing + - extensions: add osf extension + - conntrack: fix --expires parsing + +* Thu Dec 17 2009 Thomas Woerner 1.4.5-2 +- dropped nf_ext_init remains from cloexec patch + +* Thu Sep 17 2009 Thomas Woerner 1.4.5-1 +- new version 1.4.5 with support for all new features of 2.6.31 + - libxt_NFQUEUE: add new v1 version with queue-balance option + - xt_conntrack: revision 2 for enlarged state_mask member + - libxt_helper: fix invalid passed option to check_inverse + - libiptc: split v4 and v6 + - extensions: collapse registration structures + - iptables: allow for parse-less extensions + - iptables: allow for help-less extensions + - extensions: remove empty help and parse functions + - xtables: add multi-registration functions + - extensions: collapse data variables to use multi-reg calls + - xtables: warn of missing version identifier in extensions + - multi binary: allow subcommand via argv[1] + - iptables: accept multiple IP address specifications for -s, -d + - several build fixes + - several man page fixes +- fixed two leaked file descriptors on sockets (rhbz#521397) + +* Mon Aug 24 2009 Thomas Woerner 1.4.4-1 +- new version 1.4.4 with support for all new features of 2.6.30 + - several man page fixes + - iptables: replace open-coded sizeof by ARRAY_SIZE + - libip6t_policy: remove redundant functions + - policy: use direct xt_policy_info instead of ipt/ip6t + - policy: merge ipv6 and ipv4 variant + - extensions: add `cluster' match support + - extensions: add const qualifiers in print/save functions + - extensions: use NFPROTO_UNSPEC for .family field + - extensions: remove redundant casts + - iptables: close open file descriptors + - fix segfault if incorrect protocol name is used + - replace open-coded sizeof by ARRAY_SIZE + - do not include v4-only modules in ip6tables manpage + - use direct xt_policy_info instead of ipt/ip6t + - xtables: fix segfault if incorrect protocol name is used + - libxt_connlimit: initialize v6_mask + - SNAT/DNAT: add support for persistent multi-range NAT mappings + +* Fri Jul 24 2009 Fedora Release Engineering - 1.4.3.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed Apr 15 2009 Thomas Woerner 1.4.3.2-1 +- new version 1.4.3.2 +- also install iptables/internal.h, needed for iptables.h and ip6tables.h + +* Mon Mar 30 2009 Thomas Woerner 1.4.3.1-1 +- new version 1.4.3.1 + - libiptc is now shared + - supports all new features of the 2.6.29 kernel +- dropped typo_latter patch + +* Thu Mar 5 2009 Thomas Woerner 1.4.2-3 +- still more review fixes (rhbz#225906) + - consistent macro usage + - use sed instead of perl for rpath removal + - use standard RPM CFLAGS, but also -fno-strict-aliasing (needed for libiptc*) + +* Wed Feb 25 2009 Fedora Release Engineering - 1.4.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Feb 20 2009 Thomas Woerner 1.4.2-1 +- new version 1.4.2 +- removed TOS value mask patch (upstream) +- more review fixes (rhbz#225906) +- install all header files (rhbz#462207) +- dropped nf_ext_init (rhbz#472548) + +* Tue Jul 22 2008 Thomas Woerner 1.4.1.1-2 +- fixed TOS value mask problem (rhbz#456244) (upstream patch) +- two more cloexec fixes + +* Tue Jul 1 2008 Thomas Woerner 1.4.1.1-1 +- upstream bug fix release 1.4.1.1 +- dropped extra patch for 1.4.1 - not needed anymore + +* Tue Jun 10 2008 Thomas Woerner 1.4.1-1 +- new version 1.4.1 with new build environment +- additional ipv6 network mask patch from Jan Engelhardt +- spec file cleanup +- removed old patches + +* Fri Jun 6 2008 Tom "spot" Callaway 1.4.0-5 +- use normal kernel headers, not linux/compiler.h +- change BuildRequires: kernel-devel to kernel-headers +- We need to do this to be able to build for both sparcv9 and sparc64 + (there is no kernel-devel.sparcv9) + +* Thu Mar 20 2008 Thomas Woerner 1.4.0-4 +- use O_CLOEXEC for all opened files in all applications (rhbz#438189) + +* Mon Mar 3 2008 Thomas Woerner 1.4.0-3 +- use the kernel headers from the build tree for iptables for now to be able to + compile this package, but this makes the package more kernel dependant +- use s6_addr32 instead of in6_u.u6_addr32 + +* Wed Feb 20 2008 Fedora Release Engineering - 1.4.0-2 +- Autorebuild for GCC 4.3 + +* Mon Feb 11 2008 Thomas Woerner 1.4.0-1 +- new version 1.4.0 +- fixed condrestart (rhbz#428148) +- report the module in rmmod_r if there is an error +- use nf_ext_init instead of my_init for extension constructors + +* Mon Nov 5 2007 Thomas Woerner 1.3.8-6 +- fixed leaked file descriptor before fork/exec (rhbz#312191) +- blacklisting is not working, use "install X /bin/(true|false)" test instead +- return private exit code 150 for disabled ipv6 support +- use script name for output messages + +* Tue Oct 16 2007 Thomas Woerner 1.3.8-5 +- fixed error code for stopping a already stopped firewall (rhbz#321751) +- moved blacklist test into start + +* Wed Sep 26 2007 Thomas Woerner 1.3.8-4.1 +- do not start ip6tables if ipv6 is blacklisted (rhbz#236888) +- use simpler fix for (rhbz#295611) + Thanks to Linus Torvalds for the patch. + +* Mon Sep 24 2007 Thomas Woerner 1.3.8-4 +- fixed IPv6 reject type (rhbz#295181) +- fixed init script: start, stop and status +- support netfilter compiled into kernel in init script (rhbz#295611) +- dropped inversion for limit modules from man pages (rhbz#220780) +- fixed typo in ip6tables man page (rhbz#236185) + +* Wed Sep 19 2007 Thomas Woerner 1.3.8-3 +- do not depend on local_fs in lsb header - this delayes start after network +- fixed exit code for initscript usage + +* Mon Sep 17 2007 Thomas Woerner 1.3.8-2.1 +- do not use lock file for condrestart test + +* Thu Aug 23 2007 Thomas Woerner 1.3.8-2 +- fixed initscript for LSB conformance (rhbz#246953, rhbz#242459) +- provide iptc interface again, but unsupported (rhbz#216733) +- compile all extension, which are supported by the kernel-headers package +- review fixes (rhbz#225906) + +* Tue Jul 31 2007 Thomas Woerner +- reverted ipv6 fix, because it disables the ipv6 at all (rhbz#236888) + +* Fri Jul 13 2007 Steve Conklin - 1.3.8-1 +- New version 1.3.8 + +* Mon Apr 23 2007 Jeremy Katz - 1.3.7-2 +- fix error when ipv6 support isn't loaded in the kernel (#236888) + +* Wed Jan 10 2007 Thomas Woerner 1.3.7-1.1 +- fixed installation of secmark modules + +* Tue Jan 9 2007 Thomas Woerner 1.3.7-1 +- new verison 1.3.7 +- iptc is not a public interface and therefore not installed anymore +- dropped upstream secmark patch + +* Tue Sep 19 2006 Thomas Woerner 1.3.5-2 +- added secmark iptables patches (#201573) + +* Wed Jul 12 2006 Jesse Keating - 1.3.5-1.2.1 +- rebuild + +* Fri Feb 10 2006 Jesse Keating - 1.3.5-1.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 1.3.5-1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Thu Feb 2 2006 Thomas Woerner 1.3.5-1 +- new version 1.3.5 +- fixed init script to set policy for raw tables, too (#179094) + +* Tue Jan 24 2006 Thomas Woerner 1.3.4-3 +- added important iptables header files to devel package + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Fri Nov 25 2005 Thomas Woerner 1.3.4-2 +- fix for plugin problem: link with "gcc -shared" instead of "ld -shared" and + replace "_init" with "__attribute((constructor)) my_init" + +* Fri Nov 25 2005 Thomas Woerner 1.3.4-1.1 +- rebuild due to unresolved symbols in shared libraries + +* Fri Nov 18 2005 Thomas Woerner 1.3.4-1 +- new version 1.3.4 +- dropped free_opts patch (upstream fixed) +- made libipq PIC (#158623) +- additional configuration options for iptables startup script (#172929) + Thanks to Jan Gruenwald for the patch +- spec file cleanup (dropped linux_header define and usage) + +* Mon Jul 18 2005 Thomas Woerner 1.3.2-1 +- new version 1.3.2 with additional patch for the misplaced free_opts call + from Marcus Sundberg + +* Wed May 11 2005 Thomas Woerner 1.3.1-1 +- new version 1.3.1 + +* Fri Mar 18 2005 Thomas Woerner 1.3.0-2 +- Remove unnecessary explicit kernel dep (#146142) +- Fixed out of bounds accesses (#131848): Thanks to Steve Grubb + for the patch +- Adapted iptables-config to reference to modprobe.conf (#150143) +- Remove misleading message (#140154): Thanks to Ulrich Drepper + for the patch + +* Mon Feb 21 2005 Thomas Woerner 1.3.0-1 +- new version 1.3.0 + +* Thu Nov 11 2004 Thomas Woerner 1.2.11-3.2 +- fixed autoload problem in iptables and ip6tables (CAN-2004-0986) + +* Fri Sep 17 2004 Thomas Woerner 1.2.11-3.1 +- changed default behaviour for IPTABLES_STATUS_NUMERIC to "yes" (#129731) +- modified config file to match this change and un-commented variables with + default values + +* Thu Sep 16 2004 Thomas Woerner 1.2.11-3 +- applied second part of cleanup patch from (#131848): thanks to Steve Grubb + for the patch + +* Wed Aug 25 2004 Thomas Woerner 1.2.11-2 +- fixed free bug in iptables (#128322) + +* Tue Jun 22 2004 Thomas Woerner 1.2.11-1 +- new version 1.2.11 + +* Thu Jun 17 2004 Thomas Woerner 1.2.10-1 +- new version 1.2.10 + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Thu Feb 26 2004 Thomas Woerner 1.2.9-2.3 +- fixed iptables-restore -c fault if there are no counters (#116421) + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Sun Jan 25 2004 Dan Walsh 1.2.9-1.2 +- Close File descriptors to prevent SELinux error message + +* Wed Jan 7 2004 Thomas Woerner 1.2.9-1.1 +- rebuild + +* Wed Dec 17 2003 Thomas Woerner 1.2.9-1 +- vew version 1.2.9 +- new config options in ipXtables-config: + IPTABLES_MODULES_UNLOAD +- more documentation in ipXtables-config +- fix for netlink security issue in libipq (devel package) +- print fix for libipt_icmp (#109546) + +* Thu Oct 23 2003 Thomas Woerner 1.2.8-13 +- marked all messages in iptables init script for translation (#107462) +- enabled devel package (#105884, #106101) +- bumped build for fedora for libipt_recent.so (#106002) + +* Tue Sep 23 2003 Thomas Woerner 1.2.8-12.1 +- fixed lost udp port range in ip6tables-save (#104484) +- fixed non numeric multiport port output in ipXtables-savs + +* Mon Sep 22 2003 Florian La Roche 1.2.8-11 +- do not link against -lnsl + +* Wed Sep 17 2003 Thomas Woerner 1.2.8-10 +- made variables in rmmod_r local + +* Tue Jul 22 2003 Thomas Woerner 1.2.8-9 +- fixed permission for init script + +* Sat Jul 19 2003 Thomas Woerner 1.2.8-8 +- fixed save when iptables file is missing and iptables-config permissions + +* Tue Jul 8 2003 Thomas Woerner 1.2.8-7 +- fixes for ip6tables: module unloading, setting policy only for existing + tables + +* Thu Jul 3 2003 Thomas Woerner 1.2.8-6 +- IPTABLES_SAVE_COUNTER defaults to no, now +- install config file in /etc/sysconfig +- exchange unload of ip_tables and ip_conntrack +- fixed start function + +* Wed Jul 2 2003 Thomas Woerner 1.2.8-5 +- new config option IPTABLES_SAVE_ON_RESTART +- init script: new status, save and restart +- fixes #44905, #65389, #80785, #82860, #91040, #91560 and #91374 + +* Mon Jun 30 2003 Thomas Woerner 1.2.8-4 +- new config option IPTABLES_STATUS_NUMERIC +- cleared IPTABLES_MODULES in iptables-config + +* Mon Jun 30 2003 Thomas Woerner 1.2.8-3 +- new init scripts + +* Sat Jun 28 2003 Florian La Roche +- remove check for very old kernel versions in init scripts +- sync up both init scripts and remove some further ugly things +- add some docu into rpm + +* Thu Jun 26 2003 Thomas Woerner 1.2.8-2 +- rebuild + +* Mon Jun 16 2003 Thomas Woerner 1.2.8-1 +- update to 1.2.8 + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Mon Jan 13 2003 Bill Nottingham 1.2.7a-1 +- update to 1.2.7a +- add a plethora of bugfixes courtesy Michael Schwendt + +* Fri Dec 13 2002 Elliot Lee 1.2.6a-3 +- Fix multilib + +* Wed Aug 07 2002 Karsten Hopp +- fixed iptables and ip6tables initscript output, based on #70511 +- check return status of all iptables calls, not just the last one + in a 'for' loop. + +* Mon Jul 29 2002 Bernhard Rosenkraenzer 1.2.6a-1 +- 1.2.6a (bugfix release, #69747) + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Mon Mar 4 2002 Bernhard Rosenkraenzer 1.2.5-3 +- Add some fixes from CVS, fixing bug #60465 + +* Tue Feb 12 2002 Bernhard Rosenkraenzer 1.2.5-2 +- Merge ip6tables improvements from Ian Prowell + #59402 +- Update URL (#59354) +- Use /sbin/chkconfig rather than chkconfig in %%postun script + +* Fri Jan 11 2002 Bernhard Rosenkraenzer 1.2.5-1 +- 1.2.5 + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Mon Nov 5 2001 Bernhard Rosenkraenzer 1.2.4-2 +- Fix %%preun script + +* Tue Oct 30 2001 Bernhard Rosenkraenzer 1.2.4-1 +- Update to 1.2.4 (various fixes, including security fixes; among others: + #42990, #50500, #53325, #54280) +- Fix init script (#31133) + +* Mon Sep 3 2001 Bernhard Rosenkraenzer 1.2.3-1 +- 1.2.3 (5 security fixes, some other fixes) +- Fix updating (#53032) + +* Mon Aug 27 2001 Bernhard Rosenkraenzer 1.2.2-4 +- Fix #50990 +- Add some fixes from current CVS; should fix #52620 + +* Mon Jul 16 2001 Bernhard Rosenkraenzer 1.2.2-3 +- Add some fixes from the current CVS tree; fixes #49154 and some IPv6 + issues + +* Tue Jun 26 2001 Bernhard Rosenkraenzer 1.2.2-2 +- Fix iptables-save reject-with (#45632), Patch from Michael Schwendt + + +* Tue May 8 2001 Bernhard Rosenkraenzer 1.2.2-1 +- 1.2.2 + +* Wed Mar 21 2001 Bernhard Rosenkraenzer +- 1.2.1a, fixes #28412, #31136, #31460, #31133 + +* Thu Mar 1 2001 Bernhard Rosenkraenzer +- Yet another initscript fix (#30173) +- Fix the fixes; they fixed some issues but broke more important + stuff :/ (#30176) + +* Tue Feb 27 2001 Bernhard Rosenkraenzer +- Fix up initscript (#27962) +- Add fixes from CVS to iptables-{restore,save}, fixing #28412 + +* Fri Feb 09 2001 Karsten Hopp +- create /etc/sysconfig/iptables mode 600 (same problem as #24245) + +* Mon Feb 05 2001 Karsten Hopp +- fix bugzilla #25986 (initscript not marked as config file) +- fix bugzilla #25962 (iptables-restore) +- mv chkconfig --del from postun to preun + +* Thu Feb 1 2001 Trond Eivind Glomsrød +- Fix check for ipchains + +* Mon Jan 29 2001 Bernhard Rosenkraenzer +- Some fixes to init scripts + +* Wed Jan 24 2001 Bernhard Rosenkraenzer +- Add some fixes from CVS, fixes among other things Bug #24732 + +* Wed Jan 17 2001 Bernhard Rosenkraenzer +- Add missing man pages, fix up init script (Bug #17676) + +* Mon Jan 15 2001 Bill Nottingham +- add init script + +* Mon Jan 15 2001 Bernhard Rosenkraenzer +- 1.2 +- fix up ipv6 split +- add init script +- Move the plugins from /usr/lib/iptables to /lib/iptables. + This needs to work before /usr is mounted... +- Use -O1 on alpha (compiler bug) + +* Sat Jan 6 2001 Bernhard Rosenkraenzer +- 1.1.2 +- Add IPv6 support (in separate package) + +* Thu Aug 17 2000 Bill Nottingham +- build everywhere + +* Tue Jul 25 2000 Bernhard Rosenkraenzer +- 1.1.1 + +* Thu Jul 13 2000 Prospector +- automatic rebuild + +* Tue Jun 27 2000 Preston Brown +- move iptables to /sbin. +- excludearch alpha for now, not building there because of compiler bug(?) + +* Fri Jun 9 2000 Bill Nottingham +- don't obsolete ipchains either +- update to 1.1.0 + +* Sun Jun 4 2000 Bill Nottingham +- remove explicit kernel requirement + +* Tue May 2 2000 Bernhard Rosenkränzer +- initial package