From 1dc35b9e66315dee6f954690d97855f152af6aed Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 05 2019 20:53:47 +0000 Subject: import iptables-1.8.2-16.el8 --- 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/0001-iptables-apply-Use-mktemp-instead-of-tempfile.patch b/SOURCES/0001-iptables-apply-Use-mktemp-instead-of-tempfile.patch deleted file mode 100644 index 3eacce0..0000000 --- a/SOURCES/0001-iptables-apply-Use-mktemp-instead-of-tempfile.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 4ca8d47a364ffa12a0b3ae9ab5096fbe29ae2f4c 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.20.1 - diff --git a/SOURCES/0002-extensions-format-security-fixes-in-libip-6-t_icmp.patch b/SOURCES/0002-extensions-format-security-fixes-in-libip-6-t_icmp.patch deleted file mode 100644 index 3ab5eda..0000000 --- a/SOURCES/0002-extensions-format-security-fixes-in-libip-6-t_icmp.patch +++ /dev/null @@ -1,61 +0,0 @@ -From ea1b67280baebb6b0583b5fe8217f7c37b78dad9 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.20.1 - 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-arptables-nft-use-generic-expression-parsing-functio.patch b/SOURCES/0003-arptables-nft-use-generic-expression-parsing-functio.patch deleted file mode 100644 index 5cc487d..0000000 --- a/SOURCES/0003-arptables-nft-use-generic-expression-parsing-functio.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 8e065f27f51cb46171b3ab1f9d0f4ad8bd8cdf86 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) - -Conflicts: -- Drop changes to extensions/libarpt_standard.t since these test - snippets are not included in tarball. - -Signed-off-by: Phil Sutter ---- - iptables/nft-arp.c | 92 +++++----------------------------------------- - 1 file changed, 10 insertions(+), 82 deletions(-) - -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.20.1 - 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/0004-xtables-Don-t-use-native-nftables-comments.patch b/SOURCES/0004-xtables-Don-t-use-native-nftables-comments.patch deleted file mode 100644 index 22f8f5e..0000000 --- a/SOURCES/0004-xtables-Don-t-use-native-nftables-comments.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 33ec7bf3be4992f7db8049f2459afbcf8df67221 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) - -Conflicts: -- Dropped changes to extensions/libxt_comment.t not present in release - tarball. - -Signed-off-by: Phil Sutter ---- - iptables/nft-ipv4.c | 14 +++----------- - iptables/nft-ipv6.c | 14 +++----------- - iptables/nft.c | 27 --------------------------- - iptables/nft.h | 1 - - 4 files changed, 6 insertions(+), 50 deletions(-) - -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.20.1 - 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/0005-xtables-Introduce-per-table-chain-caches.patch b/SOURCES/0005-xtables-Introduce-per-table-chain-caches.patch deleted file mode 100644 index 96b5069..0000000 --- a/SOURCES/0005-xtables-Introduce-per-table-chain-caches.patch +++ /dev/null @@ -1,592 +0,0 @@ -From 6fb4660bde886f1f1ad5cfc55553b0a6fd98c2ed 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.20.1 - diff --git a/SOURCES/0006-nft-add-type-field-to-builtin_table.patch b/SOURCES/0006-nft-add-type-field-to-builtin_table.patch deleted file mode 100644 index 64d3852..0000000 --- a/SOURCES/0006-nft-add-type-field-to-builtin_table.patch +++ /dev/null @@ -1,99 +0,0 @@ -From c900978466fc50bee651f83eab8fd598b7f88183 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.20.1 - 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/0007-nft-move-chain_cache-back-to-struct-nft_handle.patch b/SOURCES/0007-nft-move-chain_cache-back-to-struct-nft_handle.patch deleted file mode 100644 index 58e96a1..0000000 --- a/SOURCES/0007-nft-move-chain_cache-back-to-struct-nft_handle.patch +++ /dev/null @@ -1,106 +0,0 @@ -From df7d696834080e595f29934f8225c12cecb3f819 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.20.1 - 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/0008-nft-move-initialize-to-struct-nft_handle.patch b/SOURCES/0008-nft-move-initialize-to-struct-nft_handle.patch deleted file mode 100644 index a943173..0000000 --- a/SOURCES/0008-nft-move-initialize-to-struct-nft_handle.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 993eea7a78dd3690cb864b58c7056d5851550f5f 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.20.1 - 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/0009-xtables-constify-struct-builtin_table-and-struct-bui.patch b/SOURCES/0009-xtables-constify-struct-builtin_table-and-struct-bui.patch deleted file mode 100644 index 5f49552..0000000 --- a/SOURCES/0009-xtables-constify-struct-builtin_table-and-struct-bui.patch +++ /dev/null @@ -1,287 +0,0 @@ -From 8ef9a56ea980170e146353bc8d7b91765b801344 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.20.1 - diff --git a/SOURCES/0010-nft-Simplify-nftnl_rule_list_chain_save.patch b/SOURCES/0010-nft-Simplify-nftnl_rule_list_chain_save.patch deleted file mode 100644 index 4e43cc0..0000000 --- a/SOURCES/0010-nft-Simplify-nftnl_rule_list_chain_save.patch +++ /dev/null @@ -1,60 +0,0 @@ -From b54cb3132045f5cac8c09b24e564ef05aff29288 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.20.1 - 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-Review-unclear-return-points.patch b/SOURCES/0011-nft-Review-unclear-return-points.patch deleted file mode 100644 index b415d20..0000000 --- a/SOURCES/0011-nft-Review-unclear-return-points.patch +++ /dev/null @@ -1,43 +0,0 @@ -From f5043360f8a340ea4b924edfe5c3779099671061 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.20.1 - 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/0012-xtables-restore-Review-chain-handling.patch b/SOURCES/0012-xtables-restore-Review-chain-handling.patch deleted file mode 100644 index dab20f9..0000000 --- a/SOURCES/0012-xtables-restore-Review-chain-handling.patch +++ /dev/null @@ -1,172 +0,0 @@ -From 6e1e7be69aa29784a3f891fe7ffbd9b5c534c901 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.20.1 - diff --git a/SOURCES/0013-nft-Review-is_-_compatible-routines.patch b/SOURCES/0013-nft-Review-is_-_compatible-routines.patch deleted file mode 100644 index db210cb..0000000 --- a/SOURCES/0013-nft-Review-is_-_compatible-routines.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 0318e0d123ebecbc98305284832774647d953859 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.20.1 - 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-Reduce-__nft_rule_del-signature.patch b/SOURCES/0014-nft-Reduce-__nft_rule_del-signature.patch deleted file mode 100644 index 6bf043a..0000000 --- a/SOURCES/0014-nft-Reduce-__nft_rule_del-signature.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 882a0b623fe352f1b25a8fc7652dfc9e2083549c 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.20.1 - 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/0015-nft-Reduce-indenting-level-in-flush_chain_cache.patch b/SOURCES/0015-nft-Reduce-indenting-level-in-flush_chain_cache.patch deleted file mode 100644 index 3ee9d68..0000000 --- a/SOURCES/0015-nft-Reduce-indenting-level-in-flush_chain_cache.patch +++ /dev/null @@ -1,60 +0,0 @@ -From f9932edff18a74dc373c708f38fe95b2f8d9a8a5 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.20.1 - 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/0016-nft-Simplify-per-table-chain-cache-update.patch b/SOURCES/0016-nft-Simplify-per-table-chain-cache-update.patch deleted file mode 100644 index e9f0165..0000000 --- a/SOURCES/0016-nft-Simplify-per-table-chain-cache-update.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 64c11057e8002896c74d10b21c64ab5796def01a 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.20.1 - diff --git a/SOURCES/0017-nft-Simplify-nft_rule_insert-a-bit.patch b/SOURCES/0017-nft-Simplify-nft_rule_insert-a-bit.patch deleted file mode 100644 index acc307c..0000000 --- a/SOURCES/0017-nft-Simplify-nft_rule_insert-a-bit.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c10f5977915b1b7ddfb6557f9f6b18cd4140c26b 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.20.1 - 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-Introduce-fetch_chain_cache.patch b/SOURCES/0018-nft-Introduce-fetch_chain_cache.patch deleted file mode 100644 index eac4624..0000000 --- a/SOURCES/0018-nft-Introduce-fetch_chain_cache.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 8fc923734c2a393a377c898b3f4c6db776745838 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.20.1 - 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/0019-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch b/SOURCES/0019-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch deleted file mode 100644 index e34fa1c..0000000 --- a/SOURCES/0019-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 510fef3a3fe67feb3da2fb237784299c7f070d70 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.20.1 - 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/0020-xtables-Implement-per-chain-rule-cache.patch b/SOURCES/0020-xtables-Implement-per-chain-rule-cache.patch deleted file mode 100644 index 499b4bd..0000000 --- a/SOURCES/0020-xtables-Implement-per-chain-rule-cache.patch +++ /dev/null @@ -1,802 +0,0 @@ -From 4c6357a568d3e079fa7246cc2aa1c46739a6a14c 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.20.1 - diff --git a/SOURCES/0021-nft-Drop-nft_chain_list_find.patch b/SOURCES/0021-nft-Drop-nft_chain_list_find.patch deleted file mode 100644 index 534482b..0000000 --- a/SOURCES/0021-nft-Drop-nft_chain_list_find.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 6e0de300158a6f3e8151903952b2a95f4487bedc 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.20.1 - 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/0022-xtables-Optimize-flushing-a-specific-chain.patch b/SOURCES/0022-xtables-Optimize-flushing-a-specific-chain.patch deleted file mode 100644 index c8cac98..0000000 --- a/SOURCES/0022-xtables-Optimize-flushing-a-specific-chain.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 96b7b6eb3c963dc835a3f132f037050d032aaa77 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.20.1 - 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/0023-xtables-Optimize-nft_chain_zero_counters.patch b/SOURCES/0023-xtables-Optimize-nft_chain_zero_counters.patch deleted file mode 100644 index ea36fd0..0000000 --- a/SOURCES/0023-xtables-Optimize-nft_chain_zero_counters.patch +++ /dev/null @@ -1,136 +0,0 @@ -From ecd80647d4b862324943ba8ecb40ae988a7e6376 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.20.1 - diff --git a/SOURCES/0024-tests-Extend-verbose-output-and-return-code-tests.patch b/SOURCES/0024-tests-Extend-verbose-output-and-return-code-tests.patch deleted file mode 100644 index 700a0d9..0000000 --- a/SOURCES/0024-tests-Extend-verbose-output-and-return-code-tests.patch +++ /dev/null @@ -1,79 +0,0 @@ -From cb418353998513b2d1b95fbd3dbcf205c38ec4a0 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.20.1 - 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/0025-xtables-Optimize-user-defined-chain-deletion.patch b/SOURCES/0025-xtables-Optimize-user-defined-chain-deletion.patch deleted file mode 100644 index 768024a..0000000 --- a/SOURCES/0025-xtables-Optimize-user-defined-chain-deletion.patch +++ /dev/null @@ -1,134 +0,0 @@ -From 7b071787e82cbc53a5a33364826d8e0495b84fc0 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.20.1 - diff --git a/SOURCES/0026-xtables-Optimize-list-command-with-given-chain.patch b/SOURCES/0026-xtables-Optimize-list-command-with-given-chain.patch deleted file mode 100644 index 58ccc2b..0000000 --- a/SOURCES/0026-xtables-Optimize-list-command-with-given-chain.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 76b233caab4925277bdbdf99e4ad4516b2d8a280 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.20.1 - 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/0027-xtables-Optimize-list-rules-command-with-given-chain.patch b/SOURCES/0027-xtables-Optimize-list-rules-command-with-given-chain.patch deleted file mode 100644 index ed896f4..0000000 --- a/SOURCES/0027-xtables-Optimize-list-rules-command-with-given-chain.patch +++ /dev/null @@ -1,158 +0,0 @@ -From adf121e392eeb87eb77df65527a4fc8580e9a84d 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.20.1 - diff --git a/SOURCES/0028-nft-Make-use-of-nftnl_rule_lookup_byindex.patch b/SOURCES/0028-nft-Make-use-of-nftnl_rule_lookup_byindex.patch deleted file mode 100644 index 2b08c97..0000000 --- a/SOURCES/0028-nft-Make-use-of-nftnl_rule_lookup_byindex.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 062f97fdd10d0930fecbbf49438ff856ea46ca9e 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.20.1 - 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/0029-nft-Simplify-nft_is_chain_compatible.patch b/SOURCES/0029-nft-Simplify-nft_is_chain_compatible.patch deleted file mode 100644 index 9aaf76c..0000000 --- a/SOURCES/0029-nft-Simplify-nft_is_chain_compatible.patch +++ /dev/null @@ -1,80 +0,0 @@ -From f13c1474a2f70d7d3cb5f3f5be8a4cceebb324a0 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.20.1 - diff --git a/SOURCES/0030-nft-Simplify-flush_chain_cache.patch b/SOURCES/0030-nft-Simplify-flush_chain_cache.patch deleted file mode 100644 index 52e9825..0000000 --- a/SOURCES/0030-nft-Simplify-flush_chain_cache.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 329090e1c375905ec388ac1025b4e9fab883c3ca 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.20.1 - 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/0031-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch b/SOURCES/0031-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch deleted file mode 100644 index fddf849..0000000 --- a/SOURCES/0031-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 63123e24c1b957cfabcfa7708994b0d61447724e 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.20.1 - 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/0032-xtables-Speed-up-chain-deletion-in-large-rulesets.patch b/SOURCES/0032-xtables-Speed-up-chain-deletion-in-large-rulesets.patch deleted file mode 100644 index 08ef8d6..0000000 --- a/SOURCES/0032-xtables-Speed-up-chain-deletion-in-large-rulesets.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 0925419844d77e7216067208f270cd1d8279b523 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.20.1 - diff --git a/SOURCES/0033-arptables-nft-Fix-listing-rules-without-target.patch b/SOURCES/0033-arptables-nft-Fix-listing-rules-without-target.patch deleted file mode 100644 index 1842b5a..0000000 --- a/SOURCES/0033-arptables-nft-Fix-listing-rules-without-target.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 6ae39816fe49ad3210a6a4ff1b997775e688be9a 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.20.1 - 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-MARK-target-parsing-and-printing.patch b/SOURCES/0034-arptables-nft-Fix-MARK-target-parsing-and-printing.patch deleted file mode 100644 index 55dee75..0000000 --- a/SOURCES/0034-arptables-nft-Fix-MARK-target-parsing-and-printing.patch +++ /dev/null @@ -1,155 +0,0 @@ -From c30599e8d9465da351cf2bc96b67574a6b1ae72b 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.20.1 - 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-CLASSIFY-target-printing.patch b/SOURCES/0035-arptables-nft-Fix-CLASSIFY-target-printing.patch deleted file mode 100644 index 1b385af..0000000 --- a/SOURCES/0035-arptables-nft-Fix-CLASSIFY-target-printing.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 474d95f86b51ee68b3dbad144b10caa07f4d519e 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.20.1 - 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/0036-arptables-nft-Remove-space-between-cnt-and-value.patch b/SOURCES/0036-arptables-nft-Remove-space-between-cnt-and-value.patch deleted file mode 100644 index 919ce17..0000000 --- a/SOURCES/0036-arptables-nft-Remove-space-between-cnt-and-value.patch +++ /dev/null @@ -1,35 +0,0 @@ -From de76174a6e76bf29c5a3cdcdab1b16ca96a0b4db 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.20.1 - 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/0037-arptables-nft-save-Fix-position-of-j-option.patch b/SOURCES/0037-arptables-nft-save-Fix-position-of-j-option.patch deleted file mode 100644 index 75e44c7..0000000 --- a/SOURCES/0037-arptables-nft-save-Fix-position-of-j-option.patch +++ /dev/null @@ -1,296 +0,0 @@ -From 59e25afcdc0a415c8b1bb6fff5fc14985d79e06b 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.20.1 - diff --git a/SOURCES/0038-arptables-nft-Don-t-print-default-h-len-h-type-value.patch b/SOURCES/0038-arptables-nft-Don-t-print-default-h-len-h-type-value.patch deleted file mode 100644 index 2c510df..0000000 --- a/SOURCES/0038-arptables-nft-Don-t-print-default-h-len-h-type-value.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 65303eb285ba082c24b2f2150918d63ed6c8398f 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.20.1 - 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/0039-tests-shell-Add-arptables-nft-verbose-output-test.patch b/SOURCES/0039-tests-shell-Add-arptables-nft-verbose-output-test.patch deleted file mode 100644 index 13948ac..0000000 --- a/SOURCES/0039-tests-shell-Add-arptables-nft-verbose-output-test.patch +++ /dev/null @@ -1,90 +0,0 @@ -From a63cfa813bb173414bfe37f8a8e2e5f96a99bb99 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.20.1 - diff --git a/SOURCES/0040-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch b/SOURCES/0040-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch deleted file mode 100644 index 6a486aa..0000000 --- a/SOURCES/0040-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 5ca3f6f4c4e673ecfab59ca81edd8bec69a7f43b 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.20.1 - 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/0041-nft-Add-new-builtin-chains-to-cache-immediately.patch b/SOURCES/0041-nft-Add-new-builtin-chains-to-cache-immediately.patch deleted file mode 100644 index 4ab7b4b..0000000 --- a/SOURCES/0041-nft-Add-new-builtin-chains-to-cache-immediately.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 598f69c07427a1457c3ac7da766d1c07d64b63ce 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.20.1 - 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/0042-xtables-Fix-position-of-replaced-rules-in-cache.patch b/SOURCES/0042-xtables-Fix-position-of-replaced-rules-in-cache.patch deleted file mode 100644 index 4cd841a..0000000 --- a/SOURCES/0042-xtables-Fix-position-of-replaced-rules-in-cache.patch +++ /dev/null @@ -1,168 +0,0 @@ -From 53422c35d925973702e043ac69119f87e08399e0 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.20.1 - diff --git a/SOURCES/0043-xtables-Fix-for-inserting-rule-at-wrong-position.patch b/SOURCES/0043-xtables-Fix-for-inserting-rule-at-wrong-position.patch deleted file mode 100644 index 1036b84..0000000 --- a/SOURCES/0043-xtables-Fix-for-inserting-rule-at-wrong-position.patch +++ /dev/null @@ -1,282 +0,0 @@ -From 9a6553277dc28dc2e4082646e14e49188aa6f096 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: 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-crash-when-comparing-rules-with-stan.patch b/SOURCES/0044-xtables-Fix-for-crash-when-comparing-rules-with-stan.patch deleted file mode 100644 index 53b6b42..0000000 --- a/SOURCES/0044-xtables-Fix-for-crash-when-comparing-rules-with-stan.patch +++ /dev/null @@ -1,97 +0,0 @@ -From be42a2a4a9382a445454eeb9db09aef52f699917 Mon Sep 17 00:00:00 2001 -From: Phil Sutter -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.20.1 - 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/0045-xtables-Fix-for-false-positive-rule-matching.patch b/SOURCES/0045-xtables-Fix-for-false-positive-rule-matching.patch deleted file mode 100644 index baf8875..0000000 --- a/SOURCES/0045-xtables-Fix-for-false-positive-rule-matching.patch +++ /dev/null @@ -1,258 +0,0 @@ -From ec020c1d789d9d8562105af2cd2fe23b797505d0 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.20.1 - diff --git a/SOURCES/0046-ebtables-Fix-rule-listing-with-counters.patch b/SOURCES/0046-ebtables-Fix-rule-listing-with-counters.patch deleted file mode 100644 index fd40165..0000000 --- a/SOURCES/0046-ebtables-Fix-rule-listing-with-counters.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 9092e808178de68c21ef35faeff153ddde1cffd1 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.20.1 - 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-Revert-ebtables-use-extrapositioned-negation-consist.patch b/SOURCES/0047-Revert-ebtables-use-extrapositioned-negation-consist.patch deleted file mode 100644 index f8d3c0e..0000000 --- a/SOURCES/0047-Revert-ebtables-use-extrapositioned-negation-consist.patch +++ /dev/null @@ -1,384 +0,0 @@ -From 71eb9a84f50211f78cf2b7b5ef34f99944a76c02 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) - -Conflicts: -- Drop changes to extensions/*.t since these files don't exist in - release tarballs. - -Signed-off-by: Phil Sutter ---- - extensions/libebt_802_3.c | 4 ++-- - extensions/libebt_arp.c | 14 +++++++------- - extensions/libebt_ip.c | 16 ++++++++-------- - extensions/libebt_ip6.c | 14 +++++++------- - extensions/libebt_mark_m.c | 2 +- - extensions/libebt_pkttype.c | 5 +---- - extensions/libebt_stp.c | 5 ++--- - extensions/libebt_vlan.c | 13 ++++--------- - iptables/nft-bridge.c | 6 +++--- - 9 files changed, 35 insertions(+), 44 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_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_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_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_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_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_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/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.20.1 - 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/0048-arptables-Support-set-counters-option.patch b/SOURCES/0048-arptables-Support-set-counters-option.patch deleted file mode 100644 index 1799940..0000000 --- a/SOURCES/0048-arptables-Support-set-counters-option.patch +++ /dev/null @@ -1,42 +0,0 @@ -From a071294e42f6b670b7e00819d2024ae7dd959993 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.20.1 - 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/0049-xshared-Explicitly-pass-target-to-command_jump.patch b/SOURCES/0049-xshared-Explicitly-pass-target-to-command_jump.patch deleted file mode 100644 index 2efc3ca..0000000 --- a/SOURCES/0049-xshared-Explicitly-pass-target-to-command_jump.patch +++ /dev/null @@ -1,136 +0,0 @@ -From 1d8efdc3ce231f08b57ee5eb5d784ccb5867c69b 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.20.1 - diff --git a/SOURCES/0050-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch b/SOURCES/0050-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch deleted file mode 100644 index fbdd4b9..0000000 --- a/SOURCES/0050-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch +++ /dev/null @@ -1,72 +0,0 @@ -From da5f63cd381cb109b73d2d31f5da35242bf5ae99 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.20.1 - 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/0051-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch b/SOURCES/0051-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch deleted file mode 100644 index 0f5cb6e..0000000 --- a/SOURCES/0051-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0af602be4dbda5bf510815d3e448d91098da594e 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.20.1 - diff --git a/SOURCES/0052-ebtables-nft-Support-user-defined-chain-policies.patch b/SOURCES/0052-ebtables-nft-Support-user-defined-chain-policies.patch deleted file mode 100644 index 1bfb1e8..0000000 --- a/SOURCES/0052-ebtables-nft-Support-user-defined-chain-policies.patch +++ /dev/null @@ -1,506 +0,0 @@ -From 008ecae50b63744d9f51fcbe794ac896163c4639 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.20.1 - 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/0053-xtables-save-Fix-table-not-found-error-message.patch b/SOURCES/0053-xtables-save-Fix-table-not-found-error-message.patch deleted file mode 100644 index a4e8698..0000000 --- a/SOURCES/0053-xtables-save-Fix-table-not-found-error-message.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 923b64e4003f4bbf50ae1b73504bd45dd55edd9b 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/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/0064-doc-Install-ip-6-tables-translate.8-manpages.patch b/SOURCES/0064-doc-Install-ip-6-tables-translate.8-manpages.patch new file mode 100644 index 0000000..6f79e53 --- /dev/null +++ b/SOURCES/0064-doc-Install-ip-6-tables-translate.8-manpages.patch @@ -0,0 +1,64 @@ +From 81f4451d47db33e803fb5a339f898e8911b55df6 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Wed, 20 Feb 2019 14:02:55 +0100 +Subject: [PATCH] doc: Install ip{6,}tables-translate.8 manpages + +These are just semantic links to xtables-translate.8. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit b738ca36777851e8f08c20a1e6c5c6492e934b38) +Signed-off-by: Phil Sutter +--- + iptables/.gitignore | 2 ++ + iptables/Makefile.am | 5 +++++ + 2 files changed, 7 insertions(+) + +diff --git a/iptables/.gitignore b/iptables/.gitignore +index d0301c6de896e..c638139b8a1d0 100644 +--- a/iptables/.gitignore ++++ b/iptables/.gitignore +@@ -2,6 +2,7 @@ + /ip6tables-save + /ip6tables-restore + /ip6tables-static ++/ip6tables-translate.8 + /iptables + /iptables.8 + /iptables-extensions.8 +@@ -11,6 +12,7 @@ + /iptables-restore + /iptables-restore.8 + /iptables-static ++/iptables-translate.8 + /iptables-xml + /iptables-xml.1 + /xtables-multi +diff --git a/iptables/Makefile.am b/iptables/Makefile.am +index 581dc32ba846b..8e902ef369b8e 100644 +--- a/iptables/Makefile.am ++++ b/iptables/Makefile.am +@@ -62,8 +62,10 @@ man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \ + iptables-xml.1 ip6tables.8 ip6tables-restore.8 \ + ip6tables-save.8 iptables-extensions.8 \ + xtables-nft.8 xtables-translate.8 xtables-legacy.8 \ ++ iptables-translate.8 ip6tables-translate.8 \ + xtables-monitor.8 + CLEANFILES = iptables.8 xtables-monitor.8 \ ++ iptables-translate.8 ip6tables-translate.8 \ + xtables-config-parser.c xtables-config-syntax.c + + vx_bin_links = iptables-xml +@@ -94,6 +96,9 @@ iptables-extensions.8: iptables-extensions.8.tmpl ../extensions/matches.man ../e + -e '/@MATCH@/ r ../extensions/matches.man' \ + -e '/@TARGET@/ r ../extensions/targets.man' $< >$@; + ++iptables-translate.8 ip6tables-translate.8: ++ ${AM_VERBOSE_GEN} echo '.so man8/xtables-translate.8' >$@ ++ + pkgconfig_DATA = xtables.pc + + # Using if..fi avoids an ugly "error (ignored)" message :) +-- +2.21.0 + diff --git a/SOURCES/0065-nft-Eliminate-dead-code-in-__nft_rule_list.patch b/SOURCES/0065-nft-Eliminate-dead-code-in-__nft_rule_list.patch new file mode 100644 index 0000000..332e141 --- /dev/null +++ b/SOURCES/0065-nft-Eliminate-dead-code-in-__nft_rule_list.patch @@ -0,0 +1,46 @@ +From 0a966eeecf8aa14924fd3ae221946c92417e6d71 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 7 Feb 2019 09:20:10 +0100 +Subject: [PATCH] nft: Eliminate dead code in __nft_rule_list + +If passed a rulenum > 0, the function uses nftnl_rule_lookup_byindex() +and returns early. Negative rulenum values are not supposed to happen, +so the remaining code which iterates over the full list of rules does +not need to respect rulenum anymore. + +Fixes: 039b048965210 ("nft: Make use of nftnl_rule_lookup_byindex()") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 519f5bcd9c07e0092a1a019176c82fb3bfbd9ced) +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 13 +------------ + 1 file changed, 1 insertion(+), 12 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index 2d527358cc7f2..d708fb6176b88 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -2331,18 +2331,7 @@ __nft_rule_list(struct nft_handle *h, struct nftnl_chain *c, + + r = nftnl_rule_iter_next(iter); + while (r != NULL) { +- rule_ctr++; +- +- if (rulenum > 0 && rule_ctr != rulenum) { +- /* List by rule number case */ +- goto next; +- } +- +- cb(r, rule_ctr, format); +- if (rulenum > 0) +- break; +- +-next: ++ cb(r, ++rule_ctr, format); + r = nftnl_rule_iter_next(iter); + } + +-- +2.21.0 + diff --git a/SOURCES/0066-arptables-Print-space-before-comma-and-counters.patch b/SOURCES/0066-arptables-Print-space-before-comma-and-counters.patch new file mode 100644 index 0000000..5bdfd36 --- /dev/null +++ b/SOURCES/0066-arptables-Print-space-before-comma-and-counters.patch @@ -0,0 +1,61 @@ +From 44f264cec0399e235755b44efbf856232b2e7e22 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Fri, 15 Feb 2019 15:27:43 +0100 +Subject: [PATCH] arptables: Print space before comma and counters + +Legacy arptables separates counters from rest of rule by ' , '. Assuming +that scripts scraping 'arptables -vL' output match on this, make +arptables-nft output conformant. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 73a0c2ef36d15e8277f0e00337736668b325381a) +Signed-off-by: Phil Sutter +--- + iptables/nft-arp.c | 2 +- + .../arptables/0003-arptables-verbose-output_0 | 12 ++++++------ + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c +index b436570291b7c..aed4c2ab02604 100644 +--- a/iptables/nft-arp.c ++++ b/iptables/nft-arp.c +@@ -618,7 +618,7 @@ nft_arp_print_rule(struct nftnl_rule *r, unsigned int num, unsigned int format) + print_matches_and_target(&cs, format); + + if (!(format & FMT_NOCOUNTS)) { +- printf(", pcnt="); ++ printf(" , pcnt="); + xtables_print_num(cs.counters.pcnt, format | FMT_NOTABLE); + printf("-- bcnt="); + xtables_print_num(cs.counters.bcnt, format | FMT_NOTABLE); +diff --git a/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 +index 35126fa7d717c..3a9807a1cfe0b 100755 +--- a/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 ++++ b/iptables/tests/shell/testcases/arptables/0003-arptables-verbose-output_0 +@@ -36,16 +36,16 @@ 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 ++-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 ++-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' ++-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) + +-- +2.21.0 + diff --git a/SOURCES/0067-extensions-Fix-ipvs-vproto-parsing.patch b/SOURCES/0067-extensions-Fix-ipvs-vproto-parsing.patch new file mode 100644 index 0000000..8b04738 --- /dev/null +++ b/SOURCES/0067-extensions-Fix-ipvs-vproto-parsing.patch @@ -0,0 +1,48 @@ +From ba7ef8b709eb347bfc5b0c76485747f89b90814f Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 21 Feb 2019 20:09:30 +0100 +Subject: [PATCH] extensions: Fix ipvs vproto parsing + +This was broken by integration into guided option parser: + +* Make 'vproto' option XTTYPE_PROTOCOL, otherwise its arguments are + parsed as garbage only. + +* Drop O_VPROTO case from ipvs_mt_parse(), due to XTOPT_POINTER() and + above change there is nothing to do for it in there. + +Fixes: 372203af4c70f ("libxt_ipvs: use guided option parser") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit fcbdc69e8a750fe02c9d7c7aced0efc91715132d) +Signed-off-by: Phil Sutter +--- + extensions/libxt_ipvs.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c +index a6c57a030d2c6..fe98fef951686 100644 +--- a/extensions/libxt_ipvs.c ++++ b/extensions/libxt_ipvs.c +@@ -27,7 +27,7 @@ enum { + static const struct xt_option_entry ipvs_mt_opts[] = { + {.name = "ipvs", .id = O_IPVS, .type = XTTYPE_NONE, + .flags = XTOPT_INVERT}, +- {.name = "vproto", .id = O_VPROTO, .type = XTTYPE_STRING, ++ {.name = "vproto", .id = O_VPROTO, .type = XTTYPE_PROTOCOL, + .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, l4proto)}, + {.name = "vaddr", .id = O_VADDR, .type = XTTYPE_HOSTMASK, + .flags = XTOPT_INVERT}, +@@ -69,9 +69,6 @@ static void ipvs_mt_parse(struct xt_option_call *cb) + + xtables_option_parse(cb); + switch (cb->entry->id) { +- case O_VPROTO: +- data->l4proto = cb->val.protocol; +- break; + case O_VADDR: + memcpy(&data->vaddr, &cb->val.haddr, sizeof(cb->val.haddr)); + memcpy(&data->vmask, &cb->val.hmask, sizeof(cb->val.hmask)); +-- +2.21.0 + diff --git a/SOURCES/0068-extensions-Fix-ipvs-vproto-option-printing.patch b/SOURCES/0068-extensions-Fix-ipvs-vproto-option-printing.patch new file mode 100644 index 0000000..63b17e1 --- /dev/null +++ b/SOURCES/0068-extensions-Fix-ipvs-vproto-option-printing.patch @@ -0,0 +1,33 @@ +From 216e0c58489f3d730456ca1e55bffe25aa50e9d8 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 21 Feb 2019 20:09:31 +0100 +Subject: [PATCH] extensions: Fix ipvs vproto option printing + +This was broken since day 1: vproto option was printed as 'proto' which +in turn iptables wouldn't accept anymore. + +Fixes: c36d05e424069 ("libxt_ipvs: user-space lib for netfilter matcher xt_ipvs") +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit dd1ad59f0df66811335c10ed90c33151a658a50e) +Signed-off-by: Phil Sutter +--- + extensions/libxt_ipvs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c +index fe98fef951686..51952be4245b3 100644 +--- a/extensions/libxt_ipvs.c ++++ b/extensions/libxt_ipvs.c +@@ -165,7 +165,7 @@ static void ipvs_mt_dump(const void *ip, const struct xt_ipvs_mtinfo *data, + if (data->bitmask & XT_IPVS_PROTO) { + if (data->invert & XT_IPVS_PROTO) + printf(" !"); +- printf(" %sproto %u", prefix, data->l4proto); ++ printf(" %svproto %u", prefix, data->l4proto); + } + + if (data->bitmask & XT_IPVS_VADDR) { +-- +2.21.0 + diff --git a/SOURCES/0069-extensions-Add-testcase-for-libxt_ipvs.patch b/SOURCES/0069-extensions-Add-testcase-for-libxt_ipvs.patch new file mode 100644 index 0000000..77db91c --- /dev/null +++ b/SOURCES/0069-extensions-Add-testcase-for-libxt_ipvs.patch @@ -0,0 +1,45 @@ +From 623a4ed4f75d1a0537525a8ea49dc882629b9eed Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Thu, 21 Feb 2019 20:09:32 +0100 +Subject: [PATCH] extensions: Add testcase for libxt_ipvs + +Given that it is fixed now, make it stay. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +(cherry picked from commit 06da3ab2c818b15304a285a798eaaf16ebf375ea) +Signed-off-by: Phil Sutter +--- + extensions/libxt_ipvs.t | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 extensions/libxt_ipvs.t + +diff --git a/extensions/libxt_ipvs.t b/extensions/libxt_ipvs.t +new file mode 100644 +index 0000000000000..c2acc6668d1b2 +--- /dev/null ++++ b/extensions/libxt_ipvs.t +@@ -0,0 +1,20 @@ ++:INPUT,FORWARD,OUTPUT ++-m ipvs --ipvs;=;OK ++-m ipvs ! --ipvs;=;OK ++-m ipvs --vproto tcp;-m ipvs --vproto 6;OK ++-m ipvs ! --vproto TCP;-m ipvs ! --vproto 6;OK ++-m ipvs --vproto 23;=;OK ++-m ipvs --vaddr 1.2.3.4;=;OK ++-m ipvs ! --vaddr 1.2.3.4/255.255.255.0;-m ipvs ! --vaddr 1.2.3.4/24;OK ++-m ipvs --vport http;-m ipvs --vport 80;OK ++-m ipvs ! --vport ssh;-m ipvs ! --vport 22;OK ++-m ipvs --vport 22;=;OK ++-m ipvs ! --vport 443;=;OK ++-m ipvs --vdir ORIGINAL;=;OK ++-m ipvs --vdir REPLY;=;OK ++-m ipvs --vmethod GATE;=;OK ++-m ipvs ! --vmethod IPIP;=;OK ++-m ipvs --vmethod MASQ;=;OK ++-m ipvs --vportctl 21;=;OK ++-m ipvs ! --vportctl 21;=;OK ++-m ipvs --vproto 6 --vaddr 1.2.3.4/16 --vport 22 --vdir ORIGINAL --vmethod GATE;=;OK +-- +2.21.0 + diff --git a/SOURCES/0070-doc-Install-ip-6-tables-restore-translate.8-man-page.patch b/SOURCES/0070-doc-Install-ip-6-tables-restore-translate.8-man-page.patch new file mode 100644 index 0000000..8124f2a --- /dev/null +++ b/SOURCES/0070-doc-Install-ip-6-tables-restore-translate.8-man-page.patch @@ -0,0 +1,67 @@ +From 77749e43ced473de311d8407f352009cc5b073a2 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 23 Jul 2019 15:24:41 +0200 +Subject: [PATCH] doc: Install ip{6,}tables-restore-translate.8 man pages + +Just like in b738ca3677785 ("doc: Install ip{6,}tables-translate.8 +manpages"), create man pages for *-restore-translate tools as semantic +links to xtables-translate.8. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit 3dfb01cf14d72c21a15ab69a2767280223b7e3cb) + +Conflicts: + iptables/Makefile.am +-> Patch applied manually, multiple context changes. + +Signed-off-by: Phil Sutter +--- + iptables/.gitignore | 2 ++ + iptables/Makefile.am | 3 ++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/iptables/.gitignore b/iptables/.gitignore +index c638139b8a1d0..d46adc8a32f02 100644 +--- a/iptables/.gitignore ++++ b/iptables/.gitignore +@@ -3,6 +3,7 @@ + /ip6tables-restore + /ip6tables-static + /ip6tables-translate.8 ++/ip6tables-restore-translate.8 + /iptables + /iptables.8 + /iptables-extensions.8 +@@ -13,6 +14,7 @@ + /iptables-restore.8 + /iptables-static + /iptables-translate.8 ++/iptables-restore-translate.8 + /iptables-xml + /iptables-xml.1 + /xtables-multi +diff --git a/iptables/Makefile.am b/iptables/Makefile.am +index 8e902ef369b8e..74bc2bf98ef8c 100644 +--- a/iptables/Makefile.am ++++ b/iptables/Makefile.am +@@ -63,6 +63,7 @@ man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \ + ip6tables-save.8 iptables-extensions.8 \ + xtables-nft.8 xtables-translate.8 xtables-legacy.8 \ + iptables-translate.8 ip6tables-translate.8 \ ++ iptables-restore-translate.8 ip6tables-restore-translate.8 \ + xtables-monitor.8 + CLEANFILES = iptables.8 xtables-monitor.8 \ + iptables-translate.8 ip6tables-translate.8 \ +@@ -96,7 +97,7 @@ iptables-extensions.8: iptables-extensions.8.tmpl ../extensions/matches.man ../e + -e '/@MATCH@/ r ../extensions/matches.man' \ + -e '/@TARGET@/ r ../extensions/targets.man' $< >$@; + +-iptables-translate.8 ip6tables-translate.8: ++iptables-translate.8 ip6tables-translate.8 iptables-restore-translate.8 ip6tables-restore-translate.8: + ${AM_VERBOSE_GEN} echo '.so man8/xtables-translate.8' >$@ + + pkgconfig_DATA = xtables.pc +-- +2.22.0 + diff --git a/SOURCES/0071-nft-Set-socket-receive-buffer.patch b/SOURCES/0071-nft-Set-socket-receive-buffer.patch new file mode 100644 index 0000000..c224f71 --- /dev/null +++ b/SOURCES/0071-nft-Set-socket-receive-buffer.patch @@ -0,0 +1,121 @@ +From 77b8d7784082889a66d689aac1972154ef46da08 Mon Sep 17 00:00:00 2001 +From: Phil Sutter +Date: Tue, 2 Jul 2019 20:30:49 +0200 +Subject: [PATCH] nft: Set socket receive buffer + +When trying to delete user-defined chains in a large ruleset, +iptables-nft aborts with "No buffer space available". This can be +reproduced using the following script: + +| #! /bin/bash +| iptables-nft-restore <( +| +| echo "*filter" +| for i in $(seq 0 200000);do +| printf ":chain_%06x - [0:0]\n" $i +| done +| for i in $(seq 0 200000);do +| printf -- "-A INPUT -j chain_%06x\n" $i +| printf -- "-A INPUT -j chain_%06x\n" $i +| done +| echo COMMIT +| +| ) +| iptables-nft -X + +The problem seems to be the sheer amount of netlink error messages sent +back to user space (one EBUSY for each chain). To solve this, set +receive buffer size depending on number of commands sent to kernel. + +Suggested-by: Pablo Neira Ayuso +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +(cherry picked from commit d3e39e9c457f452540359e42fb58d64a28fe3e18) + +Conflicts: + iptables/nft.c +-> Context change due to missing commits 17c282003f463 + ("nft: reset netlink sender buffer size of socket restart") and + 58d7de0181f61 ("xtables: handle concurrent ruleset modifications"). + +Signed-off-by: Phil Sutter +--- + iptables/nft.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/iptables/nft.c b/iptables/nft.c +index d708fb6176b88..87fdd1e66152d 100644 +--- a/iptables/nft.c ++++ b/iptables/nft.c +@@ -170,8 +170,24 @@ static void mnl_set_sndbuffer(const struct mnl_socket *nl, + nlbuffsiz = newbuffsiz; + } + ++static int nlrcvbuffsiz; ++ ++static void mnl_set_rcvbuffer(const struct mnl_socket *nl, int numcmds) ++{ ++ int newbuffsiz = getpagesize() * numcmds; ++ ++ if (newbuffsiz <= nlrcvbuffsiz) ++ return; ++ ++ if (setsockopt(mnl_socket_get_fd(nl), SOL_SOCKET, SO_RCVBUFFORCE, ++ &newbuffsiz, sizeof(socklen_t)) < 0) ++ return; ++ ++ nlrcvbuffsiz = newbuffsiz; ++} ++ + static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock, +- struct nftnl_batch *batch) ++ struct nftnl_batch *batch, int numcmds) + { + static const struct sockaddr_nl snl = { + .nl_family = AF_NETLINK +@@ -186,13 +202,15 @@ static ssize_t mnl_nft_socket_sendmsg(const struct mnl_socket *nf_sock, + }; + + mnl_set_sndbuffer(nf_sock, batch); ++ mnl_set_rcvbuffer(nf_sock, numcmds); + nftnl_batch_iovec(batch, iov, iov_len); + + return sendmsg(mnl_socket_get_fd(nf_sock), &msg, 0); + } + + static int mnl_batch_talk(const struct mnl_socket *nf_sock, +- struct nftnl_batch *batch, struct list_head *err_list) ++ struct nftnl_batch *batch, int numcmds, ++ struct list_head *err_list) + { + const struct mnl_socket *nl = nf_sock; + int ret, fd = mnl_socket_get_fd(nl), portid = mnl_socket_get_portid(nl); +@@ -204,7 +222,7 @@ static int mnl_batch_talk(const struct mnl_socket *nf_sock, + }; + int err = 0; + +- ret = mnl_nft_socket_sendmsg(nf_sock, batch); ++ ret = mnl_nft_socket_sendmsg(nf_sock, batch, numcmds); + if (ret == -1) + return -1; + +@@ -748,6 +766,7 @@ static int nft_restart(struct nft_handle *h) + return -1; + + h->portid = mnl_socket_get_portid(h->nl); ++ nlrcvbuffsiz = 0; + + return 0; + } +@@ -2728,7 +2747,7 @@ static int nft_action(struct nft_handle *h, int action) + break; + } + +- ret = mnl_batch_talk(h->nl, h->batch, &h->err_list); ++ ret = mnl_batch_talk(h->nl, h->batch, seq, &h->err_list); + + i = 0; + buflen = sizeof(errmsg); +-- +2.22.0 + diff --git a/SPECS/iptables.spec b/SPECS/iptables.spec index 464057c..14016e0 100644 --- a/SPECS/iptables.spec +++ b/SPECS/iptables.spec @@ -7,7 +7,7 @@ Name: iptables Summary: Tools for managing Linux kernel packet filtering capabilities Version: 1.8.2 -Release: 9%{?dist}.1 +Release: 16%{?dist} Source: http://www.netfilter.org/projects/iptables/files/%{name}-%{version}.tar.bz2 Source1: iptables.init Source2: iptables-config @@ -21,59 +21,78 @@ Source9: ebtables.service Source10: ebtables-config Source11: ebtables.8 Source12: arptables.8 -Patch1: 0001-iptables-apply-Use-mktemp-instead-of-tempfile.patch -Patch2: 0002-extensions-format-security-fixes-in-libip-6-t_icmp.patch -Patch3: 0003-arptables-nft-use-generic-expression-parsing-functio.patch -Patch4: 0004-xtables-Don-t-use-native-nftables-comments.patch -Patch5: 0005-xtables-Introduce-per-table-chain-caches.patch -Patch6: 0006-nft-add-type-field-to-builtin_table.patch -Patch7: 0007-nft-move-chain_cache-back-to-struct-nft_handle.patch -Patch8: 0008-nft-move-initialize-to-struct-nft_handle.patch -Patch9: 0009-xtables-constify-struct-builtin_table-and-struct-bui.patch -Patch10: 0010-nft-Simplify-nftnl_rule_list_chain_save.patch -Patch11: 0011-nft-Review-unclear-return-points.patch -Patch12: 0012-xtables-restore-Review-chain-handling.patch -Patch13: 0013-nft-Review-is_-_compatible-routines.patch -Patch14: 0014-nft-Reduce-__nft_rule_del-signature.patch -Patch15: 0015-nft-Reduce-indenting-level-in-flush_chain_cache.patch -Patch16: 0016-nft-Simplify-per-table-chain-cache-update.patch -Patch17: 0017-nft-Simplify-nft_rule_insert-a-bit.patch -Patch18: 0018-nft-Introduce-fetch_chain_cache.patch -Patch19: 0019-nft-Move-nft_rule_list_get-above-nft_chain_list_get.patch -Patch20: 0020-xtables-Implement-per-chain-rule-cache.patch -Patch21: 0021-nft-Drop-nft_chain_list_find.patch -Patch22: 0022-xtables-Optimize-flushing-a-specific-chain.patch -Patch23: 0023-xtables-Optimize-nft_chain_zero_counters.patch -Patch24: 0024-tests-Extend-verbose-output-and-return-code-tests.patch -Patch25: 0025-xtables-Optimize-user-defined-chain-deletion.patch -Patch26: 0026-xtables-Optimize-list-command-with-given-chain.patch -Patch27: 0027-xtables-Optimize-list-rules-command-with-given-chain.patch -Patch28: 0028-nft-Make-use-of-nftnl_rule_lookup_byindex.patch -Patch29: 0029-nft-Simplify-nft_is_chain_compatible.patch -Patch30: 0030-nft-Simplify-flush_chain_cache.patch -Patch31: 0031-xtables-Set-errno-in-nft_rule_check-if-chain-not-fou.patch -Patch32: 0032-xtables-Speed-up-chain-deletion-in-large-rulesets.patch -Patch33: 0033-arptables-nft-Fix-listing-rules-without-target.patch -Patch34: 0034-arptables-nft-Fix-MARK-target-parsing-and-printing.patch -Patch35: 0035-arptables-nft-Fix-CLASSIFY-target-printing.patch -Patch36: 0036-arptables-nft-Remove-space-between-cnt-and-value.patch -Patch37: 0037-arptables-nft-save-Fix-position-of-j-option.patch -Patch38: 0038-arptables-nft-Don-t-print-default-h-len-h-type-value.patch -Patch39: 0039-tests-shell-Add-arptables-nft-verbose-output-test.patch -Patch40: 0040-arptables-nft-Set-h-type-h-length-masks-by-default-t.patch -Patch41: 0041-nft-Add-new-builtin-chains-to-cache-immediately.patch -Patch42: 0042-xtables-Fix-position-of-replaced-rules-in-cache.patch -Patch43: 0043-xtables-Fix-for-inserting-rule-at-wrong-position.patch -Patch44: 0044-xtables-Fix-for-crash-when-comparing-rules-with-stan.patch -Patch45: 0045-xtables-Fix-for-false-positive-rule-matching.patch -Patch46: 0046-ebtables-Fix-rule-listing-with-counters.patch -Patch47: 0047-Revert-ebtables-use-extrapositioned-negation-consist.patch -Patch48: 0048-arptables-Support-set-counters-option.patch -Patch49: 0049-xshared-Explicitly-pass-target-to-command_jump.patch -Patch50: 0050-nft-Don-t-assume-NFTNL_RULE_USERDATA-holds-a-comment.patch -Patch51: 0051-nft-Introduce-UDATA_TYPE_EBTABLES_POLICY.patch -Patch52: 0052-ebtables-nft-Support-user-defined-chain-policies.patch -Patch53: 0053-xtables-save-Fix-table-not-found-error-message.patch +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 +Patch64: 0064-doc-Install-ip-6-tables-translate.8-manpages.patch +Patch65: 0065-nft-Eliminate-dead-code-in-__nft_rule_list.patch +Patch66: 0066-arptables-Print-space-before-comma-and-counters.patch +Patch67: 0067-extensions-Fix-ipvs-vproto-parsing.patch +Patch68: 0068-extensions-Fix-ipvs-vproto-option-printing.patch +Patch69: 0069-extensions-Add-testcase-for-libxt_ipvs.patch +Patch70: 0070-doc-Install-ip-6-tables-restore-translate.8-man-page.patch +Patch71: 0071-nft-Set-socket-receive-buffer.patch + URL: http://www.netfilter.org/ # pf.os: ISC license # iptables-apply: Artistic Licence 2.0 @@ -216,7 +235,7 @@ sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool rm -f include/linux/types.h -make %{?_smp_mflags} +make %{?_smp_mflags} V=1 %install make install DESTDIR=%{buildroot} @@ -374,12 +393,12 @@ done %{_sbindir}/ip6tables-translate %{_sbindir}/xtables-monitor %{_sbindir}/xtables-nft-multi -%{_mandir}/man8/iptables* -%{_mandir}/man8/ip6tables* -%{_mandir}/man8/nfnl_osf* -%{_mandir}/man8/xtables-monitor* -%{_mandir}/man8/xtables-nft* -%{_mandir}/man8/xtables-translate* +%doc %{_mandir}/man8/iptables* +%doc %{_mandir}/man8/ip6tables* +%doc %{_mandir}/man8/xtables-monitor* +%doc %{_mandir}/man8/xtables-nft* +%doc %{_mandir}/man8/*tables-translate* +%doc %{_mandir}/man8/*tables-restore-translate* %dir %{_libdir}/xtables %{_libdir}/xtables/libarpt* %{_libdir}/xtables/libebt* @@ -426,6 +445,8 @@ done %{_sbindir}/nfbpf_compile %dir %{_datadir}/xtables %{_datadir}/xtables/pf.os +%doc %{_mandir}/man8/nfnl_osf* +%doc %{_mandir}/man8/nfbpf_compile* %files arptables %{_sbindir}/arptables* @@ -443,8 +464,40 @@ done %doc %{_mandir}/man8/ebtables.8* %changelog -* Tue Jun 04 2019 Phil Sutter - 1.8.2-9.1 +* Thu Aug 08 2019 Phil Sutter - 1.8.2-16 +- nft: Set socket receive buffer + +* Wed Jul 31 2019 Phil Sutter - 1.8.2-15 +- doc: Install ip{6,}tables-restore-translate.8 man pages + +* Tue Jul 02 2019 Phil Sutter - 1.8.2-14 +- arptables: Print space before comma and counters +- extensions: Fix ipvs vproto parsing +- extensions: Fix ipvs vproto option printing +- extensions: Add testcase for libxt_ipvs + +* Mon Jul 01 2019 Phil Sutter - 1.8.2-13 +- doc: Install ip{6,}tables-translate.8 manpages +- nft: Eliminate dead code in __nft_rule_list + +* 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