Merge branch 'master' of git://1984.lsi.us.es/iptables into tests
diff --git a/extensions/libip6t_LOG.t b/extensions/libip6t_LOG.t
new file mode 100644
index 0000000..fbf5118
--- /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_REJECT.t b/extensions/libip6t_REJECT.t
new file mode 100644
index 0000000..5a38942
--- /dev/null
+++ b/extensions/libip6t_REJECT.t
@@ -0,0 +1,9 @@
+: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
+-p tcp -j REJECT --reject-with tcp-reset;=;OK
+-j REJECT --reject-with tcp-reset;;FAIL
diff --git a/extensions/libip6t_ah.t b/extensions/libip6t_ah.t
new file mode 100644
index 0000000..652bbf3
--- /dev/null
+++ b/extensions/libip6t_ah.t
@@ -0,0 +1,12 @@
+: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
+-m ah --ahres;=;OK
+-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
diff --git a/extensions/libip6t_eui64.t b/extensions/libip6t_eui64.t
new file mode 100644
index 0000000..e5aaaac
--- /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/libipt_DNAT.t b/extensions/libipt_DNAT.t
new file mode 100644
index 0000000..e3fd563
--- /dev/null
+++ b/extensions/libipt_DNAT.t
@@ -0,0 +1,8 @@
+:PREROUTING
+*nat
+-j DNAT --to-destination 1.1.1.1;=;OK
+-j DNAT --to-destination 1.1.1.1-1.1.1.10;=;OK
+-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
+-j DNAT;;FAIL
diff --git a/extensions/libipt_ECN.t b/extensions/libipt_ECN.t
new file mode 100644
index 0000000..2e09205
--- /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 0000000..fbf5118
--- /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 0000000..4650204
--- /dev/null
+++ b/extensions/libipt_MASQUERADE.t
@@ -0,0 +1,8 @@
+:POSTROUTING
+*nat
+-j MASQUERADE;=;OK
+-j MASQUERADE --random;=;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_REJECT.t b/extensions/libipt_REJECT.t
new file mode 100644
index 0000000..5b26b10
--- /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 0000000..73071bb
--- /dev/null
+++ b/extensions/libipt_SNAT.t
@@ -0,0 +1,8 @@
+:POSTROUTING
+*nat
+-j SNAT --to-source 1.1.1.1;=;OK
+-j SNAT --to-source 1.1.1.1-1.1.1.10;=;OK
+-p tcp -j SNAT --to-source 1.1.1.1:1025-65535;=;OK
+-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65535;=;OK
+-p tcp -j SNAT --to-source 1.1.1.1-1.1.1.10:1025-65536;;FAIL
+-j SNAT;;FAIL
diff --git a/extensions/libipt_ULOG.t b/extensions/libipt_ULOG.t
new file mode 100644
index 0000000..4577c61
--- /dev/null
+++ b/extensions/libipt_ULOG.t
@@ -0,0 +1,17 @@
+:INPUT,FORWARD,OUTPUT
+-j ULOG --ulog-nlgroup 1;-j ULOG;OK
+-j ULOG --ulog-nlgroup 32;=;OK
+-j ULOG --ulog-nlgroup 33;;FAIL
+-j ULOG --ulog-nlgroup 0;;FAIL
+-j ULOG --ulog-cprange 1;=;OK
+-j ULOG --ulog-cprange 4294967295;=;OK
+# This below outputs 0 in iptables-save
+-j ULOG --ulog-cprange 4294967296;;FAIL
+# supports up to 31 characters
+-j ULOG --ulog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;=;OK
+-j ULOG --ulog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;;FAIL
+-j ULOG --ulog-qthreshold 1;-j ULOG;OK
+-j ULOG --ulog-qthreshold 0;;FAIL
+-j ULOG --ulog-qthreshold 50;=;OK
+-j ULOG --ulog-qthreshold 51;;FAIL
+-j ULOG;=;OK
diff --git a/extensions/libipt_ah.t b/extensions/libipt_ah.t
new file mode 100644
index 0000000..a0ce3b0
--- /dev/null
+++ b/extensions/libipt_ah.t
@@ -0,0 +1,12 @@
+: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
diff --git a/extensions/libipt_icmp.t b/extensions/libipt_icmp.t
new file mode 100644
index 0000000..1581916
--- /dev/null
+++ b/extensions/libipt_icmp.t
@@ -0,0 +1,11 @@
+:INPUT,FORWARD,OUTPUT
+-p icmp -m icmp --icmp-type any;=;OK
+# output uses the number, better use the name?
+-p icmp -m icmp --icmp-type echo-reply;=;OK
+# output uses the number, better use the name?
+-p icmp -m icmp --icmp-type destination-unreachable;=;OK
+# it does not acccept name/name, should we accept this?
+-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?
+-p icmp -m icmp;=;OK
diff --git a/extensions/libipt_ttl.t b/extensions/libipt_ttl.t
new file mode 100644
index 0000000..1a3568e
--- /dev/null
+++ b/extensions/libipt_ttl.t
@@ -0,0 +1,13 @@
+: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
+-m ttl --ttl-gt 255;;FAIL
+# not possible have anything below 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 0000000..97575b0
--- /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 0000000..9451ad8
--- /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 0000000..5214dd3
--- /dev/null
+++ b/extensions/libxt_CLASSIFY.t
@@ -0,0 +1,7 @@
+:FORWARD,OUTPUT,POSTROUTING
+*mangle
+-j CLASSIFY --set-class 0000:ffff;=;OK
+# maximum handle accepted by tc is 0xffff
+-j CLASSIFY --set-class 0000:ffffffff;;FAIL
+-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 0000000..79a838f
--- /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_CT.t b/extensions/libxt_CT.t
new file mode 100644
index 0000000..1cd78df
--- /dev/null
+++ b/extensions/libxt_CT.t
@@ -0,0 +1,16 @@
+:PREROUTING,OUTPUT
+*raw
+-j CT --notrack;=;OK
+-j CT --ctevents new,related,destroy,reply,assured,protoinfo,helper,mark;=;OK
+-j CT --expevents new;=;OK
+-j CT --zone 0;=;OK
+-j CT --zone 65535;=;OK
+-j CT --zone 65536;;FAIL
+-j CT --zone -1;;FAIL
+-j CT;;FAIL
+!nfct timeout add test inet tcp ESTABLISHED 100
+-j CT --timeout test;=;OK
+!nfct timeout del test
+!nfct helper add rpc inet tcp
+-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 0000000..fcc5598
--- /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_MARK.t b/extensions/libxt_MARK.t
new file mode 100644
index 0000000..9d1aa7d
--- /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 0000000..db2def1
--- /dev/null
+++ b/extensions/libxt_NFLOG.t
@@ -0,0 +1,16 @@
+: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-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;=;OK
+-j NFLOG --nflog-prefix xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;;FAIL
+-j NFLOG --nflog-threshold 1;=;OK
+-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 0000000..912db03
--- /dev/null
+++ b/extensions/libxt_NFQUEUE.t
@@ -0,0 +1,11 @@
+: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?
+-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
diff --git a/extensions/libxt_NOTRACK.t b/extensions/libxt_NOTRACK.t
new file mode 100644
index 0000000..27c4734
--- /dev/null
+++ b/extensions/libxt_NOTRACK.t
@@ -0,0 +1,3 @@
+:PREROUTING,OUTPUT
+*raw
+-j NOTRACK;=;OK
diff --git a/extensions/libxt_TEE.t b/extensions/libxt_TEE.t
new file mode 100644
index 0000000..ce8b103
--- /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 0000000..077dbbd
--- /dev/null
+++ b/extensions/libxt_TOS.t
@@ -0,0 +1,15 @@
+: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)
+-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_TRACE.t b/extensions/libxt_TRACE.t
new file mode 100644
index 0000000..cadb733
--- /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 0000000..390a63f
--- /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_cluster.t b/extensions/libxt_cluster.t
new file mode 100644
index 0000000..ac60824
--- /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 0000000..cc702c6
--- /dev/null
+++ b/extensions/libxt_comment.t
@@ -0,0 +1,11 @@
+:INPUT,FORWARD,OUTPUT
+-m comment;;FAIL
+-m comment --comment;;FAIL
+#
+# it fails with 256 characters
+#
+-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 0000000..b2b2d02
--- /dev/null
+++ b/extensions/libxt_connbytes.t
@@ -0,0 +1,20 @@
+: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
+-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_connlimit.t b/extensions/libxt_connlimit.t
new file mode 100644
index 0000000..c7ea61e
--- /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 0000000..4dd7d9a
--- /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 0000000..db53147
--- /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 0000000..f5adb45
--- /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 0000000..50bc3b3
--- /dev/null
+++ b/extensions/libxt_dccp.t
@@ -0,0 +1,28 @@
+: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
+-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
+-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 0000000..38d7f04
--- /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_esp.t b/extensions/libxt_esp.t
new file mode 100644
index 0000000..008013b
--- /dev/null
+++ b/extensions/libxt_esp.t
@@ -0,0 +1,9 @@
+: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
+# should 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 0000000..e25f9e4
--- /dev/null
+++ b/extensions/libxt_hashlimit.t
@@ -0,0 +1,25 @@
+:INPUT,FORWARD,OUTPUT
+-m hashlimit --hashlimit-above 1/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 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"
+-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
diff --git a/extensions/libxt_helper.t b/extensions/libxt_helper.t
new file mode 100644
index 0000000..9616035
--- /dev/null
+++ b/extensions/libxt_helper.t
@@ -0,0 +1,5 @@
+:INPUT,FORWARD,OUTPUT
+-m helper --helper ftp;=;OK
+# should be OK?
+-m helper --helper wrong;;FAIL
+-m helper;;FAIL
diff --git a/extensions/libxt_iprange.t b/extensions/libxt_iprange.t
new file mode 100644
index 0000000..af40f31
--- /dev/null
+++ b/extensions/libxt_iprange.t
@@ -0,0 +1,9 @@
+: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?
+-m iprange --src-range 1.1.1.1;;FAIL
+-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 0000000..0b6624e
--- /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 0000000..b0af653
--- /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_mark.t b/extensions/libxt_mark.t
new file mode 100644
index 0000000..7c00537
--- /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 0000000..5265de8
--- /dev/null
+++ b/extensions/libxt_multiport.t
@@ -0,0 +1,22 @@
+: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"
+-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 0000000..f7dd6ba
--- /dev/null
+++ b/extensions/libxt_nfacct.t
@@ -0,0 +1,9 @@
+:INPUT,FORWARD,OUTPUT
+!nfacct add test
+#
+# extra space in iptables-save output, fix it
+#
+-m nfacct --nfacct-name test;=;OK
+-m nfacct --nfacct-name wrong;;FAIL
+-m nfacct;;FAIL
+!nfacct del test
diff --git a/extensions/libxt_owner.t b/extensions/libxt_owner.t
new file mode 100644
index 0000000..aec30b6
--- /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 0000000..1f82c2e
--- /dev/null
+++ b/extensions/libxt_physdev.t
@@ -0,0 +1,12 @@
+: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.
+-m physdev --physdev-out lo;;FAIL
+-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 0000000..d93baea
--- /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_quota.t b/extensions/libxt_quota.t
new file mode 100644
index 0000000..a1253eb
--- /dev/null
+++ b/extensions/libxt_quota.t
@@ -0,0 +1,8 @@
+:INPUT,FORWARD,OUTPUT
+-m quota --quota 0;=;OK
+# iptables-save shows wrong output
+-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 0000000..c3d8537
--- /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_sctp.t b/extensions/libxt_sctp.t
new file mode 100644
index 0000000..4016e4f
--- /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_standard.t b/extensions/libxt_standard.t
new file mode 100644
index 0000000..923569c
--- /dev/null
+++ b/extensions/libxt_standard.t
@@ -0,0 +1,4 @@
+:INPUT,FORWARD,OUTPUT
+-j DROP;=;OK
+-j ACCEPT;=;OK
+-j RETURN;=;OK
diff --git a/extensions/libxt_state.t b/extensions/libxt_state.t
new file mode 100644
index 0000000..8e4bce3
--- /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_string.t b/extensions/libxt_string.t
new file mode 100644
index 0000000..d6aaff6
--- /dev/null
+++ b/extensions/libxt_string.t
@@ -0,0 +1,11 @@
+:INPUT,FORWARD,OUTPUT
+-m string --algo bm --string "test";=;OK
+-m string --algo kmp --string "test";=;OK
+-m string --algo kmp ! --string "test";=;OK
+-m string --algo bm --string "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";=;OK
+-m string --algo bm --string "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";=;OK
+-m string --algo bm --hexstring "|0a0a0a0a|";=;OK
+-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 0000000..b0e8006
--- /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_time.t b/extensions/libxt_time.t
new file mode 100644
index 0000000..673af09
--- /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 0000000..ccbe800
--- /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_udp.t b/extensions/libxt_udp.t
new file mode 100644
index 0000000..ba94e92
--- /dev/null
+++ b/extensions/libxt_udp.t
@@ -0,0 +1,21 @@
+: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
+-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 0000000..7305c1f
--- /dev/null
+++ b/iptables-test.py
@@ -0,0 +1,233 @@
+#!/usr/bin/python
+#
+# (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
+#
+# 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 <http://www.sophos.com>
+#
+import sys, os, subprocess, re
+
+IPTABLES = "iptables"
+IP6TABLES = "ip6tables"
+EXTENSIONS_PATH = "extensions"
+
+class colors:
+	HEADER = '\033[95m'
+	BLUE = '\033[94m'
+	GREEN = '\033[92m'
+	YELLOW = '\033[93m'
+	RED = '\033[91m'
+	ENDC = '\033[0m'
+
+def print_error(filename, lineno, reason):
+	print filename + ": " + colors.RED + "ERROR" + colors.ENDC + ": line %d (%s)" %(lineno, reason)
+
+def delete_rule(iptables, rule, filename, lineno, devnull):
+	cmd = iptables + " -D " + rule
+	ret = subprocess.call(cmd, stderr=devnull, shell=True)
+	if ret == 1:
+		reason = "cannot delete: " + iptables + " -I " + rule
+		print_error(filename, lineno, reason)
+		return -1
+
+	return 0
+
+def run_test(iptables, rule, rule_save, res, filename, lineno, devnull):
+	ret = 0
+
+	cmd = iptables + " -A " + rule
+	ret = subprocess.call(cmd, stderr=devnull, shell=True)
+
+	#
+	# report failed test
+	#
+	if ret <> 0:
+		if res == "OK":
+			reason = "cannot load: " + cmd
+			print_error(filename, lineno, reason)
+			return -1
+		else:
+			# do not report this error
+			return 0
+	else:
+		if res == "FAIL":
+			reason = "should fail: " + cmd
+			print_error(filename, lineno, reason)
+			delete_rule(iptables, rule, filename, lineno, devnull)
+			return -1
+
+	matching = 0
+	proc = subprocess.Popen(iptables + "-save", 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(filename, lineno, reason)
+		delete_rule(iptables, rule, filename, lineno, devnull)
+		return -1
+
+	matching = out.find(rule_save)
+	if matching < 0:
+		reason = "cannot find: " + iptables + " -I " + rule
+		print_error(filename, lineno, reason)
+		delete_rule(iptables, rule, filename, lineno, devnull)
+		return -1
+
+	return delete_rule(iptables, rule, filename, lineno, devnull)
+
+def execute_cmd(external_cmd, devnull):
+	subprocess.call(external_cmd, stderr=devnull, shell=True)
+
+def run_test_file(filename):
+	tests = 0
+	passed = 0
+
+	#
+	# if this is not a test file, skip.
+	#
+	if filename[len(filename)-2:] <> ".t":
+		return 0, 0
+
+	if filename.find("libipt_") > 0:
+		iptables = IPTABLES
+	elif filename.find("libip6t_") > 0:
+		iptables = IP6TABLES
+	elif filename.find("libxt_") > 0:
+		iptables = IPTABLES
+	else:
+		# default to iptables if not known prefix
+		iptables = IPTABLES
+
+	f = open(filename)
+
+	lineno = 0
+	chain = ""
+	table = ""
+	external_cmd = ""
+	total_test_passed = True
+
+	# FIXME: better store standard error output in one log filename
+	devnull = open("/dev/null","w")
+
+	for line in f:
+		lineno = lineno + 1
+
+		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:]
+			execute_cmd(external_cmd, devnull)
+			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 = 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, devnull)
+			if ret < 0:
+				test_passed = False
+				total_test_passed = False
+				break
+
+		if test_passed == True:
+			passed = passed + 1
+
+	if total_test_passed == True:
+		print filename + ": " + colors.GREEN + "OK" + colors.ENDC
+
+	f.close()
+	devnull.close()
+	return tests, passed
+
+#
+# main
+#
+
+if len(sys.argv) > 2:
+	print "Usage: " + sys.argv[0] + "\t\t\tRun all test"
+	print "Usage: " + sys.argv[0] + "[path/to/file.t]\tRun test"
+	print "Usage: " + sys.argv[0] + "-M\t\t\tCheck for missing tests"
+	sys.exit()
+
+#
+# show list of missing test files
+#
+if len(sys.argv) == 2 and sys.argv[1] == "-m":
+	file_list = os.listdir(EXTENSIONS_PATH)
+	for filename in file_list:
+		if filename[-2:None] == ".t":
+			continue
+		if filename[0:3] == "lib" and filename[-2:None] == ".c":
+			#
+			# now find if there's a test for it
+			#
+			found = False
+			test_file = filename[0:-2] + ".t"
+			for x in file_list:
+				if x == test_file:
+					found = True
+					break;
+
+			if found == False:
+				print test_file
+
+	sys.exit()
+
+if os.getuid() != 0:
+	print "You need to be root to run this, sorry"
+	sys.exit()
+
+test_files = 0
+tests = 0
+passed = 0
+
+if len(sys.argv) == 2:
+	file_tests, file_passed = run_test_file(sys.argv[1])
+	tests = tests + file_tests
+	passed = passed + file_passed
+	test_files = test_files + 1
+else:
+	file_list = os.listdir(EXTENSIONS_PATH)
+	for filename in file_list:
+		file_tests, file_passed = run_test_file(EXTENSIONS_PATH + "/" + filename)
+		if file_tests:
+			tests = tests + file_tests
+			passed = passed + file_passed
+			test_files = test_files + 1
+
+print "%d test files, %d unit tests, %d passed" %(test_files, tests, passed)