aboutsummaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/.CLUSTERIP-test2
-rw-r--r--extensions/.NFLOG-test2
-rw-r--r--extensions/.NFLOG-test62
-rw-r--r--extensions/.REJECT-test64
-rw-r--r--extensions/.ah-test62
-rw-r--r--extensions/.condition-test3
-rw-r--r--extensions/.condition-test63
-rw-r--r--extensions/.connbytes-test2
-rw-r--r--extensions/.dccp-test3
-rw-r--r--extensions/.esp-test62
-rw-r--r--extensions/.frag-test62
-rw-r--r--extensions/.hashlimit-test63
-rw-r--r--extensions/.ipv6header-test62
-rw-r--r--extensions/.opts-test62
-rw-r--r--extensions/.quota-test3
-rw-r--r--extensions/.recent-test3
-rw-r--r--extensions/.rt-test62
-rw-r--r--extensions/.sctp-test63
-rw-r--r--extensions/.set-test2
-rw-r--r--extensions/.statistic-test2
-rw-r--r--extensions/.string-test2
-rw-r--r--extensions/GNUmakefile.in190
-rwxr-xr-xextensions/create_initext5
-rw-r--r--extensions/dscp_helper.c (renamed from extensions/libipt_dscp_helper.c)25
-rw-r--r--extensions/libip6t_2connmark.c151
-rw-r--r--extensions/libip6t_2hl.c149
-rw-r--r--extensions/libip6t_2mark.c142
-rw-r--r--extensions/libip6t_CONNMARK.c220
-rw-r--r--extensions/libip6t_CONNSECMARK.c124
-rw-r--r--extensions/libip6t_HL.c83
-rw-r--r--extensions/libip6t_HL.man8
-rw-r--r--extensions/libip6t_LOG.c140
-rw-r--r--extensions/libip6t_LOG.man12
-rw-r--r--extensions/libip6t_MARK.c131
-rw-r--r--extensions/libip6t_MARK.man6
-rw-r--r--extensions/libip6t_NFQUEUE.c114
-rw-r--r--extensions/libip6t_NFQUEUE.man12
-rw-r--r--extensions/libip6t_REJECT.c90
-rw-r--r--extensions/libip6t_REJECT.man29
-rw-r--r--extensions/libip6t_SECMARK.c125
-rw-r--r--extensions/libip6t_TCPMSS.c134
-rw-r--r--extensions/libip6t_TCPMSS.man42
-rw-r--r--extensions/libip6t_ah.c106
-rw-r--r--extensions/libip6t_ah.man6
-rw-r--r--extensions/libip6t_condition.c106
-rw-r--r--extensions/libip6t_condition.man4
-rw-r--r--extensions/libip6t_dst.c156
-rw-r--r--extensions/libip6t_dst.man4
-rw-r--r--extensions/libip6t_esp.c185
-rw-r--r--extensions/libip6t_esp.man3
-rw-r--r--extensions/libip6t_eui64.c75
-rw-r--r--extensions/libip6t_frag.c118
-rw-r--r--extensions/libip6t_frag.man14
-rw-r--r--extensions/libip6t_hashlimit.c369
-rw-r--r--extensions/libip6t_hbh.c164
-rw-r--r--extensions/libip6t_hbh.man4
-rw-r--r--extensions/libip6t_hl.c144
-rw-r--r--extensions/libip6t_hl.man6
-rw-r--r--extensions/libip6t_icmp6.c103
-rw-r--r--extensions/libip6t_icmp6.man6
-rw-r--r--extensions/libip6t_ipv6header.c114
-rw-r--r--extensions/libip6t_ipv6header.man58
-rw-r--r--extensions/libip6t_length.c152
-rw-r--r--extensions/libip6t_length.man4
-rw-r--r--extensions/libip6t_limit.c195
-rw-r--r--extensions/libip6t_limit.man15
-rw-r--r--extensions/libip6t_mac.c139
-rw-r--r--extensions/libip6t_mh.c240
-rw-r--r--extensions/libip6t_mh.man12
-rw-r--r--extensions/libip6t_multiport.c458
-rw-r--r--extensions/libip6t_multiport.man20
-rw-r--r--extensions/libip6t_owner.c248
-rw-r--r--extensions/libip6t_owner.man23
-rw-r--r--extensions/libip6t_physdev.c192
-rw-r--r--extensions/libip6t_policy.c478
-rw-r--r--extensions/libip6t_rt.c144
-rw-r--r--extensions/libip6t_rt.man12
-rw-r--r--extensions/libip6t_standard.c66
-rw-r--r--extensions/libip6t_state.c163
-rw-r--r--extensions/libip6t_tcp.c416
-rw-r--r--extensions/libip6t_tcp.man45
-rw-r--r--extensions/libip6t_udp.c228
-rw-r--r--extensions/libip6t_udp.man14
-rw-r--r--extensions/libipt_2connmark.c151
-rw-r--r--extensions/libipt_2dscp.c172
-rw-r--r--extensions/libipt_2mark.c143
-rw-r--r--extensions/libipt_2set.c167
-rw-r--r--extensions/libipt_2tcpmss.c152
-rw-r--r--extensions/libipt_2tos.c172
-rw-r--r--extensions/libipt_CLASSIFY.c129
-rw-r--r--extensions/libipt_CLASSIFY.man4
-rw-r--r--extensions/libipt_CLUSTERIP.c129
-rw-r--r--extensions/libipt_CLUSTERIP.man16
-rw-r--r--extensions/libipt_CONNMARK.c220
-rw-r--r--extensions/libipt_CONNMARK.man15
-rw-r--r--extensions/libipt_CONNSECMARK.c126
-rw-r--r--extensions/libipt_CONNSECMARK.man15
-rw-r--r--extensions/libipt_DNAT.c159
-rw-r--r--extensions/libipt_DNAT.man24
-rw-r--r--extensions/libipt_DSCP.c164
-rw-r--r--extensions/libipt_ECN.c98
-rw-r--r--extensions/libipt_ECN.man4
-rw-r--r--extensions/libipt_LOG.c138
-rw-r--r--extensions/libipt_LOG.man12
-rw-r--r--extensions/libipt_MARK.c243
-rw-r--r--extensions/libipt_MARK.man13
-rw-r--r--extensions/libipt_MASQUERADE.c121
-rw-r--r--extensions/libipt_MASQUERADE.man14
-rw-r--r--extensions/libipt_MIRROR.c63
-rw-r--r--extensions/libipt_NETMAP.c124
-rw-r--r--extensions/libipt_NETMAP.man2
-rw-r--r--extensions/libipt_NFLOG.c161
-rw-r--r--extensions/libipt_NFQUEUE.c114
-rw-r--r--extensions/libipt_NFQUEUE.man12
-rw-r--r--extensions/libipt_NOTRACK.c63
-rw-r--r--extensions/libipt_REDIRECT.c135
-rw-r--r--extensions/libipt_REDIRECT.man16
-rw-r--r--extensions/libipt_REJECT.c88
-rw-r--r--extensions/libipt_REJECT.man26
-rw-r--r--extensions/libipt_SAME.c153
-rw-r--r--extensions/libipt_SAME.man12
-rw-r--r--extensions/libipt_SECMARK.c125
-rw-r--r--extensions/libipt_SECMARK.man7
-rw-r--r--extensions/libipt_SET.c96
-rw-r--r--extensions/libipt_SET.man16
-rw-r--r--extensions/libipt_SNAT.c159
-rw-r--r--extensions/libipt_SNAT.man25
-rw-r--r--extensions/libipt_TCPMSS.c134
-rw-r--r--extensions/libipt_TCPMSS.man41
-rw-r--r--extensions/libipt_TOS.c174
-rw-r--r--extensions/libipt_TOS.man11
-rw-r--r--extensions/libipt_TTL.c85
-rw-r--r--extensions/libipt_TTL.man10
-rw-r--r--extensions/libipt_ULOG.c139
-rw-r--r--extensions/libipt_ULOG.man8
-rw-r--r--extensions/libipt_addrtype.c253
-rw-r--r--extensions/libipt_addrtype.man40
-rw-r--r--extensions/libipt_ah.c93
-rw-r--r--extensions/libipt_ah.man2
-rw-r--r--extensions/libipt_comment.c119
-rw-r--r--extensions/libipt_comment.man6
-rw-r--r--extensions/libipt_condition.c106
-rw-r--r--extensions/libipt_condition.man4
-rw-r--r--extensions/libipt_connbytes.c205
-rw-r--r--extensions/libipt_connbytes.man30
-rw-r--r--extensions/libipt_connmark.man9
-rw-r--r--extensions/libipt_connrate.c179
-rw-r--r--extensions/libipt_connrate.man6
-rw-r--r--extensions/libipt_conntrack.c550
-rw-r--r--extensions/libipt_conntrack.man49
-rw-r--r--extensions/libipt_dccp.c374
-rw-r--r--extensions/libipt_dccp.man12
-rw-r--r--extensions/libipt_ecn.c (renamed from extensions/libipt_2ecn.c)89
-rw-r--r--extensions/libipt_ecn.man6
-rw-r--r--extensions/libipt_esp.c193
-rw-r--r--extensions/libipt_hashlimit.c369
-rw-r--r--extensions/libipt_hashlimit.man35
-rw-r--r--extensions/libipt_helper.c101
-rw-r--r--extensions/libipt_icmp.c104
-rw-r--r--extensions/libipt_icmp.man8
-rw-r--r--extensions/libipt_iprange.c184
-rw-r--r--extensions/libipt_iprange.man7
-rw-r--r--extensions/libipt_length.c151
-rw-r--r--extensions/libipt_length.man4
-rw-r--r--extensions/libipt_limit.c196
-rw-r--r--extensions/libipt_mac.c140
-rw-r--r--extensions/libipt_mac.man10
-rw-r--r--extensions/libipt_mark.man9
-rw-r--r--extensions/libipt_multiport.c468
-rw-r--r--extensions/libipt_multiport.man20
-rw-r--r--extensions/libipt_owner.c250
-rw-r--r--extensions/libipt_owner.man28
-rw-r--r--extensions/libipt_physdev.c193
-rw-r--r--extensions/libipt_physdev.man42
-rw-r--r--extensions/libipt_pkttype.c167
-rw-r--r--extensions/libipt_pkttype.man3
-rw-r--r--extensions/libipt_policy.c436
-rw-r--r--extensions/libipt_policy.man48
-rw-r--r--extensions/libipt_quota.c107
-rw-r--r--extensions/libipt_realm.c103
-rw-r--r--extensions/libipt_realm.man2
-rw-r--r--extensions/libipt_recent.c240
-rw-r--r--extensions/libipt_recent.man93
-rw-r--r--extensions/libipt_sctp.c551
-rw-r--r--extensions/libipt_set.c160
-rw-r--r--extensions/libipt_set.h73
-rw-r--r--extensions/libipt_set.man32
-rw-r--r--extensions/libipt_standard.c69
-rw-r--r--extensions/libipt_state.c163
-rw-r--r--extensions/libipt_statistic.c175
-rw-r--r--extensions/libipt_tos.man9
-rw-r--r--extensions/libipt_ttl.c (renamed from extensions/libipt_2ttl.c)89
-rw-r--r--extensions/libipt_ttl.man6
-rw-r--r--extensions/libipt_udp.man14
-rw-r--r--extensions/libipt_unclean.c55
-rw-r--r--extensions/libxt_CLASSIFY.c115
-rw-r--r--extensions/libxt_CLASSIFY.man5
-rw-r--r--extensions/libxt_CONNMARK.c445
-rw-r--r--extensions/libxt_CONNMARK.man53
-rw-r--r--extensions/libxt_CONNSECMARK.c127
-rw-r--r--extensions/libxt_CONNSECMARK.man (renamed from extensions/libip6t_CONNSECMARK.man)4
-rw-r--r--extensions/libxt_DSCP.c149
-rw-r--r--extensions/libxt_DSCP.man (renamed from extensions/libipt_DSCP.man)4
-rw-r--r--extensions/libxt_MARK.c347
-rw-r--r--extensions/libxt_MARK.man26
-rw-r--r--extensions/libxt_NFLOG.c (renamed from extensions/libip6t_NFLOG.c)117
-rw-r--r--extensions/libxt_NFLOG.man29
-rw-r--r--extensions/libxt_NFQUEUE.c204
-rw-r--r--extensions/libxt_NFQUEUE.man18
-rw-r--r--extensions/libxt_NOTRACK.c15
-rw-r--r--extensions/libxt_NOTRACK.man (renamed from extensions/libipt_NOTRACK.man)2
-rw-r--r--extensions/libxt_RATEEST.c222
-rw-r--r--extensions/libxt_RATEEST.man12
-rw-r--r--extensions/libxt_SECMARK.c113
-rw-r--r--extensions/libxt_SECMARK.man (renamed from extensions/libip6t_SECMARK.man)4
-rw-r--r--extensions/libxt_TCPMSS.c154
-rw-r--r--extensions/libxt_TCPMSS.man50
-rw-r--r--extensions/libxt_TCPOPTSTRIP.c198
-rw-r--r--extensions/libxt_TCPOPTSTRIP.man7
-rw-r--r--extensions/libxt_TOS.c245
-rw-r--r--extensions/libxt_TOS.man27
-rw-r--r--extensions/libxt_TPROXY.c150
-rw-r--r--extensions/libxt_TPROXY.man21
-rw-r--r--extensions/libxt_TRACE.c21
-rw-r--r--extensions/libxt_TRACE.man11
-rw-r--r--extensions/libxt_cluster.c238
-rw-r--r--extensions/libxt_cluster.man62
-rw-r--r--extensions/libxt_comment.c108
-rw-r--r--extensions/libxt_comment.man6
-rw-r--r--extensions/libxt_connbytes.c199
-rw-r--r--extensions/libxt_connbytes.man36
-rw-r--r--extensions/libxt_connlimit.c216
-rw-r--r--extensions/libxt_connlimit.man27
-rw-r--r--extensions/libxt_connmark.c205
-rw-r--r--extensions/libxt_connmark.man6
-rw-r--r--extensions/libxt_conntrack.c1235
-rw-r--r--extensions/libxt_conntrack.man81
-rw-r--r--extensions/libxt_dccp.c354
-rw-r--r--extensions/libxt_dccp.man12
-rw-r--r--extensions/libxt_dscp.c150
-rw-r--r--extensions/libxt_dscp.man (renamed from extensions/libipt_dscp.man)8
-rw-r--r--extensions/libxt_esp.c168
-rw-r--r--extensions/libxt_esp.man (renamed from extensions/libipt_esp.man)2
-rw-r--r--extensions/libxt_hashlimit.c713
-rw-r--r--extensions/libxt_hashlimit.man59
-rw-r--r--extensions/libxt_helper.c87
-rw-r--r--extensions/libxt_helper.man (renamed from extensions/libipt_helper.man)4
-rw-r--r--extensions/libxt_iprange.c385
-rw-r--r--extensions/libxt_iprange.man7
-rw-r--r--extensions/libxt_length.c133
-rw-r--r--extensions/libxt_length.man5
-rw-r--r--extensions/libxt_limit.c177
-rw-r--r--extensions/libxt_limit.man (renamed from extensions/libipt_limit.man)4
-rw-r--r--extensions/libxt_mac.c131
-rw-r--r--extensions/libxt_mac.man (renamed from extensions/libip6t_mac.man)2
-rw-r--r--extensions/libxt_mark.c185
-rw-r--r--extensions/libxt_mark.man (renamed from extensions/libip6t_mark.man)2
-rw-r--r--extensions/libxt_multiport.c574
-rw-r--r--extensions/libxt_multiport.man23
-rw-r--r--extensions/libxt_osf.c155
-rw-r--r--extensions/libxt_owner.c614
-rw-r--r--extensions/libxt_owner.man19
-rw-r--r--extensions/libxt_physdev.c180
-rw-r--r--extensions/libxt_physdev.man (renamed from extensions/libip6t_physdev.man)16
-rw-r--r--extensions/libxt_pkttype.c158
-rw-r--r--extensions/libxt_pkttype.man3
-rw-r--r--extensions/libxt_policy.c513
-rw-r--r--extensions/libxt_policy.man (renamed from extensions/libip6t_policy.man)26
-rw-r--r--extensions/libxt_quota.c92
-rw-r--r--extensions/libxt_quota.man (renamed from extensions/libipt_quota.man)3
-rw-r--r--extensions/libxt_rateest.c451
-rw-r--r--extensions/libxt_rateest.man55
-rw-r--r--extensions/libxt_recent.c233
-rw-r--r--extensions/libxt_recent.man104
-rw-r--r--extensions/libxt_sctp.c (renamed from extensions/libip6t_sctp.c)170
-rw-r--r--extensions/libxt_sctp.man (renamed from extensions/libipt_sctp.man)12
-rw-r--r--extensions/libxt_socket.c19
-rw-r--r--extensions/libxt_socket.man2
-rw-r--r--extensions/libxt_standard.c24
-rw-r--r--extensions/libxt_state.c158
-rw-r--r--extensions/libxt_state.man (renamed from extensions/libipt_state.man)2
-rw-r--r--extensions/libxt_statistic.c180
-rw-r--r--extensions/libxt_statistic.man30
-rw-r--r--extensions/libxt_string.c (renamed from extensions/libipt_string.c)233
-rw-r--r--extensions/libxt_string.man (renamed from extensions/libipt_string.man)11
-rw-r--r--extensions/libxt_tcp.c (renamed from extensions/libipt_tcp.c)189
-rw-r--r--extensions/libxt_tcp.man (renamed from extensions/libipt_tcp.man)31
-rw-r--r--extensions/libxt_tcpmss.c128
-rw-r--r--extensions/libxt_tcpmss.man (renamed from extensions/libipt_tcpmss.man)2
-rw-r--r--extensions/libxt_time.c485
-rw-r--r--extensions/libxt_time.man69
-rw-r--r--extensions/libxt_tos.c178
-rw-r--r--extensions/libxt_tos.man12
-rw-r--r--extensions/libxt_u32.c284
-rw-r--r--extensions/libxt_u32.man129
-rw-r--r--extensions/libxt_udp.c (renamed from extensions/libipt_udp.c)127
-rw-r--r--extensions/libxt_udp.man14
-rw-r--r--extensions/matches4.man1205
-rw-r--r--extensions/matches6.man1060
-rwxr-xr-xextensions/rename-dups.sh17
-rw-r--r--extensions/targets4.man651
-rw-r--r--extensions/targets6.man288
-rw-r--r--extensions/tos_values.c96
303 files changed, 19139 insertions, 16619 deletions
diff --git a/extensions/.CLUSTERIP-test b/extensions/.CLUSTERIP-test
deleted file mode 100644
index 6d0017a..0000000
--- a/extensions/.CLUSTERIP-test
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/net/ipv4/netfilter/ipt_CLUSTERIP.c ] && echo CLUSTERIP
diff --git a/extensions/.NFLOG-test b/extensions/.NFLOG-test
deleted file mode 100644
index 25f0dee..0000000
--- a/extensions/.NFLOG-test
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter/xt_NFLOG.h ] && echo NFLOG
diff --git a/extensions/.NFLOG-test6 b/extensions/.NFLOG-test6
deleted file mode 100644
index 25f0dee..0000000
--- a/extensions/.NFLOG-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter/xt_NFLOG.h ] && echo NFLOG
diff --git a/extensions/.REJECT-test6 b/extensions/.REJECT-test6
deleted file mode 100644
index 1f09694..0000000
--- a/extensions/.REJECT-test6
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-FILE=$KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_REJECT.h
-# True if REJECT is applied.
-[ -f $FILE ] && grep IP6T_ICMP6_NO_ROUTE 2>&1 >/dev/null $FILE && echo REJECT
diff --git a/extensions/.ah-test6 b/extensions/.ah-test6
deleted file mode 100644
index 1812c56..0000000
--- a/extensions/.ah-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_ah.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_ah.h ] && echo ah
diff --git a/extensions/.condition-test b/extensions/.condition-test
deleted file mode 100644
index 20f3bc7..0000000
--- a/extensions/.condition-test
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if condition is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_condition.h ] && echo condition
diff --git a/extensions/.condition-test6 b/extensions/.condition-test6
deleted file mode 100644
index f4af61f..0000000
--- a/extensions/.condition-test6
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if condition6 is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_condition.h ] && echo condition
diff --git a/extensions/.connbytes-test b/extensions/.connbytes-test
deleted file mode 100644
index 61355d0..0000000
--- a/extensions/.connbytes-test
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_connbytes.h ] && echo connbytes
diff --git a/extensions/.dccp-test b/extensions/.dccp-test
deleted file mode 100644
index 5b67527..0000000
--- a/extensions/.dccp-test
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if dccp is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_dccp.h ] && echo dccp
diff --git a/extensions/.esp-test6 b/extensions/.esp-test6
deleted file mode 100644
index 7ded945..0000000
--- a/extensions/.esp-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_esp.h ] && echo esp
diff --git a/extensions/.frag-test6 b/extensions/.frag-test6
deleted file mode 100644
index ff3650d..0000000
--- a/extensions/.frag-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_frag.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_frag.h ] && echo frag
diff --git a/extensions/.hashlimit-test6 b/extensions/.hashlimit-test6
deleted file mode 100644
index 9a2a465..0000000
--- a/extensions/.hashlimit-test6
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter/xt_hashlimit.h ] && echo hashlimit
-
diff --git a/extensions/.ipv6header-test6 b/extensions/.ipv6header-test6
deleted file mode 100644
index 47f6f06..0000000
--- a/extensions/.ipv6header-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_ipv6header.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_ipv6header.h ] && echo ipv6header
diff --git a/extensions/.opts-test6 b/extensions/.opts-test6
deleted file mode 100644
index 1ed2013..0000000
--- a/extensions/.opts-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_hbh.c -a -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_dst.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_opts.h ] && echo hbh dst
diff --git a/extensions/.quota-test b/extensions/.quota-test
deleted file mode 100644
index b21058c..0000000
--- a/extensions/.quota-test
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter/xt_quota.h ] && echo quota
-
diff --git a/extensions/.recent-test b/extensions/.recent-test
deleted file mode 100644
index 2a47fc9..0000000
--- a/extensions/.recent-test
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-# True if recent match patch is applied.
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_recent.h ] && echo recent
diff --git a/extensions/.rt-test6 b/extensions/.rt-test6
deleted file mode 100644
index e8d5855..0000000
--- a/extensions/.rt-test6
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_rt.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_rt.h ] && echo rt
diff --git a/extensions/.sctp-test6 b/extensions/.sctp-test6
deleted file mode 100644
index 3cfc7b8..0000000
--- a/extensions/.sctp-test6
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter/xt_sctp.h ] && echo sctp
-
diff --git a/extensions/.set-test b/extensions/.set-test
deleted file mode 100644
index 700a73c..0000000
--- a/extensions/.set-test
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ip_set.h ] && echo set SET
diff --git a/extensions/.statistic-test b/extensions/.statistic-test
deleted file mode 100644
index 843cb41..0000000
--- a/extensions/.statistic-test
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-[ -f $KERNEL_DIR/net/netfilter/xt_statistic.c -a -f $KERNEL_DIR/include/linux/netfilter/xt_statistic.h ] && echo statistic
diff --git a/extensions/.string-test b/extensions/.string-test
deleted file mode 100644
index 609f1c2..0000000
--- a/extensions/.string-test
+++ /dev/null
@@ -1,2 +0,0 @@
-#! /bin/sh
-[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_string.h ] && echo string
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
new file mode 100644
index 0000000..709366a
--- /dev/null
+++ b/extensions/GNUmakefile.in
@@ -0,0 +1,190 @@
+# -*- Makefile -*-
+
+top_builddir := @top_builddir@
+builddir := @builddir@
+top_srcdir := @top_srcdir@
+srcdir := @srcdir@
+ksourcedir := @ksourcedir@
+prefix := @prefix@
+exec_prefix := @exec_prefix@
+libdir := @libdir@
+libexecdir := @libexecdir@
+xtlibdir := @xtlibdir@
+
+CC := @CC@
+CCLD := ${CC}
+CFLAGS := @CFLAGS@
+LDFLAGS := @LDFLAGS@
+regular_CFLAGS := @regular_CFLAGS@
+kinclude_CFLAGS := @kinclude_CFLAGS@
+
+AM_CFLAGS := ${regular_CFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CFLAGS}
+AM_DEPFLAGS = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
+
+ifeq (${V},)
+AM_LIBTOOL_SILENT = --silent
+AM_VERBOSE_CC = @echo " CC " $@;
+AM_VERBOSE_CCLD = @echo " CCLD " $@;
+AM_VERBOSE_CXX = @echo " CXX " $@;
+AM_VERBOSE_CXXLD = @echo " CXXLD " $@;
+AM_VERBOSE_AR = @echo " AR " $@;
+AM_VERBOSE_GEN = @echo " GEN " $@;
+endif
+
+#
+# Wildcard module list
+#
+pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(wildcard ${srcdir}/libxt_*.c))
+@ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(wildcard ${srcdir}/libipt_*.c))
+@ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(wildcard ${srcdir}/libip6t_*.c))
+pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod})
+pf4_build_mod := $(filter-out @blacklist_modules@,${pf4_build_mod})
+pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod})
+pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
+pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
+pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
+pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
+pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
+pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
+
+
+#
+# Building blocks
+#
+targets := libext4.a libext6.a matches4.man matches6.man \
+ targets4.man targets6.man
+targets_install :=
+@ENABLE_STATIC_TRUE@ libext4_objs := ${pfx_objs} ${pf4_objs}
+@ENABLE_STATIC_TRUE@ libext6_objs := ${pfx_objs} ${pf6_objs}
+@ENABLE_STATIC_FALSE@ targets += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
+@ENABLE_STATIC_FALSE@ targets_install += ${pfx_solibs} ${pf4_solibs} ${pf6_solibs}
+
+.SECONDARY:
+
+.PHONY: all install clean distclean FORCE
+
+all: ${targets}
+
+install: ${targets_install}
+ @mkdir -p "${DESTDIR}${xtlibdir}";
+ if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi;
+
+clean:
+ rm -f *.o *.oo *.so *.a {matches,targets}[46].man initext4.c initext6.c;
+
+distclean: clean
+ rm -f .*.d .*.dd;
+
+init%.o: init%.c
+ ${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
+
+-include .*.d
+
+
+#
+# Shared libraries
+#
+lib%.so: lib%.oo
+ ${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
+
+lib%.oo: ${srcdir}/lib%.c
+ ${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
+
+
+#
+# Static bits
+#
+# If static building is disabled, libext*.a will still be generated,
+# but will be empty. This is good since we can do with less case
+# handling code in the Makefiles.
+#
+lib%.o: ${srcdir}/lib%.c
+ ${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
+
+libext4.a: initext4.o ${libext4_objs}
+ ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+
+libext6.a: initext6.o ${libext6_objs}
+ ${AM_VERBOSE_AR} ${AR} crs $@ $^;
+
+initext_func := $(addprefix xt_,${pfx_build_mod}) $(addprefix ipt_,${pf4_build_mod})
+initext6_func := $(addprefix xt_,${pfx_build_mod}) $(addprefix ip6t_,${pf6_build_mod})
+
+.initext4.dd: FORCE
+ @echo "${initext_func}" >$@.tmp; \
+ cmp -s $@ $@.tmp || mv $@.tmp $@; \
+ rm -f $@.tmp;
+
+.initext6.dd: FORCE
+ @echo "${initext6_func}" >$@.tmp; \
+ cmp -s $@ $@.tmp || mv $@.tmp $@; \
+ rm -f $@.tmp;
+
+initext4.c: .initext4.dd
+ ${AM_VERBOSE_GEN}
+ @( \
+ echo "" >$@; \
+ for i in ${initext_func}; do \
+ echo "extern void lib$${i}_init(void);" >>$@; \
+ done; \
+ echo "void init_extensions(void);" >>$@; \
+ echo "void init_extensions(void)" >>$@; \
+ echo "{" >>$@; \
+ for i in ${initext_func}; do \
+ echo " ""lib$${i}_init();" >>$@; \
+ done; \
+ echo "}" >>$@; \
+ );
+
+initext6.c: .initext6.dd
+ ${AM_VERBOSE_GEN}
+ @( \
+ echo "" >$@; \
+ for i in ${initext6_func}; do \
+ echo "extern void lib$${i}_init(void);" >>$@; \
+ done; \
+ echo "void init_extensions(void);" >>$@; \
+ echo "void init_extensions(void)" >>$@; \
+ echo "{" >>$@; \
+ for i in ${initext6_func}; do \
+ echo " ""lib$${i}_init();" >>$@; \
+ done; \
+ echo "}" >>$@; \
+ );
+
+#
+# Manual pages
+#
+ex_matches = $(sort $(shell echo $(1) | grep -Eo '\b[a-z0-9]+\b'))
+ex_targets = $(sort $(shell echo $(1) | grep -Eo '\b[A-Z0-9]+\b'))
+man_run = \
+ ${AM_VERBOSE_GEN} \
+ for ext in $(1); do \
+ f="${srcdir}/libxt_$$ext.man"; \
+ cf="${srcdir}/libxt_$$ext.c"; \
+ if [ -f "$$f" ] && grep -Eq "$(3)|NFPROTO_UNSPEC" "$$cf"; then \
+ echo -e "\t+ $$f" >&2; \
+ echo ".SS $$ext"; \
+ cat "$$f"; \
+ continue; \
+ fi; \
+ f="${srcdir}/lib$(2)t_$$ext.man"; \
+ if [ -f "$$f" ]; then \
+ echo -e "\t+ $$f" >&2; \
+ echo ".SS $$ext"; \
+ cat "$$f"; \
+ continue; \
+ fi; \
+ done >$@;
+
+matches4.man: .initext4.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4)
+
+matches6.man: .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6)
+
+targets4.man: .initext4.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4)
+
+targets6.man: .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6)
diff --git a/extensions/create_initext b/extensions/create_initext
index 686ba04..2d39235 100755
--- a/extensions/create_initext
+++ b/extensions/create_initext
@@ -1,11 +1,12 @@
#!/bin/sh
echo ""
for i in $1; do
- echo "extern void ${i}_init(void);";
+ echo "extern void lib${i}_init(void);";
done;
+echo "void init_extensions(void);";
echo "void init_extensions(void) {"
for i in $1; do
- echo " ${i}_init();";
+ echo " lib${i}_init();";
done
echo "}"
diff --git a/extensions/libipt_dscp_helper.c b/extensions/dscp_helper.c
index 31adb6c..75b1fec 100644
--- a/extensions/libipt_dscp_helper.c
+++ b/extensions/dscp_helper.c
@@ -5,21 +5,20 @@
* <http://www.iana.org/assignments/dscp-registry>
*
* This code is released under the GNU GPL v2, 1991
- *
+ *
* Author: Iain Barnes
*/
#include <stdio.h>
#include <string.h>
-#include <iptables_common.h>
-
+#include <xtables.h>
-static struct ds_class
+static const struct ds_class
{
const char *name;
unsigned int dscp;
-} ds_classes[] =
+} ds_classes[] =
{
{ "CS0", 0x00 },
{ "CS1", 0x08 },
@@ -47,18 +46,18 @@ static struct ds_class
-static unsigned int
+static unsigned int
class_to_dscp(const char *name)
{
- int i;
+ unsigned int i;
- for (i = 0; i < sizeof(ds_classes) / sizeof(struct ds_class); i++) {
+ for (i = 0; i < ARRAY_SIZE(ds_classes); i++) {
if (!strncasecmp(name, ds_classes[i].name,
- strlen(ds_classes[i].name)))
+ strlen(ds_classes[i].name)))
return ds_classes[i].dscp;
}
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid DSCP value `%s'\n", name);
}
@@ -69,13 +68,11 @@ dscp_to_name(unsigned int dscp)
{
int i;
- for (i = 0; i < sizeof(ds_classes) / sizeof(struct ds_class); i++) {
+ for (i = 0; i < ARRAY_SIZE(ds_classes); ++i)
if (dscp == ds_classes[i].dscp)
return ds_classes[i].name;
- }
-
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid DSCP value `%d'\n", dscp);
}
#endif
diff --git a/extensions/libip6t_2connmark.c b/extensions/libip6t_2connmark.c
deleted file mode 100644
index 609c8e9..0000000
--- a/extensions/libip6t_2connmark.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Shared library add-on to iptables to add connmark matching support.
- *
- * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
- *
- * Version 1.1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include "../include/linux/netfilter_ipv4/ipt_2connmark.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"CONNMARK match v%s options:\n"
-"[!] --mark value[/mask] Match nfmark value with optional mask\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mark", 1, 0, '1' },
- {0}
-};
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- /* Can't cache this. */
- *nfcache |= NFC_UNKNOWN;
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ipt_connmark_info *markinfo = (struct ipt_connmark_info *)(*match)->data;
-
- switch (c) {
- char *end;
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-
- markinfo->mark = strtoul(optarg, &end, 0);
- markinfo->mask = 0xffffffffUL;
-
- if (*end == '/')
- markinfo->mask = strtoul(end+1, &end, 0);
-
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (invert)
- markinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_mark(unsigned long mark, unsigned long mask, int numeric)
-{
- if(mask != 0xffffffffUL)
- printf("0x%lx/0x%lx ", mark, mask);
- else
- printf("0x%lx ", mark);
-}
-
-/* Final check; must have specified --mark. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK match: You must specify `--mark'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
-
- printf("CONNMARK match ");
- if (info->invert)
- printf("!");
- print_mark(info->mark, info->mask, numeric);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
-
- if (info->invert)
- printf("! ");
-
- printf("--mark ");
- print_mark(info->mark, info->mask, 0);
-}
-
-static struct ip6tables_match connmark_match = {
- .name = "connmark",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ipt_connmark_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connmark_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_match6(&connmark_match);
-}
diff --git a/extensions/libip6t_2hl.c b/extensions/libip6t_2hl.c
deleted file mode 100644
index 208da33..0000000
--- a/extensions/libip6t_2hl.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * IPv6 Hop Limit matching module
- * Maciej Soltysiak <solt@dns.toxicfilms.tv>
- * Based on HW's ttl match
- * This program is released under the terms of GNU GPL
- * Cleanups by Stephane Ouellette <ouellettes@videotron.ca>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <ip6tables.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_hl.h>
-
-static void help(void)
-{
- printf(
-"HL match v%s options:\n"
-" --hl-eq [!] value Match hop limit value\n"
-" --hl-lt value Match HL < value\n"
-" --hl-gt value Match HL > value\n"
-, IPTABLES_VERSION);
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry, unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_hl_info *info = (struct ip6t_hl_info *) (*match)->data;
- u_int8_t value;
-
- check_inverse(optarg, &invert, &optind, 0);
- value = atoi(argv[optind-1]);
-
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify HL option twice");
-
- if (!optarg)
- exit_error(PARAMETER_PROBLEM,
- "hl: You must specify a value");
- switch (c) {
- case '2':
- if (invert)
- info->mode = IP6T_HL_NE;
- else
- info->mode = IP6T_HL_EQ;
-
- /* is 0 allowed? */
- info->hop_limit = value;
- *flags = 1;
-
- break;
- case '3':
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "hl: unexpected `!'");
-
- info->mode = IP6T_HL_LT;
- info->hop_limit = value;
- *flags = 1;
-
- break;
- case '4':
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "hl: unexpected `!'");
-
- info->mode = IP6T_HL_GT;
- info->hop_limit = value;
- *flags = 1;
-
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "HL match: You must specify one of "
- "`--hl-eq', `--hl-lt', `--hl-gt'");
-}
-
-static void print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- static const char *op[] = {
- [IP6T_HL_EQ] = "==",
- [IP6T_HL_NE] = "!=",
- [IP6T_HL_LT] = "<",
- [IP6T_HL_GT] = ">" };
-
- const struct ip6t_hl_info *info =
- (struct ip6t_hl_info *) match->data;
-
- printf("HL match HL %s %u ", op[info->mode], info->hop_limit);
-}
-
-static void save(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match)
-{
- static const char *op[] = {
- [IP6T_HL_EQ] = "eq",
- [IP6T_HL_NE] = "eq !",
- [IP6T_HL_LT] = "lt",
- [IP6T_HL_GT] = "gt" };
-
- const struct ip6t_hl_info *info =
- (struct ip6t_hl_info *) match->data;
-
- printf("--hl-%s %u ", op[info->mode], info->hop_limit);
-}
-
-static struct option opts[] = {
- { .name = "hl", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "hl-eq", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "hl-lt", .has_arg = 1, .flag = 0, .val = '3' },
- { .name = "hl-gt", .has_arg = 1, .flag = 0, .val = '4' },
- { 0 }
-};
-
-static
-struct ip6tables_match hl = {
- .name = "hl",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_hl_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_hl_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-
-void _init(void)
-{
- register_match6(&hl);
-}
diff --git a/extensions/libip6t_2mark.c b/extensions/libip6t_2mark.c
deleted file mode 100644
index b831cfe..0000000
--- a/extensions/libip6t_2mark.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* Shared library add-on to ip6tables to add NFMARK matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv6/ip6t_mark.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MARK match v%s options:\n"
-"[!] --mark value[/mask] Match nfmark value with optional mask\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mark", 1, 0, '1' },
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_mark_info *markinfo = (struct ip6t_mark_info *)(*match)->data;
-
- switch (c) {
- char *end;
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-#ifdef KERNEL_64_USERSPACE_32
- markinfo->mark = strtoull(optarg, &end, 0);
- if (*end == '/') {
- markinfo->mask = strtoull(end+1, &end, 0);
- } else
- markinfo->mask = 0xffffffffffffffffULL;
-#else
- markinfo->mark = strtoul(optarg, &end, 0);
- if (*end == '/') {
- markinfo->mask = strtoul(end+1, &end, 0);
- } else
- markinfo->mask = 0xffffffff;
-#endif
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (invert)
- markinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-#ifdef KERNEL_64_USERSPACE_32
-static void
-print_mark(unsigned long long mark, unsigned long long mask, int numeric)
-{
- if(mask != 0xffffffffffffffffULL)
- printf("0x%llx/0x%llx ", mark, mask);
- else
- printf("0x%llx ", mark);
-}
-#else
-static void
-print_mark(unsigned long mark, unsigned long mask, int numeric)
-{
- if(mask != 0xffffffff)
- printf("0x%lx/0x%lx ", mark, mask);
- else
- printf("0x%lx ", mark);
-}
-#endif
-
-/* Final check; must have specified --mark. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK match: You must specify `--mark'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct ip6t_mark_info *info = (struct ip6t_mark_info *)match->data;
-
- printf("MARK match ");
-
- if (info->invert)
- printf("!");
-
- print_mark(info->mark, info->mask, numeric);
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct ip6t_mark_info *info = (struct ip6t_mark_info *)match->data;
-
- if (info->invert)
- printf("! ");
-
- printf("--mark ");
- print_mark(info->mark, info->mask, 0);
-}
-
-static struct ip6tables_match mark = {
- .name = "mark",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_mark_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_mark_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_match6(&mark);
-}
diff --git a/extensions/libip6t_CONNMARK.c b/extensions/libip6t_CONNMARK.c
deleted file mode 100644
index 9506f26..0000000
--- a/extensions/libip6t_CONNMARK.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* Shared library add-on to iptables to add CONNMARK target support.
- *
- * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
- *
- * Version 1.1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include "../include/linux/netfilter_ipv4/ipt_CONNMARK.h"
-
-#if 0
-struct markinfo {
- struct ipt_entry_target t;
- struct ipt_connmark_target_info mark;
-};
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"CONNMARK target v%s options:\n"
-" --set-mark value[/mask] Set conntrack mark value\n"
-" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
-" --restore-mark [--mask mask] Restore saved nfmark value\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "set-mark", 1, 0, '1' },
- { "save-mark", 0, 0, '2' },
- { "restore-mark", 0, 0, '3' },
- { "mask", 1, 0, '4' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
-{
- struct ipt_connmark_target_info *markinfo
- = (struct ipt_connmark_target_info *)(*target)->data;
-
- markinfo->mask = 0xffffffffUL;
-
- switch (c) {
- char *end;
- case '1':
- markinfo->mode = IPT_CONNMARK_SET;
-
- markinfo->mark = strtoul(optarg, &end, 0);
- if (*end == '/' && end[1] != '\0')
- markinfo->mask = strtoul(end+1, &end, 0);
-
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --set-mark twice");
- *flags = 1;
- break;
- case '2':
- markinfo->mode = IPT_CONNMARK_SAVE;
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --save-mark twice");
- *flags = 1;
- break;
- case '3':
- markinfo->mode = IPT_CONNMARK_RESTORE;
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --restore-mark twice");
- *flags = 1;
- break;
- case '4':
- if (!*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --mask without a operation");
- markinfo->mask = strtoul(optarg, &end, 0);
-
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MASK value `%s'", optarg);
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: No operation specified");
-}
-
-static void
-print_mark(unsigned long mark)
-{
- printf("0x%lx", mark);
-}
-
-static void
-print_mask(const char *text, unsigned long mask)
-{
- if (mask != 0xffffffffUL)
- printf("%s0x%lx", text, mask);
-}
-
-
-/* Prints out the target info. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target,
- int numeric)
-{
- const struct ipt_connmark_target_info *markinfo =
- (const struct ipt_connmark_target_info *)target->data;
- switch (markinfo->mode) {
- case IPT_CONNMARK_SET:
- printf("CONNMARK set ");
- print_mark(markinfo->mark);
- print_mask("/", markinfo->mask);
- printf(" ");
- break;
- case IPT_CONNMARK_SAVE:
- printf("CONNMARK save ");
- print_mask("mask ", markinfo->mask);
- printf(" ");
- break;
- case IPT_CONNMARK_RESTORE:
- printf("CONNMARK restore ");
- print_mask("mask ", markinfo->mask);
- break;
- default:
- printf("ERROR: UNKNOWN CONNMARK MODE ");
- break;
- }
-}
-
-/* Saves the target into in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
-{
- const struct ipt_connmark_target_info *markinfo =
- (const struct ipt_connmark_target_info *)target->data;
-
- switch (markinfo->mode) {
- case IPT_CONNMARK_SET:
- printf("--set-mark ");
- print_mark(markinfo->mark);
- print_mask("/", markinfo->mask);
- printf(" ");
- break;
- case IPT_CONNMARK_SAVE:
- printf("--save-mark ");
- print_mask("--mask ", markinfo->mask);
- break;
- case IPT_CONNMARK_RESTORE:
- printf("--restore-mark ");
- print_mask("--mask ", markinfo->mask);
- break;
- default:
- printf("ERROR: UNKNOWN CONNMARK MODE ");
- break;
- }
-}
-
-static struct ip6tables_target connmark_target = {
- .name = "CONNMARK",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ipt_connmark_target_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ipt_connmark_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_target6(&connmark_target);
-}
diff --git a/extensions/libip6t_CONNSECMARK.c b/extensions/libip6t_CONNSECMARK.c
deleted file mode 100644
index b11ed07..0000000
--- a/extensions/libip6t_CONNSECMARK.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Shared library add-on to ip6tables to add CONNSECMARK target support.
- *
- * Based on the MARK and CONNMARK targets.
- *
- * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter/xt_CONNSECMARK.h>
-
-#define PFX "CONNSECMARK target: "
-
-static void help(void)
-{
- printf(
-"CONNSECMARK target v%s options:\n"
-" --save Copy security mark from packet to conntrack\n"
-" --restore Copy security mark from connection to packet\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "save", 0, 0, '1' },
- { "restore", 0, 0, '2' },
- { 0 }
-};
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry, struct ip6t_entry_target **target)
-{
- struct xt_connsecmark_target_info *info =
- (struct xt_connsecmark_target_info*)(*target)->data;
-
- switch (c) {
- case '1':
- if (*flags & CONNSECMARK_SAVE)
- exit_error(PARAMETER_PROBLEM, PFX
- "Can't specify --save twice");
- info->mode = CONNSECMARK_SAVE;
- *flags |= CONNSECMARK_SAVE;
- break;
-
- case '2':
- if (*flags & CONNSECMARK_RESTORE)
- exit_error(PARAMETER_PROBLEM, PFX
- "Can't specify --restore twice");
- info->mode = CONNSECMARK_RESTORE;
- *flags |= CONNSECMARK_RESTORE;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, PFX "parameter required");
-
- if (flags == (CONNSECMARK_SAVE|CONNSECMARK_RESTORE))
- exit_error(PARAMETER_PROBLEM, PFX "only one flag of --save "
- "or --restore is allowed");
-}
-
-static void print_connsecmark(struct xt_connsecmark_target_info *info)
-{
- switch (info->mode) {
- case CONNSECMARK_SAVE:
- printf("save ");
- break;
-
- case CONNSECMARK_RESTORE:
- printf("restore ");
- break;
-
- default:
- exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
- }
-}
-
-static void print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target, int numeric)
-{
- struct xt_connsecmark_target_info *info =
- (struct xt_connsecmark_target_info*)(target)->data;
-
- printf("CONNSECMARK ");
- print_connsecmark(info);
-}
-
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
-{
- struct xt_connsecmark_target_info *info =
- (struct xt_connsecmark_target_info*)target->data;
-
- printf("--");
- print_connsecmark(info);
-}
-
-static struct ip6tables_target connsecmark = {
- .name = "CONNSECMARK",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct xt_connsecmark_target_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct xt_connsecmark_target_info)),
- .parse = &parse,
- .help = &help,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_target6(&connsecmark);
-}
diff --git a/extensions/libip6t_HL.c b/extensions/libip6t_HL.c
index 2062828..bff0611 100644
--- a/extensions/libip6t_HL.c
+++ b/extensions/libip6t_HL.c
@@ -5,53 +5,46 @@
* This program is distributed under the terms of GNU GPL
*/
+#include <getopt.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
+#include <xtables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_HL.h>
#define IP6T_HL_USED 1
-static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void help(void)
+static void HL_help(void)
{
printf(
-"HL target v%s options\n"
+"HL target options\n"
" --hl-set value Set HL to <value 0-255>\n"
" --hl-dec value Decrement HL by <value 1-255>\n"
-" --hl-inc value Increment HL by <value 1-255>\n"
-, IPTABLES_VERSION);
+" --hl-inc value Increment HL by <value 1-255>\n");
}
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
+static int HL_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ip6t_HL_info *info = (struct ip6t_HL_info *) (*target)->data;
unsigned int value;
if (*flags & IP6T_HL_USED) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify HL option twice");
}
if (!optarg)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"HL: You must specify a value");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"HL: unexpected `!'");
- if (string_to_number(optarg, 0, 255, &value) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"HL: Expected value between 0 and 255");
switch (c) {
@@ -62,7 +55,7 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
case '2':
if (value == 0) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"HL: decreasing by 0?");
}
@@ -71,7 +64,7 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (value == 0) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"HL: increasing by 0?");
}
@@ -89,15 +82,14 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void final_check(unsigned int flags)
+static void HL_check(unsigned int flags)
{
if (!(flags & IP6T_HL_USED))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"HL: You must specify an action");
}
-static void save(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target)
+static void HL_save(const void *ip, const struct xt_entry_target *target)
{
const struct ip6t_HL_info *info =
(struct ip6t_HL_info *) target->data;
@@ -117,8 +109,8 @@ static void save(const struct ip6t_ip6 *ip,
printf("%u ", info->hop_limit);
}
-static void print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target, int numeric)
+static void HL_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ip6t_HL_info *info =
(struct ip6t_HL_info *) target->data;
@@ -138,29 +130,28 @@ static void print(const struct ip6t_ip6 *ip,
printf("%u ", info->hop_limit);
}
-static struct option opts[] = {
- { "hl-set", 1, 0, '1' },
- { "hl-dec", 1, 0, '2' },
- { "hl-inc", 1, 0, '3' },
- { 0 }
+static const struct option HL_opts[] = {
+ { "hl-set", 1, NULL, '1' },
+ { "hl-dec", 1, NULL, '2' },
+ { "hl-inc", 1, NULL, '3' },
+ { .name = NULL }
};
-static
-struct ip6tables_target HL = { NULL,
+static struct xtables_target hl_tg6_reg = {
.name = "HL",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_HL_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_HL_info)),
+ .help = HL_help,
+ .parse = HL_parse,
+ .final_check = HL_check,
+ .print = HL_print,
+ .save = HL_save,
+ .extra_opts = HL_opts,
};
void _init(void)
{
- register_target6(&HL);
+ xtables_register_target(&hl_tg6_reg);
}
diff --git a/extensions/libip6t_HL.man b/extensions/libip6t_HL.man
index bf46881..0f3afb1 100644
--- a/extensions/libip6t_HL.man
+++ b/extensions/libip6t_HL.man
@@ -4,14 +4,14 @@ Hop Limit field can potentially be very dangerous, so it should be avoided at
any cost. This target is only valid in
.B mangle
table.
-.TP
+.PP
.B Don't ever set or increment the value on packets that leave your local network!
.TP
-.BI "--hl-set " "value"
+\fB\-\-hl\-set\fP \fIvalue\fP
Set the Hop Limit to `value'.
.TP
-.BI "--hl-dec " "value"
+\fB\-\-hl\-dec\fP \fIvalue\fP
Decrement the Hop Limit `value' times.
.TP
-.BI "--hl-inc " "value"
+\fB\-\-hl\-inc\fP \fIvalue\fP
Increment the Hop Limit `value' times.
diff --git a/extensions/libip6t_LOG.c b/extensions/libip6t_LOG.c
index 5043b44..423d988 100644
--- a/extensions/libip6t_LOG.c
+++ b/extensions/libip6t_LOG.c
@@ -1,12 +1,11 @@
-/* Shared library add-on to iptables to add LOG support. */
+/* Shared library add-on to ip6tables to add LOG support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h>
#ifndef IP6T_LOG_UID /* Old kernel */
@@ -17,34 +16,29 @@
#define LOG_DEFAULT_LEVEL LOG_WARNING
-/* Function which prints out usage message. */
-static void
-help(void)
+static void LOG_help(void)
{
printf(
-"LOG v%s options:\n"
+"LOG target options:\n"
" --log-level level Level of logging (numeric or see syslog.conf)\n"
-" --log-prefix prefix Prefix log messages with this prefix.\n\n"
-" --log-tcp-sequence Log TCP sequence numbers.\n\n"
-" --log-tcp-options Log TCP options.\n\n"
-" --log-ip-options Log IP options.\n\n"
-" --log-uid Log UID owning the local socket.\n\n",
-IPTABLES_VERSION);
+" --log-prefix prefix Prefix log messages with this prefix.\n"
+" --log-tcp-sequence Log TCP sequence numbers.\n"
+" --log-tcp-options Log TCP options.\n"
+" --log-ip-options Log IP options.\n"
+" --log-uid Log UID owning the local socket.\n");
}
-static struct option opts[] = {
- { .name = "log-level", .has_arg = 1, .flag = 0, .val = '!' },
- { .name = "log-prefix", .has_arg = 1, .flag = 0, .val = '#' },
- { .name = "log-tcp-sequence", .has_arg = 0, .flag = 0, .val = '1' },
- { .name = "log-tcp-options", .has_arg = 0, .flag = 0, .val = '2' },
- { .name = "log-ip-options", .has_arg = 0, .flag = 0, .val = '3' },
- { .name = "log-uid", .has_arg = 0, .flag = 0, .val = '4' },
- { .name = 0 }
+static const struct option LOG_opts[] = {
+ { .name = "log-level", .has_arg = 1, .val = '!' },
+ { .name = "log-prefix", .has_arg = 1, .val = '#' },
+ { .name = "log-tcp-sequence", .has_arg = 0, .val = '1' },
+ { .name = "log-tcp-options", .has_arg = 0, .val = '2' },
+ { .name = "log-ip-options", .has_arg = 0, .val = '3' },
+ { .name = "log-uid", .has_arg = 0, .val = '4' },
+ { .name = NULL }
};
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
+static void LOG_init(struct xt_entry_target *t)
{
struct ip6t_log_info *loginfo = (struct ip6t_log_info *)t->data;
@@ -57,7 +51,7 @@ struct ip6t_log_names {
unsigned int level;
};
-static struct ip6t_log_names ip6t_log_names[]
+static const struct ip6t_log_names ip6t_log_names[]
= { { .name = "alert", .level = LOG_ALERT },
{ .name = "crit", .level = LOG_CRIT },
{ .name = "debug", .level = LOG_DEBUG },
@@ -75,28 +69,25 @@ parse_level(const char *level)
unsigned int lev = -1;
unsigned int set = 0;
- if (string_to_number(level, 0, 7, &lev) == -1) {
+ if (!xtables_strtoui(level, NULL, &lev, 0, 7)) {
unsigned int i = 0;
- for (i = 0;
- i < sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
if (strncasecmp(level, ip6t_log_names[i].name,
strlen(level)) == 0) {
if (set++)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"log-level `%s' ambiguous",
level);
lev = ip6t_log_names[i].level;
}
- }
if (!set)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"log-level `%s' unknown", level);
}
- return (u_int8_t)lev;
+ return lev;
}
#define IP6T_LOG_OPT_LEVEL 0x01
@@ -106,23 +97,19 @@ parse_level(const char *level)
#define IP6T_LOG_OPT_IPOPT 0x10
#define IP6T_LOG_OPT_UID 0x20
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
+static int LOG_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ip6t_log_info *loginfo = (struct ip6t_log_info *)(*target)->data;
switch (c) {
case '!':
if (*flags & IP6T_LOG_OPT_LEVEL)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-level twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-level");
loginfo->level = parse_level(optarg);
@@ -131,24 +118,24 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '#':
if (*flags & IP6T_LOG_OPT_PREFIX)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-prefix twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-prefix");
if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Maximum prefix length %u for --log-prefix",
(unsigned int)sizeof(loginfo->prefix) - 1);
if (strlen(optarg) == 0)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"No prefix specified for --log-prefix");
if (strlen(optarg) != strlen(strtok(optarg, "\n")))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --log-prefix");
strcpy(loginfo->prefix, optarg);
@@ -157,7 +144,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '1':
if (*flags & IP6T_LOG_OPT_TCPSEQ)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-tcp-sequence "
"twice");
@@ -167,7 +154,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '2':
if (*flags & IP6T_LOG_OPT_TCPOPT)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-tcp-options twice");
loginfo->logflags |= IP6T_LOG_TCPOPT;
@@ -176,7 +163,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (*flags & IP6T_LOG_OPT_IPOPT)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-ip-options twice");
loginfo->logflags |= IP6T_LOG_IPOPT;
@@ -185,7 +172,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '4':
if (*flags & IP6T_LOG_OPT_UID)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-uid twice");
loginfo->logflags |= IP6T_LOG_UID;
@@ -199,16 +186,8 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target,
- int numeric)
+static void LOG_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ip6t_log_info *loginfo
= (const struct ip6t_log_info *)target->data;
@@ -219,15 +198,12 @@ print(const struct ip6t_ip6 *ip,
printf("flags %u level %u ",
loginfo->logflags, loginfo->level);
else {
- for (i = 0;
- i < sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(ip6t_log_names); ++i)
if (loginfo->level == ip6t_log_names[i].level) {
printf("level %s ", ip6t_log_names[i].name);
break;
}
- }
- if (i == sizeof(ip6t_log_names) / sizeof(struct ip6t_log_names))
+ if (i == ARRAY_SIZE(ip6t_log_names))
printf("UNKNOWN level %u ", loginfo->level);
if (loginfo->logflags & IP6T_LOG_TCPSEQ)
printf("tcp-sequence ");
@@ -245,9 +221,7 @@ print(const struct ip6t_ip6 *ip,
printf("prefix `%s' ", loginfo->prefix);
}
-/* Saves the union ip6t_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
+static void LOG_save(const void *ip, const struct xt_entry_target *target)
{
const struct ip6t_log_info *loginfo
= (const struct ip6t_log_info *)target->data;
@@ -268,23 +242,21 @@ save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
printf("--log-uid ");
}
-static
-struct ip6tables_target log
-= {
+static struct xtables_target log_tg6_reg = {
.name = "LOG",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_log_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_log_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_log_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_log_info)),
+ .help = LOG_help,
+ .init = LOG_init,
+ .parse = LOG_parse,
+ .print = LOG_print,
+ .save = LOG_save,
+ .extra_opts = LOG_opts,
};
void _init(void)
{
- register_target6(&log);
+ xtables_register_target(&log_tg6_reg);
}
diff --git a/extensions/libip6t_LOG.man b/extensions/libip6t_LOG.man
index 9d51fd4..b7803fe 100644
--- a/extensions/libip6t_LOG.man
+++ b/extensions/libip6t_LOG.man
@@ -10,22 +10,22 @@ the next rule. So if you want to LOG the packets you refuse, use two
separate rules with the same matching criteria, first using target LOG
then DROP (or REJECT).
.TP
-.BI "--log-level " "level"
+\fB\-\-log\-level\fP \fIlevel\fP
Level of logging (numeric or see \fIsyslog.conf\fP(5)).
.TP
-.BI "--log-prefix " "prefix"
+\fB\-\-log\-prefix\fP \fIprefix\fP
Prefix log messages with the specified prefix; up to 29 letters long,
and useful for distinguishing messages in the logs.
.TP
-.B --log-tcp-sequence
+\fB\-\-log\-tcp\-sequence\fP
Log TCP sequence numbers. This is a security risk if the log is
readable by users.
.TP
-.B --log-tcp-options
+\fB\-\-log\-tcp\-options\fP
Log options from the TCP packet header.
.TP
-.B --log-ip-options
+\fB\-\-log\-ip\-options\fP
Log options from the IPv6 packet header.
.TP
-.B --log-uid
+\fB\-\-log\-uid\fP
Log the userid of the process which generated the packet.
diff --git a/extensions/libip6t_MARK.c b/extensions/libip6t_MARK.c
deleted file mode 100644
index a7f1a9d..0000000
--- a/extensions/libip6t_MARK.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* Shared library add-on to iptables to add MARK target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv6/ip6t_MARK.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MARK target v%s options:\n"
-" --set-mark value Set nfmark value\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { .name = "set-mark", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
-{
- struct ip6t_mark_target_info *markinfo
- = (struct ip6t_mark_target_info *)(*target)->data;
-
- switch (c) {
- case '1':
-#ifdef KERNEL_64_USERSPACE_32
- if (string_to_number_ll(optarg, 0, 0,
- &markinfo->mark))
-#else
- if (string_to_number_l(optarg, 0, 0,
- &markinfo->mark))
-#endif
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK target: Can't specify --set-mark twice");
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK target: Parameter --set-mark is required");
-}
-
-#ifdef KERNEL_64_USERSPACE_32
-static void
-print_mark(unsigned long long mark)
-{
- printf("0x%llx ", mark);
-}
-#else
-static void
-print_mark(unsigned long mark)
-{
- printf("0x%lx ", mark);
-}
-#endif
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target,
- int numeric)
-{
- const struct ip6t_mark_target_info *markinfo =
- (const struct ip6t_mark_target_info *)target->data;
-
- printf("MARK set ");
- print_mark(markinfo->mark);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
-{
- const struct ip6t_mark_target_info *markinfo =
- (const struct ip6t_mark_target_info *)target->data;
-
- printf("--set-mark ");
- print_mark(markinfo->mark);
-}
-
-static
-struct ip6tables_target mark = {
- .name = "MARK",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_mark_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_target6(&mark);
-}
diff --git a/extensions/libip6t_MARK.man b/extensions/libip6t_MARK.man
deleted file mode 100644
index 1f3260c..0000000
--- a/extensions/libip6t_MARK.man
+++ /dev/null
@@ -1,6 +0,0 @@
-This is used to set the netfilter mark value associated with the
-packet. It is only valid in the
-.B mangle
-table.
-.TP
-.BI "--set-mark " "mark"
diff --git a/extensions/libip6t_NFQUEUE.c b/extensions/libip6t_NFQUEUE.c
deleted file mode 100644
index e1964af..0000000
--- a/extensions/libip6t_NFQUEUE.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Shared library add-on to ip666666tables for NFQ
- *
- * (C) 2005 by Harald Welte <laforge@netfilter.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
-
-static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void help(void)
-{
- printf(
-"NFQUEUE target options\n"
-" --queue-num value Send packet to QUEUE number <value>.\n"
-" Valid queue numbers are 0-65535\n"
-);
-}
-
-static struct option opts[] = {
- { "queue-num", 1, 0, 'F' },
- { 0 }
-};
-
-static void
-parse_num(const char *s, struct ipt_NFQ_info *tinfo)
-{
- unsigned int num;
-
- if (string_to_number(s, 0, 65535, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "Invalid queue number `%s'\n", s);
-
- tinfo->queuenum = num & 0xffff;
- return;
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
-{
- struct ipt_NFQ_info *tinfo
- = (struct ipt_NFQ_info *)(*target)->data;
-
- switch (c) {
- case 'F':
- if (*flags)
- exit_error(PARAMETER_PROBLEM, "NFQUEUE target: "
- "Only use --queue-num ONCE!");
- parse_num(optarg, tinfo);
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target,
- int numeric)
-{
- const struct ipt_NFQ_info *tinfo =
- (const struct ipt_NFQ_info *)target->data;
- printf("NFQUEUE num %u", tinfo->queuenum);
-}
-
-/* Saves the union ip6t_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
-{
- const struct ipt_NFQ_info *tinfo =
- (const struct ipt_NFQ_info *)target->data;
-
- printf("--queue-num %u ", tinfo->queuenum);
-}
-
-static struct ip6tables_target nfqueue = {
- .next = NULL,
- .name = "NFQUEUE",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ipt_NFQ_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ipt_NFQ_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_target6(&nfqueue);
-}
diff --git a/extensions/libip6t_NFQUEUE.man b/extensions/libip6t_NFQUEUE.man
deleted file mode 100644
index c4e9d11..0000000
--- a/extensions/libip6t_NFQUEUE.man
+++ /dev/null
@@ -1,12 +0,0 @@
-This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
-you to put a packet into any specific queue, identified by its 16-bit queue
-number.
-.TP
-.BR "--queue-num " "\fIvalue"
-This specifies the QUEUE number to use. Valud queue numbers are 0 to 65535. The default value is 0.
-.TP
-It can only be used with Kernel versions 2.6.14 or later, since it requires
-the
-.B
-nfnetlink_queue
-kernel support.
diff --git a/extensions/libip6t_REJECT.c b/extensions/libip6t_REJECT.c
index 879716b..b8195d7 100644
--- a/extensions/libip6t_REJECT.c
+++ b/extensions/libip6t_REJECT.c
@@ -1,4 +1,4 @@
-/* Shared library add-on to iptables to add customized REJECT support.
+/* Shared library add-on to ip6tables to add customized REJECT support.
*
* (C) 2000 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
@@ -9,8 +9,7 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_REJECT.h>
struct reject_names {
@@ -38,41 +37,35 @@ static const struct reject_names reject_table[] = {
};
static void
-print_reject_types()
+print_reject_types(void)
{
unsigned int i;
printf("Valid reject types:\n");
- for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
printf(" %-25s\talias\n", reject_table[i].alias);
}
printf("\n");
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-
-/* Function which prints out usage message. */
-static void
-help(void)
+static void REJECT_help(void)
{
printf(
-"REJECT options:\n"
+"REJECT target options:\n"
"--reject-with type drop input packet and send back\n"
" a reply packet according to type:\n");
print_reject_types();
}
-static struct option opts[] = {
- { "reject-with", 1, 0, '1' },
- { 0 }
+static const struct option REJECT_opts[] = {
+ { "reject-with", 1, NULL, '1' },
+ { .name = NULL }
};
-/* Allocate and initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
+static void REJECT_init(struct xt_entry_target *t)
{
struct ip6t_reject_info *reject = (struct ip6t_reject_info *)t->data;
@@ -81,31 +74,25 @@ init(struct ip6t_entry_target *t, unsigned int *nfcache)
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
+static int REJECT_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ip6t_reject_info *reject =
(struct ip6t_reject_info *)(*target)->data;
- unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
unsigned int i;
switch(c) {
case '1':
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --reject-with");
- for (i = 0; i < limit; i++) {
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
|| (strncasecmp(reject_table[i].alias, optarg, strlen(optarg)) == 0)) {
reject->with = reject_table[i].with;
return 1;
}
- }
- exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
+ xtables_error(PARAMETER_PROBLEM, "unknown reject type \"%s\"", optarg);
default:
/* Fall through */
break;
@@ -113,58 +100,47 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 0;
}
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out ipt_reject_info. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target,
- int numeric)
+static void REJECT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ip6t_reject_info *reject
= (const struct ip6t_reject_info *)target->data;
unsigned int i;
- for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if (reject_table[i].with == reject->with)
break;
- }
printf("reject-with %s ", reject_table[i].name);
}
-/* Saves ipt_reject in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target)
+static void REJECT_save(const void *ip, const struct xt_entry_target *target)
{
const struct ip6t_reject_info *reject
= (const struct ip6t_reject_info *)target->data;
unsigned int i;
- for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++)
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if (reject_table[i].with == reject->with)
break;
printf("--reject-with %s ", reject_table[i].name);
}
-struct ip6tables_target reject = {
+static struct xtables_target reject_tg6_reg = {
.name = "REJECT",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_reject_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_reject_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_reject_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_reject_info)),
+ .help = REJECT_help,
+ .init = REJECT_init,
+ .parse = REJECT_parse,
+ .print = REJECT_print,
+ .save = REJECT_save,
+ .extra_opts = REJECT_opts,
};
void _init(void)
{
- register_target6(&reject);
+ xtables_register_target(&reject_tg6_reg);
}
diff --git a/extensions/libip6t_REJECT.man b/extensions/libip6t_REJECT.man
index 909d826..2d09e05 100644
--- a/extensions/libip6t_REJECT.man
+++ b/extensions/libip6t_REJECT.man
@@ -11,26 +11,23 @@ chains, and user-defined chains which are only called from those
chains. The following option controls the nature of the error packet
returned:
.TP
-.BI "--reject-with " "type"
+\fB\-\-reject\-with\fP \fItype\fP
The type given can be
-.nf
-.B " icmp6-no-route"
-.B " no-route"
-.B " icmp6-adm-prohibited"
-.B " adm-prohibited"
-.B " icmp6-addr-unreachable"
-.B " addr-unreach"
-.B " icmp6-port-unreachable"
-.B " port-unreach"
-.fi
-which return the appropriate ICMPv6 error message (\fBport-unreach\fP is
+\fBicmp6\-no\-route\fP,
+\fBno\-route\fP,
+\fBicmp6\-adm\-prohibited\fP,
+\fBadm\-prohibited\fP,
+\fBicmp6\-addr\-unreachable\fP,
+\fBaddr\-unreach\fP,
+\fBicmp6\-port\-unreachable\fP or
+\fBport\-unreach\fP
+which return the appropriate ICMPv6 error message (\fBport\-unreach\fP is
the default). Finally, the option
-.B tcp-reset
+\fBtcp\-reset\fP
can be used on rules which only match the TCP protocol: this causes a
TCP RST packet to be sent back. This is mainly useful for blocking
.I ident
(113/tcp) probes which frequently occur when sending mail to broken mail
hosts (which won't accept your mail otherwise).
-.B tcp-reset
-can only be used with kernel versions 2.6.14 or latter.
-
+\fBtcp\-reset\fP
+can only be used with kernel versions 2.6.14 or later.
diff --git a/extensions/libip6t_SECMARK.c b/extensions/libip6t_SECMARK.c
deleted file mode 100644
index 8fbae05..0000000
--- a/extensions/libip6t_SECMARK.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Shared library add-on to iptables to add SECMARK target support.
- *
- * Based on the MARK target.
- *
- * IPv6 version.
- *
- * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter/xt_SECMARK.h>
-
-#define PFX "SECMARK target: "
-
-static void help(void)
-{
- printf(
-"SECMARK target v%s options:\n"
-" --selctx value Set the SELinux security context\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "selctx", 1, 0, '1' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{ }
-
-/*
- * Function which parses command options; returns true if it
- * ate an option.
- */
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry, struct ip6t_entry_target **target)
-{
- struct xt_secmark_target_info *info =
- (struct xt_secmark_target_info*)(*target)->data;
-
- switch (c) {
- case '1':
- if (*flags & SECMARK_MODE_SEL)
- exit_error(PARAMETER_PROBLEM, PFX
- "Can't specify --selctx twice");
- info->mode = SECMARK_MODE_SEL;
-
- if (strlen(optarg) > SECMARK_SELCTX_MAX-1)
- exit_error(PARAMETER_PROBLEM, PFX
- "Maximum length %u exceeded by --selctx"
- " parameter (%zu)",
- SECMARK_SELCTX_MAX-1, strlen(optarg));
-
- strcpy(info->u.sel.selctx, optarg);
- *flags |= SECMARK_MODE_SEL;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, PFX "parameter required");
-}
-
-static void print_secmark(struct xt_secmark_target_info *info)
-{
- switch (info->mode) {
- case SECMARK_MODE_SEL:
- printf("selctx %s ", info->u.sel.selctx);\
- break;
-
- default:
- exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
- }
-}
-
-static void print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_target *target, int numeric)
-{
- struct xt_secmark_target_info *info =
- (struct xt_secmark_target_info*)(target)->data;
-
- printf("SECMARK ");
- print_secmark(info);
-}
-
-/* Saves the target info in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
-{
- struct xt_secmark_target_info *info =
- (struct xt_secmark_target_info*)target->data;
-
- printf("--");
- print_secmark(info);
-}
-
-static struct ip6tables_target secmark = {
- .name = "SECMARK",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct xt_secmark_target_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct xt_secmark_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_target6(&secmark);
-}
diff --git a/extensions/libip6t_TCPMSS.c b/extensions/libip6t_TCPMSS.c
deleted file mode 100644
index 7fcccd5..0000000
--- a/extensions/libip6t_TCPMSS.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Shared library add-on to iptables to add TCPMSS target support.
- *
- * Copyright (c) 2000 Marc Boucher
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter_ipv6/ip6t_TCPMSS.h>
-
-struct mssinfo {
- struct ip6t_entry_target t;
- struct ip6t_tcpmss_info mss;
-};
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"TCPMSS target v%s mutually-exclusive options:\n"
-" --set-mss value explicitly set MSS option to specified value\n"
-" --clamp-mss-to-pmtu automatically clamp MSS value to (path_MTU - 60)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "set-mss", 1, 0, '1' },
- { "clamp-mss-to-pmtu", 0, 0, '2' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
-{
- struct ip6t_tcpmss_info *mssinfo
- = (struct ip6t_tcpmss_info *)(*target)->data;
-
- switch (c) {
- unsigned int mssval;
-
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "TCPMSS target: Only one option may be specified");
- if (string_to_number(optarg, 0, 65535 - 60, &mssval) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad TCPMSS value `%s'", optarg);
-
- mssinfo->mss = mssval;
- *flags = 1;
- break;
-
- case '2':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "TCPMSS target: Only one option may be specified");
- mssinfo->mss = IP6T_TCPMSS_CLAMP_PMTU;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "TCPMSS target: At least one parameter is required");
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ip6t_ip6 *ip6,
- const struct ip6t_entry_target *target,
- int numeric)
-{
- const struct ip6t_tcpmss_info *mssinfo =
- (const struct ip6t_tcpmss_info *)target->data;
- if(mssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU)
- printf("TCPMSS clamp to PMTU ");
- else
- printf("TCPMSS set %u ", mssinfo->mss);
-}
-
-/* Saves the union ip6t_targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_target *target)
-{
- const struct ip6t_tcpmss_info *mssinfo =
- (const struct ip6t_tcpmss_info *)target->data;
-
- if(mssinfo->mss == IP6T_TCPMSS_CLAMP_PMTU)
- printf("--clamp-mss-to-pmtu ");
- else
- printf("--set-mss %u ", mssinfo->mss);
-}
-
-static struct ip6tables_target mss = {
- .next = NULL,
- .name = "TCPMSS",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_tcpmss_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_tcpmss_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_target6(&mss);
-}
diff --git a/extensions/libip6t_TCPMSS.man b/extensions/libip6t_TCPMSS.man
deleted file mode 100644
index b4c357e..0000000
--- a/extensions/libip6t_TCPMSS.man
+++ /dev/null
@@ -1,42 +0,0 @@
-This target allows to alter the MSS value of TCP SYN packets, to control
-the maximum size for that connection (usually limiting it to your
-outgoing interface's MTU minus 60). Of course, it can only be used
-in conjunction with
-.BR "-p tcp" .
-It is only valid in the
-.BR mangle
-table.
-.br
-This target is used to overcome criminally braindead ISPs or servers
-which block ICMPv6 Packet Too Big packets or are unable to send them.
-The symptoms of this problem are that everything works fine from your
-Linux firewall/router, but machines behind it can never exchange large
-packets:
-.PD 0
-.RS 0.1i
-.TP 0.3i
-1)
-Web browsers connect, then hang with no data received.
-.TP
-2)
-Small mail works fine, but large emails hang.
-.TP
-3)
-ssh works fine, but scp hangs after initial handshaking.
-.RE
-.PD
-Workaround: activate this option and add a rule to your firewall
-configuration like:
-.nf
- ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \\
- -j TCPMSS --clamp-mss-to-pmtu
-.fi
-.TP
-.BI "--set-mss " "value"
-Explicitly set MSS option to specified value.
-.TP
-.B "--clamp-mss-to-pmtu"
-Automatically clamp MSS value to (path_MTU - 60).
-.TP
-These options are mutually exclusive.
-
diff --git a/extensions/libip6t_ah.c b/extensions/libip6t_ah.c
index 794e02e..285704c 100644
--- a/extensions/libip6t_ah.c
+++ b/extensions/libip6t_ah.c
@@ -5,26 +5,23 @@
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#include <ip6tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_ah.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
+
+static void ah_help(void)
{
printf(
-"AH v%s options:\n"
-" --ahspi [!] spi[:spi] match spi (range)\n"
-" --ahlen [!] length total length of this header\n"
-" --ahres check the reserved filed, too\n",
-IPTABLES_VERSION);
+"ah match options:\n"
+"[!] --ahspi spi[:spi] match spi (range)\n"
+"[!] --ahlen length total length of this header\n"
+" --ahres check the reserved filed, too\n");
}
-static struct option opts[] = {
- { .name = "ahspi", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "ahlen", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "ahres", .has_arg = 0, .flag = 0, .val = '3' },
- { .name = 0 }
+static const struct option ah_opts[] = {
+ { .name = "ahspi", .has_arg = 1, .val = '1' },
+ { .name = "ahlen", .has_arg = 1, .val = '2' },
+ { .name = "ahres", .has_arg = 0, .val = '3' },
+ { .name = NULL }
};
static u_int32_t
@@ -36,19 +33,19 @@ parse_ah_spi(const char *spistr, const char *typestr)
spi = strtoul(spistr, &ep, 0);
if ( spistr == ep )
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"AH no valid digits in %s `%s'", typestr, spistr);
if ( spi == ULONG_MAX && errno == ERANGE )
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"%s `%s' specified too big: would overflow",
typestr, spistr);
if ( *spistr != '\0' && *ep != '\0' )
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"AH error parsing %s `%s'", typestr, spistr);
- return (u_int32_t) spi;
+ return spi;
}
static void
@@ -70,9 +67,7 @@ parse_ah_spis(const char *spistring, u_int32_t *spis)
free(buffer);
}
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void ah_init(struct xt_entry_match *m)
{
struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data;
@@ -81,40 +76,35 @@ init(struct ip6t_entry_match *m, unsigned int *nfcache)
ahinfo->hdrres = 0;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+static int ah_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_ah *ahinfo = (struct ip6t_ah *)(*match)->data;
switch (c) {
case '1':
if (*flags & IP6T_AH_SPI)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--ahspi' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_ah_spis(argv[optind-1], ahinfo->spis);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_ah_spis(optarg, ahinfo->spis);
if (invert)
ahinfo->invflags |= IP6T_AH_INV_SPI;
*flags |= IP6T_AH_SPI;
break;
case '2':
if (*flags & IP6T_AH_LEN)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--ahlen' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- ahinfo->hdrlen = parse_ah_spi(argv[optind-1], "length");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ ahinfo->hdrlen = parse_ah_spi(optarg, "length");
if (invert)
ahinfo->invflags |= IP6T_AH_INV_LEN;
*flags |= IP6T_AH_LEN;
break;
case '3':
if (*flags & IP6T_AH_RES)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--ahres' allowed");
ahinfo->hdrres = 1;
*flags |= IP6T_AH_RES;
@@ -126,12 +116,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
static void
print_spis(const char *name, u_int32_t min, u_int32_t max,
int invert)
@@ -155,10 +139,8 @@ print_len(const char *name, u_int32_t len, int invert)
printf("%s:%s%u ", name, inv, len);
}
-/* Prints out the union ip6t_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
+static void ah_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
@@ -176,14 +158,13 @@ print(const struct ip6t_ip6 *ip,
ah->invflags & ~IP6T_AH_INV_MASK);
}
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+static void ah_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
if (!(ahinfo->spis[0] == 0
&& ahinfo->spis[1] == 0xFFFFFFFF)) {
- printf("--ahspi %s",
+ printf("%s--ahspi ",
(ahinfo->invflags & IP6T_AH_INV_SPI) ? "! " : "");
if (ahinfo->spis[0]
!= ahinfo->spis[1])
@@ -196,7 +177,7 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
}
if (ahinfo->hdrlen != 0 || (ahinfo->invflags & IP6T_AH_INV_LEN) ) {
- printf("--ahlen %s%u ",
+ printf("%s--ahlen %u ",
(ahinfo->invflags & IP6T_AH_INV_LEN) ? "! " : "",
ahinfo->hdrlen);
}
@@ -205,23 +186,22 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
printf("--ahres ");
}
-static
-struct ip6tables_match ah = {
+static struct xtables_match ah_mt6_reg = {
.name = "ah",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_ah)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_ah)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_ah)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
+ .help = ah_help,
+ .init = ah_init,
+ .parse = ah_parse,
+ .print = ah_print,
+ .save = ah_save,
+ .extra_opts = ah_opts,
};
void
_init(void)
{
- register_match6(&ah);
+ xtables_register_match(&ah_mt6_reg);
}
diff --git a/extensions/libip6t_ah.man b/extensions/libip6t_ah.man
index 09d00fd..9c24dcf 100644
--- a/extensions/libip6t_ah.man
+++ b/extensions/libip6t_ah.man
@@ -1,10 +1,10 @@
This module matches the parameters in Authentication header of IPsec packets.
.TP
-.BR "--ahspi " "[!] \fIspi\fP[:\fIspi\fP]"
+[\fB!\fP] \fB\-\-ahspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
Matches SPI.
.TP
-.BR "--ahlen " "[!] \fIlength"
+[\fB!\fP] \fB\-\-ahlen\fP \fIlength\fP
Total length of this header in octets.
.TP
-.BI "--ahres"
+\fB\-\-ahres\fP
Matches if the reserved field is filled with zero.
diff --git a/extensions/libip6t_condition.c b/extensions/libip6t_condition.c
deleted file mode 100644
index 0e94c39..0000000
--- a/extensions/libip6t_condition.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Shared library add-on to ip6tables for condition match */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <ip6tables.h>
-
-#include<linux/netfilter_ipv6/ip6_tables.h>
-#include<linux/netfilter_ipv6/ip6t_condition.h>
-
-
-static void
-help(void)
-{
- printf("condition match v%s options:\n"
- "--condition [!] filename "
- "Match on boolean value stored in /proc file\n",
- IPTABLES_VERSION);
-}
-
-
-static struct option opts[] = {
- { .name = "condition", .has_arg = 1, .flag = 0, .val = 'X' },
- { .name = 0 }
-};
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry, unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct condition6_info *info =
- (struct condition6_info *) (*match)->data;
-
- if (c == 'X') {
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify multiple conditions");
-
- check_inverse(optarg, &invert, &optind, 0);
-
- if (strlen(argv[optind - 1]) < CONDITION6_NAME_LEN)
- strcpy(info->name, argv[optind - 1]);
- else
- exit_error(PARAMETER_PROBLEM,
- "File name too long");
-
- info->invert = invert;
- *flags = 1;
- return 1;
- }
-
- return 0;
-}
-
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "Condition match: must specify --condition");
-}
-
-
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
-{
- const struct condition6_info *info =
- (const struct condition6_info *) match->data;
-
- printf("condition %s%s ", (info->invert) ? "!" : "", info->name);
-}
-
-
-static void
-save(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match)
-{
- const struct condition6_info *info =
- (const struct condition6_info *) match->data;
-
- printf("--condition %s\"%s\" ", (info->invert) ? "! " : "", info->name);
-}
-
-
-static struct ip6tables_match condition = {
- .name = "condition",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct condition6_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct condition6_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-
-void
-_init(void)
-{
- register_match6(&condition);
-}
diff --git a/extensions/libip6t_condition.man b/extensions/libip6t_condition.man
deleted file mode 100644
index e0bba75..0000000
--- a/extensions/libip6t_condition.man
+++ /dev/null
@@ -1,4 +0,0 @@
-This matches if a specific /proc filename is '0' or '1'.
-.TP
-.BR "--condition " "[!] \fIfilename"
-Match on boolean value stored in /proc/net/ip6t_condition/filename file
diff --git a/extensions/libip6t_dst.c b/extensions/libip6t_dst.c
index 19ca23c..72df6ad 100644
--- a/extensions/libip6t_dst.c
+++ b/extensions/libip6t_dst.c
@@ -1,41 +1,31 @@
-/* Shared library add-on to ip6tables to add Hop-by-Hop and Dst headers support. */
+/* Shared library add-on to ip6tables to add Dst header support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#include <ip6tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_opts.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-#ifdef HOPBYHOP
-#define UNAME "HBH"
-#define LNAME "hbh"
-#else
-#define UNAME "DST"
-#define LNAME "dst"
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
+static void dst_help(void)
{
printf(
-UNAME " v%s options:\n"
-" --" LNAME "-len [!] length total length of this header\n"
-" --" LNAME "-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
-" Options and its length (list, max: %d)\n",
-IPTABLES_VERSION, IP6T_OPTS_OPTSNR);
+"dst match options:\n"
+"[!] --dst-len length total length of this header\n"
+" --dst-opts TYPE[:LEN][,TYPE[:LEN]...]\n"
+" Options and its length (list, max: %d)\n",
+IP6T_OPTS_OPTSNR);
}
-static struct option opts[] = {
- { .name = LNAME "-len", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = LNAME "-opts", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = LNAME "-not-strict", .has_arg = 1, .flag = 0, .val = '3' },
- { .name = 0 }
+static const struct option dst_opts[] = {
+ { .name = "dst-len", .has_arg = 1, .val = '1' },
+ { .name = "dst-opts", .has_arg = 1, .val = '2' },
+ { .name = "dst-not-strict", .has_arg = 1, .val = '3' },
+ { .name = NULL }
};
static u_int32_t
@@ -47,19 +37,19 @@ parse_opts_num(const char *idstr, const char *typestr)
id = strtoul(idstr, &ep, 0);
if ( idstr == ep ) {
- exit_error(PARAMETER_PROBLEM,
- UNAME " no valid digits in %s `%s'", typestr, idstr);
+ xtables_error(PARAMETER_PROBLEM,
+ "dst: no valid digits in %s `%s'", typestr, idstr);
}
if ( id == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"%s `%s' specified too big: would overflow",
typestr, idstr);
}
if ( *idstr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
- UNAME " error parsing %s `%s'", typestr, idstr);
+ xtables_error(PARAMETER_PROBLEM,
+ "dst: error parsing %s `%s'", typestr, idstr);
}
- return (u_int32_t) id;
+ return id;
}
static int
@@ -70,7 +60,7 @@ parse_options(const char *optsstr, u_int16_t *opts)
buffer = strdup(optsstr);
if (!buffer)
- exit_error(OTHER_PROBLEM, "strdup failed");
+ xtables_error(OTHER_PROBLEM, "strdup failed");
for (cp = buffer, i = 0; cp && i < IP6T_OPTS_OPTSNR; cp = next, i++)
{
@@ -83,18 +73,17 @@ parse_options(const char *optsstr, u_int16_t *opts)
if (range) {
if (i == IP6T_OPTS_OPTSNR-1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"too many ports specified");
*range++ = '\0';
}
- opts[i] = (u_int16_t)((parse_opts_num(cp,"opt") & 0x000000FF)<<8);
+ opts[i] = (parse_opts_num(cp, "opt") & 0xFF) << 8;
if (range) {
if (opts[i] == 0)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"PAD0 hasn't got length");
- opts[i] |= (u_int16_t)(parse_opts_num(range,"length") &
- 0x000000FF);
+ opts[i] |= parse_opts_num(range, "length") & 0xFF;
} else
opts[i] |= (0x00FF);
@@ -105,7 +94,7 @@ parse_options(const char *optsstr, u_int16_t *opts)
}
if (cp)
- exit_error(PARAMETER_PROBLEM, "too many addresses specified");
+ xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
free(buffer);
@@ -116,9 +105,7 @@ parse_options(const char *optsstr, u_int16_t *opts)
return i;
}
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void dst_init(struct xt_entry_match *m)
{
struct ip6t_opts *optinfo = (struct ip6t_opts *)m->data;
@@ -128,23 +115,18 @@ init(struct ip6t_entry_match *m, unsigned int *nfcache)
optinfo->optsnr = 0;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+static int dst_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_opts *optinfo = (struct ip6t_opts *)(*match)->data;
switch (c) {
case '1':
if (*flags & IP6T_OPTS_LEN)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--" LNAME "-len' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- optinfo->hdrlen = parse_opts_num(argv[optind-1], "length");
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--dst-len' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ optinfo->hdrlen = parse_opts_num(optarg, "length");
if (invert)
optinfo->invflags |= IP6T_OPTS_INV_LEN;
optinfo->flags |= IP6T_OPTS_LEN;
@@ -152,24 +134,24 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '2':
if (*flags & IP6T_OPTS_OPTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--" LNAME "-opts' allowed");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--dst-opts' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
if (invert)
- exit_error(PARAMETER_PROBLEM,
- " '!' not allowed with `--" LNAME "-opts'");
- optinfo->optsnr = parse_options(argv[optind-1], optinfo->opts);
+ xtables_error(PARAMETER_PROBLEM,
+ " '!' not allowed with `--dst-opts'");
+ optinfo->optsnr = parse_options(optarg, optinfo->opts);
optinfo->flags |= IP6T_OPTS_OPTS;
*flags |= IP6T_OPTS_OPTS;
break;
case '3':
if (*flags & IP6T_OPTS_NSTRICT)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--" LNAME "-not-strict' allowed");
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--dst-not-strict' allowed");
if ( !(*flags & IP6T_OPTS_OPTS) )
- exit_error(PARAMETER_PROBLEM,
- "`--" LNAME "-opts ...' required before `--"
- LNAME "-not-strict'");
+ xtables_error(PARAMETER_PROBLEM,
+ "`--dst-opts ...' required before "
+ "`--dst-not-strict'");
optinfo->flags |= IP6T_OPTS_NSTRICT;
*flags |= IP6T_OPTS_NSTRICT;
break;
@@ -180,14 +162,8 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
static void
-final_check(unsigned int flags)
-{
-}
-
-static void
-print_options(int optsnr, u_int16_t *optsp)
+print_options(unsigned int optsnr, u_int16_t *optsp)
{
unsigned int i;
@@ -201,14 +177,12 @@ print_options(int optsnr, u_int16_t *optsp)
}
}
-/* Prints out the union ip6t_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
+static void dst_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
- printf(LNAME " ");
+ printf("dst ");
if (optinfo->flags & IP6T_OPTS_LEN)
printf("length:%s%u ",
optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "",
@@ -227,43 +201,41 @@ print(const struct ip6t_ip6 *ip,
optinfo->invflags & ~IP6T_OPTS_INV_MASK);
}
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+static void dst_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
if (optinfo->flags & IP6T_OPTS_LEN) {
- printf("--" LNAME "-len %s%u ",
+ printf("%s--dst-len %u ",
(optinfo->invflags & IP6T_OPTS_INV_LEN) ? "! " : "",
optinfo->hdrlen);
}
if (optinfo->flags & IP6T_OPTS_OPTS)
- printf("--" LNAME "-opts ");
+ printf("--dst-opts ");
print_options(optinfo->optsnr, (u_int16_t *)optinfo->opts);
if (optinfo->flags & IP6T_OPTS_NSTRICT)
- printf("--" LNAME "-not-strict ");
+ printf("--dst-not-strict ");
}
-static
-struct ip6tables_match optstruct = {
- .name = LNAME,
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_opts)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_opts)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+static struct xtables_match dst_mt6_reg = {
+ .name = "dst",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_opts)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)),
+ .help = dst_help,
+ .init = dst_init,
+ .parse = dst_parse,
+ .print = dst_print,
+ .save = dst_save,
+ .extra_opts = dst_opts,
};
void
_init(void)
{
- register_match6(&optstruct);
+ xtables_register_match(&dst_mt6_reg);
}
diff --git a/extensions/libip6t_dst.man b/extensions/libip6t_dst.man
index f42d822..bfbb501 100644
--- a/extensions/libip6t_dst.man
+++ b/extensions/libip6t_dst.man
@@ -1,7 +1,7 @@
This module matches the parameters in Destination Options header
.TP
-.BR "--dst-len " "[!] \fIlength"
+[\fB!\fP] \fB\-\-dst\-len\fP \fIlength\fP
Total length of this header in octets.
.TP
-.BR "--dst-opts " "\fItype\fP[:\fIlength\fP][,\fItype\fP[:\fIlength\fP]...]"
+\fB\-\-dst\-opts\fP \fItype\fP[\fB:\fP\fIlength\fP][\fB,\fP\fItype\fP[\fB:\fP\fIlength\fP]...]
numeric type of option and the length of the option data in octets.
diff --git a/extensions/libip6t_esp.c b/extensions/libip6t_esp.c
deleted file mode 100644
index 886e09b..0000000
--- a/extensions/libip6t_esp.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/* Shared library add-on to ip6tables to add ESP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <errno.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_esp.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"ESP v%s options:\n"
-" --espspi [!] spi[:spi] match spi (range)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { .name = "espspi", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = 0 }
-};
-
-static u_int32_t
-parse_esp_spi(const char *spistr)
-{
- unsigned long int spi;
- char* ep;
-
- spi = strtoul(spistr, &ep, 0);
-
- if ( spistr == ep ) {
- exit_error(PARAMETER_PROBLEM,
- "ESP no valid digits in spi `%s'", spistr);
- }
- if ( spi == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
- "spi `%s' specified too big: would overflow", spistr);
- }
- if ( *spistr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
- "ESP error parsing spi `%s'", spistr);
- }
- return (u_int32_t) spi;
-}
-
-static void
-parse_esp_spis(const char *spistring, u_int32_t *spis)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(spistring);
- if ((cp = strchr(buffer, ':')) == NULL)
- spis[0] = spis[1] = parse_esp_spi(buffer);
- else {
- *cp = '\0';
- cp++;
-
- spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
- spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
- if (spis[0] > spis[1])
- exit_error(PARAMETER_PROBLEM,
- "Invalid ESP spi range: %s", spistring);
- }
- free(buffer);
-}
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- struct ip6t_esp *espinfo = (struct ip6t_esp *)m->data;
-
- espinfo->spis[1] = 0xFFFFFFFF;
-}
-
-#define ESP_SPI 0x01
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_esp *espinfo = (struct ip6t_esp *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & ESP_SPI)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--espspi' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_esp_spis(argv[optind-1], espinfo->spis);
- if (invert)
- espinfo->invflags |= IP6T_ESP_INV_SPI;
- *flags |= ESP_SPI;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
-static void
-print_spis(const char *name, u_int32_t min, u_int32_t max,
- int invert)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFFFFFF || invert) {
- if (min == max)
- printf("%s:%s%u ", name, inv, min);
- else
- printf("%ss:%s%u:%u ", name, inv, min, max);
- }
-}
-
-/* Prints out the union ip6t_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
-{
- const struct ip6t_esp *esp = (struct ip6t_esp *)match->data;
-
- printf("esp ");
- print_spis("spi", esp->spis[0], esp->spis[1],
- esp->invflags & IP6T_ESP_INV_SPI);
- if (esp->invflags & ~IP6T_ESP_INV_MASK)
- printf("Unknown invflags: 0x%X ",
- esp->invflags & ~IP6T_ESP_INV_MASK);
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- const struct ip6t_esp *espinfo = (struct ip6t_esp *)match->data;
-
- if (!(espinfo->spis[0] == 0
- && espinfo->spis[1] == 0xFFFFFFFF)) {
- printf("--espspi %s",
- (espinfo->invflags & IP6T_ESP_INV_SPI) ? "! " : "");
- if (espinfo->spis[0]
- != espinfo->spis[1])
- printf("%u:%u ",
- espinfo->spis[0],
- espinfo->spis[1]);
- else
- printf("%u ",
- espinfo->spis[0]);
- }
-
-}
-
-static
-struct ip6tables_match esp = {
- .name = "esp",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_esp)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_esp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void
-_init(void)
-{
- register_match6(&esp);
-}
diff --git a/extensions/libip6t_esp.man b/extensions/libip6t_esp.man
deleted file mode 100644
index 7898e02..0000000
--- a/extensions/libip6t_esp.man
+++ /dev/null
@@ -1,3 +0,0 @@
-This module matches the SPIs in ESP header of IPsec packets.
-.TP
-.BR "--espspi " "[!] \fIspi\fP[:\fIspi\fP]"
diff --git a/extensions/libip6t_eui64.c b/extensions/libip6t_eui64.c
index c74b04d..607bf86 100644
--- a/extensions/libip6t_eui64.c
+++ b/extensions/libip6t_eui64.c
@@ -1,76 +1,15 @@
/* Shared library add-on to ip6tables to add EUI64 address checking support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-#include <ip6tables.h>
+#include <xtables.h>
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"eui64 v%s options:\n"
-" This module hasn't got any option\n"
-" This module checks for EUI64 IPv6 addresses\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- return 0;
-}
-
-/* Final check */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- printf("eui64 ");
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
-
-}
-
-static struct ip6tables_match eui64 = {
+static struct xtables_match eui64_mt6_reg = {
.name = "eui64",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(int)),
- .userspacesize = IP6T_ALIGN(sizeof(int)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(int)),
+ .userspacesize = XT_ALIGN(sizeof(int)),
};
void _init(void)
{
- register_match6(&eui64);
+ xtables_register_match(&eui64_mt6_reg);
}
diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c
index 51a14fa..5a280cc 100644
--- a/extensions/libip6t_frag.c
+++ b/extensions/libip6t_frag.c
@@ -5,32 +5,29 @@
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#include <ip6tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv6/ip6t_frag.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
+
+static void frag_help(void)
{
printf(
-"FRAG v%s options:\n"
-" --fragid [!] id[:id] match the id (range)\n"
-" --fraglen [!] length total length of this header\n"
+"frag match options:\n"
+"[!] --fragid id[:id] match the id (range)\n"
+"[!] --fraglen length total length of this header\n"
" --fragres check the reserved filed, too\n"
" --fragfirst matches on the first fragment\n"
" [--fragmore|--fraglast] there are more fragments or this\n"
-" is the last one\n",
-IPTABLES_VERSION);
+" is the last one\n");
}
-static struct option opts[] = {
- { .name = "fragid", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "fraglen", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "fragres", .has_arg = 0, .flag = 0, .val = '3' },
- { .name = "fragfirst", .has_arg = 0, .flag = 0, .val = '4' },
- { .name = "fragmore", .has_arg = 0, .flag = 0, .val = '5' },
- { .name = "fraglast", .has_arg = 0, .flag = 0, .val = '6' },
- { .name = 0 }
+static const struct option frag_opts[] = {
+ { .name = "fragid", .has_arg = 1, .val = '1' },
+ { .name = "fraglen", .has_arg = 1, .val = '2' },
+ { .name = "fragres", .has_arg = 0, .val = '3' },
+ { .name = "fragfirst", .has_arg = 0, .val = '4' },
+ { .name = "fragmore", .has_arg = 0, .val = '5' },
+ { .name = "fraglast", .has_arg = 0, .val = '6' },
+ { .name = NULL }
};
static u_int32_t
@@ -42,19 +39,19 @@ parse_frag_id(const char *idstr, const char *typestr)
id = strtoul(idstr, &ep, 0);
if ( idstr == ep ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"FRAG no valid digits in %s `%s'", typestr, idstr);
}
if ( id == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"%s `%s' specified too big: would overflow",
typestr, idstr);
}
if ( *idstr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"FRAG error parsing %s `%s'", typestr, idstr);
}
- return (u_int32_t) id;
+ return id;
}
static void
@@ -76,9 +73,7 @@ parse_frag_ids(const char *idstring, u_int32_t *ids)
free(buffer);
}
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void frag_init(struct xt_entry_match *m)
{
struct ip6t_frag *fraginfo = (struct ip6t_frag *)m->data;
@@ -89,23 +84,18 @@ init(struct ip6t_entry_match *m, unsigned int *nfcache)
fraginfo->invflags = 0;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+static int frag_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_frag *fraginfo = (struct ip6t_frag *)(*match)->data;
switch (c) {
case '1':
if (*flags & IP6T_FRAG_IDS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--fragid' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_frag_ids(argv[optind-1], fraginfo->ids);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_frag_ids(optarg, fraginfo->ids);
if (invert)
fraginfo->invflags |= IP6T_FRAG_INV_IDS;
fraginfo->flags |= IP6T_FRAG_IDS;
@@ -113,10 +103,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '2':
if (*flags & IP6T_FRAG_LEN)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--fraglen' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- fraginfo->hdrlen = parse_frag_id(argv[optind-1], "length");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ fraginfo->hdrlen = parse_frag_id(optarg, "length");
if (invert)
fraginfo->invflags |= IP6T_FRAG_INV_LEN;
fraginfo->flags |= IP6T_FRAG_LEN;
@@ -124,28 +114,28 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '3':
if (*flags & IP6T_FRAG_RES)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--fragres' allowed");
fraginfo->flags |= IP6T_FRAG_RES;
*flags |= IP6T_FRAG_RES;
break;
case '4':
if (*flags & IP6T_FRAG_FST)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--fragfirst' allowed");
fraginfo->flags |= IP6T_FRAG_FST;
*flags |= IP6T_FRAG_FST;
break;
case '5':
if (*flags & (IP6T_FRAG_MF|IP6T_FRAG_NMF))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--fragmore' or `--fraglast' allowed");
fraginfo->flags |= IP6T_FRAG_MF;
*flags |= IP6T_FRAG_MF;
break;
case '6':
if (*flags & (IP6T_FRAG_MF|IP6T_FRAG_NMF))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--fragmore' or `--fraglast' allowed");
fraginfo->flags |= IP6T_FRAG_NMF;
*flags |= IP6T_FRAG_NMF;
@@ -157,12 +147,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
static void
print_ids(const char *name, u_int32_t min, u_int32_t max,
int invert)
@@ -178,10 +162,8 @@ print_ids(const char *name, u_int32_t min, u_int32_t max,
}
}
-/* Prints out the union ip6t_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
+static void frag_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ip6t_frag *frag = (struct ip6t_frag *)match->data;
@@ -212,14 +194,13 @@ print(const struct ip6t_ip6 *ip,
frag->invflags & ~IP6T_FRAG_INV_MASK);
}
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+static void frag_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_frag *fraginfo = (struct ip6t_frag *)match->data;
if (!(fraginfo->ids[0] == 0
&& fraginfo->ids[1] == 0xFFFFFFFF)) {
- printf("--fragid %s",
+ printf("%s--fragid ",
(fraginfo->invflags & IP6T_FRAG_INV_IDS) ? "! " : "");
if (fraginfo->ids[0]
!= fraginfo->ids[1])
@@ -232,7 +213,7 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
}
if (fraginfo->flags & IP6T_FRAG_LEN) {
- printf("--fraglen %s%u ",
+ printf("%s--fraglen %u ",
(fraginfo->invflags & IP6T_FRAG_INV_LEN) ? "! " : "",
fraginfo->hdrlen);
}
@@ -250,23 +231,22 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
printf("--fraglast ");
}
-static
-struct ip6tables_match frag = {
+static struct xtables_match frag_mt6_reg = {
.name = "frag",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_frag)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_frag)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_frag)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)),
+ .help = frag_help,
+ .init = frag_init,
+ .parse = frag_parse,
+ .print = frag_print,
+ .save = frag_save,
+ .extra_opts = frag_opts,
};
void
_init(void)
{
- register_match6(&frag);
+ xtables_register_match(&frag_mt6_reg);
}
diff --git a/extensions/libip6t_frag.man b/extensions/libip6t_frag.man
index 5ac13a4..7bfa227 100644
--- a/extensions/libip6t_frag.man
+++ b/extensions/libip6t_frag.man
@@ -1,20 +1,20 @@
This module matches the parameters in Fragment header.
.TP
-.BR "--fragid " "[!] \fIid\fP[:\fIid\fP]"
+[\fB!\fP] \fB\-\-fragid\fP \fIid\fP[\fB:\fP\fIid\fP]
Matches the given Identification or range of it.
.TP
-.BR "--fraglen " "[!] \fIlength\fP"
+[\fB!\fP] \fB\-\-fraglen\fP \fIlength\fP
This option cannot be used with kernel version 2.6.10 or later. The length of
Fragment header is static and this option doesn't make sense.
.TP
-.BR "--fragres "
+\fB\-\-fragres\fP
Matches if the reserved fields are filled with zero.
.TP
-.BR "--fragfirst "
+\fB\-\-fragfirst\fP
Matches on the first fragment.
.TP
-.BR "[--fragmore]"
+\fB\-\-fragmore\fP
Matches if there are more fragments.
.TP
-.BR "[--fraglast]"
-Matches if this is the last fragement.
+\fB\-\-fraglast\fP
+Matches if this is the last fragment.
diff --git a/extensions/libip6t_hashlimit.c b/extensions/libip6t_hashlimit.c
deleted file mode 100644
index 70d2ff3..0000000
--- a/extensions/libip6t_hashlimit.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/* ip6tables match extension for limiting packets per destination
- *
- * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
- *
- * Development of this code was funded by Astaro AG, http://www.astaro.com/
- *
- * Based on ipt_limit.c by
- * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne <rv@wallfire.org>
- *
- * Error corections by nmalykh@bilim.com (22.01.2005)
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <stddef.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <linux/netfilter/xt_hashlimit.h>
-
-#define XT_HASHLIMIT_BURST 5
-
-/* miliseconds */
-#define XT_HASHLIMIT_GCINTERVAL 1000
-#define XT_HASHLIMIT_EXPIRE 10000
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"hashlimit v%s options:\n"
-"--hashlimit <avg> max average match rate\n"
-" [Packets per second unless followed by \n"
-" /sec /minute /hour /day postfixes]\n"
-"--hashlimit-mode <mode> mode is a comma-separated list of\n"
-" dstip,srcip,dstport,srcport\n"
-"--hashlimit-name <name> name for /proc/net/ipt_hashlimit/\n"
-"[--hashlimit-burst <num>] number to match in a burst, default %u\n"
-"[--hashlimit-htable-size <num>] number of hashtable buckets\n"
-"[--hashlimit-htable-max <num>] number of hashtable entries\n"
-"[--hashlimit-htable-gcinterval] interval between garbage collection runs\n"
-"[--hashlimit-htable-expire] after which time are idle entries expired?\n"
-"\n", IPTABLES_VERSION, XT_HASHLIMIT_BURST);
-}
-
-static struct option opts[] = {
- { "hashlimit", 1, 0, '%' },
- { "hashlimit-burst", 1, 0, '$' },
- { "hashlimit-htable-size", 1, 0, '&' },
- { "hashlimit-htable-max", 1, 0, '*' },
- { "hashlimit-htable-gcinterval", 1, 0, '(' },
- { "hashlimit-htable-expire", 1, 0, ')' },
- { "hashlimit-mode", 1, 0, '_' },
- { "hashlimit-name", 1, 0, '"' },
- { 0 }
-};
-
-static
-int parse_rate(const char *rate, u_int32_t *val)
-{
- const char *delim;
- u_int32_t r;
- u_int32_t mult = 1; /* Seconds by default. */
-
- delim = strchr(rate, '/');
- if (delim) {
- if (strlen(delim+1) == 0)
- return 0;
-
- if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
- mult = 1;
- else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
- mult = 60;
- else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
- mult = 60*60;
- else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
- mult = 24*60*60;
- else
- return 0;
- }
- r = atoi(rate);
- if (!r)
- return 0;
-
- /* This would get mapped to infinite (1/day is minimum they
- can specify, so we're ok at that end). */
- if (r / mult > XT_HASHLIMIT_SCALE)
- exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
-
- *val = XT_HASHLIMIT_SCALE * mult / r;
- return 1;
-}
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data;
-
- r->cfg.burst = XT_HASHLIMIT_BURST;
- r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
- r->cfg.expire = XT_HASHLIMIT_EXPIRE;
-
-}
-
-
-/* Parse a 'mode' parameter into the required bitmask */
-static int parse_mode(struct xt_hashlimit_info *r, char *optarg)
-{
- char *tok;
- char *arg = strdup(optarg);
-
- if (!arg)
- return -1;
-
- r->cfg.mode = 0;
-
- for (tok = strtok(arg, ",|");
- tok;
- tok = strtok(NULL, ",|")) {
- if (!strcmp(tok, "dstip"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_DIP;
- else if (!strcmp(tok, "srcip"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_SIP;
- else if (!strcmp(tok, "srcport"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_SPT;
- else if (!strcmp(tok, "dstport"))
- r->cfg.mode |= XT_HASHLIMIT_HASH_DPT;
- else {
- free(arg);
- return -1;
- }
- }
- free(arg);
- return 0;
-}
-
-#define PARAM_LIMIT 0x00000001
-#define PARAM_BURST 0x00000002
-#define PARAM_MODE 0x00000004
-#define PARAM_NAME 0x00000008
-#define PARAM_SIZE 0x00000010
-#define PARAM_MAX 0x00000020
-#define PARAM_GCINTERVAL 0x00000040
-#define PARAM_EXPIRE 0x00000080
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct xt_hashlimit_info *r =
- (struct xt_hashlimit_info *)(*match)->data;
- unsigned int num;
-
- switch(c) {
- case '%':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (!parse_rate(optarg, &r->cfg.avg))
- exit_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- *flags |= PARAM_LIMIT;
- break;
-
- case '$':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 10000, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-burst `%s'", optarg);
- r->cfg.burst = num;
- *flags |= PARAM_BURST;
- break;
- case '&':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-size: `%s'", optarg);
- r->cfg.size = num;
- *flags |= PARAM_SIZE;
- break;
- case '*':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-max: `%s'", optarg);
- r->cfg.max = num;
- *flags |= PARAM_MAX;
- break;
- case '(':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-gcinterval: `%s'",
- optarg);
- /* FIXME: not HZ dependent!! */
- r->cfg.gc_interval = num;
- *flags |= PARAM_GCINTERVAL;
- break;
- case ')':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-expire: `%s'", optarg);
- /* FIXME: not HZ dependent */
- r->cfg.expire = num;
- *flags |= PARAM_EXPIRE;
- break;
- case '_':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (parse_mode(r, optarg) < 0)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-mode: `%s'\n", optarg);
- *flags |= PARAM_MODE;
- break;
- case '"':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (strlen(optarg) == 0)
- exit_error(PARAMETER_PROBLEM, "Zero-length name?");
- strncpy(r->name, optarg, sizeof(r->name));
- *flags |= PARAM_NAME;
- break;
- default:
- return 0;
- }
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "hashlimit does not support invert");
-
- return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
- if (!(flags & PARAM_LIMIT))
- exit_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit");
- if (!(flags & PARAM_MODE))
- exit_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-mode");
- if (!(flags & PARAM_NAME))
- exit_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-name");
-}
-
-static struct rates
-{
- const char *name;
- u_int32_t mult;
-} rates[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
- { "hour", XT_HASHLIMIT_SCALE*60*60 },
- { "min", XT_HASHLIMIT_SCALE*60 },
- { "sec", XT_HASHLIMIT_SCALE } };
-
-static void print_rate(u_int32_t period)
-{
- unsigned int i;
-
- for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
- if (period > rates[i].mult
- || rates[i].mult/period < rates[i].mult%period)
- break;
- }
-
- printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
-}
-
-static void print_mode(const struct xt_hashlimit_info *r, char separator)
-{
- int prevmode = 0;
-
- if (r->cfg.mode & XT_HASHLIMIT_HASH_SIP) {
- if (prevmode)
- putchar(separator);
- fputs("srcip", stdout);
- prevmode = 1;
- }
- if (r->cfg.mode & XT_HASHLIMIT_HASH_SPT) {
- if (prevmode)
- putchar(separator);
- fputs("srcport", stdout);
- prevmode = 1;
- }
- if (r->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
- if (prevmode)
- putchar(separator);
- fputs("dstip", stdout);
- prevmode = 1;
- }
- if (r->cfg.mode & XT_HASHLIMIT_HASH_DPT) {
- if (prevmode)
- putchar(separator);
- fputs("dstport", stdout);
- }
- putchar(' ');
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct xt_hashlimit_info *r =
- (struct xt_hashlimit_info *)match->data;
- fputs("limit: avg ", stdout); print_rate(r->cfg.avg);
- printf("burst %u ", r->cfg.burst);
- fputs("mode ", stdout);
- print_mode(r, '-');
- if (r->cfg.size)
- printf("htable-size %u ", r->cfg.size);
- if (r->cfg.max)
- printf("htable-max %u ", r->cfg.max);
- if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
- printf("htable-gcinterval %u ", r->cfg.gc_interval);
- if (r->cfg.expire != XT_HASHLIMIT_EXPIRE)
- printf("htable-expire %u ", r->cfg.expire);
-}
-
-/* FIXME: Make minimalist: only print rate if not default --RR */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct xt_hashlimit_info *r =
- (struct xt_hashlimit_info *)match->data;
-
- fputs("--hashlimit ", stdout); print_rate(r->cfg.avg);
- if (r->cfg.burst != XT_HASHLIMIT_BURST)
- printf("--hashlimit-burst %u ", r->cfg.burst);
-
- fputs("--hashlimit-mode ", stdout);
- print_mode(r, ',');
-
- printf("--hashlimit-name %s ", r->name);
-
- if (r->cfg.size)
- printf("--hashlimit-htable-size %u ", r->cfg.size);
- if (r->cfg.max)
- printf("--hashlimit-htable-max %u ", r->cfg.max);
- if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
- printf("--hashlimit-htable-gcinterval %u", r->cfg.gc_interval);
- if (r->cfg.expire != XT_HASHLIMIT_EXPIRE)
- printf("--hashlimit-htable-expire %u ", r->cfg.expire);
-}
-
-static struct ip6tables_match hashlimit = { NULL,
- .name = "hashlimit",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct xt_hashlimit_info)),
- .userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_match6(&hashlimit);
-}
diff --git a/extensions/libip6t_hbh.c b/extensions/libip6t_hbh.c
index bdcbf9b..520ec9e 100644
--- a/extensions/libip6t_hbh.c
+++ b/extensions/libip6t_hbh.c
@@ -1,49 +1,35 @@
-/* Shared library add-on to ip6tables to add Hop-by-Hop and Dst headers support. */
+/* Shared library add-on to ip6tables to add Hop-by-Hop header support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#include <ip6tables.h>
+#include <xtables.h>
/*#include <linux/in6.h>*/
#include <linux/netfilter_ipv6/ip6t_opts.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-
+
#define DEBUG 0
-#define HOPBYHOP 1
-#define UNAME (HOPBYHOP ? "HBH" : "DST")
-#define LNAME (HOPBYHOP ? "hbh" : "dst")
-/* Function which prints out usage message. */
-static void
-help(void)
+static void hbh_help(void)
{
printf(
-"%s v%s options:\n"
-" --%s-len [!] length total length of this header\n"
-" --%s-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
-" Options and its length (list, max: %d)\n",
-UNAME , IPTABLES_VERSION, LNAME, LNAME, IP6T_OPTS_OPTSNR);
+"hbh match options:\n"
+"[!] --hbh-len length total length of this header\n"
+" --hbh-opts TYPE[:LEN][,TYPE[:LEN]...] \n"
+" Options and its length (list, max: %d)\n",
+IP6T_OPTS_OPTSNR);
}
-#if HOPBYHOP
-static struct option opts[] = {
- { "hbh-len", 1, 0, '1' },
- { "hbh-opts", 1, 0, '2' },
- { "hbh-not-strict", 1, 0, '3' },
- {0}
+static const struct option hbh_opts[] = {
+ { "hbh-len", 1, NULL, '1' },
+ { "hbh-opts", 1, NULL, '2' },
+ { "hbh-not-strict", 1, NULL, '3' },
+ { .name = NULL }
};
-#else
-static struct option opts[] = {
- { "dst-len", 1, 0, '1' },
- { "dst-opts", 1, 0, '2' },
- { "dst-not-strict", 1, 0, '3' },
- {0}
-};
-#endif
static u_int32_t
parse_opts_num(const char *idstr, const char *typestr)
@@ -54,19 +40,19 @@ parse_opts_num(const char *idstr, const char *typestr)
id = strtoul(idstr,&ep,0) ;
if ( idstr == ep ) {
- exit_error(PARAMETER_PROBLEM,
- "%s no valid digits in %s `%s'", UNAME, typestr, idstr);
+ xtables_error(PARAMETER_PROBLEM,
+ "hbh: no valid digits in %s `%s'", typestr, idstr);
}
if ( id == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"%s `%s' specified too big: would overflow",
typestr, idstr);
}
if ( *idstr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
- "%s error parsing %s `%s'", UNAME, typestr, idstr);
+ xtables_error(PARAMETER_PROBLEM,
+ "hbh: error parsing %s `%s'", typestr, idstr);
}
- return (u_int32_t) id;
+ return id;
}
static int
@@ -76,7 +62,7 @@ parse_options(const char *optsstr, u_int16_t *opts)
unsigned int i;
buffer = strdup(optsstr);
- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
+ if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
for (cp=buffer, i=0; cp && i<IP6T_OPTS_OPTSNR; cp=next,i++)
{
@@ -85,16 +71,15 @@ parse_options(const char *optsstr, u_int16_t *opts)
range = strchr(cp, ':');
if (range) {
if (i == IP6T_OPTS_OPTSNR-1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"too many ports specified");
*range++ = '\0';
}
- opts[i] = (u_int16_t)((parse_opts_num(cp,"opt") & 0x000000FF)<<8);
+ opts[i] = (parse_opts_num(cp, "opt") & 0xFF) << 8;
if (range) {
if (opts[i] == 0)
- exit_error(PARAMETER_PROBLEM, "PAD0 hasn't got length");
- opts[i] |= (u_int16_t)(parse_opts_num(range,"length") &
- 0x000000FF);
+ xtables_error(PARAMETER_PROBLEM, "PAD0 has not got length");
+ opts[i] |= parse_opts_num(range, "length") & 0xFF;
} else {
opts[i] |= (0x00FF);
}
@@ -104,7 +89,7 @@ parse_options(const char *optsstr, u_int16_t *opts)
printf("opts opt: %04X\n", opts[i]);
#endif
}
- if (cp) exit_error(PARAMETER_PROBLEM, "too many addresses specified");
+ if (cp) xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
free(buffer);
@@ -115,9 +100,7 @@ parse_options(const char *optsstr, u_int16_t *opts)
return i;
}
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void hbh_init(struct xt_entry_match *m)
{
struct ip6t_opts *optinfo = (struct ip6t_opts *)m->data;
@@ -127,23 +110,18 @@ init(struct ip6t_entry_match *m, unsigned int *nfcache)
optinfo->optsnr = 0;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+static int hbh_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_opts *optinfo = (struct ip6t_opts *)(*match)->data;
switch (c) {
case '1':
if (*flags & IP6T_OPTS_LEN)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--%s-len' allowed", LNAME);
- check_inverse(optarg, &invert, &optind, 0);
- optinfo->hdrlen = parse_opts_num(argv[optind-1], "length");
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--hbh-len' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ optinfo->hdrlen = parse_opts_num(optarg, "length");
if (invert)
optinfo->invflags |= IP6T_OPTS_INV_LEN;
optinfo->flags |= IP6T_OPTS_LEN;
@@ -151,23 +129,23 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '2':
if (*flags & IP6T_OPTS_OPTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--%s-opts' allowed", LNAME);
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--hbh-opts' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
if (invert)
- exit_error(PARAMETER_PROBLEM,
- " '!' not allowed with `--%s-opts'", LNAME);
- optinfo->optsnr = parse_options(argv[optind-1], optinfo->opts);
+ xtables_error(PARAMETER_PROBLEM,
+ " '!' not allowed with `--hbh-opts'");
+ optinfo->optsnr = parse_options(optarg, optinfo->opts);
optinfo->flags |= IP6T_OPTS_OPTS;
*flags |= IP6T_OPTS_OPTS;
break;
case '3':
if (*flags & IP6T_OPTS_NSTRICT)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--%s-not-strict' allowed", LNAME);
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--hbh-not-strict' allowed");
if ( !(*flags & IP6T_OPTS_OPTS) )
- exit_error(PARAMETER_PROBLEM,
- "`--%s-opts ...' required before `--%s-not-strict'", LNAME, LNAME);
+ xtables_error(PARAMETER_PROBLEM,
+ "`--hbh-opts ...' required before `--hbh-not-strict'");
optinfo->flags |= IP6T_OPTS_NSTRICT;
*flags |= IP6T_OPTS_NSTRICT;
break;
@@ -178,14 +156,8 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
static void
-final_check(unsigned int flags)
-{
-}
-
-static void
-print_options(int optsnr, u_int16_t *optsp)
+print_options(unsigned int optsnr, u_int16_t *optsp)
{
unsigned int i;
@@ -198,14 +170,12 @@ print_options(int optsnr, u_int16_t *optsp)
}
}
-/* Prints out the union ip6t_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
+static void hbh_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
- printf("%s ", LNAME);
+ printf("hbh ");
if (optinfo->flags & IP6T_OPTS_LEN) {
printf("length");
printf(":%s", optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : "");
@@ -220,43 +190,39 @@ print(const struct ip6t_ip6 *ip,
optinfo->invflags & ~IP6T_OPTS_INV_MASK);
}
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+static void hbh_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data;
if (optinfo->flags & IP6T_OPTS_LEN) {
- printf("--%s-len %s%u ", LNAME,
+ printf("%s--hbh-len %u ",
(optinfo->invflags & IP6T_OPTS_INV_LEN) ? "! " : "",
optinfo->hdrlen);
}
- if (optinfo->flags & IP6T_OPTS_OPTS) printf("--%s-opts ", LNAME);
+ if (optinfo->flags & IP6T_OPTS_OPTS)
+ printf("--hbh-opts ");
print_options(optinfo->optsnr, (u_int16_t *)optinfo->opts);
- if (optinfo->flags & IP6T_OPTS_NSTRICT) printf("--%s-not-strict ", LNAME);
-
+ if (optinfo->flags & IP6T_OPTS_NSTRICT)
+ printf("--hbh-not-strict ");
}
-static struct ip6tables_match optstruct = {
-#if HOPBYHOP
+static struct xtables_match hbh_mt6_reg = {
.name = "hbh",
-#else
- .name = "dst",
-#endif
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_opts)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_opts)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_opts)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)),
+ .help = hbh_help,
+ .init = hbh_init,
+ .parse = hbh_parse,
+ .print = hbh_print,
+ .save = hbh_save,
+ .extra_opts = hbh_opts,
};
void
_init(void)
{
- register_match6(&optstruct);
+ xtables_register_match(&hbh_mt6_reg);
}
diff --git a/extensions/libip6t_hbh.man b/extensions/libip6t_hbh.man
index 938e1f3..2d92e04 100644
--- a/extensions/libip6t_hbh.man
+++ b/extensions/libip6t_hbh.man
@@ -1,7 +1,7 @@
This module matches the parameters in Hop-by-Hop Options header
.TP
-.BR "--hbh-len " "[!] \fIlength\fP"
+[\fB!\fP] \fB\-\-hbh\-len\fP \fIlength\fP
Total length of this header in octets.
.TP
-.BR "--hbh-opts " "\fItype\fP[:\fIlength\fP][,\fItype\fP[:\fIlength\fP]...]"
+\fB\-\-hbh\-opts\fP \fItype\fP[\fB:\fP\fIlength\fP][\fB,\fP\fItype\fP[\fB:\fP\fIlength\fP]...]
numeric type of option and the length of the option data in octets.
diff --git a/extensions/libip6t_hl.c b/extensions/libip6t_hl.c
new file mode 100644
index 0000000..09589b1
--- /dev/null
+++ b/extensions/libip6t_hl.c
@@ -0,0 +1,144 @@
+/*
+ * IPv6 Hop Limit matching module
+ * Maciej Soltysiak <solt@dns.toxicfilms.tv>
+ * Based on HW's ttl match
+ * This program is released under the terms of GNU GPL
+ * Cleanups by Stephane Ouellette <ouellettes@videotron.ca>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <xtables.h>
+
+#include <linux/netfilter_ipv6/ip6t_hl.h>
+
+static void hl_help(void)
+{
+ printf(
+"hl match options:\n"
+"[!] --hl-eq value Match hop limit value\n"
+" --hl-lt value Match HL < value\n"
+" --hl-gt value Match HL > value\n");
+}
+
+static int hl_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ip6t_hl_info *info = (struct ip6t_hl_info *) (*match)->data;
+ u_int8_t value;
+
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ value = atoi(optarg);
+
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't specify HL option twice");
+
+ if (!optarg)
+ xtables_error(PARAMETER_PROBLEM,
+ "hl: You must specify a value");
+ switch (c) {
+ case '2':
+ if (invert)
+ info->mode = IP6T_HL_NE;
+ else
+ info->mode = IP6T_HL_EQ;
+
+ /* is 0 allowed? */
+ info->hop_limit = value;
+ *flags = 1;
+
+ break;
+ case '3':
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "hl: unexpected `!'");
+
+ info->mode = IP6T_HL_LT;
+ info->hop_limit = value;
+ *flags = 1;
+
+ break;
+ case '4':
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "hl: unexpected `!'");
+
+ info->mode = IP6T_HL_GT;
+ info->hop_limit = value;
+ *flags = 1;
+
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void hl_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "HL match: You must specify one of "
+ "`--hl-eq', `--hl-lt', `--hl-gt'");
+}
+
+static void hl_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ static const char *const op[] = {
+ [IP6T_HL_EQ] = "==",
+ [IP6T_HL_NE] = "!=",
+ [IP6T_HL_LT] = "<",
+ [IP6T_HL_GT] = ">" };
+
+ const struct ip6t_hl_info *info =
+ (struct ip6t_hl_info *) match->data;
+
+ printf("HL match HL %s %u ", op[info->mode], info->hop_limit);
+}
+
+static void hl_save(const void *ip, const struct xt_entry_match *match)
+{
+ static const char *const op[] = {
+ [IP6T_HL_EQ] = "--hl-eq",
+ [IP6T_HL_NE] = "! --hl-eq",
+ [IP6T_HL_LT] = "--hl-lt",
+ [IP6T_HL_GT] = "--hl-gt" };
+
+ const struct ip6t_hl_info *info =
+ (struct ip6t_hl_info *) match->data;
+
+ printf("%s %u ", op[info->mode], info->hop_limit);
+}
+
+static const struct option hl_opts[] = {
+ { .name = "hl", .has_arg = 1, .val = '2' },
+ { .name = "hl-eq", .has_arg = 1, .val = '2' },
+ { .name = "hl-lt", .has_arg = 1, .val = '3' },
+ { .name = "hl-gt", .has_arg = 1, .val = '4' },
+ { .name = NULL }
+};
+
+static struct xtables_match hl_mt6_reg = {
+ .name = "hl",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_hl_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_hl_info)),
+ .help = hl_help,
+ .parse = hl_parse,
+ .final_check = hl_check,
+ .print = hl_print,
+ .save = hl_save,
+ .extra_opts = hl_opts,
+};
+
+
+void _init(void)
+{
+ xtables_register_match(&hl_mt6_reg);
+}
diff --git a/extensions/libip6t_hl.man b/extensions/libip6t_hl.man
index d33e431..dfbfaf8 100644
--- a/extensions/libip6t_hl.man
+++ b/extensions/libip6t_hl.man
@@ -1,10 +1,10 @@
This module matches the Hop Limit field in the IPv6 header.
.TP
-.BR "--hl-eq " "[!] \fIvalue\fP"
+[\fB!\fP] \fB\-\-hl\-eq\fP \fIvalue\fP
Matches if Hop Limit equals \fIvalue\fP.
.TP
-.BI "--hl-lt " "value"
+\fB\-\-hl\-lt\fP \fIvalue\fP
Matches if Hop Limit is less than \fIvalue\fP.
.TP
-.BI "--hl-gt " "value"
+\fB\-\-hl\-gt\fP \fIvalue\fP
Matches if Hop Limit is greater than \fIvalue\fP.
diff --git a/extensions/libip6t_icmp6.c b/extensions/libip6t_icmp6.c
index 6940d0e..fb321b3 100644
--- a/extensions/libip6t_icmp6.c
+++ b/extensions/libip6t_icmp6.c
@@ -1,10 +1,11 @@
-/* Shared library add-on to iptables to add ICMP support. */
+/* Shared library add-on to ip6tables to add ICMP support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <ip6tables.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip6_tables.h */
#include <linux/netfilter_ipv6/ip6_tables.h>
struct icmpv6_names {
@@ -53,12 +54,12 @@ static const struct icmpv6_names icmpv6_codes[] = {
};
static void
-print_icmpv6types()
+print_icmpv6types(void)
{
unsigned int i;
printf("Valid ICMPv6 Types:");
- for (i = 0; i < sizeof(icmpv6_codes)/sizeof(struct icmpv6_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i) {
if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) {
if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min
&& (icmpv6_codes[i].code_max
@@ -73,27 +74,24 @@ print_icmpv6types()
printf("\n");
}
-/* Function which prints out usage message. */
-static void
-help(void)
+static void icmp6_help(void)
{
printf(
-"ICMPv6 v%s options:\n"
-" --icmpv6-type [!] typename match icmpv6 type\n"
-" (or numeric type or type/code)\n"
-"\n", IPTABLES_VERSION);
+"icmpv6 match options:\n"
+"[!] --icmpv6-type typename match icmpv6 type\n"
+" (or numeric type or type/code)\n");
print_icmpv6types();
}
-static struct option opts[] = {
- { "icmpv6-type", 1, 0, '1' },
- {0}
+static const struct option icmp6_opts[] = {
+ { "icmpv6-type", 1, NULL, '1' },
+ { .name = NULL }
};
static void
parse_icmpv6(const char *icmpv6type, u_int8_t *type, u_int8_t code[])
{
- unsigned int limit = sizeof(icmpv6_codes)/sizeof(struct icmpv6_names);
+ static const unsigned int limit = ARRAY_SIZE(icmpv6_codes);
unsigned int match = limit;
unsigned int i;
@@ -101,7 +99,7 @@ parse_icmpv6(const char *icmpv6type, u_int8_t *type, u_int8_t code[])
if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type))
== 0) {
if (match != limit)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Ambiguous ICMPv6 type `%s':"
" `%s' or `%s'?",
icmpv6type,
@@ -126,13 +124,13 @@ parse_icmpv6(const char *icmpv6type, u_int8_t *type, u_int8_t code[])
if (slash)
*slash = '\0';
- if (string_to_number(buffer, 0, 255, &number) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"Invalid ICMPv6 type `%s'\n", buffer);
*type = number;
if (slash) {
- if (string_to_number(slash+1, 0, 255, &number) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"Invalid ICMPv6 code `%s'\n",
slash+1);
code[0] = code[1] = number;
@@ -143,32 +141,25 @@ parse_icmpv6(const char *icmpv6type, u_int8_t *type, u_int8_t code[])
}
}
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void icmp6_init(struct xt_entry_match *m)
{
struct ip6t_icmp *icmpv6info = (struct ip6t_icmp *)m->data;
icmpv6info->code[1] = 0xFF;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+static int icmp6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_icmp *icmpv6info = (struct ip6t_icmp *)(*match)->data;
switch (c) {
case '1':
if (*flags == 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"icmpv6 match: only use --icmpv6-type once!");
- check_inverse(optarg, &invert, &optind, 0);
- parse_icmpv6(argv[optind-1], &icmpv6info->type,
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_icmpv6(optarg, &icmpv6info->type,
icmpv6info->code);
if (invert)
icmpv6info->invflags |= IP6T_ICMP_INV;
@@ -190,16 +181,13 @@ static void print_icmpv6type(u_int8_t type,
if (!numeric) {
unsigned int i;
- for (i = 0;
- i < sizeof(icmpv6_codes)/sizeof(struct icmpv6_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(icmpv6_codes); ++i)
if (icmpv6_codes[i].type == type
&& icmpv6_codes[i].code_min == code_min
&& icmpv6_codes[i].code_max == code_max)
break;
- }
- if (i != sizeof(icmpv6_codes)/sizeof(struct icmpv6_names)) {
+ if (i != ARRAY_SIZE(icmpv6_codes)) {
printf("%s%s ",
invert ? "!" : "",
icmpv6_codes[i].name);
@@ -219,11 +207,8 @@ static void print_icmpv6type(u_int8_t type,
printf(" codes %u-%u ", code_min, code_max);
}
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
+static void icmp6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ip6t_icmp *icmpv6 = (struct ip6t_icmp *)match->data;
@@ -237,8 +222,7 @@ print(const struct ip6t_ip6 *ip,
icmpv6->invflags & ~IP6T_ICMP_INV);
}
-/* Saves the match in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+static void icmp6_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_icmp *icmpv6 = (struct ip6t_icmp *)match->data;
@@ -251,28 +235,29 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
printf(" ");
}
-static void final_check(unsigned int flags)
+static void icmp6_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"icmpv6 match: You must specify `--icmpv6-type'");
}
-static struct ip6tables_match icmpv6 = {
+static struct xtables_match icmp6_mt6_reg = {
.name = "icmp6",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_icmp)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_icmp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_icmp)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_icmp)),
+ .help = icmp6_help,
+ .init = icmp6_init,
+ .parse = icmp6_parse,
+ .final_check = icmp6_check,
+ .print = icmp6_print,
+ .save = icmp6_save,
+ .extra_opts = icmp6_opts,
};
void _init(void)
{
- register_match6(&icmpv6);
+ xtables_register_match(&icmp6_mt6_reg);
}
diff --git a/extensions/libip6t_icmp6.man b/extensions/libip6t_icmp6.man
index 2047180..817e21c 100644
--- a/extensions/libip6t_icmp6.man
+++ b/extensions/libip6t_icmp6.man
@@ -1,7 +1,7 @@
-This extension is loaded if `--protocol ipv6-icmp' or `--protocol icmpv6' is
+This extension can be used if `\-\-protocol ipv6\-icmp' or `\-\-protocol icmpv6' is
specified. It provides the following option:
.TP
-.BR "--icmpv6-type " "[!] \fItype\fP[/\fIcode\fP]|\fItypename\fP"
+[\fB!\fP] \fB\-\-icmpv6\-type\fP \fItype\fP[\fB/\fP\fIcode\fP]|\fItypename\fP
This allows specification of the ICMPv6 type, which can be a numeric
ICMPv6
.IR type ,
@@ -10,5 +10,5 @@ and
.IR code ,
or one of the ICMPv6 type names shown by the command
.nf
- ip6tables -p ipv6-icmp -h
+ ip6tables \-p ipv6\-icmp \-h
.fi
diff --git a/extensions/libip6t_ipv6header.c b/extensions/libip6t_ipv6header.c
index a260e6e..af1f5ef 100644
--- a/extensions/libip6t_ipv6header.c
+++ b/extensions/libip6t_ipv6header.c
@@ -5,7 +5,7 @@ on whether they contain certain headers */
* Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
#include <getopt.h>
-#include <ip6tables.h>
+#include <xtables.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -13,7 +13,6 @@ on whether they contain certain headers */
#include <netdb.h>
#include <sys/types.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_ipv6header.h>
/* This maybe required
@@ -78,7 +77,7 @@ proto_to_name(u_int8_t proto, int nolookup)
return pent->p_name;
}
- for (i = 0; i < sizeof(chain_protos)/sizeof(struct pprot); i++)
+ for (i = 0; i < ARRAY_SIZE(chain_protos); ++i)
if (chain_protos[i].num == proto)
return chain_protos[i].name;
@@ -95,67 +94,58 @@ name_to_proto(const char *s)
proto = pent->p_proto;
else {
unsigned int i;
- for (i = 0;
- i < sizeof(chain_protos)/sizeof(struct pprot);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(chain_protos); ++i)
if (strcmp(s, chain_protos[i].name) == 0) {
proto = chain_protos[i].num;
break;
}
- }
- if (i == sizeof(chain_protos)/sizeof(struct pprot))
- exit_error(PARAMETER_PROBLEM,
+ if (i == ARRAY_SIZE(chain_protos))
+ xtables_error(PARAMETER_PROBLEM,
"unknown header `%s' specified",
s);
}
- return (u_int16_t)proto;
+ return proto;
}
static unsigned int
add_proto_to_mask(int proto){
unsigned int i=0, flag=0;
- for (i = 0;
- i < sizeof(chain_flags)/sizeof(struct numflag);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(chain_flags); ++i)
if (proto == chain_flags[i].proto){
flag = chain_flags[i].flag;
break;
}
- }
- if (i == sizeof(chain_flags)/sizeof(struct numflag))
- exit_error(PARAMETER_PROBLEM,
+ if (i == ARRAY_SIZE(chain_flags))
+ xtables_error(PARAMETER_PROBLEM,
"unknown header `%d' specified",
proto);
return flag;
}
-static void
-help(void)
+static void ipv6header_help(void)
{
printf(
-"ipv6header v%s match options:\n"
-"--header [!] headers Type of header to match, by name\n"
+"ipv6header match options:\n"
+"[!] --header headers Type of header to match, by name\n"
" names: hop,dst,route,frag,auth,esp,none,proto\n"
" long names: hop-by-hop,ipv6-opts,ipv6-route,\n"
" ipv6-frag,ah,esp,ipv6-nonxt,protocol\n"
" numbers: 0,60,43,44,51,50,59\n"
-"--soft The header CONTAINS the specified extensions\n",
- IPTABLES_VERSION);
+"--soft The header CONTAINS the specified extensions\n");
}
-static struct option opts[] = {
- { "header", 1, 0, '1' },
- { "soft", 0, 0, '2' },
- { 0 }
+static const struct option ipv6header_opts[] = {
+ { "header", 1, NULL, '1' },
+ { "soft", 0, NULL, '2' },
+ { .name = NULL }
};
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void ipv6header_init(struct xt_entry_match *m)
{
struct ip6t_ipv6header_info *info = (struct ip6t_ipv6header_info *)m->data;
@@ -182,12 +172,9 @@ parse_header(const char *flags) {
#define IPV6_HDR_HEADER 0x01
#define IPV6_HDR_SOFT 0x02
-/* Parses command options; returns 0 if it ate an option */
static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+ipv6header_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_ipv6header_info *info = (struct ip6t_ipv6header_info *)(*match)->data;
@@ -195,13 +182,13 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '1' :
/* Parse the provided header names */
if (*flags & IPV6_HDR_HEADER)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--header' allowed");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
- if (! (info->matchflags = parse_header(argv[optind-1])) )
- exit_error(PARAMETER_PROBLEM, "ip6t_ipv6header: cannot parse header names");
+ if (! (info->matchflags = parse_header(optarg)) )
+ xtables_error(PARAMETER_PROBLEM, "ip6t_ipv6header: cannot parse header names");
if (invert)
info->invflags |= 0xFF;
@@ -210,7 +197,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '2' :
/* Soft-mode requested? */
if (*flags & IPV6_HDR_SOFT)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--soft' allowed");
info->modeflag |= 0xFF;
@@ -223,11 +210,9 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Checks the flags variable */
-static void
-final_check(unsigned int flags)
+static void ipv6header_check(unsigned int flags)
{
- if (!flags) exit_error(PARAMETER_PROBLEM, "ip6t_ipv6header: no options specified");
+ if (!flags) xtables_error(PARAMETER_PROBLEM, "ip6t_ipv6header: no options specified");
}
static void
@@ -252,11 +237,8 @@ print_header(u_int8_t flags){
printf("NONE");
}
-/* Prints out the match */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
+static void ipv6header_print(const void *ip,
+ const struct xt_entry_match *match, int numeric)
{
const struct ip6t_ipv6header_info *info = (const struct ip6t_ipv6header_info *)match->data;
printf("ipv6header ");
@@ -273,44 +255,36 @@ print(const struct ip6t_ip6 *ip,
if (info->modeflag)
printf("soft ");
-
- return;
}
-/* Saves the match */
-static void
-save(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match)
+static void ipv6header_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_ipv6header_info *info = (const struct ip6t_ipv6header_info *)match->data;
- printf("--header ");
- printf("%s", info->invflags ? "!" : "");
+ printf("%s--header ", info->invflags ? "! " : "");
print_header(info->matchflags);
printf(" ");
if (info->modeflag)
printf("--soft ");
-
- return;
}
-static
-struct ip6tables_match ipv6header = {
+static struct xtables_match ipv6header_mt6_reg = {
.name = "ipv6header",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_ipv6header_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_ipv6header_info)),
+ .help = ipv6header_help,
+ .init = ipv6header_init,
+ .parse = ipv6header_parse,
+ .final_check = ipv6header_check,
+ .print = ipv6header_print,
+ .save = ipv6header_save,
+ .extra_opts = ipv6header_opts,
};
void _init(void)
{
- register_match6(&ipv6header);
+ xtables_register_match(&ipv6header_mt6_reg);
}
diff --git a/extensions/libip6t_ipv6header.man b/extensions/libip6t_ipv6header.man
index fe3fe98..a998861 100644
--- a/extensions/libip6t_ipv6header.man
+++ b/extensions/libip6t_ipv6header.man
@@ -1,29 +1,37 @@
This module matches IPv6 extension headers and/or upper layer header.
.TP
-.BR "--header " "[!] \fIheader\fP[,\fIheader\fP...]"
+\fB\-\-soft\fP
+Matches if the packet includes \fBany\fP of the headers specified with
+\fB\-\-header\fP.
+.TP
+[\fB!\fP] \fB\-\-header\fP \fIheader\fP[\fB,\fP\fIheader\fP...]
Matches the packet which EXACTLY includes all specified headers. The headers
encapsulated with ESP header are out of scope.
-.IR header
-can be
-.IR hop | hop-by-hop
-(Hop-by-Hop Options header),
-.IR dst
-(Destination Options header),
-.IR route
-(Routing header),
-.IR frag
-(Fragment header),
-.IR auth
-(Authentication header),
-.IR esp
-(Encapsulating Security Payload header),
-.IR none
-(No Next header) which matches 59 in the 'Next Header field' of IPv6 header or any IPv6 extension headers, or
-.IR proto
-which matches any upper layer protocol header. A protocol name from /etc/protocols and numeric value also allowed. The number 255 is equivalent to
-.IR proto .
-.TP
-.BR "[--soft]"
-Matches if the packet includes all specified headers with
-.BR --header ,
-AT LEAST.
+Possible \fIheader\fP types can be:
+.TP
+\fBhop\fP|\fBhop\-by\-hop\fP
+Hop-by-Hop Options header
+.TP
+\fBdst\fP
+Destination Options header
+.TP
+\fBroute\fP
+Routing header
+.TP
+\fBfrag\fP
+Fragment header
+.TP
+\fBauth\fP
+Authentication header
+.TP
+\fBesp\fP
+Encapsulating Security Payload header
+.TP
+\fBnone\fP
+No Next header which matches 59 in the 'Next Header field' of IPv6 header or
+any IPv6 extension headers
+.TP
+\fBproto\fP
+which matches any upper layer protocol header. A protocol name from
+/etc/protocols and numeric value also allowed. The number 255 is equivalent to
+\fBproto\fP.
diff --git a/extensions/libip6t_length.c b/extensions/libip6t_length.c
deleted file mode 100644
index 9f7ba16..0000000
--- a/extensions/libip6t_length.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* Shared library add-on to ip6tables to add packet length matching support. */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_length.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"length v%s options:\n"
-"[!] --length length[:length] Match packet length against value or range\n"
-" of values (inclusive)\n",
-IPTABLES_VERSION);
-
-}
-
-static struct option opts[] = {
- { "length", 1, 0, '1' },
- {0}
-};
-
-static u_int16_t
-parse_length(const char *s)
-{
-
- unsigned int len;
-
- if (string_to_number(s, 0, 0xFFFF, &len) == -1)
- exit_error(PARAMETER_PROBLEM, "length invalid: `%s'\n", s);
- else
- return (u_int16_t )len;
-}
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_lengths(const char *s, struct ip6t_length_info *info)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(s);
- if ((cp = strchr(buffer, ':')) == NULL)
- info->min = info->max = parse_length(buffer);
- else {
- *cp = '\0';
- cp++;
-
- info->min = buffer[0] ? parse_length(buffer) : 0;
- info->max = cp[0] ? parse_length(cp) : 0xFFFF;
- }
- free(buffer);
-
- if (info->min > info->max)
- exit_error(PARAMETER_PROBLEM,
- "length min. range value `%u' greater than max. "
- "range value `%u'", info->min, info->max);
-
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_length_info *info = (struct ip6t_length_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "length: `--length' may only be "
- "specified once");
- check_inverse(optarg, &invert, &optind, 0);
- parse_lengths(argv[optind-1], info);
- if (invert)
- info->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-/* Final check; must have specified --length. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "length: You must specify `--length'");
-}
-
-/* Common match printing code. */
-static void
-print_length(struct ip6t_length_info *info)
-{
- if (info->invert)
- printf("! ");
-
- if (info->max == info->min)
- printf("%u ", info->min);
- else
- printf("%u:%u ", info->min, info->max);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- printf("length ");
- print_length((struct ip6t_length_info *)match->data);
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- printf("--length ");
- print_length((struct ip6t_length_info *)match->data);
-}
-
-struct ip6tables_match length = {
- .name = "length",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_length_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_length_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_match6(&length);
-}
diff --git a/extensions/libip6t_length.man b/extensions/libip6t_length.man
deleted file mode 100644
index d781a04..0000000
--- a/extensions/libip6t_length.man
+++ /dev/null
@@ -1,4 +0,0 @@
-This module matches the length of the IPv6 payload in octets, or range of it.
-IPv6 header itself isn't counted.
-.TP
-.BR "--length " "[!] \fIlength\fP[:\fIlength\fP]"
diff --git a/extensions/libip6t_limit.c b/extensions/libip6t_limit.c
deleted file mode 100644
index 6c88ee1..0000000
--- a/extensions/libip6t_limit.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Shared library add-on to iptables to add limit support.
- *
- * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne <rv@wallfire.org>
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <stddef.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv6/ip6t_limit.h"
-
-#define IP6T_LIMIT_AVG "3/hour"
-#define IP6T_LIMIT_BURST 5
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"limit v%s options:\n"
-"--limit avg max average match rate: default "IP6T_LIMIT_AVG"\n"
-" [Packets per second unless followed by \n"
-" /sec /minute /hour /day postfixes]\n"
-"--limit-burst number number to match in a burst, default %u\n"
-"\n", IPTABLES_VERSION, IP6T_LIMIT_BURST);
-}
-
-static struct option opts[] = {
- { "limit", 1, 0, '%' },
- { "limit-burst", 1, 0, '$' },
- { 0 }
-};
-
-static
-int parse_rate(const char *rate, u_int32_t *val)
-{
- const char *delim;
- u_int32_t r;
- u_int32_t mult = 1; /* Seconds by default. */
-
- delim = strchr(rate, '/');
- if (delim) {
- if (strlen(delim+1) == 0)
- return 0;
-
- if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
- mult = 1;
- else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
- mult = 60;
- else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
- mult = 60*60;
- else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
- mult = 24*60*60;
- else
- return 0;
- }
- r = atoi(rate);
- if (!r)
- return 0;
-
- /* This would get mapped to infinite (1/day is minimum they
- can specify, so we're ok at that end). */
- if (r / mult > IP6T_LIMIT_SCALE)
- exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
-
- *val = IP6T_LIMIT_SCALE * mult / r;
- return 1;
-}
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)m->data;
-
- parse_rate(IP6T_LIMIT_AVG, &r->avg);
- r->burst = IP6T_LIMIT_BURST;
-
-}
-
-/* FIXME: handle overflow:
- if (r->avg*r->burst/r->burst != r->avg)
- exit_error(PARAMETER_PROBLEM,
- "Sorry: burst too large for that avg rate.\n");
-*/
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)(*match)->data;
- unsigned int num;
-
- switch(c) {
- case '%':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (!parse_rate(optarg, &r->avg))
- exit_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- break;
-
- case '$':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 10000, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --limit-burst `%s'", optarg);
- r->burst = num;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "limit does not support invert");
-
- return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-static struct rates
-{
- const char *name;
- u_int32_t mult;
-} rates[] = { { "day", IP6T_LIMIT_SCALE*24*60*60 },
- { "hour", IP6T_LIMIT_SCALE*60*60 },
- { "min", IP6T_LIMIT_SCALE*60 },
- { "sec", IP6T_LIMIT_SCALE } };
-
-static void print_rate(u_int32_t period)
-{
- unsigned int i;
-
- for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
- if (period > rates[i].mult
- || rates[i].mult % period != 0)
- break;
- }
-
- printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)match->data;
- printf("limit: avg "); print_rate(r->avg);
- printf("burst %u ", r->burst);
-}
-
-/* FIXME: Make minimalist: only print rate if not default --RR */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct ip6t_rateinfo *r = (struct ip6t_rateinfo *)match->data;
-
- printf("--limit "); print_rate(r->avg);
- if (r->burst != IP6T_LIMIT_BURST)
- printf("--limit-burst %u ", r->burst);
-}
-
-static struct ip6tables_match limit = {
- .name = "limit",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_rateinfo)),
- .userspacesize = offsetof(struct ip6t_rateinfo, prev),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_match6(&limit);
-}
diff --git a/extensions/libip6t_limit.man b/extensions/libip6t_limit.man
deleted file mode 100644
index 84b63d4..0000000
--- a/extensions/libip6t_limit.man
+++ /dev/null
@@ -1,15 +0,0 @@
-This module matches at a limited rate using a token bucket filter.
-A rule using this extension will match until this limit is reached
-(unless the `!' flag is used). It can be used in combination with the
-.B LOG
-target to give limited logging, for example.
-.TP
-.BI "--limit " "rate"
-Maximum average matching rate: specified as a number, with an optional
-`/second', `/minute', `/hour', or `/day' suffix; the default is
-3/hour.
-.TP
-.BI "--limit-burst " "number"
-Maximum initial number of packets to match: this number gets
-recharged by one every time the limit specified above is not reached,
-up to this number; the default is 5.
diff --git a/extensions/libip6t_mac.c b/extensions/libip6t_mac.c
deleted file mode 100644
index e47f21f..0000000
--- a/extensions/libip6t_mac.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Shared library add-on to iptables to add MAC address support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_mac.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MAC v%s options:\n"
-" --mac-source [!] XX:XX:XX:XX:XX:XX\n"
-" Match source MAC address\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mac-source", 1, 0, '1' },
- {0}
-};
-
-static void
-parse_mac(const char *mac, struct ip6t_mac_info *info)
-{
- unsigned int i = 0;
-
- if (strlen(mac) != ETH_ALEN*3-1)
- exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
-
- for (i = 0; i < ETH_ALEN; i++) {
- long number;
- char *end;
-
- number = strtol(mac + i*3, &end, 16);
-
- if (end == mac + i*3 + 2
- && number >= 0
- && number <= 255)
- info->srcaddr[i] = number;
- else
- exit_error(PARAMETER_PROBLEM,
- "Bad mac address `%s'", mac);
- }
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_mac_info *macinfo = (struct ip6t_mac_info *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
- parse_mac(argv[optind-1], macinfo);
- if (invert)
- macinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void print_mac(unsigned char macaddress[ETH_ALEN])
-{
- unsigned int i;
-
- printf("%02X", macaddress[0]);
- for (i = 1; i < ETH_ALEN; i++)
- printf(":%02X", macaddress[i]);
- printf(" ");
-}
-
-/* Final check; must have specified --mac. */
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "You must specify `--mac-source'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- printf("MAC ");
-
- if (((struct ip6t_mac_info *)match->data)->invert)
- printf("! ");
-
- print_mac(((struct ip6t_mac_info *)match->data)->srcaddr);
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- if (((struct ip6t_mac_info *)match->data)->invert)
- printf("! ");
-
- printf("--mac-source ");
- print_mac(((struct ip6t_mac_info *)match->data)->srcaddr);
-}
-
-static struct ip6tables_match mac = {
- .name = "mac",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_mac_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_mac_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_match6(&mac);
-}
diff --git a/extensions/libip6t_mh.c b/extensions/libip6t_mh.c
new file mode 100644
index 0000000..95cd65d
--- /dev/null
+++ b/extensions/libip6t_mh.c
@@ -0,0 +1,240 @@
+/* Shared library add-on to ip6tables to add mobility header support. */
+/*
+ * Copyright (C)2006 USAGI/WIDE Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Author:
+ * Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
+ *
+ * Based on libip6t_{icmpv6,udp}.c
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv6/ip6t_mh.h>
+
+struct mh_name {
+ const char *name;
+ u_int8_t type;
+};
+
+static const struct mh_name mh_names[] = {
+ { "binding-refresh-request", 0, },
+ /* Alias */ { "brr", 0, },
+ { "home-test-init", 1, },
+ /* Alias */ { "hoti", 1, },
+ { "careof-test-init", 2, },
+ /* Alias */ { "coti", 2, },
+ { "home-test", 3, },
+ /* Alias */ { "hot", 3, },
+ { "careof-test", 4, },
+ /* Alias */ { "cot", 4, },
+ { "binding-update", 5, },
+ /* Alias */ { "bu", 5, },
+ { "binding-acknowledgement", 6, },
+ /* Alias */ { "ba", 6, },
+ { "binding-error", 7, },
+ /* Alias */ { "be", 7, },
+};
+
+static void print_types_all(void)
+{
+ unsigned int i;
+ printf("Valid MH types:");
+
+ for (i = 0; i < ARRAY_SIZE(mh_names); ++i) {
+ if (i && mh_names[i].type == mh_names[i-1].type)
+ printf(" (%s)", mh_names[i].name);
+ else
+ printf("\n%s", mh_names[i].name);
+ }
+ printf("\n");
+}
+
+static void mh_help(void)
+{
+ printf(
+"mh match options:\n"
+"[!] --mh-type type[:type] match mh type\n");
+ print_types_all();
+}
+
+static void mh_init(struct xt_entry_match *m)
+{
+ struct ip6t_mh *mhinfo = (struct ip6t_mh *)m->data;
+
+ mhinfo->types[1] = 0xFF;
+}
+
+static unsigned int name_to_type(const char *name)
+{
+ int namelen = strlen(name);
+ static const unsigned int limit = ARRAY_SIZE(mh_names);
+ unsigned int match = limit;
+ unsigned int i;
+
+ for (i = 0; i < limit; i++) {
+ if (strncasecmp(mh_names[i].name, name, namelen) == 0) {
+ int len = strlen(mh_names[i].name);
+ if (match == limit || len == namelen)
+ match = i;
+ }
+ }
+
+ if (match != limit) {
+ return mh_names[match].type;
+ } else {
+ unsigned int number;
+
+ if (!xtables_strtoui(name, NULL, &number, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid MH type `%s'\n", name);
+ return number;
+ }
+}
+
+static void parse_mh_types(const char *mhtype, u_int8_t *types)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(mhtype);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ types[0] = types[1] = name_to_type(buffer);
+ else {
+ *cp = '\0';
+ cp++;
+
+ types[0] = buffer[0] ? name_to_type(buffer) : 0;
+ types[1] = cp[0] ? name_to_type(cp) : 0xFF;
+
+ if (types[0] > types[1])
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid MH type range (min > max)");
+ }
+ free(buffer);
+}
+
+#define MH_TYPES 0x01
+
+static int mh_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ip6t_mh *mhinfo = (struct ip6t_mh *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & MH_TYPES)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--mh-type' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_mh_types(optarg, mhinfo->types);
+ if (invert)
+ mhinfo->invflags |= IP6T_MH_INV_TYPE;
+ *flags |= MH_TYPES;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static const char *type_to_name(u_int8_t type)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(mh_names); ++i)
+ if (mh_names[i].type == type)
+ return mh_names[i].name;
+
+ return NULL;
+}
+
+static void print_type(u_int8_t type, int numeric)
+{
+ const char *name;
+ if (numeric || !(name = type_to_name(type)))
+ printf("%u", type);
+ else
+ printf("%s", name);
+}
+
+static void print_types(u_int8_t min, u_int8_t max, int invert, int numeric)
+{
+ const char *inv = invert ? "!" : "";
+
+ if (min != 0 || max != 0xFF || invert) {
+ if (min == max) {
+ printf("%s", inv);
+ print_type(min, numeric);
+ } else {
+ printf("%s", inv);
+ print_type(min, numeric);
+ printf(":");
+ print_type(max, numeric);
+ }
+ printf(" ");
+ }
+}
+
+static void mh_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+ printf("mh ");
+ print_types(mhinfo->types[0], mhinfo->types[1],
+ mhinfo->invflags & IP6T_MH_INV_TYPE,
+ numeric);
+ if (mhinfo->invflags & ~IP6T_MH_INV_MASK)
+ printf("Unknown invflags: 0x%X ",
+ mhinfo->invflags & ~IP6T_MH_INV_MASK);
+}
+
+static void mh_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
+
+ if (mhinfo->types[0] == 0 && mhinfo->types[1] == 0xFF)
+ return;
+
+ if (mhinfo->invflags & IP6T_MH_INV_TYPE)
+ printf("! ");
+
+ if (mhinfo->types[0] != mhinfo->types[1])
+ printf("--mh-type %u:%u ", mhinfo->types[0], mhinfo->types[1]);
+ else
+ printf("--mh-type %u ", mhinfo->types[0]);
+}
+
+static const struct option mh_opts[] = {
+ { "mh-type", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static struct xtables_match mh_mt6_reg = {
+ .name = "mh",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_mh)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_mh)),
+ .help = mh_help,
+ .init = mh_init,
+ .parse = mh_parse,
+ .print = mh_print,
+ .save = mh_save,
+ .extra_opts = mh_opts,
+};
+
+void _init(void)
+{
+ xtables_register_match(&mh_mt6_reg);
+}
diff --git a/extensions/libip6t_mh.man b/extensions/libip6t_mh.man
new file mode 100644
index 0000000..4559e78
--- /dev/null
+++ b/extensions/libip6t_mh.man
@@ -0,0 +1,12 @@
+This extension is loaded if `\-\-protocol ipv6\-mh' or `\-\-protocol mh' is
+specified. It provides the following option:
+.TP
+[\fB!\fP] \fB\-\-mh\-type\fP \fItype\fP[\fB:\fP\fItype\fP]
+This allows specification of the Mobility Header(MH) type, which can be
+a numeric MH
+.IR type ,
+.IR type
+or one of the MH type names shown by the command
+.nf
+ ip6tables \-p ipv6\-mh \-h
+.fi
diff --git a/extensions/libip6t_multiport.c b/extensions/libip6t_multiport.c
deleted file mode 100644
index 166abce..0000000
--- a/extensions/libip6t_multiport.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/* Shared library add-on to iptables to add multiple TCP port support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-/* To ensure that iptables compiles with an old kernel */
-#include "../include/linux/netfilter_ipv6/ip6t_multiport.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"multiport v%s options:\n"
-" --source-ports port[,port,port...]\n"
-" --sports ...\n"
-" match source port(s)\n"
-" --destination-ports port[,port,port...]\n"
-" --dports ...\n"
-" match destination port(s)\n"
-" --ports port[,port,port]\n"
-" match both source and destination port(s)\n"
-" NOTE: this kernel does not support port ranges in multiport.\n",
-IPTABLES_VERSION);
-}
-
-static void
-help_v1(void)
-{
- printf(
-"multiport v%s options:\n"
-" --source-ports [!] port[,port:port,port...]\n"
-" --sports ...\n"
-" match source port(s)\n"
-" --destination-ports [!] port[,port:port,port...]\n"
-" --dports ...\n"
-" match destination port(s)\n"
-" --ports [!] port[,port:port,port]\n"
-" match both source and destination port(s)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "source-ports", 1, 0, '1' },
- { "sports", 1, 0, '1' }, /* synonym */
- { "destination-ports", 1, 0, '2' },
- { "dports", 1, 0, '2' }, /* synonym */
- { "ports", 1, 0, '3' },
- {0}
-};
-
-static char *
-proto_to_name(u_int8_t proto)
-{
- switch (proto) {
- case IPPROTO_TCP:
- return "tcp";
- case IPPROTO_UDP:
- return "udp";
- case IPPROTO_SCTP:
- return "sctp";
- case IPPROTO_DCCP:
- return "dccp";
- default:
- return NULL;
- }
-}
-
-static unsigned int
-parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
-{
- char *buffer, *cp, *next;
- unsigned int i;
-
- buffer = strdup(portstring);
- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
-
- for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next,i++)
- {
- next=strchr(cp, ',');
- if (next) *next++='\0';
- ports[i] = parse_port(cp, proto);
- }
- if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
- free(buffer);
- return i;
-}
-
-static void
-parse_multi_ports_v1(const char *portstring,
- struct ip6t_multiport_v1 *multiinfo,
- const char *proto)
-{
- char *buffer, *cp, *next, *range;
- unsigned int i;
- u_int16_t m;
-
- buffer = strdup(portstring);
- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
-
- for (i=0; i<IP6T_MULTI_PORTS; i++)
- multiinfo->pflags[i] = 0;
-
- for (cp=buffer, i=0; cp && i<IP6T_MULTI_PORTS; cp=next, i++) {
- next=strchr(cp, ',');
- if (next) *next++='\0';
- range = strchr(cp, ':');
- if (range) {
- if (i == IP6T_MULTI_PORTS-1)
- exit_error(PARAMETER_PROBLEM,
- "too many ports specified");
- *range++ = '\0';
- }
- multiinfo->ports[i] = parse_port(cp, proto);
- if (range) {
- multiinfo->pflags[i] = 1;
- multiinfo->ports[++i] = parse_port(range, proto);
- if (multiinfo->ports[i-1] >= multiinfo->ports[i])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange specified");
- m <<= 1;
- }
- }
- multiinfo->count = i;
- if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
- free(buffer);
-}
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
-}
-
-static const char *
-check_proto(const struct ip6t_entry *entry)
-{
- char *proto;
-
- if ((proto = proto_to_name(entry->ipv6.proto)) != NULL)
- return proto;
- else if (!entry->ipv6.proto)
- exit_error(PARAMETER_PROBLEM,
- "multiport needs `-p tcp', `-p udp', `-p sctp' or `-p dccp'");
- else
- exit_error(PARAMETER_PROBLEM,
- "multiport only works with TCP, UDP, SCTP and DCCP");
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- const char *proto;
- struct ip6t_multiport *multiinfo
- = (struct ip6t_multiport *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- multiinfo->count = parse_multi_ports(argv[optind-1],
- multiinfo->ports, proto);
- multiinfo->flags = IP6T_MULTIPORT_SOURCE;
- break;
-
- case '2':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- multiinfo->count = parse_multi_ports(argv[optind-1],
- multiinfo->ports, proto);
- multiinfo->flags = IP6T_MULTIPORT_DESTINATION;
- break;
-
- case '3':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- multiinfo->count = parse_multi_ports(argv[optind-1],
- multiinfo->ports, proto);
- multiinfo->flags = IP6T_MULTIPORT_EITHER;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "multiport does not support invert");
-
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
-}
-
-static int
-parse_v1(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- const char *proto;
- struct ip6t_multiport_v1 *multiinfo
- = (struct ip6t_multiport_v1 *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
- multiinfo->flags = IP6T_MULTIPORT_SOURCE;
- break;
-
- case '2':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
- multiinfo->flags = IP6T_MULTIPORT_DESTINATION;
- break;
-
- case '3':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
- multiinfo->flags = IP6T_MULTIPORT_EITHER;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- multiinfo->invert = 1;
-
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
-}
-
-/* Final check; must specify something. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, "multiport expection an option");
-}
-
-static char *
-port_to_service(int port, u_int8_t proto)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), proto_to_name(proto))))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, u_int8_t protocol, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port, protocol)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- const struct ip6t_multiport *multiinfo
- = (const struct ip6t_multiport *)match->data;
- unsigned int i;
-
- printf("multiport ");
-
- switch (multiinfo->flags) {
- case IP6T_MULTIPORT_SOURCE:
- printf("sports ");
- break;
-
- case IP6T_MULTIPORT_DESTINATION:
- printf("dports ");
- break;
-
- case IP6T_MULTIPORT_EITHER:
- printf("ports ");
- break;
-
- default:
- printf("ERROR ");
- break;
- }
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, numeric);
- }
- printf(" ");
-}
-
-static void
-print_v1(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- const struct ip6t_multiport_v1 *multiinfo
- = (const struct ip6t_multiport_v1 *)match->data;
- unsigned int i;
-
- printf("multiport ");
-
- switch (multiinfo->flags) {
- case IP6T_MULTIPORT_SOURCE:
- printf("sports ");
- break;
-
- case IP6T_MULTIPORT_DESTINATION:
- printf("dports ");
- break;
-
- case IP6T_MULTIPORT_EITHER:
- printf("ports ");
- break;
-
- default:
- printf("ERROR ");
- break;
- }
-
- if (multiinfo->invert)
- printf("! ");
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, numeric);
- if (multiinfo->pflags[i]) {
- printf(":");
- print_port(multiinfo->ports[++i], ip->proto, numeric);
- }
- }
- printf(" ");
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- const struct ip6t_multiport *multiinfo
- = (const struct ip6t_multiport *)match->data;
- unsigned int i;
-
- switch (multiinfo->flags) {
- case IP6T_MULTIPORT_SOURCE:
- printf("--sports ");
- break;
-
- case IP6T_MULTIPORT_DESTINATION:
- printf("--dports ");
- break;
-
- case IP6T_MULTIPORT_EITHER:
- printf("--ports ");
- break;
- }
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, 1);
- }
- printf(" ");
-}
-
-static void save_v1(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match)
-{
- const struct ip6t_multiport_v1 *multiinfo
- = (const struct ip6t_multiport_v1 *)match->data;
- unsigned int i;
-
- switch (multiinfo->flags) {
- case IP6T_MULTIPORT_SOURCE:
- printf("--sports ");
- break;
-
- case IP6T_MULTIPORT_DESTINATION:
- printf("--dports ");
- break;
-
- case IP6T_MULTIPORT_EITHER:
- printf("--ports ");
- break;
- }
-
- if (multiinfo->invert)
- printf("! ");
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, 1);
- if (multiinfo->pflags[i]) {
- printf(":");
- print_port(multiinfo->ports[++i], ip->proto, 1);
- }
- }
- printf(" ");
-}
-
-static struct ip6tables_match multiport = {
- .name = "multiport",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_multiport)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_multiport)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-static struct ip6tables_match multiport_v1 = {
- .next = NULL,
- .name = "multiport",
- .revision = 1,
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_multiport_v1)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_multiport_v1)),
- .help = &help_v1,
- .init = &init,
- .parse = &parse_v1,
- .final_check = &final_check,
- .print = &print_v1,
- .save = &save_v1,
- .extra_opts = opts
-};
-
-void
-_init(void)
-{
- register_match6(&multiport);
- register_match6(&multiport_v1);
-}
diff --git a/extensions/libip6t_multiport.man b/extensions/libip6t_multiport.man
deleted file mode 100644
index 6f75a6e..0000000
--- a/extensions/libip6t_multiport.man
+++ /dev/null
@@ -1,20 +0,0 @@
-This module matches a set of source or destination ports. Up to 15
-ports can be specified. It can only be used in conjunction
-with
-.B "-p tcp"
-or
-.BR "-p udp" .
-.TP
-.BR "--source-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport\fP...]]"
-Match if the source port is one of the given ports. The flag
-.B --sports
-is a convenient alias for this option.
-.TP
-.BR "--destination-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport\fP...]]"
-Match if the destination port is one of the given ports. The flag
-.B --dports
-is a convenient alias for this option.
-.TP
-.BR "--ports " "\fI[!] port\fP[,\fIport\fP[,\fIport\fP...]]"
-Match if the both the source and destination ports are equal to each
-other and to one of the given ports.
diff --git a/extensions/libip6t_owner.c b/extensions/libip6t_owner.c
deleted file mode 100644
index 99b5c13..0000000
--- a/extensions/libip6t_owner.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* Shared library add-on to iptables to add OWNER matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_owner.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-#ifdef IP6T_OWNER_COMM
- printf(
-"OWNER match v%s options:\n"
-"[!] --uid-owner userid Match local uid\n"
-"[!] --gid-owner groupid Match local gid\n"
-"[!] --pid-owner processid Match local pid\n"
-"[!] --sid-owner sessionid Match local sid\n"
-"[!] --cmd-owner name Match local command name\n"
-"\n",
-IPTABLES_VERSION);
-#else
- printf(
-"OWNER match v%s options:\n"
-"[!] --uid-owner userid Match local uid\n"
-"[!] --gid-owner groupid Match local gid\n"
-"[!] --pid-owner processid Match local pid\n"
-"[!] --sid-owner sessionid Match local sid\n"
-"\n",
-IPTABLES_VERSION);
-#endif /* IP6T_OWNER_COMM */
-}
-
-static struct option opts[] = {
- { "uid-owner", 1, 0, '1' },
- { "gid-owner", 1, 0, '2' },
- { "pid-owner", 1, 0, '3' },
- { "sid-owner", 1, 0, '4' },
-#ifdef IP6T_OWNER_COMM
- { "cmd-owner", 1, 0, '5' },
-#endif
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_owner_info *ownerinfo = (struct ip6t_owner_info *)(*match)->data;
-
- switch (c) {
- char *end;
- struct passwd *pwd;
- struct group *grp;
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-
- if ((pwd = getpwnam(optarg)))
- ownerinfo->uid = pwd->pw_uid;
- else {
- ownerinfo->uid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg);
- }
- if (invert)
- ownerinfo->invert |= IP6T_OWNER_UID;
- ownerinfo->match |= IP6T_OWNER_UID;
- *flags = 1;
- break;
-
- case '2':
- check_inverse(optarg, &invert, &optind, 0);
- if ((grp = getgrnam(optarg)))
- ownerinfo->gid = grp->gr_gid;
- else {
- ownerinfo->gid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg);
- }
- if (invert)
- ownerinfo->invert |= IP6T_OWNER_GID;
- ownerinfo->match |= IP6T_OWNER_GID;
- *flags = 1;
- break;
-
- case '3':
- check_inverse(optarg, &invert, &optind, 0);
- ownerinfo->pid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg);
- if (invert)
- ownerinfo->invert |= IP6T_OWNER_PID;
- ownerinfo->match |= IP6T_OWNER_PID;
- *flags = 1;
- break;
-
- case '4':
- check_inverse(optarg, &invert, &optind, 0);
- ownerinfo->sid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg);
- if (invert)
- ownerinfo->invert |= IP6T_OWNER_SID;
- ownerinfo->match |= IP6T_OWNER_SID;
- *flags = 1;
- break;
-
-#ifdef IP6T_OWNER_COMM
- case '5':
- check_inverse(optarg, &invert, &optind, 0);
- if(strlen(optarg) > sizeof(ownerinfo->comm))
- exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %d characters", optarg, sizeof(ownerinfo->comm));
-
- strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm));
- ownerinfo->comm[sizeof(ownerinfo->comm)-1] = '\0';
-
- if (invert)
- ownerinfo->invert |= IP6T_OWNER_COMM;
- ownerinfo->match |= IP6T_OWNER_COMM;
- *flags = 1;
- break;
-#endif
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_item(struct ip6t_owner_info *info, u_int8_t flag, int numeric, char *label)
-{
- if(info->match & flag) {
-
- if (info->invert & flag)
- printf("! ");
-
- printf(label);
-
- switch(info->match & flag) {
- case IP6T_OWNER_UID:
- if(!numeric) {
- struct passwd *pwd = getpwuid(info->uid);
-
- if(pwd && pwd->pw_name) {
- printf("%s ", pwd->pw_name);
- break;
- }
- /* FALLTHROUGH */
- }
- printf("%u ", info->uid);
- break;
- case IP6T_OWNER_GID:
- if(!numeric) {
- struct group *grp = getgrgid(info->gid);
-
- if(grp && grp->gr_name) {
- printf("%s ", grp->gr_name);
- break;
- }
- /* FALLTHROUGH */
- }
- printf("%u ", info->gid);
- break;
- case IP6T_OWNER_PID:
- printf("%u ", info->pid);
- break;
- case IP6T_OWNER_SID:
- printf("%u ", info->sid);
- break;
-#ifdef IP6T_OWNER_COMM
- case IP6T_OWNER_COMM:
- printf("%.*s ", (int)sizeof(info->comm), info->comm);
- break;
-#endif
- default:
- break;
- }
- }
-}
-
-/* Final check; must have specified --own. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "OWNER match: You must specify one or more options");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct ip6t_owner_info *info = (struct ip6t_owner_info *)match->data;
-
- print_item(info, IP6T_OWNER_UID, numeric, "OWNER UID match ");
- print_item(info, IP6T_OWNER_GID, numeric, "OWNER GID match ");
- print_item(info, IP6T_OWNER_PID, numeric, "OWNER PID match ");
- print_item(info, IP6T_OWNER_SID, numeric, "OWNER SID match ");
-#ifdef IP6T_OWNER_COMM
- print_item(info, IP6T_OWNER_COMM, numeric, "OWNER CMD match ");
-#endif
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct ip6t_owner_info *info = (struct ip6t_owner_info *)match->data;
-
- print_item(info, IP6T_OWNER_UID, 0, "--uid-owner ");
- print_item(info, IP6T_OWNER_GID, 0, "--gid-owner ");
- print_item(info, IP6T_OWNER_PID, 0, "--pid-owner ");
- print_item(info, IP6T_OWNER_SID, 0, "--sid-owner ");
-#ifdef IP6T_OWNER_COMM
- print_item(info, IP6T_OWNER_COMM, 0, "--cmd-owner ");
-#endif
-}
-
-static struct ip6tables_match owner = {
- .name = "owner",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_owner_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_owner_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_match6(&owner);
-}
diff --git a/extensions/libip6t_owner.man b/extensions/libip6t_owner.man
deleted file mode 100644
index edd72b1..0000000
--- a/extensions/libip6t_owner.man
+++ /dev/null
@@ -1,23 +0,0 @@
-This module attempts to match various characteristics of the packet
-creator, for locally-generated packets. It is only valid in the
-.B OUTPUT
-chain, and even this some packets (such as ICMPv6 ping responses) may
-have no owner, and hence never match. This is regarded as experimental.
-.TP
-.BI "--uid-owner " "userid"
-Matches if the packet was created by a process with the given
-effective user id.
-.TP
-.BI "--gid-owner " "groupid"
-Matches if the packet was created by a process with the given
-effective group id.
-.TP
-.BI "--pid-owner " "processid"
-Matches if the packet was created by a process with the given
-process id.
-.TP
-.BI "--sid-owner " "sessionid"
-Matches if the packet was created by a process in the given session
-group.
-.TP
-.B NOTE: pid, sid and command matching are broken on SMP
diff --git a/extensions/libip6t_physdev.c b/extensions/libip6t_physdev.c
deleted file mode 100644
index e7fa22e..0000000
--- a/extensions/libip6t_physdev.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Shared library add-on to iptables to add bridge port matching support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6t_physdev.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-
-static void
-help(void)
-{
- printf(
-"physdev v%s options:\n"
-" --physdev-in [!] input name[+] bridge port name ([+] for wildcard)\n"
-" --physdev-out [!] output name[+] bridge port name ([+] for wildcard)\n"
-" [!] --physdev-is-in arrived on a bridge device\n"
-" [!] --physdev-is-out will leave on a bridge device\n"
-" [!] --physdev-is-bridged it's a bridged packet\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "physdev-in", 1, 0, '1' },
- { "physdev-out", 1, 0, '2' },
- { "physdev-is-in", 0, 0, '3' },
- { "physdev-is-out", 0, 0, '4' },
- { "physdev-is-bridged", 0, 0, '5' },
- {0}
-};
-
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_physdev_info *info =
- (struct ip6t_physdev_info*)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & IP6T_PHYSDEV_OP_IN)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- parse_interface(argv[optind-1], info->physindev,
- (unsigned char *)info->in_mask);
- if (invert)
- info->invert |= IP6T_PHYSDEV_OP_IN;
- info->bitmask |= IP6T_PHYSDEV_OP_IN;
- *flags |= IP6T_PHYSDEV_OP_IN;
- break;
-
- case '2':
- if (*flags & IP6T_PHYSDEV_OP_OUT)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- parse_interface(argv[optind-1], info->physoutdev,
- (unsigned char *)info->out_mask);
- if (invert)
- info->invert |= IP6T_PHYSDEV_OP_OUT;
- info->bitmask |= IP6T_PHYSDEV_OP_OUT;
- *flags |= IP6T_PHYSDEV_OP_OUT;
- break;
-
- case '3':
- if (*flags & IP6T_PHYSDEV_OP_ISIN)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- info->bitmask |= IP6T_PHYSDEV_OP_ISIN;
- if (invert)
- info->invert |= IP6T_PHYSDEV_OP_ISIN;
- *flags |= IP6T_PHYSDEV_OP_ISIN;
- break;
-
- case '4':
- if (*flags & IP6T_PHYSDEV_OP_ISOUT)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- info->bitmask |= IP6T_PHYSDEV_OP_ISOUT;
- if (invert)
- info->invert |= IP6T_PHYSDEV_OP_ISOUT;
- *flags |= IP6T_PHYSDEV_OP_ISOUT;
- break;
-
- case '5':
- if (*flags & IP6T_PHYSDEV_OP_BRIDGED)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- if (invert)
- info->invert |= IP6T_PHYSDEV_OP_BRIDGED;
- *flags |= IP6T_PHYSDEV_OP_BRIDGED;
- info->bitmask |= IP6T_PHYSDEV_OP_BRIDGED;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-multiple_use:
- exit_error(PARAMETER_PROBLEM,
- "multiple use of the same physdev option is not allowed");
-
-}
-
-static void final_check(unsigned int flags)
-{
- if (flags == 0)
- exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
-}
-
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct ip6t_physdev_info *info =
- (struct ip6t_physdev_info*)match->data;
-
- printf("PHYSDEV match");
- if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
- printf("%s --physdev-is-in",
- info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
- if (info->bitmask & IP6T_PHYSDEV_OP_IN)
- printf("%s --physdev-in %s",
- (info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
-
- if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
- printf("%s --physdev-is-out",
- info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
- if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
- printf("%s --physdev-out %s",
- (info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
- if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
- printf("%s --physdev-is-bridged",
- info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
- printf(" ");
-}
-
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct ip6t_physdev_info *info =
- (struct ip6t_physdev_info*)match->data;
-
- if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
- printf("%s --physdev-is-in",
- info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
- if (info->bitmask & IP6T_PHYSDEV_OP_IN)
- printf("%s --physdev-in %s",
- (info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
-
- if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
- printf("%s --physdev-is-out",
- info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
- if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
- printf("%s --physdev-out %s",
- (info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
- if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
- printf("%s --physdev-is-bridged",
- info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
- printf(" ");
-}
-
-static struct ip6tables_match physdev = {
- .name = "physdev",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_match6(&physdev);
-}
diff --git a/extensions/libip6t_policy.c b/extensions/libip6t_policy.c
deleted file mode 100644
index 2f4453e..0000000
--- a/extensions/libip6t_policy.c
+++ /dev/null
@@ -1,478 +0,0 @@
-/* Shared library add-on to iptables to add policy support. */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <netdb.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <ip6tables.h>
-
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include "../include/linux/netfilter_ipv6/ip6t_policy.h"
-
-/*
- * HACK: global pointer to current matchinfo for making
- * final checks and adjustments in final_check.
- */
-static struct ip6t_policy_info *policy_info;
-
-static void help(void)
-{
- printf(
-"policy v%s options:\n"
-" --dir in|out match policy applied during decapsulation/\n"
-" policy to be applied during encapsulation\n"
-" --pol none|ipsec match policy\n"
-" --strict match entire policy instead of single element\n"
-" at any position\n"
-"[!] --reqid reqid match reqid\n"
-"[!] --spi spi match SPI\n"
-"[!] --proto proto match protocol (ah/esp/ipcomp)\n"
-"[!] --mode mode match mode (transport/tunnel)\n"
-"[!] --tunnel-src addr/masklen match tunnel source\n"
-"[!] --tunnel-dst addr/masklen match tunnel destination\n"
-" --next begin next element in policy\n",
- IPTABLES_VERSION);
-}
-
-static struct option opts[] =
-{
- {
- .name = "dir",
- .has_arg = 1,
- .val = '1',
- },
- {
- .name = "pol",
- .has_arg = 1,
- .val = '2',
- },
- {
- .name = "strict",
- .val = '3'
- },
- {
- .name = "reqid",
- .has_arg = 1,
- .val = '4',
- },
- {
- .name = "spi",
- .has_arg = 1,
- .val = '5'
- },
- {
- .name = "tunnel-src",
- .has_arg = 1,
- .val = '6'
- },
- {
- .name = "tunnel-dst",
- .has_arg = 1,
- .val = '7'
- },
- {
- .name = "proto",
- .has_arg = 1,
- .val = '8'
- },
- {
- .name = "mode",
- .has_arg = 1,
- .val = '9'
- },
- {
- .name = "next",
- .val = 'a'
- },
- { }
-};
-
-/* FIXME - Duplicated code from ip6tables.c */
-/* Duplicated to stop too many changes in other files .... */
-static void
-in6addrcpy(struct in6_addr *dst, struct in6_addr *src)
-{
- memcpy(dst, src, sizeof(struct in6_addr));
- /* dst->s6_addr = src->s6_addr; */
-}
-
-static char *
-addr_to_numeric(const struct in6_addr *addrp)
-{
- /* 0000:0000:0000:0000:0000:000.000.000.000
- * 0000:0000:0000:0000:0000:0000:0000:0000 */
- static char buf[50+1];
- return (char *)inet_ntop(AF_INET6, addrp, buf, sizeof(buf));
-}
-
-static char *
-mask_to_numeric(const struct in6_addr *addrp)
-{
- static char buf[50+2];
- int l = ipv6_prefix_length(addrp);
- if (l == -1) {
- strcpy(buf, "/");
- strcat(buf, addr_to_numeric(addrp));
- return buf;
- }
- sprintf(buf, "/%d", l);
- return buf;
-}
-
-/* These should be in include/ip6tables.h... */
-extern u_int16_t parse_protocol(const char *s);
-extern void parse_hostnetworkmask(const char *name, struct in6_addr **addrpp,
- struct in6_addr *maskp, unsigned int *naddrs);
-
-/* End duplicated code from ip6tables.c */
-
-static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- *nfcache |= NFC_UNKNOWN;
-}
-
-static int parse_direction(char *s)
-{
- if (strcmp(s, "in") == 0)
- return IP6T_POLICY_MATCH_IN;
- if (strcmp(s, "out") == 0)
- return IP6T_POLICY_MATCH_OUT;
- exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
-}
-
-static int parse_policy(char *s)
-{
- if (strcmp(s, "none") == 0)
- return IP6T_POLICY_MATCH_NONE;
- if (strcmp(s, "ipsec") == 0)
- return 0;
- exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
-}
-
-static int parse_mode(char *s)
-{
- if (strcmp(s, "transport") == 0)
- return IP6T_POLICY_MODE_TRANSPORT;
- if (strcmp(s, "tunnel") == 0)
- return IP6T_POLICY_MODE_TUNNEL;
- exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_policy_info *info = (void *)(*match)->data;
- struct ip6t_policy_elem *e = &info->pol[info->len];
- struct in6_addr *addr = NULL, mask;
- unsigned int naddr = 0;
- int mode;
-
- check_inverse(optarg, &invert, &optind, 0);
-
- switch (c) {
- case '1':
- if (info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT))
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --dir option");
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --dir option");
-
- info->flags |= parse_direction(argv[optind-1]);
- break;
- case '2':
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --policy option");
-
- info->flags |= parse_policy(argv[optind-1]);
- break;
- case '3':
- if (info->flags & IP6T_POLICY_MATCH_STRICT)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --strict option");
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --strict option");
-
- info->flags |= IP6T_POLICY_MATCH_STRICT;
- break;
- case '4':
- if (e->match.reqid)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --reqid option");
-
- e->match.reqid = 1;
- e->invert.reqid = invert;
- e->reqid = strtol(argv[optind-1], NULL, 10);
- break;
- case '5':
- if (e->match.spi)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --spi option");
-
- e->match.spi = 1;
- e->invert.spi = invert;
- e->spi = strtol(argv[optind-1], NULL, 0x10);
- break;
- case '6':
- if (e->match.saddr)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --tunnel-src option");
-
- parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
- if (naddr > 1)
- exit_error(PARAMETER_PROBLEM,
- "policy match: name resolves to multiple IPs");
-
- e->match.saddr = 1;
- e->invert.saddr = invert;
- in6addrcpy(&e->saddr.a6, addr);
- in6addrcpy(&e->smask.a6, &mask);
- break;
- case '7':
- if (e->match.daddr)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --tunnel-dst option");
-
- parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
- if (naddr > 1)
- exit_error(PARAMETER_PROBLEM,
- "policy match: name resolves to multiple IPs");
-
- e->match.daddr = 1;
- e->invert.daddr = invert;
- in6addrcpy(&e->daddr.a6, addr);
- in6addrcpy(&e->dmask.a6, &mask);
- break;
- case '8':
- if (e->match.proto)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --proto option");
-
- e->proto = parse_protocol(argv[optind-1]);
- if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
- e->proto != IPPROTO_COMP)
- exit_error(PARAMETER_PROBLEM,
- "policy match: protocol must ah/esp/ipcomp");
- e->match.proto = 1;
- e->invert.proto = invert;
- break;
- case '9':
- if (e->match.mode)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --mode option");
-
- mode = parse_mode(argv[optind-1]);
- e->match.mode = 1;
- e->invert.mode = invert;
- e->mode = mode;
- break;
- case 'a':
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --next option");
-
- if (++info->len == IP6T_POLICY_MAX_ELEM)
- exit_error(PARAMETER_PROBLEM,
- "policy match: maximum policy depth reached");
- break;
- default:
- return 0;
- }
-
- policy_info = info;
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- struct ip6t_policy_info *info = policy_info;
- struct ip6t_policy_elem *e;
- int i;
-
- if (info == NULL)
- exit_error(PARAMETER_PROBLEM,
- "policy match: no parameters given");
-
- if (!(info->flags & (IP6T_POLICY_MATCH_IN|IP6T_POLICY_MATCH_OUT)))
- exit_error(PARAMETER_PROBLEM,
- "policy match: neither --in nor --out specified");
-
- if (info->flags & IP6T_POLICY_MATCH_NONE) {
- if (info->flags & IP6T_POLICY_MATCH_STRICT)
- exit_error(PARAMETER_PROBLEM,
- "policy match: policy none but --strict given");
-
- if (info->len != 0)
- exit_error(PARAMETER_PROBLEM,
- "policy match: policy none but policy given");
- } else
- info->len++; /* increase len by 1, no --next after last element */
-
- if (!(info->flags & IP6T_POLICY_MATCH_STRICT) && info->len > 1)
- exit_error(PARAMETER_PROBLEM,
- "policy match: multiple elements but no --strict");
-
- for (i = 0; i < info->len; i++) {
- e = &info->pol[i];
-
- if (info->flags & IP6T_POLICY_MATCH_STRICT &&
- !(e->match.reqid || e->match.spi || e->match.saddr ||
- e->match.daddr || e->match.proto || e->match.mode))
- exit_error(PARAMETER_PROBLEM,
- "policy match: empty policy element");
-
- if ((e->match.saddr || e->match.daddr)
- && ((e->mode == IP6T_POLICY_MODE_TUNNEL && e->invert.mode) ||
- (e->mode == IP6T_POLICY_MODE_TRANSPORT && !e->invert.mode)))
- exit_error(PARAMETER_PROBLEM,
- "policy match: --tunnel-src/--tunnel-dst "
- "is only valid in tunnel mode");
- }
-}
-
-static void print_mode(char *prefix, u_int8_t mode, int numeric)
-{
- printf("%smode ", prefix);
-
- switch (mode) {
- case IP6T_POLICY_MODE_TRANSPORT:
- printf("transport ");
- break;
- case IP6T_POLICY_MODE_TUNNEL:
- printf("tunnel ");
- break;
- default:
- printf("??? ");
- break;
- }
-}
-
-static void print_proto(char *prefix, u_int8_t proto, int numeric)
-{
- struct protoent *p = NULL;
-
- printf("%sproto ", prefix);
- if (!numeric)
- p = getprotobynumber(proto);
- if (p != NULL)
- printf("%s ", p->p_name);
- else
- printf("%u ", proto);
-}
-
-#define PRINT_INVERT(x) \
-do { \
- if (x) \
- printf("! "); \
-} while(0)
-
-static void print_entry(char *prefix, const struct ip6t_policy_elem *e,
- int numeric)
-{
- if (e->match.reqid) {
- PRINT_INVERT(e->invert.reqid);
- printf("%sreqid %u ", prefix, e->reqid);
- }
- if (e->match.spi) {
- PRINT_INVERT(e->invert.spi);
- printf("%sspi 0x%x ", prefix, e->spi);
- }
- if (e->match.proto) {
- PRINT_INVERT(e->invert.proto);
- print_proto(prefix, e->proto, numeric);
- }
- if (e->match.mode) {
- PRINT_INVERT(e->invert.mode);
- print_mode(prefix, e->mode, numeric);
- }
- if (e->match.daddr) {
- PRINT_INVERT(e->invert.daddr);
- printf("%stunnel-dst %s%s ", prefix,
- addr_to_numeric((struct in6_addr *)&e->daddr),
- mask_to_numeric((struct in6_addr *)&e->dmask));
- }
- if (e->match.saddr) {
- PRINT_INVERT(e->invert.saddr);
- printf("%stunnel-src %s%s ", prefix,
- addr_to_numeric((struct in6_addr *)&e->saddr),
- mask_to_numeric((struct in6_addr *)&e->smask));
- }
-}
-
-static void print_flags(char *prefix, const struct ip6t_policy_info *info)
-{
- if (info->flags & IP6T_POLICY_MATCH_IN)
- printf("%sdir in ", prefix);
- else
- printf("%sdir out ", prefix);
-
- if (info->flags & IP6T_POLICY_MATCH_NONE)
- printf("%spol none ", prefix);
- else
- printf("%spol ipsec ", prefix);
-
- if (info->flags & IP6T_POLICY_MATCH_STRICT)
- printf("%sstrict ", prefix);
-}
-
-static void print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- const struct ip6t_policy_info *info = (void *)match->data;
- unsigned int i;
-
- printf("policy match ");
- print_flags("", info);
- for (i = 0; i < info->len; i++) {
- if (info->len > 1)
- printf("[%u] ", i);
- print_entry("", &info->pol[i], numeric);
- }
-
- printf("\n");
-}
-
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- const struct ip6t_policy_info *info = (void *)match->data;
- unsigned int i;
-
- print_flags("--", info);
- for (i = 0; i < info->len; i++) {
- print_entry("--", &info->pol[i], 0);
- if (i + 1 < info->len)
- printf("--next ");
- }
-}
-
-struct ip6tables_match policy = {
- .name = "policy",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_policy_info)),
- .help = help,
- .init = init,
- .parse = parse,
- .final_check = final_check,
- .print = print,
- .save = save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_match6(&policy);
-}
diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c
index 251604b..a04023d 100644
--- a/extensions/libip6t_rt.c
+++ b/extensions/libip6t_rt.c
@@ -5,38 +5,36 @@
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#include <ip6tables.h>
+#include <xtables.h>
/*#include <linux/in6.h>*/
#include <linux/netfilter_ipv6/ip6t_rt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
-
+
/*#define DEBUG 1*/
-/* Function which prints out usage message. */
-static void
-help(void)
+static void rt_help(void)
{
printf(
-"RT v%s options:\n"
-" --rt-type [!] type match the type\n"
-" --rt-segsleft [!] num[:num] match the Segments Left field (range)\n"
-" --rt-len [!] length total length of this header\n"
+"rt match options:\n"
+"[!] --rt-type type match the type\n"
+"[!] --rt-segsleft num[:num] match the Segments Left field (range)\n"
+"[!] --rt-len length total length of this header\n"
" --rt-0-res check the reserved filed, too (type 0)\n"
" --rt-0-addrs ADDR[,ADDR...] Type=0 addresses (list, max: %d)\n"
" --rt-0-not-strict List of Type=0 addresses not a strict list\n",
-IPTABLES_VERSION, IP6T_RT_HOPS);
+IP6T_RT_HOPS);
}
-static struct option opts[] = {
- { "rt-type", 1, 0, '1' },
- { "rt-segsleft", 1, 0, '2' },
- { "rt-len", 1, 0, '3' },
- { "rt-0-res", 0, 0, '4' },
- { "rt-0-addrs", 1, 0, '5' },
- { "rt-0-not-strict", 0, 0, '6' },
- {0}
+static const struct option rt_opts[] = {
+ { "rt-type", 1, NULL, '1' },
+ { "rt-segsleft", 1, NULL, '2' },
+ { "rt-len", 1, NULL, '3' },
+ { "rt-0-res", 0, NULL, '4' },
+ { "rt-0-addrs", 1, NULL, '5' },
+ { "rt-0-not-strict", 0, NULL, '6' },
+ { .name = NULL }
};
static u_int32_t
@@ -48,19 +46,19 @@ parse_rt_num(const char *idstr, const char *typestr)
id = strtoul(idstr,&ep,0) ;
if ( idstr == ep ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"RT no valid digits in %s `%s'", typestr, idstr);
}
if ( id == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"%s `%s' specified too big: would overflow",
typestr, idstr);
}
if ( *idstr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"RT error parsing %s `%s'", typestr, idstr);
}
- return (u_int32_t) id;
+ return id;
}
static void
@@ -100,7 +98,7 @@ numeric_to_addr(const char *num)
#ifdef DEBUG
fprintf(stderr, "\nnumeric2addr: %d\n", err);
#endif
- exit_error(PARAMETER_PROBLEM, "bad address: %s", num);
+ xtables_error(PARAMETER_PROBLEM, "bad address: %s", num);
return (struct in6_addr *)NULL;
}
@@ -113,7 +111,7 @@ parse_addresses(const char *addrstr, struct in6_addr *addrp)
unsigned int i;
buffer = strdup(addrstr);
- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
+ if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
for (cp=buffer, i=0; cp && i<IP6T_RT_HOPS; cp=next,i++)
{
@@ -126,7 +124,7 @@ parse_addresses(const char *addrstr, struct in6_addr *addrp)
printf("addr [%d]: %s\n", i, addr_to_numeric(&(addrp[i])));
#endif
}
- if (cp) exit_error(PARAMETER_PROBLEM, "too many addresses specified");
+ if (cp) xtables_error(PARAMETER_PROBLEM, "too many addresses specified");
free(buffer);
@@ -137,9 +135,7 @@ parse_addresses(const char *addrstr, struct in6_addr *addrp)
return i;
}
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
+static void rt_init(struct xt_entry_match *m)
{
struct ip6t_rt *rtinfo = (struct ip6t_rt *)m->data;
@@ -152,23 +148,18 @@ init(struct ip6t_entry_match *m, unsigned int *nfcache)
rtinfo->addrnr = 0;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+static int rt_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ip6t_rt *rtinfo = (struct ip6t_rt *)(*match)->data;
switch (c) {
case '1':
if (*flags & IP6T_RT_TYP)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--rt-type' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- rtinfo->rt_type = parse_rt_num(argv[optind-1], "type");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ rtinfo->rt_type = parse_rt_num(optarg, "type");
if (invert)
rtinfo->invflags |= IP6T_RT_INV_TYP;
rtinfo->flags |= IP6T_RT_TYP;
@@ -176,10 +167,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '2':
if (*flags & IP6T_RT_SGS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--rt-segsleft' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_rt_segsleft(argv[optind-1], rtinfo->segsleft);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_rt_segsleft(optarg, rtinfo->segsleft);
if (invert)
rtinfo->invflags |= IP6T_RT_INV_SGS;
rtinfo->flags |= IP6T_RT_SGS;
@@ -187,10 +178,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '3':
if (*flags & IP6T_RT_LEN)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--rt-len' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- rtinfo->hdrlen = parse_rt_num(argv[optind-1], "length");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ rtinfo->hdrlen = parse_rt_num(optarg, "length");
if (invert)
rtinfo->invflags |= IP6T_RT_INV_LEN;
rtinfo->flags |= IP6T_RT_LEN;
@@ -198,35 +189,35 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '4':
if (*flags & IP6T_RT_RES)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--rt-0-res' allowed");
if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"`--rt-type 0' required before `--rt-0-res'");
rtinfo->flags |= IP6T_RT_RES;
*flags |= IP6T_RT_RES;
break;
case '5':
if (*flags & IP6T_RT_FST)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--rt-0-addrs' allowed");
if ( !(*flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || (rtinfo->invflags & IP6T_RT_INV_TYP) )
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"`--rt-type 0' required before `--rt-0-addrs'");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
if (invert)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
" '!' not allowed with `--rt-0-addrs'");
- rtinfo->addrnr = parse_addresses(argv[optind-1], rtinfo->addrs);
+ rtinfo->addrnr = parse_addresses(optarg, rtinfo->addrs);
rtinfo->flags |= IP6T_RT_FST;
*flags |= IP6T_RT_FST;
break;
case '6':
if (*flags & IP6T_RT_FST_NSTRICT)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--rt-0-not-strict' allowed");
if ( !(*flags & IP6T_RT_FST) )
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"`--rt-0-addr ...' required before `--rt-0-not-strict'");
rtinfo->flags |= IP6T_RT_FST_NSTRICT;
*flags |= IP6T_RT_FST_NSTRICT;
@@ -238,12 +229,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
static void
print_nums(const char *name, u_int32_t min, u_int32_t max,
int invert)
@@ -266,7 +251,7 @@ print_nums(const char *name, u_int32_t min, u_int32_t max,
}
static void
-print_addresses(int addrnr, struct in6_addr *addrp)
+print_addresses(unsigned int addrnr, struct in6_addr *addrp)
{
unsigned int i;
@@ -275,10 +260,8 @@ print_addresses(int addrnr, struct in6_addr *addrp)
}
}
-/* Prints out the union ip6t_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
+static void rt_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
@@ -303,20 +286,19 @@ print(const struct ip6t_ip6 *ip,
rtinfo->invflags & ~IP6T_RT_INV_MASK);
}
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+static void rt_save(const void *ip, const struct xt_entry_match *match)
{
const struct ip6t_rt *rtinfo = (struct ip6t_rt *)match->data;
if (rtinfo->flags & IP6T_RT_TYP) {
- printf("--rt-type %s%u ",
+ printf("%s--rt-type %u ",
(rtinfo->invflags & IP6T_RT_INV_TYP) ? "! " : "",
rtinfo->rt_type);
}
if (!(rtinfo->segsleft[0] == 0
&& rtinfo->segsleft[1] == 0xFFFFFFFF)) {
- printf("--rt-segsleft %s",
+ printf("%s--rt-segsleft ",
(rtinfo->invflags & IP6T_RT_INV_SGS) ? "! " : "");
if (rtinfo->segsleft[0]
!= rtinfo->segsleft[1])
@@ -329,7 +311,7 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
}
if (rtinfo->flags & IP6T_RT_LEN) {
- printf("--rt-len %s%u ",
+ printf("%s--rt-len %u ",
(rtinfo->invflags & IP6T_RT_INV_LEN) ? "! " : "",
rtinfo->hdrlen);
}
@@ -341,22 +323,22 @@ static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match
}
-static struct ip6tables_match rt = {
+static struct xtables_match rt_mt6_reg = {
.name = "rt",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_rt)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_rt)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_rt)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_rt)),
+ .help = rt_help,
+ .init = rt_init,
+ .parse = rt_parse,
+ .print = rt_print,
+ .save = rt_save,
+ .extra_opts = rt_opts,
};
void
_init(void)
{
- register_match6(&rt);
+ xtables_register_match(&rt_mt6_reg);
}
diff --git a/extensions/libip6t_rt.man b/extensions/libip6t_rt.man
index e56d5f4..0443e0a 100644
--- a/extensions/libip6t_rt.man
+++ b/extensions/libip6t_rt.man
@@ -1,19 +1,19 @@
Match on IPv6 routing header
.TP
-.BR "--rt-type" " [!] \fItype\fP"
+[\fB!\fP] \fB\-\-rt\-type\fP \fItype\fP
Match the type (numeric).
.TP
-.BR "--rt-segsleft" " [!] \fInum\fP[:\fInum\fP]"
+[\fB!\fP] \fB\-\-rt\-segsleft\fP \fInum\fP[\fB:\fP\fInum\fP]
Match the `segments left' field (range).
.TP
-.BR "--rt-len" " [!] \fIlength\fP"
+[\fB!\fP] \fB\-\-rt\-len\fP \fIlength\fP
Match the length of this header.
.TP
-.BR "--rt-0-res"
+\fB\-\-rt\-0\-res\fP
Match the reserved field, too (type=0)
.TP
-.BR "--rt-0-addrs" " \fIADDR\fP[,\fIADDR\fP...]"
+\fB\-\-rt\-0\-addrs\fP \fIaddr\fP[\fB,\fP\fIaddr\fP...]
Match type=0 addresses (list).
.TP
-.BR "--rt-0-not-strict"
+\fB\-\-rt\-0\-not\-strict\fP
List of type=0 addresses is not a strict list.
diff --git a/extensions/libip6t_standard.c b/extensions/libip6t_standard.c
deleted file mode 100644
index c48882f..0000000
--- a/extensions/libip6t_standard.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Shared library add-on to iptables for standard target support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <getopt.h>
-#include <ip6tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"Standard v%s options:\n"
-"(If target is DROP, ACCEPT, RETURN or nothing)\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- {0}
-};
-
-/* Initialize the target. */
-static void
-init(struct ip6t_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct ip6t_entry_target **target)
-{
- return 0;
-}
-
-/* Final check; don't care. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Saves the targinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip6, const struct ip6t_entry_target *target)
-{
-}
-
-static struct ip6tables_target standard = {
- .name = "standard",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(int)),
- .userspacesize = IP6T_ALIGN(sizeof(int)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .save = &save,
- .extra_opts = opts,
-};
-
-void _init(void)
-{
- register_target6(&standard);
-}
diff --git a/extensions/libip6t_state.c b/extensions/libip6t_state.c
deleted file mode 100644
index 84fd1a4..0000000
--- a/extensions/libip6t_state.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Ugly hack to make state matching for ipv6 work before iptables-1.4.x is finished */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ipt_state.h>
-
-#ifndef IPT_STATE_UNTRACKED
-#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"state v%s options:\n"
-" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
-" State(s) to match\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "state", 1, 0, '1' },
- {0}
-};
-
-static int
-parse_state(const char *state, size_t strlen, struct ipt_state_info *sinfo)
-{
- if (strncasecmp(state, "INVALID", strlen) == 0)
- sinfo->statemask |= IPT_STATE_INVALID;
- else if (strncasecmp(state, "NEW", strlen) == 0)
- sinfo->statemask |= IPT_STATE_BIT(IP_CT_NEW);
- else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
- sinfo->statemask |= IPT_STATE_BIT(IP_CT_ESTABLISHED);
- else if (strncasecmp(state, "RELATED", strlen) == 0)
- sinfo->statemask |= IPT_STATE_BIT(IP_CT_RELATED);
- else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
- sinfo->statemask |= IPT_STATE_UNTRACKED;
- else
- return 0;
- return 1;
-}
-
-static void
-parse_states(const char *arg, struct ipt_state_info *sinfo)
-{
- const char *comma;
-
- while ((comma = strchr(arg, ',')) != NULL) {
- if (comma == arg || !parse_state(arg, comma-arg, sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
- arg = comma+1;
- }
-
- if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ipt_state_info *sinfo = (struct ipt_state_info *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-
- parse_states(argv[optind-1], sinfo);
- if (invert)
- sinfo->statemask = ~sinfo->statemask;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; must have specified --state. */
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, "You must specify `--state'");
-}
-
-static void print_state(unsigned int statemask)
-{
- const char *sep = "";
-
- if (statemask & IPT_STATE_INVALID) {
- printf("%sINVALID", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_BIT(IP_CT_NEW)) {
- printf("%sNEW", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_BIT(IP_CT_RELATED)) {
- printf("%sRELATED", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_BIT(IP_CT_ESTABLISHED)) {
- printf("%sESTABLISHED", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_UNTRACKED) {
- printf("%sUNTRACKED", sep);
- sep = ",";
- }
- printf(" ");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
-{
- struct ipt_state_info *sinfo = (struct ipt_state_info *)match->data;
-
- printf("state ");
- print_state(sinfo->statemask);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- struct ipt_state_info *sinfo = (struct ipt_state_info *)match->data;
-
- printf("--state ");
- print_state(sinfo->statemask);
-}
-
-static struct ip6tables_match state = {
- .next = NULL,
- .name = "state",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ipt_state_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ipt_state_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void _init(void)
-{
- register_match6(&state);
-}
diff --git a/extensions/libip6t_tcp.c b/extensions/libip6t_tcp.c
deleted file mode 100644
index 734387c..0000000
--- a/extensions/libip6t_tcp.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/* Shared library add-on to iptables to add TCP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"TCP v%s options:\n"
-" --tcp-flags [!] mask comp match when TCP flags & mask == comp\n"
-" (Flags: SYN ACK FIN RST URG PSH ALL NONE)\n"
-"[!] --syn match when only SYN flag set\n"
-" (equivalent to --tcp-flags SYN,RST,ACK SYN)\n"
-" --source-port [!] port[:port]\n"
-" --sport ...\n"
-" match source port(s)\n"
-" --destination-port [!] port[:port]\n"
-" --dport ...\n"
-" match destination port(s)\n"
-" --tcp-option [!] number match if TCP option set\n\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "source-port", 1, 0, '1' },
- { "sport", 1, 0, '1' }, /* synonym */
- { "destination-port", 1, 0, '2' },
- { "dport", 1, 0, '2' }, /* synonym */
- { "syn", 0, 0, '3' },
- { "tcp-flags", 1, 0, '4' },
- { "tcp-option", 1, 0, '5' },
- {0}
-};
-
-static void
-parse_tcp_ports(const char *portstring, u_int16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = parse_port(buffer, "tcp");
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
-struct tcp_flag_names {
- const char *name;
- unsigned int flag;
-};
-
-static struct tcp_flag_names tcp_flag_names[]
-= { { "FIN", 0x01 },
- { "SYN", 0x02 },
- { "RST", 0x04 },
- { "PSH", 0x08 },
- { "ACK", 0x10 },
- { "URG", 0x20 },
- { "ALL", 0x3F },
- { "NONE", 0 },
-};
-
-static unsigned int
-parse_tcp_flag(const char *flags)
-{
- unsigned int ret = 0;
- char *ptr;
- char *buffer;
-
- buffer = strdup(flags);
-
- for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
- unsigned int i;
- for (i = 0;
- i < sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names);
- i++) {
- if (strcasecmp(tcp_flag_names[i].name, ptr) == 0) {
- ret |= tcp_flag_names[i].flag;
- break;
- }
- }
- if (i == sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names))
- exit_error(PARAMETER_PROBLEM,
- "Unknown TCP flag `%s'", ptr);
- }
-
- free(buffer);
- return ret;
-}
-
-static void
-parse_tcp_flags(struct ip6t_tcp *tcpinfo,
- const char *mask,
- const char *cmp,
- int invert)
-{
- tcpinfo->flg_mask = parse_tcp_flag(mask);
- tcpinfo->flg_cmp = parse_tcp_flag(cmp);
-
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_FLAGS;
-}
-
-static void
-parse_tcp_option(const char *option, u_int8_t *result)
-{
- unsigned int ret;
-
- if (string_to_number(option, 1, 255, &ret) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad TCP option `%s'", option);
-
- *result = (u_int8_t)ret;
-}
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- struct ip6t_tcp *tcpinfo = (struct ip6t_tcp *)m->data;
-
- tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF;
-}
-
-#define TCP_SRC_PORTS 0x01
-#define TCP_DST_PORTS 0x02
-#define TCP_FLAGS 0x04
-#define TCP_OPTION 0x08
-
-/* Function which parses command options; returns true if it
- ate an option. */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_tcp *tcpinfo = (struct ip6t_tcp *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & TCP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->spts);
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_SRCPT;
- *flags |= TCP_SRC_PORTS;
- break;
-
- case '2':
- if (*flags & TCP_DST_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->dpts);
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_DSTPT;
- *flags |= TCP_DST_PORTS;
- break;
-
- case '3':
- if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
- "Only one of `--syn' or `--tcp-flags' "
- " allowed");
- parse_tcp_flags(tcpinfo, "SYN,RST,ACK", "SYN", invert);
- *flags |= TCP_FLAGS;
- break;
-
- case '4':
- if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
- "Only one of `--syn' or `--tcp-flags' "
- " allowed");
- check_inverse(optarg, &invert, &optind, 0);
-
- if (!argv[optind]
- || argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
- "--tcp-flags requires two args.");
-
- parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind],
- invert);
- optind++;
- *flags |= TCP_FLAGS;
- break;
-
- case '5':
- if (*flags & TCP_OPTION)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--tcp-option' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_option(argv[optind-1], &tcpinfo->option);
- if (invert)
- tcpinfo->invflags |= IP6T_TCP_INV_OPTION;
- *flags |= TCP_OPTION;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
-static char *
-port_to_service(int port)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), "tcp")))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-static void
-print_ports(const char *name, u_int16_t min, u_int16_t max,
- int invert, int numeric)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- print_port(min, numeric);
- } else {
- printf("s:%s", inv);
- print_port(min, numeric);
- printf(":");
- print_port(max, numeric);
- }
- printf(" ");
- }
-}
-
-static void
-print_option(u_int8_t option, int invert, int numeric)
-{
- if (option || invert)
- printf("option=%s%u ", invert ? "!" : "", option);
-}
-
-static void
-print_tcpf(u_int8_t flags)
-{
- int have_flag = 0;
-
- while (flags) {
- unsigned int i;
-
- for (i = 0; (flags & tcp_flag_names[i].flag) == 0; i++);
-
- if (have_flag)
- printf(",");
- printf("%s", tcp_flag_names[i].name);
- have_flag = 1;
-
- flags &= ~tcp_flag_names[i].flag;
- }
-
- if (!have_flag)
- printf("NONE");
-}
-
-static void
-print_flags(u_int8_t mask, u_int8_t cmp, int invert, int numeric)
-{
- if (mask || invert) {
- printf("flags:%s", invert ? "!" : "");
- if (numeric)
- printf("0x%02X/0x%02X ", mask, cmp);
- else {
- print_tcpf(mask);
- printf("/");
- print_tcpf(cmp);
- printf(" ");
- }
- }
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
-{
- const struct ip6t_tcp *tcp = (struct ip6t_tcp *)match->data;
-
- printf("tcp ");
- print_ports("spt", tcp->spts[0], tcp->spts[1],
- tcp->invflags & IP6T_TCP_INV_SRCPT,
- numeric);
- print_ports("dpt", tcp->dpts[0], tcp->dpts[1],
- tcp->invflags & IP6T_TCP_INV_DSTPT,
- numeric);
- print_option(tcp->option,
- tcp->invflags & IP6T_TCP_INV_OPTION,
- numeric);
- print_flags(tcp->flg_mask, tcp->flg_cmp,
- tcp->invflags & IP6T_TCP_INV_FLAGS,
- numeric);
- if (tcp->invflags & ~IP6T_TCP_INV_MASK)
- printf("Unknown invflags: 0x%X ",
- tcp->invflags & ~IP6T_TCP_INV_MASK);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- const struct ip6t_tcp *tcpinfo = (struct ip6t_tcp *)match->data;
-
- if (tcpinfo->spts[0] != 0
- || tcpinfo->spts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IP6T_TCP_INV_SRCPT)
- printf("! ");
- if (tcpinfo->spts[0]
- != tcpinfo->spts[1])
- printf("--sport %u:%u ",
- tcpinfo->spts[0],
- tcpinfo->spts[1]);
- else
- printf("--sport %u ",
- tcpinfo->spts[0]);
- }
-
- if (tcpinfo->dpts[0] != 0
- || tcpinfo->dpts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IP6T_TCP_INV_DSTPT)
- printf("! ");
- if (tcpinfo->dpts[0]
- != tcpinfo->dpts[1])
- printf("--dport %u:%u ",
- tcpinfo->dpts[0],
- tcpinfo->dpts[1]);
- else
- printf("--dport %u ",
- tcpinfo->dpts[0]);
- }
-
- if (tcpinfo->option
- || (tcpinfo->invflags & IP6T_TCP_INV_OPTION)) {
- if (tcpinfo->invflags & IP6T_TCP_INV_OPTION)
- printf("! ");
- printf("--tcp-option %u ", tcpinfo->option);
- }
-
- if (tcpinfo->flg_mask
- || (tcpinfo->invflags & IP6T_TCP_INV_FLAGS)) {
- if (tcpinfo->invflags & IP6T_TCP_INV_FLAGS)
- printf("! ");
-
- printf("--tcp-flags ");
- if (tcpinfo->flg_mask != 0xFF) {
- print_tcpf(tcpinfo->flg_mask);
- }
- printf(" ");
- print_tcpf(tcpinfo->flg_cmp);
- printf(" ");
- }
-}
-
-static struct ip6tables_match tcp = {
- .name = "tcp",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_tcp)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_tcp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void
-_init(void)
-{
- register_match6(&tcp);
-}
diff --git a/extensions/libip6t_tcp.man b/extensions/libip6t_tcp.man
deleted file mode 100644
index 75d172e..0000000
--- a/extensions/libip6t_tcp.man
+++ /dev/null
@@ -1,45 +0,0 @@
-These extensions are loaded if `--protocol tcp' is specified. It
-provides the following options:
-.TP
-.BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
-Source port or port range specification. This can either be a service
-name or a port number. An inclusive range can also be specified,
-using the format
-.IR port : port .
-If the first port is omitted, "0" is assumed; if the last is omitted,
-"65535" is assumed.
-If the second port greater then the first they will be swapped.
-The flag
-.B --sport
-is a convenient alias for this option.
-.TP
-.BR "--destination-port " "[!] \fIport\fP[:\fIport\fP]"
-Destination port or port range specification. The flag
-.B --dport
-is a convenient alias for this option.
-.TP
-.BR "--tcp-flags " "[!] \fImask\fP \fIcomp\fP"
-Match when the TCP flags are as specified. The first argument is the
-flags which we should examine, written as a comma-separated list, and
-the second argument is a comma-separated list of flags which must be
-set. Flags are:
-.BR "SYN ACK FIN RST URG PSH ALL NONE" .
-Hence the command
-.nf
- ip6tables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST SYN
-.fi
-will only match packets with the SYN flag set, and the ACK, FIN and
-RST flags unset.
-.TP
-.B "[!] --syn"
-Only match TCP packets with the SYN bit set and the ACK and RST bits
-cleared. Such packets are used to request TCP connection initiation;
-for example, blocking such packets coming in an interface will prevent
-incoming TCP connections, but outgoing TCP connections will be
-unaffected.
-It is equivalent to \fB--tcp-flags SYN,RST,ACK SYN\fP.
-If the "!" flag precedes the "--syn", the sense of the
-option is inverted.
-.TP
-.BR "--tcp-option " "[!] \fInumber\fP"
-Match if TCP option set.
diff --git a/extensions/libip6t_udp.c b/extensions/libip6t_udp.c
deleted file mode 100644
index cd3c3d4..0000000
--- a/extensions/libip6t_udp.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Shared library add-on to iptables to add UDP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"UDP v%s options:\n"
-" --source-port [!] port[:port]\n"
-" --sport ...\n"
-" match source port(s)\n"
-" --destination-port [!] port[:port]\n"
-" --dport ...\n"
-" match destination port(s)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "source-port", 1, 0, '1' },
- { "sport", 1, 0, '1' }, /* synonym */
- { "destination-port", 1, 0, '2' },
- { "dport", 1, 0, '2' }, /* synonym */
- {0}
-};
-
-static void
-parse_udp_ports(const char *portstring, u_int16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = parse_port(buffer, "udp");
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
- struct ip6t_udp *udpinfo = (struct ip6t_udp *)m->data;
-
- udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
-}
-
-#define UDP_SRC_PORTS 0x01
-#define UDP_DST_PORTS 0x02
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
-{
- struct ip6t_udp *udpinfo = (struct ip6t_udp *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & UDP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_udp_ports(argv[optind-1], udpinfo->spts);
- if (invert)
- udpinfo->invflags |= IP6T_UDP_INV_SRCPT;
- *flags |= UDP_SRC_PORTS;
- break;
-
- case '2':
- if (*flags & UDP_DST_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_udp_ports(argv[optind-1], udpinfo->dpts);
- if (invert)
- udpinfo->invflags |= IP6T_UDP_INV_DSTPT;
- *flags |= UDP_DST_PORTS;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
-static char *
-port_to_service(int port)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), "udp")))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-static void
-print_ports(const char *name, u_int16_t min, u_int16_t max,
- int invert, int numeric)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- print_port(min, numeric);
- } else {
- printf("s:%s", inv);
- print_port(min, numeric);
- printf(":");
- print_port(max, numeric);
- }
- printf(" ");
- }
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match, int numeric)
-{
- const struct ip6t_udp *udp = (struct ip6t_udp *)match->data;
-
- printf("udp ");
- print_ports("spt", udp->spts[0], udp->spts[1],
- udp->invflags & IP6T_UDP_INV_SRCPT,
- numeric);
- print_ports("dpt", udp->dpts[0], udp->dpts[1],
- udp->invflags & IP6T_UDP_INV_DSTPT,
- numeric);
- if (udp->invflags & ~IP6T_UDP_INV_MASK)
- printf("Unknown invflags: 0x%X ",
- udp->invflags & ~IP6T_UDP_INV_MASK);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
- const struct ip6t_udp *udpinfo = (struct ip6t_udp *)match->data;
-
- if (udpinfo->spts[0] != 0
- || udpinfo->spts[1] != 0xFFFF) {
- if (udpinfo->invflags & IP6T_UDP_INV_SRCPT)
- printf("! ");
- if (udpinfo->spts[0]
- != udpinfo->spts[1])
- printf("--sport %u:%u ",
- udpinfo->spts[0],
- udpinfo->spts[1]);
- else
- printf("--sport %u ",
- udpinfo->spts[0]);
- }
-
- if (udpinfo->dpts[0] != 0
- || udpinfo->dpts[1] != 0xFFFF) {
- if (udpinfo->invflags & IP6T_UDP_INV_DSTPT)
- printf("! ");
- if (udpinfo->dpts[0]
- != udpinfo->dpts[1])
- printf("--dport %u:%u ",
- udpinfo->dpts[0],
- udpinfo->dpts[1]);
- else
- printf("--dport %u ",
- udpinfo->dpts[0]);
- }
-}
-
-static struct ip6tables_match udp = {
- .name = "udp",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct ip6t_udp)),
- .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_udp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts,
-};
-
-void
-_init(void)
-{
- register_match6(&udp);
-}
diff --git a/extensions/libip6t_udp.man b/extensions/libip6t_udp.man
deleted file mode 100644
index 0408479..0000000
--- a/extensions/libip6t_udp.man
+++ /dev/null
@@ -1,14 +0,0 @@
-These extensions are loaded if `--protocol udp' is specified. It
-provides the following options:
-.TP
-.BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
-Source port or port range specification.
-See the description of the
-.B --source-port
-option of the TCP extension for details.
-.TP
-.BR "--destination-port " "[!] \fIport\fP[:\fIport\fP]"
-Destination port or port range specification.
-See the description of the
-.B --destination-port
-option of the TCP extension for details.
diff --git a/extensions/libipt_2connmark.c b/extensions/libipt_2connmark.c
deleted file mode 100644
index 18c7586..0000000
--- a/extensions/libipt_2connmark.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Shared library add-on to iptables to add connmark matching support.
- *
- * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
- *
- * Version 1.1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include "../include/linux/netfilter_ipv4/ipt_2connmark.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"CONNMARK match v%s options:\n"
-"[!] --mark value[/mask] Match nfmark value with optional mask\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mark", 1, 0, '1' },
- {0}
-};
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
- /* Can't cache this. */
- *nfcache |= NFC_UNKNOWN;
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_connmark_info *markinfo = (struct ipt_connmark_info *)(*match)->data;
-
- switch (c) {
- char *end;
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-
- markinfo->mark = strtoul(optarg, &end, 0);
- markinfo->mask = 0xffffffffUL;
-
- if (*end == '/')
- markinfo->mask = strtoul(end+1, &end, 0);
-
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (invert)
- markinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_mark(unsigned long mark, unsigned long mask, int numeric)
-{
- if(mask != 0xffffffffUL)
- printf("0x%lx/0x%lx ", mark, mask);
- else
- printf("0x%lx ", mark);
-}
-
-/* Final check; must have specified --mark. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK match: You must specify `--mark'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
-
- printf("CONNMARK match ");
- if (info->invert)
- printf("!");
- print_mark(info->mark, info->mask, numeric);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_connmark_info *info = (struct ipt_connmark_info *)match->data;
-
- if (info->invert)
- printf("! ");
-
- printf("--mark ");
- print_mark(info->mark, info->mask, 0);
-}
-
-static struct iptables_match connmark_match = {
- .name = "connmark",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_connmark_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_connmark_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_2connmark_init(void)
-{
- register_match(&connmark_match);
-}
diff --git a/extensions/libipt_2dscp.c b/extensions/libipt_2dscp.c
deleted file mode 100644
index 1cf8c2e..0000000
--- a/extensions/libipt_2dscp.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Shared library add-on to iptables for DSCP
- *
- * (C) 2002 by Harald Welte <laforge@gnumonks.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- * libipt_dscp.c borrowed heavily from libipt_tos.c
- *
- * --class support added by Iain Barnes
- *
- * For a list of DSCP codepoints see
- * http://www.iana.org/assignments/dscp-registry
- *
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_2dscp.h>
-
-/* This is evil, but it's my code - HW*/
-#include "libipt_dscp_helper.c"
-
-static void help(void)
-{
- printf(
-"DSCP match v%s options\n"
-"[!] --dscp value Match DSCP codepoint with numerical value\n"
-" This value can be in decimal (ex: 32)\n"
-" or in hex (ex: 0x20)\n"
-"[!] --dscp-class name Match the DiffServ class. This value may\n"
-" be any of the BE,EF, AFxx or CSx classes\n"
-"\n"
-" These two options are mutually exclusive !\n"
- , IPTABLES_VERSION
-);
-}
-
-static struct option opts[] = {
- { "dscp", 1, 0, 'F' },
- { "dscp-class", 1, 0, 'G' },
- { 0 }
-};
-
-static void
-parse_dscp(const char *s, struct ipt_dscp_info *dinfo)
-{
- unsigned int dscp;
-
- if (string_to_number(s, 0, 255, &dscp) == -1)
- exit_error(PARAMETER_PROBLEM,
- "Invalid dscp `%s'\n", s);
-
- if (dscp > IPT_DSCP_MAX)
- exit_error(PARAMETER_PROBLEM,
- "DSCP `%d` out of range\n", dscp);
-
- dinfo->dscp = (u_int8_t )dscp;
- return;
-}
-
-
-static void
-parse_class(const char *s, struct ipt_dscp_info *dinfo)
-{
- unsigned int dscp = class_to_dscp(s);
-
- /* Assign the value */
- dinfo->dscp = (u_int8_t)dscp;
-}
-
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_dscp_info *dinfo
- = (struct ipt_dscp_info *)(*match)->data;
-
- switch (c) {
- case 'F':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "DSCP match: Only use --dscp ONCE!");
- check_inverse(optarg, &invert, &optind, 0);
- parse_dscp(argv[optind-1], dinfo);
- if (invert)
- dinfo->invert = 1;
- *flags = 1;
- break;
-
- case 'G':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "DSCP match: Only use --dscp-class ONCE!");
- check_inverse(optarg, &invert, &optind, 0);
- parse_class(argv[optind - 1], dinfo);
- if (invert)
- dinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "DSCP match: Parameter --dscp is required");
-}
-
-static void
-print_dscp(u_int8_t dscp, int invert, int numeric)
-{
- if (invert)
- fputc('!', stdout);
-
- printf("0x%02x ", dscp);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_dscp_info *dinfo =
- (const struct ipt_dscp_info *)match->data;
- printf("DSCP match ");
- print_dscp(dinfo->dscp, dinfo->invert, numeric);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- const struct ipt_dscp_info *dinfo =
- (const struct ipt_dscp_info *)match->data;
-
- printf("--dscp ");
- print_dscp(dinfo->dscp, dinfo->invert, 1);
-}
-
-static struct iptables_match dscp = {
- .next = NULL,
- .name = "dscp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_dscp_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_dscp_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_2dscp_init(void)
-{
- register_match(&dscp);
-}
diff --git a/extensions/libipt_2mark.c b/extensions/libipt_2mark.c
deleted file mode 100644
index 5dbd2c8..0000000
--- a/extensions/libipt_2mark.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Shared library add-on to iptables to add NFMARK matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_2mark.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MARK match v%s options:\n"
-"[!] --mark value[/mask] Match nfmark value with optional mask\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mark", 1, 0, '1' },
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_mark_info *markinfo = (struct ipt_mark_info *)(*match)->data;
-
- switch (c) {
- char *end;
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-#ifdef KERNEL_64_USERSPACE_32
- markinfo->mark = strtoull(optarg, &end, 0);
- if (*end == '/') {
- markinfo->mask = strtoull(end+1, &end, 0);
- } else
- markinfo->mask = 0xffffffffffffffffULL;
-#else
- markinfo->mark = strtoul(optarg, &end, 0);
- if (*end == '/') {
- markinfo->mask = strtoul(end+1, &end, 0);
- } else
- markinfo->mask = 0xffffffff;
-#endif
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (invert)
- markinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-#ifdef KERNEL_64_USERSPACE_32
-static void
-print_mark(unsigned long long mark, unsigned long long mask, int numeric)
-{
- if(mask != 0xffffffffffffffffULL)
- printf("0x%llx/0x%llx ", mark, mask);
- else
- printf("0x%llx ", mark);
-}
-#else
-static void
-print_mark(unsigned long mark, unsigned long mask, int numeric)
-{
- if(mask != 0xffffffff)
- printf("0x%lx/0x%lx ", mark, mask);
- else
- printf("0x%lx ", mark);
-}
-#endif
-
-/* Final check; must have specified --mark. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK match: You must specify `--mark'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_mark_info *info = (struct ipt_mark_info *)match->data;
-
- printf("MARK match ");
-
- if (info->invert)
- printf("!");
-
- print_mark(info->mark, info->mask, numeric);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_mark_info *info = (struct ipt_mark_info *)match->data;
-
- if (info->invert)
- printf("! ");
-
- printf("--mark ");
- print_mark(info->mark, info->mask, 0);
-}
-
-static struct iptables_match mark = {
- .next = NULL,
- .name = "mark",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_mark_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_mark_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_2mark_init(void)
-{
- register_match(&mark);
-}
diff --git a/extensions/libipt_2set.c b/extensions/libipt_2set.c
deleted file mode 100644
index 697ed55..0000000
--- a/extensions/libipt_2set.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Shared library add-on to iptables to add IP set matching. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ipt_set.h>
-#include "libipt_2set.h"
-
-/* Function which prints out usage message. */
-static void help(void)
-{
- printf("set v%s options:\n"
- " [!] --set name flags\n"
- " 'name' is the set name from to match,\n"
- " 'flags' are the comma separated list of\n"
- " 'src' and 'dst'.\n"
- "\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- {"set", 1, 0, '1'},
- {0}
-};
-
-/* Initialize the match. */
-static void init(struct ipt_entry_match *match, unsigned int *nfcache)
-{
- struct ipt_set_info_match *info =
- (struct ipt_set_info_match *) match->data;
-
-
- memset(info, 0, sizeof(struct ipt_set_info_match));
-
-}
-
-/* Function which parses command options; returns true if it ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache, struct ipt_entry_match **match)
-{
- struct ipt_set_info_match *myinfo =
- (struct ipt_set_info_match *) (*match)->data;
- struct ipt_set_info *info = &myinfo->match_set;
-
- switch (c) {
- case '1': /* --set <set> <flag>[,<flag> */
- if (info->flags[0])
- exit_error(PARAMETER_PROBLEM,
- "--set can be specified only once");
-
- check_inverse(optarg, &invert, &optind, 0);
- if (invert)
- info->flags[0] |= IPSET_MATCH_INV;
-
- if (!argv[optind]
- || argv[optind][0] == '-'
- || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
- "--set requires two args.");
-
- if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1)
- exit_error(PARAMETER_PROBLEM,
- "setname `%s' too long, max %d characters.",
- argv[optind-1], IP_SET_MAXNAMELEN - 1);
-
- get_set_byname(argv[optind - 1], info);
- parse_bindings(argv[optind], info);
- DEBUGP("parse: set index %u\n", info->index);
- optind++;
-
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; must have specified --set. */
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "You must specify `--set' with proper arguments");
- DEBUGP("final check OK\n");
-}
-
-static void
-print_match(const char *prefix, const struct ipt_set_info *info)
-{
- int i;
- char setname[IP_SET_MAXNAMELEN];
-
- get_set_byid(setname, info->index);
- printf("%s%s %s",
- (info->flags[0] & IPSET_MATCH_INV) ? "! " : "",
- prefix,
- setname);
- for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
- if (!info->flags[i])
- break;
- printf("%s%s",
- i == 0 ? " " : ",",
- info->flags[i] & IPSET_SRC ? "src" : "dst");
- }
- printf(" ");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match, int numeric)
-{
- struct ipt_set_info_match *info =
- (struct ipt_set_info_match *) match->data;
-
- print_match("set", &info->match_set);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
-{
- struct ipt_set_info_match *info =
- (struct ipt_set_info_match *) match->data;
-
- print_match("--set", &info->match_set);
-}
-
-static
-struct iptables_match set = {
- .name = "set",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_set_info_match)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_set_info_match)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_2set_init(void)
-{
- register_match(&set);
-}
diff --git a/extensions/libipt_2tcpmss.c b/extensions/libipt_2tcpmss.c
deleted file mode 100644
index 28eea83..0000000
--- a/extensions/libipt_2tcpmss.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* Shared library add-on to iptables to add tcp MSS matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_2tcpmss.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"tcpmss match v%s options:\n"
-"[!] --mss value[:value] Match TCP MSS range.\n"
-" (only valid for TCP SYN or SYN/ACK packets)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mss", 1, 0, '1' },
- {0}
-};
-
-static u_int16_t
-parse_tcp_mssvalue(const char *mssvalue)
-{
- unsigned int mssvaluenum;
-
- if (string_to_number(mssvalue, 0, 65535, &mssvaluenum) != -1)
- return (u_int16_t)mssvaluenum;
-
- exit_error(PARAMETER_PROBLEM,
- "Invalid mss `%s' specified", mssvalue);
-}
-
-static void
-parse_tcp_mssvalues(const char *mssvaluestring,
- u_int16_t *mss_min, u_int16_t *mss_max)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(mssvaluestring);
- if ((cp = strchr(buffer, ':')) == NULL)
- *mss_min = *mss_max = parse_tcp_mssvalue(buffer);
- else {
- *cp = '\0';
- cp++;
-
- *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0;
- *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF;
- }
- free(buffer);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_tcpmss_match_info *mssinfo =
- (struct ipt_tcpmss_match_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--mss' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_mssvalues(argv[optind-1],
- &mssinfo->mss_min, &mssinfo->mss_max);
- if (invert)
- mssinfo->invert = 1;
- *flags = 1;
- break;
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_tcpmss(u_int16_t mss_min, u_int16_t mss_max, int invert, int numeric)
-{
- if (invert)
- printf("! ");
-
- if (mss_min == mss_max)
- printf("%u ", mss_min);
- else
- printf("%u:%u ", mss_min, mss_max);
-}
-
-/* Final check; must have specified --mss. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "tcpmss match: You must specify `--mss'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_tcpmss_match_info *mssinfo =
- (const struct ipt_tcpmss_match_info *)match->data;
-
- printf("tcpmss match ");
- print_tcpmss(mssinfo->mss_min, mssinfo->mss_max,
- mssinfo->invert, numeric);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- const struct ipt_tcpmss_match_info *mssinfo =
- (const struct ipt_tcpmss_match_info *)match->data;
-
- printf("--mss ");
- print_tcpmss(mssinfo->mss_min, mssinfo->mss_max,
- mssinfo->invert, 0);
-}
-
-static struct iptables_match tcpmss = {
- .next = NULL,
- .name = "tcpmss",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_2tcpmss_init(void)
-{
- register_match(&tcpmss);
-}
diff --git a/extensions/libipt_2tos.c b/extensions/libipt_2tos.c
deleted file mode 100644
index 49dbac5..0000000
--- a/extensions/libipt_2tos.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Shared library add-on to iptables to add TOS matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_tos_.h>
-
-/* TOS names and values. */
-static
-struct TOS_value
-{
- unsigned char TOS;
- const char *name;
-} TOS_values[] = {
- { IPTOS_LOWDELAY, "Minimize-Delay" },
- { IPTOS_THROUGHPUT, "Maximize-Throughput" },
- { IPTOS_RELIABILITY, "Maximize-Reliability" },
- { IPTOS_MINCOST, "Minimize-Cost" },
- { IPTOS_NORMALSVC, "Normal-Service" },
-};
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- unsigned int i;
-
- printf(
-"TOS match v%s options:\n"
-"[!] --tos value Match Type of Service field from one of the\n"
-" following numeric or descriptive values:\n",
-IPTABLES_VERSION);
-
- for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++)
- printf(" %s %u (0x%02x)\n",
- TOS_values[i].name,
- TOS_values[i].TOS,
- TOS_values[i].TOS);
- fputc('\n', stdout);
-}
-
-static struct option opts[] = {
- { "tos", 1, 0, '1' },
- {0}
-};
-
-static void
-parse_tos(const char *s, struct ipt_tos_info *info)
-{
- unsigned int i;
- unsigned int tos;
-
- if (string_to_number(s, 0, 255, &tos) != -1) {
- if (tos == IPTOS_LOWDELAY
- || tos == IPTOS_THROUGHPUT
- || tos == IPTOS_RELIABILITY
- || tos == IPTOS_MINCOST
- || tos == IPTOS_NORMALSVC) {
- info->tos = (u_int8_t )tos;
- return;
- }
- } else {
- for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
- if (strcasecmp(s,TOS_values[i].name) == 0) {
- info->tos = TOS_values[i].TOS;
- return;
- }
- }
- exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_tos_info *tosinfo = (struct ipt_tos_info *)(*match)->data;
-
- switch (c) {
- case '1':
- /* Ensure that `--tos' haven't been used yet. */
- if (*flags == 1)
- exit_error(PARAMETER_PROBLEM,
- "tos match: only use --tos once!");
-
- check_inverse(optarg, &invert, &optind, 0);
- parse_tos(argv[optind-1], tosinfo);
- if (invert)
- tosinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_tos(u_int8_t tos, int numeric)
-{
- unsigned int i;
-
- if (!numeric) {
- for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
- if (TOS_values[i].TOS == tos) {
- printf("%s ", TOS_values[i].name);
- return;
- }
- }
- printf("0x%02x ", tos);
-}
-
-/* Final check; must have specified --tos. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "TOS match: You must specify `--tos'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data;
-
- printf("TOS match ");
- if (info->invert)
- printf("!");
- print_tos(info->tos, numeric);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- const struct ipt_tos_info *info = (const struct ipt_tos_info *)match->data;
-
- if (info->invert)
- printf("! ");
- printf("--tos ");
- print_tos(info->tos, 0);
-}
-
-static struct iptables_match tos = {
- .next = NULL,
- .name = "tos",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tos_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tos_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_2tos_init(void)
-{
- register_match(&tos);
-}
diff --git a/extensions/libipt_CLASSIFY.c b/extensions/libipt_CLASSIFY.c
deleted file mode 100644
index 8fad60b..0000000
--- a/extensions/libipt_CLASSIFY.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Shared library add-on to iptables to add CLASSIFY target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
-#include <linux/types.h>
-#include <linux/pkt_sched.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"CLASSIFY target v%s options:\n"
-" --set-class [MAJOR:MINOR] Set skb->priority value\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "set-class", 1, 0, '1' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-int string_to_priority(const char *s, unsigned int *p)
-{
- unsigned int i, j;
-
- if (sscanf(s, "%x:%x", &i, &j) != 2)
- return 1;
-
- *p = TC_H_MAKE(i<<16, j);
- return 0;
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_classify_target_info *clinfo
- = (struct ipt_classify_target_info *)(*target)->data;
-
- switch (c) {
- case '1':
- if (string_to_priority(optarg, &clinfo->priority))
- exit_error(PARAMETER_PROBLEM,
- "Bad class value `%s'", optarg);
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CLASSIFY: Can't specify --set-class twice");
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "CLASSIFY: Parameter --set-class is required");
-}
-
-static void
-print_class(unsigned int priority, int numeric)
-{
- printf("%x:%x ", TC_H_MAJ(priority)>>16, TC_H_MIN(priority));
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_classify_target_info *clinfo =
- (const struct ipt_classify_target_info *)target->data;
- printf("CLASSIFY set ");
- print_class(clinfo->priority, numeric);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_classify_target_info *clinfo =
- (const struct ipt_classify_target_info *)target->data;
-
- printf("--set-class %.4x:%.4x ",
- TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
-}
-
-static struct iptables_target classify = {
- .next = NULL,
- .name = "CLASSIFY",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_classify_target_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_classify_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_CLASSIFY_init(void)
-{
- register_target(&classify);
-}
diff --git a/extensions/libipt_CLASSIFY.man b/extensions/libipt_CLASSIFY.man
deleted file mode 100644
index 393c329..0000000
--- a/extensions/libipt_CLASSIFY.man
+++ /dev/null
@@ -1,4 +0,0 @@
-This module allows you to set the skb->priority value (and thus classify the packet into a specific CBQ class).
-.TP
-.BI "--set-class " "MAJOR:MINOR"
-Set the major and minor class value.
diff --git a/extensions/libipt_CLUSTERIP.c b/extensions/libipt_CLUSTERIP.c
index 1ab77cc..cae814b 100644
--- a/extensions/libipt_CLUSTERIP.c
+++ b/extensions/libipt_CLUSTERIP.c
@@ -15,15 +15,13 @@
#include <linux/if_ether.h>
#endif
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include "../include/linux/netfilter_ipv4/ipt_CLUSTERIP.h"
+#include <xtables.h>
+#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
-static void
-help(void)
+static void CLUSTERIP_help(void)
{
printf(
-"CLUSTERIP target v%s options:\n"
+"CLUSTERIP target options:\n"
" --new Create a new ClusterIP\n"
" --hashmode <mode> Specify hashing mode\n"
" sourceip\n"
@@ -32,9 +30,7 @@ help(void)
" --clustermac <mac> Set clusterIP MAC address\n"
" --total-nodes <num> Set number of total nodes in cluster\n"
" --local-node <num> Set the local node number\n"
-" --hash-init <num> Set init value of the Jenkins hash\n"
-"\n",
-IPTABLES_VERSION);
+" --hash-init <num> Set init value of the Jenkins hash\n");
}
#define PARAM_NEW 0x0001
@@ -44,28 +40,23 @@ IPTABLES_VERSION);
#define PARAM_LOCALNODE 0x0010
#define PARAM_HASHINIT 0x0020
-static struct option opts[] = {
- { "new", 0, 0, '1' },
- { "hashmode", 1, 0, '2' },
- { "clustermac", 1, 0, '3' },
- { "total-nodes", 1, 0, '4' },
- { "local-node", 1, 0, '5' },
- { "hash-init", 1, 0, '6' },
- { 0 }
+static const struct option CLUSTERIP_opts[] = {
+ { "new", 0, NULL, '1' },
+ { "hashmode", 1, NULL, '2' },
+ { "clustermac", 1, NULL, '3' },
+ { "total-nodes", 1, NULL, '4' },
+ { "local-node", 1, NULL, '5' },
+ { "hash-init", 1, NULL, '6' },
+ { .name = NULL }
};
static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void
parse_mac(const char *mac, char *macbuf)
{
unsigned int i = 0;
if (strlen(mac) != ETH_ALEN*3-1)
- exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
+ xtables_error(PARAMETER_PROBLEM, "Bad mac address \"%s\"", mac);
for (i = 0; i < ETH_ALEN; i++) {
long number;
@@ -78,15 +69,13 @@ parse_mac(const char *mac, char *macbuf)
&& number <= 255)
macbuf[i] = number;
else
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Bad mac address `%s'", mac);
}
}
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int CLUSTERIP_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_clusterip_tgt_info *cipinfo
= (struct ipt_clusterip_tgt_info *)(*target)->data;
@@ -96,14 +85,14 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '1':
cipinfo->flags |= CLUSTERIP_FLAG_NEW;
if (*flags & PARAM_NEW)
- exit_error(PARAMETER_PROBLEM, "Can only specify `--new' once\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify \"--new\" once\n");
*flags |= PARAM_NEW;
break;
case '2':
if (!(*flags & PARAM_NEW))
- exit_error(PARAMETER_PROBLEM, "Can only specify hashmode combined with `--new'\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify hashmode combined with \"--new\"\n");
if (*flags & PARAM_HMODE)
- exit_error(PARAMETER_PROBLEM, "Can only specify hashmode once\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify hashmode once\n");
if (!strcmp(optarg, "sourceip"))
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP;
else if (!strcmp(optarg, "sourceip-sourceport"))
@@ -111,48 +100,48 @@ parse(int c, char **argv, int invert, unsigned int *flags,
else if (!strcmp(optarg, "sourceip-sourceport-destport"))
cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT_DPT;
else
- exit_error(PARAMETER_PROBLEM, "Unknown hashmode `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Unknown hashmode \"%s\"\n",
optarg);
*flags |= PARAM_HMODE;
break;
case '3':
if (!(*flags & PARAM_NEW))
- exit_error(PARAMETER_PROBLEM, "Can only specify MAC combined with `--new'\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify MAC combined with \"--new\"\n");
if (*flags & PARAM_MAC)
- exit_error(PARAMETER_PROBLEM, "Can only specify MAC once\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify MAC once\n");
parse_mac(optarg, (char *)cipinfo->clustermac);
if (!(cipinfo->clustermac[0] & 0x01))
- exit_error(PARAMETER_PROBLEM, "MAC has to be a multicast ethernet address\n");
+ xtables_error(PARAMETER_PROBLEM, "MAC has to be a multicast ethernet address\n");
*flags |= PARAM_MAC;
break;
case '4':
if (!(*flags & PARAM_NEW))
- exit_error(PARAMETER_PROBLEM, "Can only specify node number combined with `--new'\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify node number combined with \"--new\"\n");
if (*flags & PARAM_TOTALNODE)
- exit_error(PARAMETER_PROBLEM, "Can only specify total node number once\n");
- if (string_to_number(optarg, 1, CLUSTERIP_MAX_NODES, &num) < 0)
- exit_error(PARAMETER_PROBLEM, "Unable to parse `%s'\n", optarg);
- cipinfo->num_total_nodes = (u_int16_t)num;
+ xtables_error(PARAMETER_PROBLEM, "Can only specify total node number once\n");
+ if (!xtables_strtoui(optarg, NULL, &num, 1, CLUSTERIP_MAX_NODES))
+ xtables_error(PARAMETER_PROBLEM, "Unable to parse \"%s\"\n", optarg);
+ cipinfo->num_total_nodes = num;
*flags |= PARAM_TOTALNODE;
break;
case '5':
if (!(*flags & PARAM_NEW))
- exit_error(PARAMETER_PROBLEM, "Can only specify node number combined with `--new'\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify node number combined with \"--new\"\n");
if (*flags & PARAM_LOCALNODE)
- exit_error(PARAMETER_PROBLEM, "Can only specify local node number once\n");
- if (string_to_number(optarg, 1, CLUSTERIP_MAX_NODES, &num) < 0)
- exit_error(PARAMETER_PROBLEM, "Unable to parse `%s'\n", optarg);
+ xtables_error(PARAMETER_PROBLEM, "Can only specify local node number once\n");
+ if (!xtables_strtoui(optarg, NULL, &num, 1, CLUSTERIP_MAX_NODES))
+ xtables_error(PARAMETER_PROBLEM, "Unable to parse \"%s\"\n", optarg);
cipinfo->num_local_nodes = 1;
- cipinfo->local_nodes[0] = (u_int16_t)num;
+ cipinfo->local_nodes[0] = num;
*flags |= PARAM_LOCALNODE;
break;
case '6':
if (!(*flags & PARAM_NEW))
- exit_error(PARAMETER_PROBLEM, "Can only specify hash init value combined with `--new'\n");
+ xtables_error(PARAMETER_PROBLEM, "Can only specify hash init value combined with \"--new\"\n");
if (*flags & PARAM_HASHINIT)
- exit_error(PARAMETER_PROBLEM, "Can specify hash init value only once\n");
- if (string_to_number(optarg, 0, UINT_MAX, &num) < 0)
- exit_error(PARAMETER_PROBLEM, "Unable to parse `%s'\n", optarg);
+ xtables_error(PARAMETER_PROBLEM, "Can specify hash init value only once\n");
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT_MAX))
+ xtables_error(PARAMETER_PROBLEM, "Unable to parse \"%s\"\n", optarg);
cipinfo->hash_initval = num;
*flags |= PARAM_HASHINIT;
break;
@@ -163,8 +152,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void
-final_check(unsigned int flags)
+static void CLUSTERIP_check(unsigned int flags)
{
if (flags == 0)
return;
@@ -173,7 +161,7 @@ final_check(unsigned int flags)
== (PARAM_NEW|PARAM_HMODE|PARAM_MAC|PARAM_TOTALNODE|PARAM_LOCALNODE))
return;
- exit_error(PARAMETER_PROBLEM, "CLUSTERIP target: Invalid parameter combination\n");
+ xtables_error(PARAMETER_PROBLEM, "CLUSTERIP target: Invalid parameter combination\n");
}
static char *hashmode2str(enum clusterip_hashmode mode)
@@ -203,13 +191,9 @@ static char *mac2str(const u_int8_t mac[ETH_ALEN])
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return buf;
}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void CLUSTERIP_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
{
const struct ipt_clusterip_tgt_info *cipinfo =
(const struct ipt_clusterip_tgt_info *)target->data;
@@ -227,9 +211,7 @@ print(const struct ipt_ip *ip,
cipinfo->hash_initval);
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void CLUSTERIP_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_clusterip_tgt_info *cipinfo =
(const struct ipt_clusterip_tgt_info *)target->data;
@@ -247,22 +229,21 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
cipinfo->hash_initval);
}
-static struct iptables_target clusterip = {
- .next = NULL,
+static struct xtables_target clusterip_tg_reg = {
.name = "CLUSTERIP",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)),
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)),
.userspacesize = offsetof(struct ipt_clusterip_tgt_info, config),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .help = CLUSTERIP_help,
+ .parse = CLUSTERIP_parse,
+ .final_check = CLUSTERIP_check,
+ .print = CLUSTERIP_print,
+ .save = CLUSTERIP_save,
+ .extra_opts = CLUSTERIP_opts,
};
-void ipt_CLUSTERIP_init(void)
+void libipt_CLUSTERIP_init(void)
{
- register_target(&clusterip);
+ xtables_register_target(&clusterip_tg_reg);
}
diff --git a/extensions/libipt_CLUSTERIP.man b/extensions/libipt_CLUSTERIP.man
index 8e766f3..8ec6d6b 100644
--- a/extensions/libipt_CLUSTERIP.man
+++ b/extensions/libipt_CLUSTERIP.man
@@ -3,22 +3,22 @@ a certain IP and MAC address without an explicit load balancer in front of
them. Connections are statically distributed between the nodes in this
cluster.
.TP
-.BI "--new "
+\fB\-\-new\fP
Create a new ClusterIP. You always have to set this on the first rule
for a given ClusterIP.
.TP
-.BI "--hashmode " "mode"
+\fB\-\-hashmode\fP \fImode\fP
Specify the hashing mode. Has to be one of
-.B sourceip, sourceip-sourceport, sourceip-sourceport-destport
+\fBsourceip\fP, \fBsourceip\-sourceport\fP, \fBsourceip\-sourceport\-destport\fP.
.TP
-.BI "--clustermac " "mac"
-Specify the ClusterIP MAC address. Has to be a link-layer multicast address
+\fB\-\-clustermac\fP \fImac\fP
+Specify the ClusterIP MAC address. Has to be a link\-layer multicast address
.TP
-.BI "--total-nodes " "num"
+\fB\-\-total\-nodes\fP \fInum\fP
Number of total nodes within this cluster.
.TP
-.BI "--local-node " "num"
+\fB\-\-local\-node\fP \fInum\fP
Local node number within this cluster.
.TP
-.BI "--hash-init " "rnd"
+\fB\-\-hash\-init\fP \fIrnd\fP
Specify the random seed used for hash initialization.
diff --git a/extensions/libipt_CONNMARK.c b/extensions/libipt_CONNMARK.c
deleted file mode 100644
index 30dc4b0..0000000
--- a/extensions/libipt_CONNMARK.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/* Shared library add-on to iptables to add CONNMARK target support.
- *
- * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
- * by Henrik Nordstrom <hno@marasystems.com>
- *
- * Version 1.1
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include "../include/linux/netfilter_ipv4/ipt_CONNMARK.h"
-
-#if 0
-struct markinfo {
- struct ipt_entry_target t;
- struct ipt_connmark_target_info mark;
-};
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"CONNMARK target v%s options:\n"
-" --set-mark value[/mask] Set conntrack mark value\n"
-" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
-" --restore-mark [--mask mask] Restore saved nfmark value\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "set-mark", 1, 0, '1' },
- { "save-mark", 0, 0, '2' },
- { "restore-mark", 0, 0, '3' },
- { "mask", 1, 0, '4' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_connmark_target_info *markinfo
- = (struct ipt_connmark_target_info *)(*target)->data;
-
- markinfo->mask = 0xffffffffUL;
-
- switch (c) {
- char *end;
- case '1':
- markinfo->mode = IPT_CONNMARK_SET;
-
- markinfo->mark = strtoul(optarg, &end, 0);
- if (*end == '/' && end[1] != '\0')
- markinfo->mask = strtoul(end+1, &end, 0);
-
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --set-mark twice");
- *flags = 1;
- break;
- case '2':
- markinfo->mode = IPT_CONNMARK_SAVE;
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --save-mark twice");
- *flags = 1;
- break;
- case '3':
- markinfo->mode = IPT_CONNMARK_RESTORE;
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --restore-mark twice");
- *flags = 1;
- break;
- case '4':
- if (!*flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: Can't specify --mask without a operation");
- markinfo->mask = strtoul(optarg, &end, 0);
-
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad MASK value `%s'", optarg);
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "CONNMARK target: No operation specified");
-}
-
-static void
-print_mark(unsigned long mark)
-{
- printf("0x%lx", mark);
-}
-
-static void
-print_mask(const char *text, unsigned long mask)
-{
- if (mask != 0xffffffffUL)
- printf("%s0x%lx", text, mask);
-}
-
-
-/* Prints out the target info. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_connmark_target_info *markinfo =
- (const struct ipt_connmark_target_info *)target->data;
- switch (markinfo->mode) {
- case IPT_CONNMARK_SET:
- printf("CONNMARK set ");
- print_mark(markinfo->mark);
- print_mask("/", markinfo->mask);
- printf(" ");
- break;
- case IPT_CONNMARK_SAVE:
- printf("CONNMARK save ");
- print_mask("mask ", markinfo->mask);
- printf(" ");
- break;
- case IPT_CONNMARK_RESTORE:
- printf("CONNMARK restore ");
- print_mask("mask ", markinfo->mask);
- break;
- default:
- printf("ERROR: UNKNOWN CONNMARK MODE ");
- break;
- }
-}
-
-/* Saves the target into in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_connmark_target_info *markinfo =
- (const struct ipt_connmark_target_info *)target->data;
-
- switch (markinfo->mode) {
- case IPT_CONNMARK_SET:
- printf("--set-mark ");
- print_mark(markinfo->mark);
- print_mask("/", markinfo->mask);
- printf(" ");
- break;
- case IPT_CONNMARK_SAVE:
- printf("--save-mark ");
- print_mask("--mask ", markinfo->mask);
- break;
- case IPT_CONNMARK_RESTORE:
- printf("--restore-mark ");
- print_mask("--mask ", markinfo->mask);
- break;
- default:
- printf("ERROR: UNKNOWN CONNMARK MODE ");
- break;
- }
-}
-
-static struct iptables_target connmark_target = {
- .name = "CONNMARK",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_connmark_target_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_connmark_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_CONNMARK_init(void)
-{
- register_target(&connmark_target);
-}
diff --git a/extensions/libipt_CONNMARK.man b/extensions/libipt_CONNMARK.man
deleted file mode 100644
index 8b4de5a..0000000
--- a/extensions/libipt_CONNMARK.man
+++ /dev/null
@@ -1,15 +0,0 @@
-This module sets the netfilter mark value associated with a connection
-.TP
-.B --set-mark mark[/mask]
-Set connection mark. If a mask is specified then only those bits set in the
-mask is modified.
-.TP
-.B --save-mark [--mask mask]
-Copy the netfilter packet mark value to the connection mark. If a mask
-is specified then only those bits are copied.
-.TP
-.B --restore-mark [--mask mask]
-Copy the connection mark value to the packet. If a mask is specified
-then only those bits are copied. This is only valid in the
-.B mangle
-table.
diff --git a/extensions/libipt_CONNSECMARK.c b/extensions/libipt_CONNSECMARK.c
deleted file mode 100644
index bcd89ea..0000000
--- a/extensions/libipt_CONNSECMARK.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Shared library add-on to iptables to add CONNSECMARK target support.
- *
- * Based on the MARK and CONNMARK targets.
- *
- * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter/xt_CONNSECMARK.h>
-
-#define PFX "CONNSECMARK target: "
-
-static void help(void)
-{
- printf(
-"CONNSECMARK target v%s options:\n"
-" --save Copy security mark from packet to conntrack\n"
-" --restore Copy security mark from connection to packet\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "save", 0, 0, '1' },
- { "restore", 0, 0, '2' },
- { 0 }
-};
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry, struct ipt_entry_target **target)
-{
- struct xt_connsecmark_target_info *info =
- (struct xt_connsecmark_target_info*)(*target)->data;
-
- switch (c) {
- case '1':
- if (*flags & CONNSECMARK_SAVE)
- exit_error(PARAMETER_PROBLEM, PFX
- "Can't specify --save twice");
- info->mode = CONNSECMARK_SAVE;
- *flags |= CONNSECMARK_SAVE;
- break;
-
- case '2':
- if (*flags & CONNSECMARK_RESTORE)
- exit_error(PARAMETER_PROBLEM, PFX
- "Can't specify --restore twice");
- info->mode = CONNSECMARK_RESTORE;
- *flags |= CONNSECMARK_RESTORE;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, PFX "parameter required");
-
- if (flags == (CONNSECMARK_SAVE|CONNSECMARK_RESTORE))
- exit_error(PARAMETER_PROBLEM, PFX "only one flag of --save "
- "or --restore is allowed");
-}
-
-static void print_connsecmark(struct xt_connsecmark_target_info *info)
-{
- switch (info->mode) {
- case CONNSECMARK_SAVE:
- printf("save ");
- break;
-
- case CONNSECMARK_RESTORE:
- printf("restore ");
- break;
-
- default:
- exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
- }
-}
-
-static void print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target, int numeric)
-{
- struct xt_connsecmark_target_info *info =
- (struct xt_connsecmark_target_info*)(target)->data;
-
- printf("CONNSECMARK ");
- print_connsecmark(info);
-}
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- struct xt_connsecmark_target_info *info =
- (struct xt_connsecmark_target_info*)target->data;
-
- printf("--");
- print_connsecmark(info);
-}
-
-static struct iptables_target connsecmark = {
- .next = NULL,
- .name = "CONNSECMARK",
- .version = IPTABLES_VERSION,
- .revision = 0,
- .size = IPT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
- .parse = &parse,
- .help = &help,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_CONNSECMARK_init(void)
-{
- register_target(&connsecmark);
-}
diff --git a/extensions/libipt_CONNSECMARK.man b/extensions/libipt_CONNSECMARK.man
deleted file mode 100644
index b94353a..0000000
--- a/extensions/libipt_CONNSECMARK.man
+++ /dev/null
@@ -1,15 +0,0 @@
-This module copies security markings from packets to connections
-(if unlabeled), and from connections back to packets (also only
-if unlabeled). Typically used in conjunction with SECMARK, it is
-only valid in the
-.B mangle
-table.
-.TP
-.B --save
-If the packet has a security marking, copy it to the connection
-if the connection is not marked.
-.TP
-.B --restore
-If the packet does not have a security marking, and the connection
-does, copy the security marking from the connection to the packet.
-
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index fdc2115..7b69be9 100644
--- a/extensions/libipt_DNAT.c
+++ b/extensions/libipt_DNAT.c
@@ -4,47 +4,50 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
+#include <iptables.h> /* get_kernel_version */
+#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
-#include <netinet/in.h>
+#include <net/netfilter/nf_nat.h>
+
+#define IPT_DNAT_OPT_DEST 0x1
+#define IPT_DNAT_OPT_RANDOM 0x2
/* Dest NAT data consists of a multi-range, indicating where to map
to. */
struct ipt_natinfo
{
- struct ipt_entry_target t;
- struct ip_nat_multi_range mr;
+ struct xt_entry_target t;
+ struct nf_nat_multi_range mr;
};
-/* Function which prints out usage message. */
-static void
-help(void)
+static void DNAT_help(void)
{
printf(
-"DNAT v%s options:\n"
+"DNAT target options:\n"
" --to-destination <ipaddr>[-<ipaddr>][:port-port]\n"
" Address to map destination to.\n"
-" (You can use this more than once)\n\n",
-IPTABLES_VERSION);
+"[--random] [--persistent]\n");
}
-static struct option opts[] = {
- { "to-destination", 1, 0, '1' },
- { 0 }
+static const struct option DNAT_opts[] = {
+ { "to-destination", 1, NULL, '1' },
+ { "random", 0, NULL, '2' },
+ { "persistent", 0, NULL, '3' },
+ { .name = NULL }
};
static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct ip_nat_range *range)
+append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
{
unsigned int size;
/* One rangesize already in struct ipt_natinfo */
- size = IPT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
+ size = XT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
info = realloc(info, size);
if (!info)
- exit_error(OTHER_PROBLEM, "Out of memory\n");
+ xtables_error(OTHER_PROBLEM, "Out of memory\n");
info->t.u.target_size = size;
info->mr.range[info->mr.rangesize] = *range;
@@ -54,12 +57,12 @@ append_range(struct ipt_natinfo *info, const struct ip_nat_range *range)
}
/* Ranges expected in network order. */
-static struct ipt_entry_target *
+static struct xt_entry_target *
parse_to(char *arg, int portok, struct ipt_natinfo *info)
{
- struct ip_nat_range range;
+ struct nf_nat_range range;
char *colon, *dash, *error;
- struct in_addr *ip;
+ const struct in_addr *ip;
memset(&range, 0, sizeof(range));
colon = strchr(arg, ':');
@@ -68,19 +71,19 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
int port;
if (!portok)
- exit_error(PARAMETER_PROBLEM,
- "Need TCP or UDP with port specification");
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", colon+1);
error = strchr(colon+1, ':');
if (error)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid port:port syntax - use dash\n");
dash = strchr(colon, '-');
@@ -93,11 +96,11 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
maxport = atoi(dash + 1);
if (maxport <= 0 || maxport > 65535)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", dash+1);
if (maxport < port)
/* People are stupid. */
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port range `%s' funky\n", colon+1);
range.min.tcp.port = htons(port);
range.max.tcp.port = htons(maxport);
@@ -116,15 +119,15 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
if (dash)
*dash = '\0';
- ip = dotted_to_addr(arg);
+ ip = xtables_numeric_to_ipaddr(arg);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
range.min_ip = ip->s_addr;
if (dash) {
- ip = dotted_to_addr(dash+1);
+ ip = xtables_numeric_to_ipaddr(dash+1);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
dash+1);
range.max_ip = ip->s_addr;
} else
@@ -133,18 +136,17 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
return &(append_range(info, &range)->t);
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int DNAT_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_target **target)
{
+ const struct ipt_entry *entry = e;
struct ipt_natinfo *info = (void *)*target;
int portok;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
+ || entry->ip.proto == IPPROTO_SCTP
+ || entry->ip.proto == IPPROTO_DCCP
|| entry->ip.proto == IPPROTO_ICMP)
portok = 1;
else
@@ -152,19 +154,34 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --to-destination");
- if (*flags) {
+ if (*flags & IPT_DNAT_OPT_DEST) {
if (!kernel_version)
get_kernel_version();
if (kernel_version > LINUX_VERSION(2, 6, 10))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Multiple --to-destination not supported");
}
*target = parse_to(optarg, portok, info);
- *flags = 1;
+ /* WTF do we need this for?? */
+ if (*flags & IPT_DNAT_OPT_RANDOM)
+ info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ *flags |= IPT_DNAT_OPT_DEST;
+ return 1;
+
+ case '2':
+ if (*flags & IPT_DNAT_OPT_DEST) {
+ info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ *flags |= IPT_DNAT_OPT_RANDOM;
+ } else
+ *flags |= IPT_DNAT_OPT_RANDOM;
+ return 1;
+
+ case '3':
+ info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
return 1;
default:
@@ -172,24 +189,23 @@ parse(int c, char **argv, int invert, unsigned int *flags,
}
}
-/* Final check; must have specfied --to-source. */
-static void final_check(unsigned int flags)
+static void DNAT_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"You must specify --to-destination");
}
-static void print_range(const struct ip_nat_range *r)
+static void print_range(const struct nf_nat_range *r)
{
if (r->flags & IP_NAT_RANGE_MAP_IPS) {
struct in_addr a;
a.s_addr = r->min_ip;
- printf("%s", addr_to_dotted(&a));
+ printf("%s", xtables_ipaddr_to_numeric(&a));
if (r->max_ip != r->min_ip) {
a.s_addr = r->max_ip;
- printf("-%s", addr_to_dotted(&a));
+ printf("-%s", xtables_ipaddr_to_numeric(&a));
}
}
if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
@@ -200,51 +216,54 @@ static void print_range(const struct ip_nat_range *r)
}
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void DNAT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
- struct ipt_natinfo *info = (void *)target;
+ const struct ipt_natinfo *info = (const void *)target;
unsigned int i = 0;
printf("to:");
for (i = 0; i < info->mr.rangesize; i++) {
print_range(&info->mr.range[i]);
printf(" ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("random ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ printf("persistent ");
}
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void DNAT_save(const void *ip, const struct xt_entry_target *target)
{
- struct ipt_natinfo *info = (void *)target;
+ const struct ipt_natinfo *info = (const void *)target;
unsigned int i = 0;
for (i = 0; i < info->mr.rangesize; i++) {
printf("--to-destination ");
print_range(&info->mr.range[i]);
printf(" ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("--random ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ printf("--persistent ");
}
}
-static struct iptables_target dnat = {
- .next = NULL,
+static struct xtables_target dnat_tg_reg = {
.name = "DNAT",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .userspacesize = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .help = DNAT_help,
+ .parse = DNAT_parse,
+ .final_check = DNAT_check,
+ .print = DNAT_print,
+ .save = DNAT_save,
+ .extra_opts = DNAT_opts,
};
-void ipt_DNAT_init(void)
+void libipt_DNAT_init(void)
{
- register_target(&dnat);
+ xtables_register_target(&dnat_tg_reg);
}
diff --git a/extensions/libipt_DNAT.man b/extensions/libipt_DNAT.man
index 366dcb7..d1e0a3a 100644
--- a/extensions/libipt_DNAT.man
+++ b/extensions/libipt_DNAT.man
@@ -10,22 +10,30 @@ should be modified (and all future packets in this connection will
also be mangled), and rules should cease being examined. It takes one
type of option:
.TP
-.BR "--to-destination " "[\fIipaddr\fP][-\fIipaddr\fP][:\fIport\fP-\fIport\fP]"
+\fB\-\-to\-destination\fP [\fIipaddr\fP][\fB\-\fP\fIipaddr\fP][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
which can specify a single new destination IP address, an inclusive
range of IP addresses, and optionally, a port range (which is only
valid if the rule also specifies
-.B "-p tcp"
+\fB\-p tcp\fP
or
-.BR "-p udp" ).
+\fB\-p udp\fP).
If no port range is specified, then the destination port will never be
modified. If no IP address is specified then only the destination port
will be modified.
-.RS
-.PP
-In Kernels up to 2.6.10 you can add several --to-destination options. For
+
+In Kernels up to 2.6.10 you can add several \-\-to\-destination options. For
those kernels, if you specify more than one destination address, either via an
-address range or multiple --to-destination options, a simple round-robin (one
+address range or multiple \-\-to\-destination options, a simple round-robin (one
after another in cycle) load balancing takes place between these addresses.
Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
anymore.
-
+.TP
+\fB\-\-random\fP
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.22).
+.TP
+\fB\-\-persistent\fP
+Gives a client the same source-/destination-address for each connection.
+This supersedes the SAME target. Support for persistent mappings is available
+from 2.6.29-rc2.
diff --git a/extensions/libipt_DSCP.c b/extensions/libipt_DSCP.c
deleted file mode 100644
index ca06835..0000000
--- a/extensions/libipt_DSCP.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Shared library add-on to iptables for DSCP
- *
- * (C) 2000- 2002 by Matthew G. Marsh <mgm@paktronix.com>,
- * Harald Welte <laforge@gnumonks.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- * libipt_DSCP.c borrowed heavily from libipt_TOS.c
- *
- * --set-class added by Iain Barnes
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_DSCP.h>
-
-/* This is evil, but it's my code - HW*/
-#include "libipt_dscp_helper.c"
-
-
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void help(void)
-{
- printf(
-"DSCP target options\n"
-" --set-dscp value Set DSCP field in packet header to value\n"
-" This value can be in decimal (ex: 32)\n"
-" or in hex (ex: 0x20)\n"
-" --set-dscp-class class Set the DSCP field in packet header to the\n"
-" value represented by the DiffServ class value.\n"
-" This class may be EF,BE or any of the CSxx\n"
-" or AFxx classes.\n"
-"\n"
-" These two options are mutually exclusive !\n"
-);
-}
-
-static struct option opts[] = {
- { "set-dscp", 1, 0, 'F' },
- { "set-dscp-class", 1, 0, 'G' },
- { 0 }
-};
-
-static void
-parse_dscp(const char *s, struct ipt_DSCP_info *dinfo)
-{
- unsigned int dscp;
-
- if (string_to_number(s, 0, 255, &dscp) == -1)
- exit_error(PARAMETER_PROBLEM,
- "Invalid dscp `%s'\n", s);
-
- if (dscp > IPT_DSCP_MAX)
- exit_error(PARAMETER_PROBLEM,
- "DSCP `%d` out of range\n", dscp);
-
- dinfo->dscp = (u_int8_t )dscp;
- return;
-}
-
-
-static void
-parse_class(const char *s, struct ipt_DSCP_info *dinfo)
-{
- unsigned int dscp = class_to_dscp(s);
-
- /* Assign the value */
- dinfo->dscp = (u_int8_t)dscp;
-}
-
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_DSCP_info *dinfo
- = (struct ipt_DSCP_info *)(*target)->data;
-
- switch (c) {
- case 'F':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "DSCP target: Only use --set-dscp ONCE!");
- parse_dscp(optarg, dinfo);
- *flags = 1;
- break;
- case 'G':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "DSCP target: Only use --set-dscp-class ONCE!");
- parse_class(optarg, dinfo);
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "DSCP target: Parameter --set-dscp is required");
-}
-
-static void
-print_dscp(u_int8_t dscp, int numeric)
-{
- printf("0x%02x ", dscp);
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_DSCP_info *dinfo =
- (const struct ipt_DSCP_info *)target->data;
- printf("DSCP set ");
- print_dscp(dinfo->dscp, numeric);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_DSCP_info *dinfo =
- (const struct ipt_DSCP_info *)target->data;
-
- printf("--set-dscp 0x%02x ", dinfo->dscp);
-}
-
-static struct iptables_target dscp = {
- .next = NULL,
- .name = "DSCP",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_DSCP_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_DSCP_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_DSCP_init(void)
-{
- register_target(&dscp);
-}
diff --git a/extensions/libipt_ECN.c b/extensions/libipt_ECN.c
index 2dfa891..7ab51c6 100644
--- a/extensions/libipt_ECN.c
+++ b/extensions/libipt_ECN.c
@@ -6,27 +6,21 @@
*
* libipt_ECN.c borrowed heavily from libipt_DSCP.c
*
- * $Id: libipt_ECN.c 3507 2004-12-28 13:11:59Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=rusty/emailAddress=rusty@netfilter.org $
+ * $Id$
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_ECN.h>
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void help(void)
+static void ECN_help(void)
{
printf(
-"ECN target v%s options\n"
-" --ecn-tcp-remove Remove all ECN bits from TCP header\n",
- IPTABLES_VERSION);
+"ECN target options\n"
+" --ecn-tcp-remove Remove all ECN bits from TCP header\n");
}
#if 0
@@ -37,18 +31,16 @@ static void help(void)
#endif
-static struct option opts[] = {
- { "ecn-tcp-remove", 0, 0, 'F' },
- { "ecn-tcp-cwr", 1, 0, 'G' },
- { "ecn-tcp-ece", 1, 0, 'H' },
- { "ecn-ip-ect", 1, 0, '9' },
- { 0 }
+static const struct option ECN_opts[] = {
+ { "ecn-tcp-remove", 0, NULL, 'F' },
+ { "ecn-tcp-cwr", 1, NULL, 'G' },
+ { "ecn-tcp-ece", 1, NULL, 'H' },
+ { "ecn-ip-ect", 1, NULL, '9' },
+ { .name = NULL }
};
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int ECN_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
unsigned int result;
struct ipt_ECN_info *einfo
@@ -57,7 +49,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case 'F':
if (*flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Only use --ecn-tcp-remove ONCE!");
einfo->operation = IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR;
einfo->proto.tcp.ece = 0;
@@ -66,10 +58,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case 'G':
if (*flags & IPT_ECN_OP_SET_CWR)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Only use --ecn-tcp-cwr ONCE!");
- if (string_to_number(optarg, 0, 1, &result))
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &result, 0, 1))
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Value out of range");
einfo->operation |= IPT_ECN_OP_SET_CWR;
einfo->proto.tcp.cwr = result;
@@ -77,10 +69,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case 'H':
if (*flags & IPT_ECN_OP_SET_ECE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Only use --ecn-tcp-ece ONCE!");
- if (string_to_number(optarg, 0, 1, &result))
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &result, 0, 1))
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Value out of range");
einfo->operation |= IPT_ECN_OP_SET_ECE;
einfo->proto.tcp.ece = result;
@@ -88,10 +80,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
break;
case '9':
if (*flags & IPT_ECN_OP_SET_IP)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Only use --ecn-ip-ect ONCE!");
- if (string_to_number(optarg, 0, 3, &result))
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &result, 0, 3))
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Value out of range");
einfo->operation |= IPT_ECN_OP_SET_IP;
einfo->ip_ect = result;
@@ -104,19 +96,15 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void
-final_check(unsigned int flags)
+static void ECN_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN target: Parameter --ecn-tcp-remove is required");
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void ECN_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ipt_ECN_info *einfo =
(const struct ipt_ECN_info *)target->data;
@@ -139,9 +127,7 @@ print(const struct ipt_ip *ip,
}
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void ECN_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_ECN_info *einfo =
(const struct ipt_ECN_info *)target->data;
@@ -163,23 +149,21 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
}
}
-static
-struct iptables_target ecn = {
- .next = NULL,
+static struct xtables_target ecn_tg_reg = {
.name = "ECN",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_ECN_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_ECN_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_ECN_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_ECN_info)),
+ .help = ECN_help,
+ .parse = ECN_parse,
+ .final_check = ECN_check,
+ .print = ECN_print,
+ .save = ECN_save,
+ .extra_opts = ECN_opts,
};
-void ipt_ECN_init(void)
+void libipt_ECN_init(void)
{
- register_target(&ecn);
+ xtables_register_target(&ecn_tg_reg);
}
diff --git a/extensions/libipt_ECN.man b/extensions/libipt_ECN.man
index 3668490..a9cbe10 100644
--- a/extensions/libipt_ECN.man
+++ b/extensions/libipt_ECN.man
@@ -1,7 +1,7 @@
This target allows to selectively work around known ECN blackholes.
It can only be used in the mangle table.
.TP
-.BI "--ecn-tcp-remove"
+\fB\-\-ecn\-tcp\-remove\fP
Remove all ECN bits from the TCP header. Of course, it can only be used
in conjunction with
-.BR "-p tcp" .
+\fB\-p tcp\fP.
diff --git a/extensions/libipt_LOG.c b/extensions/libipt_LOG.c
index 7d3fd82..e412b6c 100644
--- a/extensions/libipt_LOG.c
+++ b/extensions/libipt_LOG.c
@@ -5,8 +5,7 @@
#include <stdlib.h>
#include <syslog.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_LOG.h>
#define LOG_DEFAULT_LEVEL LOG_WARNING
@@ -17,34 +16,29 @@
#define IPT_LOG_MASK 0x0f
#endif
-/* Function which prints out usage message. */
-static void
-help(void)
+static void LOG_help(void)
{
printf(
-"LOG v%s options:\n"
+"LOG target options:\n"
" --log-level level Level of logging (numeric or see syslog.conf)\n"
" --log-prefix prefix Prefix log messages with this prefix.\n\n"
" --log-tcp-sequence Log TCP sequence numbers.\n\n"
" --log-tcp-options Log TCP options.\n\n"
" --log-ip-options Log IP options.\n\n"
-" --log-uid Log UID owning the local socket.\n\n",
-IPTABLES_VERSION);
+" --log-uid Log UID owning the local socket.\n\n");
}
-static struct option opts[] = {
- { .name = "log-level", .has_arg = 1, .flag = 0, .val = '!' },
- { .name = "log-prefix", .has_arg = 1, .flag = 0, .val = '#' },
- { .name = "log-tcp-sequence", .has_arg = 0, .flag = 0, .val = '1' },
- { .name = "log-tcp-options", .has_arg = 0, .flag = 0, .val = '2' },
- { .name = "log-ip-options", .has_arg = 0, .flag = 0, .val = '3' },
- { .name = "log-uid", .has_arg = 0, .flag = 0, .val = '4' },
- { .name = 0 }
+static const struct option LOG_opts[] = {
+ { .name = "log-level", .has_arg = 1, .val = '!' },
+ { .name = "log-prefix", .has_arg = 1, .val = '#' },
+ { .name = "log-tcp-sequence", .has_arg = 0, .val = '1' },
+ { .name = "log-tcp-options", .has_arg = 0, .val = '2' },
+ { .name = "log-ip-options", .has_arg = 0, .val = '3' },
+ { .name = "log-uid", .has_arg = 0, .val = '4' },
+ { .name = NULL }
};
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void LOG_init(struct xt_entry_target *t)
{
struct ipt_log_info *loginfo = (struct ipt_log_info *)t->data;
@@ -57,7 +51,7 @@ struct ipt_log_names {
unsigned int level;
};
-static struct ipt_log_names ipt_log_names[]
+static const struct ipt_log_names ipt_log_names[]
= { { .name = "alert", .level = LOG_ALERT },
{ .name = "crit", .level = LOG_CRIT },
{ .name = "debug", .level = LOG_DEBUG },
@@ -75,28 +69,25 @@ parse_level(const char *level)
unsigned int lev = -1;
unsigned int set = 0;
- if (string_to_number(level, 0, 7, &lev) == -1) {
+ if (!xtables_strtoui(level, NULL, &lev, 0, 7)) {
unsigned int i = 0;
- for (i = 0;
- i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
if (strncasecmp(level, ipt_log_names[i].name,
strlen(level)) == 0) {
if (set++)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"log-level `%s' ambiguous",
level);
lev = ipt_log_names[i].level;
}
- }
if (!set)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"log-level `%s' unknown", level);
}
- return (u_int8_t)lev;
+ return lev;
}
#define IPT_LOG_OPT_LEVEL 0x01
@@ -106,23 +97,19 @@ parse_level(const char *level)
#define IPT_LOG_OPT_IPOPT 0x10
#define IPT_LOG_OPT_UID 0x20
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int LOG_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_log_info *loginfo = (struct ipt_log_info *)(*target)->data;
switch (c) {
case '!':
if (*flags & IPT_LOG_OPT_LEVEL)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-level twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-level");
loginfo->level = parse_level(optarg);
@@ -131,24 +118,24 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '#':
if (*flags & IPT_LOG_OPT_PREFIX)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-prefix twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --log-prefix");
if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Maximum prefix length %u for --log-prefix",
(unsigned int)sizeof(loginfo->prefix) - 1);
if (strlen(optarg) == 0)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"No prefix specified for --log-prefix");
if (strlen(optarg) != strlen(strtok(optarg, "\n")))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --log-prefix");
strcpy(loginfo->prefix, optarg);
@@ -157,7 +144,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '1':
if (*flags & IPT_LOG_OPT_TCPSEQ)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-tcp-sequence "
"twice");
@@ -167,7 +154,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '2':
if (*flags & IPT_LOG_OPT_TCPOPT)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-tcp-options twice");
loginfo->logflags |= IPT_LOG_TCPOPT;
@@ -176,7 +163,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (*flags & IPT_LOG_OPT_IPOPT)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-ip-options twice");
loginfo->logflags |= IPT_LOG_IPOPT;
@@ -185,7 +172,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '4':
if (*flags & IPT_LOG_OPT_UID)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --log-uid twice");
loginfo->logflags |= IPT_LOG_UID;
@@ -199,16 +186,8 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void LOG_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ipt_log_info *loginfo
= (const struct ipt_log_info *)target->data;
@@ -219,15 +198,12 @@ print(const struct ipt_ip *ip,
printf("flags %u level %u ",
loginfo->logflags, loginfo->level);
else {
- for (i = 0;
- i < sizeof(ipt_log_names) / sizeof(struct ipt_log_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(ipt_log_names); ++i)
if (loginfo->level == ipt_log_names[i].level) {
printf("level %s ", ipt_log_names[i].name);
break;
}
- }
- if (i == sizeof(ipt_log_names) / sizeof(struct ipt_log_names))
+ if (i == ARRAY_SIZE(ipt_log_names))
printf("UNKNOWN level %u ", loginfo->level);
if (loginfo->logflags & IPT_LOG_TCPSEQ)
printf("tcp-sequence ");
@@ -245,15 +221,15 @@ print(const struct ipt_ip *ip,
printf("prefix `%s' ", loginfo->prefix);
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void LOG_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_log_info *loginfo
= (const struct ipt_log_info *)target->data;
- if (strcmp(loginfo->prefix, "") != 0)
- printf("--log-prefix \"%s\" ", loginfo->prefix);
+ if (strcmp(loginfo->prefix, "") != 0) {
+ printf("--log-prefix ");
+ xtables_save_string(loginfo->prefix);
+ }
if (loginfo->level != LOG_DEFAULT_LEVEL)
printf("--log-level %d ", loginfo->level);
@@ -268,23 +244,21 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
printf("--log-uid ");
}
-static
-struct iptables_target log
-= {
+static struct xtables_target log_tg_reg = {
.name = "LOG",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_log_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_log_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_log_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_log_info)),
+ .help = LOG_help,
+ .init = LOG_init,
+ .parse = LOG_parse,
+ .print = LOG_print,
+ .save = LOG_save,
+ .extra_opts = LOG_opts,
};
-void ipt_LOG_init(void)
+void libipt_LOG_init(void)
{
- register_target(&log);
+ xtables_register_target(&log_tg_reg);
}
diff --git a/extensions/libipt_LOG.man b/extensions/libipt_LOG.man
index 597ba3f..47c35e0 100644
--- a/extensions/libipt_LOG.man
+++ b/extensions/libipt_LOG.man
@@ -10,22 +10,22 @@ the next rule. So if you want to LOG the packets you refuse, use two
separate rules with the same matching criteria, first using target LOG
then DROP (or REJECT).
.TP
-.BI "--log-level " "level"
+\fB\-\-log\-level\fP \fIlevel\fP
Level of logging (numeric or see \fIsyslog.conf\fP(5)).
.TP
-.BI "--log-prefix " "prefix"
+\fB\-\-log\-prefix\fP \fIprefix\fP
Prefix log messages with the specified prefix; up to 29 letters long,
and useful for distinguishing messages in the logs.
.TP
-.B --log-tcp-sequence
+\fB\-\-log\-tcp\-sequence\fP
Log TCP sequence numbers. This is a security risk if the log is
readable by users.
.TP
-.B --log-tcp-options
+\fB\-\-log\-tcp\-options\fP
Log options from the TCP packet header.
.TP
-.B --log-ip-options
+\fB\-\-log\-ip\-options\fP
Log options from the IP packet header.
.TP
-.B --log-uid
+\fB\-\-log\-uid\fP
Log the userid of the process which generated the packet.
diff --git a/extensions/libipt_MARK.c b/extensions/libipt_MARK.c
deleted file mode 100644
index ca2fe58..0000000
--- a/extensions/libipt_MARK.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* Shared library add-on to iptables to add MARK target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_MARK.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MARK target v%s options:\n"
-" --set-mark value Set nfmark value\n"
-" --and-mark value Binary AND the nfmark with value\n"
-" --or-mark value Binary OR the nfmark with value\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "set-mark", 1, 0, '1' },
- { "and-mark", 1, 0, '2' },
- { "or-mark", 1, 0, '3' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse_v0(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_mark_target_info *markinfo
- = (struct ipt_mark_target_info *)(*target)->data;
-
- switch (c) {
- case '1':
-#ifdef KERNEL_64_USERSPACE_32
- if (string_to_number_ll(optarg, 0, 0,
- &markinfo->mark))
-#else
- if (string_to_number_l(optarg, 0, 0,
- &markinfo->mark))
-#endif
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK target: Can't specify --set-mark twice");
- *flags = 1;
- break;
- case '2':
- exit_error(PARAMETER_PROBLEM,
- "MARK target: kernel too old for --and-mark");
- case '3':
- exit_error(PARAMETER_PROBLEM,
- "MARK target: kernel too old for --or-mark");
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK target: Parameter --set/and/or-mark"
- " is required");
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse_v1(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_mark_target_info_v1 *markinfo
- = (struct ipt_mark_target_info_v1 *)(*target)->data;
-
- switch (c) {
- case '1':
- markinfo->mode = IPT_MARK_SET;
- break;
- case '2':
- markinfo->mode = IPT_MARK_AND;
- break;
- case '3':
- markinfo->mode = IPT_MARK_OR;
- break;
- default:
- return 0;
- }
-
-#ifdef KERNEL_64_USERSPACE_32
- if (string_to_number_ll(optarg, 0, 0, &markinfo->mark))
-#else
- if (string_to_number_l(optarg, 0, 0, &markinfo->mark))
-#endif
- exit_error(PARAMETER_PROBLEM, "Bad MARK value `%s'", optarg);
-
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "MARK target: Can't specify --set-mark twice");
-
- *flags = 1;
- return 1;
-}
-
-#ifdef KERNEL_64_USERSPACE_32
-static void
-print_mark(unsigned long long mark)
-{
- printf("0x%llx ", mark);
-}
-#else
-static void
-print_mark(unsigned long mark)
-{
- printf("0x%lx ", mark);
-}
-#endif
-
-/* Prints out the targinfo. */
-static void
-print_v0(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_mark_target_info *markinfo =
- (const struct ipt_mark_target_info *)target->data;
- printf("MARK set ");
- print_mark(markinfo->mark);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save_v0(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_mark_target_info *markinfo =
- (const struct ipt_mark_target_info *)target->data;
-
- printf("--set-mark ");
- print_mark(markinfo->mark);
-}
-
-/* Prints out the targinfo. */
-static void
-print_v1(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_mark_target_info_v1 *markinfo =
- (const struct ipt_mark_target_info_v1 *)target->data;
-
- switch (markinfo->mode) {
- case IPT_MARK_SET:
- printf("MARK set ");
- break;
- case IPT_MARK_AND:
- printf("MARK and ");
- break;
- case IPT_MARK_OR:
- printf("MARK or ");
- break;
- }
- print_mark(markinfo->mark);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save_v1(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_mark_target_info_v1 *markinfo =
- (const struct ipt_mark_target_info_v1 *)target->data;
-
- switch (markinfo->mode) {
- case IPT_MARK_SET:
- printf("--set-mark ");
- break;
- case IPT_MARK_AND:
- printf("--and-mark ");
- break;
- case IPT_MARK_OR:
- printf("--or-mark ");
- break;
- }
- print_mark(markinfo->mark);
-}
-
-static
-struct iptables_target mark_v0 = {
- .next = NULL,
- .name = "MARK",
- .version = IPTABLES_VERSION,
- .revision = 0,
- .size = IPT_ALIGN(sizeof(struct ipt_mark_target_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_mark_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse_v0,
- .final_check = &final_check,
- .print = &print_v0,
- .save = &save_v0,
- .extra_opts = opts
-};
-
-static
-struct iptables_target mark_v1 = {
- .next = NULL,
- .name = "MARK",
- .version = IPTABLES_VERSION,
- .revision = 1,
- .size = IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1)),
- .help = &help,
- .init = &init,
- .parse = &parse_v1,
- .final_check = &final_check,
- .print = &print_v1,
- .save = &save_v1,
- .extra_opts = opts
-};
-
-void ipt_MARK_init(void)
-{
- register_target(&mark_v0);
- register_target(&mark_v1);
-}
diff --git a/extensions/libipt_MARK.man b/extensions/libipt_MARK.man
deleted file mode 100644
index 7ddf23e..0000000
--- a/extensions/libipt_MARK.man
+++ /dev/null
@@ -1,13 +0,0 @@
-This is used to set the netfilter mark value associated with the
-packet. It is only valid in the
-.B mangle
-table. It can for example be used in conjunction with iproute2.
-.TP
-.BI "--set-mark " "value"
-Set nfmark value
-.TP
-.BI "--and-mark " "value"
-Binary AND the nfmark with value
-.TP
-.BI "--or-mark " "value"
-Binary OR the nfmark with value
diff --git a/extensions/libipt_MASQUERADE.c b/extensions/libipt_MASQUERADE.c
index f809e78..06586d3 100644
--- a/extensions/libipt_MASQUERADE.c
+++ b/extensions/libipt_MASQUERADE.c
@@ -4,32 +4,30 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
-#include <netinet/in.h>
+#include <net/netfilter/nf_nat.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+static void MASQUERADE_help(void)
{
printf(
-"MASQUERADE v%s options:\n"
+"MASQUERADE target options:\n"
" --to-ports <port>[-<port>]\n"
-" Port (range) to map to.\n\n",
-IPTABLES_VERSION);
+" Port (range) to map to.\n"
+" --random\n"
+" Randomize source port.\n");
}
-static struct option opts[] = {
- { "to-ports", 1, 0, '1' },
- { 0 }
+static const struct option MASQUERADE_opts[] = {
+ { "to-ports", 1, NULL, '1' },
+ { "random", 0, NULL, '2' },
+ { .name = NULL }
};
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void MASQUERADE_init(struct xt_entry_target *t)
{
- struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *)t->data;
+ struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
@@ -38,7 +36,7 @@ init(struct ipt_entry_target *t, unsigned int *nfcache)
/* Parses ports */
static void
-parse_ports(const char *arg, struct ip_nat_multi_range *mr)
+parse_ports(const char *arg, struct nf_nat_multi_range *mr)
{
const char *dash;
int port;
@@ -47,7 +45,7 @@ parse_ports(const char *arg, struct ip_nat_multi_range *mr)
port = atoi(arg);
if (port <= 0 || port > 65535)
- exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", arg);
+ xtables_error(PARAMETER_PROBLEM, "Port \"%s\" not valid\n", arg);
dash = strchr(arg, '-');
if (!dash) {
@@ -59,30 +57,29 @@ parse_ports(const char *arg, struct ip_nat_multi_range *mr)
maxport = atoi(dash + 1);
if (maxport == 0 || maxport > 65535)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", dash+1);
if (maxport < port)
/* People are stupid. Present reader excepted. */
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port range `%s' funky\n", arg);
mr->range[0].min.tcp.port = htons(port);
mr->range[0].max.tcp.port = htons(maxport);
}
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int MASQUERADE_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_target **target)
{
+ const struct ipt_entry *entry = e;
int portok;
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)(*target)->data;
+ struct nf_nat_multi_range *mr
+ = (struct nf_nat_multi_range *)(*target)->data;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
+ || entry->ip.proto == IPPROTO_SCTP
+ || entry->ip.proto == IPPROTO_DCCP
|| entry->ip.proto == IPPROTO_ICMP)
portok = 1;
else
@@ -91,35 +88,31 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
if (!portok)
- exit_error(PARAMETER_PROBLEM,
- "Need TCP or UDP with port specification");
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --to-ports");
parse_ports(optarg, mr);
return 1;
+ case '2':
+ mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ return 1;
+
default:
return 0;
}
}
-/* Final check; don't care. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+MASQUERADE_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)target->data;
- struct ip_nat_range *r = &mr->range[0];
+ const struct nf_nat_multi_range *mr = (const void *)target->data;
+ const struct nf_nat_range *r = &mr->range[0];
if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
printf("masq ports: ");
@@ -128,15 +121,16 @@ print(const struct ipt_ip *ip,
printf("-%hu", ntohs(r->max.tcp.port));
printf(" ");
}
+
+ if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("random ");
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+MASQUERADE_save(const void *ip, const struct xt_entry_target *target)
{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)target->data;
- struct ip_nat_range *r = &mr->range[0];
+ const struct nf_nat_multi_range *mr = (const void *)target->data;
+ const struct nf_nat_range *r = &mr->range[0];
if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
printf("--to-ports %hu", ntohs(r->min.tcp.port));
@@ -144,23 +138,26 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
printf("-%hu", ntohs(r->max.tcp.port));
printf(" ");
}
+
+ if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("--random ");
}
-static struct iptables_target masq = { NULL,
+static struct xtables_target masquerade_tg_reg = {
.name = "MASQUERADE",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .userspacesize = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .help = MASQUERADE_help,
+ .init = MASQUERADE_init,
+ .parse = MASQUERADE_parse,
+ .print = MASQUERADE_print,
+ .save = MASQUERADE_save,
+ .extra_opts = MASQUERADE_opts,
};
-void ipt_MASQUERADE_init(void)
+void libipt_MASQUERADE_init(void)
{
- register_target(&masq);
+ xtables_register_target(&masquerade_tg_reg);
}
diff --git a/extensions/libipt_MASQUERADE.man b/extensions/libipt_MASQUERADE.man
index e82063c..8f42993 100644
--- a/extensions/libipt_MASQUERADE.man
+++ b/extensions/libipt_MASQUERADE.man
@@ -12,11 +12,19 @@ when the interface goes down. This is the correct behavior when the
next dialup is unlikely to have the same interface address (and hence
any established connections are lost anyway). It takes one option:
.TP
-.BR "--to-ports " "\fIport\fP[-\fIport\fP]"
+\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
This specifies a range of source ports to use, overriding the default
.B SNAT
source port-selection heuristics (see above). This is only valid
if the rule also specifies
-.B "-p tcp"
+\fB\-p tcp\fP
or
-.BR "-p udp" .
+\fB\-p udp\fP.
+.TP
+\fB\-\-random\fP
+Randomize source port mapping
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.21).
+.RS
+.PP
diff --git a/extensions/libipt_MIRROR.c b/extensions/libipt_MIRROR.c
index 6988c90..cb0f83c 100644
--- a/extensions/libipt_MIRROR.c
+++ b/extensions/libipt_MIRROR.c
@@ -1,62 +1,15 @@
/* Shared library add-on to iptables to add MIRROR target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
+#include <xtables.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MIRROR target v%s takes no options\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- return 0;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-static struct iptables_target mirror = {
- .next = NULL,
+static struct xtables_target mirror_tg_reg = {
.name = "MIRROR",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(0),
- .userspacesize = IPT_ALIGN(0),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = NULL,
- .save = NULL,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(0),
+ .userspacesize = XT_ALIGN(0),
};
-void ipt_MIRROR_init(void)
+void libipt_MIRROR_init(void)
{
- register_target(&mirror);
+ xtables_register_target(&mirror_tg_reg);
}
diff --git a/extensions/libipt_NETMAP.c b/extensions/libipt_NETMAP.c
index 8e9eaca..af1a474 100644
--- a/extensions/libipt_NETMAP.c
+++ b/extensions/libipt_NETMAP.c
@@ -7,26 +7,22 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
-#include <netinet/in.h>
+#include <xtables.h>
+#include <net/netfilter/nf_nat.h>
#define MODULENAME "NETMAP"
-static struct option opts[] = {
- { "to", 1, 0, '1' },
- { 0 }
+static const struct option NETMAP_opts[] = {
+ { "to", 1, NULL, '1' },
+ { .name = NULL }
};
-/* Function which prints out usage message. */
-static void
-help(void)
+static void NETMAP_help(void)
{
- printf(MODULENAME" v%s options:\n"
+ printf(MODULENAME" target options:\n"
" --%s address[/mask]\n"
" Network address to map to.\n\n",
- IPTABLES_VERSION, opts[0].name);
+ NETMAP_opts[0].name);
}
static u_int32_t
@@ -55,11 +51,9 @@ netmask2bits(u_int32_t netmask)
return bits;
}
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void NETMAP_init(struct xt_entry_target *t)
{
- struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *)t->data;
+ struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
@@ -68,10 +62,10 @@ init(struct ipt_entry_target *t, unsigned int *nfcache)
/* Parses network address */
static void
-parse_to(char *arg, struct ip_nat_range *range)
+parse_to(char *arg, struct nf_nat_range *range)
{
char *slash;
- struct in_addr *ip;
+ const struct in_addr *ip;
u_int32_t netmask;
unsigned int bits;
@@ -80,28 +74,28 @@ parse_to(char *arg, struct ip_nat_range *range)
if (slash)
*slash = '\0';
- ip = dotted_to_addr(arg);
+ ip = xtables_numeric_to_ipaddr(arg);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
range->min_ip = ip->s_addr;
if (slash) {
if (strchr(slash+1, '.')) {
- ip = dotted_to_mask(slash+1);
+ ip = xtables_numeric_to_ipmask(slash+1);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad netmask `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n",
slash+1);
netmask = ip->s_addr;
}
else {
- if (string_to_number(slash+1, 0, 32, &bits) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad netmask `%s'\n",
+ if (!xtables_strtoui(slash+1, NULL, &bits, 0, 32))
+ xtables_error(PARAMETER_PROBLEM, "Bad netmask \"%s\"\n",
slash+1);
netmask = bits2netmask(bits);
}
/* Don't allow /0 (/1 is probably insane, too) */
if (netmask == 0)
- exit_error(PARAMETER_PROBLEM, "Netmask needed\n");
+ xtables_error(PARAMETER_PROBLEM, "Netmask needed\n");
}
else
netmask = ~0;
@@ -109,27 +103,23 @@ parse_to(char *arg, struct ip_nat_range *range)
if (range->min_ip & ~netmask) {
if (slash)
*slash = '/';
- exit_error(PARAMETER_PROBLEM, "Bad network address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n",
arg);
}
range->max_ip = range->min_ip | ~netmask;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int NETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)(*target)->data;
+ struct nf_nat_multi_range *mr
+ = (struct nf_nat_multi_range *)(*target)->data;
switch (c) {
case '1':
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --%s", opts[0].name);
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected `!' after --%s", NETMAP_opts[0].name);
parse_to(optarg, &mr->range[0]);
*flags = 1;
@@ -140,61 +130,53 @@ parse(int c, char **argv, int invert, unsigned int *flags,
}
}
-/* Final check; need --to */
-static void final_check(unsigned int flags)
+static void NETMAP_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
- MODULENAME" needs --%s", opts[0].name);
+ xtables_error(PARAMETER_PROBLEM,
+ MODULENAME" needs --%s", NETMAP_opts[0].name);
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)target->data;
- struct ip_nat_range *r = &mr->range[0];
+ const struct nf_nat_multi_range *mr = (const void *)target->data;
+ const struct nf_nat_range *r = &mr->range[0];
struct in_addr a;
int bits;
a.s_addr = r->min_ip;
- printf("%s", addr_to_dotted(&a));
+ printf("%s", xtables_ipaddr_to_numeric(&a));
a.s_addr = ~(r->min_ip ^ r->max_ip);
bits = netmask2bits(a.s_addr);
if (bits < 0)
- printf("/%s", addr_to_dotted(&a));
+ printf("/%s", xtables_ipaddr_to_numeric(&a));
else
printf("/%d", bits);
}
-/* Saves the targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
{
- printf("--%s ", opts[0].name);
- print(ip, target, 0);
+ printf("--%s ", NETMAP_opts[0].name);
+ NETMAP_print(ip, target, 0);
}
-static struct iptables_target target_module = {
- .next = NULL,
+static struct xtables_target netmap_tg_reg = {
.name = MODULENAME,
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .userspacesize = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .help = NETMAP_help,
+ .init = NETMAP_init,
+ .parse = NETMAP_parse,
+ .final_check = NETMAP_check,
+ .print = NETMAP_print,
+ .save = NETMAP_save,
+ .extra_opts = NETMAP_opts,
};
-void ipt_NETMAP_init(void)
+void libipt_NETMAP_init(void)
{
- register_target(&target_module);
+ xtables_register_target(&netmap_tg_reg);
}
-
diff --git a/extensions/libipt_NETMAP.man b/extensions/libipt_NETMAP.man
index d49a025..a7e90b8 100644
--- a/extensions/libipt_NETMAP.man
+++ b/extensions/libipt_NETMAP.man
@@ -3,7 +3,7 @@ another network of addresses. It can only be used from rules in the
.B nat
table.
.TP
-.BI "--to " "address[/mask]"
+\fB\-\-to\fP \fIaddress\fP[\fB/\fP\fImask\fP]
Network address to map to. The resulting address will be constructed in the
following way: All 'one' bits in the mask are filled in from the new `address'.
All bits that are zero in the mask are filled in from the original address.
diff --git a/extensions/libipt_NFLOG.c b/extensions/libipt_NFLOG.c
deleted file mode 100644
index d054383..0000000
--- a/extensions/libipt_NFLOG.c
+++ /dev/null
@@ -1,161 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
-#include <iptables.h>
-
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter/xt_NFLOG.h>
-
-enum {
- NFLOG_GROUP = 0x1,
- NFLOG_PREFIX = 0x2,
- NFLOG_RANGE = 0x4,
- NFLOG_THRESHOLD = 0x8,
-};
-
-static struct option opts[] = {
- { "nflog-group", 1, 0, NFLOG_GROUP },
- { "nflog-prefix", 1, 0, NFLOG_PREFIX },
- { "nflog-range", 1, 0, NFLOG_RANGE },
- { "nflog-threshold", 1, 0, NFLOG_THRESHOLD },
-};
-
-static void help(void)
-{
- printf("NFLOG v%s options:\n"
- " --nflog-group NUM NETLINK group used for logging\n"
- " --nflog-range NUM Number of byte to copy\n"
- " --nflog-threshold NUM Message threshold of in-kernel queue\n"
- " --nflog-prefix STRING Prefix string for log messages\n\n",
- IPTABLES_VERSION);
-}
-
-static void init(struct xt_entry_target *t, unsigned int *nfcache)
-{
- struct xt_nflog_info *info = (struct xt_nflog_info *)t->data;
-
- info->group = XT_NFLOG_DEFAULT_GROUP;
- info->threshold = XT_NFLOG_DEFAULT_THRESHOLD;
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct xt_entry_target **target)
-{
- struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data;
- int n;
-
- switch (c) {
- case NFLOG_GROUP:
- if (*flags & NFLOG_GROUP)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify --nflog-group twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --nflog-group");
-
- n = atoi(optarg);
- if (n < 1 || n > 32)
- exit_error(PARAMETER_PROBLEM,
- "--nflog-group has to be between 1 and 32");
- info->group = 1 << (n - 1);
- break;
- case NFLOG_PREFIX:
- if (*flags & NFLOG_PREFIX)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify --nflog-prefix twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
- "Unexpected `!' after --nflog-prefix");
-
- n = strlen(optarg);
- if (n == 0)
- exit_error(PARAMETER_PROBLEM,
- "No prefix specified for --nflog-prefix");
- if (n >= sizeof(info->prefix))
- exit_error(PARAMETER_PROBLEM,
- "--nflog-prefix too long, max %Zu characters",
- sizeof(info->prefix) - 1);
- if (n != strlen(strtok(optarg, "\n")))
- exit_error(PARAMETER_PROBLEM,
- "Newlines are not allowed in --nflog-prefix");
- strcpy(info->prefix, optarg);
- break;
- case NFLOG_RANGE:
- if (*flags & NFLOG_RANGE)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify --nflog-range twice");
- n = atoi(optarg);
- if (n < 0)
- exit_error(PARAMETER_PROBLEM,
- "Invalid --nflog-range, must be >= 0");
- info->len = n;
- break;
- case NFLOG_THRESHOLD:
- if (*flags & NFLOG_THRESHOLD)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify --nflog-threshold twice");
- n = atoi(optarg);
- if (n < 1)
- exit_error(PARAMETER_PROBLEM,
- "Invalid --nflog-threshold, must be >= 1");
- info->threshold = n;
- break;
- default:
- return 0;
- }
- *flags |= c;
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- return;
-}
-
-static void nflog_print(const struct xt_nflog_info *info, char *prefix)
-{
- if (info->prefix[0] != '\0')
- printf("%snflog-prefix \"%s\" ", prefix, info->prefix);
- if (info->group != XT_NFLOG_DEFAULT_GROUP)
- printf("%snflog-group %u ", prefix, ffs(info->group));
- if (info->len)
- printf("%snflog-range %u ", prefix, info->len);
- if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
- printf("%snflog-threshold %u ", prefix, info->threshold);
-}
-
-static void print(const struct ipt_ip *ip, const struct xt_entry_target *target,
- int numeric)
-{
- const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
-
- nflog_print(info, "");
-}
-
-static void save(const struct ipt_ip *ip, const struct xt_entry_target *target)
-{
- const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
-
- nflog_print(info, "--");
-}
-
-static struct iptables_target nflog = {
- .name = "NFLOG",
- .version = IPTABLES_VERSION,
- .size = XT_ALIGN(sizeof(struct xt_nflog_info)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_nflog_info)),
- .help = help,
- .init = init,
- .parse = parse,
- .final_check = final_check,
- .print = print,
- .save = save,
- .extra_opts = opts,
-};
-
-void ipt_NFLOG_init(void)
-{
- register_target(&nflog);
-}
diff --git a/extensions/libipt_NFQUEUE.c b/extensions/libipt_NFQUEUE.c
deleted file mode 100644
index c4573ff..0000000
--- a/extensions/libipt_NFQUEUE.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Shared library add-on to iptables for NFQ
- *
- * (C) 2005 by Harald Welte <laforge@netfilter.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_NFQUEUE.h>
-
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void help(void)
-{
- printf(
-"NFQUEUE target options\n"
-" --queue-num value Send packet to QUEUE number <value>.\n"
-" Valid queue numbers are 0-65535\n"
-);
-}
-
-static struct option opts[] = {
- { "queue-num", 1, 0, 'F' },
- { 0 }
-};
-
-static void
-parse_num(const char *s, struct ipt_NFQ_info *tinfo)
-{
- unsigned int num;
-
- if (string_to_number(s, 0, 65535, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "Invalid queue number `%s'\n", s);
-
- tinfo->queuenum = num & 0xffff;
- return;
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_NFQ_info *tinfo
- = (struct ipt_NFQ_info *)(*target)->data;
-
- switch (c) {
- case 'F':
- if (*flags)
- exit_error(PARAMETER_PROBLEM, "NFQUEUE target: "
- "Only use --queue-num ONCE!");
- parse_num(optarg, tinfo);
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_NFQ_info *tinfo =
- (const struct ipt_NFQ_info *)target->data;
- printf("NFQUEUE num %u", tinfo->queuenum);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_NFQ_info *tinfo =
- (const struct ipt_NFQ_info *)target->data;
-
- printf("--queue-num %u ", tinfo->queuenum);
-}
-
-static struct iptables_target nfqueue = {
- .next = NULL,
- .name = "NFQUEUE",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_NFQ_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_NFQ_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_NFQUEUE_init(void)
-{
- register_target(&nfqueue);
-}
diff --git a/extensions/libipt_NFQUEUE.man b/extensions/libipt_NFQUEUE.man
deleted file mode 100644
index c4e9d11..0000000
--- a/extensions/libipt_NFQUEUE.man
+++ /dev/null
@@ -1,12 +0,0 @@
-This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
-you to put a packet into any specific queue, identified by its 16-bit queue
-number.
-.TP
-.BR "--queue-num " "\fIvalue"
-This specifies the QUEUE number to use. Valud queue numbers are 0 to 65535. The default value is 0.
-.TP
-It can only be used with Kernel versions 2.6.14 or later, since it requires
-the
-.B
-nfnetlink_queue
-kernel support.
diff --git a/extensions/libipt_NOTRACK.c b/extensions/libipt_NOTRACK.c
deleted file mode 100644
index f9dfefe..0000000
--- a/extensions/libipt_NOTRACK.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Shared library add-on to iptables to add NOTRACK target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"NOTRACK target v%s takes no options\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- return 0;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-static
-struct iptables_target notrack
-= { .next = NULL,
- .name = "NOTRACK",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(0),
- .userspacesize = IPT_ALIGN(0),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = NULL, /* print */
- .save = NULL, /* save */
- .extra_opts = opts
-};
-
-void ipt_NOTRACK_init(void)
-{
- register_target(&notrack);
-}
diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c
index 7fb46f6..18a2301 100644
--- a/extensions/libipt_REDIRECT.c
+++ b/extensions/libipt_REDIRECT.c
@@ -4,32 +4,31 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
-#include <netinet/in.h>
+#include <net/netfilter/nf_nat.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+#define IPT_REDIRECT_OPT_DEST 0x01
+#define IPT_REDIRECT_OPT_RANDOM 0x02
+
+static void REDIRECT_help(void)
{
printf(
-"REDIRECT v%s options:\n"
+"REDIRECT target options:\n"
" --to-ports <port>[-<port>]\n"
-" Port (range) to map to.\n\n",
-IPTABLES_VERSION);
+" Port (range) to map to.\n");
}
-static struct option opts[] = {
- { "to-ports", 1, 0, '1' },
- { 0 }
+static const struct option REDIRECT_opts[] = {
+ { "to-ports", 1, NULL, '1' },
+ { "random", 0, NULL, '2' },
+ { .name = NULL }
};
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void REDIRECT_init(struct xt_entry_target *t)
{
- struct ip_nat_multi_range *mr = (struct ip_nat_multi_range *)t->data;
+ struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
/* Actually, it's 0, but it's ignored at the moment. */
mr->rangesize = 1;
@@ -38,7 +37,7 @@ init(struct ipt_entry_target *t, unsigned int *nfcache)
/* Parses ports */
static void
-parse_ports(const char *arg, struct ip_nat_multi_range *mr)
+parse_ports(const char *arg, struct nf_nat_multi_range *mr)
{
const char *dash;
int port;
@@ -46,11 +45,14 @@ parse_ports(const char *arg, struct ip_nat_multi_range *mr)
mr->range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
if (strchr(arg, '.'))
- exit_error(PARAMETER_PROBLEM, "IP address not permitted\n");
+ xtables_error(PARAMETER_PROBLEM, "IP address not permitted\n");
port = atoi(arg);
+ if (port == 0)
+ port = xtables_service_to_port(arg, NULL);
+
if (port == 0 || port > 65535)
- exit_error(PARAMETER_PROBLEM, "Port `%s' not valid\n", arg);
+ xtables_error(PARAMETER_PROBLEM, "Port \"%s\" not valid\n", arg);
dash = strchr(arg, '-');
if (!dash) {
@@ -62,30 +64,29 @@ parse_ports(const char *arg, struct ip_nat_multi_range *mr)
maxport = atoi(dash + 1);
if (maxport == 0 || maxport > 65535)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", dash+1);
if (maxport < port)
/* People are stupid. */
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port range `%s' funky\n", arg);
mr->range[0].min.tcp.port = htons(port);
mr->range[0].max.tcp.port = htons(maxport);
}
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int REDIRECT_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_target **target)
{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)(*target)->data;
+ const struct ipt_entry *entry = e;
+ struct nf_nat_multi_range *mr
+ = (struct nf_nat_multi_range *)(*target)->data;
int portok;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
+ || entry->ip.proto == IPPROTO_SCTP
+ || entry->ip.proto == IPPROTO_DCCP
|| entry->ip.proto == IPPROTO_ICMP)
portok = 1;
else
@@ -94,14 +95,25 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
if (!portok)
- exit_error(PARAMETER_PROBLEM,
- "Need TCP or UDP with port specification");
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --to-ports");
parse_ports(optarg, mr);
+ if (*flags & IPT_REDIRECT_OPT_RANDOM)
+ mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ *flags |= IPT_REDIRECT_OPT_DEST;
+ return 1;
+
+ case '2':
+ if (*flags & IPT_REDIRECT_OPT_DEST) {
+ mr->range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ *flags |= IPT_REDIRECT_OPT_RANDOM;
+ } else
+ *flags |= IPT_REDIRECT_OPT_RANDOM;
return 1;
default:
@@ -109,20 +121,11 @@ parse(int c, char **argv, int invert, unsigned int *flags,
}
}
-/* Final check; don't care. */
-static void final_check(unsigned int flags)
+static void REDIRECT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)target->data;
- struct ip_nat_range *r = &mr->range[0];
+ const struct nf_nat_multi_range *mr = (const void *)target->data;
+ const struct nf_nat_range *r = &mr->range[0];
if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
printf("redir ports ");
@@ -130,16 +133,15 @@ print(const struct ipt_ip *ip,
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
printf(" ");
+ if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("random ");
}
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void REDIRECT_save(const void *ip, const struct xt_entry_target *target)
{
- struct ip_nat_multi_range *mr
- = (struct ip_nat_multi_range *)target->data;
- struct ip_nat_range *r = &mr->range[0];
+ const struct nf_nat_multi_range *mr = (const void *)target->data;
+ const struct nf_nat_range *r = &mr->range[0];
if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
printf("--to-ports ");
@@ -147,25 +149,26 @@ save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
if (r->max.tcp.port != r->min.tcp.port)
printf("-%hu", ntohs(r->max.tcp.port));
printf(" ");
+ if (mr->range[0].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("--random ");
}
}
-static struct iptables_target redir = {
- .next = NULL,
+static struct xtables_target redirect_tg_reg = {
.name = "REDIRECT",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .userspacesize = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .help = REDIRECT_help,
+ .init = REDIRECT_init,
+ .parse = REDIRECT_parse,
+ .print = REDIRECT_print,
+ .save = REDIRECT_save,
+ .extra_opts = REDIRECT_opts,
};
-void ipt_REDIRECT_init(void)
+void libipt_REDIRECT_init(void)
{
- register_target(&redir);
+ xtables_register_target(&redirect_tg_reg);
}
diff --git a/extensions/libipt_REDIRECT.man b/extensions/libipt_REDIRECT.man
index aeca3cb..90ab19d 100644
--- a/extensions/libipt_REDIRECT.man
+++ b/extensions/libipt_REDIRECT.man
@@ -7,13 +7,19 @@ and
chains, and user-defined chains which are only called from those
chains. It redirects the packet to the machine itself by changing the
destination IP to the primary address of the incoming interface
-(locally-generated packets are mapped to the 127.0.0.1 address). It
-takes one option:
+(locally-generated packets are mapped to the 127.0.0.1 address).
.TP
-.BR "--to-ports " "\fIport\fP[-\fIport\fP]"
+\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
This specifies a destination port or range of ports to use: without
this, the destination port is never altered. This is only valid
if the rule also specifies
-.B "-p tcp"
+\fB\-p tcp\fP
or
-.BR "-p udp" .
+\fB\-p udp\fP.
+.TP
+\fB\-\-random\fP
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.22).
+.RS
+.PP
diff --git a/extensions/libipt_REJECT.c b/extensions/libipt_REJECT.c
index 6564476..8fed8f5 100644
--- a/extensions/libipt_REJECT.c
+++ b/extensions/libipt_REJECT.c
@@ -6,8 +6,7 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_REJECT.h>
#include <linux/version.h>
@@ -51,27 +50,23 @@ static const struct reject_names reject_table[] = {
};
static void
-print_reject_types()
+print_reject_types(void)
{
unsigned int i;
printf("Valid reject types:\n");
- for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i) {
printf(" %-25s\t%s\n", reject_table[i].name, reject_table[i].desc);
printf(" %-25s\talias\n", reject_table[i].alias);
}
printf("\n");
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-
-/* Function which prints out usage message. */
-static void
-help(void)
+static void REJECT_help(void)
{
printf(
-"REJECT options:\n"
+"REJECT target options:\n"
"--reject-with type drop input packet and send back\n"
" a reply packet according to type:\n");
@@ -80,14 +75,12 @@ help(void)
printf("(*) See man page or read the INCOMPATIBILITES file for compatibility issues.\n");
}
-static struct option opts[] = {
- { "reject-with", 1, 0, '1' },
- { 0 }
+static const struct option REJECT_opts[] = {
+ { "reject-with", 1, NULL, '1' },
+ { .name = NULL }
};
-/* Allocate and initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void REJECT_init(struct xt_entry_target *t)
{
struct ipt_reject_info *reject = (struct ipt_reject_info *)t->data;
@@ -96,21 +89,17 @@ init(struct ipt_entry_target *t, unsigned int *nfcache)
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int REJECT_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_reject_info *reject = (struct ipt_reject_info *)(*target)->data;
- unsigned int limit = sizeof(reject_table)/sizeof(struct reject_names);
+ static const unsigned int limit = ARRAY_SIZE(reject_table);
unsigned int i;
switch(c) {
case '1':
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --reject-with");
for (i = 0; i < limit; i++) {
if ((strncasecmp(reject_table[i].name, optarg, strlen(optarg)) == 0)
@@ -124,7 +113,7 @@ parse(int c, char **argv, int invert, unsigned int *flags,
|| strncasecmp("echoreply", optarg, strlen(optarg)) == 0)
fprintf(stderr, "--reject-with echo-reply no longer"
" supported\n");
- exit_error(PARAMETER_PROBLEM, "unknown reject type `%s'",optarg);
+ xtables_error(PARAMETER_PROBLEM, "unknown reject type \"%s\"", optarg);
default:
/* Fall through */
break;
@@ -132,58 +121,47 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 0;
}
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out ipt_reject_info. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void REJECT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ipt_reject_info *reject
= (const struct ipt_reject_info *)target->data;
unsigned int i;
- for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if (reject_table[i].with == reject->with)
break;
- }
printf("reject-with %s ", reject_table[i].name);
}
-/* Saves ipt_reject in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void REJECT_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_reject_info *reject
= (const struct ipt_reject_info *)target->data;
unsigned int i;
- for (i = 0; i < sizeof(reject_table)/sizeof(struct reject_names); i++)
+ for (i = 0; i < ARRAY_SIZE(reject_table); ++i)
if (reject_table[i].with == reject->with)
break;
printf("--reject-with %s ", reject_table[i].name);
}
-static struct iptables_target reject = {
- .next = NULL,
+static struct xtables_target reject_tg_reg = {
.name = "REJECT",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_reject_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_reject_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_reject_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_reject_info)),
+ .help = REJECT_help,
+ .init = REJECT_init,
+ .parse = REJECT_parse,
+ .print = REJECT_print,
+ .save = REJECT_save,
+ .extra_opts = REJECT_opts,
};
-void ipt_REJECT_init(void)
+void libipt_REJECT_init(void)
{
- register_target(&reject);
+ xtables_register_target(&reject_tg_reg);
}
diff --git a/extensions/libipt_REJECT.man b/extensions/libipt_REJECT.man
index 174bf7b..c419a85 100644
--- a/extensions/libipt_REJECT.man
+++ b/extensions/libipt_REJECT.man
@@ -11,24 +11,22 @@ chains, and user-defined chains which are only called from those
chains. The following option controls the nature of the error packet
returned:
.TP
-.BI "--reject-with " "type"
+\fB\-\-reject\-with\fP \fItype\fP
The type given can be
-.nf
-.B " icmp-net-unreachable"
-.B " icmp-host-unreachable"
-.B " icmp-port-unreachable"
-.B " icmp-proto-unreachable"
-.B " icmp-net-prohibited"
-.B " icmp-host-prohibited or"
-.B " icmp-admin-prohibited (*)"
-.fi
-which return the appropriate ICMP error message (\fBport-unreachable\fP is
+\fBicmp\-net\-unreachable\fP,
+\fBicmp\-host\-unreachable\fP,
+\fBicmp\-port\-unreachable\fP,
+\fBicmp\-proto\-unreachable\fP,
+\fBicmp\-net\-prohibited\fP,
+\fBicmp\-host\-prohibited\fP or
+\fBicmp\-admin\-prohibited\fP (*)
+which return the appropriate ICMP error message (\fBport\-unreachable\fP is
the default). The option
-.B tcp-reset
+\fBtcp\-reset\fP
can be used on rules which only match the TCP protocol: this causes a
TCP RST packet to be sent back. This is mainly useful for blocking
.I ident
(113/tcp) probes which frequently occur when sending mail to broken mail
hosts (which won't accept your mail otherwise).
-.TP
-(*) Using icmp-admin-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT
+.PP
+(*) Using icmp\-admin\-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT
diff --git a/extensions/libipt_SAME.c b/extensions/libipt_SAME.c
index d8912f3..9eba42f 100644
--- a/extensions/libipt_SAME.c
+++ b/extensions/libipt_SAME.c
@@ -4,37 +4,34 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <xtables.h>
+#include <net/netfilter/nf_nat.h>
/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_SAME.h"
+#include <linux/netfilter_ipv4/ipt_SAME.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+static void SAME_help(void)
{
printf(
-"SAME v%s options:\n"
+"SAME target options:\n"
" --to <ipaddr>-<ipaddr>\n"
" Addresses to map source to.\n"
" May be specified more than\n"
" once for multiple ranges.\n"
" --nodst\n"
" Don't use destination-ip in\n"
-" source selection\n",
-IPTABLES_VERSION);
+" source selection\n"
+" --random\n"
+" Randomize source port\n");
}
-static struct option opts[] = {
- { "to", 1, 0, '1' },
- { "nodst", 0, 0, '2'},
- { 0 }
+static const struct option SAME_opts[] = {
+ { "to", 1, NULL, '1' },
+ { "nodst", 0, NULL, '2'},
+ { "random", 0, NULL, '3' },
+ { .name = NULL }
};
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void SAME_init(struct xt_entry_target *t)
{
struct ipt_same_info *mr = (struct ipt_same_info *)t->data;
@@ -47,10 +44,10 @@ init(struct ipt_entry_target *t, unsigned int *nfcache)
/* Parses range of IPs */
static void
-parse_to(char *arg, struct ip_nat_range *range)
+parse_to(char *arg, struct nf_nat_range *range)
{
char *dash;
- struct in_addr *ip;
+ const struct in_addr *ip;
range->flags |= IP_NAT_RANGE_MAP_IPS;
dash = strchr(arg, '-');
@@ -58,63 +55,71 @@ parse_to(char *arg, struct ip_nat_range *range)
if (dash)
*dash = '\0';
- ip = dotted_to_addr(arg);
+ ip = xtables_numeric_to_ipaddr(arg);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
range->min_ip = ip->s_addr;
if (dash) {
- ip = dotted_to_addr(dash+1);
+ ip = xtables_numeric_to_ipaddr(dash+1);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
dash+1);
}
range->max_ip = ip->s_addr;
if (dash)
if (range->min_ip > range->max_ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP range `%s-%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n",
arg, dash+1);
}
#define IPT_SAME_OPT_TO 0x01
#define IPT_SAME_OPT_NODST 0x02
+#define IPT_SAME_OPT_RANDOM 0x04
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int SAME_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_same_info *mr
= (struct ipt_same_info *)(*target)->data;
+ unsigned int count;
switch (c) {
case '1':
if (mr->rangesize == IPT_SAME_MAX_RANGE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Too many ranges specified, maximum "
"is %i ranges.\n",
IPT_SAME_MAX_RANGE);
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --to");
parse_to(optarg, &mr->range[mr->rangesize]);
+ /* WTF do we need this for? */
+ if (*flags & IPT_SAME_OPT_RANDOM)
+ mr->range[mr->rangesize].flags
+ |= IP_NAT_RANGE_PROTO_RANDOM;
mr->rangesize++;
*flags |= IPT_SAME_OPT_TO;
break;
case '2':
if (*flags & IPT_SAME_OPT_NODST)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --nodst twice");
mr->info |= IPT_SAME_NODST;
*flags |= IPT_SAME_OPT_NODST;
break;
-
+
+ case '3':
+ *flags |= IPT_SAME_OPT_RANDOM;
+ for (count=0; count < mr->rangesize; count++)
+ mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ break;
+
default:
return 0;
}
@@ -122,87 +127,91 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; need --to. */
-static void final_check(unsigned int flags)
+static void SAME_check(unsigned int flags)
{
if (!(flags & IPT_SAME_OPT_TO))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"SAME needs --to");
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void SAME_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
- int count;
- struct ipt_same_info *mr
- = (struct ipt_same_info *)target->data;
+ unsigned int count;
+ const struct ipt_same_info *mr = (const void *)target->data;
+ int random_selection = 0;
printf("same:");
for (count = 0; count < mr->rangesize; count++) {
- struct ip_nat_range *r = &mr->range[count];
+ const struct nf_nat_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
- printf("%s", addr_to_dotted(&a));
+ printf("%s", xtables_ipaddr_to_numeric(&a));
a.s_addr = r->max_ip;
if (r->min_ip == r->max_ip)
printf(" ");
else
- printf("-%s ", addr_to_dotted(&a));
+ printf("-%s ", xtables_ipaddr_to_numeric(&a));
+ if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ random_selection = 1;
}
if (mr->info & IPT_SAME_NODST)
printf("nodst ");
+
+ if (random_selection)
+ printf("random ");
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void SAME_save(const void *ip, const struct xt_entry_target *target)
{
- int count;
- struct ipt_same_info *mr
- = (struct ipt_same_info *)target->data;
+ unsigned int count;
+ const struct ipt_same_info *mr = (const void *)target->data;
+ int random_selection = 0;
for (count = 0; count < mr->rangesize; count++) {
- struct ip_nat_range *r = &mr->range[count];
+ const struct nf_nat_range *r = &mr->range[count];
struct in_addr a;
a.s_addr = r->min_ip;
- printf("--to %s", addr_to_dotted(&a));
+ printf("--to %s", xtables_ipaddr_to_numeric(&a));
a.s_addr = r->max_ip;
if (r->min_ip == r->max_ip)
printf(" ");
else
- printf("-%s ", addr_to_dotted(&a));
+ printf("-%s ", xtables_ipaddr_to_numeric(&a));
+ if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
+ random_selection = 1;
}
if (mr->info & IPT_SAME_NODST)
printf("--nodst ");
+
+ if (random_selection)
+ printf("--random ");
}
-static struct iptables_target same = {
- .next = NULL,
+static struct xtables_target same_tg_reg = {
.name = "SAME",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_same_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_same_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_same_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_same_info)),
+ .help = SAME_help,
+ .init = SAME_init,
+ .parse = SAME_parse,
+ .final_check = SAME_check,
+ .print = SAME_print,
+ .save = SAME_save,
+ .extra_opts = SAME_opts,
};
-void ipt_SAME_init(void)
+void libipt_SAME_init(void)
{
- register_target(&same);
+ xtables_register_target(&same_tg_reg);
}
diff --git a/extensions/libipt_SAME.man b/extensions/libipt_SAME.man
index 817c200..a99dc73 100644
--- a/extensions/libipt_SAME.man
+++ b/extensions/libipt_SAME.man
@@ -1,11 +1,17 @@
Similar to SNAT/DNAT depending on chain: it takes a range of addresses
-(`--to 1.2.3.4-1.2.3.7') and gives a client the same
+(`\-\-to 1.2.3.4\-1.2.3.7') and gives a client the same
source-/destination-address for each connection.
+.PP
+N.B.: The DNAT target's \fB\-\-persistent\fP option replaced the SAME target.
.TP
-.BI "--to " "<ipaddr>-<ipaddr>"
+\fB\-\-to\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP]
Addresses to map source to. May be specified more than once for
multiple ranges.
.TP
-.B "--nodst"
+\fB\-\-nodst\fP
Don't use the destination-ip in the calculations when selecting the
new source-ip
+.TP
+\fB\-\-random\fP
+Port mapping will be forcibly randomized to avoid attacks based on
+port prediction (kernel >= 2.6.21).
diff --git a/extensions/libipt_SECMARK.c b/extensions/libipt_SECMARK.c
deleted file mode 100644
index c7f0fb2..0000000
--- a/extensions/libipt_SECMARK.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Shared library add-on to iptables to add SECMARK target support.
- *
- * Based on the MARK target.
- *
- * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter/xt_SECMARK.h>
-
-#define PFX "SECMARK target: "
-
-static void help(void)
-{
- printf(
-"SECMARK target v%s options:\n"
-" --selctx value Set the SELinux security context\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "selctx", 1, 0, '1' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
-{ }
-
-/*
- * Function which parses command options; returns true if it
- * ate an option.
- */
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry, struct ipt_entry_target **target)
-{
- struct xt_secmark_target_info *info =
- (struct xt_secmark_target_info*)(*target)->data;
-
- switch (c) {
- case '1':
- if (*flags & SECMARK_MODE_SEL)
- exit_error(PARAMETER_PROBLEM, PFX
- "Can't specify --selctx twice");
- info->mode = SECMARK_MODE_SEL;
-
- if (strlen(optarg) > SECMARK_SELCTX_MAX-1)
- exit_error(PARAMETER_PROBLEM, PFX
- "Maximum length %u exceeded by --selctx"
- " parameter (%zu)",
- SECMARK_SELCTX_MAX-1, strlen(optarg));
-
- strcpy(info->u.sel.selctx, optarg);
- *flags |= SECMARK_MODE_SEL;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, PFX "parameter required");
-}
-
-static void print_secmark(struct xt_secmark_target_info *info)
-{
- switch (info->mode) {
- case SECMARK_MODE_SEL:
- printf("selctx %s ", info->u.sel.selctx);\
- break;
-
- default:
- exit_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
- }
-}
-
-static void print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target, int numeric)
-{
- struct xt_secmark_target_info *info =
- (struct xt_secmark_target_info*)(target)->data;
-
- printf("SECMARK ");
- print_secmark(info);
-}
-
-/* Saves the target info in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- struct xt_secmark_target_info *info =
- (struct xt_secmark_target_info*)target->data;
-
- printf("--");
- print_secmark(info);
-}
-
-static struct iptables_target secmark = {
- .next = NULL,
- .name = "SECMARK",
- .version = IPTABLES_VERSION,
- .revision = 0,
- .size = IPT_ALIGN(sizeof(struct xt_secmark_target_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct xt_secmark_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_SECMARK_init(void)
-{
- register_target(&secmark);
-}
diff --git a/extensions/libipt_SECMARK.man b/extensions/libipt_SECMARK.man
deleted file mode 100644
index f892de9..0000000
--- a/extensions/libipt_SECMARK.man
+++ /dev/null
@@ -1,7 +0,0 @@
-This is used to set the security mark value associated with the
-packet for use by security subsystems such as SELinux. It is only
-valid in the
-.B mangle
-table.
-.TP
-.BI "--selctx " "security_context"
diff --git a/extensions/libipt_SET.c b/extensions/libipt_SET.c
index f483418..4dcb78a 100644
--- a/extensions/libipt_SET.c
+++ b/extensions/libipt_SET.c
@@ -16,33 +16,28 @@
#include <getopt.h>
#include <ctype.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
+#include <xtables.h>
#include <linux/netfilter_ipv4/ip_set.h>
#include <linux/netfilter_ipv4/ipt_set.h>
#include "libipt_set.h"
-/* Function which prints out usage message. */
-static void help(void)
+static void SET_help(void)
{
- printf("SET v%s options:\n"
+ printf("SET target options:\n"
" --add-set name flags\n"
" --del-set name flags\n"
" add/del src/dst IP/port from/to named sets,\n"
" where flags are the comma separated list of\n"
- " 'src' and 'dst'.\n"
- "\n", IPTABLES_VERSION);
+ " 'src' and 'dst' specifications.\n");
}
-static struct option opts[] = {
- {"add-set", 1, 0, '1'},
- {"del-set", 1, 0, '2'},
- {0}
+static const struct option SET_opts[] = {
+ { .name = "add-set", .has_arg = true, .val = '1'},
+ { .name = "del-set", .has_arg = true, .val = '2'},
+ { .name = NULL }
};
-/* Initialize the target. */
-static void init(struct ipt_entry_target *target, unsigned int *nfcache)
+static void SET_init(struct xt_entry_target *target)
{
struct ipt_set_info_target *info =
(struct ipt_set_info_target *) target->data;
@@ -58,35 +53,32 @@ parse_target(char **argv, int invert, unsigned int *flags,
struct ipt_set_info *info, const char *what)
{
if (info->flags[0])
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"--%s can be specified only once", what);
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --%s", what);
if (!argv[optind]
|| argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"--%s requires two args.", what);
- if (strlen(argv[optind-1]) > IP_SET_MAXNAMELEN - 1)
- exit_error(PARAMETER_PROBLEM,
+ if (strlen(optarg) > IP_SET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
"setname `%s' too long, max %d characters.",
- argv[optind-1], IP_SET_MAXNAMELEN - 1);
+ optarg, IP_SET_MAXNAMELEN - 1);
- get_set_byname(argv[optind - 1], info);
+ get_set_byname(optarg, info);
parse_bindings(argv[optind], info);
optind++;
*flags = 1;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry, struct ipt_entry_target **target)
+static int SET_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_set_info_target *myinfo =
(struct ipt_set_info_target *) (*target)->data;
@@ -107,11 +99,10 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; must specify at least one. */
-static void final_check(unsigned int flags)
+static void SET_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"You must specify either `--add-set' or `--del-set'");
}
@@ -135,46 +126,39 @@ print_target(const char *prefix, const struct ipt_set_info *info)
printf(" ");
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target, int numeric)
+static void SET_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
- struct ipt_set_info_target *info =
- (struct ipt_set_info_target *) target->data;
+ const struct ipt_set_info_target *info = (const void *)target->data;
print_target("add-set", &info->add_set);
print_target("del-set", &info->del_set);
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void SET_save(const void *ip, const struct xt_entry_target *target)
{
- struct ipt_set_info_target *info =
- (struct ipt_set_info_target *) target->data;
+ const struct ipt_set_info_target *info = (const void *)target->data;
print_target("--add-set", &info->add_set);
print_target("--del-set", &info->del_set);
}
-static
-struct iptables_target ipt_set_target
-= {
+static struct xtables_target set_tg_reg = {
.name = "SET",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_set_info_target)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_set_info_target)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_set_info_target)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_set_info_target)),
+ .help = SET_help,
+ .init = SET_init,
+ .parse = SET_parse,
+ .final_check = SET_check,
+ .print = SET_print,
+ .save = SET_save,
+ .extra_opts = SET_opts,
};
-void ipt_SET_init(void)
+void libipt_SET_init(void)
{
- register_target(&ipt_set_target);
+ xtables_register_target(&set_tg_reg);
}
diff --git a/extensions/libipt_SET.man b/extensions/libipt_SET.man
index 8f25bea..ea80c2a 100644
--- a/extensions/libipt_SET.man
+++ b/extensions/libipt_SET.man
@@ -1,16 +1,18 @@
This modules adds and/or deletes entries from IP sets which can be defined
by ipset(8).
.TP
-.BR "--add-set " "setname flag[,flag...]"
+\fB\-\-add\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
add the address(es)/port(s) of the packet to the sets
.TP
-.BR "--del-set " "setname flag[,flag...]"
-delete the address(es)/port(s) of the packet from the sets,
+\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
+delete the address(es)/port(s) of the packet from the sets
+.IP
where flags are
.BR "src"
and/or
.BR "dst"
-and there can be no more than six of them.
-.TP
-The bindings to follow must previously be defined in order to use
-multilevel adding/deleting by the SET target.
+specifications and there can be no more than six of them.
+.PP
+Use of -j SET requires that ipset kernel support is provided. As standard
+kernels do not ship this currently, the ipset or Xtables-addons package needs
+to be installed.
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
index 94b85c7..f8a46f4 100644
--- a/extensions/libipt_SNAT.c
+++ b/extensions/libipt_SNAT.c
@@ -4,47 +4,50 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
+#include <xtables.h>
#include <iptables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ip_nat_rule.h>
-#include <netinet/in.h>
+#include <net/netfilter/nf_nat.h>
+
+#define IPT_SNAT_OPT_SOURCE 0x01
+#define IPT_SNAT_OPT_RANDOM 0x02
/* Source NAT data consists of a multi-range, indicating where to map
to. */
struct ipt_natinfo
{
- struct ipt_entry_target t;
- struct ip_nat_multi_range mr;
+ struct xt_entry_target t;
+ struct nf_nat_multi_range mr;
};
-/* Function which prints out usage message. */
-static void
-help(void)
+static void SNAT_help(void)
{
printf(
-"SNAT v%s options:\n"
+"SNAT target options:\n"
" --to-source <ipaddr>[-<ipaddr>][:port-port]\n"
" Address to map source to.\n"
-" (You can use this more than once)\n\n",
-IPTABLES_VERSION);
+"[--random] [--persistent]\n");
}
-static struct option opts[] = {
- { "to-source", 1, 0, '1' },
- { 0 }
+static const struct option SNAT_opts[] = {
+ { "to-source", 1, NULL, '1' },
+ { "random", 0, NULL, '2' },
+ { "persistent", 0, NULL, '3' },
+ { .name = NULL }
};
static struct ipt_natinfo *
-append_range(struct ipt_natinfo *info, const struct ip_nat_range *range)
+append_range(struct ipt_natinfo *info, const struct nf_nat_range *range)
{
unsigned int size;
/* One rangesize already in struct ipt_natinfo */
- size = IPT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
+ size = XT_ALIGN(sizeof(*info) + info->mr.rangesize * sizeof(*range));
info = realloc(info, size);
if (!info)
- exit_error(OTHER_PROBLEM, "Out of memory\n");
+ xtables_error(OTHER_PROBLEM, "Out of memory\n");
info->t.u.target_size = size;
info->mr.range[info->mr.rangesize] = *range;
@@ -54,12 +57,12 @@ append_range(struct ipt_natinfo *info, const struct ip_nat_range *range)
}
/* Ranges expected in network order. */
-static struct ipt_entry_target *
+static struct xt_entry_target *
parse_to(char *arg, int portok, struct ipt_natinfo *info)
{
- struct ip_nat_range range;
+ struct nf_nat_range range;
char *colon, *dash, *error;
- struct in_addr *ip;
+ const struct in_addr *ip;
memset(&range, 0, sizeof(range));
colon = strchr(arg, ':');
@@ -68,19 +71,19 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
int port;
if (!portok)
- exit_error(PARAMETER_PROBLEM,
- "Need TCP or UDP with port specification");
+ xtables_error(PARAMETER_PROBLEM,
+ "Need TCP, UDP, SCTP or DCCP with port specification");
range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon+1);
if (port <= 0 || port > 65535)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", colon+1);
error = strchr(colon+1, ':');
if (error)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid port:port syntax - use dash\n");
dash = strchr(colon, '-');
@@ -93,11 +96,11 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
maxport = atoi(dash + 1);
if (maxport <= 0 || maxport > 65535)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port `%s' not valid\n", dash+1);
if (maxport < port)
/* People are stupid. */
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Port range `%s' funky\n", colon+1);
range.min.tcp.port = htons(port);
range.max.tcp.port = htons(maxport);
@@ -116,15 +119,15 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
if (dash)
*dash = '\0';
- ip = dotted_to_addr(arg);
+ ip = xtables_numeric_to_ipaddr(arg);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
arg);
range.min_ip = ip->s_addr;
if (dash) {
- ip = dotted_to_addr(dash+1);
+ ip = xtables_numeric_to_ipaddr(dash+1);
if (!ip)
- exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
+ xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
dash+1);
range.max_ip = ip->s_addr;
} else
@@ -133,18 +136,17 @@ parse_to(char *arg, int portok, struct ipt_natinfo *info)
return &(append_range(info, &range)->t);
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int SNAT_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_target **target)
{
+ const struct ipt_entry *entry = e;
struct ipt_natinfo *info = (void *)*target;
int portok;
if (entry->ip.proto == IPPROTO_TCP
|| entry->ip.proto == IPPROTO_UDP
+ || entry->ip.proto == IPPROTO_SCTP
+ || entry->ip.proto == IPPROTO_DCCP
|| entry->ip.proto == IPPROTO_ICMP)
portok = 1;
else
@@ -152,19 +154,34 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --to-source");
- if (*flags) {
+ if (*flags & IPT_SNAT_OPT_SOURCE) {
if (!kernel_version)
get_kernel_version();
if (kernel_version > LINUX_VERSION(2, 6, 10))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Multiple --to-source not supported");
}
*target = parse_to(optarg, portok, info);
- *flags = 1;
+ /* WTF do we need this for?? */
+ if (*flags & IPT_SNAT_OPT_RANDOM)
+ info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ *flags |= IPT_SNAT_OPT_SOURCE;
+ return 1;
+
+ case '2':
+ if (*flags & IPT_SNAT_OPT_SOURCE) {
+ info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+ *flags |= IPT_SNAT_OPT_RANDOM;
+ } else
+ *flags |= IPT_SNAT_OPT_RANDOM;
+ return 1;
+
+ case '3':
+ info->mr.range[0].flags |= IP_NAT_RANGE_PERSISTENT;
return 1;
default:
@@ -172,24 +189,23 @@ parse(int c, char **argv, int invert, unsigned int *flags,
}
}
-/* Final check; must have specfied --to-source. */
-static void final_check(unsigned int flags)
+static void SNAT_check(unsigned int flags)
{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ if (!(flags & IPT_SNAT_OPT_SOURCE))
+ xtables_error(PARAMETER_PROBLEM,
"You must specify --to-source");
}
-static void print_range(const struct ip_nat_range *r)
+static void print_range(const struct nf_nat_range *r)
{
if (r->flags & IP_NAT_RANGE_MAP_IPS) {
struct in_addr a;
a.s_addr = r->min_ip;
- printf("%s", addr_to_dotted(&a));
+ printf("%s", xtables_ipaddr_to_numeric(&a));
if (r->max_ip != r->min_ip) {
a.s_addr = r->max_ip;
- printf("-%s", addr_to_dotted(&a));
+ printf("-%s", xtables_ipaddr_to_numeric(&a));
}
}
if (r->flags & IP_NAT_RANGE_PROTO_SPECIFIED) {
@@ -200,51 +216,54 @@ static void print_range(const struct ip_nat_range *r)
}
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
+static void SNAT_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
- struct ipt_natinfo *info = (void *)target;
+ const struct ipt_natinfo *info = (const void *)target;
unsigned int i = 0;
printf("to:");
for (i = 0; i < info->mr.rangesize; i++) {
print_range(&info->mr.range[i]);
printf(" ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("random ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ printf("persistent ");
}
}
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
+static void SNAT_save(const void *ip, const struct xt_entry_target *target)
{
- struct ipt_natinfo *info = (void *)target;
+ const struct ipt_natinfo *info = (const void *)target;
unsigned int i = 0;
for (i = 0; i < info->mr.rangesize; i++) {
printf("--to-source ");
print_range(&info->mr.range[i]);
printf(" ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PROTO_RANDOM)
+ printf("--random ");
+ if (info->mr.range[i].flags & IP_NAT_RANGE_PERSISTENT)
+ printf("--persistent ");
}
}
-static struct iptables_target snat = {
- .next = NULL,
+static struct xtables_target snat_tg_reg = {
.name = "SNAT",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .userspacesize = IPT_ALIGN(sizeof(struct ip_nat_multi_range)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .userspacesize = XT_ALIGN(sizeof(struct nf_nat_multi_range)),
+ .help = SNAT_help,
+ .parse = SNAT_parse,
+ .final_check = SNAT_check,
+ .print = SNAT_print,
+ .save = SNAT_save,
+ .extra_opts = SNAT_opts,
};
-void ipt_SNAT_init(void)
+void libipt_SNAT_init(void)
{
- register_target(&snat);
+ xtables_register_target(&snat_tg_reg);
}
diff --git a/extensions/libipt_SNAT.man b/extensions/libipt_SNAT.man
index 2d9427f..6b828fd 100644
--- a/extensions/libipt_SNAT.man
+++ b/extensions/libipt_SNAT.man
@@ -7,22 +7,31 @@ modified (and all future packets in this connection will also be
mangled), and rules should cease being examined. It takes one type
of option:
.TP
-.BR "--to-source " "\fIipaddr\fP[-\fIipaddr\fP][:\fIport\fP-\fIport\fP]"
+\fB\-\-to\-source\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
which can specify a single new source IP address, an inclusive range
of IP addresses, and optionally, a port range (which is only valid if
the rule also specifies
-.B "-p tcp"
+\fB\-p tcp\fP
or
-.BR "-p udp" ).
+\fB\-p udp\fP).
If no port range is specified, then source ports below 512 will be
mapped to other ports below 512: those between 512 and 1023 inclusive
will be mapped to ports below 1024, and other ports will be mapped to
-1024 or above. Where possible, no port alteration will occur.
-.RS
-.PP
-In Kernels up to 2.6.10, you can add several --to-source options. For those
+1024 or above. Where possible, no port alteration will
+
+In Kernels up to 2.6.10, you can add several \-\-to\-source options. For those
kernels, if you specify more than one source address, either via an address
-range or multiple --to-source options, a simple round-robin (one after another
+range or multiple \-\-to\-source options, a simple round-robin (one after another
in cycle) takes place between these addresses.
Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
anymore.
+.TP
+\fB\-\-random\fP
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.21).
+.TP
+\fB\-\-persistent\fP
+Gives a client the same source-/destination-address for each connection.
+This supersedes the SAME target. Support for persistent mappings is available
+from 2.6.29-rc2.
diff --git a/extensions/libipt_TCPMSS.c b/extensions/libipt_TCPMSS.c
deleted file mode 100644
index bf9af58..0000000
--- a/extensions/libipt_TCPMSS.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Shared library add-on to iptables to add TCPMSS target support.
- *
- * Copyright (c) 2000 Marc Boucher
-*/
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_TCPMSS.h>
-
-struct mssinfo {
- struct ipt_entry_target t;
- struct ipt_tcpmss_info mss;
-};
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"TCPMSS target v%s mutually-exclusive options:\n"
-" --set-mss value explicitly set MSS option to specified value\n"
-" --clamp-mss-to-pmtu automatically clamp MSS value to (path_MTU - 40)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "set-mss", 1, 0, '1' },
- { "clamp-mss-to-pmtu", 0, 0, '2' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_tcpmss_info *mssinfo
- = (struct ipt_tcpmss_info *)(*target)->data;
-
- switch (c) {
- unsigned int mssval;
-
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "TCPMSS target: Only one option may be specified");
- if (string_to_number(optarg, 0, 65535 - 40, &mssval) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad TCPMSS value `%s'", optarg);
-
- mssinfo->mss = mssval;
- *flags = 1;
- break;
-
- case '2':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "TCPMSS target: Only one option may be specified");
- mssinfo->mss = IPT_TCPMSS_CLAMP_PMTU;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "TCPMSS target: At least one parameter is required");
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_tcpmss_info *mssinfo =
- (const struct ipt_tcpmss_info *)target->data;
- if(mssinfo->mss == IPT_TCPMSS_CLAMP_PMTU)
- printf("TCPMSS clamp to PMTU ");
- else
- printf("TCPMSS set %u ", mssinfo->mss);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_tcpmss_info *mssinfo =
- (const struct ipt_tcpmss_info *)target->data;
-
- if(mssinfo->mss == IPT_TCPMSS_CLAMP_PMTU)
- printf("--clamp-mss-to-pmtu ");
- else
- printf("--set-mss %u ", mssinfo->mss);
-}
-
-static struct iptables_target mss = {
- .next = NULL,
- .name = "TCPMSS",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tcpmss_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tcpmss_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_TCPMSS_init(void)
-{
- register_target(&mss);
-}
diff --git a/extensions/libipt_TCPMSS.man b/extensions/libipt_TCPMSS.man
deleted file mode 100644
index 30668b0..0000000
--- a/extensions/libipt_TCPMSS.man
+++ /dev/null
@@ -1,41 +0,0 @@
-This target allows to alter the MSS value of TCP SYN packets, to control
-the maximum size for that connection (usually limiting it to your
-outgoing interface's MTU minus 40). Of course, it can only be used
-in conjunction with
-.BR "-p tcp" .
-It is only valid in the
-.BR mangle
-table.
-.br
-This target is used to overcome criminally braindead ISPs or servers
-which block ICMP Fragmentation Needed packets. The symptoms of this
-problem are that everything works fine from your Linux
-firewall/router, but machines behind it can never exchange large
-packets:
-.PD 0
-.RS 0.1i
-.TP 0.3i
-1)
-Web browsers connect, then hang with no data received.
-.TP
-2)
-Small mail works fine, but large emails hang.
-.TP
-3)
-ssh works fine, but scp hangs after initial handshaking.
-.RE
-.PD
-Workaround: activate this option and add a rule to your firewall
-configuration like:
-.nf
- iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN \\
- -j TCPMSS --clamp-mss-to-pmtu
-.fi
-.TP
-.BI "--set-mss " "value"
-Explicitly set MSS option to specified value.
-.TP
-.B "--clamp-mss-to-pmtu"
-Automatically clamp MSS value to (path_MTU - 40).
-.TP
-These options are mutually exclusive.
diff --git a/extensions/libipt_TOS.c b/extensions/libipt_TOS.c
deleted file mode 100644
index 1acd995..0000000
--- a/extensions/libipt_TOS.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Shared library add-on to iptables to add TOS target support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_TOS.h>
-
-struct tosinfo {
- struct ipt_entry_target t;
- struct ipt_tos_target_info tos;
-};
-
-/* TOS names and values. */
-static
-struct TOS_value
-{
- unsigned char TOS;
- const char *name;
-} TOS_values[] = {
- { IPTOS_LOWDELAY, "Minimize-Delay" },
- { IPTOS_THROUGHPUT, "Maximize-Throughput" },
- { IPTOS_RELIABILITY, "Maximize-Reliability" },
- { IPTOS_MINCOST, "Minimize-Cost" },
- { IPTOS_NORMALSVC, "Normal-Service" },
-};
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- unsigned int i;
-
- printf(
-"TOS target v%s options:\n"
-" --set-tos value Set Type of Service field to one of the\n"
-" following numeric or descriptive values:\n",
-IPTABLES_VERSION);
-
- for (i = 0; i < sizeof(TOS_values)/sizeof(struct TOS_value);i++)
- printf(" %s %u (0x%02x)\n",
- TOS_values[i].name,
- TOS_values[i].TOS,
- TOS_values[i].TOS);
- fputc('\n', stdout);
-}
-
-static struct option opts[] = {
- { "set-tos", 1, 0, '1' },
- { 0 }
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void
-parse_tos(const char *s, struct ipt_tos_target_info *info)
-{
- unsigned int i, tos;
-
- if (string_to_number(s, 0, 255, &tos) != -1) {
- if (tos == IPTOS_LOWDELAY
- || tos == IPTOS_THROUGHPUT
- || tos == IPTOS_RELIABILITY
- || tos == IPTOS_MINCOST
- || tos == IPTOS_NORMALSVC) {
- info->tos = (u_int8_t )tos;
- return;
- }
- } else {
- for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
- if (strcasecmp(s,TOS_values[i].name) == 0) {
- info->tos = TOS_values[i].TOS;
- return;
- }
- }
- exit_error(PARAMETER_PROBLEM, "Bad TOS value `%s'", s);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- struct ipt_tos_target_info *tosinfo
- = (struct ipt_tos_target_info *)(*target)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "TOS target: Cant specify --set-tos twice");
- parse_tos(optarg, tosinfo);
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "TOS target: Parameter --set-tos is required");
-}
-
-static void
-print_tos(u_int8_t tos, int numeric)
-{
- unsigned int i;
-
- if (!numeric) {
- for (i = 0; i<sizeof(TOS_values)/sizeof(struct TOS_value); i++)
- if (TOS_values[i].TOS == tos) {
- printf("%s ", TOS_values[i].name);
- return;
- }
- }
- printf("0x%02x ", tos);
-}
-
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target,
- int numeric)
-{
- const struct ipt_tos_target_info *tosinfo =
- (const struct ipt_tos_target_info *)target->data;
- printf("TOS set ");
- print_tos(tosinfo->tos, numeric);
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
- const struct ipt_tos_target_info *tosinfo =
- (const struct ipt_tos_target_info *)target->data;
-
- printf("--set-tos 0x%02x ", tosinfo->tos);
-}
-
-static struct iptables_target tos = {
- .next = NULL,
- .name = "TOS",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tos_target_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tos_target_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_TOS_init(void)
-{
- register_target(&tos);
-}
diff --git a/extensions/libipt_TOS.man b/extensions/libipt_TOS.man
deleted file mode 100644
index c31b068..0000000
--- a/extensions/libipt_TOS.man
+++ /dev/null
@@ -1,11 +0,0 @@
-This is used to set the 8-bit Type of Service field in the IP header.
-It is only valid in the
-.B mangle
-table.
-.TP
-.BI "--set-tos " "tos"
-You can use a numeric TOS values, or use
-.nf
- iptables -j TOS -h
-.fi
-to see the list of valid TOS names.
diff --git a/extensions/libipt_TTL.c b/extensions/libipt_TTL.c
index beafbe2..27e6ff5 100644
--- a/extensions/libipt_TTL.c
+++ b/extensions/libipt_TTL.c
@@ -1,7 +1,7 @@
/* Shared library add-on to iptables for the TTL target
* (C) 2000 by Harald Welte <laforge@gnumonks.org>
*
- * $Id: libipt_TTL.c 3507 2004-12-28 13:11:59Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=rusty/emailAddress=rusty@netfilter.org $
+ * $Id$
*
* This program is distributed under the terms of GNU GPL
*/
@@ -9,49 +9,42 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_TTL.h>
#define IPT_TTL_USED 1
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-static void help(void)
+static void TTL_help(void)
{
printf(
-"TTL target v%s options\n"
+"TTL target options\n"
" --ttl-set value Set TTL to <value 0-255>\n"
" --ttl-dec value Decrement TTL by <value 1-255>\n"
-" --ttl-inc value Increment TTL by <value 1-255>\n"
-, IPTABLES_VERSION);
+" --ttl-inc value Increment TTL by <value 1-255>\n");
}
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int TTL_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_TTL_info *info = (struct ipt_TTL_info *) (*target)->data;
unsigned int value;
if (*flags & IPT_TTL_USED) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify TTL option twice");
}
if (!optarg)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"TTL: You must specify a value");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"TTL: unexpected `!'");
- if (string_to_number(optarg, 0, 255, &value) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"TTL: Expected value between 0 and 255");
switch (c) {
@@ -62,7 +55,7 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
case '2':
if (value == 0) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"TTL: decreasing by 0?");
}
@@ -71,7 +64,7 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (value == 0) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"TTL: increasing by 0?");
}
@@ -89,15 +82,14 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void final_check(unsigned int flags)
+static void TTL_check(unsigned int flags)
{
if (!(flags & IPT_TTL_USED))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"TTL: You must specify an action");
}
-static void save(const struct ipt_ip *ip,
- const struct ipt_entry_target *target)
+static void TTL_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_TTL_info *info =
(struct ipt_TTL_info *) target->data;
@@ -117,8 +109,8 @@ static void save(const struct ipt_ip *ip,
printf("%u ", info->ttl);
}
-static void print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target, int numeric)
+static void TTL_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ipt_TTL_info *info =
(struct ipt_TTL_info *) target->data;
@@ -138,29 +130,28 @@ static void print(const struct ipt_ip *ip,
printf("%u ", info->ttl);
}
-static struct option opts[] = {
- { "ttl-set", 1, 0, '1' },
- { "ttl-dec", 1, 0, '2' },
- { "ttl-inc", 1, 0, '3' },
- { 0 }
+static const struct option TTL_opts[] = {
+ { "ttl-set", 1, NULL, '1' },
+ { "ttl-dec", 1, NULL, '2' },
+ { "ttl-inc", 1, NULL, '3' },
+ { .name = NULL }
};
-static struct iptables_target TTL = {
- .next = NULL,
+static struct xtables_target ttl_tg_reg = {
.name = "TTL",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_TTL_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_TTL_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_TTL_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_TTL_info)),
+ .help = TTL_help,
+ .parse = TTL_parse,
+ .final_check = TTL_check,
+ .print = TTL_print,
+ .save = TTL_save,
+ .extra_opts = TTL_opts,
};
-void ipt_TTL_init(void)
+void libipt_TTL_init(void)
{
- register_target(&TTL);
+ xtables_register_target(&ttl_tg_reg);
}
diff --git a/extensions/libipt_TTL.man b/extensions/libipt_TTL.man
index 97c46c4..89fc18f 100644
--- a/extensions/libipt_TTL.man
+++ b/extensions/libipt_TTL.man
@@ -1,19 +1,19 @@
This is used to modify the IPv4 TTL header field. The TTL field determines
how many hops (routers) a packet can traverse until it's time to live is
exceeded.
-.TP
+.PP
Setting or incrementing the TTL field can potentially be very dangerous,
so it should be avoided at any cost.
-.TP
+.PP
.B Don't ever set or increment the value on packets that leave your local network!
.B mangle
table.
.TP
-.BI "--ttl-set " "value"
+\fB\-\-ttl\-set\fP \fIvalue\fP
Set the TTL value to `value'.
.TP
-.BI "--ttl-dec " "value"
+\fB\-\-ttl\-dec\fP \fIvalue\fP
Decrement the TTL value `value' times.
.TP
-.BI "--ttl-inc " "value"
+\fB\-\-ttl\-inc\fP \fIvalue\fP
Increment the TTL value `value' times.
diff --git a/extensions/libipt_ULOG.c b/extensions/libipt_ULOG.c
index a8546e0..db6c855 100644
--- a/extensions/libipt_ULOG.c
+++ b/extensions/libipt_ULOG.c
@@ -15,13 +15,12 @@
#include <stdlib.h>
#include <syslog.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <xtables.h>
/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_ULOG.h"
+#include <linux/netfilter_ipv4/ipt_ULOG.h>
-void print_groups(unsigned int gmask)
+static void print_groups(unsigned int gmask)
{
int b;
unsigned int test;
@@ -33,27 +32,24 @@ void print_groups(unsigned int gmask)
}
}
-/* Function which prints out usage message. */
-static void help(void)
+static void ULOG_help(void)
{
- printf("ULOG v%s options:\n"
+ printf("ULOG target options:\n"
" --ulog-nlgroup nlgroup NETLINK group used for logging\n"
" --ulog-cprange size Bytes of each packet to be passed\n"
" --ulog-qthreshold Threshold of in-kernel queue\n"
- " --ulog-prefix prefix Prefix log messages with this prefix.\n\n",
- IPTABLES_VERSION);
+ " --ulog-prefix prefix Prefix log messages with this prefix.\n");
}
-static struct option opts[] = {
- {"ulog-nlgroup", 1, 0, '!'},
- {"ulog-prefix", 1, 0, '#'},
- {"ulog-cprange", 1, 0, 'A'},
- {"ulog-qthreshold", 1, 0, 'B'},
- {0}
+static const struct option ULOG_opts[] = {
+ {"ulog-nlgroup", 1, NULL, '!'},
+ {"ulog-prefix", 1, NULL, '#'},
+ {"ulog-cprange", 1, NULL, 'A'},
+ {"ulog-qthreshold", 1, NULL, 'B'},
+ { .name = NULL }
};
-/* Initialize the target. */
-static void init(struct ipt_entry_target *t, unsigned int *nfcache)
+static void ULOG_init(struct xt_entry_target *t)
{
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data;
@@ -67,11 +63,8 @@ static void init(struct ipt_entry_target *t, unsigned int *nfcache)
#define IPT_LOG_OPT_CPRANGE 0x04
#define IPT_LOG_OPT_QTHRESHOLD 0x08
-/* Function which parses command options; returns true if it
- ate an option */
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
+static int ULOG_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct ipt_ulog_info *loginfo =
(struct ipt_ulog_info *) (*target)->data;
@@ -80,15 +73,15 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '!':
if (*flags & IPT_LOG_OPT_NLGROUP)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --ulog-nlgroup twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --ulog-nlgroup");
group_d = atoi(optarg);
if (group_d > 32 || group_d < 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"--ulog-nlgroup has to be between 1 and 32");
loginfo->nl_group = (1 << (group_d - 1));
@@ -98,24 +91,24 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
case '#':
if (*flags & IPT_LOG_OPT_PREFIX)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --ulog-prefix twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --ulog-prefix");
if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Maximum prefix length %u for --ulog-prefix",
(unsigned int)sizeof(loginfo->prefix) - 1);
if (strlen(optarg) == 0)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"No prefix specified for --ulog-prefix");
if (strlen(optarg) != strlen(strtok(optarg, "\n")))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --ulog-prefix");
strcpy(loginfo->prefix, optarg);
@@ -123,33 +116,25 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
break;
case 'A':
if (*flags & IPT_LOG_OPT_CPRANGE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --ulog-cprange twice");
if (atoi(optarg) < 0)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Negative copy range?");
-#ifdef KERNEL_64_USERSPACE_32
- loginfo->copy_range = (unsigned long long)atoll(optarg);
-#else
loginfo->copy_range = atoi(optarg);
-#endif
*flags |= IPT_LOG_OPT_CPRANGE;
break;
case 'B':
if (*flags & IPT_LOG_OPT_QTHRESHOLD)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --ulog-qthreshold twice");
if (atoi(optarg) < 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Negative or zero queue threshold ?");
if (atoi(optarg) > ULOG_MAX_QLEN)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Maximum queue length exceeded");
-#ifdef KERNEL_64_USERSPACE_32
- loginfo->qthreshold = (unsigned long long)atoll(optarg);
-#else
loginfo->qthreshold = atoi(optarg);
-#endif
*flags |= IPT_LOG_OPT_QTHRESHOLD;
break;
default:
@@ -158,80 +143,56 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Saves the union ipt_targinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip,
- const struct ipt_entry_target *target)
+static void ULOG_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_ulog_info *loginfo
= (const struct ipt_ulog_info *) target->data;
- if (strcmp(loginfo->prefix, "") != 0)
- printf("--ulog-prefix \"%s\" ", loginfo->prefix);
+ if (strcmp(loginfo->prefix, "") != 0) {
+ fputs("--ulog-prefix ", stdout);
+ xtables_save_string(loginfo->prefix);
+ }
if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) {
printf("--ulog-nlgroup ");
print_groups(loginfo->nl_group);
}
-#ifdef KERNEL_64_USERSPACE_32
- if (loginfo->copy_range)
- printf("--ulog-cprange %llu ", loginfo->copy_range);
-
- if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
- printf("--ulog-qthreshold %llu ", loginfo->qthreshold);
-#else
if (loginfo->copy_range)
printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range);
if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD)
printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold);
-#endif
}
-/* Prints out the targinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_target *target, int numeric)
+static void ULOG_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct ipt_ulog_info *loginfo
= (const struct ipt_ulog_info *) target->data;
printf("ULOG ");
-#ifdef KERNEL_64_USERSPACE_32
- printf("copy_range %llu nlgroup ", loginfo->copy_range);
-#else
printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range);
-#endif
print_groups(loginfo->nl_group);
if (strcmp(loginfo->prefix, "") != 0)
printf("prefix `%s' ", loginfo->prefix);
-#ifdef KERNEL_64_USERSPACE_32
- printf("queue_threshold %llu ", loginfo->qthreshold);
-#else
printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold);
-#endif
}
-static struct iptables_target ulog = {
- .next = NULL,
+static struct xtables_target ulog_tg_reg = {
.name = "ULOG",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_ulog_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_ulog_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_ulog_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_ulog_info)),
+ .help = ULOG_help,
+ .init = ULOG_init,
+ .parse = ULOG_parse,
+ .print = ULOG_print,
+ .save = ULOG_save,
+ .extra_opts = ULOG_opts,
};
-void ipt_ULOG_init(void)
+void libipt_ULOG_init(void)
{
- register_target(&ulog);
+ xtables_register_target(&ulog_tg_reg);
}
diff --git a/extensions/libipt_ULOG.man b/extensions/libipt_ULOG.man
index 51aa619..649b6e3 100644
--- a/extensions/libipt_ULOG.man
+++ b/extensions/libipt_ULOG.man
@@ -7,19 +7,19 @@ multicast groups and receive the packets.
Like LOG, this is a "non-terminating target", i.e. rule traversal
continues at the next rule.
.TP
-.BI "--ulog-nlgroup " "nlgroup"
+\fB\-\-ulog\-nlgroup\fP \fInlgroup\fP
This specifies the netlink group (1-32) to which the packet is sent.
Default value is 1.
.TP
-.BI "--ulog-prefix " "prefix"
+\fB\-\-ulog\-prefix\fP \fIprefix\fP
Prefix log messages with the specified prefix; up to 32 characters
long, and useful for distinguishing messages in the logs.
.TP
-.BI "--ulog-cprange " "size"
+\fB\-\-ulog\-cprange\fP \fIsize\fP
Number of bytes to be copied to userspace. A value of 0 always copies
the entire packet, regardless of its size. Default is 0.
.TP
-.BI "--ulog-qthreshold " "size"
+\fB\-\-ulog\-qthreshold\fP \fIsize\fP
Number of packet to queue inside kernel. Setting this value to, e.g. 10
accumulates ten packets inside the kernel and transmits them as one
netlink multipart message to userspace. Default is 1 (for backwards
diff --git a/extensions/libipt_addrtype.c b/extensions/libipt_addrtype.c
index 644e515..40fec0f 100644
--- a/extensions/libipt_addrtype.c
+++ b/extensions/libipt_addrtype.c
@@ -6,13 +6,12 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_addrtype.h>
/* from linux/rtnetlink.h, must match order of enumeration */
-static char *rtn_names[] = {
+static const char *const rtn_names[] = {
"UNSPEC",
"UNICAST",
"LOCAL",
@@ -28,7 +27,7 @@ static char *rtn_names[] = {
NULL
};
-static void help_types(void)
+static void addrtype_help_types(void)
{
int i;
@@ -36,25 +35,37 @@ static void help_types(void)
printf(" %s\n", rtn_names[i]);
}
-static void help(void)
+static void addrtype_help_v0(void)
{
printf(
-"Address type match v%s options:\n"
+"Address type match options:\n"
" [!] --src-type type[,...] Match source address type\n"
" [!] --dst-type type[,...] Match destination address type\n"
"\n"
-"Valid types: \n"
-, IPTABLES_VERSION);
- help_types();
+"Valid types: \n");
+ addrtype_help_types();
+}
+
+static void addrtype_help_v1(void)
+{
+ printf(
+"Address type match options:\n"
+" [!] --src-type type[,...] Match source address type\n"
+" [!] --dst-type type[,...] Match destination address type\n"
+" --limit-iface-in Match only on the packet's incoming device\n"
+" --limit-iface-out Match only on the packet's incoming device\n"
+"\n"
+"Valid types: \n");
+ addrtype_help_types();
}
static int
-parse_type(const char *name, size_t strlen, u_int16_t *mask)
+parse_type(const char *name, size_t len, u_int16_t *mask)
{
int i;
for (i = 0; rtn_names[i]; i++)
- if (strncasecmp(name, rtn_names[i], strlen) == 0) {
+ if (strncasecmp(name, rtn_names[i], len) == 0) {
/* build up bitmask for kernel module */
*mask |= (1 << i);
return 1;
@@ -69,21 +80,23 @@ static void parse_types(const char *arg, u_int16_t *mask)
while ((comma = strchr(arg, ',')) != NULL) {
if (comma == arg || !parse_type(arg, comma-arg, mask))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"addrtype: bad type `%s'", arg);
arg = comma + 1;
}
if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask))
- exit_error(PARAMETER_PROBLEM, "addrtype: bad type `%s'", arg);
+ xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg);
}
#define IPT_ADDRTYPE_OPT_SRCTYPE 0x1
#define IPT_ADDRTYPE_OPT_DSTTYPE 0x2
+#define IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN 0x4
+#define IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT 0x8
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry, unsigned int *nfcache,
- struct ipt_entry_match **match)
+static int
+addrtype_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ipt_addrtype_info *info =
(struct ipt_addrtype_info *) (*match)->data;
@@ -91,20 +104,20 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
if (*flags&IPT_ADDRTYPE_OPT_SRCTYPE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"addrtype: can't specify src-type twice");
- check_inverse(optarg, &invert, &optind, 0);
- parse_types(argv[optind-1], &info->source);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_types(optarg, &info->source);
if (invert)
info->invert_source = 1;
*flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
break;
case '2':
if (*flags&IPT_ADDRTYPE_OPT_DSTTYPE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"addrtype: can't specify dst-type twice");
- check_inverse(optarg, &invert, &optind, 0);
- parse_types(argv[optind-1], &info->dest);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_types(optarg, &info->dest);
if (invert)
info->invert_dest = 1;
*flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
@@ -116,13 +129,74 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void final_check(unsigned int flags)
+static int
+addrtype_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ipt_addrtype_info_v1 *info =
+ (struct ipt_addrtype_info_v1 *) (*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & IPT_ADDRTYPE_OPT_SRCTYPE)
+ xtables_error(PARAMETER_PROBLEM,
+ "addrtype: can't specify src-type twice");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_types(optarg, &info->source);
+ if (invert)
+ info->flags |= IPT_ADDRTYPE_INVERT_SOURCE;
+ *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
+ break;
+ case '2':
+ if (*flags & IPT_ADDRTYPE_OPT_DSTTYPE)
+ xtables_error(PARAMETER_PROBLEM,
+ "addrtype: can't specify dst-type twice");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_types(optarg, &info->dest);
+ if (invert)
+ info->flags |= IPT_ADDRTYPE_INVERT_DEST;
+ *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
+ break;
+ case '3':
+ if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN)
+ xtables_error(PARAMETER_PROBLEM,
+ "addrtype: can't specify limit-iface-in twice");
+ info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN;
+ *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN;
+ break;
+ case '4':
+ if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
+ xtables_error(PARAMETER_PROBLEM,
+ "addrtype: can't specify limit-iface-out twice");
+ info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT;
+ *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void addrtype_check_v0(unsigned int flags)
{
if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"addrtype: you must specify --src-type or --dst-type");
}
+static void addrtype_check_v1(unsigned int flags)
+{
+ if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
+ xtables_error(PARAMETER_PROBLEM,
+ "addrtype: you must specify --src-type or --dst-type");
+ if (flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN &&
+ flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
+ xtables_error(PARAMETER_PROBLEM,
+ "addrtype: you can't specify both --limit-iface-in "
+ "and --limit-iface-out");
+}
+
static void print_types(u_int16_t mask)
{
const char *sep = "";
@@ -137,9 +211,8 @@ static void print_types(u_int16_t mask)
printf(" ");
}
-static void print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
+static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ipt_addrtype_info *info =
(struct ipt_addrtype_info *) match->data;
@@ -159,49 +232,129 @@ static void print(const struct ipt_ip *ip,
}
}
-static void save(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
+static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_addrtype_info_v1 *info =
+ (struct ipt_addrtype_info_v1 *) match->data;
+
+ printf("ADDRTYPE match ");
+ if (info->source) {
+ printf("src-type ");
+ if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
+ printf("!");
+ print_types(info->source);
+ }
+ if (info->dest) {
+ printf("dst-type ");
+ if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
+ printf("!");
+ print_types(info->dest);
+ }
+ if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
+ printf("limit-in ");
+ }
+ if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
+ printf("limit-out ");
+ }
+}
+
+static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match)
{
const struct ipt_addrtype_info *info =
(struct ipt_addrtype_info *) match->data;
if (info->source) {
- printf("--src-type ");
if (info->invert_source)
printf("! ");
+ printf("--src-type ");
print_types(info->source);
}
if (info->dest) {
- printf("--dst-type ");
if (info->invert_dest)
printf("! ");
+ printf("--dst-type ");
+ print_types(info->dest);
+ }
+}
+
+static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ipt_addrtype_info_v1 *info =
+ (struct ipt_addrtype_info_v1 *) match->data;
+
+ if (info->source) {
+ if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
+ printf("! ");
+ printf("--src-type ");
+ print_types(info->source);
+ }
+ if (info->dest) {
+ if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
+ printf("! ");
+ printf("--dst-type ");
print_types(info->dest);
}
+ if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
+ printf("--limit-iface-in ");
+ }
+ if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
+ printf("--limit-iface-out ");
+ }
}
-static struct option opts[] = {
- { "src-type", 1, 0, '1' },
- { "dst-type", 1, 0, '2' },
- { 0 }
+static const struct option addrtype_opts[] = {
+ { "src-type", 1, NULL, '1' },
+ { "dst-type", 1, NULL, '2' },
+ { .name = NULL }
+};
+
+static const struct option addrtype_opts_v0[] = {
+ { "src-type", 1, NULL, '1' },
+ { "dst-type", 1, NULL, '2' },
+ { .name = NULL }
+};
+
+static const struct option addrtype_opts_v1[] = {
+ { "src-type", 1, NULL, '1' },
+ { "dst-type", 1, NULL, '2' },
+ { "limit-iface-in", 0, NULL, '3' },
+ { "limit-iface-out", 0, NULL, '4' },
+ { .name = NULL }
};
-static
-struct iptables_match addrtype = {
- .next = NULL,
- .name = "addrtype",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_addrtype_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_addrtype_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+static struct xtables_match addrtype_mt_reg[] = {
+ {
+ .name = "addrtype",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
+ .help = addrtype_help_v0,
+ .parse = addrtype_parse_v0,
+ .final_check = addrtype_check_v0,
+ .print = addrtype_print_v0,
+ .save = addrtype_save_v0,
+ .extra_opts = addrtype_opts_v0,
+ },
+ {
+ .name = "addrtype",
+ .revision = 1,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
+ .help = addrtype_help_v1,
+ .parse = addrtype_parse_v1,
+ .final_check = addrtype_check_v1,
+ .print = addrtype_print_v1,
+ .save = addrtype_save_v1,
+ .extra_opts = addrtype_opts_v1,
+ },
};
-void ipt_addrtype_init(void)
+void libipt_addrtype_init(void)
{
- register_match(&addrtype);
+ xtables_register_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
}
diff --git a/extensions/libipt_addrtype.man b/extensions/libipt_addrtype.man
index 2c3bbab..16fd9df 100644
--- a/extensions/libipt_addrtype.man
+++ b/extensions/libipt_addrtype.man
@@ -2,36 +2,68 @@ This module matches packets based on their
.B address type.
Address types are used within the kernel networking stack and categorize
addresses into various groups. The exact definition of that group depends on the specific layer three protocol.
-.TP
+.PP
The following address types are possible:
.TP
.BI "UNSPEC"
an unspecified address (i.e. 0.0.0.0)
+.TP
.BI "UNICAST"
an unicast address
+.TP
.BI "LOCAL"
a local address
+.TP
.BI "BROADCAST"
a broadcast address
+.TP
.BI "ANYCAST"
an anycast packet
+.TP
.BI "MULTICAST"
a multicast address
+.TP
.BI "BLACKHOLE"
a blackhole address
+.TP
.BI "UNREACHABLE"
an unreachable address
+.TP
.BI "PROHIBIT"
a prohibited address
+.TP
.BI "THROW"
FIXME
+.TP
.BI "NAT"
FIXME
+.TP
.BI "XRESOLVE"
-FIXME
.TP
-.BI "--src-type " "type"
+[\fB!\fP] \fB\-\-src\-type\fP \fItype\fP
Matches if the source address is of given type
.TP
-.BI "--dst-type " "type"
+[\fB!\fP] \fB\-\-dst\-type\fP \fItype\fP
Matches if the destination address is of given type
+.TP
+.BI "\-\-limit\-iface\-in"
+The address type checking can be limited to the interface the packet is coming
+in. This option is only valid in the
+.BR PREROUTING ,
+.B INPUT
+and
+.B FORWARD
+chains. It cannot be specified with the
+\fB\-\-limit\-iface\-out\fP
+option.
+.TP
+\fB\-\-limit\-iface\-out\fP
+The address type checking can be limited to the interface the packet is going
+out. This option is only valid in the
+.BR POSTROUTING ,
+.B OUTPUT
+and
+.B FORWARD
+chains. It cannot be specified with the
+\fB\-\-limit\-iface\-in\fP
+option.
diff --git a/extensions/libipt_ah.c b/extensions/libipt_ah.c
index e04bbe5..6ca13ea 100644
--- a/extensions/libipt_ah.c
+++ b/extensions/libipt_ah.c
@@ -5,23 +5,20 @@
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
-#include <iptables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_ah.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
+
+static void ah_help(void)
{
printf(
-"AH v%s options:\n"
-" --ahspi [!] spi[:spi]\n"
-" match spi (range)\n",
-IPTABLES_VERSION);
+"ah match options:\n"
+"[!] --ahspi spi[:spi]\n"
+" match spi (range)\n");
}
-static struct option opts[] = {
- { "ahspi", 1, 0, '1' },
- {0}
+static const struct option ah_opts[] = {
+ { "ahspi", 1, NULL, '1' },
+ { .name = NULL }
};
static u_int32_t
@@ -33,18 +30,18 @@ parse_ah_spi(const char *spistr)
spi = strtoul(spistr,&ep,0) ;
if ( spistr == ep ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"AH no valid digits in spi `%s'", spistr);
}
if ( spi == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"spi `%s' specified too big: would overflow", spistr);
}
if ( *spistr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"AH error parsing spi `%s'", spistr);
}
- return (u_int32_t) spi;
+ return spi;
}
static void
@@ -66,9 +63,7 @@ parse_ah_spis(const char *spistring, u_int32_t *spis)
free(buffer);
}
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
+static void ah_init(struct xt_entry_match *m)
{
struct ipt_ah *ahinfo = (struct ipt_ah *)m->data;
@@ -77,23 +72,18 @@ init(struct ipt_entry_match *m, unsigned int *nfcache)
#define AH_SPI 0x01
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+static int ah_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ipt_ah *ahinfo = (struct ipt_ah *)(*match)->data;
switch (c) {
case '1':
if (*flags & AH_SPI)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--ahspi' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_ah_spis(argv[optind-1], ahinfo->spis);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_ah_spis(optarg, ahinfo->spis);
if (invert)
ahinfo->invflags |= IPT_AH_INV_SPI;
*flags |= AH_SPI;
@@ -105,12 +95,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
static void
print_spis(const char *name, u_int32_t min, u_int32_t max,
int invert)
@@ -132,10 +116,8 @@ print_spis(const char *name, u_int32_t min, u_int32_t max,
}
}
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match, int numeric)
+static void ah_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ipt_ah *ah = (struct ipt_ah *)match->data;
@@ -147,14 +129,13 @@ print(const struct ipt_ip *ip,
ah->invflags & ~IPT_AH_INV_MASK);
}
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void ah_save(const void *ip, const struct xt_entry_match *match)
{
const struct ipt_ah *ahinfo = (struct ipt_ah *)match->data;
if (!(ahinfo->spis[0] == 0
&& ahinfo->spis[1] == 0xFFFFFFFF)) {
- printf("--ahspi %s",
+ printf("%s--ahspi ",
(ahinfo->invflags & IPT_AH_INV_SPI) ? "! " : "");
if (ahinfo->spis[0]
!= ahinfo->spis[1])
@@ -168,23 +149,21 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
}
-static struct iptables_match ah = {
- .next = NULL,
+static struct xtables_match ah_mt_reg = {
.name = "ah",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_ah)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_ah)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_ah)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_ah)),
+ .help = ah_help,
+ .init = ah_init,
+ .parse = ah_parse,
+ .print = ah_print,
+ .save = ah_save,
+ .extra_opts = ah_opts,
};
-void
-ipt_ah_init(void)
+void libipt_ah_init(void)
{
- register_match(&ah);
+ xtables_register_match(&ah_mt_reg);
}
diff --git a/extensions/libipt_ah.man b/extensions/libipt_ah.man
index 7300c18..d26455e 100644
--- a/extensions/libipt_ah.man
+++ b/extensions/libipt_ah.man
@@ -1,3 +1,3 @@
This module matches the SPIs in Authentication header of IPsec packets.
.TP
-.BR "--ahspi " "[!] \fIspi\fP[:\fIspi\fP]"
+[\fB!\fP] \fB\-\-ahspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
diff --git a/extensions/libipt_comment.c b/extensions/libipt_comment.c
deleted file mode 100644
index 405b7e2..0000000
--- a/extensions/libipt_comment.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Shared library add-on to iptables to add comment match support.
- *
- * ChangeLog
- * 2003-05-13: Brad Fisher <brad@info-link.net>
- * Initial comment match
- * 2004-05-12: Brad Fisher <brad@info-link.net>
- * Port to patch-o-matic-ng
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_comment.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
- "COMMENT match options:\n"
- "--comment COMMENT Attach a comment to a rule\n\n"
- );
-}
-
-static struct option opts[] = {
- { "comment", 1, 0, '1' },
- {0}
-};
-
-static void
-parse_comment(const char *s, struct ipt_comment_info *info)
-{
- int slen = strlen(s);
-
- if (slen >= IPT_MAX_COMMENT_LEN) {
- exit_error(PARAMETER_PROBLEM,
- "COMMENT must be shorter than %i characters", IPT_MAX_COMMENT_LEN);
- }
- strcpy((char *)info->comment, s);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_comment_info *commentinfo = (struct ipt_comment_info *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- if (invert) {
- exit_error(PARAMETER_PROBLEM,
- "Sorry, you can't have an inverted comment");
- }
- parse_comment(argv[optind-1], commentinfo);
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-/* Final check; must have specified --comment. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "COMMENT match: You must specify `--comment'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_comment_info *commentinfo = (struct ipt_comment_info *)match->data;
-
- commentinfo->comment[IPT_MAX_COMMENT_LEN-1] = '\0';
- printf("/* %s */ ", commentinfo->comment);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_comment_info *commentinfo = (struct ipt_comment_info *)match->data;
-
- commentinfo->comment[IPT_MAX_COMMENT_LEN-1] = '\0';
- printf("--comment \"%s\" ", commentinfo->comment);
-}
-
-static struct iptables_match comment = {
- .next = NULL,
- .name = "comment",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_comment_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_comment_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_comment_init(void)
-{
- register_match(&comment);
-}
diff --git a/extensions/libipt_comment.man b/extensions/libipt_comment.man
deleted file mode 100644
index 2f4ce55..0000000
--- a/extensions/libipt_comment.man
+++ /dev/null
@@ -1,6 +0,0 @@
-Allows you to add comments (up to 256 characters) to any rule.
-.TP
-.BI "--comment " "comment"
-.TP
-Example:
-iptables -A INPUT -s 192.168.0.0/16 -m comment --comment "A privatized IP block"
diff --git a/extensions/libipt_condition.c b/extensions/libipt_condition.c
deleted file mode 100644
index e91cb8e..0000000
--- a/extensions/libipt_condition.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Shared library add-on to iptables for condition match */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <iptables.h>
-
-#include<linux/netfilter_ipv4/ip_tables.h>
-#include<linux/netfilter_ipv4/ipt_condition.h>
-
-
-static void
-help(void)
-{
- printf("condition match v%s options:\n"
- "--condition [!] filename "
- "Match on boolean value stored in /proc file\n",
- IPTABLES_VERSION);
-}
-
-
-static struct option opts[] = {
- { .name = "condition", .has_arg = 1, .flag = 0, .val = 'X' },
- { .name = 0 }
-};
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry, unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct condition_info *info =
- (struct condition_info *) (*match)->data;
-
- if (c == 'X') {
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "Can't specify multiple conditions");
-
- check_inverse(optarg, &invert, &optind, 0);
-
- if (strlen(argv[optind - 1]) < CONDITION_NAME_LEN)
- strcpy(info->name, argv[optind - 1]);
- else
- exit_error(PARAMETER_PROBLEM,
- "File name too long");
-
- info->invert = invert;
- *flags = 1;
- return 1;
- }
-
- return 0;
-}
-
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "Condition match: must specify --condition");
-}
-
-
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match, int numeric)
-{
- const struct condition_info *info =
- (const struct condition_info *) match->data;
-
- printf("condition %s%s ", (info->invert) ? "!" : "", info->name);
-}
-
-
-static void
-save(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
-{
- const struct condition_info *info =
- (const struct condition_info *) match->data;
-
- printf("--condition %s\"%s\" ", (info->invert) ? "! " : "", info->name);
-}
-
-
-static struct iptables_match condition = {
- .name = "condition",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct condition_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct condition_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-
-void
-ipt_condition_init(void)
-{
- register_match(&condition);
-}
diff --git a/extensions/libipt_condition.man b/extensions/libipt_condition.man
deleted file mode 100644
index ce2aa95..0000000
--- a/extensions/libipt_condition.man
+++ /dev/null
@@ -1,4 +0,0 @@
-This matches if a specific /proc filename is '0' or '1'.
-.TP
-.BI "--condition " "[!] \fIfilename\fP"
-Match on boolean value stored in /proc/net/ipt_condition/filename file
diff --git a/extensions/libipt_connbytes.c b/extensions/libipt_connbytes.c
deleted file mode 100644
index fec4ce0..0000000
--- a/extensions/libipt_connbytes.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* Shared library add-on to iptables to add byte tracking support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ipt_connbytes.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"connbytes v%s options:\n"
-" [!] --connbytes from:[to]\n"
-" --connbytes-dir [original, reply, both]\n"
-" --connbytes-mode [packets, bytes, avgpkt]\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "connbytes", 1, 0, '1' },
- { "connbytes-dir", 1, 0, '2' },
- { "connbytes-mode", 1, 0, '3' },
- {0}
-};
-
-static void
-parse_range(const char *arg, struct ipt_connbytes_info *si)
-{
- char *colon,*p;
-
- si->count.from = strtoul(arg,&colon,10);
- if (*colon != ':')
- exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
- si->count.to = strtoul(colon+1,&p,10);
- if (p == colon+1) {
- /* second number omited */
- si->count.to = 0xffffffff;
- }
- if (si->count.from > si->count.to)
- exit_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
- si->count.from, si->count.to);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_connbytes_info *sinfo = (struct ipt_connbytes_info *)(*match)->data;
- unsigned long i;
-
- switch (c) {
- case '1':
- if (check_inverse(optarg, &invert, &optind, 0))
- optind++;
-
- parse_range(argv[optind-1], sinfo);
- if (invert) {
- i = sinfo->count.from;
- sinfo->count.from = sinfo->count.to;
- sinfo->count.to = i;
- }
- *flags |= 1;
- break;
- case '2':
- if (!strcmp(optarg, "original"))
- sinfo->direction = IPT_CONNBYTES_DIR_ORIGINAL;
- else if (!strcmp(optarg, "reply"))
- sinfo->direction = IPT_CONNBYTES_DIR_REPLY;
- else if (!strcmp(optarg, "both"))
- sinfo->direction = IPT_CONNBYTES_DIR_BOTH;
- else
- exit_error(PARAMETER_PROBLEM,
- "Unknown --connbytes-dir `%s'", optarg);
-
- *flags |= 2;
- break;
- case '3':
- if (!strcmp(optarg, "packets"))
- sinfo->what = IPT_CONNBYTES_PKTS;
- else if (!strcmp(optarg, "bytes"))
- sinfo->what = IPT_CONNBYTES_BYTES;
- else if (!strcmp(optarg, "avgpkt"))
- sinfo->what = IPT_CONNBYTES_AVGPKT;
- else
- exit_error(PARAMETER_PROBLEM,
- "Unknown --connbytes-mode `%s'", optarg);
- *flags |= 4;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (flags != 7)
- exit_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
- "`--connbytes-dir' and `--connbytes-mode'");
-}
-
-static void print_mode(struct ipt_connbytes_info *sinfo)
-{
- switch (sinfo->what) {
- case IPT_CONNBYTES_PKTS:
- fputs("packets ", stdout);
- break;
- case IPT_CONNBYTES_BYTES:
- fputs("bytes ", stdout);
- break;
- case IPT_CONNBYTES_AVGPKT:
- fputs("avgpkt ", stdout);
- break;
- default:
- fputs("unknown ", stdout);
- break;
- }
-}
-
-static void print_direction(struct ipt_connbytes_info *sinfo)
-{
- switch (sinfo->direction) {
- case IPT_CONNBYTES_DIR_ORIGINAL:
- fputs("original ", stdout);
- break;
- case IPT_CONNBYTES_DIR_REPLY:
- fputs("reply ", stdout);
- break;
- case IPT_CONNBYTES_DIR_BOTH:
- fputs("both ", stdout);
- break;
- default:
- fputs("unknown ", stdout);
- break;
- }
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_connbytes_info *sinfo = (struct ipt_connbytes_info *)match->data;
-
- if (sinfo->count.from > sinfo->count.to)
- printf("connbytes ! %llu:%llu ", sinfo->count.to,
- sinfo->count.from);
- else
- printf("connbytes %llu:%llu ",sinfo->count.from,
- sinfo->count.to);
-
- fputs("connbytes mode ", stdout);
- print_mode(sinfo);
-
- fputs("connbytes direction ", stdout);
- print_direction(sinfo);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_connbytes_info *sinfo = (struct ipt_connbytes_info *)match->data;
-
- if (sinfo->count.from > sinfo->count.to)
- printf("! --connbytes %llu:%llu ", sinfo->count.to,
- sinfo->count.from);
- else
- printf("--connbytes %llu:%llu ", sinfo->count.from,
- sinfo->count.to);
-
- fputs("--connbytes-mode ", stdout);
- print_mode(sinfo);
-
- fputs("--connbytes-dir ", stdout);
- print_direction(sinfo);
-}
-
-static struct iptables_match state = {
- .next = NULL,
- .name = "connbytes",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_connbytes_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_connbytes_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_connbytes_init(void)
-{
- register_match(&state);
-}
diff --git a/extensions/libipt_connbytes.man b/extensions/libipt_connbytes.man
deleted file mode 100644
index ce7b665..0000000
--- a/extensions/libipt_connbytes.man
+++ /dev/null
@@ -1,30 +0,0 @@
-Match by how many bytes or packets a connection (or one of the two
-flows constituting the connection) have tranferred so far, or by
-average bytes per packet.
-
-The counters are 64bit and are thus not expected to overflow ;)
-
-The primary use is to detect long-lived downloads and mark them to be
-scheduled using a lower priority band in traffic control.
-
-The transfered bytes per connection can also be viewed through
-/proc/net/ip_conntrack and accessed via ctnetlink
-.TP
-[\fB!\fR]\fB --connbytes \fIfrom\fB:\fR[\fIto\fR]
-match packets from a connection whose packets/bytes/average packet
-size is more than FROM and less than TO bytes/packets. if TO is
-omitted only FROM check is done. "!" is used to match packets not
-falling in the range.
-.TP
-\fB--connbytes-dir\fR [\fBoriginal\fR|\fBreply\fR|\fBboth\fR]
-which packets to consider
-.TP
-\fB--connbytes-mode\fR [\fBpackets\fR|\fBbytes\fR|\fBavgpkt\fR]
-whether to check the amount of packets, number of bytes transferred or
-the average size (in bytes) of all packets received so far. Note that
-when "both" is used together with "avgpkt", and data is going (mainly)
-only in one direction (for example HTTP), the average packet size will
-be about half of the actual data packets.
-.TP
-Example:
-iptables .. -m connbytes --connbytes 10000:100000 --connbytes-dir both --connbytes-mode bytes ...
diff --git a/extensions/libipt_connmark.man b/extensions/libipt_connmark.man
deleted file mode 100644
index a8e0600..0000000
--- a/extensions/libipt_connmark.man
+++ /dev/null
@@ -1,9 +0,0 @@
-This module matches the netfilter mark field associated with a connection
-(which can be set using the
-.B CONNMARK
-target below).
-.TP
-.BI "--mark " "value[/mask]"
-Matches packets in connections with the given mark value (if a mask is
-specified, this is logically ANDed with the mark before the
-comparison).
diff --git a/extensions/libipt_connrate.c b/extensions/libipt_connrate.c
deleted file mode 100644
index fbb18ec..0000000
--- a/extensions/libipt_connrate.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Shared library add-on to iptables to add connection rate tracking
- * support.
- *
- * Copyright (c) 2004 Nuutti Kotivuori <naked@iki.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- **/
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ipt_connrate.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"connrate v%s options:\n"
-" --connrate [!] [from]:[to]\n"
-" Match connection transfer rate in bytes\n"
-" per second. `inf' can be used for maximum\n"
-" expressible value.\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "connrate", 1, 0, '1' },
- {0}
-};
-
-static u_int32_t
-parse_value(const char *arg, u_int32_t def)
-{
- char *end;
- size_t len;
- u_int32_t value;
-
- len = strlen(arg);
- if(len == 0)
- return def;
- if(strcmp(arg, "inf") == 0)
- return 0xFFFFFFFF;
- value = strtoul(arg, &end, 0);
- if(*end != '\0')
- exit_error(PARAMETER_PROBLEM,
- "Bad value in range `%s'", arg);
- return value;
-}
-
-static void
-parse_range(const char *arg, struct ipt_connrate_info *si)
-{
- char *buffer;
- char *colon;
-
- buffer = strdup(arg);
- if ((colon = strchr(buffer, ':')) == NULL)
- exit_error(PARAMETER_PROBLEM, "Bad range `%s'", arg);
- *colon = '\0';
- si->from = parse_value(buffer, 0);
- si->to = parse_value(colon+1, 0xFFFFFFFF);
- if (si->from > si->to)
- exit_error(PARAMETER_PROBLEM, "%u should be less than %u", si->from,si->to);
- free(buffer);
-}
-
-#define CONNRATE_OPT 0x01
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)(*match)->data;
- u_int32_t tmp;
-
- switch (c) {
- case '1':
- if (*flags & CONNRATE_OPT)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--connrate' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_range(argv[optind-1], sinfo);
- if (invert) {
- tmp = sinfo->from;
- sinfo->from = sinfo->to;
- sinfo->to = tmp;
- }
- *flags |= CONNRATE_OPT;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!(flags & CONNRATE_OPT))
- exit_error(PARAMETER_PROBLEM,
- "connrate match: You must specify `--connrate'");
-}
-
-static void
-print_value(u_int32_t value)
-{
- if(value == 0xFFFFFFFF)
- printf("inf");
- else
- printf("%u", value);
-}
-
-static void
-print_range(struct ipt_connrate_info *sinfo)
-{
- if (sinfo->from > sinfo->to) {
- printf("! ");
- print_value(sinfo->to);
- printf(":");
- print_value(sinfo->from);
- } else {
- print_value(sinfo->from);
- printf(":");
- print_value(sinfo->to);
- }
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)match->data;
-
- printf("connrate ");
- print_range(sinfo);
- printf(" ");
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_connrate_info *sinfo = (struct ipt_connrate_info *)match->data;
-
- printf("--connrate ");
- print_range(sinfo);
- printf(" ");
-}
-
-static struct iptables_match state = {
- .next = NULL,
- .name = "connrate",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_connrate_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_connrate_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_connrate_init(void)
-{
- register_match(&state);
-}
diff --git a/extensions/libipt_connrate.man b/extensions/libipt_connrate.man
deleted file mode 100644
index 45cba9d..0000000
--- a/extensions/libipt_connrate.man
+++ /dev/null
@@ -1,6 +0,0 @@
-This module matches the current transfer rate in a connection.
-.TP
-.BI "--connrate " "[!] [\fIfrom\fP]:[\fIto\fP]"
-Match against the current connection transfer rate being within 'from'
-and 'to' bytes per second. When the "!" argument is used before the
-range, the sense of the match is inverted.
diff --git a/extensions/libipt_conntrack.c b/extensions/libipt_conntrack.c
deleted file mode 100644
index e26b523..0000000
--- a/extensions/libipt_conntrack.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/* Shared library add-on to iptables for conntrack matching support.
- * GPL (C) 2001 Marc Boucher (marc@mbsi.ca).
- */
-
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_conntrack.h"
-
-#ifndef IPT_CONNTRACK_STATE_UNTRACKED
-#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3))
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"conntrack match v%s options:\n"
-" [!] --ctstate [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT][,...]\n"
-" State(s) to match\n"
-" [!] --ctproto proto Protocol to match; by number or name, eg. `tcp'\n"
-" --ctorigsrc [!] address[/mask]\n"
-" Original source specification\n"
-" --ctorigdst [!] address[/mask]\n"
-" Original destination specification\n"
-" --ctreplsrc [!] address[/mask]\n"
-" Reply source specification\n"
-" --ctrepldst [!] address[/mask]\n"
-" Reply destination specification\n"
-" [!] --ctstatus [NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED][,...]\n"
-" Status(es) to match\n"
-" [!] --ctexpire time[:time] Match remaining lifetime in seconds against\n"
-" value or range of values (inclusive)\n"
-"\n", IPTABLES_VERSION);
-}
-
-
-
-static struct option opts[] = {
- { "ctstate", 1, 0, '1' },
- { "ctproto", 1, 0, '2' },
- { "ctorigsrc", 1, 0, '3' },
- { "ctorigdst", 1, 0, '4' },
- { "ctreplsrc", 1, 0, '5' },
- { "ctrepldst", 1, 0, '6' },
- { "ctstatus", 1, 0, '7' },
- { "ctexpire", 1, 0, '8' },
- {0}
-};
-
-static int
-parse_state(const char *state, size_t strlen, struct ipt_conntrack_info *sinfo)
-{
- if (strncasecmp(state, "INVALID", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_INVALID;
- else if (strncasecmp(state, "NEW", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_NEW);
- else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
- else if (strncasecmp(state, "RELATED", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
- else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_UNTRACKED;
- else if (strncasecmp(state, "SNAT", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_SNAT;
- else if (strncasecmp(state, "DNAT", strlen) == 0)
- sinfo->statemask |= IPT_CONNTRACK_STATE_DNAT;
- else
- return 0;
- return 1;
-}
-
-static void
-parse_states(const char *arg, struct ipt_conntrack_info *sinfo)
-{
- const char *comma;
-
- while ((comma = strchr(arg, ',')) != NULL) {
- if (comma == arg || !parse_state(arg, comma-arg, sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
- arg = comma+1;
- }
-
- if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad ctstate `%s'", arg);
-}
-
-static int
-parse_status(const char *status, size_t strlen, struct ipt_conntrack_info *sinfo)
-{
- if (strncasecmp(status, "NONE", strlen) == 0)
- sinfo->statusmask |= 0;
- else if (strncasecmp(status, "EXPECTED", strlen) == 0)
- sinfo->statusmask |= IPS_EXPECTED;
- else if (strncasecmp(status, "SEEN_REPLY", strlen) == 0)
- sinfo->statusmask |= IPS_SEEN_REPLY;
- else if (strncasecmp(status, "ASSURED", strlen) == 0)
- sinfo->statusmask |= IPS_ASSURED;
-#ifdef IPS_CONFIRMED
- else if (strncasecmp(status, "CONFIRMED", strlen) == 0)
- sinfo->stausmask |= IPS_CONFIRMED;
-#endif
- else
- return 0;
- return 1;
-}
-
-static void
-parse_statuses(const char *arg, struct ipt_conntrack_info *sinfo)
-{
- const char *comma;
-
- while ((comma = strchr(arg, ',')) != NULL) {
- if (comma == arg || !parse_status(arg, comma-arg, sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
- arg = comma+1;
- }
-
- if (strlen(arg) == 0 || !parse_status(arg, strlen(arg), sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad ctstatus `%s'", arg);
-}
-
-#ifdef KERNEL_64_USERSPACE_32
-static unsigned long long
-parse_expire(const char *s)
-{
- unsigned long long len;
-
- if (string_to_number_ll(s, 0, 0, &len) == -1)
- exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", s);
- else
- return len;
-}
-#else
-static unsigned long
-parse_expire(const char *s)
-{
- unsigned int len;
-
- if (string_to_number(s, 0, 0, &len) == -1)
- exit_error(PARAMETER_PROBLEM, "expire value invalid: `%s'\n", s);
- else
- return len;
-}
-#endif
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_expires(const char *s, struct ipt_conntrack_info *sinfo)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(s);
- if ((cp = strchr(buffer, ':')) == NULL)
- sinfo->expires_min = sinfo->expires_max = parse_expire(buffer);
- else {
- *cp = '\0';
- cp++;
-
- sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
- sinfo->expires_max = cp[0] ? parse_expire(cp) : -1;
- }
- free(buffer);
-
- if (sinfo->expires_min > sinfo->expires_max)
- exit_error(PARAMETER_PROBLEM,
-#ifdef KERNEL_64_USERSPACE_32
- "expire min. range value `%llu' greater than max. "
- "range value `%llu'", sinfo->expires_min, sinfo->expires_max);
-#else
- "expire min. range value `%lu' greater than max. "
- "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
-#endif
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)(*match)->data;
- char *protocol = NULL;
- unsigned int naddrs = 0;
- struct in_addr *addrs = NULL;
-
-
- switch (c) {
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-
- parse_states(argv[optind-1], sinfo);
- if (invert) {
- sinfo->invflags |= IPT_CONNTRACK_STATE;
- }
- sinfo->flags |= IPT_CONNTRACK_STATE;
- break;
-
- case '2':
- check_inverse(optarg, &invert, &optind, 0);
-
- if(invert)
- sinfo->invflags |= IPT_CONNTRACK_PROTO;
-
- /* Canonicalize into lower case */
- for (protocol = argv[optind-1]; *protocol; protocol++)
- *protocol = tolower(*protocol);
-
- protocol = argv[optind-1];
- sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum = parse_protocol(protocol);
-
- if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
- && (sinfo->invflags & IPT_INV_PROTO))
- exit_error(PARAMETER_PROBLEM,
- "rule would never match protocol");
-
- sinfo->flags |= IPT_CONNTRACK_PROTO;
- break;
-
- case '3':
- check_inverse(optarg, &invert, &optind, 9);
-
- if (invert)
- sinfo->invflags |= IPT_CONNTRACK_ORIGSRC;
-
- parse_hostnetworkmask(argv[optind-1], &addrs,
- &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
- &naddrs);
- if(naddrs > 1)
- exit_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
- }
-
- sinfo->flags |= IPT_CONNTRACK_ORIGSRC;
- break;
-
- case '4':
- check_inverse(optarg, &invert, &optind, 0);
-
- if (invert)
- sinfo->invflags |= IPT_CONNTRACK_ORIGDST;
-
- parse_hostnetworkmask(argv[optind-1], &addrs,
- &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
- &naddrs);
- if(naddrs > 1)
- exit_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
- }
-
- sinfo->flags |= IPT_CONNTRACK_ORIGDST;
- break;
-
- case '5':
- check_inverse(optarg, &invert, &optind, 0);
-
- if (invert)
- sinfo->invflags |= IPT_CONNTRACK_REPLSRC;
-
- parse_hostnetworkmask(argv[optind-1], &addrs,
- &sinfo->sipmsk[IP_CT_DIR_REPLY],
- &naddrs);
- if(naddrs > 1)
- exit_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
- }
-
- sinfo->flags |= IPT_CONNTRACK_REPLSRC;
- break;
-
- case '6':
- check_inverse(optarg, &invert, &optind, 0);
-
- if (invert)
- sinfo->invflags |= IPT_CONNTRACK_REPLDST;
-
- parse_hostnetworkmask(argv[optind-1], &addrs,
- &sinfo->dipmsk[IP_CT_DIR_REPLY],
- &naddrs);
- if(naddrs > 1)
- exit_error(PARAMETER_PROBLEM,
- "multiple IP addresses not allowed");
-
- if(naddrs == 1) {
- sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
- }
-
- sinfo->flags |= IPT_CONNTRACK_REPLDST;
- break;
-
- case '7':
- check_inverse(optarg, &invert, &optind, 0);
-
- parse_statuses(argv[optind-1], sinfo);
- if (invert) {
- sinfo->invflags |= IPT_CONNTRACK_STATUS;
- }
- sinfo->flags |= IPT_CONNTRACK_STATUS;
- break;
-
- case '8':
- check_inverse(optarg, &invert, &optind, 0);
-
- parse_expires(argv[optind-1], sinfo);
- if (invert) {
- sinfo->invflags |= IPT_CONNTRACK_EXPIRES;
- }
- sinfo->flags |= IPT_CONNTRACK_EXPIRES;
- break;
-
- default:
- return 0;
- }
-
- *flags = sinfo->flags;
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, "You must specify one or more options");
-}
-
-static void
-print_state(unsigned int statemask)
-{
- const char *sep = "";
-
- if (statemask & IPT_CONNTRACK_STATE_INVALID) {
- printf("%sINVALID", sep);
- sep = ",";
- }
- if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
- printf("%sNEW", sep);
- sep = ",";
- }
- if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
- printf("%sRELATED", sep);
- sep = ",";
- }
- if (statemask & IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
- printf("%sESTABLISHED", sep);
- sep = ",";
- }
- if (statemask & IPT_CONNTRACK_STATE_UNTRACKED) {
- printf("%sUNTRACKED", sep);
- sep = ",";
- }
- if (statemask & IPT_CONNTRACK_STATE_SNAT) {
- printf("%sSNAT", sep);
- sep = ",";
- }
- if (statemask & IPT_CONNTRACK_STATE_DNAT) {
- printf("%sDNAT", sep);
- sep = ",";
- }
- printf(" ");
-}
-
-static void
-print_status(unsigned int statusmask)
-{
- const char *sep = "";
-
- if (statusmask & IPS_EXPECTED) {
- printf("%sEXPECTED", sep);
- sep = ",";
- }
- if (statusmask & IPS_SEEN_REPLY) {
- printf("%sSEEN_REPLY", sep);
- sep = ",";
- }
- if (statusmask & IPS_ASSURED) {
- printf("%sASSURED", sep);
- sep = ",";
- }
-#ifdef IPS_CONFIRMED
- if (statusmask & IPS_CONFIRMED) {
- printf("%sCONFIRMED", sep);
- sep =",";
- }
-#endif
- if (statusmask == 0) {
- printf("%sNONE", sep);
- sep = ",";
- }
- printf(" ");
-}
-
-static void
-print_addr(struct in_addr *addr, struct in_addr *mask, int inv, int numeric)
-{
- char buf[BUFSIZ];
-
- if (inv)
- printf("! ");
-
- if (mask->s_addr == 0L && !numeric)
- printf("%s ", "anywhere");
- else {
- if (numeric)
- sprintf(buf, "%s", addr_to_dotted(addr));
- else
- sprintf(buf, "%s", addr_to_anyname(addr));
- strcat(buf, mask_to_dotted(mask));
- printf("%s ", buf);
- }
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void
-matchinfo_print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric, const char *optpfx)
-{
- struct ipt_conntrack_info *sinfo = (struct ipt_conntrack_info *)match->data;
-
- if(sinfo->flags & IPT_CONNTRACK_STATE) {
- printf("%sctstate ", optpfx);
- if (sinfo->invflags & IPT_CONNTRACK_STATE)
- printf("! ");
- print_state(sinfo->statemask);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_PROTO) {
- printf("%sctproto ", optpfx);
- if (sinfo->invflags & IPT_CONNTRACK_PROTO)
- printf("! ");
- printf("%u ", sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) {
- printf("%sctorigsrc ", optpfx);
-
- print_addr(
- (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
- &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
- sinfo->invflags & IPT_CONNTRACK_ORIGSRC,
- numeric);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_ORIGDST) {
- printf("%sctorigdst ", optpfx);
-
- print_addr(
- (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
- &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
- sinfo->invflags & IPT_CONNTRACK_ORIGDST,
- numeric);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_REPLSRC) {
- printf("%sctreplsrc ", optpfx);
-
- print_addr(
- (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
- &sinfo->sipmsk[IP_CT_DIR_REPLY],
- sinfo->invflags & IPT_CONNTRACK_REPLSRC,
- numeric);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_REPLDST) {
- printf("%sctrepldst ", optpfx);
-
- print_addr(
- (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
- &sinfo->dipmsk[IP_CT_DIR_REPLY],
- sinfo->invflags & IPT_CONNTRACK_REPLDST,
- numeric);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_STATUS) {
- printf("%sctstatus ", optpfx);
- if (sinfo->invflags & IPT_CONNTRACK_STATUS)
- printf("! ");
- print_status(sinfo->statusmask);
- }
-
- if(sinfo->flags & IPT_CONNTRACK_EXPIRES) {
- printf("%sctexpire ", optpfx);
- if (sinfo->invflags & IPT_CONNTRACK_EXPIRES)
- printf("! ");
-
-#ifdef KERNEL_64_USERSPACE_32
- if (sinfo->expires_max == sinfo->expires_min)
- printf("%llu ", sinfo->expires_min);
- else
- printf("%llu:%llu ", sinfo->expires_min, sinfo->expires_max);
-#else
- if (sinfo->expires_max == sinfo->expires_min)
- printf("%lu ", sinfo->expires_min);
- else
- printf("%lu:%lu ", sinfo->expires_min, sinfo->expires_max);
-#endif
- }
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- matchinfo_print(ip, match, numeric, "");
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- matchinfo_print(ip, match, 1, "--");
-}
-
-static struct iptables_match conntrack = {
- .next = NULL,
- .name = "conntrack",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_conntrack_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_conntrack_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_conntrack_init(void)
-{
- register_match(&conntrack);
-}
diff --git a/extensions/libipt_conntrack.man b/extensions/libipt_conntrack.man
deleted file mode 100644
index b732b28..0000000
--- a/extensions/libipt_conntrack.man
+++ /dev/null
@@ -1,49 +0,0 @@
-This module, when combined with connection tracking, allows access to
-more connection tracking information than the "state" match.
-(this module is present only if iptables was compiled under a kernel
-supporting this feature)
-.TP
-.BI "--ctstate " "state"
-Where state is a comma separated list of the connection states to
-match. Possible states are
-.B INVALID
-meaning that the packet is associated with no known connection,
-.B ESTABLISHED
-meaning that the packet is associated with a connection which has seen
-packets in both directions,
-.B NEW
-meaning that the packet has started a new connection, or otherwise
-associated with a connection which has not seen packets in both
-directions, and
-.B RELATED
-meaning that the packet is starting a new connection, but is
-associated with an existing connection, such as an FTP data transfer,
-or an ICMP error.
-.B SNAT
-A virtual state, matching if the original source address differs from
-the reply destination.
-.B DNAT
-A virtual state, matching if the original destination differs from the
-reply source.
-.TP
-.BI "--ctproto " "proto"
-Protocol to match (by number or name)
-.TP
-.BI "--ctorigsrc " "[!] \fIaddress\fP[/\fImask\fP]"
-Match against original source address
-.TP
-.BI "--ctorigdst " "[!] \fIaddress\fP[/\fImask\fP]"
-Match against original destination address
-.TP
-.BI "--ctreplsrc " "[!] \fIaddress\fP[/\fImask\fP]"
-Match against reply source address
-.TP
-.BI "--ctrepldst " "[!] \fIaddress\fB[/\fImask\fP]"
-Match against reply destination address
-.TP
-.BI "--ctstatus " "[\fINONE|EXPECTED|SEEN_REPLY|ASSURED\fP][,...]"
-Match against internal conntrack states
-.TP
-.BI "--ctexpire " "\fItime\fP[\fI:time\fP]"
-Match remaining lifetime in seconds against given value
-or range of values (inclusive)
diff --git a/extensions/libipt_dccp.c b/extensions/libipt_dccp.c
deleted file mode 100644
index 9770639..0000000
--- a/extensions/libipt_dccp.c
+++ /dev/null
@@ -1,374 +0,0 @@
-/* Shared library add-on to iptables for DCCP matching
- *
- * (C) 2005 by Harald Welte <laforge@netfilter.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <netdb.h>
-#include <ctype.h>
-
-#include <iptables.h>
-#include <linux/dccp.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_dccp.h>
-
-#if 0
-#define DEBUGP(format, first...) printf(format, ##first)
-#define static
-#else
-#define DEBUGP(format, fist...)
-#endif
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m,
- unsigned int *nfcache)
-{
- struct ipt_dccp_info *einfo = (struct ipt_dccp_info *)m->data;
-
- memset(einfo, 0, sizeof(struct ipt_dccp_info));
-}
-
-static void help(void)
-{
- printf(
-"DCCP match v%s options\n"
-" --source-port [!] port[:port] match source port(s)\n"
-" --sport ...\n"
-" --destination-port [!] port[:port] match destination port(s)\n"
-" --dport ...\n"
-,
- IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { .name = "source-port", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "sport", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "destination-port", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "dport", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "dccp-types", .has_arg = 1, .flag = 0, .val = '3' },
- { .name = "dccp-option", .has_arg = 1, .flag = 0, .val = '4' },
- { .name = 0 }
-};
-
-static void
-parse_dccp_ports(const char *portstring,
- u_int16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- DEBUGP("%s\n", portstring);
- if ((cp = strchr(buffer, ':')) == NULL) {
- ports[0] = ports[1] = parse_port(buffer, "dccp");
- }
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? parse_port(buffer, "dccp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "dccp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
-static char *dccp_pkt_types[] = {
- [DCCP_PKT_REQUEST] = "REQUEST",
- [DCCP_PKT_RESPONSE] = "RESPONSE",
- [DCCP_PKT_DATA] = "DATA",
- [DCCP_PKT_ACK] = "ACK",
- [DCCP_PKT_DATAACK] = "DATAACK",
- [DCCP_PKT_CLOSEREQ] = "CLOSEREQ",
- [DCCP_PKT_CLOSE] = "CLOSE",
- [DCCP_PKT_RESET] = "RESET",
- [DCCP_PKT_SYNC] = "SYNC",
- [DCCP_PKT_SYNCACK] = "SYNCACK",
- [DCCP_PKT_INVALID] = "INVALID",
-};
-
-static u_int16_t
-parse_dccp_types(const char *typestring)
-{
- u_int16_t typemask = 0;
- char *ptr, *buffer;
-
- buffer = strdup(typestring);
-
- for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
- unsigned int i;
- for (i = 0; i < sizeof(dccp_pkt_types)/sizeof(char *); i++) {
- if (!strcasecmp(dccp_pkt_types[i], ptr)) {
- typemask |= (1 << i);
- break;
- }
- }
- if (i == sizeof(dccp_pkt_types)/sizeof(char *))
- exit_error(PARAMETER_PROBLEM,
- "Unknown DCCP type `%s'", ptr);
- }
-
- free(buffer);
- return typemask;
-}
-
-static u_int8_t parse_dccp_option(char *optstring)
-{
- unsigned int ret;
-
- if (string_to_number(optstring, 1, 255, &ret) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad DCCP option `%s'",
- optstring);
-
- return (u_int8_t)ret;
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_dccp_info *einfo
- = (struct ipt_dccp_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & IPT_DCCP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- einfo->flags |= IPT_DCCP_SRC_PORTS;
- check_inverse(optarg, &invert, &optind, 0);
- parse_dccp_ports(argv[optind-1], einfo->spts);
- if (invert)
- einfo->invflags |= IPT_DCCP_SRC_PORTS;
- *flags |= IPT_DCCP_SRC_PORTS;
- break;
-
- case '2':
- if (*flags & IPT_DCCP_DEST_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- einfo->flags |= IPT_DCCP_DEST_PORTS;
- check_inverse(optarg, &invert, &optind, 0);
- parse_dccp_ports(argv[optind-1], einfo->dpts);
- if (invert)
- einfo->invflags |= IPT_DCCP_DEST_PORTS;
- *flags |= IPT_DCCP_DEST_PORTS;
- break;
-
- case '3':
- if (*flags & IPT_DCCP_TYPE)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--dccp-types' allowed");
- einfo->flags |= IPT_DCCP_TYPE;
- check_inverse(optarg, &invert, &optind, 0);
- einfo->typemask = parse_dccp_types(argv[optind-1]);
- if (invert)
- einfo->invflags |= IPT_DCCP_TYPE;
- *flags |= IPT_DCCP_TYPE;
- break;
-
- case '4':
- if (*flags & IPT_DCCP_OPTION)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--dccp-option' allowed");
- einfo->flags |= IPT_DCCP_OPTION;
- check_inverse(optarg, &invert, &optind, 0);
- einfo->option = parse_dccp_option(argv[optind-1]);
- if (invert)
- einfo->invflags |= IPT_DCCP_OPTION;
- *flags |= IPT_DCCP_OPTION;
- break;
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-static char *
-port_to_service(int port)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), "dccp")))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-static void
-print_ports(const char *name, u_int16_t min, u_int16_t max,
- int invert, int numeric)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- print_port(min, numeric);
- } else {
- printf("s:%s", inv);
- print_port(min, numeric);
- printf(":");
- print_port(max, numeric);
- }
- printf(" ");
- }
-}
-
-static void
-print_types(u_int16_t types, int inverted, int numeric)
-{
- int have_type = 0;
-
- if (inverted)
- printf("! ");
-
- while (types) {
- unsigned int i;
-
- for (i = 0; !(types & (1 << i)); i++);
-
- if (have_type)
- printf(",");
- else
- have_type = 1;
-
- if (numeric)
- printf("%u", i);
- else
- printf("%s", dccp_pkt_types[i]);
-
- types &= ~(1 << i);
- }
-}
-
-static void
-print_option(u_int8_t option, int invert, int numeric)
-{
- if (option || invert)
- printf("option=%s%u ", invert ? "!" : "", option);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_dccp_info *einfo =
- (const struct ipt_dccp_info *)match->data;
-
- printf("dccp ");
-
- if (einfo->flags & IPT_DCCP_SRC_PORTS) {
- print_ports("spt", einfo->spts[0], einfo->spts[1],
- einfo->invflags & IPT_DCCP_SRC_PORTS,
- numeric);
- }
-
- if (einfo->flags & IPT_DCCP_DEST_PORTS) {
- print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
- einfo->invflags & IPT_DCCP_DEST_PORTS,
- numeric);
- }
-
- if (einfo->flags & IPT_DCCP_TYPE) {
- print_types(einfo->typemask,
- einfo->invflags & IPT_DCCP_TYPE,
- numeric);
- }
-
- if (einfo->flags & IPT_DCCP_OPTION) {
- print_option(einfo->option,
- einfo->invflags & IPT_DCCP_OPTION, numeric);
- }
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
-{
- const struct ipt_dccp_info *einfo =
- (const struct ipt_dccp_info *)match->data;
-
- if (einfo->flags & IPT_DCCP_SRC_PORTS) {
- if (einfo->invflags & IPT_DCCP_SRC_PORTS)
- printf("! ");
- if (einfo->spts[0] != einfo->spts[1])
- printf("--sport %u:%u ",
- einfo->spts[0], einfo->spts[1]);
- else
- printf("--sport %u ", einfo->spts[0]);
- }
-
- if (einfo->flags & IPT_DCCP_DEST_PORTS) {
- if (einfo->invflags & IPT_DCCP_DEST_PORTS)
- printf("! ");
- if (einfo->dpts[0] != einfo->dpts[1])
- printf("--dport %u:%u ",
- einfo->dpts[0], einfo->dpts[1]);
- else
- printf("--dport %u ", einfo->dpts[0]);
- }
-
- if (einfo->flags & IPT_DCCP_TYPE) {
- printf("--dccp-type ");
- print_types(einfo->typemask, einfo->invflags & IPT_DCCP_TYPE,0);
- }
-
- if (einfo->flags & IPT_DCCP_OPTION) {
- printf("--dccp-option %s%u ",
- einfo->typemask & IPT_DCCP_OPTION ? "! " : "",
- einfo->option);
- }
-}
-
-static
-struct iptables_match dccp
-= { .name = "dccp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_dccp_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_dccp_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_dccp_init(void)
-{
- register_match(&dccp);
-}
-
diff --git a/extensions/libipt_dccp.man b/extensions/libipt_dccp.man
deleted file mode 100644
index 6443ec3..0000000
--- a/extensions/libipt_dccp.man
+++ /dev/null
@@ -1,12 +0,0 @@
-.TP
-\fB--source-port\fR,\fB--sport \fR[\fB!\fR] \fIport\fR[\fB:\fIport\fR]
-.TP
-\fB--destination-port\fR,\fB--dport \fR[\fB!\fR] \fIport\fR[\fB:\fIport\fR]
-.TP
-\fB--dccp-types\fR [\fB!\fR] \fImask\fP
-Match when the DCCP packet type is one of 'mask'. 'mask' is a comma-separated
-list of packet types. Packet types are:
-.BR "REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID" .
-.TP
-\fB--dccp-option\fR [\fB!\fR\] \fInumber\fP
-Match if DCP option set.
diff --git a/extensions/libipt_2ecn.c b/extensions/libipt_ecn.c
index 2d5a38e..3b7b299 100644
--- a/extensions/libipt_2ecn.c
+++ b/extensions/libipt_ecn.c
@@ -12,32 +12,27 @@
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_2ecn.h>
+#include <xtables.h>
+#include <linux/netfilter_ipv4/ipt_ecn.h>
-static void help(void)
+static void ecn_help(void)
{
printf(
-"ECN match v%s options\n"
+"ECN match options\n"
"[!] --ecn-tcp-cwr Match CWR bit of TCP header\n"
"[!] --ecn-tcp-ece Match ECE bit of TCP header\n"
-"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n",
- IPTABLES_VERSION);
+"[!] --ecn-ip-ect [0..3] Match ECN codepoint in IPv4 header\n");
}
-static struct option opts[] = {
- { .name = "ecn-tcp-cwr", .has_arg = 0, .flag = 0, .val = 'F' },
- { .name = "ecn-tcp-ece", .has_arg = 0, .flag = 0, .val = 'G' },
- { .name = "ecn-ip-ect", .has_arg = 1, .flag = 0, .val = 'H' },
- { .name = 0 }
+static const struct option ecn_opts[] = {
+ { .name = "ecn-tcp-cwr", .has_arg = 0, .val = 'F' },
+ { .name = "ecn-tcp-ece", .has_arg = 0, .val = 'G' },
+ { .name = "ecn-ip-ect", .has_arg = 1, .val = 'H' },
+ { .name = NULL }
};
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+static int ecn_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
unsigned int result;
struct ipt_ecn_info *einfo
@@ -46,9 +41,9 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case 'F':
if (*flags & IPT_ECN_OP_MATCH_CWR)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN match: can only use parameter ONCE!");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
einfo->operation |= IPT_ECN_OP_MATCH_CWR;
if (invert)
einfo->invert |= IPT_ECN_OP_MATCH_CWR;
@@ -57,9 +52,9 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case 'G':
if (*flags & IPT_ECN_OP_MATCH_ECE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN match: can only use parameter ONCE!");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
einfo->operation |= IPT_ECN_OP_MATCH_ECE;
if (invert)
einfo->invert |= IPT_ECN_OP_MATCH_ECE;
@@ -68,15 +63,15 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case 'H':
if (*flags & IPT_ECN_OP_MATCH_IP)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN match: can only use parameter ONCE!");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
if (invert)
einfo->invert |= IPT_ECN_OP_MATCH_IP;
*flags |= IPT_ECN_OP_MATCH_IP;
einfo->operation |= IPT_ECN_OP_MATCH_IP;
- if (string_to_number(optarg, 0, 3, &result))
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &result, 0, 3))
+ xtables_error(PARAMETER_PROBLEM,
"ECN match: Value out of range");
einfo->ip_ect = result;
break;
@@ -87,19 +82,15 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void
-final_check(unsigned int flags)
+static void ecn_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ECN match: some option required");
}
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
+static void ecn_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ipt_ecn_info *einfo =
(const struct ipt_ecn_info *)match->data;
@@ -125,9 +116,7 @@ print(const struct ipt_ip *ip,
}
}
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void ecn_save(const void *ip, const struct xt_entry_match *match)
{
const struct ipt_ecn_info *einfo =
(const struct ipt_ecn_info *)match->data;
@@ -151,21 +140,21 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
}
}
-static
-struct iptables_match ecn
-= { .name = "ecn",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_ecn_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_ecn_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+static struct xtables_match ecn_mt_reg = {
+ .name = "ecn",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_ecn_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_ecn_info)),
+ .help = ecn_help,
+ .parse = ecn_parse,
+ .final_check = ecn_check,
+ .print = ecn_print,
+ .save = ecn_save,
+ .extra_opts = ecn_opts,
};
-void ipt_2ecn_init(void)
+void libipt_ecn_init(void)
{
- register_match(&ecn);
+ xtables_register_match(&ecn_mt_reg);
}
diff --git a/extensions/libipt_ecn.man b/extensions/libipt_ecn.man
index 8ecfef5..7f80647 100644
--- a/extensions/libipt_ecn.man
+++ b/extensions/libipt_ecn.man
@@ -1,11 +1,11 @@
This allows you to match the ECN bits of the IPv4 and TCP header. ECN is the Explicit Congestion Notification mechanism as specified in RFC3168
.TP
-.BI "--ecn-tcp-cwr"
+[\fB!\fP] \fB\-\-ecn\-tcp\-cwr\fP
This matches if the TCP ECN CWR (Congestion Window Received) bit is set.
.TP
-.BI "--ecn-tcp-ece"
+[\fB!\fP] \fB\-\-ecn\-tcp\-ece\fP
This matches if the TCP ECN ECE (ECN Echo) bit is set.
.TP
-.BI "--ecn-ip-ect " "num"
+[\fB!\fP] \fB\-\-ecn\-ip\-ect\fP \fInum\fP
This matches a particular IPv4 ECT (ECN-Capable Transport). You have to specify
a number between `0' and `3'.
diff --git a/extensions/libipt_esp.c b/extensions/libipt_esp.c
deleted file mode 100644
index d75a407..0000000
--- a/extensions/libipt_esp.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* Shared library add-on to iptables to add ESP support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <errno.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_esp.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"ESP v%s options:\n"
-" --espspi [!] spi[:spi]\n"
-" match spi (range)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "espspi", 1, 0, '1' },
- {0}
-};
-
-static u_int32_t
-parse_esp_spi(const char *spistr)
-{
- unsigned long int spi;
- char* ep;
-
- spi = strtoul(spistr,&ep,0) ;
-
- if ( spistr == ep ) {
- exit_error(PARAMETER_PROBLEM,
- "ESP no valid digits in spi `%s'", spistr);
- }
- if ( spi == ULONG_MAX && errno == ERANGE ) {
- exit_error(PARAMETER_PROBLEM,
- "spi `%s' specified too big: would overflow", spistr);
- }
- if ( *spistr != '\0' && *ep != '\0' ) {
- exit_error(PARAMETER_PROBLEM,
- "ESP error parsing spi `%s'", spistr);
- }
- return (u_int32_t) spi;
-}
-
-static void
-parse_esp_spis(const char *spistring, u_int32_t *spis)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(spistring);
- if ((cp = strchr(buffer, ':')) == NULL)
- spis[0] = spis[1] = parse_esp_spi(buffer);
- else {
- *cp = '\0';
- cp++;
-
- spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
- spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
- if (spis[0] > spis[1])
- exit_error(PARAMETER_PROBLEM,
- "Invalid ESP spi range: %s", spistring);
- }
- free(buffer);
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
- struct ipt_esp *espinfo = (struct ipt_esp *)m->data;
-
- espinfo->spis[1] = 0xFFFFFFFF;
-}
-
-#define ESP_SPI 0x01
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_esp *espinfo = (struct ipt_esp *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & ESP_SPI)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--espspi' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_esp_spis(argv[optind-1], espinfo->spis);
- if (invert)
- espinfo->invflags |= IPT_ESP_INV_SPI;
- *flags |= ESP_SPI;
- break;
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
-static void
-print_spis(const char *name, u_int32_t min, u_int32_t max,
- int invert)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFFFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- printf("%u", min);
- } else {
- printf("s:%s", inv);
- printf("%u",min);
- printf(":");
- printf("%u",max);
- }
- printf(" ");
- }
-}
-
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match, int numeric)
-{
- const struct ipt_esp *esp = (struct ipt_esp *)match->data;
-
- printf("esp ");
- print_spis("spi", esp->spis[0], esp->spis[1],
- esp->invflags & IPT_ESP_INV_SPI);
- if (esp->invflags & ~IPT_ESP_INV_MASK)
- printf("Unknown invflags: 0x%X ",
- esp->invflags & ~IPT_ESP_INV_MASK);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- const struct ipt_esp *espinfo = (struct ipt_esp *)match->data;
-
- if (!(espinfo->spis[0] == 0
- && espinfo->spis[1] == 0xFFFFFFFF)) {
- printf("--espspi %s",
- (espinfo->invflags & IPT_ESP_INV_SPI) ? "! " : "");
- if (espinfo->spis[0]
- != espinfo->spis[1])
- printf("%u:%u ",
- espinfo->spis[0],
- espinfo->spis[1]);
- else
- printf("%u ",
- espinfo->spis[0]);
- }
-
-}
-
-static struct iptables_match esp = {
- .next = NULL,
- .name = "esp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_esp)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_esp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void
-ipt_esp_init(void)
-{
- register_match(&esp);
-}
diff --git a/extensions/libipt_hashlimit.c b/extensions/libipt_hashlimit.c
deleted file mode 100644
index ce77628..0000000
--- a/extensions/libipt_hashlimit.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/* iptables match extension for limiting packets per destination
- *
- * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
- *
- * Development of this code was funded by Astaro AG, http://www.astaro.com/
- *
- * Based on ipt_limit.c by
- * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne <rv@wallfire.org>
- *
- * Error corections by nmalykh@bilim.com (22.01.2005)
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <stddef.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_hashlimit.h>
-
-#define IPT_HASHLIMIT_BURST 5
-
-/* miliseconds */
-#define IPT_HASHLIMIT_GCINTERVAL 1000
-#define IPT_HASHLIMIT_EXPIRE 10000
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"hashlimit v%s options:\n"
-"--hashlimit <avg> max average match rate\n"
-" [Packets per second unless followed by \n"
-" /sec /minute /hour /day postfixes]\n"
-"--hashlimit-mode <mode> mode is a comma-separated list of\n"
-" dstip,srcip,dstport,srcport\n"
-"--hashlimit-name <name> name for /proc/net/ipt_hashlimit/\n"
-"[--hashlimit-burst <num>] number to match in a burst, default %u\n"
-"[--hashlimit-htable-size <num>] number of hashtable buckets\n"
-"[--hashlimit-htable-max <num>] number of hashtable entries\n"
-"[--hashlimit-htable-gcinterval] interval between garbage collection runs\n"
-"[--hashlimit-htable-expire] after which time are idle entries expired?\n"
-"\n", IPTABLES_VERSION, IPT_HASHLIMIT_BURST);
-}
-
-static struct option opts[] = {
- { "hashlimit", 1, 0, '%' },
- { "hashlimit-burst", 1, 0, '$' },
- { "hashlimit-htable-size", 1, 0, '&' },
- { "hashlimit-htable-max", 1, 0, '*' },
- { "hashlimit-htable-gcinterval", 1, 0, '(' },
- { "hashlimit-htable-expire", 1, 0, ')' },
- { "hashlimit-mode", 1, 0, '_' },
- { "hashlimit-name", 1, 0, '"' },
- { 0 }
-};
-
-static
-int parse_rate(const char *rate, u_int32_t *val)
-{
- const char *delim;
- u_int32_t r;
- u_int32_t mult = 1; /* Seconds by default. */
-
- delim = strchr(rate, '/');
- if (delim) {
- if (strlen(delim+1) == 0)
- return 0;
-
- if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
- mult = 1;
- else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
- mult = 60;
- else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
- mult = 60*60;
- else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
- mult = 24*60*60;
- else
- return 0;
- }
- r = atoi(rate);
- if (!r)
- return 0;
-
- /* This would get mapped to infinite (1/day is minimum they
- can specify, so we're ok at that end). */
- if (r / mult > IPT_HASHLIMIT_SCALE)
- exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
-
- *val = IPT_HASHLIMIT_SCALE * mult / r;
- return 1;
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
- struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *)m->data;
-
- r->cfg.burst = IPT_HASHLIMIT_BURST;
- r->cfg.gc_interval = IPT_HASHLIMIT_GCINTERVAL;
- r->cfg.expire = IPT_HASHLIMIT_EXPIRE;
-
-}
-
-
-/* Parse a 'mode' parameter into the required bitmask */
-static int parse_mode(struct ipt_hashlimit_info *r, char *optarg)
-{
- char *tok;
- char *arg = strdup(optarg);
-
- if (!arg)
- return -1;
-
- r->cfg.mode = 0;
-
- for (tok = strtok(arg, ",|");
- tok;
- tok = strtok(NULL, ",|")) {
- if (!strcmp(tok, "dstip"))
- r->cfg.mode |= IPT_HASHLIMIT_HASH_DIP;
- else if (!strcmp(tok, "srcip"))
- r->cfg.mode |= IPT_HASHLIMIT_HASH_SIP;
- else if (!strcmp(tok, "srcport"))
- r->cfg.mode |= IPT_HASHLIMIT_HASH_SPT;
- else if (!strcmp(tok, "dstport"))
- r->cfg.mode |= IPT_HASHLIMIT_HASH_DPT;
- else {
- free(arg);
- return -1;
- }
- }
- free(arg);
- return 0;
-}
-
-#define PARAM_LIMIT 0x00000001
-#define PARAM_BURST 0x00000002
-#define PARAM_MODE 0x00000004
-#define PARAM_NAME 0x00000008
-#define PARAM_SIZE 0x00000010
-#define PARAM_MAX 0x00000020
-#define PARAM_GCINTERVAL 0x00000040
-#define PARAM_EXPIRE 0x00000080
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_hashlimit_info *r =
- (struct ipt_hashlimit_info *)(*match)->data;
- unsigned int num;
-
- switch(c) {
- case '%':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (!parse_rate(optarg, &r->cfg.avg))
- exit_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- *flags |= PARAM_LIMIT;
- break;
-
- case '$':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 10000, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-burst `%s'", optarg);
- r->cfg.burst = num;
- *flags |= PARAM_BURST;
- break;
- case '&':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-size: `%s'", optarg);
- r->cfg.size = num;
- *flags |= PARAM_SIZE;
- break;
- case '*':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-max: `%s'", optarg);
- r->cfg.max = num;
- *flags |= PARAM_MAX;
- break;
- case '(':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-gcinterval: `%s'",
- optarg);
- /* FIXME: not HZ dependent!! */
- r->cfg.gc_interval = num;
- *flags |= PARAM_GCINTERVAL;
- break;
- case ')':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 0xffffffff, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-htable-expire: `%s'", optarg);
- /* FIXME: not HZ dependent */
- r->cfg.expire = num;
- *flags |= PARAM_EXPIRE;
- break;
- case '_':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (parse_mode(r, optarg) < 0)
- exit_error(PARAMETER_PROBLEM,
- "bad --hashlimit-mode: `%s'\n", optarg);
- *flags |= PARAM_MODE;
- break;
- case '"':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (strlen(optarg) == 0)
- exit_error(PARAMETER_PROBLEM, "Zero-length name?");
- strncpy(r->name, optarg, sizeof(r->name));
- *flags |= PARAM_NAME;
- break;
- default:
- return 0;
- }
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "hashlimit does not support invert");
-
- return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
- if (!(flags & PARAM_LIMIT))
- exit_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit");
- if (!(flags & PARAM_MODE))
- exit_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-mode");
- if (!(flags & PARAM_NAME))
- exit_error(PARAMETER_PROBLEM,
- "You have to specify --hashlimit-name");
-}
-
-static struct rates
-{
- const char *name;
- u_int32_t mult;
-} rates[] = { { "day", IPT_HASHLIMIT_SCALE*24*60*60 },
- { "hour", IPT_HASHLIMIT_SCALE*60*60 },
- { "min", IPT_HASHLIMIT_SCALE*60 },
- { "sec", IPT_HASHLIMIT_SCALE } };
-
-static void print_rate(u_int32_t period)
-{
- unsigned int i;
-
- for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
- if (period > rates[i].mult
- || rates[i].mult/period < rates[i].mult%period)
- break;
- }
-
- printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
-}
-
-static void print_mode(const struct ipt_hashlimit_info *r, char separator)
-{
- int prevmode = 0;
-
- if (r->cfg.mode & IPT_HASHLIMIT_HASH_SIP) {
- if (prevmode)
- putchar(separator);
- fputs("srcip", stdout);
- prevmode = 1;
- }
- if (r->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
- if (prevmode)
- putchar(separator);
- fputs("srcport", stdout);
- prevmode = 1;
- }
- if (r->cfg.mode & IPT_HASHLIMIT_HASH_DIP) {
- if (prevmode)
- putchar(separator);
- fputs("dstip", stdout);
- prevmode = 1;
- }
- if (r->cfg.mode & IPT_HASHLIMIT_HASH_DPT) {
- if (prevmode)
- putchar(separator);
- fputs("dstport", stdout);
- }
- putchar(' ');
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_hashlimit_info *r =
- (struct ipt_hashlimit_info *)match->data;
- fputs("limit: avg ", stdout); print_rate(r->cfg.avg);
- printf("burst %u ", r->cfg.burst);
- fputs("mode ", stdout);
- print_mode(r, '-');
- if (r->cfg.size)
- printf("htable-size %u ", r->cfg.size);
- if (r->cfg.max)
- printf("htable-max %u ", r->cfg.max);
- if (r->cfg.gc_interval != IPT_HASHLIMIT_GCINTERVAL)
- printf("htable-gcinterval %u ", r->cfg.gc_interval);
- if (r->cfg.expire != IPT_HASHLIMIT_EXPIRE)
- printf("htable-expire %u ", r->cfg.expire);
-}
-
-/* FIXME: Make minimalist: only print rate if not default --RR */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_hashlimit_info *r =
- (struct ipt_hashlimit_info *)match->data;
-
- fputs("--hashlimit ", stdout); print_rate(r->cfg.avg);
- if (r->cfg.burst != IPT_HASHLIMIT_BURST)
- printf("--hashlimit-burst %u ", r->cfg.burst);
-
- fputs("--hashlimit-mode ", stdout);
- print_mode(r, ',');
-
- printf("--hashlimit-name %s ", r->name);
-
- if (r->cfg.size)
- printf("--hashlimit-htable-size %u ", r->cfg.size);
- if (r->cfg.max)
- printf("--hashlimit-htable-max %u ", r->cfg.max);
- if (r->cfg.gc_interval != IPT_HASHLIMIT_GCINTERVAL)
- printf("--hashlimit-htable-gcinterval %u", r->cfg.gc_interval);
- if (r->cfg.expire != IPT_HASHLIMIT_EXPIRE)
- printf("--hashlimit-htable-expire %u ", r->cfg.expire);
-}
-
-static struct iptables_match hashlimit = { NULL,
- .name = "hashlimit",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_hashlimit_info)),
- .userspacesize = offsetof(struct ipt_hashlimit_info, hinfo),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_hashlimit_init(void)
-{
- register_match(&hashlimit);
-}
diff --git a/extensions/libipt_hashlimit.man b/extensions/libipt_hashlimit.man
deleted file mode 100644
index 1b0a5d4..0000000
--- a/extensions/libipt_hashlimit.man
+++ /dev/null
@@ -1,35 +0,0 @@
-This patch adds a new match called 'hashlimit'.
-The idea is to have something like 'limit', but either per
-destination-ip or per (destip,destport) tuple.
-
-It gives you the ability to express
-.IP
- '1000 packets per second for every host in 192.168.0.0/16'
-.IP
- '100 packets per second for every service of 192.168.1.1'
-.P
-with a single iptables rule.
-.TP
-.BI "--hashlimit " "rate"
-A rate just like the limit match
-.TP
-.BI "--hashlimit-burst " "num"
-Burst value, just like limit match
-.TP
-.BI "--hashlimit-mode " "destip | destip-destport"
-Limit per IP or per port
-.TP
-.BI "--hashlimit-name " "foo"
-The name for the /proc/net/ipt_hashlimit/foo entry
-.TP
-.BI "--hashlimit-htable-size " "num"
-The number of buckets of the hash table
-.TP
-.BI "--hashlimit-htable-max " "num"
-Maximum entries in the hash
-.TP
-.BI "--hashlimit-htable-expire " "num"
-After how many miliseconds do hash entries expire
-.TP
-.BI "--hashlimit-htable-gcinterval " "num"
-How many miliseconds between garbage collection intervals
diff --git a/extensions/libipt_helper.c b/extensions/libipt_helper.c
deleted file mode 100644
index f7e0ce0..0000000
--- a/extensions/libipt_helper.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Shared library add-on to iptables to add related packet matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_helper.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"helper match v%s options:\n"
-"[!] --helper string Match helper identified by string\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "helper", 1, 0, '1' },
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_helper_info *info = (struct ipt_helper_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "helper match: Only use --helper ONCE!");
- check_inverse(optarg, &invert, &invert, 0);
- strncpy(info->name, optarg, 29);
- info->name[29] = '\0';
- if (invert)
- info->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-/* Final check; must have specified --helper. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "helper match: You must specify `--helper'");
-}
-
-/* Prints out the info. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_helper_info *info = (struct ipt_helper_info *)match->data;
-
- printf("helper match %s\"%s\" ", info->invert ? "! " : "", info->name);
-}
-
-/* Saves the union ipt_info in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_helper_info *info = (struct ipt_helper_info *)match->data;
-
- printf("%s--helper \"%s\" ",info->invert ? "! " : "", info->name);
-}
-
-static struct iptables_match helper = {
- .next = NULL,
- .name = "helper",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_helper_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_helper_init(void)
-{
- register_match(&helper);
-}
diff --git a/extensions/libipt_icmp.c b/extensions/libipt_icmp.c
index 3a7b1c0..46c536a 100644
--- a/extensions/libipt_icmp.c
+++ b/extensions/libipt_icmp.c
@@ -4,7 +4,8 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
+#include <limits.h> /* INT_MAX in ip_tables.h */
#include <linux/netfilter_ipv4/ip_tables.h>
/* special hack for icmp-type 'any':
@@ -77,12 +78,12 @@ static const struct icmp_names icmp_codes[] = {
};
static void
-print_icmptypes()
+print_icmptypes(void)
{
unsigned int i;
printf("Valid ICMP Types:");
- for (i = 0; i < sizeof(icmp_codes)/sizeof(struct icmp_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(icmp_codes); ++i) {
if (i && icmp_codes[i].type == icmp_codes[i-1].type) {
if (icmp_codes[i].code_min == icmp_codes[i-1].code_min
&& (icmp_codes[i].code_max
@@ -97,27 +98,24 @@ print_icmptypes()
printf("\n");
}
-/* Function which prints out usage message. */
-static void
-help(void)
+static void icmp_help(void)
{
printf(
-"ICMP v%s options:\n"
-" --icmp-type [!] typename match icmp type\n"
-" (or numeric type or type/code)\n"
-"\n", IPTABLES_VERSION);
+"icmp match options:\n"
+"[!] --icmp-type typename match icmp type\n"
+"[!] --icmp-type type[/code] (or numeric type or type/code)\n");
print_icmptypes();
}
-static struct option opts[] = {
- { "icmp-type", 1, 0, '1' },
- {0}
+static const struct option icmp_opts[] = {
+ { "icmp-type", 1, NULL, '1' },
+ { .name = NULL }
};
static void
parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[])
{
- unsigned int limit = sizeof(icmp_codes)/sizeof(struct icmp_names);
+ static const unsigned int limit = ARRAY_SIZE(icmp_codes);
unsigned int match = limit;
unsigned int i;
@@ -125,7 +123,7 @@ parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[])
if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype))
== 0) {
if (match != limit)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Ambiguous ICMP type `%s':"
" `%s' or `%s'?",
icmptype,
@@ -150,13 +148,13 @@ parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[])
if (slash)
*slash = '\0';
- if (string_to_number(buffer, 0, 255, &number) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(buffer, NULL, &number, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"Invalid ICMP type `%s'\n", buffer);
*type = number;
if (slash) {
- if (string_to_number(slash+1, 0, 255, &number) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(slash+1, NULL, &number, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"Invalid ICMP code `%s'\n",
slash+1);
code[0] = code[1] = number;
@@ -167,9 +165,7 @@ parse_icmp(const char *icmptype, u_int8_t *type, u_int8_t code[])
}
}
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
+static void icmp_init(struct xt_entry_match *m)
{
struct ipt_icmp *icmpinfo = (struct ipt_icmp *)m->data;
@@ -177,23 +173,18 @@ init(struct ipt_entry_match *m, unsigned int *nfcache)
icmpinfo->code[1] = 0xFF;
}
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+static int icmp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ipt_icmp *icmpinfo = (struct ipt_icmp *)(*match)->data;
switch (c) {
case '1':
if (*flags == 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"icmp match: only use --icmp-type once!");
- check_inverse(optarg, &invert, &optind, 0);
- parse_icmp(argv[optind-1], &icmpinfo->type,
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_icmp(optarg, &icmpinfo->type,
icmpinfo->code);
if (invert)
icmpinfo->invflags |= IPT_ICMP_INV;
@@ -215,16 +206,13 @@ static void print_icmptype(u_int8_t type,
if (!numeric) {
unsigned int i;
- for (i = 0;
- i < sizeof(icmp_codes)/sizeof(struct icmp_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(icmp_codes); ++i)
if (icmp_codes[i].type == type
&& icmp_codes[i].code_min == code_min
&& icmp_codes[i].code_max == code_max)
break;
- }
- if (i != sizeof(icmp_codes)/sizeof(struct icmp_names)) {
+ if (i != ARRAY_SIZE(icmp_codes)) {
printf("%s%s ",
invert ? "!" : "",
icmp_codes[i].name);
@@ -244,11 +232,8 @@ static void print_icmptype(u_int8_t type,
printf(" codes %u-%u ", code_min, code_max);
}
-/* Prints out the union ipt_matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
+static void icmp_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data;
@@ -262,8 +247,7 @@ print(const struct ipt_ip *ip,
icmp->invflags & ~IPT_ICMP_INV);
}
-/* Saves the match in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void icmp_save(const void *ip, const struct xt_entry_match *match)
{
const struct ipt_icmp *icmp = (struct ipt_icmp *)match->data;
@@ -281,27 +265,21 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
}
}
-/* Final check; we don't care. */
-static void final_check(unsigned int flags)
-{
-}
-
-static struct iptables_match icmp = {
- .next = NULL,
+static struct xtables_match icmp_mt_reg = {
.name = "icmp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_icmp)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_icmp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_icmp)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_icmp)),
+ .help = icmp_help,
+ .init = icmp_init,
+ .parse = icmp_parse,
+ .print = icmp_print,
+ .save = icmp_save,
+ .extra_opts = icmp_opts,
};
-void ipt_icmp_init(void)
+void libipt_icmp_init(void)
{
- register_match(&icmp);
+ xtables_register_match(&icmp_mt_reg);
}
diff --git a/extensions/libipt_icmp.man b/extensions/libipt_icmp.man
index 5b91514..1039704 100644
--- a/extensions/libipt_icmp.man
+++ b/extensions/libipt_icmp.man
@@ -1,9 +1,9 @@
-This extension is loaded if `--protocol icmp' is specified. It
+This extension can be used if `\-\-protocol icmp' is specified. It
provides the following option:
.TP
-.BR "--icmp-type " "[!] \fItypename\fP"
+[\fB!\fP] \fB\-\-icmp\-type\fP {\fItype\fP[\fB/\fP\fIcode\fP]|\fItypename\fP}
This allows specification of the ICMP type, which can be a numeric
-ICMP type, or one of the ICMP type names shown by the command
+ICMP type, type/code pair, or one of the ICMP type names shown by the command
.nf
- iptables -p icmp -h
+ iptables \-p icmp \-h
.fi
diff --git a/extensions/libipt_iprange.c b/extensions/libipt_iprange.c
deleted file mode 100644
index 847802b..0000000
--- a/extensions/libipt_iprange.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Shared library add-on to iptables to add IP range matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_iprange.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"iprange match v%s options:\n"
-"[!] --src-range ip-ip Match source IP in the specified range\n"
-"[!] --dst-range ip-ip Match destination IP in the specified range\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "src-range", 1, 0, '1' },
- { "dst-range", 1, 0, '2' },
- {0}
-};
-
-static void
-parse_iprange(char *arg, struct ipt_iprange *range)
-{
- char *dash;
- struct in_addr *ip;
-
- dash = strchr(arg, '-');
- if (dash)
- *dash = '\0';
-
- ip = dotted_to_addr(arg);
- if (!ip)
- exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
- arg);
- range->min_ip = ip->s_addr;
-
- if (dash) {
- ip = dotted_to_addr(dash+1);
- if (!ip)
- exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
- dash+1);
- range->max_ip = ip->s_addr;
- } else
- range->max_ip = range->min_ip;
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & IPRANGE_SRC)
- exit_error(PARAMETER_PROBLEM,
- "iprange match: Only use --src-range ONCE!");
- *flags |= IPRANGE_SRC;
-
- info->flags |= IPRANGE_SRC;
- check_inverse(optarg, &invert, &optind, 0);
- if (invert) {
- info->flags |= IPRANGE_SRC_INV;
- }
- parse_iprange(optarg, &info->src);
-
- break;
-
- case '2':
- if (*flags & IPRANGE_DST)
- exit_error(PARAMETER_PROBLEM,
- "iprange match: Only use --dst-range ONCE!");
- *flags |= IPRANGE_DST;
-
- info->flags |= IPRANGE_DST;
- check_inverse(optarg, &invert, &optind, 0);
- if (invert)
- info->flags |= IPRANGE_DST_INV;
-
- parse_iprange(optarg, &info->dst);
-
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-/* Final check; must have specified --src-range or --dst-range. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "iprange match: You must specify `--src-range' or `--dst-range'");
-}
-
-static void
-print_iprange(const struct ipt_iprange *range)
-{
- const unsigned char *byte_min, *byte_max;
-
- byte_min = (const unsigned char *) &(range->min_ip);
- byte_max = (const unsigned char *) &(range->max_ip);
- printf("%d.%d.%d.%d-%d.%d.%d.%d ",
- byte_min[0], byte_min[1], byte_min[2], byte_min[3],
- byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
-}
-
-/* Prints out the info. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
-
- if (info->flags & IPRANGE_SRC) {
- printf("source IP range ");
- if (info->flags & IPRANGE_SRC_INV)
- printf("! ");
- print_iprange(&info->src);
- }
- if (info->flags & IPRANGE_DST) {
- printf("destination IP range ");
- if (info->flags & IPRANGE_DST_INV)
- printf("! ");
- print_iprange(&info->dst);
- }
-}
-
-/* Saves the union ipt_info in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
-
- if (info->flags & IPRANGE_SRC) {
- if (info->flags & IPRANGE_SRC_INV)
- printf("! ");
- printf("--src-range ");
- print_iprange(&info->src);
- if (info->flags & IPRANGE_DST)
- fputc(' ', stdout);
- }
- if (info->flags & IPRANGE_DST) {
- if (info->flags & IPRANGE_DST_INV)
- printf("! ");
- printf("--dst-range ");
- print_iprange(&info->dst);
- }
-}
-
-static struct iptables_match iprange = {
- .next = NULL,
- .name = "iprange",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_iprange_init(void)
-{
- register_match(&iprange);
-}
diff --git a/extensions/libipt_iprange.man b/extensions/libipt_iprange.man
deleted file mode 100644
index 57e1cff..0000000
--- a/extensions/libipt_iprange.man
+++ /dev/null
@@ -1,7 +0,0 @@
-This matches on a given arbitrary range of IPv4 addresses
-.TP
-.BI "[!]" "--src-range " "ip-ip"
-Match source IP in the specified range.
-.TP
-.BI "[!]" "--dst-range " "ip-ip"
-Match destination IP in the specified range.
diff --git a/extensions/libipt_length.c b/extensions/libipt_length.c
deleted file mode 100644
index 38c70b5..0000000
--- a/extensions/libipt_length.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Shared library add-on to iptables to add packet length matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_length.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"length v%s options:\n"
-"[!] --length length[:length] Match packet length against value or range\n"
-" of values (inclusive)\n",
-IPTABLES_VERSION);
-
-}
-
-static struct option opts[] = {
- { "length", 1, 0, '1' },
- {0}
-};
-
-static u_int16_t
-parse_length(const char *s)
-{
- unsigned int len;
-
- if (string_to_number(s, 0, 0xFFFF, &len) == -1)
- exit_error(PARAMETER_PROBLEM, "length invalid: `%s'\n", s);
- else
- return (u_int16_t )len;
-}
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_lengths(const char *s, struct ipt_length_info *info)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(s);
- if ((cp = strchr(buffer, ':')) == NULL)
- info->min = info->max = parse_length(buffer);
- else {
- *cp = '\0';
- cp++;
-
- info->min = buffer[0] ? parse_length(buffer) : 0;
- info->max = cp[0] ? parse_length(cp) : 0xFFFF;
- }
- free(buffer);
-
- if (info->min > info->max)
- exit_error(PARAMETER_PROBLEM,
- "length min. range value `%u' greater than max. "
- "range value `%u'", info->min, info->max);
-
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_length_info *info = (struct ipt_length_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "length: `--length' may only be "
- "specified once");
- check_inverse(optarg, &invert, &optind, 0);
- parse_lengths(argv[optind-1], info);
- if (invert)
- info->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-/* Final check; must have specified --length. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "length: You must specify `--length'");
-}
-
-/* Common match printing code. */
-static void
-print_length(struct ipt_length_info *info)
-{
- if (info->invert)
- printf("! ");
-
- if (info->max == info->min)
- printf("%u ", info->min);
- else
- printf("%u:%u ", info->min, info->max);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- printf("length ");
- print_length((struct ipt_length_info *)match->data);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- printf("--length ");
- print_length((struct ipt_length_info *)match->data);
-}
-
-static struct iptables_match length = {
- .next = NULL,
- .name = "length",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_length_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_length_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_length_init(void)
-{
- register_match(&length);
-}
diff --git a/extensions/libipt_length.man b/extensions/libipt_length.man
deleted file mode 100644
index 43bbdcf..0000000
--- a/extensions/libipt_length.man
+++ /dev/null
@@ -1,4 +0,0 @@
-This module matches the length of a packet against a specific value
-or range of values.
-.TP
-.BR "--length " "[!] \fIlength\fP[:\fIlength\fP]"
diff --git a/extensions/libipt_limit.c b/extensions/libipt_limit.c
deleted file mode 100644
index 5e75d93..0000000
--- a/extensions/libipt_limit.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Shared library add-on to iptables to add limit support.
- *
- * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
- * Hervé Eychenne <rv@wallfire.org>
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <stddef.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-/* For 64bit kernel / 32bit userspace */
-#include "../include/linux/netfilter_ipv4/ipt_limit.h"
-
-#define IPT_LIMIT_AVG "3/hour"
-#define IPT_LIMIT_BURST 5
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"limit v%s options:\n"
-"--limit avg max average match rate: default "IPT_LIMIT_AVG"\n"
-" [Packets per second unless followed by \n"
-" /sec /minute /hour /day postfixes]\n"
-"--limit-burst number number to match in a burst, default %u\n"
-"\n", IPTABLES_VERSION, IPT_LIMIT_BURST);
-}
-
-static struct option opts[] = {
- { "limit", 1, 0, '%' },
- { "limit-burst", 1, 0, '$' },
- { 0 }
-};
-
-static
-int parse_rate(const char *rate, u_int32_t *val)
-{
- const char *delim;
- u_int32_t r;
- u_int32_t mult = 1; /* Seconds by default. */
-
- delim = strchr(rate, '/');
- if (delim) {
- if (strlen(delim+1) == 0)
- return 0;
-
- if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
- mult = 1;
- else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
- mult = 60;
- else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
- mult = 60*60;
- else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
- mult = 24*60*60;
- else
- return 0;
- }
- r = atoi(rate);
- if (!r)
- return 0;
-
- /* This would get mapped to infinite (1/day is minimum they
- can specify, so we're ok at that end). */
- if (r / mult > IPT_LIMIT_SCALE)
- exit_error(PARAMETER_PROBLEM, "Rate too fast `%s'\n", rate);
-
- *val = IPT_LIMIT_SCALE * mult / r;
- return 1;
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
- struct ipt_rateinfo *r = (struct ipt_rateinfo *)m->data;
-
- parse_rate(IPT_LIMIT_AVG, &r->avg);
- r->burst = IPT_LIMIT_BURST;
-
-}
-
-/* FIXME: handle overflow:
- if (r->avg*r->burst/r->burst != r->avg)
- exit_error(PARAMETER_PROBLEM,
- "Sorry: burst too large for that avg rate.\n");
-*/
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_rateinfo *r = (struct ipt_rateinfo *)(*match)->data;
- unsigned int num;
-
- switch(c) {
- case '%':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (!parse_rate(optarg, &r->avg))
- exit_error(PARAMETER_PROBLEM,
- "bad rate `%s'", optarg);
- break;
-
- case '$':
- if (check_inverse(argv[optind-1], &invert, &optind, 0)) break;
- if (string_to_number(optarg, 0, 10000, &num) == -1)
- exit_error(PARAMETER_PROBLEM,
- "bad --limit-burst `%s'", optarg);
- r->burst = num;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "limit does not support invert");
-
- return 1;
-}
-
-/* Final check; nothing. */
-static void final_check(unsigned int flags)
-{
-}
-
-static struct rates
-{
- const char *name;
- u_int32_t mult;
-} rates[] = { { "day", IPT_LIMIT_SCALE*24*60*60 },
- { "hour", IPT_LIMIT_SCALE*60*60 },
- { "min", IPT_LIMIT_SCALE*60 },
- { "sec", IPT_LIMIT_SCALE } };
-
-static void print_rate(u_int32_t period)
-{
- unsigned int i;
-
- for (i = 1; i < sizeof(rates)/sizeof(struct rates); i++) {
- if (period > rates[i].mult
- || rates[i].mult/period < rates[i].mult%period)
- break;
- }
-
- printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_rateinfo *r = (struct ipt_rateinfo *)match->data;
- printf("limit: avg "); print_rate(r->avg);
- printf("burst %u ", r->burst);
-}
-
-/* FIXME: Make minimalist: only print rate if not default --RR */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_rateinfo *r = (struct ipt_rateinfo *)match->data;
-
- printf("--limit "); print_rate(r->avg);
- if (r->burst != IPT_LIMIT_BURST)
- printf("--limit-burst %u ", r->burst);
-}
-
-static struct iptables_match limit = {
- .next = NULL,
- .name = "limit",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_rateinfo)),
- .userspacesize = offsetof(struct ipt_rateinfo, prev),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_limit_init(void)
-{
- register_match(&limit);
-}
diff --git a/extensions/libipt_mac.c b/extensions/libipt_mac.c
deleted file mode 100644
index 59f9fc0..0000000
--- a/extensions/libipt_mac.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/* Shared library add-on to iptables to add MAC address support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_mac.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"MAC v%s options:\n"
-" --mac-source [!] XX:XX:XX:XX:XX:XX\n"
-" Match source MAC address\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mac-source", 1, 0, '1' },
- {0}
-};
-
-static void
-parse_mac(const char *mac, struct ipt_mac_info *info)
-{
- unsigned int i = 0;
-
- if (strlen(mac) != ETH_ALEN*3-1)
- exit_error(PARAMETER_PROBLEM, "Bad mac address `%s'", mac);
-
- for (i = 0; i < ETH_ALEN; i++) {
- long number;
- char *end;
-
- number = strtol(mac + i*3, &end, 16);
-
- if (end == mac + i*3 + 2
- && number >= 0
- && number <= 255)
- info->srcaddr[i] = number;
- else
- exit_error(PARAMETER_PROBLEM,
- "Bad mac address `%s'", mac);
- }
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_mac_info *macinfo = (struct ipt_mac_info *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
- parse_mac(argv[optind-1], macinfo);
- if (invert)
- macinfo->invert = 1;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void print_mac(unsigned char macaddress[ETH_ALEN])
-{
- unsigned int i;
-
- printf("%02X", macaddress[0]);
- for (i = 1; i < ETH_ALEN; i++)
- printf(":%02X", macaddress[i]);
- printf(" ");
-}
-
-/* Final check; must have specified --mac. */
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "You must specify `--mac-source'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- printf("MAC ");
-
- if (((struct ipt_mac_info *)match->data)->invert)
- printf("! ");
-
- print_mac(((struct ipt_mac_info *)match->data)->srcaddr);
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- if (((struct ipt_mac_info *)match->data)->invert)
- printf("! ");
-
- printf("--mac-source ");
- print_mac(((struct ipt_mac_info *)match->data)->srcaddr);
-}
-
-static struct iptables_match mac = {
- .next = NULL,
- .name = "mac",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_mac_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_mac_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_mac_init(void)
-{
- register_match(&mac);
-}
diff --git a/extensions/libipt_mac.man b/extensions/libipt_mac.man
deleted file mode 100644
index 5321ca1..0000000
--- a/extensions/libipt_mac.man
+++ /dev/null
@@ -1,10 +0,0 @@
-.TP
-.BR "--mac-source " "[!] \fIaddress\fP"
-Match source MAC address. It must be of the form XX:XX:XX:XX:XX:XX.
-Note that this only makes sense for packets coming from an Ethernet device
-and entering the
-.BR PREROUTING ,
-.B FORWARD
-or
-.B INPUT
-chains.
diff --git a/extensions/libipt_mark.man b/extensions/libipt_mark.man
deleted file mode 100644
index a2a1395..0000000
--- a/extensions/libipt_mark.man
+++ /dev/null
@@ -1,9 +0,0 @@
-This module matches the netfilter mark field associated with a packet
-(which can be set using the
-.B MARK
-target below).
-.TP
-.BR "--mark " "\fIvalue\fP[/\fImask\fP]"
-Matches packets with the given unsigned mark value (if a \fImask\fP is
-specified, this is logically ANDed with the \fImask\fP before the
-comparison).
diff --git a/extensions/libipt_multiport.c b/extensions/libipt_multiport.c
deleted file mode 100644
index 694d69d..0000000
--- a/extensions/libipt_multiport.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/* Shared library add-on to iptables to add multiple TCP port support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <netinet/in.h>
-/* To ensure that iptables compiles with an old kernel */
-#include "../include/linux/netfilter_ipv4/ipt_multiport.h"
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"multiport v%s options:\n"
-" --source-ports port[,port,port...]\n"
-" --sports ...\n"
-" match source port(s)\n"
-" --destination-ports port[,port,port...]\n"
-" --dports ...\n"
-" match destination port(s)\n"
-" --ports port[,port,port]\n"
-" match both source and destination port(s)\n"
-" NOTE: this kernel does not support port ranges in multiport.\n",
-IPTABLES_VERSION);
-}
-
-static void
-help_v1(void)
-{
- printf(
-"multiport v%s options:\n"
-" --source-ports [!] port[,port:port,port...]\n"
-" --sports ...\n"
-" match source port(s)\n"
-" --destination-ports [!] port[,port:port,port...]\n"
-" --dports ...\n"
-" match destination port(s)\n"
-" --ports [!] port[,port:port,port]\n"
-" match both source and destination port(s)\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "source-ports", 1, 0, '1' },
- { "sports", 1, 0, '1' }, /* synonym */
- { "destination-ports", 1, 0, '2' },
- { "dports", 1, 0, '2' }, /* synonym */
- { "ports", 1, 0, '3' },
- {0}
-};
-
-static char *
-proto_to_name(u_int8_t proto)
-{
- switch (proto) {
- case IPPROTO_TCP:
- return "tcp";
- case IPPROTO_UDP:
- return "udp";
- case IPPROTO_UDPLITE:
- return "udplite";
- case IPPROTO_SCTP:
- return "sctp";
- case IPPROTO_DCCP:
- return "dccp";
- default:
- return NULL;
- }
-}
-
-static unsigned int
-parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
-{
- char *buffer, *cp, *next;
- unsigned int i;
-
- buffer = strdup(portstring);
- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
-
- for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next,i++)
- {
- next=strchr(cp, ',');
- if (next) *next++='\0';
- ports[i] = parse_port(cp, proto);
- }
- if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
- free(buffer);
- return i;
-}
-
-static void
-parse_multi_ports_v1(const char *portstring,
- struct ipt_multiport_v1 *multiinfo,
- const char *proto)
-{
- char *buffer, *cp, *next, *range;
- unsigned int i;
- u_int16_t m;
-
- buffer = strdup(portstring);
- if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
-
- for (i=0; i<IPT_MULTI_PORTS; i++)
- multiinfo->pflags[i] = 0;
-
- for (cp=buffer, i=0; cp && i<IPT_MULTI_PORTS; cp=next, i++) {
- next=strchr(cp, ',');
- if (next) *next++='\0';
- range = strchr(cp, ':');
- if (range) {
- if (i == IPT_MULTI_PORTS-1)
- exit_error(PARAMETER_PROBLEM,
- "too many ports specified");
- *range++ = '\0';
- }
- multiinfo->ports[i] = parse_port(cp, proto);
- if (range) {
- multiinfo->pflags[i] = 1;
- multiinfo->ports[++i] = parse_port(range, proto);
- if (multiinfo->ports[i-1] >= multiinfo->ports[i])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange specified");
- m <<= 1;
- }
- }
- multiinfo->count = i;
- if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
- free(buffer);
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-}
-
-static const char *
-check_proto(const struct ipt_entry *entry)
-{
- char *proto;
-
- if (entry->ip.invflags & IPT_INV_PROTO)
- exit_error(PARAMETER_PROBLEM,
- "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
-
- if ((proto = proto_to_name(entry->ip.proto)) != NULL)
- return proto;
- else if (!entry->ip.proto)
- exit_error(PARAMETER_PROBLEM,
- "multiport needs `-p tcp', `-p udp', `-p udplite', "
- "`-p sctp' or `-p dccp'");
- else
- exit_error(PARAMETER_PROBLEM,
- "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- const char *proto;
- struct ipt_multiport *multiinfo
- = (struct ipt_multiport *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- multiinfo->count = parse_multi_ports(argv[optind-1],
- multiinfo->ports, proto);
- multiinfo->flags = IPT_MULTIPORT_SOURCE;
- break;
-
- case '2':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- multiinfo->count = parse_multi_ports(argv[optind-1],
- multiinfo->ports, proto);
- multiinfo->flags = IPT_MULTIPORT_DESTINATION;
- break;
-
- case '3':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- multiinfo->count = parse_multi_ports(argv[optind-1],
- multiinfo->ports, proto);
- multiinfo->flags = IPT_MULTIPORT_EITHER;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "multiport does not support invert");
-
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
-}
-
-static int
-parse_v1(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- const char *proto;
- struct ipt_multiport_v1 *multiinfo
- = (struct ipt_multiport_v1 *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
- multiinfo->flags = IPT_MULTIPORT_SOURCE;
- break;
-
- case '2':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
- multiinfo->flags = IPT_MULTIPORT_DESTINATION;
- break;
-
- case '3':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- proto = check_proto(entry);
- parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
- multiinfo->flags = IPT_MULTIPORT_EITHER;
- break;
-
- default:
- return 0;
- }
-
- if (invert)
- multiinfo->invert = 1;
-
- if (*flags)
- exit_error(PARAMETER_PROBLEM,
- "multiport can only have one option");
- *flags = 1;
- return 1;
-}
-
-/* Final check; must specify something. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, "multiport expection an option");
-}
-
-static char *
-port_to_service(int port, u_int8_t proto)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), proto_to_name(proto))))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, u_int8_t protocol, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port, protocol)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_multiport *multiinfo
- = (const struct ipt_multiport *)match->data;
- unsigned int i;
-
- printf("multiport ");
-
- switch (multiinfo->flags) {
- case IPT_MULTIPORT_SOURCE:
- printf("sports ");
- break;
-
- case IPT_MULTIPORT_DESTINATION:
- printf("dports ");
- break;
-
- case IPT_MULTIPORT_EITHER:
- printf("ports ");
- break;
-
- default:
- printf("ERROR ");
- break;
- }
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, numeric);
- }
- printf(" ");
-}
-
-static void
-print_v1(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_multiport_v1 *multiinfo
- = (const struct ipt_multiport_v1 *)match->data;
- unsigned int i;
-
- printf("multiport ");
-
- switch (multiinfo->flags) {
- case IPT_MULTIPORT_SOURCE:
- printf("sports ");
- break;
-
- case IPT_MULTIPORT_DESTINATION:
- printf("dports ");
- break;
-
- case IPT_MULTIPORT_EITHER:
- printf("ports ");
- break;
-
- default:
- printf("ERROR ");
- break;
- }
-
- if (multiinfo->invert)
- printf("! ");
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, numeric);
- if (multiinfo->pflags[i]) {
- printf(":");
- print_port(multiinfo->ports[++i], ip->proto, numeric);
- }
- }
- printf(" ");
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- const struct ipt_multiport *multiinfo
- = (const struct ipt_multiport *)match->data;
- unsigned int i;
-
- switch (multiinfo->flags) {
- case IPT_MULTIPORT_SOURCE:
- printf("--sports ");
- break;
-
- case IPT_MULTIPORT_DESTINATION:
- printf("--dports ");
- break;
-
- case IPT_MULTIPORT_EITHER:
- printf("--ports ");
- break;
- }
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, 1);
- }
- printf(" ");
-}
-
-static void save_v1(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
-{
- const struct ipt_multiport_v1 *multiinfo
- = (const struct ipt_multiport_v1 *)match->data;
- unsigned int i;
-
- switch (multiinfo->flags) {
- case IPT_MULTIPORT_SOURCE:
- printf("--sports ");
- break;
-
- case IPT_MULTIPORT_DESTINATION:
- printf("--dports ");
- break;
-
- case IPT_MULTIPORT_EITHER:
- printf("--ports ");
- break;
- }
-
- if (multiinfo->invert)
- printf("! ");
-
- for (i=0; i < multiinfo->count; i++) {
- printf("%s", i ? "," : "");
- print_port(multiinfo->ports[i], ip->proto, 1);
- if (multiinfo->pflags[i]) {
- printf(":");
- print_port(multiinfo->ports[++i], ip->proto, 1);
- }
- }
- printf(" ");
-}
-
-static struct iptables_match multiport = {
- .next = NULL,
- .name = "multiport",
- .revision = 0,
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_multiport)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-static struct iptables_match multiport_v1 = {
- .next = NULL,
- .name = "multiport",
- .version = IPTABLES_VERSION,
- .revision = 1,
- .size = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_multiport_v1)),
- .help = &help_v1,
- .init = &init,
- .parse = &parse_v1,
- .final_check = &final_check,
- .print = &print_v1,
- .save = &save_v1,
- .extra_opts = opts
-};
-
-void
-ipt_multiport_init(void)
-{
- register_match(&multiport);
- register_match(&multiport_v1);
-}
diff --git a/extensions/libipt_multiport.man b/extensions/libipt_multiport.man
deleted file mode 100644
index ba760e9..0000000
--- a/extensions/libipt_multiport.man
+++ /dev/null
@@ -1,20 +0,0 @@
-This module matches a set of source or destination ports. Up to 15
-ports can be specified. A port range (port:port) counts as two
-ports. It can only be used in conjunction with
-.B "-p tcp"
-or
-.BR "-p udp" .
-.TP
-.BR "--source-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport:port\fP...]]"
-Match if the source port is one of the given ports. The flag
-.B --sports
-is a convenient alias for this option.
-.TP
-.BR "--destination-ports " "\fI[!] port\fP[,\fIport\fP[,\fIport:port\fP...]]"
-Match if the destination port is one of the given ports. The flag
-.B --dports
-is a convenient alias for this option.
-.TP
-.BR "--ports " "\fI[!] port\fP[,\fIport\fP[,\fIport:port\fP...]]"
-Match if either the source or destination ports are equal to one of
-the given ports.
diff --git a/extensions/libipt_owner.c b/extensions/libipt_owner.c
deleted file mode 100644
index 89e1a7c..0000000
--- a/extensions/libipt_owner.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Shared library add-on to iptables to add OWNER matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_owner.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-#ifdef IPT_OWNER_COMM
- printf(
-"OWNER match v%s options:\n"
-"[!] --uid-owner userid Match local uid\n"
-"[!] --gid-owner groupid Match local gid\n"
-"[!] --pid-owner processid Match local pid\n"
-"[!] --sid-owner sessionid Match local sid\n"
-"[!] --cmd-owner name Match local command name\n"
-"NOTE: pid, sid and command matching are broken on SMP\n"
-"\n",
-IPTABLES_VERSION);
-#else
- printf(
-"OWNER match v%s options:\n"
-"[!] --uid-owner userid Match local uid\n"
-"[!] --gid-owner groupid Match local gid\n"
-"[!] --pid-owner processid Match local pid\n"
-"[!] --sid-owner sessionid Match local sid\n"
-"NOTE: pid and sid matching are broken on SMP\n"
-"\n",
-IPTABLES_VERSION);
-#endif /* IPT_OWNER_COMM */
-}
-
-static struct option opts[] = {
- { "uid-owner", 1, 0, '1' },
- { "gid-owner", 1, 0, '2' },
- { "pid-owner", 1, 0, '3' },
- { "sid-owner", 1, 0, '4' },
-#ifdef IPT_OWNER_COMM
- { "cmd-owner", 1, 0, '5' },
-#endif
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_owner_info *ownerinfo = (struct ipt_owner_info *)(*match)->data;
-
- switch (c) {
- char *end;
- struct passwd *pwd;
- struct group *grp;
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
- if ((pwd = getpwnam(optarg)))
- ownerinfo->uid = pwd->pw_uid;
- else {
- ownerinfo->uid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg);
- }
- if (invert)
- ownerinfo->invert |= IPT_OWNER_UID;
- ownerinfo->match |= IPT_OWNER_UID;
- *flags = 1;
- break;
-
- case '2':
- check_inverse(optarg, &invert, &optind, 0);
- if ((grp = getgrnam(optarg)))
- ownerinfo->gid = grp->gr_gid;
- else {
- ownerinfo->gid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg);
- }
- if (invert)
- ownerinfo->invert |= IPT_OWNER_GID;
- ownerinfo->match |= IPT_OWNER_GID;
- *flags = 1;
- break;
-
- case '3':
- check_inverse(optarg, &invert, &optind, 0);
- ownerinfo->pid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg);
- if (invert)
- ownerinfo->invert |= IPT_OWNER_PID;
- ownerinfo->match |= IPT_OWNER_PID;
- *flags = 1;
- break;
-
- case '4':
- check_inverse(optarg, &invert, &optind, 0);
- ownerinfo->sid = strtoul(optarg, &end, 0);
- if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg);
- if (invert)
- ownerinfo->invert |= IPT_OWNER_SID;
- ownerinfo->match |= IPT_OWNER_SID;
- *flags = 1;
- break;
-
-#ifdef IPT_OWNER_COMM
- case '5':
- check_inverse(optarg, &invert, &optind, 0);
- if(strlen(optarg) > sizeof(ownerinfo->comm))
- exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %u characters", optarg, (unsigned int)sizeof(ownerinfo->comm));
-
- strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm));
- ownerinfo->comm[sizeof(ownerinfo->comm)-1] = '\0';
-
- if (invert)
- ownerinfo->invert |= IPT_OWNER_COMM;
- ownerinfo->match |= IPT_OWNER_COMM;
- *flags = 1;
- break;
-#endif
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-print_item(struct ipt_owner_info *info, u_int8_t flag, int numeric, char *label)
-{
- if(info->match & flag) {
-
- if (info->invert & flag)
- printf("! ");
-
- printf(label);
-
- switch(info->match & flag) {
- case IPT_OWNER_UID:
- if(!numeric) {
- struct passwd *pwd = getpwuid(info->uid);
-
- if(pwd && pwd->pw_name) {
- printf("%s ", pwd->pw_name);
- break;
- }
- /* FALLTHROUGH */
- }
- printf("%u ", info->uid);
- break;
- case IPT_OWNER_GID:
- if(!numeric) {
- struct group *grp = getgrgid(info->gid);
-
- if(grp && grp->gr_name) {
- printf("%s ", grp->gr_name);
- break;
- }
- /* FALLTHROUGH */
- }
- printf("%u ", info->gid);
- break;
- case IPT_OWNER_PID:
- printf("%u ", info->pid);
- break;
- case IPT_OWNER_SID:
- printf("%u ", info->sid);
- break;
-#ifdef IPT_OWNER_COMM
- case IPT_OWNER_COMM:
- printf("%.*s ", (int)sizeof(info->comm), info->comm);
- break;
-#endif
- default:
- break;
- }
- }
-}
-
-/* Final check; must have specified --own. */
-static void
-final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "OWNER match: You must specify one or more options");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_owner_info *info = (struct ipt_owner_info *)match->data;
-
- print_item(info, IPT_OWNER_UID, numeric, "OWNER UID match ");
- print_item(info, IPT_OWNER_GID, numeric, "OWNER GID match ");
- print_item(info, IPT_OWNER_PID, numeric, "OWNER PID match ");
- print_item(info, IPT_OWNER_SID, numeric, "OWNER SID match ");
-#ifdef IPT_OWNER_COMM
- print_item(info, IPT_OWNER_COMM, numeric, "OWNER CMD match ");
-#endif
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_owner_info *info = (struct ipt_owner_info *)match->data;
-
- print_item(info, IPT_OWNER_UID, 0, "--uid-owner ");
- print_item(info, IPT_OWNER_GID, 0, "--gid-owner ");
- print_item(info, IPT_OWNER_PID, 0, "--pid-owner ");
- print_item(info, IPT_OWNER_SID, 0, "--sid-owner ");
-#ifdef IPT_OWNER_COMM
- print_item(info, IPT_OWNER_COMM, 0, "--cmd-owner ");
-#endif
-}
-
-static struct iptables_match owner = {
- .next = NULL,
- .name = "owner",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_owner_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_owner_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_owner_init(void)
-{
- register_match(&owner);
-}
diff --git a/extensions/libipt_owner.man b/extensions/libipt_owner.man
deleted file mode 100644
index b635e7d..0000000
--- a/extensions/libipt_owner.man
+++ /dev/null
@@ -1,28 +0,0 @@
-This module attempts to match various characteristics of the packet
-creator, for locally-generated packets. It is only valid in the
-.B OUTPUT
-chain, and even this some packets (such as ICMP ping responses) may
-have no owner, and hence never match.
-.TP
-.BI "--uid-owner " "userid"
-Matches if the packet was created by a process with the given
-effective user id.
-.TP
-.BI "--gid-owner " "groupid"
-Matches if the packet was created by a process with the given
-effective group id.
-.TP
-.BI "--pid-owner " "processid"
-Matches if the packet was created by a process with the given
-process id.
-.TP
-.BI "--sid-owner " "sessionid"
-Matches if the packet was created by a process in the given session
-group.
-.TP
-.BI "--cmd-owner " "name"
-Matches if the packet was created by a process with the given command name.
-(this option is present only if iptables was compiled under a kernel
-supporting this feature)
-.TP
-.B NOTE: pid, sid and command matching are broken on SMP
diff --git a/extensions/libipt_physdev.c b/extensions/libipt_physdev.c
deleted file mode 100644
index ab87cf8..0000000
--- a/extensions/libipt_physdev.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/* Shared library add-on to iptables to add bridge port matching support. */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <ctype.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_physdev.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-
-static void
-help(void)
-{
- printf(
-"physdev v%s options:\n"
-" --physdev-in [!] input name[+] bridge port name ([+] for wildcard)\n"
-" --physdev-out [!] output name[+] bridge port name ([+] for wildcard)\n"
-" [!] --physdev-is-in arrived on a bridge device\n"
-" [!] --physdev-is-out will leave on a bridge device\n"
-" [!] --physdev-is-bridged it's a bridged packet\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "physdev-in", 1, 0, '1' },
- { "physdev-out", 1, 0, '2' },
- { "physdev-is-in", 0, 0, '3' },
- { "physdev-is-out", 0, 0, '4' },
- { "physdev-is-bridged", 0, 0, '5' },
- {0}
-};
-
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_physdev_info *info =
- (struct ipt_physdev_info*)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & IPT_PHYSDEV_OP_IN)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- parse_interface(argv[optind-1], info->physindev,
- (unsigned char *)info->in_mask);
- if (invert)
- info->invert |= IPT_PHYSDEV_OP_IN;
- info->bitmask |= IPT_PHYSDEV_OP_IN;
- *flags |= IPT_PHYSDEV_OP_IN;
- break;
-
- case '2':
- if (*flags & IPT_PHYSDEV_OP_OUT)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- parse_interface(argv[optind-1], info->physoutdev,
- (unsigned char *)info->out_mask);
- if (invert)
- info->invert |= IPT_PHYSDEV_OP_OUT;
- info->bitmask |= IPT_PHYSDEV_OP_OUT;
- *flags |= IPT_PHYSDEV_OP_OUT;
- break;
-
- case '3':
- if (*flags & IPT_PHYSDEV_OP_ISIN)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- info->bitmask |= IPT_PHYSDEV_OP_ISIN;
- if (invert)
- info->invert |= IPT_PHYSDEV_OP_ISIN;
- *flags |= IPT_PHYSDEV_OP_ISIN;
- break;
-
- case '4':
- if (*flags & IPT_PHYSDEV_OP_ISOUT)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- info->bitmask |= IPT_PHYSDEV_OP_ISOUT;
- if (invert)
- info->invert |= IPT_PHYSDEV_OP_ISOUT;
- *flags |= IPT_PHYSDEV_OP_ISOUT;
- break;
-
- case '5':
- if (*flags & IPT_PHYSDEV_OP_BRIDGED)
- goto multiple_use;
- check_inverse(optarg, &invert, &optind, 0);
- if (invert)
- info->invert |= IPT_PHYSDEV_OP_BRIDGED;
- *flags |= IPT_PHYSDEV_OP_BRIDGED;
- info->bitmask |= IPT_PHYSDEV_OP_BRIDGED;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-multiple_use:
- exit_error(PARAMETER_PROBLEM,
- "multiple use of the same physdev option is not allowed");
-
-}
-
-static void final_check(unsigned int flags)
-{
- if (flags == 0)
- exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
-}
-
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_physdev_info *info =
- (struct ipt_physdev_info*)match->data;
-
- printf("PHYSDEV match");
- if (info->bitmask & IPT_PHYSDEV_OP_ISIN)
- printf("%s --physdev-is-in",
- info->invert & IPT_PHYSDEV_OP_ISIN ? " !":"");
- if (info->bitmask & IPT_PHYSDEV_OP_IN)
- printf("%s --physdev-in %s",
- (info->invert & IPT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
-
- if (info->bitmask & IPT_PHYSDEV_OP_ISOUT)
- printf("%s --physdev-is-out",
- info->invert & IPT_PHYSDEV_OP_ISOUT ? " !":"");
- if (info->bitmask & IPT_PHYSDEV_OP_OUT)
- printf("%s --physdev-out %s",
- (info->invert & IPT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
- if (info->bitmask & IPT_PHYSDEV_OP_BRIDGED)
- printf("%s --physdev-is-bridged",
- info->invert & IPT_PHYSDEV_OP_BRIDGED ? " !":"");
- printf(" ");
-}
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_physdev_info *info =
- (struct ipt_physdev_info*)match->data;
-
- if (info->bitmask & IPT_PHYSDEV_OP_ISIN)
- printf("%s --physdev-is-in",
- info->invert & IPT_PHYSDEV_OP_ISIN ? " !":"");
- if (info->bitmask & IPT_PHYSDEV_OP_IN)
- printf("%s --physdev-in %s",
- (info->invert & IPT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
-
- if (info->bitmask & IPT_PHYSDEV_OP_ISOUT)
- printf("%s --physdev-is-out",
- info->invert & IPT_PHYSDEV_OP_ISOUT ? " !":"");
- if (info->bitmask & IPT_PHYSDEV_OP_OUT)
- printf("%s --physdev-out %s",
- (info->invert & IPT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
- if (info->bitmask & IPT_PHYSDEV_OP_BRIDGED)
- printf("%s --physdev-is-bridged",
- info->invert & IPT_PHYSDEV_OP_BRIDGED ? " !":"");
- printf(" ");
-}
-
-static struct iptables_match physdev = {
- .next = NULL,
- .name = "physdev",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_physdev_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_physdev_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_physdev_init(void)
-{
- register_match(&physdev);
-}
diff --git a/extensions/libipt_physdev.man b/extensions/libipt_physdev.man
deleted file mode 100644
index 1e635fc..0000000
--- a/extensions/libipt_physdev.man
+++ /dev/null
@@ -1,42 +0,0 @@
-This module matches on the bridge port input and output devices enslaved
-to a bridge device. This module is a part of the infrastructure that enables
-a transparent bridging IP firewall and is only useful for kernel versions
-above version 2.5.44.
-.TP
-.BR --physdev-in " [!] \fIname\fP"
-Name of a bridge port via which a packet is received (only for
-packets entering the
-.BR INPUT ,
-.B FORWARD
-and
-.B PREROUTING
-chains). If the interface name ends in a "+", then any
-interface which begins with this name will match. If the packet didn't arrive
-through a bridge device, this packet won't match this option, unless '!' is used.
-.TP
-.BR --physdev-out " [!] \fIname\fP"
-Name of a bridge port via which a packet is going to be sent (for packets
-entering the
-.BR FORWARD ,
-.B OUTPUT
-and
-.B POSTROUTING
-chains). If the interface name ends in a "+", then any
-interface which begins with this name will match. Note that in the
-.BR nat " and " mangle
-.B OUTPUT
-chains one cannot match on the bridge output port, however one can in the
-.B "filter OUTPUT"
-chain. If the packet won't leave by a bridge device or it is yet unknown what
-the output device will be, then the packet won't match this option, unless
-'!' is used.
-.TP
-.RB "[!] " --physdev-is-in
-Matches if the packet has entered through a bridge interface.
-.TP
-.RB "[!] " --physdev-is-out
-Matches if the packet will leave through a bridge interface.
-.TP
-.RB "[!] " --physdev-is-bridged
-Matches if the packet is being bridged and therefore is not being routed.
-This is only useful in the FORWARD and POSTROUTING chains.
diff --git a/extensions/libipt_pkttype.c b/extensions/libipt_pkttype.c
deleted file mode 100644
index 7fa1c99..0000000
--- a/extensions/libipt_pkttype.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Shared library add-on to iptables to match
- * packets by their type (BROADCAST, UNICAST, MULTICAST).
- *
- * Michal Ludvig <michal@logix.cz>
- */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-#include <iptables.h>
-#include <linux/if_packet.h>
-#include <linux/netfilter_ipv4/ipt_pkttype.h>
-
-#define PKTTYPE_VERSION "0.1"
-
-struct pkttypes {
- const char *name;
- unsigned char pkttype;
- unsigned char printhelp;
- const char *help;
-};
-
-static const struct pkttypes supported_types[] = {
- {"unicast", PACKET_HOST, 1, "to us"},
- {"broadcast", PACKET_BROADCAST, 1, "to all"},
- {"multicast", PACKET_MULTICAST, 1, "to group"},
-/*
- {"otherhost", PACKET_OTHERHOST, 1, "to someone else"},
- {"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"},
-*/
- /* aliases */
- {"bcast", PACKET_BROADCAST, 0, NULL},
- {"mcast", PACKET_MULTICAST, 0, NULL},
- {"host", PACKET_HOST, 0, NULL}
-};
-
-static void print_types()
-{
- unsigned int i;
-
- printf("Valid packet types:\n");
- for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
- {
- if(supported_types[i].printhelp == 1)
- printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help);
- }
- printf("\n");
-}
-
-/* Function which prints out usage message. */
-static void help(void)
-{
- printf(
-"pkt_type v%s options:\n"
-" --pkt-type [!] packettype\tmatch packet type\n"
-"\n", PKTTYPE_VERSION);
- print_types();
-}
-
-static struct option opts[] = {
- {"pkt-type", 1, 0, '1'},
- {0}
-};
-
-static void parse_pkttype(const char *pkttype, struct ipt_pkttype_info *info)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
- {
- if(strcasecmp(pkttype, supported_types[i].name)==0)
- {
- info->pkttype=supported_types[i].pkttype;
- return;
- }
- }
-
- exit_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)(*match)->data;
-
- switch(c)
- {
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
- parse_pkttype(argv[optind-1], info);
- if(invert)
- info->invert=1;
- *flags=1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, "You must specify `--pkt-type'");
-}
-
-static void print_pkttype(struct ipt_pkttype_info *info)
-{
- unsigned int i;
-
- for (i = 0; i < sizeof(supported_types)/sizeof(struct pkttypes); i++)
- {
- if(supported_types[i].pkttype==info->pkttype)
- {
- printf("%s ", supported_types[i].name);
- return;
- }
- }
-
- printf("%d ", info->pkttype); /* in case we didn't find an entry in named-packtes */
-}
-
-static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
-{
- struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
-
- printf("PKTTYPE %s= ", info->invert?"!":"");
- print_pkttype(info);
-}
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_pkttype_info *info = (struct ipt_pkttype_info *)match->data;
-
- printf("--pkt-type %s", info->invert?"! ":"");
- print_pkttype(info);
-}
-
-static struct iptables_match pkttype = {
- .next = NULL,
- .name = "pkttype",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_pkttype_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_pkttype_init(void)
-{
- register_match(&pkttype);
-}
diff --git a/extensions/libipt_pkttype.man b/extensions/libipt_pkttype.man
deleted file mode 100644
index b52810b..0000000
--- a/extensions/libipt_pkttype.man
+++ /dev/null
@@ -1,3 +0,0 @@
-This module matches the link-layer packet type.
-.TP
-.BI "--pkt-type " "[\fIunicast\fP|\fIbroadcast\fP|\fImulticast\fP]"
diff --git a/extensions/libipt_policy.c b/extensions/libipt_policy.c
deleted file mode 100644
index cd8b43d..0000000
--- a/extensions/libipt_policy.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/* Shared library add-on to iptables to add policy support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <syslog.h>
-#include <getopt.h>
-#include <netdb.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <iptables.h>
-
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include "../include/linux/netfilter_ipv4/ipt_policy.h"
-
-/*
- * HACK: global pointer to current matchinfo for making
- * final checks and adjustments in final_check.
- */
-static struct ipt_policy_info *policy_info;
-
-static void help(void)
-{
- printf(
-"policy v%s options:\n"
-" --dir in|out match policy applied during decapsulation/\n"
-" policy to be applied during encapsulation\n"
-" --pol none|ipsec match policy\n"
-" --strict match entire policy instead of single element\n"
-" at any position\n"
-"[!] --reqid reqid match reqid\n"
-"[!] --spi spi match SPI\n"
-"[!] --proto proto match protocol (ah/esp/ipcomp)\n"
-"[!] --mode mode match mode (transport/tunnel)\n"
-"[!] --tunnel-src addr/mask match tunnel source\n"
-"[!] --tunnel-dst addr/mask match tunnel destination\n"
-" --next begin next element in policy\n",
- IPTABLES_VERSION);
-}
-
-static struct option opts[] =
-{
- {
- .name = "dir",
- .has_arg = 1,
- .val = '1',
- },
- {
- .name = "pol",
- .has_arg = 1,
- .val = '2',
- },
- {
- .name = "strict",
- .val = '3'
- },
- {
- .name = "reqid",
- .has_arg = 1,
- .val = '4',
- },
- {
- .name = "spi",
- .has_arg = 1,
- .val = '5'
- },
- {
- .name = "tunnel-src",
- .has_arg = 1,
- .val = '6'
- },
- {
- .name = "tunnel-dst",
- .has_arg = 1,
- .val = '7'
- },
- {
- .name = "proto",
- .has_arg = 1,
- .val = '8'
- },
- {
- .name = "mode",
- .has_arg = 1,
- .val = '9'
- },
- {
- .name = "next",
- .val = 'a'
- },
- { }
-};
-
-static void init(struct ipt_entry_match *m, unsigned int *nfcache)
-{
- *nfcache |= NFC_UNKNOWN;
-}
-
-static int parse_direction(char *s)
-{
- if (strcmp(s, "in") == 0)
- return IPT_POLICY_MATCH_IN;
- if (strcmp(s, "out") == 0)
- return IPT_POLICY_MATCH_OUT;
- exit_error(PARAMETER_PROBLEM, "policy_match: invalid dir `%s'", s);
-}
-
-static int parse_policy(char *s)
-{
- if (strcmp(s, "none") == 0)
- return IPT_POLICY_MATCH_NONE;
- if (strcmp(s, "ipsec") == 0)
- return 0;
- exit_error(PARAMETER_PROBLEM, "policy match: invalid policy `%s'", s);
-}
-
-static int parse_mode(char *s)
-{
- if (strcmp(s, "transport") == 0)
- return IPT_POLICY_MODE_TRANSPORT;
- if (strcmp(s, "tunnel") == 0)
- return IPT_POLICY_MODE_TUNNEL;
- exit_error(PARAMETER_PROBLEM, "policy match: invalid mode `%s'", s);
-}
-
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_policy_info *info = (void *)(*match)->data;
- struct ipt_policy_elem *e = &info->pol[info->len];
- struct in_addr *addr = NULL, mask;
- unsigned int naddr = 0;
- int mode;
-
- check_inverse(optarg, &invert, &optind, 0);
-
- switch (c) {
- case '1':
- if (info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT))
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --dir option");
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --dir option");
-
- info->flags |= parse_direction(argv[optind-1]);
- break;
- case '2':
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --policy option");
-
- info->flags |= parse_policy(argv[optind-1]);
- break;
- case '3':
- if (info->flags & IPT_POLICY_MATCH_STRICT)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --strict option");
-
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --strict option");
-
- info->flags |= IPT_POLICY_MATCH_STRICT;
- break;
- case '4':
- if (e->match.reqid)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --reqid option");
-
- e->match.reqid = 1;
- e->invert.reqid = invert;
- e->reqid = strtol(argv[optind-1], NULL, 10);
- break;
- case '5':
- if (e->match.spi)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --spi option");
-
- e->match.spi = 1;
- e->invert.spi = invert;
- e->spi = strtol(argv[optind-1], NULL, 0x10);
- break;
- case '6':
- if (e->match.saddr)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --tunnel-src option");
-
- parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
- if (naddr > 1)
- exit_error(PARAMETER_PROBLEM,
- "policy match: name resolves to multiple IPs");
-
- e->match.saddr = 1;
- e->invert.saddr = invert;
- e->saddr.a4 = addr[0];
- e->smask.a4 = mask;
- break;
- case '7':
- if (e->match.daddr)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --tunnel-dst option");
-
- parse_hostnetworkmask(argv[optind-1], &addr, &mask, &naddr);
- if (naddr > 1)
- exit_error(PARAMETER_PROBLEM,
- "policy match: name resolves to multiple IPs");
-
- e->match.daddr = 1;
- e->invert.daddr = invert;
- e->daddr.a4 = addr[0];
- e->dmask.a4 = mask;
- break;
- case '8':
- if (e->match.proto)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --proto option");
-
- e->proto = parse_protocol(argv[optind-1]);
- if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
- e->proto != IPPROTO_COMP)
- exit_error(PARAMETER_PROBLEM,
- "policy match: protocol must ah/esp/ipcomp");
- e->match.proto = 1;
- e->invert.proto = invert;
- break;
- case '9':
- if (e->match.mode)
- exit_error(PARAMETER_PROBLEM,
- "policy match: double --mode option");
-
- mode = parse_mode(argv[optind-1]);
- e->match.mode = 1;
- e->invert.mode = invert;
- e->mode = mode;
- break;
- case 'a':
- if (invert)
- exit_error(PARAMETER_PROBLEM,
- "policy match: can't invert --next option");
-
- if (++info->len == IPT_POLICY_MAX_ELEM)
- exit_error(PARAMETER_PROBLEM,
- "policy match: maximum policy depth reached");
- break;
- default:
- return 0;
- }
-
- policy_info = info;
- return 1;
-}
-
-static void final_check(unsigned int flags)
-{
- struct ipt_policy_info *info = policy_info;
- struct ipt_policy_elem *e;
- int i;
-
- if (info == NULL)
- exit_error(PARAMETER_PROBLEM,
- "policy match: no parameters given");
-
- if (!(info->flags & (IPT_POLICY_MATCH_IN|IPT_POLICY_MATCH_OUT)))
- exit_error(PARAMETER_PROBLEM,
- "policy match: neither --in nor --out specified");
-
- if (info->flags & IPT_POLICY_MATCH_NONE) {
- if (info->flags & IPT_POLICY_MATCH_STRICT)
- exit_error(PARAMETER_PROBLEM,
- "policy match: policy none but --strict given");
-
- if (info->len != 0)
- exit_error(PARAMETER_PROBLEM,
- "policy match: policy none but policy given");
- } else
- info->len++; /* increase len by 1, no --next after last element */
-
- if (!(info->flags & IPT_POLICY_MATCH_STRICT) && info->len > 1)
- exit_error(PARAMETER_PROBLEM,
- "policy match: multiple elements but no --strict");
-
- for (i = 0; i < info->len; i++) {
- e = &info->pol[i];
-
- if (info->flags & IPT_POLICY_MATCH_STRICT &&
- !(e->match.reqid || e->match.spi || e->match.saddr ||
- e->match.daddr || e->match.proto || e->match.mode))
- exit_error(PARAMETER_PROBLEM,
- "policy match: empty policy element");
-
- if ((e->match.saddr || e->match.daddr)
- && ((e->mode == IPT_POLICY_MODE_TUNNEL && e->invert.mode) ||
- (e->mode == IPT_POLICY_MODE_TRANSPORT && !e->invert.mode)))
- exit_error(PARAMETER_PROBLEM,
- "policy match: --tunnel-src/--tunnel-dst "
- "is only valid in tunnel mode");
- }
-}
-
-static void print_mode(char *prefix, u_int8_t mode, int numeric)
-{
- printf("%smode ", prefix);
-
- switch (mode) {
- case IPT_POLICY_MODE_TRANSPORT:
- printf("transport ");
- break;
- case IPT_POLICY_MODE_TUNNEL:
- printf("tunnel ");
- break;
- default:
- printf("??? ");
- break;
- }
-}
-
-static void print_proto(char *prefix, u_int8_t proto, int numeric)
-{
- struct protoent *p = NULL;
-
- printf("%sproto ", prefix);
- if (!numeric)
- p = getprotobynumber(proto);
- if (p != NULL)
- printf("%s ", p->p_name);
- else
- printf("%u ", proto);
-}
-
-#define PRINT_INVERT(x) \
-do { \
- if (x) \
- printf("! "); \
-} while(0)
-
-static void print_entry(char *prefix, const struct ipt_policy_elem *e,
- int numeric)
-{
- if (e->match.reqid) {
- PRINT_INVERT(e->invert.reqid);
- printf("%sreqid %u ", prefix, e->reqid);
- }
- if (e->match.spi) {
- PRINT_INVERT(e->invert.spi);
- printf("%sspi 0x%x ", prefix, e->spi);
- }
- if (e->match.proto) {
- PRINT_INVERT(e->invert.proto);
- print_proto(prefix, e->proto, numeric);
- }
- if (e->match.mode) {
- PRINT_INVERT(e->invert.mode);
- print_mode(prefix, e->mode, numeric);
- }
- if (e->match.daddr) {
- PRINT_INVERT(e->invert.daddr);
- printf("%stunnel-dst %s%s ", prefix,
- addr_to_dotted((struct in_addr *)&e->daddr),
- mask_to_dotted((struct in_addr *)&e->dmask));
- }
- if (e->match.saddr) {
- PRINT_INVERT(e->invert.saddr);
- printf("%stunnel-src %s%s ", prefix,
- addr_to_dotted((struct in_addr *)&e->saddr),
- mask_to_dotted((struct in_addr *)&e->smask));
- }
-}
-
-static void print_flags(char *prefix, const struct ipt_policy_info *info)
-{
- if (info->flags & IPT_POLICY_MATCH_IN)
- printf("%sdir in ", prefix);
- else
- printf("%sdir out ", prefix);
-
- if (info->flags & IPT_POLICY_MATCH_NONE)
- printf("%spol none ", prefix);
- else
- printf("%spol ipsec ", prefix);
-
- if (info->flags & IPT_POLICY_MATCH_STRICT)
- printf("%sstrict ", prefix);
-}
-
-static void print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_policy_info *info = (void *)match->data;
- unsigned int i;
-
- printf("policy match ");
- print_flags("", info);
- for (i = 0; i < info->len; i++) {
- if (info->len > 1)
- printf("[%u] ", i);
- print_entry("", &info->pol[i], numeric);
- }
-}
-
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- const struct ipt_policy_info *info = (void *)match->data;
- unsigned int i;
-
- print_flags("--", info);
- for (i = 0; i < info->len; i++) {
- print_entry("--", &info->pol[i], 0);
- if (i + 1 < info->len)
- printf("--next ");
- }
-}
-
-struct iptables_match policy = {
- .name = "policy",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_policy_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_policy_info)),
- .help = help,
- .init = init,
- .parse = parse,
- .final_check = final_check,
- .print = print,
- .save = save,
- .extra_opts = opts
-};
-
-void ipt_policy_init(void)
-{
- register_match(&policy);
-}
diff --git a/extensions/libipt_policy.man b/extensions/libipt_policy.man
deleted file mode 100644
index eed163e..0000000
--- a/extensions/libipt_policy.man
+++ /dev/null
@@ -1,48 +0,0 @@
-This modules matches the policy used by IPsec for handling a packet.
-.TP
-.BI "--dir " "in|out"
-Used to select whether to match the policy used for decapsulation or the
-policy that will be used for encapsulation.
-.B in
-is valid in the
-.B PREROUTING, INPUT and FORWARD
-chains,
-.B out
-is valid in the
-.B POSTROUTING, OUTPUT and FORWARD
-chains.
-.TP
-.BI "--pol " "none|ipsec"
-Matches if the packet is subject to IPsec processing.
-.TP
-.BI "--strict"
-Selects whether to match the exact policy or match if any rule of
-the policy matches the given policy.
-.TP
-.BI "--reqid " "id"
-Matches the reqid of the policy rule. The reqid can be specified with
-.B setkey(8)
-using
-.B unique:id
-as level.
-.TP
-.BI "--spi " "spi"
-Matches the SPI of the SA.
-.TP
-.BI "--proto " "ah|esp|ipcomp"
-Matches the encapsulation protocol.
-.TP
-.BI "--mode " "tunnel|transport"
-Matches the encapsulation mode.
-.TP
-.BI "--tunnel-src " "addr[/mask]"
-Matches the source end-point address of a tunnel mode SA.
-Only valid with --mode tunnel.
-.TP
-.BI "--tunnel-dst " "addr[/mask]"
-Matches the destination end-point address of a tunnel mode SA.
-Only valid with --mode tunnel.
-.TP
-.BI "--next"
-Start the next element in the policy specification. Can only be used with
---strict
diff --git a/extensions/libipt_quota.c b/extensions/libipt_quota.c
deleted file mode 100644
index 68e3672..0000000
--- a/extensions/libipt_quota.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Shared library add-on to iptables to add quota support
- *
- * Sam Johnston <samj@samj.net>
- */
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-
-#include <linux/netfilter/xt_quota.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-static struct option opts[] = {
- {"quota", 1, 0, '1'},
- {0}
-};
-
-/* print usage */
-static void
-help(void)
-{
- printf("quota options:\n"
- " --quota quota quota (bytes)\n" "\n");
-}
-
-/* print matchinfo */
-static void
-print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric)
-{
- struct xt_quota_info *q = (struct xt_quota_info *) match->data;
- printf("quota: %llu bytes", (unsigned long long) q->quota);
-}
-
-/* save matchinfo */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct xt_quota_info *q = (struct xt_quota_info *) match->data;
- printf("--quota %llu ", (unsigned long long) q->quota);
-}
-
-/* parse quota option */
-static int
-parse_quota(const char *s, u_int64_t * quota)
-{
- *quota = strtoull(s, (char **) NULL, 10);
-
-#ifdef DEBUG_IPT_QUOTA
- printf("Quota: %llu\n", *quota);
-#endif
-
- if (*quota == -1)
- exit_error(PARAMETER_PROBLEM, "quota invalid: '%s'\n", s);
- else
- return 1;
-}
-
-/* parse all options, returning true if we found any for us */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache, struct ipt_entry_match **match)
-{
- struct xt_quota_info *info = (struct xt_quota_info *) (*match)->data;
-
- switch (c) {
- case '1':
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM, "quota: unexpected '!'");
- if (!parse_quota(optarg, &info->quota))
- exit_error(PARAMETER_PROBLEM,
- "bad quota: '%s'", optarg);
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-/* no final check */
-static void
-final_check(unsigned int flags)
-{
-}
-
-struct iptables_match quota = {
- .next = NULL,
- .name = "quota",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof (struct xt_quota_info)),
- .userspacesize = offsetof(struct xt_quota_info, quota),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void
-ipt_quota_init(void)
-{
- register_match(&quota);
-}
diff --git a/extensions/libipt_realm.c b/extensions/libipt_realm.c
index 966d76e..203d407 100644
--- a/extensions/libipt_realm.c
+++ b/extensions/libipt_realm.c
@@ -11,23 +11,20 @@
#else
#include <linux/if_ether.h>
#endif
-#include <iptables.h>
+#include <xtables.h>
#include <linux/netfilter_ipv4/ipt_realm.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+static void realm_help(void)
{
printf(
-"realm v%s options:\n"
-" --realm [!] value[/mask]\n"
-" Match realm\n"
-"\n", IPTABLES_VERSION);
+"realm match options:\n"
+"[!] --realm value[/mask]\n"
+" Match realm\n");
}
-static struct option opts[] = {
- { "realm", 1, 0, '1' },
- {0}
+static const struct option realm_opts[] = {
+ { "realm", 1, NULL, '1' },
+ { .name = NULL }
};
struct realmname {
@@ -38,12 +35,11 @@ struct realmname {
};
/* array of realms from /etc/iproute2/rt_realms */
-static struct realmname *realms = NULL;
+static struct realmname *realms;
/* 1 if loading failed */
-static int rdberr = 0;
-
+static int rdberr;
-void load_realms()
+static void load_realms(void)
{
const char* rfnm = "/etc/iproute2/rt_realms";
char buf[512];
@@ -89,14 +85,14 @@ void load_realms()
continue;
/* found valid data */
- newnm = (struct realmname*)malloc(sizeof(struct realmname));
+ newnm = malloc(sizeof(struct realmname));
if (newnm == NULL) {
perror("libipt_realm: malloc failed");
exit(1);
}
newnm->id = id;
newnm->len = nxt - cur;
- newnm->name = (char*)malloc(newnm->len + 1);
+ newnm->name = malloc(newnm->len + 1);
if (newnm->name == NULL) {
perror("libipt_realm: malloc failed");
exit(1);
@@ -116,7 +112,7 @@ void load_realms()
}
/* get realm id for name, -1 if error/not found */
-int realm_name2id(const char* name)
+static int realm_name2id(const char* name)
{
struct realmname* cur;
@@ -134,7 +130,7 @@ int realm_name2id(const char* name)
}
/* get realm name for id, NULL if error/not found */
-const char* realm_id2name(int id)
+static const char *realm_id2name(int id)
{
struct realmname* cur;
@@ -151,14 +147,8 @@ const char* realm_id2name(int id)
return NULL;
}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+static int realm_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ipt_realm_info *realminfo = (struct ipt_realm_info *)(*match)->data;
int id;
@@ -166,8 +156,8 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
char *end;
case '1':
- check_inverse(argv[optind-1], &invert, &optind, 0);
- end = optarg = argv[optind-1];
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ end = optarg = optarg;
realminfo->id = strtoul(optarg, &end, 0);
if (end != optarg && (*end == '/' || *end == '\0')) {
if (*end == '/')
@@ -175,14 +165,14 @@ parse(int c, char **argv, int invert, unsigned int *flags,
else
realminfo->mask = 0xffffffff;
if (*end != '\0' || end == optarg)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Bad realm value `%s'", optarg);
} else {
id = realm_name2id(optarg);
if (id == -1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Realm `%s' not found", optarg);
- realminfo->id = (u_int32_t)id;
+ realminfo->id = id;
realminfo->mask = 0xffffffff;
}
if (invert)
@@ -213,13 +203,10 @@ print_realm(unsigned long id, unsigned long mask, int numeric)
}
}
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
+static void realm_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
- struct ipt_realm_info *ri = (struct ipt_realm_info *) match->data;
+ const struct ipt_realm_info *ri = (const void *)match->data;
if (ri->invert)
printf("! ");
@@ -228,12 +215,9 @@ print(const struct ipt_ip *ip,
print_realm(ri->id, ri->mask, numeric);
}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void realm_save(const void *ip, const struct xt_entry_match *match)
{
- struct ipt_realm_info *ri = (struct ipt_realm_info *) match->data;
+ const struct ipt_realm_info *ri = (const void *)match->data;
if (ri->invert)
printf("! ");
@@ -242,31 +226,28 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
print_realm(ri->id, ri->mask, 0);
}
-/* Final check; must have specified --mark. */
-static void
-final_check(unsigned int flags)
+static void realm_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"realm match: You must specify `--realm'");
}
-static struct iptables_match realm = { NULL,
+static struct xtables_match realm_mt_reg = {
.name = "realm",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_realm_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_realm_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_realm_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_realm_info)),
+ .help = realm_help,
+ .parse = realm_parse,
+ .final_check = realm_check,
+ .print = realm_print,
+ .save = realm_save,
+ .extra_opts = realm_opts,
};
-void ipt_realm_init(void)
+void libipt_realm_init(void)
{
- register_match(&realm);
+ xtables_register_match(&realm_mt_reg);
}
-
-
diff --git a/extensions/libipt_realm.man b/extensions/libipt_realm.man
index b33da0e..a40b1ad 100644
--- a/extensions/libipt_realm.man
+++ b/extensions/libipt_realm.man
@@ -1,7 +1,7 @@
This matches the routing realm. Routing realms are used in complex routing
setups involving dynamic routing protocols like BGP.
.TP
-.BI "--realm " "[!] " "value[/mask]"
+[\fB!\fP] \fB\-\-realm\fP \fIvalue\fP[\fB/\fP\fImask\fP]
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).
diff --git a/extensions/libipt_recent.c b/extensions/libipt_recent.c
deleted file mode 100644
index beb180c..0000000
--- a/extensions/libipt_recent.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/* Shared library add-on to iptables to add recent matching support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ipt_recent.h>
-
-/* Need these in order to not fail when compiling against an older kernel. */
-#ifndef RECENT_NAME
-#define RECENT_NAME "ipt_recent"
-#endif /* RECENT_NAME */
-
-#ifndef RECENT_VER
-#define RECENT_VER "unknown"
-#endif /* RECENT_VER */
-
-#ifndef IPT_RECENT_NAME_LEN
-#define IPT_RECENT_NAME_LEN 200
-#endif /* IPT_RECENT_NAME_LEN */
-
-/* Options for this module */
-static struct option opts[] = {
- { .name = "set", .has_arg = 0, .flag = 0, .val = 201 },
- { .name = "rcheck", .has_arg = 0, .flag = 0, .val = 202 },
- { .name = "update", .has_arg = 0, .flag = 0, .val = 203 },
- { .name = "seconds", .has_arg = 1, .flag = 0, .val = 204 },
- { .name = "hitcount", .has_arg = 1, .flag = 0, .val = 205 },
- { .name = "remove", .has_arg = 0, .flag = 0, .val = 206 },
- { .name = "rttl", .has_arg = 0, .flag = 0, .val = 207 },
- { .name = "name", .has_arg = 1, .flag = 0, .val = 208 },
- { .name = "rsource", .has_arg = 0, .flag = 0, .val = 209 },
- { .name = "rdest", .has_arg = 0, .flag = 0, .val = 210 },
- { .name = 0, .has_arg = 0, .flag = 0, .val = 0 }
-};
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"recent v%s options:\n"
-"[!] --set Add source address to list, always matches.\n"
-"[!] --rcheck Match if source address in list.\n"
-"[!] --update Match if source address in list, also update last-seen time.\n"
-"[!] --remove Match if source address in list, also removes that address from list.\n"
-" --seconds seconds For check and update commands above.\n"
-" Specifies that the match will only occur if source address last seen within\n"
-" the last 'seconds' seconds.\n"
-" --hitcount hits For check and update commands above.\n"
-" Specifies that the match will only occur if source address seen hits times.\n"
-" May be used in conjunction with the seconds option.\n"
-" --rttl For check and update commands above.\n"
-" Specifies that the match will only occur if the source address and the TTL\n"
-" match between this packet and the one which was set.\n"
-" Useful if you have problems with people spoofing their source address in order\n"
-" to DoS you via this module.\n"
-" --name name Name of the recent list to be used. DEFAULT used if none given.\n"
-" --rsource Match/Save the source address of each packet in the recent list table (default).\n"
-" --rdest Match/Save the destination address of each packet in the recent list table.\n"
-RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n"
-,
-IPTABLES_VERSION);
-
-}
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *match, unsigned int *nfcache)
-{
- struct ipt_recent_info *info = (struct ipt_recent_info *)(match)->data;
-
-
- strncpy(info->name,"DEFAULT",IPT_RECENT_NAME_LEN);
- /* eventhough IPT_RECENT_NAME_LEN is currently defined as 200,
- * better be safe, than sorry */
- info->name[IPT_RECENT_NAME_LEN-1] = '\0';
- info->side = IPT_RECENT_SOURCE;
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
- switch (c) {
- case 201:
- if (*flags) exit_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- check_inverse(optarg, &invert, &optind, 0);
- info->check_set |= IPT_RECENT_SET;
- if (invert) info->invert = 1;
- *flags = 1;
- break;
-
- case 202:
- if (*flags) exit_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- check_inverse(optarg, &invert, &optind, 0);
- info->check_set |= IPT_RECENT_CHECK;
- if(invert) info->invert = 1;
- *flags = 1;
- break;
-
- case 203:
- if (*flags) exit_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- check_inverse(optarg, &invert, &optind, 0);
- info->check_set |= IPT_RECENT_UPDATE;
- if (invert) info->invert = 1;
- *flags = 1;
- break;
-
- case 206:
- if (*flags) exit_error(PARAMETER_PROBLEM,
- "recent: only one of `--set', `--rcheck' "
- "`--update' or `--remove' may be set");
- check_inverse(optarg, &invert, &optind, 0);
- info->check_set |= IPT_RECENT_REMOVE;
- if (invert) info->invert = 1;
- *flags = 1;
- break;
-
- case 204:
- info->seconds = atoi(optarg);
- break;
-
- case 205:
- info->hit_count = atoi(optarg);
- break;
-
- case 207:
- info->check_set |= IPT_RECENT_TTL;
- break;
-
- case 208:
- strncpy(info->name,optarg,IPT_RECENT_NAME_LEN);
- info->name[IPT_RECENT_NAME_LEN-1] = '\0';
- break;
-
- case 209:
- info->side = IPT_RECENT_SOURCE;
- break;
-
- case 210:
- info->side = IPT_RECENT_DEST;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; must have specified a specific option. */
-static void
-final_check(unsigned int flags)
-{
-
- if (!flags)
- exit_error(PARAMETER_PROBLEM,
- "recent: you must specify one of `--set', `--rcheck' "
- "`--update' or `--remove'");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
-
- if (info->invert)
- fputc('!', stdout);
-
- printf("recent: ");
- if(info->check_set & IPT_RECENT_SET) printf("SET ");
- if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
- if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
- if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
- if(info->seconds) printf("seconds: %d ",info->seconds);
- if(info->hit_count) printf("hit_count: %d ",info->hit_count);
- if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
- if(info->name) printf("name: %s ",info->name);
- if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
- if(info->side == IPT_RECENT_DEST) printf("side: dest");
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
-
- if (info->invert)
- printf("! ");
-
- if(info->check_set & IPT_RECENT_SET) printf("--set ");
- if(info->check_set & IPT_RECENT_CHECK) printf("--rcheck ");
- if(info->check_set & IPT_RECENT_UPDATE) printf("--update ");
- if(info->check_set & IPT_RECENT_REMOVE) printf("--remove ");
- if(info->seconds) printf("--seconds %d ",info->seconds);
- if(info->hit_count) printf("--hitcount %d ",info->hit_count);
- if(info->check_set & IPT_RECENT_TTL) printf("--rttl ");
- if(info->name) printf("--name %s ",info->name);
- if(info->side == IPT_RECENT_SOURCE) printf("--rsource ");
- if(info->side == IPT_RECENT_DEST) printf("--rdest ");
-}
-
-/* Structure for iptables to use to communicate with module */
-static struct iptables_match recent = {
- .next = NULL,
- .name = "recent",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_recent_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_recent_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_recent_init(void)
-{
- register_match(&recent);
-}
diff --git a/extensions/libipt_recent.man b/extensions/libipt_recent.man
deleted file mode 100644
index bf5d710..0000000
--- a/extensions/libipt_recent.man
+++ /dev/null
@@ -1,93 +0,0 @@
-Allows you to dynamically create a list of IP addresses and then match
-against that list in a few different ways.
-
-For example, you can create a `badguy' list out of people attempting
-to connect to port 139 on your firewall and then DROP all future
-packets from them without considering them.
-.TP
-.BI "--name " "name"
-Specify the list to use for the commands. If no name is given then 'DEFAULT'
-will be used.
-.TP
-[\fB!\fR] \fB--set\fR
-This will add the source address of the packet to the list. If the
-source address is already in the list, this will update the existing
-entry. This will always return success (or failure if `!' is passed
-in).
-.TP
-[\fB!\fR] \fB--rcheck\fR
-Check if the source address of the packet is currently in
-the list.
-.TP
-[\fB!\fR] \fB--update\fR
-Like \fB--rcheck\fR, except it will update the "last seen" timestamp if it
-matches.
-.TP
-[\fB!\fR] \fB--remove\fR
-Check if the source address of the packet is currently in the list and
-if so that address will be removed from the list and the rule will
-return true. If the address is not found, false is returned.
-.TP
-[\fB!\fR] \fB--seconds \fIseconds\fR
-This option must be used in conjunction with one of \fB--rcheck\fR or
-\fB--update\fR. When used, this will narrow the match to only happen
-when the address is in the list and was seen within the last given
-number of seconds.
-.TP
-[\fB!\fR] \fB--hitcount \fIhits\fR
-This option must be used in conjunction with one of \fB--rcheck\fR or
-\fB--update\fR. When used, this will narrow the match to only happen
-when the address is in the list and packets had been received greater
-than or equal to the given value. This option may be used along with
-\fB--seconds\fR to create an even narrower match requiring a certain
-number of hits within a specific time frame.
-.TP
-\fB--rttl\fR
-This option must be used in conjunction with one of \fB--rcheck\fR or
-\fB--update\fR. When used, this will narrow the match to only happen
-when the address is in the list and the TTL of the current packet
-matches that of the packet which hit the \fB--set\fR rule. This may be
-useful if you have problems with people faking their source address in
-order to DoS you via this module by disallowing others access to your
-site by sending bogus packets to you.
-.P
-Examples:
-.IP
-# iptables -A FORWARD -m recent --name badguy --rcheck --seconds 60 -j DROP
-
-# iptables -A FORWARD -p tcp -i eth0 --dport 139 -m recent --name badguy --set -j DROP
-.P
-Official website (http://snowman.net/projects/ipt_recent/) also has
-some examples of usage.
-
-/proc/net/ipt_recent/* are the current lists of addresses and information
-about each entry of each list.
-
-Each file in /proc/net/ipt_recent/ can be read from to see the current list
-or written two using the following commands to modify the list:
-.TP
-echo xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT
-to Add to the DEFAULT list
-.TP
-echo -xx.xx.xx.xx > /proc/net/ipt_recent/DEFAULT
-to Remove from the DEFAULT list
-.TP
-echo clear > /proc/net/ipt_recent/DEFAULT
-to empty the DEFAULT list.
-.P
-The module itself accepts parameters, defaults shown:
-.TP
-.BI "ip_list_tot=" "100"
-Number of addresses remembered per table
-.TP
-.BI "ip_pkt_list_tot=" "20"
-Number of packets per address remembered
-.TP
-.BI "ip_list_hash_size=" "0"
-Hash table size. 0 means to calculate it based on ip_list_tot, default: 512
-.TP
-.BI "ip_list_perms=" "0644"
-Permissions for /proc/net/ipt_recent/* files
-.TP
-.BI "debug=" "0"
-Set to 1 to get lots of debugging info
diff --git a/extensions/libipt_sctp.c b/extensions/libipt_sctp.c
deleted file mode 100644
index 6301953..0000000
--- a/extensions/libipt_sctp.c
+++ /dev/null
@@ -1,551 +0,0 @@
-/* Shared library add-on to iptables for SCTP matching
- *
- * (C) 2003 by Harald Welte <laforge@gnumonks.org>
- *
- * This program is distributed under the terms of GNU GPL v2, 1991
- *
- * libipt_ecn.c borrowed heavily from libipt_dscp.c
- *
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <netdb.h>
-#include <ctype.h>
-#include <netinet/in.h>
-
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#endif
-
-#include <linux/netfilter_ipv4/ipt_sctp.h>
-
-/* Some ZS!#@:$%*#$! has replaced the ELEMCOUNT macro in ipt_sctp.h with
- * ARRAY_SIZE without noticing that this file is used from userserspace,
- * and userspace doesn't have ARRAY_SIZE */
-
-#ifndef ELEMCOUNT
-#define ELEMCOUNT ARRAY_SIZE
-#endif
-
-#if 0
-#define DEBUGP(format, first...) printf(format, ##first)
-#define static
-#else
-#define DEBUGP(format, fist...)
-#endif
-
-static void
-print_chunk(u_int32_t chunknum, int numeric);
-
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m,
- unsigned int *nfcache)
-{
- int i;
- struct ipt_sctp_info *einfo = (struct ipt_sctp_info *)m->data;
-
- memset(einfo, 0, sizeof(struct ipt_sctp_info));
-
- for (i = 0; i < IPT_NUM_SCTP_FLAGS; i++) {
- einfo->flag_info[i].chunktype = -1;
- }
-}
-
-static void help(void)
-{
- printf(
-"SCTP match v%s options\n"
-" --source-port [!] port[:port] match source port(s)\n"
-" --sport ...\n"
-" --destination-port [!] port[:port] match destination port(s)\n"
-" --dport ...\n"
-" --chunk-types [!] (all|any|none) (chunktype[:flags])+ match if all, any or none of\n"
-" chunktypes are present\n"
-"chunktypes - DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK ALL NONE\n",
- IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { .name = "source-port", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "sport", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "destination-port", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "dport", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "chunk-types", .has_arg = 1, .flag = 0, .val = '3' },
- { .name = 0 }
-};
-
-static void
-parse_sctp_ports(const char *portstring,
- u_int16_t *ports)
-{
- char *buffer;
- char *cp;
-
- buffer = strdup(portstring);
- DEBUGP("%s\n", portstring);
- if ((cp = strchr(buffer, ':')) == NULL) {
- ports[0] = ports[1] = parse_port(buffer, "sctp");
- }
- else {
- *cp = '\0';
- cp++;
-
- ports[0] = buffer[0] ? parse_port(buffer, "sctp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "sctp") : 0xFFFF;
-
- if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
- "invalid portrange (min > max)");
- }
- free(buffer);
-}
-
-struct sctp_chunk_names {
- const char *name;
- unsigned int chunk_type;
- const char *valid_flags;
-};
-
-/*'ALL' and 'NONE' will be treated specially. */
-static struct sctp_chunk_names sctp_chunk_names[]
-= { { .name = "DATA", .chunk_type = 0, .valid_flags = "-----UBE"},
- { .name = "INIT", .chunk_type = 1, .valid_flags = "--------"},
- { .name = "INIT_ACK", .chunk_type = 2, .valid_flags = "--------"},
- { .name = "SACK", .chunk_type = 3, .valid_flags = "--------"},
- { .name = "HEARTBEAT", .chunk_type = 4, .valid_flags = "--------"},
- { .name = "HEARTBEAT_ACK", .chunk_type = 5, .valid_flags = "--------"},
- { .name = "ABORT", .chunk_type = 6, .valid_flags = "-------T"},
- { .name = "SHUTDOWN", .chunk_type = 7, .valid_flags = "--------"},
- { .name = "SHUTDOWN_ACK", .chunk_type = 8, .valid_flags = "--------"},
- { .name = "ERROR", .chunk_type = 9, .valid_flags = "--------"},
- { .name = "COOKIE_ECHO", .chunk_type = 10, .valid_flags = "--------"},
- { .name = "COOKIE_ACK", .chunk_type = 11, .valid_flags = "--------"},
- { .name = "ECN_ECNE", .chunk_type = 12, .valid_flags = "--------"},
- { .name = "ECN_CWR", .chunk_type = 13, .valid_flags = "--------"},
- { .name = "SHUTDOWN_COMPLETE", .chunk_type = 14, .valid_flags = "-------T"},
- { .name = "ASCONF", .chunk_type = 31, .valid_flags = "--------"},
- { .name = "ASCONF_ACK", .chunk_type = 30, .valid_flags = "--------"},
-};
-
-static void
-save_chunk_flag_info(struct ipt_sctp_flag_info *flag_info,
- int *flag_count,
- int chunktype,
- int bit,
- int set)
-{
- int i;
-
- for (i = 0; i < *flag_count; i++) {
- if (flag_info[i].chunktype == chunktype) {
- DEBUGP("Previous match found\n");
- flag_info[i].chunktype = chunktype;
- flag_info[i].flag_mask |= (1 << bit);
- if (set) {
- flag_info[i].flag |= (1 << bit);
- }
-
- return;
- }
- }
-
- if (*flag_count == IPT_NUM_SCTP_FLAGS) {
- exit_error (PARAMETER_PROBLEM,
- "Number of chunk types with flags exceeds currently allowed limit."
- "Increasing this limit involves changing IPT_NUM_SCTP_FLAGS and"
- "recompiling both the kernel space and user space modules\n");
- }
-
- flag_info[*flag_count].chunktype = chunktype;
- flag_info[*flag_count].flag_mask |= (1 << bit);
- if (set) {
- flag_info[*flag_count].flag |= (1 << bit);
- }
- (*flag_count)++;
-}
-
-static void
-parse_sctp_chunk(struct ipt_sctp_info *einfo,
- const char *chunks)
-{
- char *ptr;
- char *buffer;
- unsigned int i, j;
- int found = 0;
- char *chunk_flags;
-
- buffer = strdup(chunks);
- DEBUGP("Buffer: %s\n", buffer);
-
- SCTP_CHUNKMAP_RESET(einfo->chunkmap);
-
- if (!strcasecmp(buffer, "ALL")) {
- SCTP_CHUNKMAP_SET_ALL(einfo->chunkmap);
- goto out;
- }
-
- if (!strcasecmp(buffer, "NONE")) {
- SCTP_CHUNKMAP_RESET(einfo->chunkmap);
- goto out;
- }
-
- for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
- found = 0;
- DEBUGP("Next Chunk type %s\n", ptr);
-
- if ((chunk_flags = strchr(ptr, ':')) != NULL) {
- *chunk_flags++ = 0;
- }
-
- for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
- if (strcasecmp(sctp_chunk_names[i].name, ptr) == 0) {
- DEBUGP("Chunk num %d\n", sctp_chunk_names[i].chunk_type);
- SCTP_CHUNKMAP_SET(einfo->chunkmap,
- sctp_chunk_names[i].chunk_type);
- found = 1;
- break;
- }
- }
- if (!found)
- exit_error(PARAMETER_PROBLEM,
- "Unknown sctp chunk `%s'", ptr);
-
- if (chunk_flags) {
- DEBUGP("Chunk flags %s\n", chunk_flags);
- for (j = 0; j < strlen(chunk_flags); j++) {
- char *p;
- int bit;
-
- if ((p = strchr(sctp_chunk_names[i].valid_flags,
- toupper(chunk_flags[j]))) != NULL) {
- bit = p - sctp_chunk_names[i].valid_flags;
- bit = 7 - bit;
-
- save_chunk_flag_info(einfo->flag_info,
- &(einfo->flag_count), i, bit,
- isupper(chunk_flags[j]));
- } else {
- exit_error(PARAMETER_PROBLEM,
- "Invalid flags for chunk type %d\n", i);
- }
- }
- }
- }
-out:
- free(buffer);
-}
-
-static void
-parse_sctp_chunks(struct ipt_sctp_info *einfo,
- const char *match_type,
- const char *chunks)
-{
- DEBUGP("Match type: %s Chunks: %s\n", match_type, chunks);
- if (!strcasecmp(match_type, "ANY")) {
- einfo->chunk_match_type = SCTP_CHUNK_MATCH_ANY;
- } else if (!strcasecmp(match_type, "ALL")) {
- einfo->chunk_match_type = SCTP_CHUNK_MATCH_ALL;
- } else if (!strcasecmp(match_type, "ONLY")) {
- einfo->chunk_match_type = SCTP_CHUNK_MATCH_ONLY;
- } else {
- exit_error (PARAMETER_PROBLEM,
- "Match type has to be one of \"ALL\", \"ANY\" or \"ONLY\"");
- }
-
- SCTP_CHUNKMAP_RESET(einfo->chunkmap);
- parse_sctp_chunk(einfo, chunks);
-}
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_sctp_info *einfo
- = (struct ipt_sctp_info *)(*match)->data;
-
- switch (c) {
- case '1':
- if (*flags & IPT_SCTP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--source-port' allowed");
- einfo->flags |= IPT_SCTP_SRC_PORTS;
- check_inverse(optarg, &invert, &optind, 0);
- parse_sctp_ports(argv[optind-1], einfo->spts);
- if (invert)
- einfo->invflags |= IPT_SCTP_SRC_PORTS;
- *flags |= IPT_SCTP_SRC_PORTS;
- break;
-
- case '2':
- if (*flags & IPT_SCTP_DEST_PORTS)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--destination-port' allowed");
- einfo->flags |= IPT_SCTP_DEST_PORTS;
- check_inverse(optarg, &invert, &optind, 0);
- parse_sctp_ports(argv[optind-1], einfo->dpts);
- if (invert)
- einfo->invflags |= IPT_SCTP_DEST_PORTS;
- *flags |= IPT_SCTP_DEST_PORTS;
- break;
-
- case '3':
- if (*flags & IPT_SCTP_CHUNK_TYPES)
- exit_error(PARAMETER_PROBLEM,
- "Only one `--chunk-types' allowed");
- check_inverse(optarg, &invert, &optind, 0);
-
- if (!argv[optind]
- || argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
- "--chunk-types requires two args");
-
- einfo->flags |= IPT_SCTP_CHUNK_TYPES;
- parse_sctp_chunks(einfo, argv[optind-1], argv[optind]);
- if (invert)
- einfo->invflags |= IPT_SCTP_CHUNK_TYPES;
- optind++;
- *flags |= IPT_SCTP_CHUNK_TYPES;
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-static void
-final_check(unsigned int flags)
-{
-}
-
-static char *
-port_to_service(int port)
-{
- struct servent *service;
-
- if ((service = getservbyport(htons(port), "sctp")))
- return service->s_name;
-
- return NULL;
-}
-
-static void
-print_port(u_int16_t port, int numeric)
-{
- char *service;
-
- if (numeric || (service = port_to_service(port)) == NULL)
- printf("%u", port);
- else
- printf("%s", service);
-}
-
-static void
-print_ports(const char *name, u_int16_t min, u_int16_t max,
- int invert, int numeric)
-{
- const char *inv = invert ? "!" : "";
-
- if (min != 0 || max != 0xFFFF || invert) {
- printf("%s", name);
- if (min == max) {
- printf(":%s", inv);
- print_port(min, numeric);
- } else {
- printf("s:%s", inv);
- print_port(min, numeric);
- printf(":");
- print_port(max, numeric);
- }
- printf(" ");
- }
-}
-
-static void
-print_chunk_flags(u_int32_t chunknum, u_int8_t chunk_flags, u_int8_t chunk_flags_mask)
-{
- int i;
-
- DEBUGP("type: %d\tflags: %x\tflag mask: %x\n", chunknum, chunk_flags,
- chunk_flags_mask);
-
- if (chunk_flags_mask) {
- printf(":");
- }
-
- for (i = 7; i >= 0; i--) {
- if (chunk_flags_mask & (1 << i)) {
- if (chunk_flags & (1 << i)) {
- printf("%c", sctp_chunk_names[chunknum].valid_flags[7-i]);
- } else {
- printf("%c", tolower(sctp_chunk_names[chunknum].valid_flags[7-i]));
- }
- }
- }
-}
-
-static void
-print_chunk(u_int32_t chunknum, int numeric)
-{
- if (numeric) {
- printf("0x%04X", chunknum);
- }
- else {
- int i;
-
- for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
- if (sctp_chunk_names[i].chunk_type == chunknum)
- printf("%s", sctp_chunk_names[chunknum].name);
- }
- }
-}
-
-static void
-print_chunks(u_int32_t chunk_match_type,
- const u_int32_t *chunkmap,
- const struct ipt_sctp_flag_info *flag_info,
- int flag_count,
- int numeric)
-{
- int i, j;
- int flag;
-
- switch (chunk_match_type) {
- case SCTP_CHUNK_MATCH_ANY: printf("any "); break;
- case SCTP_CHUNK_MATCH_ALL: printf("all "); break;
- case SCTP_CHUNK_MATCH_ONLY: printf("only "); break;
- default: printf("Never reach herer\n"); break;
- }
-
- if (SCTP_CHUNKMAP_IS_CLEAR(chunkmap)) {
- printf("NONE ");
- goto out;
- }
-
- if (SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)) {
- printf("ALL ");
- goto out;
- }
-
- flag = 0;
- for (i = 0; i < 256; i++) {
- if (SCTP_CHUNKMAP_IS_SET(chunkmap, i)) {
- if (flag)
- printf(",");
- flag = 1;
- print_chunk(i, numeric);
- for (j = 0; j < flag_count; j++) {
- if (flag_info[j].chunktype == i) {
- print_chunk_flags(i, flag_info[j].flag,
- flag_info[j].flag_mask);
- }
- }
- }
- }
-
- if (flag)
- printf(" ");
-out:
- return;
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- const struct ipt_sctp_info *einfo =
- (const struct ipt_sctp_info *)match->data;
-
- printf("sctp ");
-
- if (einfo->flags & IPT_SCTP_SRC_PORTS) {
- print_ports("spt", einfo->spts[0], einfo->spts[1],
- einfo->invflags & IPT_SCTP_SRC_PORTS,
- numeric);
- }
-
- if (einfo->flags & IPT_SCTP_DEST_PORTS) {
- print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
- einfo->invflags & IPT_SCTP_DEST_PORTS,
- numeric);
- }
-
- if (einfo->flags & IPT_SCTP_CHUNK_TYPES) {
- /* FIXME: print_chunks() is used in save() where the printing of '!'
- s taken care of, so we need to do that here as well */
- if (einfo->invflags & IPT_SCTP_CHUNK_TYPES) {
- printf("! ");
- }
- print_chunks(einfo->chunk_match_type, einfo->chunkmap,
- einfo->flag_info, einfo->flag_count, numeric);
- }
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
-{
- const struct ipt_sctp_info *einfo =
- (const struct ipt_sctp_info *)match->data;
-
- if (einfo->flags & IPT_SCTP_SRC_PORTS) {
- if (einfo->invflags & IPT_SCTP_SRC_PORTS)
- printf("! ");
- if (einfo->spts[0] != einfo->spts[1])
- printf("--sport %u:%u ",
- einfo->spts[0], einfo->spts[1]);
- else
- printf("--sport %u ", einfo->spts[0]);
- }
-
- if (einfo->flags & IPT_SCTP_DEST_PORTS) {
- if (einfo->invflags & IPT_SCTP_DEST_PORTS)
- printf("! ");
- if (einfo->dpts[0] != einfo->dpts[1])
- printf("--dport %u:%u ",
- einfo->dpts[0], einfo->dpts[1]);
- else
- printf("--dport %u ", einfo->dpts[0]);
- }
-
- if (einfo->flags & IPT_SCTP_CHUNK_TYPES) {
- if (einfo->invflags & IPT_SCTP_CHUNK_TYPES)
- printf("! ");
- printf("--chunk-types ");
-
- print_chunks(einfo->chunk_match_type, einfo->chunkmap,
- einfo->flag_info, einfo->flag_count, 0);
- }
-}
-
-static
-struct iptables_match sctp
-= { .name = "sctp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_sctp_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_sctp_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_sctp_init(void)
-{
- register_match(&sctp);
-}
-
diff --git a/extensions/libipt_set.c b/extensions/libipt_set.c
new file mode 100644
index 0000000..ffc6685
--- /dev/null
+++ b/extensions/libipt_set.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ * Patrick Schaaf <bof@bof.de>
+ * Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Shared library add-on to iptables to add IP set matching. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <xtables.h>
+#include <linux/netfilter_ipv4/ipt_set.h>
+#include "libipt_set.h"
+
+static void set_help(void)
+{
+ printf("set match options:\n"
+ " [!] --match-set name flags\n"
+ " 'name' is the set name from to match,\n"
+ " 'flags' are the comma separated list of\n"
+ " 'src' and 'dst' specifications.\n");
+}
+
+static const struct option set_opts[] = {
+ { .name = "match-set", .has_arg = true, .val = '1'},
+ { .name = "set", .has_arg = true, .val = '2'},
+ { .name = NULL }
+};
+
+static void set_init(struct xt_entry_match *match)
+{
+ struct ipt_set_info_match *info =
+ (struct ipt_set_info_match *) match->data;
+
+
+ memset(info, 0, sizeof(struct ipt_set_info_match));
+
+}
+
+static int set_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ipt_set_info_match *myinfo =
+ (struct ipt_set_info_match *) (*match)->data;
+ struct ipt_set_info *info = &myinfo->match_set;
+
+ switch (c) {
+ case '2':
+#if 0
+ fprintf(stderr,
+ "--set option deprecated, please use --match-set\n");
+#endif
+ case '1': /* --match-set <set> <flag>[,<flag> */
+ if (info->flags[0])
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set can be specified only once");
+
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ info->flags[0] |= IPSET_MATCH_INV;
+
+ if (!argv[optind]
+ || argv[optind][0] == '-'
+ || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set requires two args.");
+
+ if (strlen(optarg) > IP_SET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IP_SET_MAXNAMELEN - 1);
+
+ get_set_byname(optarg, info);
+ parse_bindings(argv[optind], info);
+ DEBUGP("parse: set index %u\n", info->index);
+ optind++;
+
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void set_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify `--match-set' with proper arguments");
+ DEBUGP("final check OK\n");
+}
+
+static void
+print_match(const char *prefix, const struct ipt_set_info *info)
+{
+ int i;
+ char setname[IP_SET_MAXNAMELEN];
+
+ get_set_byid(setname, info->index);
+ printf("%s%s %s",
+ (info->flags[0] & IPSET_MATCH_INV) ? "! " : "",
+ prefix,
+ setname);
+ for (i = 0; i < IP_SET_MAX_BINDINGS; i++) {
+ if (!info->flags[i])
+ break;
+ printf("%s%s",
+ i == 0 ? " " : ",",
+ info->flags[i] & IPSET_SRC ? "src" : "dst");
+ }
+ printf(" ");
+}
+
+/* Prints out the matchinfo. */
+static void set_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_set_info_match *info = (const void *)match->data;
+
+ print_match("match-set", &info->match_set);
+}
+
+static void set_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ipt_set_info_match *info = (const void *)match->data;
+
+ print_match("--match-set", &info->match_set);
+}
+
+static struct xtables_match set_mt_reg = {
+ .name = "set",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_set_info_match)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_set_info_match)),
+ .help = set_help,
+ .init = set_init,
+ .parse = set_parse,
+ .final_check = set_check,
+ .print = set_print,
+ .save = set_save,
+ .extra_opts = set_opts,
+};
+
+void libipt_set_init(void)
+{
+ xtables_register_match(&set_mt_reg);
+}
diff --git a/extensions/libipt_set.h b/extensions/libipt_set.h
index 02de0fa..0e9b0b5 100644
--- a/extensions/libipt_set.h
+++ b/extensions/libipt_set.h
@@ -1,6 +1,7 @@
#ifndef _LIBIPT_SET_H
#define _LIBIPT_SET_H
+#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
@@ -12,9 +13,9 @@
#endif
static void
-parse_bindings(const char *optarg, struct ipt_set_info *info)
+parse_bindings(const char *opt_arg, struct ipt_set_info *info)
{
- char *saved = strdup(optarg);
+ char *saved = strdup(opt_arg);
char *ptr, *tmp = saved;
int i = 0;
@@ -25,78 +26,92 @@ parse_bindings(const char *optarg, struct ipt_set_info *info)
else if (strncmp(ptr, "dst", 3) == 0)
info->flags[i++] |= IPSET_DST;
else
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"You must spefify (the comma separated list of) 'src' or 'dst'.");
}
if (tmp)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't follow bindings deeper than %i.",
IP_SET_MAX_BINDINGS - 1);
free(saved);
}
-static int get_set_getsockopt(void *data, socklen_t * size)
+static int get_version(unsigned *version)
{
- int sockfd = -1;
- sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ int res, sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+ struct ip_set_req_version req_version;
+ socklen_t size = sizeof(req_version);
+
if (sockfd < 0)
- exit_error(OTHER_PROBLEM,
+ xtables_error(OTHER_PROBLEM,
"Can't open socket to ipset.\n");
- /* Send! */
- return getsockopt(sockfd, SOL_IP, SO_IP_SET, data, size);
+
+ req_version.op = IP_SET_OP_VERSION;
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req_version, &size);
+ if (res != 0)
+ xtables_error(OTHER_PROBLEM,
+ "Kernel module ip_set is not loaded in.\n");
+
+ *version = req_version.version;
+
+ return sockfd;
}
static void get_set_byname(const char *setname, struct ipt_set_info *info)
{
struct ip_set_req_get_set req;
socklen_t size = sizeof(struct ip_set_req_get_set);
- int res;
+ int res, sockfd;
+ sockfd = get_version(&req.version);
req.op = IP_SET_OP_GET_BYNAME;
- req.version = IP_SET_PROTOCOL_VERSION;
strncpy(req.set.name, setname, IP_SET_MAXNAMELEN);
req.set.name[IP_SET_MAXNAMELEN - 1] = '\0';
- res = get_set_getsockopt(&req, &size);
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
+ close(sockfd);
+
if (res != 0)
- exit_error(OTHER_PROBLEM,
+ xtables_error(OTHER_PROBLEM,
"Problem when communicating with ipset, errno=%d.\n",
errno);
if (size != sizeof(struct ip_set_req_get_set))
- exit_error(OTHER_PROBLEM,
+ xtables_error(OTHER_PROBLEM,
"Incorrect return size from kernel during ipset lookup, "
- "(want %ld, got %ld)\n",
- sizeof(struct ip_set_req_get_set), size);
+ "(want %zu, got %zu)\n",
+ sizeof(struct ip_set_req_get_set), (size_t)size);
if (req.set.index == IP_SET_INVALID_ID)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Set %s doesn't exist.\n", setname);
info->index = req.set.index;
}
-static void get_set_byid(char * setname, ip_set_id_t index)
+static void get_set_byid(char * setname, ip_set_id_t idx)
{
struct ip_set_req_get_set req;
socklen_t size = sizeof(struct ip_set_req_get_set);
- int res;
+ int res, sockfd;
+ sockfd = get_version(&req.version);
req.op = IP_SET_OP_GET_BYINDEX;
- req.version = IP_SET_PROTOCOL_VERSION;
- req.set.index = index;
- res = get_set_getsockopt(&req, &size);
+ req.set.index = idx;
+ res = getsockopt(sockfd, SOL_IP, SO_IP_SET, &req, &size);
+ close(sockfd);
+
if (res != 0)
- exit_error(OTHER_PROBLEM,
+ xtables_error(OTHER_PROBLEM,
"Problem when communicating with ipset, errno=%d.\n",
errno);
if (size != sizeof(struct ip_set_req_get_set))
- exit_error(OTHER_PROBLEM,
+ xtables_error(OTHER_PROBLEM,
"Incorrect return size from kernel during ipset lookup, "
- "(want %ld, got %ld)\n",
- sizeof(struct ip_set_req_get_set), size);
+ "(want %zu, got %zu)\n",
+ sizeof(struct ip_set_req_get_set), (size_t)size);
if (req.set.name[0] == '\0')
- exit_error(PARAMETER_PROBLEM,
- "Set id %i in kernel doesn't exist.\n", index);
+ xtables_error(PARAMETER_PROBLEM,
+ "Set id %i in kernel doesn't exist.\n", idx);
strncpy(setname, req.set.name, IP_SET_MAXNAMELEN);
}
diff --git a/extensions/libipt_set.man b/extensions/libipt_set.man
index d280577..aca1bfc 100644
--- a/extensions/libipt_set.man
+++ b/extensions/libipt_set.man
@@ -1,17 +1,23 @@
-This modules macthes IP sets which can be defined by ipset(8).
+This module matches IP sets which can be defined by ipset(8).
.TP
-.BR "--set " "setname flag[,flag...]"
-where flags are
+[\fB!\fP] \fB\-\-match\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP]...
+where flags are the comma separated list of
.BR "src"
and/or
.BR "dst"
-and there can be no more than six of them. Hence the command
-.nf
- iptables -A FORWARD -m set --set test src,dst
-.fi
-will match packets, for which (depending on the type of the set) the source
-address or port number of the packet can be found in the specified set. If
-there is a binding belonging to the mached set element or there is a default
-binding for the given set, then the rule will match the packet only if
-additionally (depending on the type of the set) the destination address or
-port number of the packet can be found in the set according to the binding.
+specifications and there can be no more than six of them. Hence the command
+.IP
+ iptables \-A FORWARD \-m set \-\-match\-set test src,dst
+.IP
+will match packets, for which (if the set type is ipportmap) the source
+address and destination port pair can be found in the specified set. If
+the set type of the specified set is single dimension (for example ipmap),
+then the command will match packets for which the source address can be
+found in the specified set.
+.PP
+The option \fB\-\-match\-set\fR can be replaced by \fB\-\-set\fR if that does
+not clash with an option of other extensions.
+.PP
+Use of -m set requires that ipset kernel support is provided. As standard
+kernels do not ship this currently, the ipset or Xtables-addons package needs
+to be installed.
diff --git a/extensions/libipt_standard.c b/extensions/libipt_standard.c
deleted file mode 100644
index 9c3cdc2..0000000
--- a/extensions/libipt_standard.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Shared library add-on to iptables for standard target support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <getopt.h>
-#include <iptables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"Standard v%s options:\n"
-"(If target is DROP, ACCEPT, RETURN or nothing)\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- {0}
-};
-
-/* Initialize the target. */
-static void
-init(struct ipt_entry_target *t, unsigned int *nfcache)
-{
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- struct ipt_entry_target **target)
-{
- return 0;
-}
-
-/* Final check; don't care. */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Saves the targinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
-{
-}
-
-static
-struct iptables_target standard = {
- .next = NULL,
- .name = "standard",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(int)),
- .userspacesize = IPT_ALIGN(sizeof(int)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = NULL,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_standard_init(void)
-{
- register_target(&standard);
-}
diff --git a/extensions/libipt_state.c b/extensions/libipt_state.c
deleted file mode 100644
index 48d834d..0000000
--- a/extensions/libipt_state.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/* Shared library add-on to iptables to add state tracking support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/ipt_state.h>
-
-#ifndef IPT_STATE_UNTRACKED
-#define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
-#endif
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"state v%s options:\n"
-" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
-" State(s) to match\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "state", 1, 0, '1' },
- {0}
-};
-
-static int
-parse_state(const char *state, size_t strlen, struct ipt_state_info *sinfo)
-{
- if (strncasecmp(state, "INVALID", strlen) == 0)
- sinfo->statemask |= IPT_STATE_INVALID;
- else if (strncasecmp(state, "NEW", strlen) == 0)
- sinfo->statemask |= IPT_STATE_BIT(IP_CT_NEW);
- else if (strncasecmp(state, "ESTABLISHED", strlen) == 0)
- sinfo->statemask |= IPT_STATE_BIT(IP_CT_ESTABLISHED);
- else if (strncasecmp(state, "RELATED", strlen) == 0)
- sinfo->statemask |= IPT_STATE_BIT(IP_CT_RELATED);
- else if (strncasecmp(state, "UNTRACKED", strlen) == 0)
- sinfo->statemask |= IPT_STATE_UNTRACKED;
- else
- return 0;
- return 1;
-}
-
-static void
-parse_states(const char *arg, struct ipt_state_info *sinfo)
-{
- const char *comma;
-
- while ((comma = strchr(arg, ',')) != NULL) {
- if (comma == arg || !parse_state(arg, comma-arg, sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
- arg = comma+1;
- }
-
- if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
- exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
-}
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- struct ipt_state_info *sinfo = (struct ipt_state_info *)(*match)->data;
-
- switch (c) {
- case '1':
- check_inverse(optarg, &invert, &optind, 0);
-
- parse_states(argv[optind-1], sinfo);
- if (invert)
- sinfo->statemask = ~sinfo->statemask;
- *flags = 1;
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Final check; must have specified --state. */
-static void final_check(unsigned int flags)
-{
- if (!flags)
- exit_error(PARAMETER_PROBLEM, "You must specify `--state'");
-}
-
-static void print_state(unsigned int statemask)
-{
- const char *sep = "";
-
- if (statemask & IPT_STATE_INVALID) {
- printf("%sINVALID", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_BIT(IP_CT_NEW)) {
- printf("%sNEW", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_BIT(IP_CT_RELATED)) {
- printf("%sRELATED", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_BIT(IP_CT_ESTABLISHED)) {
- printf("%sESTABLISHED", sep);
- sep = ",";
- }
- if (statemask & IPT_STATE_UNTRACKED) {
- printf("%sUNTRACKED", sep);
- sep = ",";
- }
- printf(" ");
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct ipt_state_info *sinfo = (struct ipt_state_info *)match->data;
-
- printf("state ");
- print_state(sinfo->statemask);
-}
-
-/* Saves the matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct ipt_state_info *sinfo = (struct ipt_state_info *)match->data;
-
- printf("--state ");
- print_state(sinfo->statemask);
-}
-
-static struct iptables_match state = {
- .next = NULL,
- .name = "state",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_state_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_state_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
-};
-
-void ipt_state_init(void)
-{
- register_match(&state);
-}
diff --git a/extensions/libipt_statistic.c b/extensions/libipt_statistic.c
deleted file mode 100644
index 58ac983..0000000
--- a/extensions/libipt_statistic.c
+++ /dev/null
@@ -1,175 +0,0 @@
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <getopt.h>
-
-#include <iptables.h>
-#include <linux/netfilter/xt_statistic.h>
-
-static void
-help(void)
-{
- printf(
-"statistic match v%s options:\n"
-" --mode mode Match mode (random, nth)\n"
-" random mode:\n"
-" --probability p Probability\n"
-" nth mode:\n"
-" --every n Match every nth packet\n"
-" --packet p Initial counter value (0 <= p <= n-1, default 0)\n"
-"\n",
-IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- { "mode", 1, 0, '1' },
- { "probability", 1, 0, '2' },
- { "every", 1, 0, '3' },
- { "packet", 1, 0, '4' },
- { 0 }
-};
-
-static struct xt_statistic_info *info;
-
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- double prob;
-
- info = (void *)(*match)->data;
-
- if (invert)
- info->flags |= XT_STATISTIC_INVERT;
-
- switch (c) {
- case '1':
- if (*flags & 0x1)
- exit_error(PARAMETER_PROBLEM, "double --mode");
- if (!strcmp(optarg, "random"))
- info->mode = XT_STATISTIC_MODE_RANDOM;
- else if (!strcmp(optarg, "nth"))
- info->mode = XT_STATISTIC_MODE_NTH;
- else
- exit_error(PARAMETER_PROBLEM, "Bad mode `%s'", optarg);
- *flags |= 0x1;
- break;
- case '2':
- if (*flags & 0x2)
- exit_error(PARAMETER_PROBLEM, "double --probability");
- prob = atof(optarg);
- if (prob < 0 || prob > 1)
- exit_error(PARAMETER_PROBLEM,
- "--probability must be between 0 and 1");
- info->u.random.probability = 0x80000000 * prob;
- *flags |= 0x2;
- break;
- case '3':
- if (*flags & 0x4)
- exit_error(PARAMETER_PROBLEM, "double --every");
- if (string_to_number(optarg, 0, 0xFFFFFFFF,
- &info->u.nth.every) == -1)
- exit_error(PARAMETER_PROBLEM,
- "cannot parse --every `%s'", optarg);
- if (info->u.nth.every == 0)
- exit_error(PARAMETER_PROBLEM, "--every cannot be 0");
- info->u.nth.every--;
- *flags |= 0x4;
- break;
- case '4':
- if (*flags & 0x8)
- exit_error(PARAMETER_PROBLEM, "double --packet");
- if (string_to_number(optarg, 0, 0xFFFFFFFF,
- &info->u.nth.packet) == -1)
- exit_error(PARAMETER_PROBLEM,
- "cannot parse --packet `%s'", optarg);
- *flags |= 0x8;
- break;
- default:
- return 0;
- }
- return 1;
-}
-
-/* Final check; must have specified --mark. */
-static void
-final_check(unsigned int flags)
-{
- if (!(flags & 0x1))
- exit_error(PARAMETER_PROBLEM, "no mode specified");
- if ((flags & 0x2) && (flags & (0x4 | 0x8)))
- exit_error(PARAMETER_PROBLEM,
- "both nth and random parameters given");
- if (flags & 0x2 && info->mode != XT_STATISTIC_MODE_RANDOM)
- exit_error(PARAMETER_PROBLEM,
- "--probability can only be used in random mode");
- if (flags & 0x4 && info->mode != XT_STATISTIC_MODE_NTH)
- exit_error(PARAMETER_PROBLEM,
- "--every can only be used in nth mode");
- if (flags & 0x8 && info->mode != XT_STATISTIC_MODE_NTH)
- exit_error(PARAMETER_PROBLEM,
- "--packet can only be used in nth mode");
- info->u.nth.count = info->u.nth.every - info->u.nth.packet;
-}
-
-/* Prints out the matchinfo. */
-static void print_match(const struct xt_statistic_info *info, char *prefix)
-{
- if (info->flags & XT_STATISTIC_INVERT)
- printf("! ");
-
- switch (info->mode) {
- case XT_STATISTIC_MODE_RANDOM:
- printf("%smode random %sprobability %f ", prefix, prefix,
- 1.0 * info->u.random.probability / 0x80000000);
- break;
- case XT_STATISTIC_MODE_NTH:
- printf("%smode nth %severy %u ", prefix, prefix,
- info->u.nth.every + 1);
- if (info->u.nth.packet)
- printf("%spacket %u ", prefix, info->u.nth.packet);
- break;
- }
-}
-
-static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
-{
- struct xt_statistic_info *info = (struct xt_statistic_info *)match->data;
-
- printf("statistic ");
- print_match(info, "");
-}
-
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
-{
- struct xt_statistic_info *info = (struct xt_statistic_info *)match->data;
-
- print_match(info, "--");
-}
-
-static struct iptables_match statistic = {
- .name = "statistic",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct xt_statistic_info)),
- .userspacesize = offsetof(struct xt_statistic_info, u.nth.count),
- .help = help,
- .parse = parse,
- .final_check = final_check,
- .print = print,
- .save = save,
- .extra_opts = opts
-};
-
-void ipt_statistic_init(void)
-{
- register_match(&statistic);
-}
diff --git a/extensions/libipt_tos.man b/extensions/libipt_tos.man
deleted file mode 100644
index c612b29..0000000
--- a/extensions/libipt_tos.man
+++ /dev/null
@@ -1,9 +0,0 @@
-This module matches the 8 bits of Type of Service field in the IP
-header (ie. including the precedence bits).
-.TP
-.BI "--tos " "tos"
-The argument is either a standard name, (use
-.br
- iptables -m tos -h
-.br
-to see the list), or a numeric value to match.
diff --git a/extensions/libipt_2ttl.c b/extensions/libipt_ttl.c
index 5e16713..1a82fd4 100644
--- a/extensions/libipt_2ttl.c
+++ b/extensions/libipt_ttl.c
@@ -1,7 +1,7 @@
/* Shared library add-on to iptables to add TTL matching support
* (C) 2000 by Harald Welte <laforge@gnumonks.org>
*
- * $Id: libipt_ttl.c 4544 2005-11-18 17:59:56Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org $
+ * $Id$
*
* This program is released under the terms of GNU GPL */
@@ -9,34 +9,31 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
-#include <linux/netfilter_ipv4/ipt_2ttl.h>
+#include <linux/netfilter_ipv4/ipt_ttl.h>
-static void help(void)
+static void ttl_help(void)
{
printf(
-"TTL match v%s options:\n"
+"ttl match options:\n"
" --ttl-eq value Match time to live value\n"
" --ttl-lt value Match TTL < value\n"
-" --ttl-gt value Match TTL > value\n"
-, IPTABLES_VERSION);
+" --ttl-gt value Match TTL > value\n");
}
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry, unsigned int *nfcache,
- struct ipt_entry_match **match)
+static int ttl_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct ipt_ttl_info *info = (struct ipt_ttl_info *) (*match)->data;
unsigned int value;
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
switch (c) {
case '2':
- if (string_to_number(optarg, 0, 255, &value) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"ttl: Expected value between 0 and 255");
if (invert)
@@ -48,24 +45,24 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
info->ttl = value;
break;
case '3':
- if (string_to_number(optarg, 0, 255, &value) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"ttl: Expected value between 0 and 255");
if (invert)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ttl: unexpected `!'");
info->mode = IPT_TTL_LT;
info->ttl = value;
break;
case '4':
- if (string_to_number(optarg, 0, 255, &value) == -1)
- exit_error(PARAMETER_PROBLEM,
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
"ttl: Expected value between 0 and 255");
if (invert)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"ttl: unexpected `!'");
info->mode = IPT_TTL_GT;
@@ -77,24 +74,23 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
}
if (*flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify TTL option twice");
*flags = 1;
return 1;
}
-static void final_check(unsigned int flags)
+static void ttl_check(unsigned int flags)
{
if (!flags)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"TTL match: You must specify one of "
"`--ttl-eq', `--ttl-lt', `--ttl-gt");
}
-static void print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
+static void ttl_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
{
const struct ipt_ttl_info *info =
(struct ipt_ttl_info *) match->data;
@@ -117,8 +113,7 @@ static void print(const struct ipt_ip *ip,
printf("%u ", info->ttl);
}
-static void save(const struct ipt_ip *ip,
- const struct ipt_entry_match *match)
+static void ttl_save(const void *ip, const struct xt_entry_match *match)
{
const struct ipt_ttl_info *info =
(struct ipt_ttl_info *) match->data;
@@ -143,30 +138,30 @@ static void save(const struct ipt_ip *ip,
printf("%u ", info->ttl);
}
-static struct option opts[] = {
- { "ttl", 1, 0, '2' },
- { "ttl-eq", 1, 0, '2'},
- { "ttl-lt", 1, 0, '3'},
- { "ttl-gt", 1, 0, '4'},
- { 0 }
+static const struct option ttl_opts[] = {
+ { "ttl", 1, NULL, '2' },
+ { "ttl-eq", 1, NULL, '2'},
+ { "ttl-lt", 1, NULL, '3'},
+ { "ttl-gt", 1, NULL, '4'},
+ { .name = NULL }
};
-static struct iptables_match ttl = {
- .next = NULL,
+static struct xtables_match ttl_mt_reg = {
.name = "ttl",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_ttl_info)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_ttl_info)),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_ttl_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_ttl_info)),
+ .help = ttl_help,
+ .parse = ttl_parse,
+ .final_check = ttl_check,
+ .print = ttl_print,
+ .save = ttl_save,
+ .extra_opts = ttl_opts,
};
-void ipt_2ttl_init(void)
+void libipt_ttl_init(void)
{
- register_match(&ttl);
+ xtables_register_match(&ttl_mt_reg);
}
diff --git a/extensions/libipt_ttl.man b/extensions/libipt_ttl.man
index f043c79..849f704 100644
--- a/extensions/libipt_ttl.man
+++ b/extensions/libipt_ttl.man
@@ -1,10 +1,10 @@
This module matches the time to live field in the IP header.
.TP
-.BI "--ttl-eq " "ttl"
+\fB\-\-ttl\-eq\fP \fIttl\fP
Matches the given TTL value.
.TP
-.BI "--ttl-gt " "ttl"
+\fB\-\-ttl\-gt\fP \fIttl\fP
Matches if TTL is greater than the given TTL value.
.TP
-.BI "--ttl-lt " "ttl"
+\fB\-\-ttl\-lt\fP \fIttl\fP
Matches if TTL is less than the given TTL value.
diff --git a/extensions/libipt_udp.man b/extensions/libipt_udp.man
deleted file mode 100644
index 0408479..0000000
--- a/extensions/libipt_udp.man
+++ /dev/null
@@ -1,14 +0,0 @@
-These extensions are loaded if `--protocol udp' is specified. It
-provides the following options:
-.TP
-.BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
-Source port or port range specification.
-See the description of the
-.B --source-port
-option of the TCP extension for details.
-.TP
-.BR "--destination-port " "[!] \fIport\fP[:\fIport\fP]"
-Destination port or port range specification.
-See the description of the
-.B --destination-port
-option of the TCP extension for details.
diff --git a/extensions/libipt_unclean.c b/extensions/libipt_unclean.c
index 6f4333a..4941ae4 100644
--- a/extensions/libipt_unclean.c
+++ b/extensions/libipt_unclean.c
@@ -1,54 +1,15 @@
/* Shared library add-on to iptables for unclean. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <iptables.h>
+#include <xtables.h>
-/* Function which prints out usage message. */
-static void
-help(void)
-{
- printf(
-"unclean v%s takes no options\n"
-"\n", IPTABLES_VERSION);
-}
-
-static struct option opts[] = {
- {0}
-};
-
-/* Function which parses command options; returns true if it
- ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
-{
- return 0;
-}
-
-/* Final check; must have specified --mac. */
-static void final_check(unsigned int flags)
-{
-}
-
-static
-struct iptables_match unclean = {
- .next = NULL,
+static struct xtables_match unclean_mt_reg = {
.name = "unclean",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(0),
- .userspacesize = IPT_ALIGN(0),
- .help = &help,
- .parse = &parse,
- .final_check = &final_check,
- .print = NULL,
- .save = NULL,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(0),
+ .userspacesize = XT_ALIGN(0),
};
-void ipt_unclean_init(void)
+void libipt_unclean_init(void)
{
- register_match(&unclean);
+ xtables_register_match(&unclean_mt_reg);
}
diff --git a/extensions/libxt_CLASSIFY.c b/extensions/libxt_CLASSIFY.c
new file mode 100644
index 0000000..b46e629
--- /dev/null
+++ b/extensions/libxt_CLASSIFY.c
@@ -0,0 +1,115 @@
+/* Shared library add-on to iptables to add CLASSIFY target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CLASSIFY.h>
+#include <linux/types.h>
+#include <linux/pkt_sched.h>
+
+static void
+CLASSIFY_help(void)
+{
+ printf(
+"CLASSIFY target options:\n"
+"--set-class MAJOR:MINOR Set skb->priority value (always hexadecimal!)\n");
+}
+
+static const struct option CLASSIFY_opts[] = {
+ { "set-class", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static int CLASSIFY_string_to_priority(const char *s, unsigned int *p)
+{
+ unsigned int i, j;
+
+ if (sscanf(s, "%x:%x", &i, &j) != 2)
+ return 1;
+
+ *p = TC_H_MAKE(i<<16, j);
+ return 0;
+}
+
+static int
+CLASSIFY_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_classify_target_info *clinfo
+ = (struct xt_classify_target_info *)(*target)->data;
+
+ switch (c) {
+ case '1':
+ if (CLASSIFY_string_to_priority(optarg, &clinfo->priority))
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad class value `%s'", optarg);
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CLASSIFY: Can't specify --set-class twice");
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+CLASSIFY_final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CLASSIFY: Parameter --set-class is required");
+}
+
+static void
+CLASSIFY_print_class(unsigned int priority, int numeric)
+{
+ printf("%x:%x ", TC_H_MAJ(priority)>>16, TC_H_MIN(priority));
+}
+
+static void
+CLASSIFY_print(const void *ip,
+ const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_classify_target_info *clinfo =
+ (const struct xt_classify_target_info *)target->data;
+ printf("CLASSIFY set ");
+ CLASSIFY_print_class(clinfo->priority, numeric);
+}
+
+static void
+CLASSIFY_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 %.4x:%.4x ",
+ TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
+}
+
+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,
+ .parse = CLASSIFY_parse,
+ .final_check = CLASSIFY_final_check,
+ .print = CLASSIFY_print,
+ .save = CLASSIFY_save,
+ .extra_opts = CLASSIFY_opts,
+};
+
+void libxt_CLASSIFY_init(void)
+{
+ xtables_register_target(&classify_target);
+}
diff --git a/extensions/libxt_CLASSIFY.man b/extensions/libxt_CLASSIFY.man
new file mode 100644
index 0000000..0270fd1
--- /dev/null
+++ b/extensions/libxt_CLASSIFY.man
@@ -0,0 +1,5 @@
+This module allows you to set the skb\->priority value (and thus classify the packet into a specific CBQ class).
+.TP
+\fB\-\-set\-class\fP \fImajor\fP\fB:\fP\fIminor\fP
+Set the major and minor class value. The values are always interpreted as
+hexadecimal even if no 0x prefix is given.
diff --git a/extensions/libxt_CONNMARK.c b/extensions/libxt_CONNMARK.c
new file mode 100644
index 0000000..e63d04d
--- /dev/null
+++ b/extensions/libxt_CONNMARK.c
@@ -0,0 +1,445 @@
+/* Shared library add-on to iptables to add CONNMARK target support.
+ *
+ * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * Version 1.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNMARK.h>
+
+struct xt_connmark_target_info {
+ unsigned long mark;
+ unsigned long mask;
+ u_int8_t mode;
+};
+
+enum {
+ F_MARK = 1 << 0,
+ F_SR_MARK = 1 << 1,
+};
+
+static void CONNMARK_help(void)
+{
+ printf(
+"CONNMARK target options:\n"
+" --set-mark value[/mask] Set conntrack mark value\n"
+" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
+" --restore-mark [--mask mask] Restore saved nfmark value\n");
+}
+
+static const struct option CONNMARK_opts[] = {
+ { "set-mark", 1, NULL, '1' },
+ { "save-mark", 0, NULL, '2' },
+ { "restore-mark", 0, NULL, '3' },
+ { "mask", 1, NULL, '4' },
+ { .name = NULL }
+};
+
+static const struct option connmark_tg_opts[] = {
+ {.name = "set-xmark", .has_arg = true, .val = '='},
+ {.name = "set-mark", .has_arg = true, .val = '-'},
+ {.name = "and-mark", .has_arg = true, .val = '&'},
+ {.name = "or-mark", .has_arg = true, .val = '|'},
+ {.name = "xor-mark", .has_arg = true, .val = '^'},
+ {.name = "save-mark", .has_arg = false, .val = 'S'},
+ {.name = "restore-mark", .has_arg = false, .val = 'R'},
+ {.name = "ctmask", .has_arg = true, .val = 'c'},
+ {.name = "nfmask", .has_arg = true, .val = 'n'},
+ {.name = "mask", .has_arg = true, .val = 'm'},
+ {.name = NULL},
+};
+
+static void connmark_tg_help(void)
+{
+ printf(
+"CONNMARK target options:\n"
+" --set-xmark value[/ctmask] Zero mask bits and XOR ctmark with value\n"
+" --save-mark [--ctmask mask] [--nfmask mask]\n"
+" Copy ctmark to nfmark using masks\n"
+" --restore-mark [--ctmask mask] [--nfmask mask]\n"
+" Copy nfmark to ctmark using masks\n"
+" --set-mark value[/mask] Set conntrack mark value\n"
+" --save-mark [--mask mask] Save the packet nfmark in the connection\n"
+" --restore-mark [--mask mask] Restore saved nfmark value\n"
+" --and-mark value Binary AND the ctmark with bits\n"
+" --or-mark value Binary OR the ctmark with bits\n"
+" --xor-mark value Binary XOR the ctmark with bits\n"
+);
+}
+
+static void connmark_tg_init(struct xt_entry_target *target)
+{
+ struct xt_connmark_tginfo1 *info = (void *)target->data;
+
+ /*
+ * Need these defaults for --save-mark/--restore-mark if no
+ * --ctmark or --nfmask is given.
+ */
+ info->ctmask = UINT32_MAX;
+ info->nfmask = UINT32_MAX;
+}
+
+static int
+CONNMARK_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_connmark_target_info *markinfo
+ = (struct xt_connmark_target_info *)(*target)->data;
+
+ switch (c) {
+ char *end;
+ case '1':
+ markinfo->mode = XT_CONNMARK_SET;
+
+ markinfo->mark = strtoul(optarg, &end, 0);
+ if (*end == '/' && end[1] != '\0')
+ markinfo->mask = strtoul(end+1, &end, 0);
+
+ if (*end != '\0' || end == optarg)
+ xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CONNMARK target: Can't specify --set-mark twice");
+ *flags = 1;
+ break;
+ case '2':
+ markinfo->mode = XT_CONNMARK_SAVE;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CONNMARK target: Can't specify --save-mark twice");
+ *flags = 1;
+ break;
+ case '3':
+ markinfo->mode = XT_CONNMARK_RESTORE;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CONNMARK target: Can't specify --restore-mark twice");
+ *flags = 1;
+ break;
+ case '4':
+ if (!*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CONNMARK target: Can't specify --mask without a operation");
+ markinfo->mask = strtoul(optarg, &end, 0);
+
+ if (*end != '\0' || end == optarg)
+ xtables_error(PARAMETER_PROBLEM, "Bad MASK value \"%s\"", optarg);
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int connmark_tg_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_connmark_tginfo1 *info = (void *)(*target)->data;
+ unsigned int value, mask = UINT32_MAX;
+ char *end;
+
+ switch (c) {
+ case '=': /* --set-xmark */
+ case '-': /* --set-mark */
+ xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ if (*end == '/')
+ if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--set-xmark/--set-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = mask;
+ if (c == '-')
+ info->ctmask |= value;
+ *flags |= F_MARK;
+ return true;
+
+ case '&': /* --and-mark */
+ xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--and-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = 0;
+ info->ctmask = ~mask;
+ *flags |= F_MARK;
+ return true;
+
+ case '|': /* --or-mark */
+ xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--or-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = value;
+ *flags |= F_MARK;
+ return true;
+
+ case '^': /* --xor-mark */
+ xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--xor-mark", optarg);
+ info->mode = XT_CONNMARK_SET;
+ info->ctmark = value;
+ info->ctmask = 0;
+ *flags |= F_MARK;
+ return true;
+
+ case 'S': /* --save-mark */
+ xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ info->mode = XT_CONNMARK_SAVE;
+ *flags |= F_MARK | F_SR_MARK;
+ return true;
+
+ case 'R': /* --restore-mark */
+ xtables_param_act(XTF_ONE_ACTION, "CONNMARK", *flags & F_MARK);
+ info->mode = XT_CONNMARK_RESTORE;
+ *flags |= F_MARK | F_SR_MARK;
+ return true;
+
+ case 'n': /* --nfmask */
+ if (!(*flags & F_SR_MARK))
+ xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--nfmask");
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--nfmask", optarg);
+ info->nfmask = value;
+ return true;
+
+ case 'c': /* --ctmask */
+ if (!(*flags & F_SR_MARK))
+ xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--ctmask");
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--ctmask", optarg);
+ info->ctmask = value;
+ return true;
+
+ case 'm': /* --mask */
+ if (!(*flags & F_SR_MARK))
+ xtables_error(PARAMETER_PROBLEM, "CONNMARK: --save-mark "
+ "or --restore-mark is required for "
+ "--mask");
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "CONNMARK", "--mask", optarg);
+ info->nfmask = info->ctmask = value;
+ return true;
+ }
+
+ return false;
+}
+
+static void connmark_tg_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "CONNMARK target: No operation specified");
+}
+
+static void
+print_mark(unsigned long mark)
+{
+ printf("0x%lx", mark);
+}
+
+static void
+print_mask(const char *text, unsigned long mask)
+{
+ if (mask != 0xffffffffUL)
+ printf("%s0x%lx", text, mask);
+}
+
+static void CONNMARK_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_connmark_target_info *markinfo =
+ (const struct xt_connmark_target_info *)target->data;
+ switch (markinfo->mode) {
+ case XT_CONNMARK_SET:
+ printf("CONNMARK set ");
+ print_mark(markinfo->mark);
+ print_mask("/", markinfo->mask);
+ printf(" ");
+ break;
+ case XT_CONNMARK_SAVE:
+ printf("CONNMARK save ");
+ print_mask("mask ", markinfo->mask);
+ printf(" ");
+ break;
+ case XT_CONNMARK_RESTORE:
+ printf("CONNMARK restore ");
+ print_mask("mask ", markinfo->mask);
+ break;
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE ");
+ break;
+ }
+}
+
+static void
+connmark_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_connmark_tginfo1 *info = (const void *)target->data;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ if (info->ctmark == 0)
+ printf("CONNMARK and 0x%x ",
+ (unsigned int)(u_int32_t)~info->ctmask);
+ else if (info->ctmark == info->ctmask)
+ printf("CONNMARK or 0x%x ", info->ctmark);
+ else if (info->ctmask == 0)
+ printf("CONNMARK xor 0x%x ", info->ctmark);
+ else if (info->ctmask == 0xFFFFFFFFU)
+ printf("CONNMARK set 0x%x ", info->ctmark);
+ else
+ printf("CONNMARK xset 0x%x/0x%x ",
+ info->ctmark, info->ctmask);
+ break;
+ case XT_CONNMARK_SAVE:
+ if (info->nfmask == UINT32_MAX && info->ctmask == UINT32_MAX)
+ printf("CONNMARK save ");
+ else if (info->nfmask == info->ctmask)
+ printf("CONNMARK save mask 0x%x ", info->nfmask);
+ else
+ printf("CONNMARK save nfmask 0x%x ctmask ~0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ if (info->ctmask == UINT32_MAX && info->nfmask == UINT32_MAX)
+ printf("CONNMARK restore ");
+ else if (info->ctmask == info->nfmask)
+ printf("CONNMARK restore mask 0x%x ", info->ctmask);
+ else
+ printf("CONNMARK restore ctmask 0x%x nfmask ~0x%x ",
+ info->ctmask, info->nfmask);
+ break;
+
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE");
+ break;
+ }
+}
+
+static void CONNMARK_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_connmark_target_info *markinfo =
+ (const struct xt_connmark_target_info *)target->data;
+
+ switch (markinfo->mode) {
+ case XT_CONNMARK_SET:
+ printf("--set-mark ");
+ print_mark(markinfo->mark);
+ print_mask("/", markinfo->mask);
+ printf(" ");
+ break;
+ case XT_CONNMARK_SAVE:
+ printf("--save-mark ");
+ print_mask("--mask ", markinfo->mask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ printf("--restore-mark ");
+ print_mask("--mask ", markinfo->mask);
+ break;
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE ");
+ break;
+ }
+}
+
+static void CONNMARK_init(struct xt_entry_target *t)
+{
+ struct xt_connmark_target_info *markinfo
+ = (struct xt_connmark_target_info *)t->data;
+
+ markinfo->mask = 0xffffffffUL;
+}
+
+static void
+connmark_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_connmark_tginfo1 *info = (const void *)target->data;
+
+ switch (info->mode) {
+ case XT_CONNMARK_SET:
+ printf("--set-xmark 0x%x/0x%x ", info->ctmark, info->ctmask);
+ break;
+ case XT_CONNMARK_SAVE:
+ printf("--save-mark --nfmask 0x%x --ctmask 0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ case XT_CONNMARK_RESTORE:
+ printf("--restore-mark --nfmask 0x%x --ctmask 0x%x ",
+ info->nfmask, info->ctmask);
+ break;
+ default:
+ printf("ERROR: UNKNOWN CONNMARK MODE");
+ break;
+ }
+}
+
+static struct xtables_target connmark_tg_reg[] = {
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "CONNMARK",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_target_info)),
+ .help = CONNMARK_help,
+ .init = CONNMARK_init,
+ .parse = CONNMARK_parse,
+ .final_check = connmark_tg_check,
+ .print = CONNMARK_print,
+ .save = CONNMARK_save,
+ .extra_opts = CONNMARK_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "CONNMARK",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_tginfo1)),
+ .help = connmark_tg_help,
+ .init = connmark_tg_init,
+ .parse = connmark_tg_parse,
+ .final_check = connmark_tg_check,
+ .print = connmark_tg_print,
+ .save = connmark_tg_save,
+ .extra_opts = connmark_tg_opts,
+ },
+};
+
+void libxt_CONNMARK_init(void)
+{
+ xtables_register_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
+}
diff --git a/extensions/libxt_CONNMARK.man b/extensions/libxt_CONNMARK.man
new file mode 100644
index 0000000..13c6b4b
--- /dev/null
+++ b/extensions/libxt_CONNMARK.man
@@ -0,0 +1,53 @@
+This module sets the netfilter mark value associated with a connection. The
+mark is 32 bits wide.
+.TP
+\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zero out the bits given by \fImask\fR and XOR \fIvalue\fR into the ctmark.
+.TP
+\fB\-\-save\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
+Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
+masks. The new nfmark value is determined as follows:
+.IP
+ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
+.IP
+i.e. \fIctmask\fR defines what bits to clear and \fInfmask\fR what bits of the
+nfmark to XOR into the ctmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.TP
+\fB\-\-restore\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
+Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
+masks. The new ctmark value is determined as follows:
+.IP
+nfmark = (nfmark & ~\fInfmask\fR) ^ (ctmark & \fIctmask\fR);
+.IP
+i.e. \fInfmask\fR defines what bits to clear and \fIctmask\fR what bits of the
+ctmark to XOR into the nfmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.IP
+\fB\-\-restore\-mark\fP is only valid in the \fBmangle\fP table.
+.PP
+The following mnemonics are available for \fB\-\-set\-xmark\fP:
+.TP
+\fB\-\-and\-mark\fP \fIbits\fP
+Binary AND the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-mark\fP \fIbits\fP
+Binary OR the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-mark\fP \fIbits\fP
+Binary XOR the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/0\fR.)
+.TP
+\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Set the connection mark. If a mask is specified then only those bits set in the
+mask are modified.
+.TP
+\fB\-\-save\-mark\fP [\fB\-\-mask\fP \fImask\fP]
+Copy the nfmark to the ctmark. If a mask is specified, only those bits are
+copied.
+.TP
+\fB\-\-restore\-mark\fP [\fB\-\-mask\fP \fImask\fP]
+Copy the ctmark to the nfmark. If a mask is specified, only those bits are
+copied. This is only valid in the \fBmangle\fR table.
diff --git a/extensions/libxt_CONNSECMARK.c b/extensions/libxt_CONNSECMARK.c
new file mode 100644
index 0000000..22f2d64
--- /dev/null
+++ b/extensions/libxt_CONNSECMARK.c
@@ -0,0 +1,127 @@
+/*
+ * Shared library add-on to iptables to add CONNSECMARK target support.
+ *
+ * Based on the MARK and CONNMARK targets.
+ *
+ * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+
+#define PFX "CONNSECMARK target: "
+
+static void CONNSECMARK_help(void)
+{
+ printf(
+"CONNSECMARK target options:\n"
+" --save Copy security mark from packet to conntrack\n"
+" --restore Copy security mark from connection to packet\n");
+}
+
+static const struct option CONNSECMARK_opts[] = {
+ { "save", 0, NULL, '1' },
+ { "restore", 0, NULL, '2' },
+ { .name = NULL }
+};
+
+static int
+CONNSECMARK_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_connsecmark_target_info *info =
+ (struct xt_connsecmark_target_info*)(*target)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & CONNSECMARK_SAVE)
+ xtables_error(PARAMETER_PROBLEM, PFX
+ "Can't specify --save twice");
+ info->mode = CONNSECMARK_SAVE;
+ *flags |= CONNSECMARK_SAVE;
+ break;
+
+ case '2':
+ if (*flags & CONNSECMARK_RESTORE)
+ xtables_error(PARAMETER_PROBLEM, PFX
+ "Can't specify --restore twice");
+ info->mode = CONNSECMARK_RESTORE;
+ *flags |= CONNSECMARK_RESTORE;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void CONNSECMARK_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM, PFX "parameter required");
+
+ if (flags == (CONNSECMARK_SAVE|CONNSECMARK_RESTORE))
+ xtables_error(PARAMETER_PROBLEM, PFX "only one flag of --save "
+ "or --restore is allowed");
+}
+
+static void print_connsecmark(const struct xt_connsecmark_target_info *info)
+{
+ switch (info->mode) {
+ case CONNSECMARK_SAVE:
+ printf("save ");
+ break;
+
+ case CONNSECMARK_RESTORE:
+ printf("restore ");
+ break;
+
+ default:
+ xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+ }
+}
+
+static void
+CONNSECMARK_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_connsecmark_target_info *info =
+ (struct xt_connsecmark_target_info*)(target)->data;
+
+ printf("CONNSECMARK ");
+ print_connsecmark(info);
+}
+
+static void
+CONNSECMARK_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_connsecmark_target_info *info =
+ (struct xt_connsecmark_target_info*)target->data;
+
+ printf("--");
+ print_connsecmark(info);
+}
+
+static struct xtables_target connsecmark_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "CONNSECMARK",
+ .version = XTABLES_VERSION,
+ .revision = 0,
+ .size = XT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connsecmark_target_info)),
+ .parse = CONNSECMARK_parse,
+ .help = CONNSECMARK_help,
+ .final_check = CONNSECMARK_check,
+ .print = CONNSECMARK_print,
+ .save = CONNSECMARK_save,
+ .extra_opts = CONNSECMARK_opts,
+};
+
+void libxt_CONNSECMARK_init(void)
+{
+ xtables_register_target(&connsecmark_target);
+}
diff --git a/extensions/libip6t_CONNSECMARK.man b/extensions/libxt_CONNSECMARK.man
index b94353a..a72e710 100644
--- a/extensions/libip6t_CONNSECMARK.man
+++ b/extensions/libxt_CONNSECMARK.man
@@ -5,11 +5,11 @@ only valid in the
.B mangle
table.
.TP
-.B --save
+\fB\-\-save\fP
If the packet has a security marking, copy it to the connection
if the connection is not marked.
.TP
-.B --restore
+\fB\-\-restore\fP
If the packet does not have a security marking, and the connection
does, copy the security marking from the connection to the packet.
diff --git a/extensions/libxt_DSCP.c b/extensions/libxt_DSCP.c
new file mode 100644
index 0000000..4381b93
--- /dev/null
+++ b/extensions/libxt_DSCP.c
@@ -0,0 +1,149 @@
+/* Shared library add-on to iptables for DSCP
+ *
+ * (C) 2000- 2002 by Matthew G. Marsh <mgm@paktronix.com>,
+ * Harald Welte <laforge@gnumonks.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ * libipt_DSCP.c borrowed heavily from libipt_TOS.c
+ *
+ * --set-class added by Iain Barnes
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_DSCP.h>
+
+/* This is evil, but it's my code - HW*/
+#include "dscp_helper.c"
+
+static void DSCP_help(void)
+{
+ printf(
+"DSCP target options\n"
+" --set-dscp value Set DSCP field in packet header to value\n"
+" This value can be in decimal (ex: 32)\n"
+" or in hex (ex: 0x20)\n"
+" --set-dscp-class class Set the DSCP field in packet header to the\n"
+" value represented by the DiffServ class value.\n"
+" This class may be EF,BE or any of the CSxx\n"
+" or AFxx classes.\n"
+"\n"
+" These two options are mutually exclusive !\n"
+);
+}
+
+static const struct option DSCP_opts[] = {
+ { "set-dscp", 1, NULL, 'F' },
+ { "set-dscp-class", 1, NULL, 'G' },
+ { .name = NULL }
+};
+
+static void
+parse_dscp(const char *s, struct xt_DSCP_info *dinfo)
+{
+ unsigned int dscp;
+
+ if (!xtables_strtoui(s, NULL, &dscp, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid dscp `%s'\n", s);
+
+ if (dscp > XT_DSCP_MAX)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP `%d` out of range\n", dscp);
+
+ dinfo->dscp = dscp;
+}
+
+
+static void
+parse_class(const char *s, struct xt_DSCP_info *dinfo)
+{
+ unsigned int dscp = class_to_dscp(s);
+
+ /* Assign the value */
+ dinfo->dscp = dscp;
+}
+
+
+static int DSCP_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_DSCP_info *dinfo
+ = (struct xt_DSCP_info *)(*target)->data;
+
+ switch (c) {
+ case 'F':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP target: Only use --set-dscp ONCE!");
+ parse_dscp(optarg, dinfo);
+ *flags = 1;
+ break;
+ case 'G':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP target: Only use --set-dscp-class ONCE!");
+ parse_class(optarg, dinfo);
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void DSCP_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP target: Parameter --set-dscp is required");
+}
+
+static void
+print_dscp(u_int8_t dscp, int numeric)
+{
+ printf("0x%02x ", dscp);
+}
+
+static void DSCP_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_DSCP_info *dinfo =
+ (const struct xt_DSCP_info *)target->data;
+ printf("DSCP set ");
+ print_dscp(dinfo->dscp, numeric);
+}
+
+static void DSCP_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_DSCP_info *dinfo =
+ (const struct xt_DSCP_info *)target->data;
+
+ printf("--set-dscp 0x%02x ", dinfo->dscp);
+}
+
+static struct xtables_target dscp_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "DSCP",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_DSCP_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_DSCP_info)),
+ .help = DSCP_help,
+ .parse = DSCP_parse,
+ .final_check = DSCP_check,
+ .print = DSCP_print,
+ .save = DSCP_save,
+ .extra_opts = DSCP_opts,
+};
+
+void libxt_DSCP_init(void)
+{
+ xtables_register_target(&dscp_target);
+}
diff --git a/extensions/libipt_DSCP.man b/extensions/libxt_DSCP.man
index e8e5cf5..551ba2e 100644
--- a/extensions/libipt_DSCP.man
+++ b/extensions/libxt_DSCP.man
@@ -2,8 +2,8 @@ This target allows to alter the value of the DSCP bits within the TOS
header of the IPv4 packet. As this manipulates a packet, it can only
be used in the mangle table.
.TP
-.BI "--set-dscp " "value"
+\fB\-\-set\-dscp\fP \fIvalue\fP
Set the DSCP field to a numerical value (can be decimal or hex)
.TP
-.BI "--set-dscp-class " "class"
+\fB\-\-set\-dscp\-class\fP \fIclass\fP
Set the DSCP field to a DiffServ class.
diff --git a/extensions/libxt_MARK.c b/extensions/libxt_MARK.c
new file mode 100644
index 0000000..fcafa53
--- /dev/null
+++ b/extensions/libxt_MARK.c
@@ -0,0 +1,347 @@
+/* Shared library add-on to iptables to add MARK target support. */
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_MARK.h>
+
+/* Version 0 */
+struct xt_mark_target_info {
+ unsigned long mark;
+};
+
+/* Version 1 */
+enum {
+ XT_MARK_SET=0,
+ XT_MARK_AND,
+ XT_MARK_OR,
+};
+
+struct xt_mark_target_info_v1 {
+ unsigned long mark;
+ u_int8_t mode;
+};
+
+enum {
+ F_MARK = 1 << 0,
+};
+
+static void MARK_help(void)
+{
+ printf(
+"MARK target options:\n"
+" --set-mark value Set nfmark value\n"
+" --and-mark value Binary AND the nfmark with value\n"
+" --or-mark value Binary OR the nfmark with value\n");
+}
+
+static const struct option MARK_opts[] = {
+ { "set-mark", 1, NULL, '1' },
+ { "and-mark", 1, NULL, '2' },
+ { "or-mark", 1, NULL, '3' },
+ { .name = NULL }
+};
+
+static const struct option mark_tg_opts[] = {
+ {.name = "set-xmark", .has_arg = true, .val = 'X'},
+ {.name = "set-mark", .has_arg = true, .val = '='},
+ {.name = "and-mark", .has_arg = true, .val = '&'},
+ {.name = "or-mark", .has_arg = true, .val = '|'},
+ {.name = "xor-mark", .has_arg = true, .val = '^'},
+ { .name = NULL }
+};
+
+static void mark_tg_help(void)
+{
+ printf(
+"MARK target options:\n"
+" --set-xmark value[/mask] Clear bits in mask and XOR value into nfmark\n"
+" --set-mark value[/mask] Clear bits in mask and OR value into nfmark\n"
+" --and-mark bits Binary AND the nfmark with bits\n"
+" --or-mark bits Binary OR the nfmark with bits\n"
+" --xor-mask bits Binary XOR the nfmark with bits\n"
+"\n");
+}
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int
+MARK_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_mark_target_info *markinfo
+ = (struct xt_mark_target_info *)(*target)->data;
+ unsigned int mark = 0;
+
+ switch (c) {
+ case '1':
+ if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
+ markinfo->mark = mark;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK target: Can't specify --set-mark twice");
+ *flags = 1;
+ break;
+ case '2':
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK target: kernel too old for --and-mark");
+ case '3':
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK target: kernel too old for --or-mark");
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void MARK_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK target: Parameter --set/and/or-mark"
+ " is required");
+}
+
+static int
+MARK_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_mark_target_info_v1 *markinfo
+ = (struct xt_mark_target_info_v1 *)(*target)->data;
+ unsigned int mark = 0;
+
+ switch (c) {
+ case '1':
+ markinfo->mode = XT_MARK_SET;
+ break;
+ case '2':
+ markinfo->mode = XT_MARK_AND;
+ break;
+ case '3':
+ markinfo->mode = XT_MARK_OR;
+ break;
+ default:
+ return 0;
+ }
+
+ if (!xtables_strtoui(optarg, NULL, &mark, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
+ markinfo->mark = mark;
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "MARK target: Can't specify --set-mark twice");
+
+ *flags = 1;
+ return 1;
+}
+
+static int mark_tg_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_mark_tginfo2 *info = (void *)(*target)->data;
+ unsigned int value, mask = UINT32_MAX;
+ char *end;
+
+ switch (c) {
+ case 'X': /* --set-xmark */
+ case '=': /* --set-mark */
+ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
+ xtables_param_act(XTF_NO_INVERT, "MARK", "--set-xmark/--set-mark", invert);
+ if (!xtables_strtoui(optarg, &end, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
+ if (*end == '/')
+ if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "MARK", "--set-xmark/--set-mark", optarg);
+ info->mark = value;
+ info->mask = mask;
+
+ if (c == '=')
+ info->mask = value | mask;
+ break;
+
+ case '&': /* --and-mark */
+ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
+ xtables_param_act(XTF_NO_INVERT, "MARK", "--and-mark", invert);
+ if (!xtables_strtoui(optarg, NULL, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MARK", "--and-mark", optarg);
+ info->mark = 0;
+ info->mask = ~mask;
+ break;
+
+ case '|': /* --or-mark */
+ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
+ xtables_param_act(XTF_NO_INVERT, "MARK", "--or-mark", invert);
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MARK", "--or-mark", optarg);
+ info->mark = value;
+ info->mask = value;
+ break;
+
+ case '^': /* --xor-mark */
+ xtables_param_act(XTF_ONE_ACTION, "MARK", *flags & F_MARK);
+ xtables_param_act(XTF_NO_INVERT, "MARK", "--xor-mark", invert);
+ if (!xtables_strtoui(optarg, NULL, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "MARK", "--xor-mark", optarg);
+ info->mark = value;
+ info->mask = 0;
+ break;
+
+ default:
+ return false;
+ }
+
+ *flags |= F_MARK;
+ return true;
+}
+
+static void mark_tg_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
+ "--{and,or,xor,set}-mark options is required");
+}
+
+static void
+print_mark(unsigned long mark)
+{
+ printf("0x%lx ", mark);
+}
+
+static void MARK_print_v0(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_mark_target_info *markinfo =
+ (const struct xt_mark_target_info *)target->data;
+ printf("MARK set ");
+ print_mark(markinfo->mark);
+}
+
+static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_mark_target_info *markinfo =
+ (const struct xt_mark_target_info *)target->data;
+
+ printf("--set-mark ");
+ print_mark(markinfo->mark);
+}
+
+static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_mark_target_info_v1 *markinfo =
+ (const struct xt_mark_target_info_v1 *)target->data;
+
+ switch (markinfo->mode) {
+ case XT_MARK_SET:
+ printf("MARK set ");
+ break;
+ case XT_MARK_AND:
+ printf("MARK and ");
+ break;
+ case XT_MARK_OR:
+ printf("MARK or ");
+ break;
+ }
+ print_mark(markinfo->mark);
+}
+
+static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_mark_tginfo2 *info = (const void *)target->data;
+
+ if (info->mark == 0)
+ printf("MARK and 0x%x ", (unsigned int)(u_int32_t)~info->mask);
+ else if (info->mark == info->mask)
+ printf("MARK or 0x%x ", info->mark);
+ else if (info->mask == 0)
+ printf("MARK xor 0x%x ", info->mark);
+ else if (info->mask == 0xffffffffU)
+ printf("MARK set 0x%x ", info->mark);
+ else
+ printf("MARK xset 0x%x/0x%x ", info->mark, info->mask);
+}
+
+static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_mark_target_info_v1 *markinfo =
+ (const struct xt_mark_target_info_v1 *)target->data;
+
+ switch (markinfo->mode) {
+ case XT_MARK_SET:
+ printf("--set-mark ");
+ break;
+ case XT_MARK_AND:
+ printf("--and-mark ");
+ break;
+ case XT_MARK_OR:
+ printf("--or-mark ");
+ break;
+ }
+ print_mark(markinfo->mark);
+}
+
+static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_mark_tginfo2 *info = (const void *)target->data;
+
+ printf("--set-xmark 0x%x/0x%x ", info->mark, info->mask);
+}
+
+static struct xtables_target mark_tg_reg[] = {
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "MARK",
+ .version = XTABLES_VERSION,
+ .revision = 0,
+ .size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
+ .help = MARK_help,
+ .parse = MARK_parse_v0,
+ .final_check = MARK_check,
+ .print = MARK_print_v0,
+ .save = MARK_save_v0,
+ .extra_opts = MARK_opts,
+ },
+ {
+ .family = NFPROTO_IPV4,
+ .name = "MARK",
+ .version = XTABLES_VERSION,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
+ .help = MARK_help,
+ .parse = MARK_parse_v1,
+ .final_check = MARK_check,
+ .print = MARK_print_v1,
+ .save = MARK_save_v1,
+ .extra_opts = MARK_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "MARK",
+ .revision = 2,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
+ .help = mark_tg_help,
+ .parse = mark_tg_parse,
+ .final_check = mark_tg_check,
+ .print = mark_tg_print,
+ .save = mark_tg_save,
+ .extra_opts = mark_tg_opts,
+ },
+};
+
+void libxt_MARK_init(void)
+{
+ xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
+}
diff --git a/extensions/libxt_MARK.man b/extensions/libxt_MARK.man
new file mode 100644
index 0000000..98be812
--- /dev/null
+++ b/extensions/libxt_MARK.man
@@ -0,0 +1,26 @@
+This target is used to set the Netfilter mark value associated with the packet.
+The target can only be used in the \fBmangle\fR table. It can, for example, be
+used in conjunction with routing based on fwmark (needs iproute2). The mark
+field is 32 bits wide.
+.TP
+\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the packet
+mark ("nfmark"). If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.TP
+\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and ORs \fIvalue\fR into the packet
+mark. If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.PP
+The following mnemonics are available:
+.TP
+\fB\-\-and\-mark\fP \fIbits\fP
+Binary AND the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-mark\fP \fIbits\fP
+Binary OR the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-mark\fP \fIbits\fP
+Binary XOR the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/0\fR.)
diff --git a/extensions/libip6t_NFLOG.c b/extensions/libxt_NFLOG.c
index c2a3dbd..1a406ea 100644
--- a/extensions/libip6t_NFLOG.c
+++ b/extensions/libxt_NFLOG.c
@@ -2,9 +2,9 @@
#include <stdio.h>
#include <string.h>
#include <getopt.h>
-#include <ip6tables.h>
+#include <xtables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_NFLOG.h>
enum {
@@ -14,91 +14,91 @@ enum {
NFLOG_THRESHOLD = 0x8,
};
-static struct option opts[] = {
- { "nflog-group", 1, 0, NFLOG_GROUP },
- { "nflog-prefix", 1, 0, NFLOG_PREFIX },
- { "nflog-range", 1, 0, NFLOG_RANGE },
- { "nflog-threshold", 1, 0, NFLOG_THRESHOLD },
+static const struct option NFLOG_opts[] = {
+ { "nflog-group", 1, NULL, NFLOG_GROUP },
+ { "nflog-prefix", 1, NULL, NFLOG_PREFIX },
+ { "nflog-range", 1, NULL, NFLOG_RANGE },
+ { "nflog-threshold", 1, NULL, NFLOG_THRESHOLD },
+ { .name = NULL }
};
-static void help(void)
+static void NFLOG_help(void)
{
- printf("NFLOG v%s options:\n"
+ printf("NFLOG target options:\n"
" --nflog-group NUM NETLINK group used for logging\n"
" --nflog-range NUM Number of byte to copy\n"
" --nflog-threshold NUM Message threshold of in-kernel queue\n"
- " --nflog-prefix STRING Prefix string for log messages\n\n",
- IPTABLES_VERSION);
+ " --nflog-prefix STRING Prefix string for log messages\n");
}
-static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
+static void NFLOG_init(struct xt_entry_target *t)
{
struct xt_nflog_info *info = (struct xt_nflog_info *)t->data;
- info->group = XT_NFLOG_DEFAULT_GROUP;
+ info->group = 0;
info->threshold = XT_NFLOG_DEFAULT_THRESHOLD;
}
-static int parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- struct xt_entry_target **target)
+static int NFLOG_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
{
struct xt_nflog_info *info = (struct xt_nflog_info *)(*target)->data;
int n;
+ size_t length;
switch (c) {
case NFLOG_GROUP:
if (*flags & NFLOG_GROUP)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --nflog-group twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --nflog-group");
n = atoi(optarg);
- if (n < 1 || n > 32)
- exit_error(PARAMETER_PROBLEM,
- "--nflog-group has to be between 1 and 32");
- info->group = 1 << (n - 1);
+ if (n < 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "--nflog-group can not be negative");
+ info->group = n;
break;
case NFLOG_PREFIX:
if (*flags & NFLOG_PREFIX)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --nflog-prefix twice");
- if (check_inverse(optarg, &invert, NULL, 0))
- exit_error(PARAMETER_PROBLEM,
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM,
"Unexpected `!' after --nflog-prefix");
- n = strlen(optarg);
- if (n == 0)
- exit_error(PARAMETER_PROBLEM,
+ length = strlen(optarg);
+ if (length == 0)
+ xtables_error(PARAMETER_PROBLEM,
"No prefix specified for --nflog-prefix");
- if (n >= sizeof(info->prefix))
- exit_error(PARAMETER_PROBLEM,
+ if (length >= sizeof(info->prefix))
+ xtables_error(PARAMETER_PROBLEM,
"--nflog-prefix too long, max %Zu characters",
sizeof(info->prefix) - 1);
- if (n != strlen(strtok(optarg, "\n")))
- exit_error(PARAMETER_PROBLEM,
+ if (length != strlen(strtok(optarg, "\n")))
+ xtables_error(PARAMETER_PROBLEM,
"Newlines are not allowed in --nflog-prefix");
strcpy(info->prefix, optarg);
break;
case NFLOG_RANGE:
if (*flags & NFLOG_RANGE)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --nflog-range twice");
n = atoi(optarg);
if (n < 0)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid --nflog-range, must be >= 0");
info->len = n;
break;
case NFLOG_THRESHOLD:
if (*flags & NFLOG_THRESHOLD)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify --nflog-threshold twice");
n = atoi(optarg);
if (n < 1)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid --nflog-threshold, must be >= 1");
info->threshold = n;
break;
@@ -109,53 +109,50 @@ static int parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void final_check(unsigned int flags)
-{
- return;
-}
-
static void nflog_print(const struct xt_nflog_info *info, char *prefix)
{
- if (info->prefix[0] != '\0')
- printf("%snflog-prefix \"%s\" ", prefix, info->prefix);
- if (info->group != XT_NFLOG_DEFAULT_GROUP)
- printf("%snflog-group %u ", prefix, ffs(info->group));
+ if (info->prefix[0] != '\0') {
+ printf("%snflog-prefix ", prefix);
+ xtables_save_string(info->prefix);
+ }
+ if (info->group)
+ printf("%snflog-group %u ", prefix, info->group);
if (info->len)
printf("%snflog-range %u ", prefix, info->len);
if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
printf("%snflog-threshold %u ", prefix, info->threshold);
}
-static void print(const struct ip6t_ip6 *ip, const struct xt_entry_target *target,
- int numeric)
+static void NFLOG_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
{
const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
nflog_print(info, "");
}
-static void save(const struct ip6t_ip6 *ip, const struct xt_entry_target *target)
+static void NFLOG_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
nflog_print(info, "--");
}
-static struct ip6tables_target nflog = {
+static struct xtables_target nflog_target = {
+ .family = NFPROTO_UNSPEC,
.name = "NFLOG",
- .version = IPTABLES_VERSION,
+ .version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_nflog_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_nflog_info)),
- .help = help,
- .init = init,
- .parse = parse,
- .final_check = final_check,
- .print = print,
- .save = save,
- .extra_opts = opts,
+ .help = NFLOG_help,
+ .init = NFLOG_init,
+ .parse = NFLOG_parse,
+ .print = NFLOG_print,
+ .save = NFLOG_save,
+ .extra_opts = NFLOG_opts,
};
-void _init(void)
+void libxt_NFLOG_init(void)
{
- register_target6(&nflog);
+ xtables_register_target(&nflog_target);
}
diff --git a/extensions/libxt_NFLOG.man b/extensions/libxt_NFLOG.man
new file mode 100644
index 0000000..66f0b97
--- /dev/null
+++ b/extensions/libxt_NFLOG.man
@@ -0,0 +1,29 @@
+This target provides logging of matching packets. When this target is
+set for a rule, the Linux kernel will pass the packet to the loaded
+logging backend to log the packet. This is usually used in combination
+with nfnetlink_log as logging backend, which will multicast the packet
+through a
+.IR netlink
+socket to the specified multicast group. One or more userspace processes
+may subscribe to the group to receive the packets. Like LOG, this is a
+non-terminating target, i.e. rule traversal continues at the next rule.
+.TP
+\fB\-\-nflog\-group\fP \fInlgroup\fP
+The netlink group (1 \- 2^32\-1) to which packets are (only applicable for
+nfnetlink_log). The default value is 0.
+.TP
+\fB\-\-nflog\-prefix\fP \fIprefix\fP
+A prefix string to include in the log message, up to 64 characters
+long, useful for distinguishing messages in the logs.
+.TP
+\fB\-\-nflog\-range\fP \fIsize\fP
+The number of bytes to be copied to userspace (only applicable for
+nfnetlink_log). nfnetlink_log instances may specify their own
+range, this option overrides it.
+.TP
+\fB\-\-nflog\-threshold\fP \fIsize\fP
+Number of packets to queue inside the kernel before sending them
+to userspace (only applicable for nfnetlink_log). Higher values
+result in less overhead per packet, but increase delay until the
+packets reach userspace. The default value is 1.
+.BR
diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c
new file mode 100644
index 0000000..29edbc7
--- /dev/null
+++ b/extensions/libxt_NFQUEUE.c
@@ -0,0 +1,204 @@
+/* Shared library add-on to iptables for NFQ
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_NFQUEUE.h>
+
+static void NFQUEUE_help(void)
+{
+ printf(
+"NFQUEUE target options\n"
+" --queue-num value Send packet to QUEUE number <value>.\n"
+" Valid queue numbers are 0-65535\n"
+);
+}
+
+static void NFQUEUE_help_v1(void)
+{
+ NFQUEUE_help();
+ printf(
+" --queue-balance first:last Balance flows between queues <value> to <value>.\n");
+}
+
+static const struct option NFQUEUE_opts[] = {
+ { "queue-num", 1, NULL, 'F' },
+ { "queue-balance", 1, NULL, 'B' },
+ { .name = NULL }
+};
+
+static void exit_badqueue(const char *s)
+{
+ xtables_error(PARAMETER_PROBLEM, "Invalid queue number `%s'\n", s);
+}
+
+static void
+parse_num(const char *s, struct xt_NFQ_info *tinfo)
+{
+ unsigned int num;
+
+ if (!xtables_strtoui(s, NULL, &num, 0, UINT16_MAX))
+ exit_badqueue(s);
+
+ tinfo->queuenum = num;
+}
+
+static int
+NFQUEUE_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_NFQ_info *tinfo
+ = (struct xt_NFQ_info *)(*target)->data;
+
+ switch (c) {
+ case 'F':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
+ "Only use --queue-num ONCE!");
+ parse_num(optarg, tinfo);
+ break;
+ case 'B':
+ xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
+ "--queue-balance not supported (kernel too old?)");
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int
+NFQUEUE_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_NFQ_info_v1 *info = (void *)(*target)->data;
+ char *colon;
+ unsigned int firstqueue, lastqueue;
+
+ switch (c) {
+ case 'F': /* fallthrough */
+ case 'B':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
+ "Only use --queue-num ONCE!");
+
+ if (!xtables_strtoui(optarg, &colon, &firstqueue, 0, UINT16_MAX))
+ exit_badqueue(optarg);
+
+ info->queuenum = firstqueue;
+
+ if (c == 'F') {
+ if (*colon)
+ exit_badqueue(optarg);
+ break;
+ }
+
+ if (*colon != ':')
+ xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", optarg);
+
+ if (!xtables_strtoui(colon + 1, NULL, &lastqueue, 1, UINT16_MAX))
+ exit_badqueue(optarg);
+
+ if (firstqueue >= lastqueue)
+ xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
+ firstqueue, lastqueue);
+ info->queues_total = lastqueue - firstqueue + 1;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void NFQUEUE_print(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_NFQ_info *tinfo =
+ (const struct xt_NFQ_info *)target->data;
+ printf("NFQUEUE num %u", tinfo->queuenum);
+}
+
+static void NFQUEUE_print_v1(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
+ unsigned int last = tinfo->queues_total;
+
+ if (last > 1) {
+ last += tinfo->queuenum - 1;
+ printf("NFQUEUE balance %u:%u", tinfo->queuenum, last);
+ } else {
+ printf("NFQUEUE num %u", tinfo->queuenum);
+ }
+}
+
+static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_NFQ_info *tinfo =
+ (const struct xt_NFQ_info *)target->data;
+
+ printf("--queue-num %u ", tinfo->queuenum);
+}
+
+static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
+ unsigned int last = tinfo->queues_total;
+
+ if (last > 1) {
+ last += tinfo->queuenum - 1;
+ printf("--queue-balance %u:%u ", tinfo->queuenum, last);
+ } else {
+ printf("--queue-num %u ", tinfo->queuenum);
+ }
+}
+
+static void NFQUEUE_init_v1(struct xt_entry_target *t)
+{
+ struct xt_NFQ_info_v1 *tinfo = (void *)t->data;
+ tinfo->queues_total = 1;
+}
+
+static struct xtables_target nfqueue_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "NFQUEUE",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
+ .help = NFQUEUE_help,
+ .parse = NFQUEUE_parse,
+ .print = NFQUEUE_print,
+ .save = NFQUEUE_save,
+ .extra_opts = NFQUEUE_opts
+};
+
+static struct xtables_target nfqueue_target_v1 = {
+ .family = NFPROTO_UNSPEC,
+ .revision = 1,
+ .name = "NFQUEUE",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
+ .help = NFQUEUE_help_v1,
+ .init = NFQUEUE_init_v1,
+ .parse = NFQUEUE_parse_v1,
+ .print = NFQUEUE_print_v1,
+ .save = NFQUEUE_save_v1,
+ .extra_opts = NFQUEUE_opts,
+};
+
+void libxt_NFQUEUE_init(void)
+{
+ xtables_register_target(&nfqueue_target);
+ xtables_register_target(&nfqueue_target_v1);
+}
diff --git a/extensions/libxt_NFQUEUE.man b/extensions/libxt_NFQUEUE.man
new file mode 100644
index 0000000..59eddfc
--- /dev/null
+++ b/extensions/libxt_NFQUEUE.man
@@ -0,0 +1,18 @@
+This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
+you to put a packet into any specific queue, identified by its 16-bit queue
+number.
+It can only be used with Kernel versions 2.6.14 or later, since it requires
+the
+.B
+nfnetlink_queue
+kernel support. The \fBqueue-balance\fP option was added in Linux 2.6.31.
+.TP
+\fB\-\-queue\-num\fP \fIvalue\fP
+This specifies the QUEUE number to use. Valid queue numbers are 0 to 65535. The default value is 0.
+.PP
+.TP
+\fB\-\-queue\-balance\fP \fIvalue\fP\fB:\fP\fIvalue\fP
+This specifies a range of queues to use. Packets are then balanced across the given queues.
+This is useful for multicore systems: start multiple instances of the userspace program on
+queues x, x+1, .. x+n and use "\-\-queue\-balance \fIx\fP\fB:\fP\fIx+n\fP".
+Packets belonging to the same connection are put into the same nfqueue.
diff --git a/extensions/libxt_NOTRACK.c b/extensions/libxt_NOTRACK.c
new file mode 100644
index 0000000..5c3d866
--- /dev/null
+++ b/extensions/libxt_NOTRACK.c
@@ -0,0 +1,15 @@
+/* Shared library add-on to iptables to add NOTRACK target support. */
+#include <xtables.h>
+
+static struct xtables_target notrack_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "NOTRACK",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(0),
+ .userspacesize = XT_ALIGN(0),
+};
+
+void libxt_NOTRACK_init(void)
+{
+ xtables_register_target(&notrack_target);
+}
diff --git a/extensions/libipt_NOTRACK.man b/extensions/libxt_NOTRACK.man
index 30e830a..c2cdf5a 100644
--- a/extensions/libipt_NOTRACK.man
+++ b/extensions/libxt_NOTRACK.man
@@ -1,5 +1,5 @@
This target disables connection tracking for all packets matching that rule.
-.TP
+.PP
It can only be used in the
.B raw
table.
diff --git a/extensions/libxt_RATEEST.c b/extensions/libxt_RATEEST.c
new file mode 100644
index 0000000..794bd37
--- /dev/null
+++ b/extensions/libxt_RATEEST.c
@@ -0,0 +1,222 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+#include <math.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_RATEEST.h>
+
+/* hack to pass raw values to final_check */
+static struct xt_rateest_target_info *RATEEST_info;
+static unsigned int interval;
+static unsigned int ewma_log;
+
+static void
+RATEEST_help(void)
+{
+ printf(
+"RATEEST target options:\n"
+" --rateest-name name Rate estimator name\n"
+" --rateest-interval sec Rate measurement interval in seconds\n"
+" --rateest-ewmalog value Rate measurement averaging time constant\n");
+}
+
+enum RATEEST_options {
+ RATEEST_OPT_NAME,
+ RATEEST_OPT_INTERVAL,
+ RATEEST_OPT_EWMALOG,
+};
+
+static const struct option RATEEST_opts[] = {
+ { "rateest-name", 1, NULL, RATEEST_OPT_NAME },
+ { "rateest-interval", 1, NULL, RATEEST_OPT_INTERVAL },
+ { "rateest-ewmalog", 1, NULL, RATEEST_OPT_EWMALOG },
+ { .name = NULL },
+};
+
+/* Copied from iproute */
+#define TIME_UNITS_PER_SEC 1000000
+
+static int
+RATEEST_get_time(unsigned int *time, const char *str)
+{
+ double t;
+ char *p;
+
+ t = strtod(str, &p);
+ if (p == str)
+ return -1;
+
+ if (*p) {
+ if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
+ strcasecmp(p, "secs")==0)
+ t *= TIME_UNITS_PER_SEC;
+ else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
+ strcasecmp(p, "msecs") == 0)
+ t *= TIME_UNITS_PER_SEC/1000;
+ else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 ||
+ strcasecmp(p, "usecs") == 0)
+ t *= TIME_UNITS_PER_SEC/1000000;
+ else
+ return -1;
+ }
+
+ *time = t;
+ return 0;
+}
+
+static void
+RATEEST_print_time(unsigned int time)
+{
+ double tmp = time;
+
+ if (tmp >= TIME_UNITS_PER_SEC)
+ printf("%.1fs ", tmp/TIME_UNITS_PER_SEC);
+ else if (tmp >= TIME_UNITS_PER_SEC/1000)
+ printf("%.1fms ", tmp/(TIME_UNITS_PER_SEC/1000));
+ else
+ printf("%uus ", time);
+}
+
+static void
+RATEEST_init(struct xt_entry_target *target)
+{
+ interval = 0;
+ ewma_log = 0;
+}
+
+static int
+RATEEST_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_rateest_target_info *info = (void *)(*target)->data;
+
+ RATEEST_info = info;
+
+ switch (c) {
+ case RATEEST_OPT_NAME:
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: can't specify --rateest-name twice");
+ *flags |= 1 << c;
+
+ strncpy(info->name, optarg, sizeof(info->name) - 1);
+ break;
+
+ case RATEEST_OPT_INTERVAL:
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: can't specify --rateest-interval twice");
+ *flags |= 1 << c;
+
+ if (RATEEST_get_time(&interval, optarg) < 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: bad interval value `%s'", optarg);
+
+ break;
+
+ case RATEEST_OPT_EWMALOG:
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: can't specify --rateest-ewmalog twice");
+ *flags |= 1 << c;
+
+ if (RATEEST_get_time(&ewma_log, optarg) < 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: bad ewmalog value `%s'", optarg);
+
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+RATEEST_final_check(unsigned int flags)
+{
+ struct xt_rateest_target_info *info = RATEEST_info;
+
+ if (!(flags & (1 << RATEEST_OPT_NAME)))
+ xtables_error(PARAMETER_PROBLEM, "RATEEST: no name specified");
+ if (!(flags & (1 << RATEEST_OPT_INTERVAL)))
+ xtables_error(PARAMETER_PROBLEM, "RATEEST: no interval specified");
+ if (!(flags & (1 << RATEEST_OPT_EWMALOG)))
+ xtables_error(PARAMETER_PROBLEM, "RATEEST: no ewmalog specified");
+
+ for (info->interval = 0; info->interval <= 5; info->interval++) {
+ if (interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4))
+ break;
+ }
+
+ if (info->interval > 5)
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: interval value is too large");
+ info->interval -= 2;
+
+ for (info->ewma_log = 1; info->ewma_log < 32; info->ewma_log++) {
+ double w = 1.0 - 1.0 / (1 << info->ewma_log);
+ if (interval / (-log(w)) > ewma_log)
+ break;
+ }
+ info->ewma_log--;
+
+ if (info->ewma_log == 0 || info->ewma_log >= 31)
+ xtables_error(PARAMETER_PROBLEM,
+ "RATEEST: ewmalog value is out of range");
+}
+
+static void
+__RATEEST_print(const struct xt_entry_target *target, const char *prefix)
+{
+ const struct xt_rateest_target_info *info = (const void *)target->data;
+ unsigned int local_interval;
+ unsigned int local_ewma_log;
+
+ local_interval = (TIME_UNITS_PER_SEC << (info->interval + 2)) / 4;
+ local_ewma_log = local_interval * (1 << (info->ewma_log));
+
+ printf("%sname %s ", prefix, info->name);
+ printf("%sinterval ", prefix);
+ RATEEST_print_time(local_interval);
+ printf("%sewmalog ", prefix);
+ RATEEST_print_time(local_ewma_log);
+}
+
+static void
+RATEEST_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ __RATEEST_print(target, "");
+}
+
+static void
+RATEEST_save(const void *ip, const struct xt_entry_target *target)
+{
+ __RATEEST_print(target, "--rateest-");
+}
+
+static struct xtables_target rateest_tg_reg = {
+ .family = NFPROTO_UNSPEC,
+ .name = "RATEEST",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
+ .help = RATEEST_help,
+ .init = RATEEST_init,
+ .parse = RATEEST_parse,
+ .final_check = RATEEST_final_check,
+ .print = RATEEST_print,
+ .save = RATEEST_save,
+ .extra_opts = RATEEST_opts,
+};
+
+void libxt_RATEEST_init(void)
+{
+ xtables_register_target(&rateest_tg_reg);
+}
diff --git a/extensions/libxt_RATEEST.man b/extensions/libxt_RATEEST.man
new file mode 100644
index 0000000..37de759
--- /dev/null
+++ b/extensions/libxt_RATEEST.man
@@ -0,0 +1,12 @@
+The RATEEST target collects statistics, performs rate estimation calculation
+and saves the results for later evaluation using the \fBrateest\fP match.
+.TP
+\fB\-\-rateest\-name\fP \fIname\fP
+Count matched packets into the pool referred to by \fIname\fP, which is freely
+choosable.
+.TP
+\fB\-\-rateest\-interval\fP \fIamount\fP{\fBs\fP|\fBms\fP|\fBus\fP}
+Rate measurement interval, in seconds, milliseconds or microseconds.
+.TP
+\fB\-\-rateest\-ewmalog\fP \fIvalue\fP
+Rate measurement averaging time constant.
diff --git a/extensions/libxt_SECMARK.c b/extensions/libxt_SECMARK.c
new file mode 100644
index 0000000..ed6683d
--- /dev/null
+++ b/extensions/libxt_SECMARK.c
@@ -0,0 +1,113 @@
+/*
+ * Shared library add-on to iptables to add SECMARK target support.
+ *
+ * Based on the MARK target.
+ *
+ * Copyright (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+#define PFX "SECMARK target: "
+
+static void SECMARK_help(void)
+{
+ printf(
+"SECMARK target options:\n"
+" --selctx value Set the SELinux security context\n");
+}
+
+static const struct option SECMARK_opts[] = {
+ { "selctx", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static int SECMARK_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_secmark_target_info *info =
+ (struct xt_secmark_target_info*)(*target)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & SECMARK_MODE_SEL)
+ xtables_error(PARAMETER_PROBLEM, PFX
+ "Can't specify --selctx twice");
+ info->mode = SECMARK_MODE_SEL;
+
+ if (strlen(optarg) > SECMARK_SELCTX_MAX-1)
+ xtables_error(PARAMETER_PROBLEM, PFX
+ "Maximum length %u exceeded by --selctx"
+ " parameter (%zu)",
+ SECMARK_SELCTX_MAX-1, strlen(optarg));
+
+ strcpy(info->u.sel.selctx, optarg);
+ *flags |= SECMARK_MODE_SEL;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void SECMARK_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM, PFX "parameter required");
+}
+
+static void print_secmark(const struct xt_secmark_target_info *info)
+{
+ switch (info->mode) {
+ case SECMARK_MODE_SEL:
+ printf("selctx %s ", info->u.sel.selctx);\
+ break;
+
+ default:
+ xtables_error(OTHER_PROBLEM, PFX "invalid mode %hhu\n", info->mode);
+ }
+}
+
+static void SECMARK_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_secmark_target_info *info =
+ (struct xt_secmark_target_info*)(target)->data;
+
+ printf("SECMARK ");
+ print_secmark(info);
+}
+
+static void SECMARK_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_secmark_target_info *info =
+ (struct xt_secmark_target_info*)target->data;
+
+ printf("--");
+ print_secmark(info);
+}
+
+static struct xtables_target secmark_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "SECMARK",
+ .version = XTABLES_VERSION,
+ .revision = 0,
+ .size = XT_ALIGN(sizeof(struct xt_secmark_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_secmark_target_info)),
+ .help = SECMARK_help,
+ .parse = SECMARK_parse,
+ .final_check = SECMARK_check,
+ .print = SECMARK_print,
+ .save = SECMARK_save,
+ .extra_opts = SECMARK_opts,
+};
+
+void libxt_SECMARK_init(void)
+{
+ xtables_register_target(&secmark_target);
+}
diff --git a/extensions/libip6t_SECMARK.man b/extensions/libxt_SECMARK.man
index f892de9..e44efce 100644
--- a/extensions/libip6t_SECMARK.man
+++ b/extensions/libxt_SECMARK.man
@@ -2,6 +2,6 @@ This is used to set the security mark value associated with the
packet for use by security subsystems such as SELinux. It is only
valid in the
.B mangle
-table.
+table. The mark is 32 bits wide.
.TP
-.BI "--selctx " "security_context"
+\fB\-\-selctx\fP \fIsecurity_context\fP
diff --git a/extensions/libxt_TCPMSS.c b/extensions/libxt_TCPMSS.c
new file mode 100644
index 0000000..1436c57
--- /dev/null
+++ b/extensions/libxt_TCPMSS.c
@@ -0,0 +1,154 @@
+/* Shared library add-on to iptables to add TCPMSS target support.
+ *
+ * Copyright (c) 2000 Marc Boucher
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPMSS.h>
+
+struct mssinfo {
+ struct xt_entry_target t;
+ struct xt_tcpmss_info mss;
+};
+
+static void __TCPMSS_help(int hdrsize)
+{
+ printf(
+"TCPMSS target mutually-exclusive options:\n"
+" --set-mss value explicitly set MSS option to specified value\n"
+" --clamp-mss-to-pmtu automatically clamp MSS value to (path_MTU - %d)\n",
+hdrsize);
+}
+
+static void TCPMSS_help(void)
+{
+ __TCPMSS_help(40);
+}
+
+static void TCPMSS_help6(void)
+{
+ __TCPMSS_help(60);
+}
+
+static const struct option TCPMSS_opts[] = {
+ { "set-mss", 1, NULL, '1' },
+ { "clamp-mss-to-pmtu", 0, NULL, '2' },
+ { .name = NULL }
+};
+
+static int __TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target,
+ int hdrsize)
+{
+ struct xt_tcpmss_info *mssinfo
+ = (struct xt_tcpmss_info *)(*target)->data;
+
+ switch (c) {
+ unsigned int mssval;
+
+ case '1':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "TCPMSS target: Only one option may be specified");
+ if (!xtables_strtoui(optarg, NULL, &mssval,
+ 0, UINT16_MAX - hdrsize))
+ xtables_error(PARAMETER_PROBLEM, "Bad TCPMSS value \"%s\"", optarg);
+
+ mssinfo->mss = mssval;
+ *flags = 1;
+ break;
+
+ case '2':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "TCPMSS target: Only one option may be specified");
+ mssinfo->mss = XT_TCPMSS_CLAMP_PMTU;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int TCPMSS_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ return __TCPMSS_parse(c, argv, invert, flags, entry, target, 40);
+}
+
+static int TCPMSS_parse6(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ return __TCPMSS_parse(c, argv, invert, flags, entry, target, 60);
+}
+
+static void TCPMSS_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "TCPMSS target: At least one parameter is required");
+}
+
+static void TCPMSS_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_tcpmss_info *mssinfo =
+ (const struct xt_tcpmss_info *)target->data;
+ if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
+ printf("TCPMSS clamp to PMTU ");
+ else
+ printf("TCPMSS set %u ", mssinfo->mss);
+}
+
+static void TCPMSS_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_tcpmss_info *mssinfo =
+ (const struct xt_tcpmss_info *)target->data;
+
+ if(mssinfo->mss == XT_TCPMSS_CLAMP_PMTU)
+ printf("--clamp-mss-to-pmtu ");
+ else
+ printf("--set-mss %u ", mssinfo->mss);
+}
+
+static struct xtables_target tcpmss_target = {
+ .family = NFPROTO_IPV4,
+ .name = "TCPMSS",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
+ .help = TCPMSS_help,
+ .parse = TCPMSS_parse,
+ .final_check = TCPMSS_check,
+ .print = TCPMSS_print,
+ .save = TCPMSS_save,
+ .extra_opts = TCPMSS_opts,
+};
+
+static struct xtables_target tcpmss_target6 = {
+ .family = NFPROTO_IPV6,
+ .name = "TCPMSS",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_info)),
+ .help = TCPMSS_help6,
+ .parse = TCPMSS_parse6,
+ .final_check = TCPMSS_check,
+ .print = TCPMSS_print,
+ .save = TCPMSS_save,
+ .extra_opts = TCPMSS_opts,
+};
+
+void libxt_TCPMSS_init(void)
+{
+ xtables_register_target(&tcpmss_target);
+ xtables_register_target(&tcpmss_target6);
+}
diff --git a/extensions/libxt_TCPMSS.man b/extensions/libxt_TCPMSS.man
new file mode 100644
index 0000000..b5cb455
--- /dev/null
+++ b/extensions/libxt_TCPMSS.man
@@ -0,0 +1,50 @@
+This target allows to alter the MSS value of TCP SYN packets, to control
+the maximum size for that connection (usually limiting it to your
+outgoing interface's MTU minus 40 for IPv4 or 60 for IPv6, respectively).
+Of course, it can only be used
+in conjunction with
+\fB\-p tcp\fP.
+It is only valid in the
+.BR mangle
+table.
+.br
+This target is used to overcome criminally braindead ISPs or servers
+which block "ICMP Fragmentation Needed" or "ICMPv6 Packet Too Big"
+packets. The symptoms of this
+problem are that everything works fine from your Linux
+firewall/router, but machines behind it can never exchange large
+packets:
+.PD 0
+.RS 0.1i
+.TP 0.3i
+1)
+Web browsers connect, then hang with no data received.
+.TP
+2)
+Small mail works fine, but large emails hang.
+.TP
+3)
+ssh works fine, but scp hangs after initial handshaking.
+.RE
+.PD
+Workaround: activate this option and add a rule to your firewall
+configuration like:
+.IP
+ iptables \-t mangle \-A FORWARD \-p tcp \-\-tcp\-flags SYN,RST SYN
+ \-j TCPMSS \-\-clamp\-mss\-to\-pmtu
+.TP
+\fB\-\-set\-mss\fP \fIvalue\fP
+Explicitly sets MSS option to specified value. If the MSS of the packet is
+already lower than \fIvalue\fP, it will \fBnot\fP be increased (from Linux
+2.6.25 onwards) to avoid more problems with hosts relying on a proper MSS.
+.TP
+\fB\-\-clamp\-mss\-to\-pmtu\fP
+Automatically clamp MSS value to (path_MTU \- 40 for IPv4; \-60 for IPv6).
+This may not function as desired where asymmetric routes with differing
+path MTU exist \(em the kernel uses the path MTU which it would use to send
+packets from itself to the source and destination IP addresses. Prior to
+Linux 2.6.25, only the path MTU to the destination IP address was
+considered by this option; subsequent kernels also consider the path MTU
+to the source IP address.
+.PP
+These options are mutually exclusive.
diff --git a/extensions/libxt_TCPOPTSTRIP.c b/extensions/libxt_TCPOPTSTRIP.c
new file mode 100644
index 0000000..e901741
--- /dev/null
+++ b/extensions/libxt_TCPOPTSTRIP.c
@@ -0,0 +1,198 @@
+/*
+ * Shared library add-on to iptables to add TCPOPTSTRIP target support.
+ * Copyright (c) 2007 Sven Schnelle <svens@bitebene.org>
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <xtables.h>
+#include <netinet/tcp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TCPOPTSTRIP.h>
+#ifndef TCPOPT_MD5SIG
+# define TCPOPT_MD5SIG 19
+#endif
+
+enum {
+ FLAG_STRIP = 1 << 0,
+};
+
+struct tcp_optionmap {
+ const char *name, *desc;
+ const unsigned int option;
+};
+
+static const struct option tcpoptstrip_tg_opts[] = {
+ {.name = "strip-options", .has_arg = true, .val = 's'},
+ { .name = NULL }
+};
+
+static const struct tcp_optionmap tcp_optionmap[] = {
+ {"wscale", "Window scale", TCPOPT_WINDOW},
+ {"mss", "Maximum Segment Size", TCPOPT_MAXSEG},
+ {"sack-permitted", "SACK permitted", TCPOPT_SACK_PERMITTED},
+ {"sack", "Selective ACK", TCPOPT_SACK},
+ {"timestamp", "Timestamp", TCPOPT_TIMESTAMP},
+ {"md5", "MD5 signature", TCPOPT_MD5SIG},
+ { .name = NULL }
+};
+
+static void tcpoptstrip_tg_help(void)
+{
+ const struct tcp_optionmap *w;
+
+ printf(
+"TCPOPTSTRIP target options:\n"
+" --strip-options value strip specified TCP options denoted by value\n"
+" (separated by comma) from TCP header\n"
+" Instead of the numeric value, you can also use the following names:\n"
+ );
+
+ for (w = tcp_optionmap; w->name != NULL; ++w)
+ printf(" %-14s strip \"%s\" option\n", w->name, w->desc);
+}
+
+static void tcpoptstrip_tg_init(struct xt_entry_target *t)
+{
+ struct xt_tcpoptstrip_target_info *info = (void *)t->data;
+
+ /* strictly necessary? play safe for now. */
+ memset(info->strip_bmap, 0, sizeof(info->strip_bmap));
+}
+
+static void parse_list(struct xt_tcpoptstrip_target_info *info, char *arg)
+{
+ unsigned int option;
+ char *p;
+ int i;
+
+ while (true) {
+ p = strchr(arg, ',');
+ if (p != NULL)
+ *p = '\0';
+
+ option = 0;
+ for (i = 0; tcp_optionmap[i].name != NULL; ++i)
+ if (strcmp(tcp_optionmap[i].name, arg) == 0) {
+ option = tcp_optionmap[i].option;
+ break;
+ }
+
+ if (option == 0 &&
+ !xtables_strtoui(arg, NULL, &option, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad TCP option value \"%s\"", arg);
+
+ if (option < 2)
+ xtables_error(PARAMETER_PROBLEM,
+ "Option value may not be 0 or 1");
+
+ if (tcpoptstrip_test_bit(info->strip_bmap, option))
+ xtables_error(PARAMETER_PROBLEM,
+ "Option \"%s\" already specified", arg);
+
+ tcpoptstrip_set_bit(info->strip_bmap, option);
+ if (p == NULL)
+ break;
+ arg = p + 1;
+ }
+}
+
+static int tcpoptstrip_tg_parse(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_target **target)
+{
+ struct xt_tcpoptstrip_target_info *info = (void *)(*target)->data;
+
+ switch (c) {
+ case 's':
+ if (*flags & FLAG_STRIP)
+ xtables_error(PARAMETER_PROBLEM,
+ "You can specify --strip-options only once");
+ parse_list(info, optarg);
+ *flags |= FLAG_STRIP;
+ return true;
+ }
+
+ return false;
+}
+
+static void tcpoptstrip_tg_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "TCPOPTSTRIP: --strip-options parameter required");
+}
+
+static void
+tcpoptstrip_print_list(const struct xt_tcpoptstrip_target_info *info,
+ bool numeric)
+{
+ unsigned int i, j;
+ const char *name;
+ bool first = true;
+
+ for (i = 0; i < 256; ++i) {
+ if (!tcpoptstrip_test_bit(info->strip_bmap, i))
+ continue;
+ if (!first)
+ printf(",");
+
+ first = false;
+ name = NULL;
+ if (!numeric)
+ for (j = 0; tcp_optionmap[j].name != NULL; ++j)
+ if (tcp_optionmap[j].option == i)
+ name = tcp_optionmap[j].name;
+
+ if (name != NULL)
+ printf("%s", name);
+ else
+ printf("%u", i);
+ }
+}
+
+static void
+tcpoptstrip_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_tcpoptstrip_target_info *info =
+ (const void *)target->data;
+
+ printf("TCPOPTSTRIP options ");
+ tcpoptstrip_print_list(info, numeric);
+}
+
+static void
+tcpoptstrip_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_tcpoptstrip_target_info *info =
+ (const void *)target->data;
+
+ printf("--strip-options ");
+ tcpoptstrip_print_list(info, true);
+}
+
+static struct xtables_target tcpoptstrip_tg_reg = {
+ .version = XTABLES_VERSION,
+ .name = "TCPOPTSTRIP",
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpoptstrip_target_info)),
+ .help = tcpoptstrip_tg_help,
+ .init = tcpoptstrip_tg_init,
+ .parse = tcpoptstrip_tg_parse,
+ .final_check = tcpoptstrip_tg_check,
+ .print = tcpoptstrip_tg_print,
+ .save = tcpoptstrip_tg_save,
+ .extra_opts = tcpoptstrip_tg_opts,
+};
+
+void libxt_TCPOPTSTRIP_init(void)
+{
+ xtables_register_target(&tcpoptstrip_tg_reg);
+}
diff --git a/extensions/libxt_TCPOPTSTRIP.man b/extensions/libxt_TCPOPTSTRIP.man
new file mode 100644
index 0000000..2a07709
--- /dev/null
+++ b/extensions/libxt_TCPOPTSTRIP.man
@@ -0,0 +1,7 @@
+This target will strip TCP options off a TCP packet. (It will actually replace
+them by NO-OPs.) As such, you will need to add the \fB\-p tcp\fP parameters.
+.TP
+\fB\-\-strip\-options\fP \fIoption\fP[\fB,\fP\fIoption\fP...]
+Strip the given option(s). The options may be specified by TCP option number or
+by symbolic name. The list of recognized options can be obtained by calling
+iptables with \fB\-j TCPOPTSTRIP \-h\fP.
diff --git a/extensions/libxt_TOS.c b/extensions/libxt_TOS.c
new file mode 100644
index 0000000..1fff1f7
--- /dev/null
+++ b/extensions/libxt_TOS.c
@@ -0,0 +1,245 @@
+/*
+ * Shared library add-on to iptables to add TOS target support
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_DSCP.h>
+#include "tos_values.c"
+
+struct ipt_tos_target_info {
+ u_int8_t tos;
+};
+
+enum {
+ FLAG_TOS = 1 << 0,
+};
+
+static const struct option tos_tg_opts_v0[] = {
+ {.name = "set-tos", .has_arg = true, .val = '='},
+ { .name = NULL }
+};
+
+static const struct option tos_tg_opts[] = {
+ {.name = "set-tos", .has_arg = true, .val = '='},
+ {.name = "and-tos", .has_arg = true, .val = '&'},
+ {.name = "or-tos", .has_arg = true, .val = '|'},
+ {.name = "xor-tos", .has_arg = true, .val = '^'},
+ { .name = NULL }
+};
+
+static void tos_tg_help_v0(void)
+{
+ const struct tos_symbol_info *symbol;
+
+ printf(
+"TOS target options:\n"
+" --set-tos value Set Type of Service/Priority field to value\n"
+" --set-tos symbol Set TOS field (IPv4 only) by symbol\n"
+" Accepted symbolic names for value are:\n");
+
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ printf(" (0x%02x) %2u %s\n",
+ symbol->value, symbol->value, symbol->name);
+
+ printf("\n");
+}
+
+static void tos_tg_help(void)
+{
+ const struct tos_symbol_info *symbol;
+
+ printf(
+"TOS target v%s options:\n"
+" --set-tos value[/mask] Set Type of Service/Priority field to value\n"
+" (Zero out bits in mask and XOR value into TOS)\n"
+" --set-tos symbol Set TOS field (IPv4 only) by symbol\n"
+" (this zeroes the 4-bit Precedence part!)\n"
+" Accepted symbolic names for value are:\n",
+XTABLES_VERSION);
+
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ printf(" (0x%02x) %2u %s\n",
+ symbol->value, symbol->value, symbol->name);
+
+ printf(
+"\n"
+" --and-tos bits Binary AND the TOS value with bits\n"
+" --or-tos bits Binary OR the TOS value with bits\n"
+" --xor-tos bits Binary XOR the TOS value with bits\n"
+);
+}
+
+static int tos_tg_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct ipt_tos_target_info *info = (void *)(*target)->data;
+ struct tos_value_mask tvm;
+
+ switch (c) {
+ case '=':
+ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
+ xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert);
+ if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
+ xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg);
+ if (tvm.mask != 0xFF)
+ xtables_error(PARAMETER_PROBLEM, "tos match: Your kernel "
+ "is too old to support anything besides "
+ "/0xFF as a mask.");
+ info->tos = tvm.value;
+ *flags |= FLAG_TOS;
+ return true;
+ }
+
+ return false;
+}
+
+static int tos_tg_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_tos_target_info *info = (void *)(*target)->data;
+ struct tos_value_mask tvm;
+ unsigned int bits;
+
+ switch (c) {
+ case '=': /* --set-tos */
+ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--set-tos", *flags & FLAG_TOS);
+ xtables_param_act(XTF_NO_INVERT, "TOS", "--set-tos", invert);
+ if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
+ xtables_param_act(XTF_BAD_VALUE, "TOS", "--set-tos", optarg);
+ info->tos_value = tvm.value;
+ info->tos_mask = tvm.mask;
+ break;
+
+ case '&': /* --and-tos */
+ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--and-tos", *flags & FLAG_TOS);
+ xtables_param_act(XTF_NO_INVERT, "TOS", "--and-tos", invert);
+ if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "TOS", "--and-tos", optarg);
+ info->tos_value = 0;
+ info->tos_mask = ~bits;
+ break;
+
+ case '|': /* --or-tos */
+ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--or-tos", *flags & FLAG_TOS);
+ xtables_param_act(XTF_NO_INVERT, "TOS", "--or-tos", invert);
+ if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "TOS", "--or-tos", optarg);
+ info->tos_value = bits;
+ info->tos_mask = bits;
+ break;
+
+ case '^': /* --xor-tos */
+ xtables_param_act(XTF_ONLY_ONCE, "TOS", "--xor-tos", *flags & FLAG_TOS);
+ xtables_param_act(XTF_NO_INVERT, "TOS", "--xor-tos", invert);
+ if (!xtables_strtoui(optarg, NULL, &bits, 0, UINT8_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "TOS", "--xor-tos", optarg);
+ info->tos_value = bits;
+ info->tos_mask = 0;
+ break;
+
+ default:
+ return false;
+ }
+
+ *flags |= FLAG_TOS;
+ return true;
+}
+
+static void tos_tg_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "TOS: The --set-tos parameter is required");
+}
+
+static void tos_tg_print_v0(const void *ip,
+ const struct xt_entry_target *target, int numeric)
+{
+ const struct ipt_tos_target_info *info = (const void *)target->data;
+
+ printf("TOS set ");
+ if (numeric || !tos_try_print_symbolic("", info->tos, 0xFF))
+ printf("0x%02x ", info->tos);
+}
+
+static void tos_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_tos_target_info *info = (const void *)target->data;
+
+ if (numeric)
+ printf("TOS set 0x%02x/0x%02x ",
+ info->tos_value, info->tos_mask);
+ else if (tos_try_print_symbolic("TOS set ",
+ info->tos_value, info->tos_mask))
+ /* already printed by call */
+ return;
+ else if (info->tos_value == 0)
+ printf("TOS and 0x%02x ",
+ (unsigned int)(u_int8_t)~info->tos_mask);
+ else if (info->tos_value == info->tos_mask)
+ printf("TOS or 0x%02x ", info->tos_value);
+ else if (info->tos_mask == 0)
+ printf("TOS xor 0x%02x ", info->tos_value);
+ else
+ printf("TOS set 0x%02x/0x%02x ",
+ info->tos_value, info->tos_mask);
+}
+
+static void tos_tg_save_v0(const void *ip, const struct xt_entry_target *target)
+{
+ const struct ipt_tos_target_info *info = (const void *)target->data;
+
+ printf("--set-tos 0x%02x ", info->tos);
+}
+
+static void tos_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_tos_target_info *info = (const void *)target->data;
+
+ printf("--set-tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static struct xtables_target tos_tg_reg[] = {
+ {
+ .version = XTABLES_VERSION,
+ .name = "TOS",
+ .revision = 0,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+ .help = tos_tg_help_v0,
+ .parse = tos_tg_parse_v0,
+ .final_check = tos_tg_check,
+ .print = tos_tg_print_v0,
+ .save = tos_tg_save_v0,
+ .extra_opts = tos_tg_opts_v0,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "TOS",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tos_target_info)),
+ .help = tos_tg_help,
+ .parse = tos_tg_parse,
+ .final_check = tos_tg_check,
+ .print = tos_tg_print,
+ .save = tos_tg_save,
+ .extra_opts = tos_tg_opts,
+ },
+};
+
+void libxt_TOS_init(void)
+{
+ xtables_register_targets(tos_tg_reg, ARRAY_SIZE(tos_tg_reg));
+}
diff --git a/extensions/libxt_TOS.man b/extensions/libxt_TOS.man
new file mode 100644
index 0000000..d5cbfcb
--- /dev/null
+++ b/extensions/libxt_TOS.man
@@ -0,0 +1,27 @@
+This module sets the Type of Service field in the IPv4 header (including the
+"precedence" bits) or the Priority field in the IPv6 header. Note that TOS
+shares the same bits as DSCP and ECN. The TOS target is only valid in the
+\fBmangle\fR table.
+.TP
+\fB\-\-set\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the
+TOS/Priority field. If \fImask\fR is omitted, 0xFF is assumed.
+.TP
+\fB\-\-set\-tos\fP \fIsymbol\fP
+You can specify a symbolic name when using the TOS target for IPv4. It implies
+a mask of 0xFF. The list of recognized TOS names can be obtained by calling
+iptables with \fB\-j TOS \-h\fP.
+.PP
+The following mnemonics are available:
+.TP
+\fB\-\-and\-tos\fP \fIbits\fP
+Binary AND the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-tos\fP \fIbits\fP
+Binary OR the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-tos\fP \fIbits\fP
+Binary XOR the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos\fP
+\fIbits\fR\fB/0\fR.)
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
new file mode 100644
index 0000000..ab21eec
--- /dev/null
+++ b/extensions/libxt_TPROXY.c
@@ -0,0 +1,150 @@
+/*
+ * Shared library add-on to iptables to add TPROXY target support.
+ *
+ * Copyright (C) 2002-2008 BalaBit IT Ltd.
+ */
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_TPROXY.h>
+
+static const struct option tproxy_tg_opts[] = {
+ { .name = "on-port", .has_arg = 1, .val = '1'},
+ { .name = "on-ip", .has_arg = 1, .val = '2'},
+ { .name = "tproxy-mark", .has_arg = 1, .val = '3'},
+ {NULL},
+};
+
+enum {
+ PARAM_ONPORT = 1 << 0,
+ PARAM_ONIP = 1 << 1,
+ PARAM_MARK = 1 << 2,
+};
+
+static void tproxy_tg_help(void)
+{
+ printf(
+"TPROXY target options:\n"
+" --on-port port Redirect connection to port, or the original port if 0\n"
+" --on-ip ip Optionally redirect to the given IP\n"
+" --tproxy-mark value[/mask] Mark packets with the given value/mask\n\n");
+}
+
+static void parse_tproxy_lport(const char *s, struct xt_tproxy_target_info *info)
+{
+ unsigned int lport;
+
+ if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX))
+ info->lport = htons(lport);
+ else
+ xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s);
+}
+
+static void parse_tproxy_laddr(const char *s, struct xt_tproxy_target_info *info)
+{
+ struct in_addr *laddr;
+
+ if ((laddr = xtables_numeric_to_ipaddr(s)) == NULL)
+ xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-ip", s);
+
+ info->laddr = laddr->s_addr;
+}
+
+static void parse_tproxy_mark(char *s, struct xt_tproxy_target_info *info)
+{
+ unsigned int value, mask = UINT32_MAX;
+ char *end;
+
+ if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
+ if (*end == '/')
+ if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
+
+ info->mark_mask = mask;
+ info->mark_value = value;
+}
+
+static int tproxy_tg_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_target **target)
+{
+ struct xt_tproxy_target_info *tproxyinfo = (void *)(*target)->data;
+
+ switch (c) {
+ case '1':
+ xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT);
+ xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert);
+ parse_tproxy_lport(optarg, tproxyinfo);
+ *flags |= PARAM_ONPORT;
+ return 1;
+ case '2':
+ xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP);
+ xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert);
+ parse_tproxy_laddr(optarg, tproxyinfo);
+ *flags |= PARAM_ONIP;
+ return 1;
+ case '3':
+ xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK);
+ xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert);
+ parse_tproxy_mark(optarg, tproxyinfo);
+ *flags |= PARAM_MARK;
+ return 1;
+ }
+
+ return 0;
+}
+
+static void tproxy_tg_check(unsigned int flags)
+{
+ if (!(flags & PARAM_ONPORT))
+ xtables_error(PARAMETER_PROBLEM,
+ "TPROXY target: Parameter --on-port is required");
+}
+
+static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target,
+ int numeric)
+{
+ const struct xt_tproxy_target_info *info = (const void *)target->data;
+ printf("TPROXY redirect %s:%u mark 0x%x/0x%x",
+ xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr),
+ ntohs(info->lport), (unsigned int)info->mark_value,
+ (unsigned int)info->mark_mask);
+}
+
+static void tproxy_tg_save(const void *ip, const struct xt_entry_target *target)
+{
+ const struct xt_tproxy_target_info *info = (const void *)target->data;
+
+ printf("--on-port %u ", ntohs(info->lport));
+ printf("--on-ip %s ",
+ xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr));
+ printf("--tproxy-mark 0x%x/0x%x ",
+ (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
+}
+
+static struct xtables_target tproxy_tg_reg = {
+ .name = "TPROXY",
+ .family = NFPROTO_IPV4,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
+ .help = tproxy_tg_help,
+ .parse = tproxy_tg_parse,
+ .final_check = tproxy_tg_check,
+ .print = tproxy_tg_print,
+ .save = tproxy_tg_save,
+ .extra_opts = tproxy_tg_opts,
+};
+
+void libxt_TPROXY_init(void)
+{
+ xtables_register_target(&tproxy_tg_reg);
+}
diff --git a/extensions/libxt_TPROXY.man b/extensions/libxt_TPROXY.man
new file mode 100644
index 0000000..0129f84
--- /dev/null
+++ b/extensions/libxt_TPROXY.man
@@ -0,0 +1,21 @@
+This target is only valid in the \fBmangle\fR table, in the \fBPREROUTING\fR
+chain and user-defined chains which are only called from this chain. It
+redirects the packet to a local socket without changing the packet header in
+any way. It can also change the mark value which can then be used in advanced
+routing rules.
+It takes three options:
+.TP
+\fB\-\-on\-port\fP \fIport\fP
+This specifies a destination port to use. It is a required option, 0 means the
+new destination port is the same as the original. This is only valid if the
+rule also specifies \fB\-p tcp\fP or \fB\-p udp\fP.
+.TP
+\fB\-\-on\-ip\fP \fIaddress\fP
+This specifies a destination address to use. By default the address is the IP
+address of the incoming interface. This is only valid if the rule also
+specifies \fB\-p tcp\fP or \fB\-p udp\fP.
+.TP
+\fB\-\-tproxy\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Marks packets with the given value/mask. The fwmark value set here can be used
+by advanced routing. (Required for transparent proxying to work: otherwise
+these packets will get forwarded, which is probably not what you want.)
diff --git a/extensions/libxt_TRACE.c b/extensions/libxt_TRACE.c
new file mode 100644
index 0000000..672ff6b
--- /dev/null
+++ b/extensions/libxt_TRACE.c
@@ -0,0 +1,21 @@
+/* Shared library add-on to iptables to add TRACE target support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+
+static struct xtables_target trace_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "TRACE",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(0),
+ .userspacesize = XT_ALIGN(0),
+};
+
+void libxt_TRACE_init(void)
+{
+ xtables_register_target(&trace_target);
+}
diff --git a/extensions/libxt_TRACE.man b/extensions/libxt_TRACE.man
new file mode 100644
index 0000000..d28c3a0
--- /dev/null
+++ b/extensions/libxt_TRACE.man
@@ -0,0 +1,11 @@
+This target marks packes so that the kernel will log every rule which match
+the packets as those traverse the tables, chains, rules. (The ipt_LOG or
+ip6t_LOG module
+is required for the logging.) 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.
diff --git a/extensions/libxt_cluster.c b/extensions/libxt_cluster.c
new file mode 100644
index 0000000..e397d9e
--- /dev/null
+++ b/extensions/libxt_cluster.c
@@ -0,0 +1,238 @@
+/*
+ * (C) 2009 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <stddef.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_cluster.h>
+
+/* hack to keep for check */
+static unsigned int total_nodes;
+static unsigned int node_mask;
+
+static void
+cluster_help(void)
+{
+ printf(
+"cluster match options:\n"
+" --cluster-total-nodes <num> Set number of total nodes in cluster\n"
+" [!] --cluster-local-node <num> Set the local node number\n"
+" [!] --cluster-local-nodemask <num> Set the local node mask\n"
+" --cluster-hash-seed <num> Set seed value of the Jenkins hash\n");
+}
+
+enum {
+ CLUSTER_OPT_TOTAL_NODES,
+ CLUSTER_OPT_LOCAL_NODE,
+ CLUSTER_OPT_NODE_MASK,
+ CLUSTER_OPT_HASH_SEED,
+};
+
+static const struct option cluster_opts[] = {
+ { "cluster-total-nodes", 1, NULL, CLUSTER_OPT_TOTAL_NODES },
+ { "cluster-local-node", 1, NULL, CLUSTER_OPT_LOCAL_NODE },
+ { "cluster-local-nodemask", 1, NULL, CLUSTER_OPT_NODE_MASK },
+ { "cluster-hash-seed", 1, NULL, CLUSTER_OPT_HASH_SEED },
+ { .name = NULL }
+};
+
+static int
+cluster_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_cluster_match_info *info = (void *)(*match)->data;
+ unsigned int num;
+
+ switch (c) {
+ case CLUSTER_OPT_TOTAL_NODES:
+ if (*flags & (1 << c)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Can only specify "
+ "`--cluster-total-nodes' once");
+ }
+ if (!xtables_strtoui(optarg, NULL, &num, 1,
+ XT_CLUSTER_NODES_MAX)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Unable to parse `%s' in "
+ "`--cluster-total-nodes'", optarg);
+ }
+ total_nodes = num;
+ info->total_nodes = total_nodes = num;
+ *flags |= 1 << c;
+ break;
+ case CLUSTER_OPT_LOCAL_NODE:
+ if (*flags & (1 << c)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Can only specify "
+ "`--cluster-local-node' once");
+ }
+ if (*flags & (1 << CLUSTER_OPT_NODE_MASK)) {
+ xtables_error(PARAMETER_PROBLEM, "You cannot use "
+ "`--cluster-local-nodemask' and "
+ "`--cluster-local-node'");
+ }
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (!xtables_strtoui(optarg, NULL, &num, 1,
+ XT_CLUSTER_NODES_MAX)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Unable to parse `%s' in "
+ "`--cluster-local-node'", optarg);
+ }
+ if (invert)
+ info->flags |= (1 << XT_CLUSTER_F_INV);
+
+ info->node_mask = node_mask = (1 << (num - 1));
+ *flags |= 1 << c;
+ break;
+ case CLUSTER_OPT_NODE_MASK:
+ if (*flags & (1 << c)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Can only specify "
+ "`--cluster-local-node' once");
+ }
+ if (*flags & (1 << CLUSTER_OPT_LOCAL_NODE)) {
+ xtables_error(PARAMETER_PROBLEM, "You cannot use "
+ "`--cluster-local-nodemask' and "
+ "`--cluster-local-node'");
+ }
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (!xtables_strtoui(optarg, NULL, &num, 1,
+ XT_CLUSTER_NODES_MAX)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Unable to parse `%s' in "
+ "`--cluster-local-node'", optarg);
+ }
+ if (invert)
+ info->flags |= (1 << XT_CLUSTER_F_INV);
+
+ info->node_mask = node_mask = num;
+ *flags |= 1 << c;
+ break;
+
+ case CLUSTER_OPT_HASH_SEED:
+ if (*flags & (1 << c)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Can only specify "
+ "`--cluster-hash-seed' once");
+ }
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Unable to parse `%s'", optarg);
+ }
+ info->hash_seed = num;
+ *flags |= 1 << c;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+cluster_check(unsigned int flags)
+{
+ if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) |
+ (1 << CLUSTER_OPT_LOCAL_NODE) |
+ (1 << CLUSTER_OPT_HASH_SEED)))
+ == ((1 << CLUSTER_OPT_TOTAL_NODES) |
+ (1 << CLUSTER_OPT_LOCAL_NODE) |
+ (1 << CLUSTER_OPT_HASH_SEED))) {
+ if (node_mask >= (1ULL << total_nodes)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "cluster match: "
+ "`--cluster-local-node' "
+ "must be <= `--cluster-total-nodes'");
+ }
+ return;
+ }
+ if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) |
+ (1 << CLUSTER_OPT_NODE_MASK) |
+ (1 << CLUSTER_OPT_HASH_SEED)))
+ == ((1 << CLUSTER_OPT_TOTAL_NODES) |
+ (1 << CLUSTER_OPT_NODE_MASK) |
+ (1 << CLUSTER_OPT_HASH_SEED))) {
+ if (node_mask >= (1ULL << total_nodes)) {
+ xtables_error(PARAMETER_PROBLEM,
+ "cluster match: "
+ "`--cluster-local-nodemask' too big "
+ "for `--cluster-total-nodes'");
+ }
+ return;
+ }
+ if (!(flags & (1 << CLUSTER_OPT_TOTAL_NODES))) {
+ xtables_error(PARAMETER_PROBLEM,
+ "cluster match: `--cluster-total-nodes' "
+ "is missing");
+ }
+ if (!(flags & (1 << CLUSTER_OPT_HASH_SEED))) {
+ xtables_error(PARAMETER_PROBLEM,
+ "cluster match: `--cluster-hash-seed' "
+ "is missing");
+ }
+ if (!(flags & ((1 << (CLUSTER_OPT_LOCAL_NODE) |
+ (1 << (CLUSTER_OPT_NODE_MASK)))))) {
+ xtables_error(PARAMETER_PROBLEM,
+ "cluster match: `--cluster-local-node' or"
+ "`--cluster-local-nodemask' is missing");
+ }
+}
+
+static void
+cluster_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_cluster_match_info *info = (void *)match->data;
+
+ printf("cluster ");
+ if (info->flags & XT_CLUSTER_F_INV)
+ printf("!node_mask=0x%08x ", info->node_mask);
+ else
+ printf("node_mask=0x%08x ", info->node_mask);
+
+ printf("total_nodes=%u hash_seed=0x%08x ",
+ info->total_nodes, info->hash_seed);
+}
+
+static void
+cluster_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_cluster_match_info *info = (void *)match->data;
+
+ if (info->flags & XT_CLUSTER_F_INV)
+ printf("! --cluster-local-nodemask 0x%08x ", info->node_mask);
+ else
+ printf("--cluster-local-nodemask 0x%08x ", info->node_mask);
+
+ printf("--cluster-total-nodes %u --cluster-hash-seed 0x%08x ",
+ info->total_nodes, info->hash_seed);
+}
+
+static struct xtables_match cluster_mt_reg = {
+ .family = NFPROTO_UNSPEC,
+ .name = "cluster",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_cluster_match_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_cluster_match_info)),
+ .help = cluster_help,
+ .parse = cluster_parse,
+ .final_check = cluster_check,
+ .print = cluster_print,
+ .save = cluster_save,
+ .extra_opts = cluster_opts,
+};
+
+void libxt_cluster_init(void)
+{
+ xtables_register_match(&cluster_mt_reg);
+}
diff --git a/extensions/libxt_cluster.man b/extensions/libxt_cluster.man
new file mode 100644
index 0000000..62ad71c
--- /dev/null
+++ b/extensions/libxt_cluster.man
@@ -0,0 +1,62 @@
+Allows you to deploy gateway and back-end load-sharing clusters without the
+need of load-balancers.
+.PP
+This match requires that all the nodes see the same packets. Thus, the cluster
+match decides if this node has to handle a packet given the following options:
+.TP
+\fB\-\-cluster\-total\-nodes\fP \fInum\fP
+Set number of total nodes in cluster.
+.TP
+[\fB!\fP] \fB\-\-cluster\-local\-node\fP \fInum\fP
+Set the local node number ID.
+.TP
+[\fB!\fP] \fB\-\-cluster\-local\-nodemask\fP \fImask\fP
+Set the local node number ID mask. You can use this option instead
+of \fB\-\-cluster\-local\-node\fP.
+.TP
+\fB\-\-cluster\-hash\-seed\fP \fIvalue\fP
+Set seed value of the Jenkins hash.
+.PP
+Example:
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth1 \-m cluster
+\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
+\-\-cluster\-hash\-seed 0xdeadbeef
+\-j MARK \-\-set-mark 0xffff
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth2 \-m cluster
+\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
+\-\-cluster\-hash\-seed 0xdeadbeef
+\-j MARK -\-set\-mark 0xffff
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth1
+\-m mark ! \-\-mark 0xffff \-j DROP
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth2
+\-m mark ! \-\-mark 0xffff \-j DROP
+.PP
+And the following commands to make all nodes see the same packets:
+.IP
+ip maddr add 01:00:5e:00:01:01 dev eth1
+.IP
+ip maddr add 01:00:5e:00:01:02 dev eth2
+.IP
+arptables \-A OUTPUT \-o eth1 \-\-h\-length 6
+\-j mangle \-\-mangle-mac-s 01:00:5e:00:01:01
+.IP
+arptables \-A INPUT \-i eth1 \-\-h-length 6
+\-\-destination-mac 01:00:5e:00:01:01
+\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
+.IP
+arptables \-A OUTPUT \-o eth2 \-\-h\-length 6
+\-j mangle \-\-mangle\-mac\-s 01:00:5e:00:01:02
+.IP
+arptables \-A INPUT \-i eth2 \-\-h\-length 6
+\-\-destination\-mac 01:00:5e:00:01:02
+\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
+.PP
+In the case of TCP connections, pickup facility has to be disabled
+to avoid marking TCP ACK packets coming in the reply direction as
+valid.
+.IP
+echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose
diff --git a/extensions/libxt_comment.c b/extensions/libxt_comment.c
new file mode 100644
index 0000000..f9f0b4e
--- /dev/null
+++ b/extensions/libxt_comment.c
@@ -0,0 +1,108 @@
+/* Shared library add-on to iptables to add comment match support.
+ *
+ * ChangeLog
+ * 2003-05-13: Brad Fisher <brad@info-link.net>
+ * Initial comment match
+ * 2004-05-12: Brad Fisher <brad@info-link.net>
+ * Port to patch-o-matic-ng
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_comment.h>
+
+static void comment_help(void)
+{
+ printf(
+ "comment match options:\n"
+ "--comment COMMENT Attach a comment to a rule\n");
+}
+
+static const struct option comment_opts[] = {
+ { "comment", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static void
+parse_comment(const char *s, struct xt_comment_info *info)
+{
+ int slen = strlen(s);
+
+ if (slen >= XT_MAX_COMMENT_LEN) {
+ xtables_error(PARAMETER_PROBLEM,
+ "COMMENT must be shorter than %i characters", XT_MAX_COMMENT_LEN);
+ }
+ strcpy((char *)info->comment, s);
+}
+
+static int
+comment_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_comment_info *commentinfo = (struct xt_comment_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert) {
+ xtables_error(PARAMETER_PROBLEM,
+ "Sorry, you can't have an inverted comment");
+ }
+ parse_comment(optarg, commentinfo);
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void comment_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "COMMENT match: You must specify `--comment'");
+}
+
+static void
+comment_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ struct xt_comment_info *commentinfo = (void *)match->data;
+
+ commentinfo->comment[XT_MAX_COMMENT_LEN-1] = '\0';
+ printf("/* %s */ ", commentinfo->comment);
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void
+comment_save(const void *ip, const struct xt_entry_match *match)
+{
+ struct xt_comment_info *commentinfo = (void *)match->data;
+
+ commentinfo->comment[XT_MAX_COMMENT_LEN-1] = '\0';
+ printf("--comment ");
+ xtables_save_string((const char *)commentinfo->comment);
+}
+
+static struct xtables_match comment_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "comment",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_comment_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_comment_info)),
+ .help = comment_help,
+ .parse = comment_parse,
+ .final_check = comment_check,
+ .print = comment_print,
+ .save = comment_save,
+ .extra_opts = comment_opts,
+};
+
+void libxt_comment_init(void)
+{
+ xtables_register_match(&comment_match);
+}
diff --git a/extensions/libxt_comment.man b/extensions/libxt_comment.man
new file mode 100644
index 0000000..94f871e
--- /dev/null
+++ b/extensions/libxt_comment.man
@@ -0,0 +1,6 @@
+Allows you to add comments (up to 256 characters) to any rule.
+.TP
+\fB\-\-comment\fP \fIcomment\fP
+.TP
+Example:
+iptables \-A INPUT \-s 192.168.0.0/16 \-m comment \-\-comment "A privatized IP block"
diff --git a/extensions/libxt_connbytes.c b/extensions/libxt_connbytes.c
new file mode 100644
index 0000000..b709627
--- /dev/null
+++ b/extensions/libxt_connbytes.c
@@ -0,0 +1,199 @@
+/* Shared library add-on to iptables to add byte tracking support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/xt_connbytes.h>
+
+static void connbytes_help(void)
+{
+ printf(
+"connbytes match options:\n"
+" [!] --connbytes from:[to]\n"
+" --connbytes-dir [original, reply, both]\n"
+" --connbytes-mode [packets, bytes, avgpkt]\n");
+}
+
+static const struct option connbytes_opts[] = {
+ { "connbytes", 1, NULL, '1' },
+ { "connbytes-dir", 1, NULL, '2' },
+ { "connbytes-mode", 1, NULL, '3' },
+ { .name = NULL }
+};
+
+static void
+parse_range(const char *arg, struct xt_connbytes_info *si)
+{
+ char *colon,*p;
+
+ si->count.from = strtoul(arg,&colon,10);
+ if (*colon != ':')
+ xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", arg);
+ si->count.to = strtoul(colon+1,&p,10);
+ if (p == colon+1) {
+ /* second number omited */
+ si->count.to = 0xffffffff;
+ }
+ if (si->count.from > si->count.to)
+ xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu",
+ (unsigned long long)si->count.from,
+ (unsigned long long)si->count.to);
+}
+
+static int
+connbytes_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data;
+ unsigned long i;
+
+ switch (c) {
+ case '1':
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv))
+ optind++;
+
+ parse_range(optarg, sinfo);
+ if (invert) {
+ i = sinfo->count.from;
+ sinfo->count.from = sinfo->count.to;
+ sinfo->count.to = i;
+ }
+ *flags |= 1;
+ break;
+ case '2':
+ if (!strcmp(optarg, "original"))
+ sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL;
+ else if (!strcmp(optarg, "reply"))
+ sinfo->direction = XT_CONNBYTES_DIR_REPLY;
+ else if (!strcmp(optarg, "both"))
+ sinfo->direction = XT_CONNBYTES_DIR_BOTH;
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown --connbytes-dir `%s'", optarg);
+
+ *flags |= 2;
+ break;
+ case '3':
+ if (!strcmp(optarg, "packets"))
+ sinfo->what = XT_CONNBYTES_PKTS;
+ else if (!strcmp(optarg, "bytes"))
+ sinfo->what = XT_CONNBYTES_BYTES;
+ else if (!strcmp(optarg, "avgpkt"))
+ sinfo->what = XT_CONNBYTES_AVGPKT;
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown --connbytes-mode `%s'", optarg);
+ *flags |= 4;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void connbytes_check(unsigned int flags)
+{
+ if (flags != 7)
+ xtables_error(PARAMETER_PROBLEM, "You must specify `--connbytes'"
+ "`--connbytes-dir' and `--connbytes-mode'");
+}
+
+static void print_mode(const struct xt_connbytes_info *sinfo)
+{
+ switch (sinfo->what) {
+ case XT_CONNBYTES_PKTS:
+ fputs("packets ", stdout);
+ break;
+ case XT_CONNBYTES_BYTES:
+ fputs("bytes ", stdout);
+ break;
+ case XT_CONNBYTES_AVGPKT:
+ fputs("avgpkt ", stdout);
+ break;
+ default:
+ fputs("unknown ", stdout);
+ break;
+ }
+}
+
+static void print_direction(const struct xt_connbytes_info *sinfo)
+{
+ switch (sinfo->direction) {
+ case XT_CONNBYTES_DIR_ORIGINAL:
+ fputs("original ", stdout);
+ break;
+ case XT_CONNBYTES_DIR_REPLY:
+ fputs("reply ", stdout);
+ break;
+ case XT_CONNBYTES_DIR_BOTH:
+ fputs("both ", stdout);
+ break;
+ default:
+ fputs("unknown ", stdout);
+ break;
+ }
+}
+
+static void
+connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_connbytes_info *sinfo = (const void *)match->data;
+
+ if (sinfo->count.from > sinfo->count.to)
+ printf("connbytes ! %llu:%llu ",
+ (unsigned long long)sinfo->count.to,
+ (unsigned long long)sinfo->count.from);
+ else
+ printf("connbytes %llu:%llu ",
+ (unsigned long long)sinfo->count.from,
+ (unsigned long long)sinfo->count.to);
+
+ fputs("connbytes mode ", stdout);
+ print_mode(sinfo);
+
+ fputs("connbytes direction ", stdout);
+ print_direction(sinfo);
+}
+
+static void connbytes_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_connbytes_info *sinfo = (const void *)match->data;
+
+ if (sinfo->count.from > sinfo->count.to)
+ printf("! --connbytes %llu:%llu ",
+ (unsigned long long)sinfo->count.to,
+ (unsigned long long)sinfo->count.from);
+ else
+ printf("--connbytes %llu:%llu ",
+ (unsigned long long)sinfo->count.from,
+ (unsigned long long)sinfo->count.to);
+
+ fputs("--connbytes-mode ", stdout);
+ print_mode(sinfo);
+
+ fputs("--connbytes-dir ", stdout);
+ print_direction(sinfo);
+}
+
+static struct xtables_match connbytes_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "connbytes",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_connbytes_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)),
+ .help = connbytes_help,
+ .parse = connbytes_parse,
+ .final_check = connbytes_check,
+ .print = connbytes_print,
+ .save = connbytes_save,
+ .extra_opts = connbytes_opts,
+};
+
+void libxt_connbytes_init(void)
+{
+ xtables_register_match(&connbytes_match);
+}
diff --git a/extensions/libxt_connbytes.man b/extensions/libxt_connbytes.man
new file mode 100644
index 0000000..0504a55
--- /dev/null
+++ b/extensions/libxt_connbytes.man
@@ -0,0 +1,36 @@
+Match by how many bytes or packets a connection (or one of the two
+flows constituting the connection) has transferred so far, or by
+average bytes per packet.
+.PP
+The counters are 64-bit and are thus not expected to overflow ;)
+.PP
+The primary use is to detect long-lived downloads and mark them to be
+scheduled using a lower priority band in traffic control.
+.PP
+The transferred bytes per connection can also be viewed through
+`conntrack \-L` and accessed via ctnetlink.
+.PP
+NOTE that for connections which have no accounting information, the match will
+always return false. The "net.netfilter.nf_conntrack_acct" sysctl flag controls
+whether \fBnew\fP connections will be byte/packet counted. Existing connection
+flows will not be gaining/losing a/the accounting structure when be sysctl flag
+is flipped.
+.TP
+[\fB!\fP] \fB\-\-connbytes\fP \fIfrom\fP[\fB:\fP\fIto\fP]
+match packets from a connection whose packets/bytes/average packet
+size is more than FROM and less than TO bytes/packets. if TO is
+omitted only FROM check is done. "!" is used to match packets not
+falling in the range.
+.TP
+\fB\-\-connbytes\-dir\fP {\fBoriginal\fP|\fBreply\fP|\fBboth\fP}
+which packets to consider
+.TP
+\fB\-\-connbytes\-mode\fP {\fBpackets\fP|\fBbytes\fP|\fBavgpkt\fP}
+whether to check the amount of packets, number of bytes transferred or
+the average size (in bytes) of all packets received so far. Note that
+when "both" is used together with "avgpkt", and data is going (mainly)
+only in one direction (for example HTTP), the average packet size will
+be about half of the actual data packets.
+.TP
+Example:
+iptables .. \-m connbytes \-\-connbytes 10000:100000 \-\-connbytes\-dir both \-\-connbytes\-mode bytes ...
diff --git a/extensions/libxt_connlimit.c b/extensions/libxt_connlimit.c
new file mode 100644
index 0000000..284a102
--- /dev/null
+++ b/extensions/libxt_connlimit.c
@@ -0,0 +1,216 @@
+/* Shared library add-on to iptables to add connection limit support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_connlimit.h>
+
+static void connlimit_help(void)
+{
+ printf(
+"connlimit match options:\n"
+"[!] --connlimit-above n match if the number of existing "
+" connections is (not) above n\n"
+" --connlimit-mask n group hosts using mask\n");
+}
+
+static const struct option connlimit_opts[] = {
+ {"connlimit-above", 1, NULL, 'A'},
+ {"connlimit-mask", 1, NULL, 'M'},
+ { .name = NULL }
+};
+
+static void connlimit_init(struct xt_entry_match *match)
+{
+ struct xt_connlimit_info *info = (void *)match->data;
+
+ /* This will also initialize the v4 mask correctly */
+ memset(info->v6_mask, 0xFF, sizeof(info->v6_mask));
+}
+
+static void prefix_to_netmask(u_int32_t *mask, unsigned int prefix_len)
+{
+ if (prefix_len == 0) {
+ mask[0] = mask[1] = mask[2] = mask[3] = 0;
+ } else if (prefix_len <= 32) {
+ mask[0] <<= 32 - prefix_len;
+ mask[1] = mask[2] = mask[3] = 0;
+ } else if (prefix_len <= 64) {
+ mask[1] <<= 32 - (prefix_len - 32);
+ mask[2] = mask[3] = 0;
+ } else if (prefix_len <= 96) {
+ mask[2] <<= 32 - (prefix_len - 64);
+ mask[3] = 0;
+ } else if (prefix_len <= 128) {
+ mask[3] <<= 32 - (prefix_len - 96);
+ }
+ mask[0] = htonl(mask[0]);
+ mask[1] = htonl(mask[1]);
+ mask[2] = htonl(mask[2]);
+ mask[3] = htonl(mask[3]);
+}
+
+static int connlimit_parse(int c, char **argv, int invert, unsigned int *flags,
+ struct xt_connlimit_info *info, unsigned int family)
+{
+ char *err;
+ int i;
+
+ switch (c) {
+ case 'A':
+ if (*flags & 0x1)
+ xtables_error(PARAMETER_PROBLEM,
+ "--connlimit-above may be given only once");
+ *flags |= 0x1;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->limit = strtoul(optarg, NULL, 0);
+ info->inverse = invert;
+ break;
+ case 'M':
+ if (*flags & 0x2)
+ xtables_error(PARAMETER_PROBLEM,
+ "--connlimit-mask may be given only once");
+
+ *flags |= 0x2;
+ i = strtoul(optarg, &err, 0);
+ if (family == NFPROTO_IPV6) {
+ if (i > 128 || *err != '\0')
+ xtables_error(PARAMETER_PROBLEM,
+ "--connlimit-mask must be between "
+ "0 and 128");
+ prefix_to_netmask(info->v6_mask, i);
+ } else {
+ if (i > 32 || *err != '\0')
+ xtables_error(PARAMETER_PROBLEM,
+ "--connlimit-mask must be between "
+ "0 and 32");
+ if (i == 0)
+ info->v4_mask = 0;
+ else
+ info->v4_mask = htonl(0xFFFFFFFF << (32 - i));
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static int connlimit_parse4(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_match **match)
+{
+ return connlimit_parse(c, argv, invert, flags,
+ (void *)(*match)->data, NFPROTO_IPV4);
+}
+
+static int connlimit_parse6(int c, char **argv, int invert,
+ unsigned int *flags, const void *entry,
+ struct xt_entry_match **match)
+{
+ return connlimit_parse(c, argv, invert, flags,
+ (void *)(*match)->data, NFPROTO_IPV6);
+}
+
+static void connlimit_check(unsigned int flags)
+{
+ if (!(flags & 0x1))
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify \"--connlimit-above\"");
+}
+
+static unsigned int count_bits4(u_int32_t mask)
+{
+ unsigned int bits = 0;
+
+ for (mask = ~ntohl(mask); mask != 0; mask >>= 1)
+ ++bits;
+
+ return 32 - bits;
+}
+
+static unsigned int count_bits6(const u_int32_t *mask)
+{
+ unsigned int bits = 0, i;
+ u_int32_t tmp[4];
+
+ for (i = 0; i < 4; ++i)
+ for (tmp[i] = ~ntohl(mask[i]); tmp[i] != 0; tmp[i] >>= 1)
+ ++bits;
+ return 128 - bits;
+}
+
+static void connlimit_print4(const void *ip,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_connlimit_info *info = (const void *)match->data;
+
+ printf("#conn/%u %s %u ", count_bits4(info->v4_mask),
+ info->inverse ? "<=" : ">", info->limit);
+}
+
+static void connlimit_print6(const void *ip,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_connlimit_info *info = (const void *)match->data;
+ printf("#conn/%u %s %u ", count_bits6(info->v6_mask),
+ info->inverse ? "<=" : ">", info->limit);
+}
+
+static void connlimit_save4(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_connlimit_info *info = (const void *)match->data;
+
+ printf("%s--connlimit-above %u --connlimit-mask %u ",
+ info->inverse ? "! " : "", info->limit,
+ count_bits4(info->v4_mask));
+}
+
+static void connlimit_save6(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_connlimit_info *info = (const void *)match->data;
+
+ printf("%s--connlimit-above %u --connlimit-mask %u ",
+ info->inverse ? "! " : "", info->limit,
+ count_bits6(info->v6_mask));
+}
+
+static struct xtables_match connlimit_mt_reg[] = {
+ {
+ .name = "connlimit",
+ .family = NFPROTO_IPV4,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_connlimit_info)),
+ .userspacesize = offsetof(struct xt_connlimit_info, data),
+ .help = connlimit_help,
+ .init = connlimit_init,
+ .parse = connlimit_parse4,
+ .final_check = connlimit_check,
+ .print = connlimit_print4,
+ .save = connlimit_save4,
+ .extra_opts = connlimit_opts,
+ },
+ {
+ .name = "connlimit",
+ .family = NFPROTO_IPV6,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_connlimit_info)),
+ .userspacesize = offsetof(struct xt_connlimit_info, data),
+ .help = connlimit_help,
+ .init = connlimit_init,
+ .parse = connlimit_parse6,
+ .final_check = connlimit_check,
+ .print = connlimit_print6,
+ .save = connlimit_save6,
+ .extra_opts = connlimit_opts,
+ },
+};
+
+void libxt_connlimit_init(void)
+{
+ xtables_register_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
+}
diff --git a/extensions/libxt_connlimit.man b/extensions/libxt_connlimit.man
new file mode 100644
index 0000000..c85d768
--- /dev/null
+++ b/extensions/libxt_connlimit.man
@@ -0,0 +1,27 @@
+Allows you to restrict the number of parallel connections to a server per
+client IP address (or client address block).
+.TP
+[\fB!\fP] \fB\-\-connlimit\-above\fP \fIn\fP
+Match if the number of existing connections is (not) above \fIn\fR.
+.TP
+\fB\-\-connlimit\-mask\fP \fIprefix_length\fP
+Group hosts using the prefix length. For IPv4, this must be a number between
+(including) 0 and 32. For IPv6, between 0 and 128.
+.P
+Examples:
+.TP
+# allow 2 telnet connections per client host
+iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit \-\-connlimit\-above 2 \-j REJECT
+.TP
+# you can also match the other way around:
+iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit ! \-\-connlimit\-above 2 \-j ACCEPT
+.TP
+# limit the number of parallel HTTP requests to 16 per class C sized \
+network (24 bit netmask)
+iptables \-p tcp \-\-syn \-\-dport 80 \-m connlimit \-\-connlimit\-above 16
+\-\-connlimit\-mask 24 \-j REJECT
+.TP
+# limit the number of parallel HTTP requests to 16 for the link local network
+(ipv6)
+ip6tables \-p tcp \-\-syn \-\-dport 80 \-s fe80::/64 \-m connlimit \-\-connlimit\-above
+16 \-\-connlimit\-mask 64 \-j REJECT
diff --git a/extensions/libxt_connmark.c b/extensions/libxt_connmark.c
new file mode 100644
index 0000000..9ddcb2d
--- /dev/null
+++ b/extensions/libxt_connmark.c
@@ -0,0 +1,205 @@
+/* Shared library add-on to iptables to add connmark matching support.
+ *
+ * (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ * by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * Version 1.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_connmark.h>
+
+struct xt_connmark_info {
+ unsigned long mark, mask;
+ u_int8_t invert;
+};
+
+enum {
+ F_MARK = 1 << 0,
+};
+
+static void connmark_mt_help(void)
+{
+ printf(
+"connmark match options:\n"
+"[!] --mark value[/mask] Match ctmark value with optional mask\n");
+}
+
+static const struct option connmark_mt_opts[] = {
+ {.name = "mark", .has_arg = true, .val = '1'},
+ { .name = NULL }
+};
+
+static int
+connmark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_connmark_mtinfo1 *info = (void *)(*match)->data;
+ unsigned int mark, mask = UINT32_MAX;
+ char *end;
+
+ switch (c) {
+ case '1': /* --mark */
+ xtables_param_act(XTF_ONLY_ONCE, "connmark", "--mark", *flags & F_MARK);
+ if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
+ if (*end == '/')
+ if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "connmark", "--mark", optarg);
+
+ if (invert)
+ info->invert = true;
+ info->mark = mark;
+ info->mask = mask;
+ *flags |= F_MARK;
+ return true;
+ }
+ return false;
+}
+
+static int
+connmark_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_connmark_info *markinfo = (struct xt_connmark_info *)(*match)->data;
+
+ switch (c) {
+ char *end;
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ markinfo->mark = strtoul(optarg, &end, 0);
+ markinfo->mask = 0xffffffffUL;
+
+ if (*end == '/')
+ markinfo->mask = strtoul(end+1, &end, 0);
+
+ if (*end != '\0' || end == optarg)
+ xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
+ if (invert)
+ markinfo->invert = 1;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void print_mark(unsigned int mark, unsigned int mask)
+{
+ if (mask != 0xffffffffU)
+ printf("0x%x/0x%x ", mark, mask);
+ else
+ printf("0x%x ", mark);
+}
+
+static void connmark_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "connmark: The --mark option is required");
+}
+
+static void
+connmark_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_connmark_info *info = (const void *)match->data;
+
+ printf("CONNMARK match ");
+ if (info->invert)
+ printf("!");
+ print_mark(info->mark, info->mask);
+}
+
+static void
+connmark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
+
+ printf("connmark match ");
+ if (info->invert)
+ printf("!");
+ print_mark(info->mark, info->mask);
+}
+
+static void connmark_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_connmark_info *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+
+ printf("--mark ");
+ print_mark(info->mark, info->mask);
+}
+
+static void
+connmark_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_connmark_mtinfo1 *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+
+ printf("--mark ");
+ print_mark(info->mark, info->mask);
+}
+
+static struct xtables_match connmark_mt_reg[] = {
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "connmark",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_info)),
+ .help = connmark_mt_help,
+ .parse = connmark_parse,
+ .final_check = connmark_mt_check,
+ .print = connmark_print,
+ .save = connmark_save,
+ .extra_opts = connmark_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "connmark",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_connmark_mtinfo1)),
+ .help = connmark_mt_help,
+ .parse = connmark_mt_parse,
+ .final_check = connmark_mt_check,
+ .print = connmark_mt_print,
+ .save = connmark_mt_save,
+ .extra_opts = connmark_mt_opts,
+ },
+};
+
+void libxt_connmark_init(void)
+{
+ xtables_register_matches(connmark_mt_reg, ARRAY_SIZE(connmark_mt_reg));
+}
diff --git a/extensions/libxt_connmark.man b/extensions/libxt_connmark.man
new file mode 100644
index 0000000..ee87d9e
--- /dev/null
+++ b/extensions/libxt_connmark.man
@@ -0,0 +1,6 @@
+This module matches the netfilter mark field associated with a connection
+(which can be set using the \fBCONNMARK\fR target below).
+.TP
+[\fB!\fP] \fB\-\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets in connections with the given mark value (if a mask is
+specified, this is logically ANDed with the mark before the comparison).
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
new file mode 100644
index 0000000..34ddfe3
--- /dev/null
+++ b/extensions/libxt_conntrack.c
@@ -0,0 +1,1235 @@
+/*
+ * libxt_conntrack
+ * Shared library add-on to iptables for conntrack matching support.
+ *
+ * GPL (C) 2001 Marc Boucher (marc@mbsi.ca).
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xtables.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/xt_conntrack.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <arpa/inet.h>
+
+struct ip_conntrack_old_tuple {
+ struct {
+ __be32 ip;
+ union {
+ __u16 all;
+ } u;
+ } src;
+
+ struct {
+ __be32 ip;
+ union {
+ __u16 all;
+ } u;
+
+ /* The protocol. */
+ __u16 protonum;
+ } dst;
+};
+
+struct xt_conntrack_info {
+ unsigned int statemask, statusmask;
+
+ struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX];
+ struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX];
+
+ unsigned long expires_min, expires_max;
+
+ /* Flags word */
+ u_int8_t flags;
+ /* Inverse flags */
+ u_int8_t invflags;
+};
+
+static void conntrack_mt_help(void)
+{
+ printf(
+"conntrack match options:\n"
+"[!] --ctstate {INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|SNAT|DNAT}[,...]\n"
+" State(s) to match\n"
+"[!] --ctproto proto Protocol to match; by number or name, e.g. \"tcp\"\n"
+"[!] --ctorigsrc address[/mask]\n"
+"[!] --ctorigdst address[/mask]\n"
+"[!] --ctreplsrc address[/mask]\n"
+"[!] --ctrepldst address[/mask]\n"
+" Original/Reply source/destination address\n"
+"[!] --ctorigsrcport port\n"
+"[!] --ctorigdstport port\n"
+"[!] --ctreplsrcport port\n"
+"[!] --ctrepldstport port\n"
+" TCP/UDP/SCTP orig./reply source/destination port\n"
+"[!] --ctstatus {NONE|EXPECTED|SEEN_REPLY|ASSURED|CONFIRMED}[,...]\n"
+" Status(es) to match\n"
+"[!] --ctexpire time[:time] Match remaining lifetime in seconds against\n"
+" value or range of values (inclusive)\n"
+" --ctdir {ORIGINAL|REPLY} Flow direction of packet\n");
+}
+
+static const struct option conntrack_mt_opts_v0[] = {
+ {.name = "ctstate", .has_arg = true, .val = '1'},
+ {.name = "ctproto", .has_arg = true, .val = '2'},
+ {.name = "ctorigsrc", .has_arg = true, .val = '3'},
+ {.name = "ctorigdst", .has_arg = true, .val = '4'},
+ {.name = "ctreplsrc", .has_arg = true, .val = '5'},
+ {.name = "ctrepldst", .has_arg = true, .val = '6'},
+ {.name = "ctstatus", .has_arg = true, .val = '7'},
+ {.name = "ctexpire", .has_arg = true, .val = '8'},
+ { .name = NULL }
+};
+
+static const struct option conntrack_mt_opts[] = {
+ {.name = "ctstate", .has_arg = true, .val = '1'},
+ {.name = "ctproto", .has_arg = true, .val = '2'},
+ {.name = "ctorigsrc", .has_arg = true, .val = '3'},
+ {.name = "ctorigdst", .has_arg = true, .val = '4'},
+ {.name = "ctreplsrc", .has_arg = true, .val = '5'},
+ {.name = "ctrepldst", .has_arg = true, .val = '6'},
+ {.name = "ctstatus", .has_arg = true, .val = '7'},
+ {.name = "ctexpire", .has_arg = true, .val = '8'},
+ {.name = "ctorigsrcport", .has_arg = true, .val = 'a'},
+ {.name = "ctorigdstport", .has_arg = true, .val = 'b'},
+ {.name = "ctreplsrcport", .has_arg = true, .val = 'c'},
+ {.name = "ctrepldstport", .has_arg = true, .val = 'd'},
+ {.name = "ctdir", .has_arg = true, .val = 'e'},
+ {.name = NULL},
+};
+
+static int
+parse_state(const char *state, size_t len, struct xt_conntrack_info *sinfo)
+{
+ if (strncasecmp(state, "INVALID", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_INVALID;
+ else if (strncasecmp(state, "NEW", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
+ else if (strncasecmp(state, "ESTABLISHED", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
+ else if (strncasecmp(state, "RELATED", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
+ else if (strncasecmp(state, "UNTRACKED", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_UNTRACKED;
+ else if (strncasecmp(state, "SNAT", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_SNAT;
+ else if (strncasecmp(state, "DNAT", len) == 0)
+ sinfo->statemask |= XT_CONNTRACK_STATE_DNAT;
+ else
+ return 0;
+ return 1;
+}
+
+static void
+parse_states(const char *arg, struct xt_conntrack_info *sinfo)
+{
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg || !parse_state(arg, comma-arg, sinfo))
+ xtables_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
+ arg = comma+1;
+ }
+ if (!*arg)
+ xtables_error(PARAMETER_PROBLEM, "\"--ctstate\" requires a list of "
+ "states with no spaces, e.g. "
+ "ESTABLISHED,RELATED");
+ if (strlen(arg) == 0 || !parse_state(arg, strlen(arg), sinfo))
+ xtables_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
+}
+
+static bool
+conntrack_ps_state(struct xt_conntrack_mtinfo2 *info, const char *state,
+ size_t z)
+{
+ if (strncasecmp(state, "INVALID", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_INVALID;
+ else if (strncasecmp(state, "NEW", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_NEW);
+ else if (strncasecmp(state, "ESTABLISHED", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
+ else if (strncasecmp(state, "RELATED", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
+ else if (strncasecmp(state, "UNTRACKED", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_UNTRACKED;
+ else if (strncasecmp(state, "SNAT", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_SNAT;
+ else if (strncasecmp(state, "DNAT", z) == 0)
+ info->state_mask |= XT_CONNTRACK_STATE_DNAT;
+ else
+ return false;
+ return true;
+}
+
+static void
+conntrack_ps_states(struct xt_conntrack_mtinfo2 *info, const char *arg)
+{
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg || !conntrack_ps_state(info, arg, comma - arg))
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad ctstate \"%s\"", arg);
+ arg = comma + 1;
+ }
+
+ if (strlen(arg) == 0 || !conntrack_ps_state(info, arg, strlen(arg)))
+ xtables_error(PARAMETER_PROBLEM, "Bad ctstate \"%s\"", arg);
+}
+
+static int
+parse_status(const char *status, size_t len, struct xt_conntrack_info *sinfo)
+{
+ if (strncasecmp(status, "NONE", len) == 0)
+ sinfo->statusmask |= 0;
+ else if (strncasecmp(status, "EXPECTED", len) == 0)
+ sinfo->statusmask |= IPS_EXPECTED;
+ else if (strncasecmp(status, "SEEN_REPLY", len) == 0)
+ sinfo->statusmask |= IPS_SEEN_REPLY;
+ else if (strncasecmp(status, "ASSURED", len) == 0)
+ sinfo->statusmask |= IPS_ASSURED;
+#ifdef IPS_CONFIRMED
+ else if (strncasecmp(status, "CONFIRMED", len) == 0)
+ sinfo->statusmask |= IPS_CONFIRMED;
+#endif
+ else
+ return 0;
+ return 1;
+}
+
+static void
+parse_statuses(const char *arg, struct xt_conntrack_info *sinfo)
+{
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg || !parse_status(arg, comma-arg, sinfo))
+ xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
+ arg = comma+1;
+ }
+
+ if (strlen(arg) == 0 || !parse_status(arg, strlen(arg), sinfo))
+ xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
+}
+
+static bool
+conntrack_ps_status(struct xt_conntrack_mtinfo2 *info, const char *status,
+ size_t z)
+{
+ if (strncasecmp(status, "NONE", z) == 0)
+ info->status_mask |= 0;
+ else if (strncasecmp(status, "EXPECTED", z) == 0)
+ info->status_mask |= IPS_EXPECTED;
+ else if (strncasecmp(status, "SEEN_REPLY", z) == 0)
+ info->status_mask |= IPS_SEEN_REPLY;
+ else if (strncasecmp(status, "ASSURED", z) == 0)
+ info->status_mask |= IPS_ASSURED;
+ else if (strncasecmp(status, "CONFIRMED", z) == 0)
+ info->status_mask |= IPS_CONFIRMED;
+ else
+ return false;
+ return true;
+}
+
+static void
+conntrack_ps_statuses(struct xt_conntrack_mtinfo2 *info, const char *arg)
+{
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg || !conntrack_ps_status(info, arg, comma - arg))
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad ctstatus \"%s\"", arg);
+ arg = comma + 1;
+ }
+
+ if (strlen(arg) == 0 || !conntrack_ps_status(info, arg, strlen(arg)))
+ xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
+}
+
+static unsigned long
+parse_expire(const char *s)
+{
+ unsigned int len;
+
+ if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM, "expire value invalid: \"%s\"\n", s);
+ else
+ return len;
+}
+
+/* If a single value is provided, min and max are both set to the value */
+static void
+parse_expires(const char *s, struct xt_conntrack_info *sinfo)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(s);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ sinfo->expires_min = sinfo->expires_max =
+ parse_expire(buffer);
+ else {
+ *cp = '\0';
+ cp++;
+
+ sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
+ sinfo->expires_max = cp[0]
+ ? parse_expire(cp)
+ : (unsigned long)-1;
+ }
+ free(buffer);
+
+ if (sinfo->expires_min > sinfo->expires_max)
+ xtables_error(PARAMETER_PROBLEM,
+ "expire min. range value `%lu' greater than max. "
+ "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
+}
+
+static void
+conntrack_ps_expires(struct xt_conntrack_mtinfo2 *info, const char *s)
+{
+ unsigned int min, max;
+ char *end;
+
+ if (!xtables_strtoui(s, &end, &min, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
+ max = min;
+ if (*end == ':')
+ if (!xtables_strtoui(end + 1, &end, &max, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
+
+ if (min > max)
+ xtables_error(PARAMETER_PROBLEM,
+ "expire min. range value \"%u\" greater than max. "
+ "range value \"%u\"", min, max);
+
+ info->expires_min = min;
+ info->expires_max = max;
+}
+
+static int conntrack_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_conntrack_info *sinfo = (void *)(*match)->data;
+ char *protocol = NULL;
+ unsigned int naddrs = 0;
+ struct in_addr *addrs = NULL;
+
+
+ switch (c) {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ parse_states(optarg, sinfo);
+ if (invert) {
+ sinfo->invflags |= XT_CONNTRACK_STATE;
+ }
+ sinfo->flags |= XT_CONNTRACK_STATE;
+ break;
+
+ case '2':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if(invert)
+ sinfo->invflags |= XT_CONNTRACK_PROTO;
+
+ /* Canonicalize into lower case */
+ for (protocol = optarg; *protocol; protocol++)
+ *protocol = tolower(*protocol);
+
+ protocol = optarg;
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum =
+ xtables_parse_protocol(protocol);
+
+ if (sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum == 0
+ && (sinfo->invflags & XT_INV_PROTO))
+ xtables_error(PARAMETER_PROBLEM,
+ "rule would never match protocol");
+
+ sinfo->flags |= XT_CONNTRACK_PROTO;
+ break;
+
+ case '3':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (invert)
+ sinfo->invflags |= XT_CONNTRACK_ORIGSRC;
+
+ xtables_ipparse_any(optarg, &addrs,
+ &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
+ &naddrs);
+ if(naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+
+ if(naddrs == 1) {
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip = addrs[0].s_addr;
+ }
+
+ sinfo->flags |= XT_CONNTRACK_ORIGSRC;
+ break;
+
+ case '4':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (invert)
+ sinfo->invflags |= XT_CONNTRACK_ORIGDST;
+
+ xtables_ipparse_any(optarg, &addrs,
+ &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
+ &naddrs);
+ if(naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+
+ if(naddrs == 1) {
+ sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip = addrs[0].s_addr;
+ }
+
+ sinfo->flags |= XT_CONNTRACK_ORIGDST;
+ break;
+
+ case '5':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (invert)
+ sinfo->invflags |= XT_CONNTRACK_REPLSRC;
+
+ xtables_ipparse_any(optarg, &addrs,
+ &sinfo->sipmsk[IP_CT_DIR_REPLY],
+ &naddrs);
+ if(naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+
+ if(naddrs == 1) {
+ sinfo->tuple[IP_CT_DIR_REPLY].src.ip = addrs[0].s_addr;
+ }
+
+ sinfo->flags |= XT_CONNTRACK_REPLSRC;
+ break;
+
+ case '6':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (invert)
+ sinfo->invflags |= XT_CONNTRACK_REPLDST;
+
+ xtables_ipparse_any(optarg, &addrs,
+ &sinfo->dipmsk[IP_CT_DIR_REPLY],
+ &naddrs);
+ if(naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+
+ if(naddrs == 1) {
+ sinfo->tuple[IP_CT_DIR_REPLY].dst.ip = addrs[0].s_addr;
+ }
+
+ sinfo->flags |= XT_CONNTRACK_REPLDST;
+ break;
+
+ case '7':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ parse_statuses(optarg, sinfo);
+ if (invert) {
+ sinfo->invflags |= XT_CONNTRACK_STATUS;
+ }
+ sinfo->flags |= XT_CONNTRACK_STATUS;
+ break;
+
+ case '8':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ parse_expires(optarg, sinfo);
+ if (invert) {
+ sinfo->invflags |= XT_CONNTRACK_EXPIRES;
+ }
+ sinfo->flags |= XT_CONNTRACK_EXPIRES;
+ break;
+
+ default:
+ return 0;
+ }
+
+ *flags = sinfo->flags;
+ return 1;
+}
+
+static int
+conntrack_mt_parse(int c, bool invert, unsigned int *flags,
+ struct xt_conntrack_mtinfo2 *info)
+{
+ unsigned int port;
+ char *p;
+
+ switch (c) {
+ case '1': /* --ctstate */
+ conntrack_ps_states(info, optarg);
+ info->match_flags |= XT_CONNTRACK_STATE;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_STATE;
+ break;
+
+ case '2': /* --ctproto */
+ /* Canonicalize into lower case */
+ for (p = optarg; *p != '\0'; ++p)
+ *p = tolower(*p);
+ info->l4proto = xtables_parse_protocol(optarg);
+
+ if (info->l4proto == 0 && (info->invert_flags & XT_INV_PROTO))
+ xtables_error(PARAMETER_PROBLEM, "conntrack: rule would "
+ "never match protocol");
+
+ info->match_flags |= XT_CONNTRACK_PROTO;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_PROTO;
+ break;
+
+ case '7': /* --ctstatus */
+ conntrack_ps_statuses(info, optarg);
+ info->match_flags |= XT_CONNTRACK_STATUS;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_STATUS;
+ break;
+
+ case '8': /* --ctexpire */
+ conntrack_ps_expires(info, optarg);
+ info->match_flags |= XT_CONNTRACK_EXPIRES;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_EXPIRES;
+ break;
+
+ case 'a': /* --ctorigsrcport */
+ if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "conntrack",
+ "--ctorigsrcport", optarg);
+ info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
+ info->origsrc_port = htons(port);
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
+ break;
+
+ case 'b': /* --ctorigdstport */
+ if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "conntrack",
+ "--ctorigdstport", optarg);
+ info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
+ info->origdst_port = htons(port);
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
+ break;
+
+ case 'c': /* --ctreplsrcport */
+ if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "conntrack",
+ "--ctreplsrcport", optarg);
+ info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
+ info->replsrc_port = htons(port);
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
+ break;
+
+ case 'd': /* --ctrepldstport */
+ if (!xtables_strtoui(optarg, NULL, &port, 0, UINT16_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "conntrack",
+ "--ctrepldstport", optarg);
+ info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
+ info->repldst_port = htons(port);
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
+ break;
+
+ case 'e': /* --ctdir */
+ xtables_param_act(XTF_NO_INVERT, "conntrack", "--ctdir", invert);
+ if (strcasecmp(optarg, "ORIGINAL") == 0) {
+ info->match_flags |= XT_CONNTRACK_DIRECTION;
+ info->invert_flags &= ~XT_CONNTRACK_DIRECTION;
+ } else if (strcasecmp(optarg, "REPLY") == 0) {
+ info->match_flags |= XT_CONNTRACK_DIRECTION;
+ info->invert_flags |= XT_CONNTRACK_DIRECTION;
+ } else {
+ xtables_param_act(XTF_BAD_VALUE, "conntrack", "--ctdir", optarg);
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ *flags = info->match_flags;
+ return true;
+}
+
+static int
+conntrack_mt4_parse(int c, bool invert, unsigned int *flags,
+ struct xt_conntrack_mtinfo2 *info)
+{
+ struct in_addr *addr = NULL;
+ unsigned int naddrs = 0;
+
+ switch (c) {
+ case '3': /* --ctorigsrc */
+ xtables_ipparse_any(optarg, &addr, &info->origsrc_mask.in,
+ &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->origsrc_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_ORIGSRC;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+ break;
+
+ case '4': /* --ctorigdst */
+ xtables_ipparse_any(optarg, &addr, &info->origdst_mask.in,
+ &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_ORIGDST;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGDST;
+ break;
+
+ case '5': /* --ctreplsrc */
+ xtables_ipparse_any(optarg, &addr, &info->replsrc_mask.in,
+ &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_REPLSRC;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_REPLSRC;
+ break;
+
+ case '6': /* --ctrepldst */
+ xtables_ipparse_any(optarg, &addr, &info->repldst_mask.in,
+ &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_REPLDST;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_REPLDST;
+ break;
+
+
+ default:
+ return conntrack_mt_parse(c, invert, flags, info);
+ }
+
+ *flags = info->match_flags;
+ return true;
+}
+
+static int
+conntrack_mt6_parse(int c, bool invert, unsigned int *flags,
+ struct xt_conntrack_mtinfo2 *info)
+{
+ struct in6_addr *addr = NULL;
+ unsigned int naddrs = 0;
+
+ switch (c) {
+ case '3': /* --ctorigsrc */
+ xtables_ip6parse_any(optarg, &addr,
+ &info->origsrc_mask.in6, &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->origsrc_addr.in6, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_ORIGSRC;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGSRC;
+ break;
+
+ case '4': /* --ctorigdst */
+ xtables_ip6parse_any(optarg, &addr,
+ &info->origdst_mask.in6, &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->origdst_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_ORIGDST;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_ORIGDST;
+ break;
+
+ case '5': /* --ctreplsrc */
+ xtables_ip6parse_any(optarg, &addr,
+ &info->replsrc_mask.in6, &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->replsrc_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_REPLSRC;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_REPLSRC;
+ break;
+
+ case '6': /* --ctrepldst */
+ xtables_ip6parse_any(optarg, &addr,
+ &info->repldst_mask.in6, &naddrs);
+ if (naddrs > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple IP addresses not allowed");
+ if (naddrs == 1)
+ memcpy(&info->repldst_addr.in, addr, sizeof(*addr));
+ info->match_flags |= XT_CONNTRACK_REPLDST;
+ if (invert)
+ info->invert_flags |= XT_CONNTRACK_REPLDST;
+ break;
+
+
+ default:
+ return conntrack_mt_parse(c, invert, flags, info);
+ }
+
+ *flags = info->match_flags;
+ return true;
+}
+
+#define cinfo_transform(r, l) \
+ do { \
+ memcpy((r), (l), offsetof(typeof(*(l)), state_mask)); \
+ (r)->state_mask = (l)->state_mask; \
+ (r)->status_mask = (l)->status_mask; \
+ } while (false);
+
+static int
+conntrack1_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+ struct xt_conntrack_mtinfo2 up;
+
+ cinfo_transform(&up, info);
+ if (!conntrack_mt4_parse(c, invert, flags, &up))
+ return false;
+ cinfo_transform(info, &up);
+ return true;
+}
+
+static int
+conntrack1_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_conntrack_mtinfo1 *info = (void *)(*match)->data;
+ struct xt_conntrack_mtinfo2 up;
+
+ cinfo_transform(&up, info);
+ if (!conntrack_mt6_parse(c, invert, flags, &up))
+ return false;
+ cinfo_transform(info, &up);
+ return true;
+}
+
+static int
+conntrack2_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return conntrack_mt4_parse(c, invert, flags, (void *)(*match)->data);
+}
+
+static int
+conntrack2_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return conntrack_mt6_parse(c, invert, flags, (void *)(*match)->data);
+}
+
+static void conntrack_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM, "conntrack: At least one option "
+ "is required");
+}
+
+static void
+print_state(unsigned int statemask)
+{
+ const char *sep = "";
+
+ if (statemask & XT_CONNTRACK_STATE_INVALID) {
+ printf("%sINVALID", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_NEW)) {
+ printf("%sNEW", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_RELATED)) {
+ printf("%sRELATED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED)) {
+ printf("%sESTABLISHED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_UNTRACKED) {
+ printf("%sUNTRACKED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_SNAT) {
+ printf("%sSNAT", sep);
+ sep = ",";
+ }
+ if (statemask & XT_CONNTRACK_STATE_DNAT) {
+ printf("%sDNAT", sep);
+ sep = ",";
+ }
+ printf(" ");
+}
+
+static void
+print_status(unsigned int statusmask)
+{
+ const char *sep = "";
+
+ if (statusmask & IPS_EXPECTED) {
+ printf("%sEXPECTED", sep);
+ sep = ",";
+ }
+ if (statusmask & IPS_SEEN_REPLY) {
+ printf("%sSEEN_REPLY", sep);
+ sep = ",";
+ }
+ if (statusmask & IPS_ASSURED) {
+ printf("%sASSURED", sep);
+ sep = ",";
+ }
+ if (statusmask & IPS_CONFIRMED) {
+ printf("%sCONFIRMED", sep);
+ sep = ",";
+ }
+ if (statusmask == 0)
+ printf("%sNONE", sep);
+ printf(" ");
+}
+
+static void
+conntrack_dump_addr(const union nf_inet_addr *addr,
+ const union nf_inet_addr *mask,
+ unsigned int family, bool numeric)
+{
+ if (family == NFPROTO_IPV4) {
+ if (!numeric && addr->ip == 0) {
+ printf("anywhere ");
+ return;
+ }
+ if (numeric)
+ printf("%s ", xtables_ipaddr_to_numeric(&addr->in));
+ else
+ printf("%s ", xtables_ipaddr_to_anyname(&addr->in));
+ } else if (family == NFPROTO_IPV6) {
+ if (!numeric && addr->ip6[0] == 0 && addr->ip6[1] == 0 &&
+ addr->ip6[2] == 0 && addr->ip6[3] == 0) {
+ printf("anywhere ");
+ return;
+ }
+ if (numeric)
+ printf("%s ", xtables_ip6addr_to_numeric(&addr->in6));
+ else
+ printf("%s ", xtables_ip6addr_to_anyname(&addr->in6));
+ }
+}
+
+static void
+print_addr(const struct in_addr *addr, const struct in_addr *mask,
+ int inv, int numeric)
+{
+ char buf[BUFSIZ];
+
+ if (inv)
+ printf("! ");
+
+ if (mask->s_addr == 0L && !numeric)
+ printf("%s ", "anywhere");
+ else {
+ if (numeric)
+ strcpy(buf, xtables_ipaddr_to_numeric(addr));
+ else
+ strcpy(buf, xtables_ipaddr_to_anyname(addr));
+ strcat(buf, xtables_ipmask_to_numeric(mask));
+ printf("%s ", buf);
+ }
+}
+
+static void
+matchinfo_print(const void *ip, const struct xt_entry_match *match, int numeric, const char *optpfx)
+{
+ const struct xt_conntrack_info *sinfo = (const void *)match->data;
+
+ if(sinfo->flags & XT_CONNTRACK_STATE) {
+ if (sinfo->invflags & XT_CONNTRACK_STATE)
+ printf("! ");
+ printf("%sctstate ", optpfx);
+ print_state(sinfo->statemask);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_PROTO) {
+ if (sinfo->invflags & XT_CONNTRACK_PROTO)
+ printf("! ");
+ printf("%sctproto ", optpfx);
+ printf("%u ", sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
+ if (sinfo->invflags & XT_CONNTRACK_ORIGSRC)
+ printf("! ");
+ printf("%sctorigsrc ", optpfx);
+
+ print_addr(
+ (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip,
+ &sinfo->sipmsk[IP_CT_DIR_ORIGINAL],
+ false,
+ numeric);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
+ if (sinfo->invflags & XT_CONNTRACK_ORIGDST)
+ printf("! ");
+ printf("%sctorigdst ", optpfx);
+
+ print_addr(
+ (struct in_addr *)&sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip,
+ &sinfo->dipmsk[IP_CT_DIR_ORIGINAL],
+ false,
+ numeric);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
+ if (sinfo->invflags & XT_CONNTRACK_REPLSRC)
+ printf("! ");
+ printf("%sctreplsrc ", optpfx);
+
+ print_addr(
+ (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].src.ip,
+ &sinfo->sipmsk[IP_CT_DIR_REPLY],
+ false,
+ numeric);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_REPLDST) {
+ if (sinfo->invflags & XT_CONNTRACK_REPLDST)
+ printf("! ");
+ printf("%sctrepldst ", optpfx);
+
+ print_addr(
+ (struct in_addr *)&sinfo->tuple[IP_CT_DIR_REPLY].dst.ip,
+ &sinfo->dipmsk[IP_CT_DIR_REPLY],
+ false,
+ numeric);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_STATUS) {
+ if (sinfo->invflags & XT_CONNTRACK_STATUS)
+ printf("! ");
+ printf("%sctstatus ", optpfx);
+ print_status(sinfo->statusmask);
+ }
+
+ if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
+ if (sinfo->invflags & XT_CONNTRACK_EXPIRES)
+ printf("! ");
+ printf("%sctexpire ", optpfx);
+
+ if (sinfo->expires_max == sinfo->expires_min)
+ printf("%lu ", sinfo->expires_min);
+ else
+ printf("%lu:%lu ", sinfo->expires_min, sinfo->expires_max);
+ }
+
+ if (sinfo->flags & XT_CONNTRACK_DIRECTION) {
+ if (sinfo->invflags & XT_CONNTRACK_DIRECTION)
+ printf("%sctdir REPLY", optpfx);
+ else
+ printf("%sctdir ORIGINAL", optpfx);
+ }
+
+}
+
+static void
+conntrack_dump(const struct xt_conntrack_mtinfo2 *info, const char *prefix,
+ unsigned int family, bool numeric)
+{
+ if (info->match_flags & XT_CONNTRACK_STATE) {
+ if (info->invert_flags & XT_CONNTRACK_STATE)
+ printf("! ");
+ printf("%sctstate ", prefix);
+ print_state(info->state_mask);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_PROTO) {
+ if (info->invert_flags & XT_CONNTRACK_PROTO)
+ printf("! ");
+ printf("%sctproto %u ", prefix, info->l4proto);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_ORIGSRC) {
+ if (info->invert_flags & XT_CONNTRACK_ORIGSRC)
+ printf("! ");
+ printf("%sctorigsrc ", prefix);
+ conntrack_dump_addr(&info->origsrc_addr, &info->origsrc_mask,
+ family, numeric);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_ORIGDST) {
+ if (info->invert_flags & XT_CONNTRACK_ORIGDST)
+ printf("! ");
+ printf("%sctorigdst ", prefix);
+ conntrack_dump_addr(&info->origdst_addr, &info->origdst_mask,
+ family, numeric);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_REPLSRC) {
+ if (info->invert_flags & XT_CONNTRACK_REPLSRC)
+ printf("! ");
+ printf("%sctreplsrc ", prefix);
+ conntrack_dump_addr(&info->replsrc_addr, &info->replsrc_mask,
+ family, numeric);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_REPLDST) {
+ if (info->invert_flags & XT_CONNTRACK_REPLDST)
+ printf("! ");
+ printf("%sctrepldst ", prefix);
+ conntrack_dump_addr(&info->repldst_addr, &info->repldst_mask,
+ family, numeric);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) {
+ if (info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT)
+ printf("! ");
+ printf("%sctorigsrcport %u ", prefix,
+ ntohs(info->origsrc_port));
+ }
+
+ if (info->match_flags & XT_CONNTRACK_ORIGDST_PORT) {
+ if (info->invert_flags & XT_CONNTRACK_ORIGDST_PORT)
+ printf("! ");
+ printf("%sctorigdstport %u ", prefix,
+ ntohs(info->origdst_port));
+ }
+
+ if (info->match_flags & XT_CONNTRACK_REPLSRC_PORT) {
+ if (info->invert_flags & XT_CONNTRACK_REPLSRC_PORT)
+ printf("! ");
+ printf("%sctreplsrcport %u ", prefix,
+ ntohs(info->replsrc_port));
+ }
+
+ if (info->match_flags & XT_CONNTRACK_REPLDST_PORT) {
+ if (info->invert_flags & XT_CONNTRACK_REPLDST_PORT)
+ printf("! ");
+ printf("%sctrepldstport %u ", prefix,
+ ntohs(info->repldst_port));
+ }
+
+ if (info->match_flags & XT_CONNTRACK_STATUS) {
+ if (info->invert_flags & XT_CONNTRACK_STATUS)
+ printf("! ");
+ printf("%sctstatus ", prefix);
+ print_status(info->status_mask);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_EXPIRES) {
+ if (info->invert_flags & XT_CONNTRACK_EXPIRES)
+ printf("! ");
+ printf("%sctexpire ", prefix);
+
+ if (info->expires_max == info->expires_min)
+ printf("%u ", (unsigned int)info->expires_min);
+ else
+ printf("%u:%u ", (unsigned int)info->expires_min,
+ (unsigned int)info->expires_max);
+ }
+
+ if (info->match_flags & XT_CONNTRACK_DIRECTION) {
+ if (info->invert_flags & XT_CONNTRACK_DIRECTION)
+ printf("%sctdir REPLY", prefix);
+ else
+ printf("%sctdir ORIGINAL", prefix);
+ }
+}
+
+static void conntrack_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ matchinfo_print(ip, match, numeric, "");
+}
+
+static void
+conntrack1_mt4_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
+ struct xt_conntrack_mtinfo2 up;
+
+ cinfo_transform(&up, info);
+ conntrack_dump(&up, "", NFPROTO_IPV4, numeric);
+}
+
+static void
+conntrack1_mt6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
+ struct xt_conntrack_mtinfo2 up;
+
+ cinfo_transform(&up, info);
+ conntrack_dump(&up, "", NFPROTO_IPV6, numeric);
+}
+
+static void
+conntrack_mt_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ conntrack_dump((const void *)match->data, "", NFPROTO_IPV4, numeric);
+}
+
+static void
+conntrack_mt6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ conntrack_dump((const void *)match->data, "", NFPROTO_IPV6, numeric);
+}
+
+static void conntrack_save(const void *ip, const struct xt_entry_match *match)
+{
+ matchinfo_print(ip, match, 1, "--");
+}
+
+static void conntrack_mt_save(const void *ip,
+ const struct xt_entry_match *match)
+{
+ conntrack_dump((const void *)match->data, "--", NFPROTO_IPV4, true);
+}
+
+static void conntrack_mt6_save(const void *ip,
+ const struct xt_entry_match *match)
+{
+ conntrack_dump((const void *)match->data, "--", NFPROTO_IPV6, true);
+}
+
+static void
+conntrack1_mt4_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
+ struct xt_conntrack_mtinfo2 up;
+
+ cinfo_transform(&up, info);
+ conntrack_dump(&up, "--", NFPROTO_IPV4, true);
+}
+
+static void
+conntrack1_mt6_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_conntrack_mtinfo1 *info = (void *)match->data;
+ struct xt_conntrack_mtinfo2 up;
+
+ cinfo_transform(&up, info);
+ conntrack_dump(&up, "--", NFPROTO_IPV6, true);
+}
+
+static struct xtables_match conntrack_mt_reg[] = {
+ {
+ .version = XTABLES_VERSION,
+ .name = "conntrack",
+ .revision = 0,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_info)),
+ .help = conntrack_mt_help,
+ .parse = conntrack_parse,
+ .final_check = conntrack_mt_check,
+ .print = conntrack_print,
+ .save = conntrack_save,
+ .extra_opts = conntrack_mt_opts_v0,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "conntrack",
+ .revision = 1,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+ .help = conntrack_mt_help,
+ .parse = conntrack1_mt4_parse,
+ .final_check = conntrack_mt_check,
+ .print = conntrack1_mt4_print,
+ .save = conntrack1_mt4_save,
+ .extra_opts = conntrack_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "conntrack",
+ .revision = 1,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)),
+ .help = conntrack_mt_help,
+ .parse = conntrack1_mt6_parse,
+ .final_check = conntrack_mt_check,
+ .print = conntrack1_mt6_print,
+ .save = conntrack1_mt6_save,
+ .extra_opts = conntrack_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "conntrack",
+ .revision = 2,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
+ .help = conntrack_mt_help,
+ .parse = conntrack2_mt4_parse,
+ .final_check = conntrack_mt_check,
+ .print = conntrack_mt_print,
+ .save = conntrack_mt_save,
+ .extra_opts = conntrack_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "conntrack",
+ .revision = 2,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)),
+ .help = conntrack_mt_help,
+ .parse = conntrack2_mt6_parse,
+ .final_check = conntrack_mt_check,
+ .print = conntrack_mt6_print,
+ .save = conntrack_mt6_save,
+ .extra_opts = conntrack_mt_opts,
+ },
+};
+
+void libxt_conntrack_init(void)
+{
+ xtables_register_matches(conntrack_mt_reg, ARRAY_SIZE(conntrack_mt_reg));
+}
diff --git a/extensions/libxt_conntrack.man b/extensions/libxt_conntrack.man
new file mode 100644
index 0000000..b3d9e73
--- /dev/null
+++ b/extensions/libxt_conntrack.man
@@ -0,0 +1,81 @@
+This module, when combined with connection tracking, allows access to the
+connection tracking state for this packet/connection.
+.TP
+[\fB!\fR] \fB\-\-ctstate\fP \fIstatelist\fP
+\fIstatelist\fR is a comma separated list of the connection states to match.
+Possible states are listed below.
+.TP
+[\fB!\fR] \fB\-\-ctproto\fP \fIl4proto\fP
+Layer-4 protocol to match (by number or name)
+.TP
+[\fB!\fR] \fB\-\-ctorigsrc\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctorigdst\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctreplsrc\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctrepldst\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+Match against original/reply source/destination address
+.TP
+[\fB!\fR] \fB\-\-ctorigsrcport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctorigdstport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctreplsrcport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctrepldstport\fP \fIport\fP
+Match against original/reply source/destination port (TCP/UDP/etc.) or GRE key.
+.TP
+[\fB!\fR] \fB\-\-ctstatus\fP \fIstatelist\fP
+\fIstatuslist\fR is a comma separated list of the connection statuses to match.
+Possible statuses are listed below.
+.TP
+[\fB!\fR] \fB\-\-ctexpire\fP \fItime\fP[\fB:\fP\fItime\fP]
+Match remaining lifetime in seconds against given value or range of values
+(inclusive)
+.TP
+\fB\-\-ctdir\fP {\fBORIGINAL\fP|\fBREPLY\fP}
+Match packets that are flowing in the specified direction. If this flag is not
+specified at all, matches packets in both directions.
+.PP
+States for \fB\-\-ctstate\fP:
+.TP
+\fBINVALID\fR
+meaning that the packet is associated with no known connection
+.TP
+\fBNEW\fR
+meaning that the packet has started a new connection, or otherwise associated
+with a connection which has not seen packets in both directions, and
+.TP
+\fBESTABLISHED\fR
+meaning that the packet is associated with a connection which has seen packets
+in both directions,
+.TP
+\fBRELATED\fR
+meaning that the packet is starting a new connection, but is associated with an
+existing connection, such as an FTP data transfer, or an ICMP error.
+.TP
+\fBSNAT\fR
+A virtual state, matching if the original source address differs from the reply
+destination.
+.TP
+\fBDNAT\fR
+A virtual state, matching if the original destination differs from the reply
+source.
+.PP
+Statuses for \fB\-\-ctstatus\fP:
+.TP
+\fBNONE\fR
+None of the below.
+.TP
+\fBEXPECTED\fR
+This is an expected connection (i.e. a conntrack helper set it up)
+.TP
+\fBSEEN_REPLY\fR
+Conntrack has seen packets in both directions.
+.TP
+\fBASSURED\fR
+Conntrack entry should never be early-expired.
+.TP
+\fBCONFIRMED\fR
+Connection is confirmed: originating packet has left box.
diff --git a/extensions/libxt_dccp.c b/extensions/libxt_dccp.c
new file mode 100644
index 0000000..695422f
--- /dev/null
+++ b/extensions/libxt_dccp.c
@@ -0,0 +1,354 @@
+/* Shared library add-on to iptables for DCCP matching
+ *
+ * (C) 2005 by Harald Welte <laforge@netfilter.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <ctype.h>
+
+#include <netinet/in.h>
+#include <xtables.h>
+#include <linux/dccp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_dccp.h>
+
+#if 0
+#define DEBUGP(format, first...) printf(format, ##first)
+#define static
+#else
+#define DEBUGP(format, fist...)
+#endif
+
+static void dccp_init(struct xt_entry_match *m)
+{
+ struct xt_dccp_info *einfo = (struct xt_dccp_info *)m->data;
+
+ memset(einfo, 0, sizeof(struct xt_dccp_info));
+}
+
+static void dccp_help(void)
+{
+ printf(
+"dccp match options\n"
+"[!] --source-port port[:port] match source port(s)\n"
+" --sport ...\n"
+"[!] --destination-port port[:port] match destination port(s)\n"
+" --dport ...\n");
+}
+
+static const struct option dccp_opts[] = {
+ { .name = "source-port", .has_arg = 1, .val = '1' },
+ { .name = "sport", .has_arg = 1, .val = '1' },
+ { .name = "destination-port", .has_arg = 1, .val = '2' },
+ { .name = "dport", .has_arg = 1, .val = '2' },
+ { .name = "dccp-types", .has_arg = 1, .val = '3' },
+ { .name = "dccp-option", .has_arg = 1, .val = '4' },
+ { .name = NULL }
+};
+
+static void
+parse_dccp_ports(const char *portstring,
+ u_int16_t *ports)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(portstring);
+ DEBUGP("%s\n", portstring);
+ if ((cp = strchr(buffer, ':')) == NULL) {
+ ports[0] = ports[1] = xtables_parse_port(buffer, "dccp");
+ }
+ else {
+ *cp = '\0';
+ cp++;
+
+ ports[0] = buffer[0] ? xtables_parse_port(buffer, "dccp") : 0;
+ ports[1] = cp[0] ? xtables_parse_port(cp, "dccp") : 0xFFFF;
+
+ if (ports[0] > ports[1])
+ xtables_error(PARAMETER_PROBLEM,
+ "invalid portrange (min > max)");
+ }
+ free(buffer);
+}
+
+static const char *const dccp_pkt_types[] = {
+ [DCCP_PKT_REQUEST] = "REQUEST",
+ [DCCP_PKT_RESPONSE] = "RESPONSE",
+ [DCCP_PKT_DATA] = "DATA",
+ [DCCP_PKT_ACK] = "ACK",
+ [DCCP_PKT_DATAACK] = "DATAACK",
+ [DCCP_PKT_CLOSEREQ] = "CLOSEREQ",
+ [DCCP_PKT_CLOSE] = "CLOSE",
+ [DCCP_PKT_RESET] = "RESET",
+ [DCCP_PKT_SYNC] = "SYNC",
+ [DCCP_PKT_SYNCACK] = "SYNCACK",
+ [DCCP_PKT_INVALID] = "INVALID",
+};
+
+static u_int16_t
+parse_dccp_types(const char *typestring)
+{
+ u_int16_t typemask = 0;
+ char *ptr, *buffer;
+
+ buffer = strdup(typestring);
+
+ for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(dccp_pkt_types); ++i)
+ if (!strcasecmp(dccp_pkt_types[i], ptr)) {
+ typemask |= (1 << i);
+ break;
+ }
+ if (i == ARRAY_SIZE(dccp_pkt_types))
+ xtables_error(PARAMETER_PROBLEM,
+ "Unknown DCCP type `%s'", ptr);
+ }
+
+ free(buffer);
+ return typemask;
+}
+
+static u_int8_t parse_dccp_option(char *optstring)
+{
+ unsigned int ret;
+
+ if (!xtables_strtoui(optstring, NULL, &ret, 1, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM, "Bad DCCP option \"%s\"",
+ optstring);
+
+ return ret;
+}
+
+static int
+dccp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_dccp_info *einfo
+ = (struct xt_dccp_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & XT_DCCP_SRC_PORTS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--source-port' allowed");
+ einfo->flags |= XT_DCCP_SRC_PORTS;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_dccp_ports(optarg, einfo->spts);
+ if (invert)
+ einfo->invflags |= XT_DCCP_SRC_PORTS;
+ *flags |= XT_DCCP_SRC_PORTS;
+ break;
+
+ case '2':
+ if (*flags & XT_DCCP_DEST_PORTS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--destination-port' allowed");
+ einfo->flags |= XT_DCCP_DEST_PORTS;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_dccp_ports(optarg, einfo->dpts);
+ if (invert)
+ einfo->invflags |= XT_DCCP_DEST_PORTS;
+ *flags |= XT_DCCP_DEST_PORTS;
+ break;
+
+ case '3':
+ if (*flags & XT_DCCP_TYPE)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--dccp-types' allowed");
+ einfo->flags |= XT_DCCP_TYPE;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ einfo->typemask = parse_dccp_types(optarg);
+ if (invert)
+ einfo->invflags |= XT_DCCP_TYPE;
+ *flags |= XT_DCCP_TYPE;
+ break;
+
+ case '4':
+ if (*flags & XT_DCCP_OPTION)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--dccp-option' allowed");
+ einfo->flags |= XT_DCCP_OPTION;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ einfo->option = parse_dccp_option(optarg);
+ if (invert)
+ einfo->invflags |= XT_DCCP_OPTION;
+ *flags |= XT_DCCP_OPTION;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static char *
+port_to_service(int port)
+{
+ struct servent *service;
+
+ if ((service = getservbyport(htons(port), "dccp")))
+ return service->s_name;
+
+ return NULL;
+}
+
+static void
+print_port(u_int16_t port, int numeric)
+{
+ char *service;
+
+ if (numeric || (service = port_to_service(port)) == NULL)
+ printf("%u", port);
+ else
+ printf("%s", service);
+}
+
+static void
+print_ports(const char *name, u_int16_t min, u_int16_t max,
+ int invert, int numeric)
+{
+ const char *inv = invert ? "!" : "";
+
+ if (min != 0 || max != 0xFFFF || invert) {
+ printf("%s", name);
+ if (min == max) {
+ printf(":%s", inv);
+ print_port(min, numeric);
+ } else {
+ printf("s:%s", inv);
+ print_port(min, numeric);
+ printf(":");
+ print_port(max, numeric);
+ }
+ printf(" ");
+ }
+}
+
+static void
+print_types(u_int16_t types, int inverted, int numeric)
+{
+ int have_type = 0;
+
+ if (inverted)
+ printf("! ");
+
+ while (types) {
+ unsigned int i;
+
+ for (i = 0; !(types & (1 << i)); i++);
+
+ if (have_type)
+ printf(",");
+ else
+ have_type = 1;
+
+ if (numeric)
+ printf("%u", i);
+ else
+ printf("%s", dccp_pkt_types[i]);
+
+ types &= ~(1 << i);
+ }
+}
+
+static void
+print_option(u_int8_t option, int invert, int numeric)
+{
+ if (option || invert)
+ printf("option=%s%u ", invert ? "!" : "", option);
+}
+
+static void
+dccp_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_dccp_info *einfo =
+ (const struct xt_dccp_info *)match->data;
+
+ printf("dccp ");
+
+ if (einfo->flags & XT_DCCP_SRC_PORTS) {
+ print_ports("spt", einfo->spts[0], einfo->spts[1],
+ einfo->invflags & XT_DCCP_SRC_PORTS,
+ numeric);
+ }
+
+ if (einfo->flags & XT_DCCP_DEST_PORTS) {
+ print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
+ einfo->invflags & XT_DCCP_DEST_PORTS,
+ numeric);
+ }
+
+ if (einfo->flags & XT_DCCP_TYPE) {
+ print_types(einfo->typemask,
+ einfo->invflags & XT_DCCP_TYPE,
+ numeric);
+ }
+
+ if (einfo->flags & XT_DCCP_OPTION) {
+ print_option(einfo->option,
+ einfo->invflags & XT_DCCP_OPTION, numeric);
+ }
+}
+
+static void dccp_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_dccp_info *einfo =
+ (const struct xt_dccp_info *)match->data;
+
+ if (einfo->flags & XT_DCCP_SRC_PORTS) {
+ if (einfo->invflags & XT_DCCP_SRC_PORTS)
+ printf("! ");
+ if (einfo->spts[0] != einfo->spts[1])
+ printf("--sport %u:%u ",
+ einfo->spts[0], einfo->spts[1]);
+ else
+ printf("--sport %u ", einfo->spts[0]);
+ }
+
+ if (einfo->flags & XT_DCCP_DEST_PORTS) {
+ if (einfo->invflags & XT_DCCP_DEST_PORTS)
+ printf("! ");
+ if (einfo->dpts[0] != einfo->dpts[1])
+ printf("--dport %u:%u ",
+ einfo->dpts[0], einfo->dpts[1]);
+ else
+ printf("--dport %u ", einfo->dpts[0]);
+ }
+
+ if (einfo->flags & XT_DCCP_TYPE) {
+ printf("--dccp-type ");
+ print_types(einfo->typemask, einfo->invflags & XT_DCCP_TYPE,0);
+ }
+
+ if (einfo->flags & XT_DCCP_OPTION) {
+ printf("--dccp-option %s%u ",
+ einfo->typemask & XT_DCCP_OPTION ? "! " : "",
+ einfo->option);
+ }
+}
+
+static struct xtables_match dccp_match = {
+ .name = "dccp",
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_dccp_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_dccp_info)),
+ .help = dccp_help,
+ .init = dccp_init,
+ .parse = dccp_parse,
+ .print = dccp_print,
+ .save = dccp_save,
+ .extra_opts = dccp_opts,
+};
+
+void libxt_dccp_init(void)
+{
+ xtables_register_match(&dccp_match);
+}
diff --git a/extensions/libxt_dccp.man b/extensions/libxt_dccp.man
new file mode 100644
index 0000000..82c3f70
--- /dev/null
+++ b/extensions/libxt_dccp.man
@@ -0,0 +1,12 @@
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-dccp\-types\fP \fImask\fP
+Match when the DCCP packet type is one of 'mask'. 'mask' is a comma-separated
+list of packet types. Packet types are:
+.BR "REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID" .
+.TP
+[\fB!\fP] \fB\-\-dccp\-option\fP \fInumber\fP
+Match if DCP option set.
diff --git a/extensions/libxt_dscp.c b/extensions/libxt_dscp.c
new file mode 100644
index 0000000..1fd4217
--- /dev/null
+++ b/extensions/libxt_dscp.c
@@ -0,0 +1,150 @@
+/* Shared library add-on to iptables for DSCP
+ *
+ * (C) 2002 by Harald Welte <laforge@gnumonks.org>
+ *
+ * This program is distributed under the terms of GNU GPL v2, 1991
+ *
+ * libipt_dscp.c borrowed heavily from libipt_tos.c
+ *
+ * --class support added by Iain Barnes
+ *
+ * For a list of DSCP codepoints see
+ * http://www.iana.org/assignments/dscp-registry
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_dscp.h>
+
+/* This is evil, but it's my code - HW*/
+#include "dscp_helper.c"
+
+static void dscp_help(void)
+{
+ printf(
+"dscp match options\n"
+"[!] --dscp value Match DSCP codepoint with numerical value\n"
+" This value can be in decimal (ex: 32)\n"
+" or in hex (ex: 0x20)\n"
+"[!] --dscp-class name Match the DiffServ class. This value may\n"
+" be any of the BE,EF, AFxx or CSx classes\n"
+"\n"
+" These two options are mutually exclusive !\n");
+}
+
+static const struct option dscp_opts[] = {
+ { "dscp", 1, NULL, 'F' },
+ { "dscp-class", 1, NULL, 'G' },
+ { .name = NULL }
+};
+
+static void
+parse_dscp(const char *s, struct xt_dscp_info *dinfo)
+{
+ unsigned int dscp;
+
+ if (!xtables_strtoui(s, NULL, &dscp, 0, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid dscp `%s'\n", s);
+
+ if (dscp > XT_DSCP_MAX)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP `%d` out of range\n", dscp);
+
+ dinfo->dscp = dscp;
+}
+
+
+static void
+parse_class(const char *s, struct xt_dscp_info *dinfo)
+{
+ unsigned int dscp = class_to_dscp(s);
+
+ /* Assign the value */
+ dinfo->dscp = dscp;
+}
+
+
+static int
+dscp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_dscp_info *dinfo
+ = (struct xt_dscp_info *)(*match)->data;
+
+ switch (c) {
+ case 'F':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP match: Only use --dscp ONCE!");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_dscp(optarg, dinfo);
+ if (invert)
+ dinfo->invert = 1;
+ *flags = 1;
+ break;
+
+ case 'G':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP match: Only use --dscp-class ONCE!");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_class(optarg, dinfo);
+ if (invert)
+ dinfo->invert = 1;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void dscp_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "DSCP match: Parameter --dscp is required");
+}
+
+static void
+dscp_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_dscp_info *dinfo =
+ (const struct xt_dscp_info *)match->data;
+ printf("DSCP match %s0x%02x", dinfo->invert ? "!" : "", dinfo->dscp);
+}
+
+static void dscp_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_dscp_info *dinfo =
+ (const struct xt_dscp_info *)match->data;
+
+ printf("%s--dscp 0x%02x ", dinfo->invert ? "! " : "", dinfo->dscp);
+}
+
+static struct xtables_match dscp_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "dscp",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_dscp_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_dscp_info)),
+ .help = dscp_help,
+ .parse = dscp_parse,
+ .final_check = dscp_check,
+ .print = dscp_print,
+ .save = dscp_save,
+ .extra_opts = dscp_opts,
+};
+
+void libxt_dscp_init(void)
+{
+ xtables_register_match(&dscp_match);
+}
diff --git a/extensions/libipt_dscp.man b/extensions/libxt_dscp.man
index 4a84210..63a17da 100644
--- a/extensions/libipt_dscp.man
+++ b/extensions/libxt_dscp.man
@@ -1,10 +1,10 @@
This module matches the 6 bit DSCP field within the TOS field in the
IP header. DSCP has superseded TOS within the IETF.
.TP
-.BI "--dscp " "value"
-Match against a numeric (decimal or hex) value [0-32].
+[\fB!\fP] \fB\-\-dscp\fP \fIvalue\fP
+Match against a numeric (decimal or hex) value [0-63].
.TP
-.BI "--dscp-class " "\fIDiffServ Class\fP"
+[\fB!\fP] \fB\-\-dscp\-class\fP \fIclass\fP
Match the DiffServ class. This value may be any of the
BE, EF, AFxx or CSx classes. It will then be converted
-into it's according numeric value.
+into its according numeric value.
diff --git a/extensions/libxt_esp.c b/extensions/libxt_esp.c
new file mode 100644
index 0000000..3cd1ef3
--- /dev/null
+++ b/extensions/libxt_esp.c
@@ -0,0 +1,168 @@
+/* Shared library add-on to iptables to add ESP support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_esp.h>
+
+static void esp_help(void)
+{
+ printf(
+"esp match options:\n"
+"[!] --espspi spi[:spi]\n"
+" match spi (range)\n");
+}
+
+static const struct option esp_opts[] = {
+ { "espspi", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static u_int32_t
+parse_esp_spi(const char *spistr)
+{
+ unsigned long int spi;
+ char* ep;
+
+ spi = strtoul(spistr,&ep,0) ;
+
+ if ( spistr == ep ) {
+ xtables_error(PARAMETER_PROBLEM,
+ "ESP no valid digits in spi `%s'", spistr);
+ }
+ if ( spi == ULONG_MAX && errno == ERANGE ) {
+ xtables_error(PARAMETER_PROBLEM,
+ "spi `%s' specified too big: would overflow", spistr);
+ }
+ if ( *spistr != '\0' && *ep != '\0' ) {
+ xtables_error(PARAMETER_PROBLEM,
+ "ESP error parsing spi `%s'", spistr);
+ }
+ return spi;
+}
+
+static void
+parse_esp_spis(const char *spistring, u_int32_t *spis)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(spistring);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ spis[0] = spis[1] = parse_esp_spi(buffer);
+ else {
+ *cp = '\0';
+ cp++;
+
+ spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
+ spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
+ if (spis[0] > spis[1])
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid ESP spi range: %s", spistring);
+ }
+ free(buffer);
+}
+
+static void esp_init(struct xt_entry_match *m)
+{
+ struct xt_esp *espinfo = (struct xt_esp *)m->data;
+
+ espinfo->spis[1] = 0xFFFFFFFF;
+}
+
+#define ESP_SPI 0x01
+
+static int
+esp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_esp *espinfo = (struct xt_esp *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & ESP_SPI)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--espspi' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_esp_spis(optarg, espinfo->spis);
+ if (invert)
+ espinfo->invflags |= XT_ESP_INV_SPI;
+ *flags |= ESP_SPI;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+print_spis(const char *name, u_int32_t min, u_int32_t max,
+ int invert)
+{
+ const char *inv = invert ? "!" : "";
+
+ if (min != 0 || max != 0xFFFFFFFF || invert) {
+ if (min == max)
+ printf("%s:%s%u ", name, inv, min);
+ else
+ printf("%ss:%s%u:%u ", name, inv, min, max);
+ }
+}
+
+static void
+esp_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_esp *esp = (struct xt_esp *)match->data;
+
+ printf("esp ");
+ print_spis("spi", esp->spis[0], esp->spis[1],
+ esp->invflags & XT_ESP_INV_SPI);
+ if (esp->invflags & ~XT_ESP_INV_MASK)
+ printf("Unknown invflags: 0x%X ",
+ esp->invflags & ~XT_ESP_INV_MASK);
+}
+
+static void esp_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_esp *espinfo = (struct xt_esp *)match->data;
+
+ if (!(espinfo->spis[0] == 0
+ && espinfo->spis[1] == 0xFFFFFFFF)) {
+ printf("%s--espspi ",
+ (espinfo->invflags & XT_ESP_INV_SPI) ? "! " : "");
+ if (espinfo->spis[0]
+ != espinfo->spis[1])
+ printf("%u:%u ",
+ espinfo->spis[0],
+ espinfo->spis[1]);
+ else
+ printf("%u ",
+ espinfo->spis[0]);
+ }
+
+}
+
+static struct xtables_match esp_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "esp",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_esp)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_esp)),
+ .help = esp_help,
+ .init = esp_init,
+ .parse = esp_parse,
+ .print = esp_print,
+ .save = esp_save,
+ .extra_opts = esp_opts,
+};
+
+void libxt_esp_init(void)
+{
+ xtables_register_match(&esp_match);
+}
diff --git a/extensions/libipt_esp.man b/extensions/libxt_esp.man
index 7898e02..699a41c 100644
--- a/extensions/libipt_esp.man
+++ b/extensions/libxt_esp.man
@@ -1,3 +1,3 @@
This module matches the SPIs in ESP header of IPsec packets.
.TP
-.BR "--espspi " "[!] \fIspi\fP[:\fIspi\fP]"
+[\fB!\fP] \fB\-\-espspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
new file mode 100644
index 0000000..1ec16eb
--- /dev/null
+++ b/extensions/libxt_hashlimit.c
@@ -0,0 +1,713 @@
+/* ip6tables match extension for limiting packets per destination
+ *
+ * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
+ *
+ * Development of this code was funded by Astaro AG, http://www.astaro.com/
+ *
+ * Based on ipt_limit.c by
+ * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
+ * Hervé Eychenne <rv@wallfire.org>
+ *
+ * Error corections by nmalykh@bilim.com (22.01.2005)
+ */
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <stddef.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_hashlimit.h>
+
+#define XT_HASHLIMIT_BURST 5
+
+/* miliseconds */
+#define XT_HASHLIMIT_GCINTERVAL 1000
+#define XT_HASHLIMIT_EXPIRE 10000
+
+static void hashlimit_help(void)
+{
+ printf(
+"hashlimit match options:\n"
+"--hashlimit <avg> max average match rate\n"
+" [Packets per second unless followed by \n"
+" /sec /minute /hour /day postfixes]\n"
+"--hashlimit-mode <mode> mode is a comma-separated list of\n"
+" dstip,srcip,dstport,srcport\n"
+"--hashlimit-name <name> name for /proc/net/ipt_hashlimit/\n"
+"[--hashlimit-burst <num>] number to match in a burst, default %u\n"
+"[--hashlimit-htable-size <num>] number of hashtable buckets\n"
+"[--hashlimit-htable-max <num>] number of hashtable entries\n"
+"[--hashlimit-htable-gcinterval] interval between garbage collection runs\n"
+"[--hashlimit-htable-expire] after which time are idle entries expired?\n",
+XT_HASHLIMIT_BURST);
+}
+
+static void hashlimit_mt_help(void)
+{
+ printf(
+"hashlimit match options:\n"
+" --hashlimit-upto <avg> max average match rate\n"
+" [Packets per second unless followed by \n"
+" /sec /minute /hour /day postfixes]\n"
+" --hashlimit-above <avg> min average match rate\n"
+" --hashlimit-mode <mode> mode is a comma-separated list of\n"
+" dstip,srcip,dstport,srcport (or none)\n"
+" --hashlimit-srcmask <length> source address grouping prefix length\n"
+" --hashlimit-dstmask <length> destination address grouping prefix length\n"
+" --hashlimit-name <name> name for /proc/net/ipt_hashlimit\n"
+" --hashlimit-burst <num> number to match in a burst, default %u\n"
+" --hashlimit-htable-size <num> number of hashtable buckets\n"
+" --hashlimit-htable-max <num> number of hashtable entries\n"
+" --hashlimit-htable-gcinterval interval between garbage collection runs\n"
+" --hashlimit-htable-expire after which time are idle entries expired?\n"
+"\n", XT_HASHLIMIT_BURST);
+}
+
+static const struct option hashlimit_opts[] = {
+ { "hashlimit", 1, NULL, '%' },
+ { "hashlimit-burst", 1, NULL, '$' },
+ { "hashlimit-htable-size", 1, NULL, '&' },
+ { "hashlimit-htable-max", 1, NULL, '*' },
+ { "hashlimit-htable-gcinterval", 1, NULL, '(' },
+ { "hashlimit-htable-expire", 1, NULL, ')' },
+ { "hashlimit-mode", 1, NULL, '_' },
+ { "hashlimit-name", 1, NULL, '"' },
+ { .name = NULL }
+};
+
+static const struct option hashlimit_mt_opts[] = {
+ {.name = "hashlimit-upto", .has_arg = true, .val = '%'},
+ {.name = "hashlimit-above", .has_arg = true, .val = '^'},
+ {.name = "hashlimit", .has_arg = true, .val = '%'},
+ {.name = "hashlimit-srcmask", .has_arg = true, .val = '<'},
+ {.name = "hashlimit-dstmask", .has_arg = true, .val = '>'},
+ {.name = "hashlimit-burst", .has_arg = true, .val = '$'},
+ {.name = "hashlimit-htable-size", .has_arg = true, .val = '&'},
+ {.name = "hashlimit-htable-max", .has_arg = true, .val = '*'},
+ {.name = "hashlimit-htable-gcinterval", .has_arg = true, .val = '('},
+ {.name = "hashlimit-htable-expire", .has_arg = true, .val = ')'},
+ {.name = "hashlimit-mode", .has_arg = true, .val = '_'},
+ {.name = "hashlimit-name", .has_arg = true, .val = '"'},
+ {},
+};
+
+static
+int parse_rate(const char *rate, u_int32_t *val)
+{
+ const char *delim;
+ u_int32_t r;
+ u_int32_t mult = 1; /* Seconds by default. */
+
+ delim = strchr(rate, '/');
+ if (delim) {
+ if (strlen(delim+1) == 0)
+ return 0;
+
+ if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
+ mult = 1;
+ else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
+ mult = 60;
+ else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
+ mult = 60*60;
+ else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
+ mult = 24*60*60;
+ else
+ return 0;
+ }
+ r = atoi(rate);
+ if (!r)
+ return 0;
+
+ /* This would get mapped to infinite (1/day is minimum they
+ can specify, so we're ok at that end). */
+ if (r / mult > XT_HASHLIMIT_SCALE)
+ xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
+
+ *val = XT_HASHLIMIT_SCALE * mult / r;
+ return 1;
+}
+
+static void hashlimit_init(struct xt_entry_match *m)
+{
+ struct xt_hashlimit_info *r = (struct xt_hashlimit_info *)m->data;
+
+ r->cfg.mode = 0;
+ r->cfg.burst = XT_HASHLIMIT_BURST;
+ r->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ r->cfg.expire = XT_HASHLIMIT_EXPIRE;
+
+}
+
+static void hashlimit_mt4_init(struct xt_entry_match *match)
+{
+ struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
+
+ info->cfg.mode = 0;
+ info->cfg.burst = XT_HASHLIMIT_BURST;
+ info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ info->cfg.expire = XT_HASHLIMIT_EXPIRE;
+ info->cfg.srcmask = 32;
+ info->cfg.dstmask = 32;
+}
+
+static void hashlimit_mt6_init(struct xt_entry_match *match)
+{
+ struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
+
+ info->cfg.mode = 0;
+ info->cfg.burst = XT_HASHLIMIT_BURST;
+ info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
+ info->cfg.expire = XT_HASHLIMIT_EXPIRE;
+ info->cfg.srcmask = 128;
+ info->cfg.dstmask = 128;
+}
+
+/* Parse a 'mode' parameter into the required bitmask */
+static int parse_mode(uint32_t *mode, char *option_arg)
+{
+ char *tok;
+ char *arg = strdup(option_arg);
+
+ if (!arg)
+ return -1;
+
+ for (tok = strtok(arg, ",|");
+ tok;
+ tok = strtok(NULL, ",|")) {
+ if (!strcmp(tok, "dstip"))
+ *mode |= XT_HASHLIMIT_HASH_DIP;
+ else if (!strcmp(tok, "srcip"))
+ *mode |= XT_HASHLIMIT_HASH_SIP;
+ else if (!strcmp(tok, "srcport"))
+ *mode |= XT_HASHLIMIT_HASH_SPT;
+ else if (!strcmp(tok, "dstport"))
+ *mode |= XT_HASHLIMIT_HASH_DPT;
+ else {
+ free(arg);
+ return -1;
+ }
+ }
+ free(arg);
+ return 0;
+}
+
+enum {
+ PARAM_LIMIT = 1 << 0,
+ PARAM_BURST = 1 << 1,
+ PARAM_MODE = 1 << 2,
+ PARAM_NAME = 1 << 3,
+ PARAM_SIZE = 1 << 4,
+ PARAM_MAX = 1 << 5,
+ PARAM_GCINTERVAL = 1 << 6,
+ PARAM_EXPIRE = 1 << 7,
+ PARAM_SRCMASK = 1 << 8,
+ PARAM_DSTMASK = 1 << 9,
+};
+
+static int
+hashlimit_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_hashlimit_info *r =
+ (struct xt_hashlimit_info *)(*match)->data;
+ unsigned int num;
+
+ switch(c) {
+ case '%':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit",
+ *flags & PARAM_LIMIT);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!parse_rate(optarg, &r->cfg.avg))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad rate `%s'", optarg);
+ *flags |= PARAM_LIMIT;
+ break;
+
+ case '$':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
+ *flags & PARAM_BURST);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --hashlimit-burst `%s'", optarg);
+ r->cfg.burst = num;
+ *flags |= PARAM_BURST;
+ break;
+ case '&':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
+ *flags & PARAM_SIZE);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --hashlimit-htable-size: `%s'", optarg);
+ r->cfg.size = num;
+ *flags |= PARAM_SIZE;
+ break;
+ case '*':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
+ *flags & PARAM_MAX);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --hashlimit-htable-max: `%s'", optarg);
+ r->cfg.max = num;
+ *flags |= PARAM_MAX;
+ break;
+ case '(':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
+ "--hashlimit-htable-gcinterval",
+ *flags & PARAM_GCINTERVAL);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --hashlimit-htable-gcinterval: `%s'",
+ optarg);
+ /* FIXME: not HZ dependent!! */
+ r->cfg.gc_interval = num;
+ *flags |= PARAM_GCINTERVAL;
+ break;
+ case ')':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
+ "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --hashlimit-htable-expire: `%s'", optarg);
+ /* FIXME: not HZ dependent */
+ r->cfg.expire = num;
+ *flags |= PARAM_EXPIRE;
+ break;
+ case '_':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
+ *flags & PARAM_MODE);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (parse_mode(&r->cfg.mode, optarg) < 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --hashlimit-mode: `%s'\n", optarg);
+ *flags |= PARAM_MODE;
+ break;
+ case '"':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name",
+ *flags & PARAM_NAME);
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (strlen(optarg) == 0)
+ xtables_error(PARAMETER_PROBLEM, "Zero-length name?");
+ strncpy(r->name, optarg, sizeof(r->name));
+ *flags |= PARAM_NAME;
+ break;
+ default:
+ return 0;
+ }
+
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "hashlimit does not support invert");
+
+ return 1;
+}
+
+static int
+hashlimit_mt_parse(struct xt_hashlimit_mtinfo1 *info, unsigned int *flags,
+ int c, int invert, unsigned int maxmask)
+{
+ unsigned int num;
+
+ switch(c) {
+ case '%': /* --hashlimit / --hashlimit-below */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-upto",
+ *flags & PARAM_LIMIT);
+ if (invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (!parse_rate(optarg, &info->cfg.avg))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-upto", optarg);
+ *flags |= PARAM_LIMIT;
+ return true;
+
+ case '^': /* --hashlimit-above == !--hashlimit-below */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-above",
+ *flags & PARAM_LIMIT);
+ if (!invert)
+ info->cfg.mode |= XT_HASHLIMIT_INVERT;
+ if (!parse_rate(optarg, &info->cfg.avg))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-above", optarg);
+ *flags |= PARAM_LIMIT;
+ return true;
+
+ case '$': /* --hashlimit-burst */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-burst",
+ *flags & PARAM_BURST);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-burst", optarg);
+ info->cfg.burst = num;
+ *flags |= PARAM_BURST;
+ return true;
+
+ case '&': /* --hashlimit-htable-size */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-size",
+ *flags & PARAM_SIZE);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-size", optarg);
+ info->cfg.size = num;
+ *flags |= PARAM_SIZE;
+ return true;
+
+ case '*': /* --hashlimit-htable-max */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-htable-max",
+ *flags & PARAM_MAX);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-max", optarg);
+ info->cfg.max = num;
+ *flags |= PARAM_MAX;
+ return true;
+
+ case '(': /* --hashlimit-htable-gcinterval */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
+ "--hashlimit-htable-gcinterval",
+ *flags & PARAM_GCINTERVAL);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-gcinterval", optarg);
+ /* FIXME: not HZ dependent!! */
+ info->cfg.gc_interval = num;
+ *flags |= PARAM_GCINTERVAL;
+ return true;
+
+ case ')': /* --hashlimit-htable-expire */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit",
+ "--hashlimit-htable-expire", *flags & PARAM_EXPIRE);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-htable-expire", optarg);
+ /* FIXME: not HZ dependent */
+ info->cfg.expire = num;
+ *flags |= PARAM_EXPIRE;
+ return true;
+
+ case '_':
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-mode",
+ *flags & PARAM_MODE);
+ if (parse_mode(&info->cfg.mode, optarg) < 0)
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-mode", optarg);
+ *flags |= PARAM_MODE;
+ return true;
+
+ case '"': /* --hashlimit-name */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-name",
+ *flags & PARAM_NAME);
+ if (strlen(optarg) == 0)
+ xtables_error(PARAMETER_PROBLEM, "Zero-length name?");
+ strncpy(info->name, optarg, sizeof(info->name));
+ info->name[sizeof(info->name)-1] = '\0';
+ *flags |= PARAM_NAME;
+ return true;
+
+ case '<': /* --hashlimit-srcmask */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-srcmask",
+ *flags & PARAM_SRCMASK);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-srcmask", optarg);
+ info->cfg.srcmask = num;
+ *flags |= PARAM_SRCMASK;
+ return true;
+
+ case '>': /* --hashlimit-dstmask */
+ xtables_param_act(XTF_ONLY_ONCE, "hashlimit", "--hashlimit-dstmask",
+ *flags & PARAM_DSTMASK);
+ if (!xtables_strtoui(optarg, NULL, &num, 0, maxmask))
+ xtables_param_act(XTF_BAD_VALUE, "hashlimit",
+ "--hashlimit-dstmask", optarg);
+ info->cfg.dstmask = num;
+ *flags |= PARAM_DSTMASK;
+ return true;
+ }
+ return false;
+}
+
+static int
+hashlimit_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return hashlimit_mt_parse((void *)(*match)->data,
+ flags, c, invert, 32);
+}
+
+static int
+hashlimit_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return hashlimit_mt_parse((void *)(*match)->data,
+ flags, c, invert, 128);
+}
+
+static void hashlimit_check(unsigned int flags)
+{
+ if (!(flags & PARAM_LIMIT))
+ xtables_error(PARAMETER_PROBLEM,
+ "You have to specify --hashlimit");
+ if (!(flags & PARAM_MODE))
+ xtables_error(PARAMETER_PROBLEM,
+ "You have to specify --hashlimit-mode");
+ if (!(flags & PARAM_NAME))
+ xtables_error(PARAMETER_PROBLEM,
+ "You have to specify --hashlimit-name");
+}
+
+static void hashlimit_mt_check(unsigned int flags)
+{
+ if (!(flags & PARAM_LIMIT))
+ xtables_error(PARAMETER_PROBLEM, "You have to specify "
+ "--hashlimit-upto or --hashlimit-above");
+ if (!(flags & PARAM_NAME))
+ xtables_error(PARAMETER_PROBLEM,
+ "You have to specify --hashlimit-name");
+}
+
+static const struct rates
+{
+ const char *name;
+ u_int32_t mult;
+} rates[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
+ { "hour", XT_HASHLIMIT_SCALE*60*60 },
+ { "min", XT_HASHLIMIT_SCALE*60 },
+ { "sec", XT_HASHLIMIT_SCALE } };
+
+static void print_rate(u_int32_t period)
+{
+ unsigned int i;
+
+ for (i = 1; i < ARRAY_SIZE(rates); ++i)
+ if (period > rates[i].mult
+ || rates[i].mult/period < rates[i].mult%period)
+ break;
+
+ printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
+}
+
+static void print_mode(unsigned int mode, char separator)
+{
+ bool prevmode = false;
+
+ if (mode & XT_HASHLIMIT_HASH_SIP) {
+ fputs("srcip", stdout);
+ prevmode = 1;
+ }
+ if (mode & XT_HASHLIMIT_HASH_SPT) {
+ if (prevmode)
+ putchar(separator);
+ fputs("srcport", stdout);
+ prevmode = 1;
+ }
+ if (mode & XT_HASHLIMIT_HASH_DIP) {
+ if (prevmode)
+ putchar(separator);
+ fputs("dstip", stdout);
+ prevmode = 1;
+ }
+ if (mode & XT_HASHLIMIT_HASH_DPT) {
+ if (prevmode)
+ putchar(separator);
+ fputs("dstport", stdout);
+ }
+ putchar(' ');
+}
+
+static void hashlimit_print(const void *ip,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_hashlimit_info *r = (const void *)match->data;
+ fputs("limit: avg ", stdout); print_rate(r->cfg.avg);
+ printf("burst %u ", r->cfg.burst);
+ fputs("mode ", stdout);
+ print_mode(r->cfg.mode, '-');
+ if (r->cfg.size)
+ printf("htable-size %u ", r->cfg.size);
+ if (r->cfg.max)
+ printf("htable-max %u ", r->cfg.max);
+ if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+ printf("htable-gcinterval %u ", r->cfg.gc_interval);
+ if (r->cfg.expire != XT_HASHLIMIT_EXPIRE)
+ printf("htable-expire %u ", r->cfg.expire);
+}
+
+static void
+hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask)
+{
+ if (info->cfg.mode & XT_HASHLIMIT_INVERT)
+ fputs("limit: above ", stdout);
+ else
+ fputs("limit: up to ", stdout);
+ print_rate(info->cfg.avg);
+ printf("burst %u ", info->cfg.burst);
+ if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
+ XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
+ fputs("mode ", stdout);
+ print_mode(info->cfg.mode, '-');
+ }
+ if (info->cfg.size != 0)
+ printf("htable-size %u ", info->cfg.size);
+ if (info->cfg.max != 0)
+ printf("htable-max %u ", info->cfg.max);
+ if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+ printf("htable-gcinterval %u ", info->cfg.gc_interval);
+ if (info->cfg.expire != XT_HASHLIMIT_EXPIRE)
+ printf("htable-expire %u ", info->cfg.expire);
+
+ if (info->cfg.srcmask != dmask)
+ printf("srcmask %u ", info->cfg.srcmask);
+ if (info->cfg.dstmask != dmask)
+ printf("dstmask %u ", info->cfg.dstmask);
+}
+
+static void
+hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_print(info, 32);
+}
+
+static void
+hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_print(info, 128);
+}
+
+static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_info *r = (const void *)match->data;
+
+ fputs("--hashlimit ", stdout); print_rate(r->cfg.avg);
+ if (r->cfg.burst != XT_HASHLIMIT_BURST)
+ printf("--hashlimit-burst %u ", r->cfg.burst);
+
+ fputs("--hashlimit-mode ", stdout);
+ print_mode(r->cfg.mode, ',');
+
+ printf("--hashlimit-name %s ", r->name);
+
+ if (r->cfg.size)
+ printf("--hashlimit-htable-size %u ", r->cfg.size);
+ if (r->cfg.max)
+ printf("--hashlimit-htable-max %u ", r->cfg.max);
+ if (r->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+ printf("--hashlimit-htable-gcinterval %u ", r->cfg.gc_interval);
+ if (r->cfg.expire != XT_HASHLIMIT_EXPIRE)
+ printf("--hashlimit-htable-expire %u ", r->cfg.expire);
+}
+
+static void
+hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask)
+{
+ if (info->cfg.mode & XT_HASHLIMIT_INVERT)
+ fputs("--hashlimit-above ", stdout);
+ else
+ fputs("--hashlimit-upto ", stdout);
+ print_rate(info->cfg.avg);
+ if (info->cfg.burst != XT_HASHLIMIT_BURST)
+ printf("--hashlimit-burst %u ", info->cfg.burst);
+
+ if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
+ XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
+ fputs("--hashlimit-mode ", stdout);
+ print_mode(info->cfg.mode, ',');
+ }
+
+ printf("--hashlimit-name %s ", info->name);
+
+ if (info->cfg.size != 0)
+ printf("--hashlimit-htable-size %u ", info->cfg.size);
+ if (info->cfg.max != 0)
+ printf("--hashlimit-htable-max %u ", info->cfg.max);
+ if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
+ printf("--hashlimit-htable-gcinterval %u ", info->cfg.gc_interval);
+ if (info->cfg.expire != XT_HASHLIMIT_EXPIRE)
+ printf("--hashlimit-htable-expire %u ", info->cfg.expire);
+
+ if (info->cfg.srcmask != dmask)
+ printf("--hashlimit-srcmask %u ", info->cfg.srcmask);
+ if (info->cfg.dstmask != dmask)
+ printf("--hashlimit-dstmask %u ", info->cfg.dstmask);
+}
+
+static void
+hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_save(info, 32);
+}
+
+static void
+hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
+
+ hashlimit_mt_save(info, 128);
+}
+
+static struct xtables_match hashlimit_mt_reg[] = {
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "hashlimit",
+ .version = XTABLES_VERSION,
+ .revision = 0,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_info)),
+ .userspacesize = offsetof(struct xt_hashlimit_info, hinfo),
+ .help = hashlimit_help,
+ .init = hashlimit_init,
+ .parse = hashlimit_parse,
+ .final_check = hashlimit_check,
+ .print = hashlimit_print,
+ .save = hashlimit_save,
+ .extra_opts = hashlimit_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "hashlimit",
+ .revision = 1,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
+ .help = hashlimit_mt_help,
+ .init = hashlimit_mt4_init,
+ .parse = hashlimit_mt4_parse,
+ .final_check = hashlimit_mt_check,
+ .print = hashlimit_mt4_print,
+ .save = hashlimit_mt4_save,
+ .extra_opts = hashlimit_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "hashlimit",
+ .revision = 1,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
+ .userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
+ .help = hashlimit_mt_help,
+ .init = hashlimit_mt6_init,
+ .parse = hashlimit_mt6_parse,
+ .final_check = hashlimit_mt_check,
+ .print = hashlimit_mt6_print,
+ .save = hashlimit_mt6_save,
+ .extra_opts = hashlimit_mt_opts,
+ },
+};
+
+void libxt_hashlimit_init(void)
+{
+ xtables_register_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
+}
diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man
new file mode 100644
index 0000000..9820a92
--- /dev/null
+++ b/extensions/libxt_hashlimit.man
@@ -0,0 +1,59 @@
+\fBhashlimit\fR uses hash buckets to express a rate limiting match (like the
+\fBlimit\fR match) for a group of connections using a \fBsingle\fR iptables
+rule. Grouping can be done per-hostgroup (source and/or destination address)
+and/or per-port. It gives you the ability to express "\fIN\fR packets per time
+quantum per group":
+.TP
+matching on source host
+"1000 packets per second for every host in 192.168.0.0/16"
+.TP
+matching on source prot
+"100 packets per second for every service of 192.168.1.1"
+.TP
+matching on subnet
+"10000 packets per minute for every /28 subnet in 10.0.0.0/8"
+.PP
+A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and
+\fB\-\-hashlimit\-name\fP are required.
+.TP
+\fB\-\-hashlimit\-upto\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Match if the rate is below or equal to \fIamount\fR/quantum. It is specified as
+a number, with an optional time quantum suffix; the default is 3/hour.
+.TP
+\fB\-\-hashlimit\-above\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Match if the rate is above \fIamount\fR/quantum.
+.TP
+\fB\-\-hashlimit\-burst\fP \fIamount\fP
+Maximum initial number of packets to match: this number gets recharged by one
+every time the limit specified above is not reached, up to this number; the
+default is 5.
+.TP
+\fB\-\-hashlimit\-mode\fP {\fBsrcip\fP|\fBsrcport\fP|\fBdstip\fP|\fBdstport\fP}\fB,\fP...
+A comma-separated list of objects to take into consideration. If no
+\-\-hashlimit\-mode option is given, hashlimit acts like limit, but at the
+expensive of doing the hash housekeeping.
+.TP
+\fB\-\-hashlimit\-srcmask\fP \fIprefix\fP
+When \-\-hashlimit\-mode srcip is used, all source addresses encountered will be
+grouped according to the given prefix length and the so-created subnet will be
+subject to hashlimit. \fIprefix\fR must be between (inclusive) 0 and 32. Note
+that \-\-hashlimit\-srcmask 0 is basically doing the same thing as not specifying
+srcip for \-\-hashlimit\-mode, but is technically more expensive.
+.TP
+\fB\-\-hashlimit\-dstmask\fP \fIprefix\fP
+Like \-\-hashlimit\-srcmask, but for destination addresses.
+.TP
+\fB\-\-hashlimit\-name\fP \fIfoo\fP
+The name for the /proc/net/ipt_hashlimit/foo entry.
+.TP
+\fB\-\-hashlimit\-htable\-size\fP \fIbuckets\fP
+The number of buckets of the hash table
+.TP
+\fB\-\-hashlimit\-htable\-max\fP \fIentries\fP
+Maximum entries in the hash.
+.TP
+\fB\-\-hashlimit\-htable\-expire\fP \fImsec\fP
+After how many milliseconds do hash entries expire.
+.TP
+\fB\-\-hashlimit\-htable\-gcinterval\fP \fImsec\fP
+How many milliseconds between garbage collection intervals.
diff --git a/extensions/libxt_helper.c b/extensions/libxt_helper.c
new file mode 100644
index 0000000..cb087c2
--- /dev/null
+++ b/extensions/libxt_helper.c
@@ -0,0 +1,87 @@
+/* Shared library add-on to iptables to add related packet matching support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_helper.h>
+
+static void helper_help(void)
+{
+ printf(
+"helper match options:\n"
+"[!] --helper string Match helper identified by string\n");
+}
+
+static const struct option helper_opts[] = {
+ { "helper", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static int
+helper_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_helper_info *info = (struct xt_helper_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "helper match: Only use --helper ONCE!");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ strncpy(info->name, optarg, 29);
+ info->name[29] = '\0';
+ if (invert)
+ info->invert = 1;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void helper_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "helper match: You must specify `--helper'");
+}
+
+static void
+helper_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_helper_info *info = (const void *)match->data;
+
+ printf("helper match %s\"%s\" ", info->invert ? "! " : "", info->name);
+}
+
+static void helper_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_helper_info *info = (const void *)match->data;
+
+ printf("%s--helper ",info->invert ? "! " : "");
+ xtables_save_string(info->name);
+}
+
+static struct xtables_match helper_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "helper",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_helper_info)),
+ .help = helper_help,
+ .parse = helper_parse,
+ .final_check = helper_check,
+ .print = helper_print,
+ .save = helper_save,
+ .extra_opts = helper_opts,
+};
+
+void libxt_helper_init(void)
+{
+ xtables_register_match(&helper_match);
+}
diff --git a/extensions/libipt_helper.man b/extensions/libxt_helper.man
index c3221ad..772b135 100644
--- a/extensions/libipt_helper.man
+++ b/extensions/libxt_helper.man
@@ -1,11 +1,11 @@
This module matches packets related to a specific conntrack-helper.
.TP
-.BI "--helper " "string"
+[\fB!\fP] \fB\-\-helper\fP \fIstring\fP
Matches packets related to the specified conntrack-helper.
.RS
.PP
string can be "ftp" for packets related to a ftp-session on default port.
-For other ports append -portnr to the value, ie. "ftp-2121".
+For other ports append \-portnr to the value, ie. "ftp\-2121".
.PP
Same rules apply for other conntrack-helpers.
.RE
diff --git a/extensions/libxt_iprange.c b/extensions/libxt_iprange.c
new file mode 100644
index 0000000..5c0e22b
--- /dev/null
+++ b/extensions/libxt_iprange.c
@@ -0,0 +1,385 @@
+/* Shared library add-on to iptables to add IP range matching support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <netinet/in.h>
+#include <xtables.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/xt_iprange.h>
+
+struct ipt_iprange {
+ /* Inclusive: network order. */
+ __be32 min_ip, max_ip;
+};
+
+struct ipt_iprange_info {
+ struct ipt_iprange src;
+ struct ipt_iprange dst;
+
+ /* Flags from above */
+ u_int8_t flags;
+};
+
+enum {
+ F_SRCIP = 1 << 0,
+ F_DSTIP = 1 << 1,
+};
+
+static void iprange_mt_help(void)
+{
+ printf(
+"iprange match options:\n"
+"[!] --src-range ip[-ip] Match source IP in the specified range\n"
+"[!] --dst-range ip[-ip] Match destination IP in the specified range\n");
+}
+
+static const struct option iprange_mt_opts[] = {
+ {.name = "src-range", .has_arg = true, .val = '1'},
+ {.name = "dst-range", .has_arg = true, .val = '2'},
+ { .name = NULL }
+};
+
+static void
+iprange_parse_spec(const char *from, const char *to, union nf_inet_addr *range,
+ uint8_t family, const char *optname)
+{
+ const char *spec[2] = {from, to};
+ struct in6_addr *ia6;
+ struct in_addr *ia4;
+ unsigned int i;
+
+ memset(range, 0, sizeof(union nf_inet_addr) * 2);
+
+ if (family == NFPROTO_IPV6) {
+ for (i = 0; i < ARRAY_SIZE(spec); ++i) {
+ ia6 = xtables_numeric_to_ip6addr(spec[i]);
+ if (ia6 == NULL)
+ xtables_param_act(XTF_BAD_VALUE, "iprange",
+ optname, spec[i]);
+ range[i].in6 = *ia6;
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(spec); ++i) {
+ ia4 = xtables_numeric_to_ipaddr(spec[i]);
+ if (ia4 == NULL)
+ xtables_param_act(XTF_BAD_VALUE, "iprange",
+ optname, spec[i]);
+ range[i].in = *ia4;
+ }
+ }
+}
+
+static void iprange_parse_range(char *arg, union nf_inet_addr *range,
+ u_int8_t family, const char *optname)
+{
+ char *dash;
+
+ dash = strchr(arg, '-');
+ if (dash == NULL) {
+ iprange_parse_spec(arg, arg, range, family, optname);
+ return;
+ }
+
+ *dash = '\0';
+ iprange_parse_spec(arg, dash + 1, range, family, optname);
+ if (memcmp(&range[0], &range[1], sizeof(*range)) > 0)
+ fprintf(stderr, "xt_iprange: range %s-%s is reversed and "
+ "will never match\n", arg, dash + 1);
+}
+
+static int iprange_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
+ union nf_inet_addr range[2];
+
+ switch (c) {
+ case '1':
+ if (*flags & IPRANGE_SRC)
+ xtables_error(PARAMETER_PROBLEM,
+ "iprange match: Only use --src-range ONCE!");
+ *flags |= IPRANGE_SRC;
+
+ info->flags |= IPRANGE_SRC;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ info->flags |= IPRANGE_SRC_INV;
+ iprange_parse_range(optarg, range, NFPROTO_IPV4, "--src-range");
+
+ break;
+
+ case '2':
+ if (*flags & IPRANGE_DST)
+ xtables_error(PARAMETER_PROBLEM,
+ "iprange match: Only use --dst-range ONCE!");
+ *flags |= IPRANGE_DST;
+
+ info->flags |= IPRANGE_DST;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ info->flags |= IPRANGE_DST_INV;
+
+ iprange_parse_range(optarg, range, NFPROTO_IPV4, "--src-range");
+
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static int
+iprange_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_iprange_mtinfo *info = (void *)(*match)->data;
+
+ switch (c) {
+ case '1': /* --src-range */
+ iprange_parse_range(optarg, &info->src_min, NFPROTO_IPV4,
+ "--src-range");
+ info->flags |= IPRANGE_SRC;
+ if (invert)
+ info->flags |= IPRANGE_SRC_INV;
+ *flags |= F_SRCIP;
+ return true;
+
+ case '2': /* --dst-range */
+ iprange_parse_range(optarg, &info->dst_min, NFPROTO_IPV4,
+ "--dst-range");
+ info->flags |= IPRANGE_DST;
+ if (invert)
+ info->flags |= IPRANGE_DST_INV;
+ *flags |= F_DSTIP;
+ return true;
+ }
+ return false;
+}
+
+static int
+iprange_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_iprange_mtinfo *info = (void *)(*match)->data;
+
+ switch (c) {
+ case '1': /* --src-range */
+ iprange_parse_range(optarg, &info->src_min, NFPROTO_IPV6,
+ "--src-range");
+ info->flags |= IPRANGE_SRC;
+ if (invert)
+ info->flags |= IPRANGE_SRC_INV;
+ *flags |= F_SRCIP;
+ return true;
+
+ case '2': /* --dst-range */
+ iprange_parse_range(optarg, &info->dst_min, NFPROTO_IPV6,
+ "--dst-range");
+ info->flags |= IPRANGE_DST;
+ if (invert)
+ info->flags |= IPRANGE_DST_INV;
+ *flags |= F_DSTIP;
+ return true;
+ }
+ return false;
+}
+
+static void iprange_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "iprange match: You must specify `--src-range' or `--dst-range'");
+}
+
+static void
+print_iprange(const struct ipt_iprange *range)
+{
+ const unsigned char *byte_min, *byte_max;
+
+ byte_min = (const unsigned char *)&range->min_ip;
+ byte_max = (const unsigned char *)&range->max_ip;
+ printf("%u.%u.%u.%u-%u.%u.%u.%u ",
+ byte_min[0], byte_min[1], byte_min[2], byte_min[3],
+ byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
+}
+
+static void iprange_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_iprange_info *info = (const void *)match->data;
+
+ if (info->flags & IPRANGE_SRC) {
+ printf("source IP range ");
+ if (info->flags & IPRANGE_SRC_INV)
+ printf("! ");
+ print_iprange(&info->src);
+ }
+ if (info->flags & IPRANGE_DST) {
+ printf("destination IP range ");
+ if (info->flags & IPRANGE_DST_INV)
+ printf("! ");
+ print_iprange(&info->dst);
+ }
+}
+
+static void
+iprange_mt4_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_iprange_mtinfo *info = (const void *)match->data;
+
+ if (info->flags & IPRANGE_SRC) {
+ printf("source IP range ");
+ if (info->flags & IPRANGE_SRC_INV)
+ printf("! ");
+ /*
+ * ipaddr_to_numeric() uses a static buffer, so cannot
+ * combine the printf() calls.
+ */
+ printf("%s", xtables_ipaddr_to_numeric(&info->src_min.in));
+ printf("-%s ", xtables_ipaddr_to_numeric(&info->src_max.in));
+ }
+ if (info->flags & IPRANGE_DST) {
+ printf("destination IP range ");
+ if (info->flags & IPRANGE_DST_INV)
+ printf("! ");
+ printf("%s", xtables_ipaddr_to_numeric(&info->dst_min.in));
+ printf("-%s ", xtables_ipaddr_to_numeric(&info->dst_max.in));
+ }
+}
+
+static void
+iprange_mt6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_iprange_mtinfo *info = (const void *)match->data;
+
+ if (info->flags & IPRANGE_SRC) {
+ printf("source IP range ");
+ if (info->flags & IPRANGE_SRC_INV)
+ printf("! ");
+ /*
+ * ipaddr_to_numeric() uses a static buffer, so cannot
+ * combine the printf() calls.
+ */
+ printf("%s", xtables_ip6addr_to_numeric(&info->src_min.in6));
+ printf("-%s ", xtables_ip6addr_to_numeric(&info->src_max.in6));
+ }
+ if (info->flags & IPRANGE_DST) {
+ printf("destination IP range ");
+ if (info->flags & IPRANGE_DST_INV)
+ printf("! ");
+ printf("%s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
+ printf("-%s ", xtables_ip6addr_to_numeric(&info->dst_max.in6));
+ }
+}
+
+static void iprange_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ipt_iprange_info *info = (const void *)match->data;
+
+ if (info->flags & IPRANGE_SRC) {
+ if (info->flags & IPRANGE_SRC_INV)
+ printf("! ");
+ printf("--src-range ");
+ print_iprange(&info->src);
+ if (info->flags & IPRANGE_DST)
+ fputc(' ', stdout);
+ }
+ if (info->flags & IPRANGE_DST) {
+ if (info->flags & IPRANGE_DST_INV)
+ printf("! ");
+ printf("--dst-range ");
+ print_iprange(&info->dst);
+ }
+}
+
+static void iprange_mt4_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_iprange_mtinfo *info = (const void *)match->data;
+
+ if (info->flags & IPRANGE_SRC) {
+ if (info->flags & IPRANGE_SRC_INV)
+ printf("! ");
+ printf("--src-range %s", xtables_ipaddr_to_numeric(&info->src_min.in));
+ printf("-%s ", xtables_ipaddr_to_numeric(&info->src_max.in));
+ }
+ if (info->flags & IPRANGE_DST) {
+ if (info->flags & IPRANGE_DST_INV)
+ printf("! ");
+ printf("--dst-range %s", xtables_ipaddr_to_numeric(&info->dst_min.in));
+ printf("-%s ", xtables_ipaddr_to_numeric(&info->dst_max.in));
+ }
+}
+
+static void iprange_mt6_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_iprange_mtinfo *info = (const void *)match->data;
+
+ if (info->flags & IPRANGE_SRC) {
+ if (info->flags & IPRANGE_SRC_INV)
+ printf("! ");
+ printf("--src-range %s", xtables_ip6addr_to_numeric(&info->src_min.in6));
+ printf("-%s ", xtables_ip6addr_to_numeric(&info->src_max.in6));
+ }
+ if (info->flags & IPRANGE_DST) {
+ if (info->flags & IPRANGE_DST_INV)
+ printf("! ");
+ printf("--dst-range %s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
+ printf("-%s ", xtables_ip6addr_to_numeric(&info->dst_max.in6));
+ }
+}
+
+static struct xtables_match iprange_mt_reg[] = {
+ {
+ .version = XTABLES_VERSION,
+ .name = "iprange",
+ .revision = 0,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_iprange_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_iprange_info)),
+ .help = iprange_mt_help,
+ .parse = iprange_parse,
+ .final_check = iprange_mt_check,
+ .print = iprange_print,
+ .save = iprange_save,
+ .extra_opts = iprange_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "iprange",
+ .revision = 1,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
+ .help = iprange_mt_help,
+ .parse = iprange_mt4_parse,
+ .final_check = iprange_mt_check,
+ .print = iprange_mt4_print,
+ .save = iprange_mt4_save,
+ .extra_opts = iprange_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "iprange",
+ .revision = 1,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
+ .help = iprange_mt_help,
+ .parse = iprange_mt6_parse,
+ .final_check = iprange_mt_check,
+ .print = iprange_mt6_print,
+ .save = iprange_mt6_save,
+ .extra_opts = iprange_mt_opts,
+ },
+};
+
+void libxt_iprange_init(void)
+{
+ xtables_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
+}
diff --git a/extensions/libxt_iprange.man b/extensions/libxt_iprange.man
new file mode 100644
index 0000000..9f65de4
--- /dev/null
+++ b/extensions/libxt_iprange.man
@@ -0,0 +1,7 @@
+This matches on a given arbitrary range of IP addresses.
+.TP
+[\fB!\fR] \fB\-\-src\-range\fP \fIfrom\fP[\fB\-\fP\fIto\fP]
+Match source IP in the specified range.
+.TP
+[\fB!\fR] \fB\-\-dst\-range\fP \fIfrom\fP[\fB\-\fP\fIto\fP]
+Match destination IP in the specified range.
diff --git a/extensions/libxt_length.c b/extensions/libxt_length.c
new file mode 100644
index 0000000..627245b
--- /dev/null
+++ b/extensions/libxt_length.c
@@ -0,0 +1,133 @@
+/* Shared library add-on to iptables to add packet length matching support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_length.h>
+
+static void length_help(void)
+{
+ printf(
+"length match options:\n"
+"[!] --length length[:length] Match packet length against value or range\n"
+" of values (inclusive)\n");
+}
+
+static const struct option length_opts[] = {
+ { "length", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static u_int16_t
+parse_length(const char *s)
+{
+ unsigned int len;
+
+ if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM, "length invalid: \"%s\"\n", s);
+ else
+ return len;
+}
+
+/* If a single value is provided, min and max are both set to the value */
+static void
+parse_lengths(const char *s, struct xt_length_info *info)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(s);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ info->min = info->max = parse_length(buffer);
+ else {
+ *cp = '\0';
+ cp++;
+
+ info->min = buffer[0] ? parse_length(buffer) : 0;
+ info->max = cp[0] ? parse_length(cp) : 0xFFFF;
+ }
+ free(buffer);
+
+ if (info->min > info->max)
+ xtables_error(PARAMETER_PROBLEM,
+ "length min. range value `%u' greater than max. "
+ "range value `%u'", info->min, info->max);
+
+}
+
+static int
+length_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_length_info *info = (struct xt_length_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "length: `--length' may only be "
+ "specified once");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_lengths(optarg, info);
+ if (invert)
+ info->invert = 1;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void length_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "length: You must specify `--length'");
+}
+
+static void
+length_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_length_info *info = (void *)match->data;
+
+ printf("length %s", info->invert ? "!" : "");
+ if (info->min == info->max)
+ printf("%u ", info->min);
+ else
+ printf("%u:%u ", info->min, info->max);
+}
+
+static void length_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_length_info *info = (void *)match->data;
+
+ printf("%s--length ", info->invert ? "! " : "");
+ if (info->min == info->max)
+ printf("%u ", info->min);
+ else
+ printf("%u:%u ", info->min, info->max);
+}
+
+static struct xtables_match length_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "length",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_length_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_length_info)),
+ .help = length_help,
+ .parse = length_parse,
+ .final_check = length_check,
+ .print = length_print,
+ .save = length_save,
+ .extra_opts = length_opts,
+};
+
+void libxt_length_init(void)
+{
+ xtables_register_match(&length_match);
+}
diff --git a/extensions/libxt_length.man b/extensions/libxt_length.man
new file mode 100644
index 0000000..07b6ea6
--- /dev/null
+++ b/extensions/libxt_length.man
@@ -0,0 +1,5 @@
+This module matches the length of the layer-3 payload (e.g. layer-4 packet)
+of a packet against a specific value
+or range of values.
+.TP
+[\fB!\fP] \fB\-\-length\fP \fIlength\fP[\fB:\fP\fIlength\fP]
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
new file mode 100644
index 0000000..74c8b42
--- /dev/null
+++ b/extensions/libxt_limit.c
@@ -0,0 +1,177 @@
+/* Shared library add-on to iptables to add limit support.
+ *
+ * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
+ * Hervé Eychenne <rv@wallfire.org>
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <stddef.h>
+#include <linux/netfilter/x_tables.h>
+/* For 64bit kernel / 32bit userspace */
+#include <linux/netfilter/xt_limit.h>
+
+#define XT_LIMIT_AVG "3/hour"
+#define XT_LIMIT_BURST 5
+
+static void limit_help(void)
+{
+ printf(
+"limit match options:\n"
+"--limit avg max average match rate: default "XT_LIMIT_AVG"\n"
+" [Packets per second unless followed by \n"
+" /sec /minute /hour /day postfixes]\n"
+"--limit-burst number number to match in a burst, default %u\n",
+XT_LIMIT_BURST);
+}
+
+static const struct option limit_opts[] = {
+ { "limit", 1, NULL, '%' },
+ { "limit-burst", 1, NULL, '$' },
+ { .name = NULL }
+};
+
+static
+int parse_rate(const char *rate, u_int32_t *val)
+{
+ const char *delim;
+ u_int32_t r;
+ u_int32_t mult = 1; /* Seconds by default. */
+
+ delim = strchr(rate, '/');
+ if (delim) {
+ if (strlen(delim+1) == 0)
+ return 0;
+
+ if (strncasecmp(delim+1, "second", strlen(delim+1)) == 0)
+ mult = 1;
+ else if (strncasecmp(delim+1, "minute", strlen(delim+1)) == 0)
+ mult = 60;
+ else if (strncasecmp(delim+1, "hour", strlen(delim+1)) == 0)
+ mult = 60*60;
+ else if (strncasecmp(delim+1, "day", strlen(delim+1)) == 0)
+ mult = 24*60*60;
+ else
+ return 0;
+ }
+ r = atoi(rate);
+ if (!r)
+ return 0;
+
+ /* This would get mapped to infinite (1/day is minimum they
+ can specify, so we're ok at that end). */
+ if (r / mult > XT_LIMIT_SCALE)
+ xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
+
+ *val = XT_LIMIT_SCALE * mult / r;
+ return 1;
+}
+
+static void limit_init(struct xt_entry_match *m)
+{
+ struct xt_rateinfo *r = (struct xt_rateinfo *)m->data;
+
+ parse_rate(XT_LIMIT_AVG, &r->avg);
+ r->burst = XT_LIMIT_BURST;
+
+}
+
+/* FIXME: handle overflow:
+ if (r->avg*r->burst/r->burst != r->avg)
+ xtables_error(PARAMETER_PROBLEM,
+ "Sorry: burst too large for that avg rate.\n");
+*/
+
+static int
+limit_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_rateinfo *r = (struct xt_rateinfo *)(*match)->data;
+ unsigned int num;
+
+ switch(c) {
+ case '%':
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!parse_rate(optarg, &r->avg))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad rate `%s'", optarg);
+ break;
+
+ case '$':
+ if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) break;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, 10000))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad --limit-burst `%s'", optarg);
+ r->burst = num;
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "limit does not support invert");
+
+ return 1;
+}
+
+static const struct rates
+{
+ const char *name;
+ u_int32_t mult;
+} rates[] = { { "day", XT_LIMIT_SCALE*24*60*60 },
+ { "hour", XT_LIMIT_SCALE*60*60 },
+ { "min", XT_LIMIT_SCALE*60 },
+ { "sec", XT_LIMIT_SCALE } };
+
+static void print_rate(u_int32_t period)
+{
+ unsigned int i;
+
+ for (i = 1; i < ARRAY_SIZE(rates); ++i)
+ if (period > rates[i].mult
+ || rates[i].mult/period < rates[i].mult%period)
+ break;
+
+ printf("%u/%s ", rates[i-1].mult / period, rates[i-1].name);
+}
+
+static void
+limit_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_rateinfo *r = (const void *)match->data;
+ printf("limit: avg "); print_rate(r->avg);
+ printf("burst %u ", r->burst);
+}
+
+static void limit_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_rateinfo *r = (const void *)match->data;
+
+ printf("--limit "); print_rate(r->avg);
+ if (r->burst != XT_LIMIT_BURST)
+ printf("--limit-burst %u ", r->burst);
+}
+
+static struct xtables_match limit_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "limit",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_rateinfo)),
+ .userspacesize = offsetof(struct xt_rateinfo, prev),
+ .help = limit_help,
+ .init = limit_init,
+ .parse = limit_parse,
+ .print = limit_print,
+ .save = limit_save,
+ .extra_opts = limit_opts,
+};
+
+void libxt_limit_init(void)
+{
+ xtables_register_match(&limit_match);
+}
diff --git a/extensions/libipt_limit.man b/extensions/libxt_limit.man
index 84b63d4..9f51ce3 100644
--- a/extensions/libipt_limit.man
+++ b/extensions/libxt_limit.man
@@ -4,12 +4,12 @@ A rule using this extension will match until this limit is reached
.B LOG
target to give limited logging, for example.
.TP
-.BI "--limit " "rate"
+\fB\-\-limit\fP \fIrate\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
Maximum average matching rate: specified as a number, with an optional
`/second', `/minute', `/hour', or `/day' suffix; the default is
3/hour.
.TP
-.BI "--limit-burst " "number"
+\fB\-\-limit\-burst\fP \fInumber\fP
Maximum initial number of packets to match: this number gets
recharged by one every time the limit specified above is not reached,
up to this number; the default is 5.
diff --git a/extensions/libxt_mac.c b/extensions/libxt_mac.c
new file mode 100644
index 0000000..dd89b60
--- /dev/null
+++ b/extensions/libxt_mac.c
@@ -0,0 +1,131 @@
+/* Shared library add-on to iptables to add MAC address support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+#include <xtables.h>
+#include <linux/netfilter/xt_mac.h>
+
+static void mac_help(void)
+{
+ printf(
+"mac match options:\n"
+"[!] --mac-source XX:XX:XX:XX:XX:XX\n"
+" Match source MAC address\n");
+}
+
+static const struct option mac_opts[] = {
+ { "mac-source", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static void
+parse_mac(const char *mac, struct xt_mac_info *info)
+{
+ unsigned int i = 0;
+
+ if (strlen(mac) != ETH_ALEN*3-1)
+ xtables_error(PARAMETER_PROBLEM, "Bad mac address \"%s\"", mac);
+
+ for (i = 0; i < ETH_ALEN; i++) {
+ long number;
+ char *end;
+
+ number = strtol(mac + i*3, &end, 16);
+
+ if (end == mac + i*3 + 2
+ && number >= 0
+ && number <= 255)
+ info->srcaddr[i] = number;
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "Bad mac address `%s'", mac);
+ }
+}
+
+static int
+mac_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_mac_info *macinfo = (struct xt_mac_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_mac(optarg, macinfo);
+ if (invert)
+ macinfo->invert = 1;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void print_mac(const unsigned char macaddress[ETH_ALEN])
+{
+ unsigned int i;
+
+ printf("%02X", macaddress[0]);
+ for (i = 1; i < ETH_ALEN; i++)
+ printf(":%02X", macaddress[i]);
+ printf(" ");
+}
+
+static void mac_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "You must specify `--mac-source'");
+}
+
+static void
+mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_mac_info *info = (void *)match->data;
+ printf("MAC ");
+
+ if (info->invert)
+ printf("! ");
+
+ print_mac(info->srcaddr);
+}
+
+static void mac_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_mac_info *info = (void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+
+ printf("--mac-source ");
+ print_mac(info->srcaddr);
+}
+
+static struct xtables_match mac_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "mac",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_mac_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mac_info)),
+ .help = mac_help,
+ .parse = mac_parse,
+ .final_check = mac_check,
+ .print = mac_print,
+ .save = mac_save,
+ .extra_opts = mac_opts,
+};
+
+void libxt_mac_init(void)
+{
+ xtables_register_match(&mac_match);
+}
diff --git a/extensions/libip6t_mac.man b/extensions/libxt_mac.man
index 5321ca1..66072a2 100644
--- a/extensions/libip6t_mac.man
+++ b/extensions/libxt_mac.man
@@ -1,5 +1,5 @@
.TP
-.BR "--mac-source " "[!] \fIaddress\fP"
+[\fB!\fP] \fB\-\-mac\-source\fP \fIaddress\fP
Match source MAC address. It must be of the form XX:XX:XX:XX:XX:XX.
Note that this only makes sense for packets coming from an Ethernet device
and entering the
diff --git a/extensions/libxt_mark.c b/extensions/libxt_mark.c
new file mode 100644
index 0000000..9669cdf
--- /dev/null
+++ b/extensions/libxt_mark.c
@@ -0,0 +1,185 @@
+/* Shared library add-on to iptables to add NFMARK matching support. */
+#include <stdbool.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_mark.h>
+
+struct xt_mark_info {
+ unsigned long mark, mask;
+ u_int8_t invert;
+};
+
+enum {
+ F_MARK = 1 << 0,
+};
+
+static void mark_mt_help(void)
+{
+ printf(
+"mark match options:\n"
+"[!] --mark value[/mask] Match nfmark value with optional mask\n");
+}
+
+static const struct option mark_mt_opts[] = {
+ {.name = "mark", .has_arg = true, .val = '1'},
+ { .name = NULL }
+};
+
+static int mark_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_mark_mtinfo1 *info = (void *)(*match)->data;
+ unsigned int mark, mask = UINT32_MAX;
+ char *end;
+
+ switch (c) {
+ case '1': /* --mark */
+ xtables_param_act(XTF_ONLY_ONCE, "mark", "--mark", *flags & F_MARK);
+ if (!xtables_strtoui(optarg, &end, &mark, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
+ if (*end == '/')
+ if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "mark", "--mark", optarg);
+
+ if (invert)
+ info->invert = true;
+ info->mark = mark;
+ info->mask = mask;
+ *flags |= F_MARK;
+ return true;
+ }
+ return false;
+}
+
+static int
+mark_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_mark_info *markinfo = (struct xt_mark_info *)(*match)->data;
+
+ switch (c) {
+ char *end;
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ markinfo->mark = strtoul(optarg, &end, 0);
+ if (*end == '/') {
+ markinfo->mask = strtoul(end+1, &end, 0);
+ } else
+ markinfo->mask = 0xffffffff;
+ if (*end != '\0' || end == optarg)
+ xtables_error(PARAMETER_PROBLEM, "Bad MARK value \"%s\"", optarg);
+ if (invert)
+ markinfo->invert = 1;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void print_mark(unsigned int mark, unsigned int mask)
+{
+ if (mask != 0xffffffffU)
+ printf("0x%x/0x%x ", mark, mask);
+ else
+ printf("0x%x ", mark);
+}
+
+static void mark_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "mark match: The --mark option is required");
+}
+
+static void
+mark_mt_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_mark_mtinfo1 *info = (const void *)match->data;
+
+ printf("mark match ");
+ if (info->invert)
+ printf("!");
+ print_mark(info->mark, info->mask);
+}
+
+static void
+mark_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_mark_info *info = (const void *)match->data;
+
+ printf("MARK match ");
+
+ if (info->invert)
+ printf("!");
+
+ print_mark(info->mark, info->mask);
+}
+
+static void mark_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_mark_mtinfo1 *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+
+ printf("--mark ");
+ print_mark(info->mark, info->mask);
+}
+
+static void
+mark_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_mark_info *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+
+ printf("--mark ");
+ print_mark(info->mark, info->mask);
+}
+
+static struct xtables_match mark_mt_reg[] = {
+ {
+ .family = NFPROTO_UNSPEC,
+ .name = "mark",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_mark_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_info)),
+ .help = mark_mt_help,
+ .parse = mark_parse,
+ .final_check = mark_mt_check,
+ .print = mark_print,
+ .save = mark_save,
+ .extra_opts = mark_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "mark",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
+ .help = mark_mt_help,
+ .parse = mark_mt_parse,
+ .final_check = mark_mt_check,
+ .print = mark_mt_print,
+ .save = mark_mt_save,
+ .extra_opts = mark_mt_opts,
+ },
+};
+
+void libxt_mark_init(void)
+{
+ xtables_register_matches(mark_mt_reg, ARRAY_SIZE(mark_mt_reg));
+}
diff --git a/extensions/libip6t_mark.man b/extensions/libxt_mark.man
index a2a1395..264b17d 100644
--- a/extensions/libip6t_mark.man
+++ b/extensions/libxt_mark.man
@@ -3,7 +3,7 @@ This module matches the netfilter mark field associated with a packet
.B MARK
target below).
.TP
-.BR "--mark " "\fIvalue\fP[/\fImask\fP]"
+[\fB!\fP] \fB\-\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
Matches packets with the given unsigned mark value (if a \fImask\fP is
specified, this is logically ANDed with the \fImask\fP before the
comparison).
diff --git a/extensions/libxt_multiport.c b/extensions/libxt_multiport.c
new file mode 100644
index 0000000..4bf25f7
--- /dev/null
+++ b/extensions/libxt_multiport.c
@@ -0,0 +1,574 @@
+/* Shared library add-on to iptables to add multiple TCP port support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <libiptc/libiptc.h>
+#include <libiptc/libip6tc.h>
+#include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter/xt_multiport.h>
+
+/* Function which prints out usage message. */
+static void multiport_help(void)
+{
+ printf(
+"multiport match options:\n"
+" --source-ports port[,port,port...]\n"
+" --sports ...\n"
+" match source port(s)\n"
+" --destination-ports port[,port,port...]\n"
+" --dports ...\n"
+" match destination port(s)\n"
+" --ports port[,port,port]\n"
+" match both source and destination port(s)\n"
+" NOTE: this kernel does not support port ranges in multiport.\n");
+}
+
+static void multiport_help_v1(void)
+{
+ printf(
+"multiport match options:\n"
+"[!] --source-ports port[,port:port,port...]\n"
+" --sports ...\n"
+" match source port(s)\n"
+"[!] --destination-ports port[,port:port,port...]\n"
+" --dports ...\n"
+" match destination port(s)\n"
+"[!] --ports port[,port:port,port]\n"
+" match both source and destination port(s)\n");
+}
+
+static const struct option multiport_opts[] = {
+ { "source-ports", 1, NULL, '1' },
+ { "sports", 1, NULL, '1' }, /* synonym */
+ { "destination-ports", 1, NULL, '2' },
+ { "dports", 1, NULL, '2' }, /* synonym */
+ { "ports", 1, NULL, '3' },
+ { .name = NULL }
+};
+
+static char *
+proto_to_name(u_int8_t proto)
+{
+ switch (proto) {
+ case IPPROTO_TCP:
+ return "tcp";
+ case IPPROTO_UDP:
+ return "udp";
+ case IPPROTO_UDPLITE:
+ return "udplite";
+ case IPPROTO_SCTP:
+ return "sctp";
+ case IPPROTO_DCCP:
+ return "dccp";
+ default:
+ return NULL;
+ }
+}
+
+static unsigned int
+parse_multi_ports(const char *portstring, u_int16_t *ports, const char *proto)
+{
+ char *buffer, *cp, *next;
+ unsigned int i;
+
+ buffer = strdup(portstring);
+ if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
+
+ for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next,i++)
+ {
+ next=strchr(cp, ',');
+ if (next) *next++='\0';
+ ports[i] = xtables_parse_port(cp, proto);
+ }
+ if (cp) xtables_error(PARAMETER_PROBLEM, "too many ports specified");
+ free(buffer);
+ return i;
+}
+
+static void
+parse_multi_ports_v1(const char *portstring,
+ struct xt_multiport_v1 *multiinfo,
+ const char *proto)
+{
+ char *buffer, *cp, *next, *range;
+ unsigned int i;
+ u_int16_t m;
+
+ buffer = strdup(portstring);
+ if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
+
+ for (i=0; i<XT_MULTI_PORTS; i++)
+ multiinfo->pflags[i] = 0;
+
+ for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
+ next=strchr(cp, ',');
+ if (next) *next++='\0';
+ range = strchr(cp, ':');
+ if (range) {
+ if (i == XT_MULTI_PORTS-1)
+ xtables_error(PARAMETER_PROBLEM,
+ "too many ports specified");
+ *range++ = '\0';
+ }
+ multiinfo->ports[i] = xtables_parse_port(cp, proto);
+ if (range) {
+ multiinfo->pflags[i] = 1;
+ multiinfo->ports[++i] = xtables_parse_port(range, proto);
+ if (multiinfo->ports[i-1] >= multiinfo->ports[i])
+ xtables_error(PARAMETER_PROBLEM,
+ "invalid portrange specified");
+ m <<= 1;
+ }
+ }
+ multiinfo->count = i;
+ if (cp) xtables_error(PARAMETER_PROBLEM, "too many ports specified");
+ free(buffer);
+}
+
+static const char *
+check_proto(u_int16_t pnum, u_int8_t invflags)
+{
+ char *proto;
+
+ if (invflags & XT_INV_PROTO)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
+
+ if ((proto = proto_to_name(pnum)) != NULL)
+ return proto;
+ else if (!pnum)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiport needs `-p tcp', `-p udp', `-p udplite', "
+ "`-p sctp' or `-p dccp'");
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "multiport only works with TCP, UDP, UDPLITE, SCTP and DCCP");
+}
+
+/* Function which parses command options; returns true if it
+ ate an option */
+static int
+__multiport_parse(int c, char **argv, int invert, unsigned int *flags,
+ struct xt_entry_match **match, u_int16_t pnum,
+ u_int8_t invflags)
+{
+ const char *proto;
+ struct xt_multiport *multiinfo
+ = (struct xt_multiport *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ proto = check_proto(pnum, invflags);
+ multiinfo->count = parse_multi_ports(optarg,
+ multiinfo->ports, proto);
+ multiinfo->flags = XT_MULTIPORT_SOURCE;
+ break;
+
+ case '2':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ proto = check_proto(pnum, invflags);
+ multiinfo->count = parse_multi_ports(optarg,
+ multiinfo->ports, proto);
+ multiinfo->flags = XT_MULTIPORT_DESTINATION;
+ break;
+
+ case '3':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ proto = check_proto(pnum, invflags);
+ multiinfo->count = parse_multi_ports(optarg,
+ multiinfo->ports, proto);
+ multiinfo->flags = XT_MULTIPORT_EITHER;
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiport does not support invert");
+
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiport can only have one option");
+ *flags = 1;
+ return 1;
+}
+
+static int
+multiport_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_match **match)
+{
+ const struct ipt_entry *entry = e;
+ return __multiport_parse(c, argv, invert, flags, match,
+ entry->ip.proto, entry->ip.invflags);
+}
+
+static int
+multiport_parse6(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_match **match)
+{
+ const struct ip6t_entry *entry = e;
+ return __multiport_parse(c, argv, invert, flags, match,
+ entry->ipv6.proto, entry->ipv6.invflags);
+}
+
+static int
+__multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ struct xt_entry_match **match, u_int16_t pnum,
+ u_int8_t invflags)
+{
+ const char *proto;
+ struct xt_multiport_v1 *multiinfo
+ = (struct xt_multiport_v1 *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ proto = check_proto(pnum, invflags);
+ parse_multi_ports_v1(optarg, multiinfo, proto);
+ multiinfo->flags = XT_MULTIPORT_SOURCE;
+ break;
+
+ case '2':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ proto = check_proto(pnum, invflags);
+ parse_multi_ports_v1(optarg, multiinfo, proto);
+ multiinfo->flags = XT_MULTIPORT_DESTINATION;
+ break;
+
+ case '3':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ proto = check_proto(pnum, invflags);
+ parse_multi_ports_v1(optarg, multiinfo, proto);
+ multiinfo->flags = XT_MULTIPORT_EITHER;
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (invert)
+ multiinfo->invert = 1;
+
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "multiport can only have one option");
+ *flags = 1;
+ return 1;
+}
+
+static int
+multiport_parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_match **match)
+{
+ const struct ipt_entry *entry = e;
+ return __multiport_parse_v1(c, argv, invert, flags, match,
+ entry->ip.proto, entry->ip.invflags);
+}
+
+static int
+multiport_parse6_v1(int c, char **argv, int invert, unsigned int *flags,
+ const void *e, struct xt_entry_match **match)
+{
+ const struct ip6t_entry *entry = e;
+ return __multiport_parse_v1(c, argv, invert, flags, match,
+ entry->ipv6.proto, entry->ipv6.invflags);
+}
+
+/* Final check; must specify something. */
+static void multiport_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM, "multiport expection an option");
+}
+
+static char *
+port_to_service(int port, u_int8_t proto)
+{
+ struct servent *service;
+
+ if ((service = getservbyport(htons(port), proto_to_name(proto))))
+ return service->s_name;
+
+ return NULL;
+}
+
+static void
+print_port(u_int16_t port, u_int8_t protocol, int numeric)
+{
+ char *service;
+
+ if (numeric || (service = port_to_service(port, protocol)) == NULL)
+ printf("%u", port);
+ else
+ printf("%s", service);
+}
+
+/* Prints out the matchinfo. */
+static void
+__multiport_print(const struct xt_entry_match *match, int numeric,
+ u_int16_t proto)
+{
+ const struct xt_multiport *multiinfo
+ = (const struct xt_multiport *)match->data;
+ unsigned int i;
+
+ printf("multiport ");
+
+ switch (multiinfo->flags) {
+ case XT_MULTIPORT_SOURCE:
+ printf("sports ");
+ break;
+
+ case XT_MULTIPORT_DESTINATION:
+ printf("dports ");
+ break;
+
+ case XT_MULTIPORT_EITHER:
+ printf("ports ");
+ break;
+
+ default:
+ printf("ERROR ");
+ break;
+ }
+
+ for (i=0; i < multiinfo->count; i++) {
+ printf("%s", i ? "," : "");
+ print_port(multiinfo->ports[i], proto, numeric);
+ }
+ printf(" ");
+}
+
+static void multiport_print(const void *ip_void,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct ipt_ip *ip = ip_void;
+ __multiport_print(match, numeric, ip->proto);
+}
+
+static void multiport_print6(const void *ip_void,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct ip6t_ip6 *ip = ip_void;
+ __multiport_print(match, numeric, ip->proto);
+}
+
+static void __multiport_print_v1(const struct xt_entry_match *match,
+ int numeric, u_int16_t proto)
+{
+ const struct xt_multiport_v1 *multiinfo
+ = (const struct xt_multiport_v1 *)match->data;
+ unsigned int i;
+
+ printf("multiport ");
+
+ switch (multiinfo->flags) {
+ case XT_MULTIPORT_SOURCE:
+ printf("sports ");
+ break;
+
+ case XT_MULTIPORT_DESTINATION:
+ printf("dports ");
+ break;
+
+ case XT_MULTIPORT_EITHER:
+ printf("ports ");
+ break;
+
+ default:
+ printf("ERROR ");
+ break;
+ }
+
+ if (multiinfo->invert)
+ printf("! ");
+
+ for (i=0; i < multiinfo->count; i++) {
+ printf("%s", i ? "," : "");
+ print_port(multiinfo->ports[i], proto, numeric);
+ if (multiinfo->pflags[i]) {
+ printf(":");
+ print_port(multiinfo->ports[++i], proto, numeric);
+ }
+ }
+ printf(" ");
+}
+
+static void multiport_print_v1(const void *ip_void,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct ipt_ip *ip = ip_void;
+ __multiport_print_v1(match, numeric, ip->proto);
+}
+
+static void multiport_print6_v1(const void *ip_void,
+ const struct xt_entry_match *match, int numeric)
+{
+ const struct ip6t_ip6 *ip = ip_void;
+ __multiport_print_v1(match, numeric, ip->proto);
+}
+
+/* Saves the union ipt_matchinfo in parsable form to stdout. */
+static void __multiport_save(const struct xt_entry_match *match,
+ u_int16_t proto)
+{
+ const struct xt_multiport *multiinfo
+ = (const struct xt_multiport *)match->data;
+ unsigned int i;
+
+ switch (multiinfo->flags) {
+ case XT_MULTIPORT_SOURCE:
+ printf("--sports ");
+ break;
+
+ case XT_MULTIPORT_DESTINATION:
+ printf("--dports ");
+ break;
+
+ case XT_MULTIPORT_EITHER:
+ printf("--ports ");
+ break;
+ }
+
+ for (i=0; i < multiinfo->count; i++) {
+ printf("%s", i ? "," : "");
+ print_port(multiinfo->ports[i], proto, 1);
+ }
+ printf(" ");
+}
+
+static void multiport_save(const void *ip_void,
+ const struct xt_entry_match *match)
+{
+ const struct ipt_ip *ip = ip_void;
+ __multiport_save(match, ip->proto);
+}
+
+static void multiport_save6(const void *ip_void,
+ const struct xt_entry_match *match)
+{
+ const struct ip6t_ip6 *ip = ip_void;
+ __multiport_save(match, ip->proto);
+}
+
+static void __multiport_save_v1(const struct xt_entry_match *match,
+ u_int16_t proto)
+{
+ const struct xt_multiport_v1 *multiinfo
+ = (const struct xt_multiport_v1 *)match->data;
+ unsigned int i;
+
+ if (multiinfo->invert)
+ printf("! ");
+
+ switch (multiinfo->flags) {
+ case XT_MULTIPORT_SOURCE:
+ printf("--sports ");
+ break;
+
+ case XT_MULTIPORT_DESTINATION:
+ printf("--dports ");
+ break;
+
+ case XT_MULTIPORT_EITHER:
+ printf("--ports ");
+ break;
+ }
+
+ for (i=0; i < multiinfo->count; i++) {
+ printf("%s", i ? "," : "");
+ print_port(multiinfo->ports[i], proto, 1);
+ if (multiinfo->pflags[i]) {
+ printf(":");
+ print_port(multiinfo->ports[++i], proto, 1);
+ }
+ }
+ printf(" ");
+}
+
+static void multiport_save_v1(const void *ip_void,
+ const struct xt_entry_match *match)
+{
+ const struct ipt_ip *ip = ip_void;
+ __multiport_save_v1(match, ip->proto);
+}
+
+static void multiport_save6_v1(const void *ip_void,
+ const struct xt_entry_match *match)
+{
+ const struct ip6t_ip6 *ip = ip_void;
+ __multiport_save_v1(match, ip->proto);
+}
+
+static struct xtables_match multiport_mt_reg[] = {
+ {
+ .family = NFPROTO_IPV4,
+ .name = "multiport",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_multiport)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
+ .help = multiport_help,
+ .parse = multiport_parse,
+ .final_check = multiport_check,
+ .print = multiport_print,
+ .save = multiport_save,
+ .extra_opts = multiport_opts,
+ },
+ {
+ .family = NFPROTO_IPV6,
+ .name = "multiport",
+ .revision = 0,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_multiport)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_multiport)),
+ .help = multiport_help,
+ .parse = multiport_parse6,
+ .final_check = multiport_check,
+ .print = multiport_print6,
+ .save = multiport_save6,
+ .extra_opts = multiport_opts,
+ },
+ {
+ .family = NFPROTO_IPV4,
+ .name = "multiport",
+ .version = XTABLES_VERSION,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
+ .help = multiport_help_v1,
+ .parse = multiport_parse_v1,
+ .final_check = multiport_check,
+ .print = multiport_print_v1,
+ .save = multiport_save_v1,
+ .extra_opts = multiport_opts,
+ },
+ {
+ .family = NFPROTO_IPV6,
+ .name = "multiport",
+ .version = XTABLES_VERSION,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_multiport_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_multiport_v1)),
+ .help = multiport_help_v1,
+ .parse = multiport_parse6_v1,
+ .final_check = multiport_check,
+ .print = multiport_print6_v1,
+ .save = multiport_save6_v1,
+ .extra_opts = multiport_opts,
+ },
+};
+
+void libxt_multiport_init(void)
+{
+ xtables_register_matches(multiport_mt_reg, ARRAY_SIZE(multiport_mt_reg));
+}
diff --git a/extensions/libxt_multiport.man b/extensions/libxt_multiport.man
new file mode 100644
index 0000000..caf5c56
--- /dev/null
+++ b/extensions/libxt_multiport.man
@@ -0,0 +1,23 @@
+This module matches a set of source or destination ports. Up to 15
+ports can be specified. A port range (port:port) counts as two
+ports. It can only be used in conjunction with
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+[\fB!\fP] \fB\-\-source\-ports\fP,\fB\-\-sports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if the source port is one of the given ports. The flag
+\fB\-\-sports\fP
+is a convenient alias for this option. Multiple ports or port ranges are
+separated using a comma, and a port range is specified using a colon.
+\fB53,1024:65535\fP would therefore match ports 53 and all from 1024 through
+65535.
+.TP
+[\fB!\fP] \fB\-\-destination\-ports\fP,\fB\-\-dports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if the destination port is one of the given ports. The flag
+\fB\-\-dports\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-ports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if either the source or destination ports are equal to one of
+the given ports.
diff --git a/extensions/libxt_osf.c b/extensions/libxt_osf.c
new file mode 100644
index 0000000..c147525
--- /dev/null
+++ b/extensions/libxt_osf.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2003+ Evgeniy Polyakov <zbr@ioremap.net>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * xtables interface for OS fingerprint matching module.
+ */
+
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+
+#include <linux/types.h>
+
+#include <xtables.h>
+
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+
+#include <linux/netfilter/xt_osf.h>
+
+static void osf_help(void)
+{
+ printf("OS fingerprint match options:\n"
+ "--genre [!] string Match a OS genre by passive fingerprinting.\n"
+ "--ttl Use some TTL check extensions to determine OS:\n"
+ " 0 true ip and fingerprint TTL comparison. Works for LAN.\n"
+ " 1 check if ip TTL is less than fingerprint one. Works for global addresses.\n"
+ " 2 do not compare TTL at all. Allows to detect NMAP, but can produce false results.\n"
+ "--log level Log determined genres into dmesg even if they do not match desired one:\n"
+ " 0 log all matched or unknown signatures.\n"
+ " 1 log only first one.\n"
+ " 2 log all known matched signatures.\n"
+ );
+}
+
+
+static const struct option osf_opts[] = {
+ { .name = "genre", .has_arg = true, .val = '1' },
+ { .name = "ttl", .has_arg = true, .val = '2' },
+ { .name = "log", .has_arg = true, .val = '3' },
+ { .name = NULL }
+};
+
+
+static void osf_parse_string(const char *s, struct xt_osf_info *info)
+{
+ if (strlen(s) < MAXGENRELEN)
+ strcpy(info->genre, s);
+ else
+ xtables_error(PARAMETER_PROBLEM,
+ "Genre string too long `%s' [%zd], max=%d",
+ s, strlen(s), MAXGENRELEN);
+}
+
+static int osf_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ struct xt_entry_match **match)
+{
+ struct xt_osf_info *info = (struct xt_osf_info *)(*match)->data;
+
+ switch(c) {
+ case '1': /* --genre */
+ if (*flags & XT_OSF_GENRE)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't specify multiple genre parameter");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ osf_parse_string(argv[optind-1], info);
+ if (invert)
+ info->flags |= XT_OSF_INVERT;
+ info->len=strlen(info->genre);
+ *flags |= XT_OSF_GENRE;
+ break;
+ case '2': /* --ttl */
+ if (*flags & XT_OSF_TTL)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't specify multiple ttl parameter");
+ *flags |= XT_OSF_TTL;
+ info->flags |= XT_OSF_TTL;
+ if (!xtables_strtoui(argv[optind-1], NULL, &info->ttl, 0, 2))
+ xtables_error(PARAMETER_PROBLEM, "TTL parameter is too big");
+ break;
+ case '3': /* --log */
+ if (*flags & XT_OSF_LOG)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can't specify multiple log parameter");
+ *flags |= XT_OSF_LOG;
+ if (!xtables_strtoui(argv[optind-1], NULL, &info->loglevel, 0, 2))
+ xtables_error(PARAMETER_PROBLEM, "Log level parameter is too big");
+ info->flags |= XT_OSF_LOG;
+ break;
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void osf_final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "OS fingerprint match: You must specify `--genre'");
+}
+
+static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_osf_info *info = (const struct xt_osf_info*) match->data;
+
+ printf("OS fingerprint match %s%s ", (info->flags & XT_OSF_INVERT) ? "! " : "", info->genre);
+}
+
+static void osf_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_osf_info *info = (const struct xt_osf_info*) match->data;
+
+ printf("--genre %s%s ", (info->flags & XT_OSF_INVERT) ? "! ": "", info->genre);
+}
+
+static struct xtables_match osf_match = {
+ .name = "osf",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_osf_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_osf_info)),
+ .help = osf_help,
+ .parse = osf_parse,
+ .print = osf_print,
+ .final_check = osf_final_check,
+ .save = osf_save,
+ .extra_opts = osf_opts,
+ .family = NFPROTO_IPV4
+};
+
+void libxt_osf_init(void)
+{
+ xtables_register_match(&osf_match);
+}
diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c
new file mode 100644
index 0000000..3a35bfa
--- /dev/null
+++ b/extensions/libxt_owner.c
@@ -0,0 +1,614 @@
+/*
+ * libxt_owner - iptables addon for xt_owner
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007 - 2008
+ * Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <grp.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_owner.h>
+
+/* match and invert flags */
+enum {
+ IPT_OWNER_UID = 0x01,
+ IPT_OWNER_GID = 0x02,
+ IPT_OWNER_PID = 0x04,
+ IPT_OWNER_SID = 0x08,
+ IPT_OWNER_COMM = 0x10,
+ IP6T_OWNER_UID = IPT_OWNER_UID,
+ IP6T_OWNER_GID = IPT_OWNER_GID,
+ IP6T_OWNER_PID = IPT_OWNER_PID,
+ IP6T_OWNER_SID = IPT_OWNER_SID,
+ IP6T_OWNER_COMM = IPT_OWNER_COMM,
+};
+
+struct ipt_owner_info {
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ pid_t sid;
+ char comm[16];
+ u_int8_t match, invert; /* flags */
+};
+
+struct ip6t_owner_info {
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ pid_t sid;
+ char comm[16];
+ u_int8_t match, invert; /* flags */
+};
+
+/*
+ * Note: "UINT32_MAX - 1" is used in the code because -1 is a reserved
+ * UID/GID value anyway.
+ */
+
+enum {
+ FLAG_UID_OWNER = 1 << 0,
+ FLAG_GID_OWNER = 1 << 1,
+ FLAG_SOCKET_EXISTS = 1 << 2,
+ FLAG_PID_OWNER = 1 << 3,
+ FLAG_SID_OWNER = 1 << 4,
+ FLAG_COMM = 1 << 5,
+};
+
+static void owner_mt_help_v0(void)
+{
+#ifdef IPT_OWNER_COMM
+ printf(
+"owner match options:\n"
+"[!] --uid-owner userid Match local UID\n"
+"[!] --gid-owner groupid Match local GID\n"
+"[!] --pid-owner processid Match local PID\n"
+"[!] --sid-owner sessionid Match local SID\n"
+"[!] --cmd-owner name Match local command name\n"
+"NOTE: PID, SID and command matching are broken on SMP\n");
+#else
+ printf(
+"owner match options:\n"
+"[!] --uid-owner userid Match local UID\n"
+"[!] --gid-owner groupid Match local GID\n"
+"[!] --pid-owner processid Match local PID\n"
+"[!] --sid-owner sessionid Match local SID\n"
+"NOTE: PID and SID matching are broken on SMP\n");
+#endif /* IPT_OWNER_COMM */
+}
+
+static void owner_mt6_help_v0(void)
+{
+ printf(
+"owner match options:\n"
+"[!] --uid-owner userid Match local UID\n"
+"[!] --gid-owner groupid Match local GID\n"
+"[!] --pid-owner processid Match local PID\n"
+"[!] --sid-owner sessionid Match local SID\n"
+"NOTE: PID and SID matching are broken on SMP\n");
+}
+
+static void owner_mt_help(void)
+{
+ printf(
+"owner match options:\n"
+"[!] --uid-owner userid[-userid] Match local UID\n"
+"[!] --gid-owner groupid[-groupid] Match local GID\n"
+"[!] --socket-exists Match if socket exists\n");
+}
+
+static const struct option owner_mt_opts_v0[] = {
+ {.name = "uid-owner", .has_arg = true, .val = 'u'},
+ {.name = "gid-owner", .has_arg = true, .val = 'g'},
+ {.name = "pid-owner", .has_arg = true, .val = 'p'},
+ {.name = "sid-owner", .has_arg = true, .val = 's'},
+#ifdef IPT_OWNER_COMM
+ {.name = "cmd-owner", .has_arg = true, .val = 'c'},
+#endif
+ { .name = NULL }
+};
+
+static const struct option owner_mt6_opts_v0[] = {
+ {.name = "uid-owner", .has_arg = true, .val = 'u'},
+ {.name = "gid-owner", .has_arg = true, .val = 'g'},
+ {.name = "pid-owner", .has_arg = true, .val = 'p'},
+ {.name = "sid-owner", .has_arg = true, .val = 's'},
+ { .name = NULL }
+};
+
+static const struct option owner_mt_opts[] = {
+ {.name = "uid-owner", .has_arg = true, .val = 'u'},
+ {.name = "gid-owner", .has_arg = true, .val = 'g'},
+ {.name = "socket-exists", .has_arg = false, .val = 'k'},
+ { .name = NULL }
+};
+
+static int
+owner_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ipt_owner_info *info = (void *)(*match)->data;
+ struct passwd *pwd;
+ struct group *grp;
+ unsigned int id;
+
+ switch (c) {
+ case 'u':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner", *flags & FLAG_UID_OWNER);
+ if ((pwd = getpwnam(optarg)) != NULL)
+ id = pwd->pw_uid;
+ else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg);
+ if (invert)
+ info->invert |= IPT_OWNER_UID;
+ info->match |= IPT_OWNER_UID;
+ info->uid = id;
+ *flags |= FLAG_UID_OWNER;
+ return true;
+
+ case 'g':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner", *flags & FLAG_GID_OWNER);
+ if ((grp = getgrnam(optarg)) != NULL)
+ id = grp->gr_gid;
+ else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg);
+ if (invert)
+ info->invert |= IPT_OWNER_GID;
+ info->match |= IPT_OWNER_GID;
+ info->gid = id;
+ *flags |= FLAG_GID_OWNER;
+ return true;
+
+ case 'p':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner", *flags & FLAG_PID_OWNER);
+ if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg);
+ if (invert)
+ info->invert |= IPT_OWNER_PID;
+ info->match |= IPT_OWNER_PID;
+ info->pid = id;
+ *flags |= FLAG_PID_OWNER;
+ return true;
+
+ case 's':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner", *flags & FLAG_SID_OWNER);
+ if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-value", optarg);
+ if (invert)
+ info->invert |= IPT_OWNER_SID;
+ info->match |= IPT_OWNER_SID;
+ info->sid = id;
+ *flags |= FLAG_SID_OWNER;
+ return true;
+
+#ifdef IPT_OWNER_COMM
+ case 'c':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--cmd-owner", *flags & FLAG_COMM);
+ if (strlen(optarg) > sizeof(info->comm))
+ xtables_error(PARAMETER_PROBLEM, "owner match: command "
+ "\"%s\" too long, max. %zu characters",
+ optarg, sizeof(info->comm));
+
+ info->comm[sizeof(info->comm)-1] = '\0';
+ strncpy(info->comm, optarg, sizeof(info->comm));
+
+ if (invert)
+ info->invert |= IPT_OWNER_COMM;
+ info->match |= IPT_OWNER_COMM;
+ *flags |= FLAG_COMM;
+ return true;
+#endif
+ }
+ return false;
+}
+
+static int
+owner_mt6_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ip6t_owner_info *info = (void *)(*match)->data;
+ struct passwd *pwd;
+ struct group *grp;
+ unsigned int id;
+
+ switch (c) {
+ case 'u':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner",
+ *flags & FLAG_UID_OWNER);
+ if ((pwd = getpwnam(optarg)) != NULL)
+ id = pwd->pw_uid;
+ else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", optarg);
+ if (invert)
+ info->invert |= IP6T_OWNER_UID;
+ info->match |= IP6T_OWNER_UID;
+ info->uid = id;
+ *flags |= FLAG_UID_OWNER;
+ return true;
+
+ case 'g':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner",
+ *flags & FLAG_GID_OWNER);
+ if ((grp = getgrnam(optarg)) != NULL)
+ id = grp->gr_gid;
+ else if (!xtables_strtoui(optarg, NULL, &id, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", optarg);
+ if (invert)
+ info->invert |= IP6T_OWNER_GID;
+ info->match |= IP6T_OWNER_GID;
+ info->gid = id;
+ *flags |= FLAG_GID_OWNER;
+ return true;
+
+ case 'p':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--pid-owner",
+ *flags & FLAG_PID_OWNER);
+ if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--pid-owner", optarg);
+ if (invert)
+ info->invert |= IP6T_OWNER_PID;
+ info->match |= IP6T_OWNER_PID;
+ info->pid = id;
+ *flags |= FLAG_PID_OWNER;
+ return true;
+
+ case 's':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--sid-owner",
+ *flags & FLAG_SID_OWNER);
+ if (!xtables_strtoui(optarg, NULL, &id, 0, INT_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "owner", "--sid-owner", optarg);
+ if (invert)
+ info->invert |= IP6T_OWNER_SID;
+ info->match |= IP6T_OWNER_SID;
+ info->sid = id;
+ *flags |= FLAG_SID_OWNER;
+ return true;
+ }
+ return false;
+}
+
+static void owner_parse_range(const char *s, unsigned int *from,
+ unsigned int *to, const char *opt)
+{
+ char *end;
+
+ /* -1 is reversed, so the max is one less than that. */
+ if (!xtables_strtoui(s, &end, from, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
+ *to = *from;
+ if (*end == '-' || *end == ':')
+ if (!xtables_strtoui(end + 1, &end, to, 0, UINT32_MAX - 1))
+ xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
+ if (*end != '\0')
+ xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
+}
+
+static int owner_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_owner_match_info *info = (void *)(*match)->data;
+ struct passwd *pwd;
+ struct group *grp;
+ unsigned int from, to;
+
+ switch (c) {
+ case 'u':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--uid-owner",
+ *flags & FLAG_UID_OWNER);
+ if ((pwd = getpwnam(optarg)) != NULL)
+ from = to = pwd->pw_uid;
+ else
+ owner_parse_range(optarg, &from, &to, "--uid-owner");
+ if (invert)
+ info->invert |= XT_OWNER_UID;
+ info->match |= XT_OWNER_UID;
+ info->uid_min = from;
+ info->uid_max = to;
+ *flags |= FLAG_UID_OWNER;
+ return true;
+
+ case 'g':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--gid-owner",
+ *flags & FLAG_GID_OWNER);
+ if ((grp = getgrnam(optarg)) != NULL)
+ from = to = grp->gr_gid;
+ else
+ owner_parse_range(optarg, &from, &to, "--gid-owner");
+ if (invert)
+ info->invert |= XT_OWNER_GID;
+ info->match |= XT_OWNER_GID;
+ info->gid_min = from;
+ info->gid_max = to;
+ *flags |= FLAG_GID_OWNER;
+ return true;
+
+ case 'k':
+ xtables_param_act(XTF_ONLY_ONCE, "owner", "--socket-exists",
+ *flags & FLAG_SOCKET_EXISTS);
+ if (invert)
+ info->invert |= XT_OWNER_SOCKET;
+ info->match |= XT_OWNER_SOCKET;
+ *flags |= FLAG_SOCKET_EXISTS;
+ return true;
+
+ }
+ return false;
+}
+
+static void owner_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM, "owner: At least one of "
+ "--uid-owner, --gid-owner or --socket-exists "
+ "is required");
+}
+
+static void
+owner_mt_print_item_v0(const struct ipt_owner_info *info, const char *label,
+ u_int8_t flag, bool numeric)
+{
+ if (!(info->match & flag))
+ return;
+ if (info->invert & flag)
+ printf("! ");
+ printf("%s ", label);
+
+ switch (info->match & flag) {
+ case IPT_OWNER_UID:
+ if (!numeric) {
+ struct passwd *pwd = getpwuid(info->uid);
+
+ if (pwd != NULL && pwd->pw_name != NULL) {
+ printf("%s ", pwd->pw_name);
+ break;
+ }
+ }
+ printf("%u ", (unsigned int)info->uid);
+ break;
+
+ case IPT_OWNER_GID:
+ if (!numeric) {
+ struct group *grp = getgrgid(info->gid);
+
+ if (grp != NULL && grp->gr_name != NULL) {
+ printf("%s ", grp->gr_name);
+ break;
+ }
+ }
+ printf("%u ", (unsigned int)info->gid);
+ break;
+
+ case IPT_OWNER_PID:
+ printf("%u ", (unsigned int)info->pid);
+ break;
+
+ case IPT_OWNER_SID:
+ printf("%u ", (unsigned int)info->sid);
+ break;
+
+#ifdef IPT_OWNER_COMM
+ case IPT_OWNER_COMM:
+ printf("%.*s ", (int)sizeof(info->comm), info->comm);
+ break;
+#endif
+ }
+}
+
+static void
+owner_mt6_print_item_v0(const struct ip6t_owner_info *info, const char *label,
+ u_int8_t flag, bool numeric)
+{
+ if (!(info->match & flag))
+ return;
+ if (info->invert & flag)
+ printf("! ");
+ printf("%s ", label);
+
+ switch (info->match & flag) {
+ case IP6T_OWNER_UID:
+ if (!numeric) {
+ struct passwd *pwd = getpwuid(info->uid);
+
+ if (pwd != NULL && pwd->pw_name != NULL) {
+ printf("%s ", pwd->pw_name);
+ break;
+ }
+ }
+ printf("%u ", (unsigned int)info->uid);
+ break;
+
+ case IP6T_OWNER_GID:
+ if (!numeric) {
+ struct group *grp = getgrgid(info->gid);
+
+ if (grp != NULL && grp->gr_name != NULL) {
+ printf("%s ", grp->gr_name);
+ break;
+ }
+ }
+ printf("%u ", (unsigned int)info->gid);
+ break;
+
+ case IP6T_OWNER_PID:
+ printf("%u ", (unsigned int)info->pid);
+ break;
+
+ case IP6T_OWNER_SID:
+ printf("%u ", (unsigned int)info->sid);
+ break;
+ }
+}
+
+static void
+owner_mt_print_item(const struct xt_owner_match_info *info, const char *label,
+ u_int8_t flag, bool numeric)
+{
+ if (!(info->match & flag))
+ return;
+ if (info->invert & flag)
+ printf("! ");
+ printf("%s ", label);
+
+ switch (info->match & flag) {
+ case XT_OWNER_UID:
+ if (info->uid_min != info->uid_max) {
+ printf("%u-%u ", (unsigned int)info->uid_min,
+ (unsigned int)info->uid_max);
+ break;
+ } else if (!numeric) {
+ const struct passwd *pwd = getpwuid(info->uid_min);
+
+ if (pwd != NULL && pwd->pw_name != NULL) {
+ printf("%s ", pwd->pw_name);
+ break;
+ }
+ }
+ printf("%u ", (unsigned int)info->uid_min);
+ break;
+
+ case XT_OWNER_GID:
+ if (info->gid_min != info->gid_max) {
+ printf("%u-%u ", (unsigned int)info->gid_min,
+ (unsigned int)info->gid_max);
+ break;
+ } else if (!numeric) {
+ const struct group *grp = getgrgid(info->gid_min);
+
+ if (grp != NULL && grp->gr_name != NULL) {
+ printf("%s ", grp->gr_name);
+ break;
+ }
+ }
+ printf("%u ", (unsigned int)info->gid_min);
+ break;
+ }
+}
+
+static void
+owner_mt_print_v0(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_owner_info *info = (void *)match->data;
+
+ owner_mt_print_item_v0(info, "owner UID match", IPT_OWNER_UID, numeric);
+ owner_mt_print_item_v0(info, "owner GID match", IPT_OWNER_GID, numeric);
+ owner_mt_print_item_v0(info, "owner PID match", IPT_OWNER_PID, numeric);
+ owner_mt_print_item_v0(info, "owner SID match", IPT_OWNER_SID, numeric);
+#ifdef IPT_OWNER_COMM
+ owner_mt_print_item_v0(info, "owner CMD match", IPT_OWNER_COMM, numeric);
+#endif
+}
+
+static void
+owner_mt6_print_v0(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ip6t_owner_info *info = (void *)match->data;
+
+ owner_mt6_print_item_v0(info, "owner UID match", IPT_OWNER_UID, numeric);
+ owner_mt6_print_item_v0(info, "owner GID match", IPT_OWNER_GID, numeric);
+ owner_mt6_print_item_v0(info, "owner PID match", IPT_OWNER_PID, numeric);
+ owner_mt6_print_item_v0(info, "owner SID match", IPT_OWNER_SID, numeric);
+}
+
+static void owner_mt_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_owner_match_info *info = (void *)match->data;
+
+ owner_mt_print_item(info, "owner socket exists", XT_OWNER_SOCKET, numeric);
+ owner_mt_print_item(info, "owner UID match", XT_OWNER_UID, numeric);
+ owner_mt_print_item(info, "owner GID match", XT_OWNER_GID, numeric);
+}
+
+static void
+owner_mt_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ipt_owner_info *info = (void *)match->data;
+
+ owner_mt_print_item_v0(info, "--uid-owner", IPT_OWNER_UID, true);
+ owner_mt_print_item_v0(info, "--gid-owner", IPT_OWNER_GID, true);
+ owner_mt_print_item_v0(info, "--pid-owner", IPT_OWNER_PID, true);
+ owner_mt_print_item_v0(info, "--sid-owner", IPT_OWNER_SID, true);
+#ifdef IPT_OWNER_COMM
+ owner_mt_print_item_v0(info, "--cmd-owner", IPT_OWNER_COMM, true);
+#endif
+}
+
+static void
+owner_mt6_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ip6t_owner_info *info = (void *)match->data;
+
+ owner_mt6_print_item_v0(info, "--uid-owner", IPT_OWNER_UID, true);
+ owner_mt6_print_item_v0(info, "--gid-owner", IPT_OWNER_GID, true);
+ owner_mt6_print_item_v0(info, "--pid-owner", IPT_OWNER_PID, true);
+ owner_mt6_print_item_v0(info, "--sid-owner", IPT_OWNER_SID, true);
+}
+
+static void owner_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_owner_match_info *info = (void *)match->data;
+
+ owner_mt_print_item(info, "--socket-exists", XT_OWNER_SOCKET, false);
+ owner_mt_print_item(info, "--uid-owner", XT_OWNER_UID, false);
+ owner_mt_print_item(info, "--gid-owner", XT_OWNER_GID, false);
+}
+
+static struct xtables_match owner_mt_reg[] = {
+ {
+ .version = XTABLES_VERSION,
+ .name = "owner",
+ .revision = 0,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct ipt_owner_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_owner_info)),
+ .help = owner_mt_help_v0,
+ .parse = owner_mt_parse_v0,
+ .final_check = owner_mt_check,
+ .print = owner_mt_print_v0,
+ .save = owner_mt_save_v0,
+ .extra_opts = owner_mt_opts_v0,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "owner",
+ .revision = 0,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct ip6t_owner_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ip6t_owner_info)),
+ .help = owner_mt6_help_v0,
+ .parse = owner_mt6_parse_v0,
+ .final_check = owner_mt_check,
+ .print = owner_mt6_print_v0,
+ .save = owner_mt6_save_v0,
+ .extra_opts = owner_mt6_opts_v0,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "owner",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_owner_match_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)),
+ .help = owner_mt_help,
+ .parse = owner_mt_parse,
+ .final_check = owner_mt_check,
+ .print = owner_mt_print,
+ .save = owner_mt_save,
+ .extra_opts = owner_mt_opts,
+ },
+};
+
+void libxt_owner_init(void)
+{
+ xtables_register_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg));
+}
diff --git a/extensions/libxt_owner.man b/extensions/libxt_owner.man
new file mode 100644
index 0000000..49b58ce
--- /dev/null
+++ b/extensions/libxt_owner.man
@@ -0,0 +1,19 @@
+This module attempts to match various characteristics of the packet creator,
+for locally generated packets. This match is only valid in the OUTPUT and
+POSTROUTING chains. Forwarded packets do not have any socket associated with
+them. Packets from kernel threads do have a socket, but usually no owner.
+.TP
+[\fB!\fP] \fB\-\-uid\-owner\fP \fIusername\fP
+.TP
+[\fB!\fP] \fB\-\-uid\-owner\fP \fIuserid\fP[\fB\-\fP\fIuserid\fP]
+Matches if the packet socket's file structure (if it has one) is owned by the
+given user. You may also specify a numerical UID, or an UID range.
+.TP
+[\fB!\fP] \fB\-\-gid\-owner\fP \fIgroupname\fP
+.TP
+[\fB!\fP] \fB\-\-gid\-owner\fP \fIgroupid\fP[\fB\-\fP\fIgroupid\fP]
+Matches if the packet socket's file structure is owned by the given group.
+You may also specify a numerical GID, or a GID range.
+.TP
+[\fB!\fP] \fB\-\-socket\-exists\fP
+Matches if the packet is associated with a socket.
diff --git a/extensions/libxt_physdev.c b/extensions/libxt_physdev.c
new file mode 100644
index 0000000..0345465
--- /dev/null
+++ b/extensions/libxt_physdev.c
@@ -0,0 +1,180 @@
+/* Shared library add-on to iptables to add bridge port matching support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_physdev.h>
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+
+static void physdev_help(void)
+{
+ printf(
+"physdev match options:\n"
+" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n"
+" [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n"
+" [!] --physdev-is-in arrived on a bridge device\n"
+" [!] --physdev-is-out will leave on a bridge device\n"
+" [!] --physdev-is-bridged it's a bridged packet\n");
+}
+
+static const struct option physdev_opts[] = {
+ { "physdev-in", 1, NULL, '1' },
+ { "physdev-out", 1, NULL, '2' },
+ { "physdev-is-in", 0, NULL, '3' },
+ { "physdev-is-out", 0, NULL, '4' },
+ { "physdev-is-bridged", 0, NULL, '5' },
+ { .name = NULL }
+};
+
+static int
+physdev_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_physdev_info *info =
+ (struct xt_physdev_info*)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & XT_PHYSDEV_OP_IN)
+ goto multiple_use;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ xtables_parse_interface(optarg, info->physindev,
+ (unsigned char *)info->in_mask);
+ if (invert)
+ info->invert |= XT_PHYSDEV_OP_IN;
+ info->bitmask |= XT_PHYSDEV_OP_IN;
+ *flags |= XT_PHYSDEV_OP_IN;
+ break;
+
+ case '2':
+ if (*flags & XT_PHYSDEV_OP_OUT)
+ goto multiple_use;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ xtables_parse_interface(optarg, info->physoutdev,
+ (unsigned char *)info->out_mask);
+ if (invert)
+ info->invert |= XT_PHYSDEV_OP_OUT;
+ info->bitmask |= XT_PHYSDEV_OP_OUT;
+ *flags |= XT_PHYSDEV_OP_OUT;
+ break;
+
+ case '3':
+ if (*flags & XT_PHYSDEV_OP_ISIN)
+ goto multiple_use;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->bitmask |= XT_PHYSDEV_OP_ISIN;
+ if (invert)
+ info->invert |= XT_PHYSDEV_OP_ISIN;
+ *flags |= XT_PHYSDEV_OP_ISIN;
+ break;
+
+ case '4':
+ if (*flags & XT_PHYSDEV_OP_ISOUT)
+ goto multiple_use;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->bitmask |= XT_PHYSDEV_OP_ISOUT;
+ if (invert)
+ info->invert |= XT_PHYSDEV_OP_ISOUT;
+ *flags |= XT_PHYSDEV_OP_ISOUT;
+ break;
+
+ case '5':
+ if (*flags & XT_PHYSDEV_OP_BRIDGED)
+ goto multiple_use;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ info->invert |= XT_PHYSDEV_OP_BRIDGED;
+ *flags |= XT_PHYSDEV_OP_BRIDGED;
+ info->bitmask |= XT_PHYSDEV_OP_BRIDGED;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+multiple_use:
+ xtables_error(PARAMETER_PROBLEM,
+ "multiple use of the same physdev option is not allowed");
+
+}
+
+static void physdev_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
+}
+
+static void
+physdev_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_physdev_info *info = (const void *)match->data;
+
+ printf("PHYSDEV match");
+ if (info->bitmask & XT_PHYSDEV_OP_ISIN)
+ printf("%s --physdev-is-in",
+ info->invert & XT_PHYSDEV_OP_ISIN ? " !":"");
+ if (info->bitmask & XT_PHYSDEV_OP_IN)
+ printf("%s --physdev-in %s",
+ (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
+
+ if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
+ printf("%s --physdev-is-out",
+ info->invert & XT_PHYSDEV_OP_ISOUT ? " !":"");
+ if (info->bitmask & XT_PHYSDEV_OP_OUT)
+ printf("%s --physdev-out %s",
+ (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
+ if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
+ printf("%s --physdev-is-bridged",
+ info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":"");
+ printf(" ");
+}
+
+static void physdev_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_physdev_info *info = (const void *)match->data;
+
+ if (info->bitmask & XT_PHYSDEV_OP_ISIN)
+ printf("%s--physdev-is-in ",
+ (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : "");
+ if (info->bitmask & XT_PHYSDEV_OP_IN)
+ printf("%s--physdev-in %s ",
+ (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "",
+ info->physindev);
+
+ if (info->bitmask & XT_PHYSDEV_OP_ISOUT)
+ printf("%s--physdev-is-out ",
+ (info->invert & XT_PHYSDEV_OP_ISOUT) ? "! " : "");
+ if (info->bitmask & XT_PHYSDEV_OP_OUT)
+ printf("%s--physdev-out %s ",
+ (info->invert & XT_PHYSDEV_OP_OUT) ? "! " : "",
+ info->physoutdev);
+ if (info->bitmask & XT_PHYSDEV_OP_BRIDGED)
+ printf("%s--physdev-is-bridged ",
+ (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : "");
+}
+
+static struct xtables_match physdev_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "physdev",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_physdev_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)),
+ .help = physdev_help,
+ .parse = physdev_parse,
+ .final_check = physdev_check,
+ .print = physdev_print,
+ .save = physdev_save,
+ .extra_opts = physdev_opts,
+};
+
+void libxt_physdev_init(void)
+{
+ xtables_register_match(&physdev_match);
+}
diff --git a/extensions/libip6t_physdev.man b/extensions/libxt_physdev.man
index 1e635fc..53beb2e 100644
--- a/extensions/libip6t_physdev.man
+++ b/extensions/libxt_physdev.man
@@ -3,7 +3,7 @@ to a bridge device. This module is a part of the infrastructure that enables
a transparent bridging IP firewall and is only useful for kernel versions
above version 2.5.44.
.TP
-.BR --physdev-in " [!] \fIname\fP"
+[\fB!\fP] \fB\-\-physdev\-in\fP \fIname\fP
Name of a bridge port via which a packet is received (only for
packets entering the
.BR INPUT ,
@@ -14,7 +14,7 @@ chains). If the interface name ends in a "+", then any
interface which begins with this name will match. If the packet didn't arrive
through a bridge device, this packet won't match this option, unless '!' is used.
.TP
-.BR --physdev-out " [!] \fIname\fP"
+[\fB!\fP] \fB\-\-physdev\-out\fP \fIname\fP
Name of a bridge port via which a packet is going to be sent (for packets
entering the
.BR FORWARD ,
@@ -27,16 +27,16 @@ interface which begins with this name will match. Note that in the
.B OUTPUT
chains one cannot match on the bridge output port, however one can in the
.B "filter OUTPUT"
-chain. If the packet won't leave by a bridge device or it is yet unknown what
-the output device will be, then the packet won't match this option, unless
-'!' is used.
+chain. If the packet won't leave by a bridge device or if it is yet unknown what
+the output device will be, then the packet won't match this option,
+unless '!' is used.
.TP
-.RB "[!] " --physdev-is-in
+[\fB!\fP] \fB\-\-physdev\-is\-in\fP
Matches if the packet has entered through a bridge interface.
.TP
-.RB "[!] " --physdev-is-out
+[\fB!\fP] \fB\-\-physdev\-is\-out\fP
Matches if the packet will leave through a bridge interface.
.TP
-.RB "[!] " --physdev-is-bridged
+[\fB!\fP] \fB\-\-physdev\-is\-bridged\fP
Matches if the packet is being bridged and therefore is not being routed.
This is only useful in the FORWARD and POSTROUTING chains.
diff --git a/extensions/libxt_pkttype.c b/extensions/libxt_pkttype.c
new file mode 100644
index 0000000..c57f7fd
--- /dev/null
+++ b/extensions/libxt_pkttype.c
@@ -0,0 +1,158 @@
+/*
+ * Shared library add-on to iptables to match
+ * packets by their type (BROADCAST, UNICAST, MULTICAST).
+ *
+ * Michal Ludvig <michal@logix.cz>
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+#include <xtables.h>
+#include <linux/if_packet.h>
+#include <linux/netfilter/xt_pkttype.h>
+
+#define PKTTYPE_VERSION "0.1"
+
+struct pkttypes {
+ const char *name;
+ unsigned char pkttype;
+ unsigned char printhelp;
+ const char *help;
+};
+
+static const struct pkttypes supported_types[] = {
+ {"unicast", PACKET_HOST, 1, "to us"},
+ {"broadcast", PACKET_BROADCAST, 1, "to all"},
+ {"multicast", PACKET_MULTICAST, 1, "to group"},
+/*
+ {"otherhost", PACKET_OTHERHOST, 1, "to someone else"},
+ {"outgoing", PACKET_OUTGOING, 1, "outgoing of any type"},
+*/
+ /* aliases */
+ {"bcast", PACKET_BROADCAST, 0, NULL},
+ {"mcast", PACKET_MULTICAST, 0, NULL},
+ {"host", PACKET_HOST, 0, NULL}
+};
+
+static void print_types(void)
+{
+ unsigned int i;
+
+ printf("Valid packet types:\n");
+ for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
+ if(supported_types[i].printhelp == 1)
+ printf("\t%-14s\t\t%s\n", supported_types[i].name, supported_types[i].help);
+ printf("\n");
+}
+
+static void pkttype_help(void)
+{
+ printf(
+"pkttype match options:\n"
+"[!] --pkt-type packettype match packet type\n");
+ print_types();
+}
+
+static const struct option pkttype_opts[] = {
+ {"pkt-type", 1, NULL, '1'},
+ { .name = NULL }
+};
+
+static void parse_pkttype(const char *pkttype, struct xt_pkttype_info *info)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
+ if(strcasecmp(pkttype, supported_types[i].name)==0)
+ {
+ info->pkttype=supported_types[i].pkttype;
+ return;
+ }
+
+ xtables_error(PARAMETER_PROBLEM, "Bad packet type '%s'", pkttype);
+}
+
+static int pkttype_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_pkttype_info *info = (struct xt_pkttype_info *)(*match)->data;
+
+ switch(c)
+ {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_pkttype(optarg, info);
+ if(invert)
+ info->invert=1;
+ *flags=1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void pkttype_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM, "You must specify \"--pkt-type\"");
+}
+
+static void print_pkttype(const struct xt_pkttype_info *info)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(supported_types); ++i)
+ if(supported_types[i].pkttype==info->pkttype)
+ {
+ printf("%s ", supported_types[i].name);
+ return;
+ }
+
+ printf("%d ", info->pkttype); /* in case we didn't find an entry in named-packtes */
+}
+
+static void pkttype_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_pkttype_info *info = (const void *)match->data;
+
+ printf("PKTTYPE %s= ", info->invert?"!":"");
+ print_pkttype(info);
+}
+
+static void pkttype_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_pkttype_info *info = (const void *)match->data;
+
+ printf("%s--pkt-type ", info->invert ? "! " : "");
+ print_pkttype(info);
+}
+
+static struct xtables_match pkttype_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "pkttype",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_pkttype_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_pkttype_info)),
+ .help = pkttype_help,
+ .parse = pkttype_parse,
+ .final_check = pkttype_check,
+ .print = pkttype_print,
+ .save = pkttype_save,
+ .extra_opts = pkttype_opts,
+};
+
+void libxt_pkttype_init(void)
+{
+ xtables_register_match(&pkttype_match);
+}
diff --git a/extensions/libxt_pkttype.man b/extensions/libxt_pkttype.man
new file mode 100644
index 0000000..4560c76
--- /dev/null
+++ b/extensions/libxt_pkttype.man
@@ -0,0 +1,3 @@
+This module matches the link-layer packet type.
+.TP
+[\fB!\fP] \fB\-\-pkt\-type\fP {\fBunicast\fP|\fBbroadcast\fP|\fBmulticast\fP}
diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c
new file mode 100644
index 0000000..b905259
--- /dev/null
+++ b/extensions/libxt_policy.c
@@ -0,0 +1,513 @@
+/* Shared library add-on to iptables to add policy support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <xtables.h>
+
+#include <linux/netfilter/xt_policy.h>
+
+/*
+ * HACK: global pointer to current matchinfo for making
+ * final checks and adjustments in final_check.
+ */
+static struct xt_policy_info *policy_info;
+
+static void policy_help(void)
+{
+ printf(
+"policy match options:\n"
+" --dir in|out match policy applied during decapsulation/\n"
+" policy to be applied during encapsulation\n"
+" --pol none|ipsec match policy\n"
+" --strict match entire policy instead of single element\n"
+" at any position\n"
+"[!] --reqid reqid match reqid\n"
+"[!] --spi spi match SPI\n"
+"[!] --proto proto match protocol (ah/esp/ipcomp)\n"
+"[!] --mode mode match mode (transport/tunnel)\n"
+"[!] --tunnel-src addr/mask match tunnel source\n"
+"[!] --tunnel-dst addr/mask match tunnel destination\n"
+" --next begin next element in policy\n");
+}
+
+static const struct option policy_opts[] =
+{
+ {
+ .name = "dir",
+ .has_arg = 1,
+ .val = '1',
+ },
+ {
+ .name = "pol",
+ .has_arg = 1,
+ .val = '2',
+ },
+ {
+ .name = "strict",
+ .val = '3'
+ },
+ {
+ .name = "reqid",
+ .has_arg = 1,
+ .val = '4',
+ },
+ {
+ .name = "spi",
+ .has_arg = 1,
+ .val = '5'
+ },
+ {
+ .name = "tunnel-src",
+ .has_arg = 1,
+ .val = '6'
+ },
+ {
+ .name = "tunnel-dst",
+ .has_arg = 1,
+ .val = '7'
+ },
+ {
+ .name = "proto",
+ .has_arg = 1,
+ .val = '8'
+ },
+ {
+ .name = "mode",
+ .has_arg = 1,
+ .val = '9'
+ },
+ {
+ .name = "next",
+ .val = 'a'
+ },
+ { .name = NULL }
+};
+
+static int parse_direction(char *s)
+{
+ if (strcmp(s, "in") == 0)
+ return XT_POLICY_MATCH_IN;
+ if (strcmp(s, "out") == 0)
+ return XT_POLICY_MATCH_OUT;
+ xtables_error(PARAMETER_PROBLEM, "policy_match: invalid dir \"%s\"", s);
+}
+
+static int parse_policy(char *s)
+{
+ if (strcmp(s, "none") == 0)
+ return XT_POLICY_MATCH_NONE;
+ if (strcmp(s, "ipsec") == 0)
+ return 0;
+ xtables_error(PARAMETER_PROBLEM, "policy match: invalid policy \"%s\"", s);
+}
+
+static int parse_mode(char *s)
+{
+ if (strcmp(s, "transport") == 0)
+ return XT_POLICY_MODE_TRANSPORT;
+ if (strcmp(s, "tunnel") == 0)
+ return XT_POLICY_MODE_TUNNEL;
+ xtables_error(PARAMETER_PROBLEM, "policy match: invalid mode \"%s\"", s);
+}
+
+static int policy_parse(int c, char **argv, int invert, unsigned int *flags,
+ struct xt_policy_info *info, uint8_t family)
+{
+ struct xt_policy_elem *e = &info->pol[info->len];
+ struct in_addr *addr = NULL, mask;
+ struct in6_addr *addr6 = NULL, mask6;
+ unsigned int naddr = 0, num;
+ int mode;
+
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ switch (c) {
+ case '1':
+ if (info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT))
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --dir option");
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: can't invert --dir option");
+
+ info->flags |= parse_direction(optarg);
+ break;
+ case '2':
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: can't invert --policy option");
+
+ info->flags |= parse_policy(optarg);
+ break;
+ case '3':
+ if (info->flags & XT_POLICY_MATCH_STRICT)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --strict option");
+
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: can't invert --strict option");
+
+ info->flags |= XT_POLICY_MATCH_STRICT;
+ break;
+ case '4':
+ if (e->match.reqid)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --reqid option");
+
+ e->match.reqid = 1;
+ e->invert.reqid = invert;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg);
+ e->reqid = num;
+ break;
+ case '5':
+ if (e->match.spi)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --spi option");
+
+ e->match.spi = 1;
+ e->invert.spi = invert;
+ if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX))
+ xtables_param_act(XTF_BAD_VALUE, "policy", "--spi", optarg);
+ e->spi = num;
+ break;
+ case '6':
+ if (e->match.saddr)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --tunnel-src option");
+
+ if (family == NFPROTO_IPV6)
+ xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr);
+ else
+ xtables_ipparse_any(optarg, &addr, &mask, &naddr);
+ if (naddr > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: name resolves to multiple IPs");
+
+ e->match.saddr = 1;
+ e->invert.saddr = invert;
+ if (family == NFPROTO_IPV6) {
+ memcpy(&e->saddr.a6, addr6, sizeof(*addr6));
+ memcpy(&e->smask.a6, &mask6, sizeof(mask6));
+ } else {
+ e->saddr.a4 = addr[0];
+ e->smask.a4 = mask;
+ }
+ break;
+ case '7':
+ if (e->match.daddr)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --tunnel-dst option");
+
+ if (family == NFPROTO_IPV6)
+ xtables_ip6parse_any(optarg, &addr6, &mask6, &naddr);
+ else
+ xtables_ipparse_any(optarg, &addr, &mask, &naddr);
+ if (naddr > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: name resolves to multiple IPs");
+
+ e->match.daddr = 1;
+ e->invert.daddr = invert;
+ if (family == NFPROTO_IPV6) {
+ memcpy(&e->daddr.a6, addr6, sizeof(*addr6));
+ memcpy(&e->dmask.a6, &mask6, sizeof(mask6));
+ } else {
+ e->daddr.a4 = addr[0];
+ e->dmask.a4 = mask;
+ }
+ break;
+ case '8':
+ if (e->match.proto)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --proto option");
+
+ e->proto = xtables_parse_protocol(optarg);
+ if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
+ e->proto != IPPROTO_COMP)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: protocol must ah/esp/ipcomp");
+ e->match.proto = 1;
+ e->invert.proto = invert;
+ break;
+ case '9':
+ if (e->match.mode)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: double --mode option");
+
+ mode = parse_mode(optarg);
+ e->match.mode = 1;
+ e->invert.mode = invert;
+ e->mode = mode;
+ break;
+ case 'a':
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: can't invert --next option");
+
+ if (++info->len == XT_POLICY_MAX_ELEM)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: maximum policy depth reached");
+ break;
+ default:
+ return 0;
+ }
+
+ policy_info = info;
+ return 1;
+}
+
+static int policy4_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return policy_parse(c, argv, invert, flags, (void *)(*match)->data,
+ NFPROTO_IPV4);
+}
+
+static int policy6_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ return policy_parse(c, argv, invert, flags, (void *)(*match)->data,
+ NFPROTO_IPV6);
+}
+
+static void policy_check(unsigned int flags)
+{
+ struct xt_policy_info *info = policy_info;
+ struct xt_policy_elem *e;
+ int i;
+
+ if (info == NULL)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: no parameters given");
+
+ if (!(info->flags & (XT_POLICY_MATCH_IN | XT_POLICY_MATCH_OUT)))
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: neither --dir in nor --dir out specified");
+
+ if (info->flags & XT_POLICY_MATCH_NONE) {
+ if (info->flags & XT_POLICY_MATCH_STRICT)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: policy none but --strict given");
+
+ if (info->len != 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: policy none but policy given");
+ } else
+ info->len++; /* increase len by 1, no --next after last element */
+
+ if (!(info->flags & XT_POLICY_MATCH_STRICT) && info->len > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: multiple elements but no --strict");
+
+ for (i = 0; i < info->len; i++) {
+ e = &info->pol[i];
+
+ if (info->flags & XT_POLICY_MATCH_STRICT &&
+ !(e->match.reqid || e->match.spi || e->match.saddr ||
+ e->match.daddr || e->match.proto || e->match.mode))
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: empty policy element");
+
+ if ((e->match.saddr || e->match.daddr)
+ && ((e->mode == XT_POLICY_MODE_TUNNEL && e->invert.mode) ||
+ (e->mode == XT_POLICY_MODE_TRANSPORT && !e->invert.mode)))
+ xtables_error(PARAMETER_PROBLEM,
+ "policy match: --tunnel-src/--tunnel-dst "
+ "is only valid in tunnel mode");
+ }
+}
+
+static void print_mode(const char *prefix, u_int8_t mode, int numeric)
+{
+ printf("%smode ", prefix);
+
+ switch (mode) {
+ case XT_POLICY_MODE_TRANSPORT:
+ printf("transport ");
+ break;
+ case XT_POLICY_MODE_TUNNEL:
+ printf("tunnel ");
+ break;
+ default:
+ printf("??? ");
+ break;
+ }
+}
+
+static void print_proto(const char *prefix, u_int8_t proto, int numeric)
+{
+ struct protoent *p = NULL;
+
+ printf("%sproto ", prefix);
+ if (!numeric)
+ p = getprotobynumber(proto);
+ if (p != NULL)
+ printf("%s ", p->p_name);
+ else
+ printf("%u ", proto);
+}
+
+#define PRINT_INVERT(x) \
+do { \
+ if (x) \
+ printf("! "); \
+} while(0)
+
+static void print_entry(const char *prefix, const struct xt_policy_elem *e,
+ bool numeric, uint8_t family)
+{
+ if (e->match.reqid) {
+ PRINT_INVERT(e->invert.reqid);
+ printf("%sreqid %u ", prefix, e->reqid);
+ }
+ if (e->match.spi) {
+ PRINT_INVERT(e->invert.spi);
+ printf("%sspi 0x%x ", prefix, e->spi);
+ }
+ if (e->match.proto) {
+ PRINT_INVERT(e->invert.proto);
+ print_proto(prefix, e->proto, numeric);
+ }
+ if (e->match.mode) {
+ PRINT_INVERT(e->invert.mode);
+ print_mode(prefix, e->mode, numeric);
+ }
+ if (e->match.daddr) {
+ PRINT_INVERT(e->invert.daddr);
+ if (family == NFPROTO_IPV6)
+ printf("%stunnel-dst %s%s ", prefix,
+ xtables_ip6addr_to_numeric(&e->daddr.a6),
+ xtables_ip6mask_to_numeric(&e->dmask.a6));
+ else
+ printf("%stunnel-dst %s%s ", prefix,
+ xtables_ipaddr_to_numeric(&e->daddr.a4),
+ xtables_ipmask_to_numeric(&e->dmask.a4));
+ }
+ if (e->match.saddr) {
+ PRINT_INVERT(e->invert.saddr);
+ if (family == NFPROTO_IPV6)
+ printf("%stunnel-src %s%s ", prefix,
+ xtables_ip6addr_to_numeric(&e->saddr.a6),
+ xtables_ip6mask_to_numeric(&e->smask.a6));
+ else
+ printf("%stunnel-src %s%s ", prefix,
+ xtables_ipaddr_to_numeric(&e->saddr.a4),
+ xtables_ipmask_to_numeric(&e->smask.a4));
+ }
+}
+
+static void print_flags(char *prefix, const struct xt_policy_info *info)
+{
+ if (info->flags & XT_POLICY_MATCH_IN)
+ printf("%sdir in ", prefix);
+ else
+ printf("%sdir out ", prefix);
+
+ if (info->flags & XT_POLICY_MATCH_NONE)
+ printf("%spol none ", prefix);
+ else
+ printf("%spol ipsec ", prefix);
+
+ if (info->flags & XT_POLICY_MATCH_STRICT)
+ printf("%sstrict ", prefix);
+}
+
+static void policy4_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_policy_info *info = (void *)match->data;
+ unsigned int i;
+
+ printf("policy match ");
+ print_flags("", info);
+ for (i = 0; i < info->len; i++) {
+ if (info->len > 1)
+ printf("[%u] ", i);
+ print_entry("", &info->pol[i], numeric, NFPROTO_IPV4);
+ }
+}
+
+static void policy6_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_policy_info *info = (void *)match->data;
+ unsigned int i;
+
+ printf("policy match ");
+ print_flags("", info);
+ for (i = 0; i < info->len; i++) {
+ if (info->len > 1)
+ printf("[%u] ", i);
+ print_entry("", &info->pol[i], numeric, NFPROTO_IPV6);
+ }
+}
+
+static void policy4_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_policy_info *info = (void *)match->data;
+ unsigned int i;
+
+ print_flags("--", info);
+ for (i = 0; i < info->len; i++) {
+ print_entry("--", &info->pol[i], false, NFPROTO_IPV4);
+ if (i + 1 < info->len)
+ printf("--next ");
+ }
+}
+
+static void policy6_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_policy_info *info = (void *)match->data;
+ unsigned int i;
+
+ print_flags("--", info);
+ for (i = 0; i < info->len; i++) {
+ print_entry("--", &info->pol[i], false, NFPROTO_IPV6);
+ if (i + 1 < info->len)
+ printf("--next ");
+ }
+}
+
+static struct xtables_match policy_mt_reg[] = {
+ {
+ .name = "policy",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(sizeof(struct xt_policy_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)),
+ .help = policy_help,
+ .parse = policy4_parse,
+ .final_check = policy_check,
+ .print = policy4_print,
+ .save = policy4_save,
+ .extra_opts = policy_opts,
+ },
+ {
+ .name = "policy",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV6,
+ .size = XT_ALIGN(sizeof(struct xt_policy_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_policy_info)),
+ .help = policy_help,
+ .parse = policy6_parse,
+ .final_check = policy_check,
+ .print = policy6_print,
+ .save = policy6_save,
+ .extra_opts = policy_opts,
+ },
+};
+
+void libxt_policy_init(void)
+{
+ xtables_register_matches(policy_mt_reg, ARRAY_SIZE(policy_mt_reg));
+}
diff --git a/extensions/libip6t_policy.man b/extensions/libxt_policy.man
index eed163e..3500025 100644
--- a/extensions/libip6t_policy.man
+++ b/extensions/libxt_policy.man
@@ -1,6 +1,6 @@
This modules matches the policy used by IPsec for handling a packet.
.TP
-.BI "--dir " "in|out"
+\fB\-\-dir\fP {\fBin\fP|\fBout\fP}
Used to select whether to match the policy used for decapsulation or the
policy that will be used for encapsulation.
.B in
@@ -12,37 +12,37 @@ is valid in the
.B POSTROUTING, OUTPUT and FORWARD
chains.
.TP
-.BI "--pol " "none|ipsec"
+\fB\-\-pol\fP {\fBnone\fP|\fBipsec\fP}
Matches if the packet is subject to IPsec processing.
.TP
-.BI "--strict"
+\fB\-\-strict\fP
Selects whether to match the exact policy or match if any rule of
the policy matches the given policy.
.TP
-.BI "--reqid " "id"
+[\fB!\fP] \fB\-\-reqid\fP \fIid\fP
Matches the reqid of the policy rule. The reqid can be specified with
.B setkey(8)
using
.B unique:id
as level.
.TP
-.BI "--spi " "spi"
+[\fB!\fP] \fB\-\-spi\fP \fIspi\fP
Matches the SPI of the SA.
.TP
-.BI "--proto " "ah|esp|ipcomp"
+[\fB!\fP] \fB\-\-proto\fP {\fBah\fP|\fBesp\fP|\fBipcomp\fP}
Matches the encapsulation protocol.
.TP
-.BI "--mode " "tunnel|transport"
+[\fB!\fP] \fB\-\-mode\fP {\fBtunnel\fP|\fBtransport\fP}
Matches the encapsulation mode.
.TP
-.BI "--tunnel-src " "addr[/mask]"
+[\fB!\fP] \fB\-\-tunnel\-src\fP \fIaddr\fP[\fB/\fP\fImask\fP]
Matches the source end-point address of a tunnel mode SA.
-Only valid with --mode tunnel.
+Only valid with \fB\-\-mode tunnel\fP.
.TP
-.BI "--tunnel-dst " "addr[/mask]"
+[\fB!\fP] \fB\-\-tunnel\-dst\fP \fIaddr\fP[\fB/\fP\fImask\fP]
Matches the destination end-point address of a tunnel mode SA.
-Only valid with --mode tunnel.
+Only valid with \fB\-\-mode tunnel\fP.
.TP
-.BI "--next"
+\fB\-\-next\fP
Start the next element in the policy specification. Can only be used with
---strict
+\fB\-\-strict\fP.
diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c
new file mode 100644
index 0000000..03dbf21
--- /dev/null
+++ b/extensions/libxt_quota.c
@@ -0,0 +1,92 @@
+/*
+ * Shared library add-on to iptables to add quota support
+ *
+ * Sam Johnston <samj@samj.net>
+ */
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+
+#include <linux/netfilter/xt_quota.h>
+
+static const struct option quota_opts[] = {
+ {"quota", 1, NULL, '1'},
+ { .name = NULL }
+};
+
+static void quota_help(void)
+{
+ printf("quota match options:\n"
+ " --quota quota quota (bytes)\n");
+}
+
+static void
+quota_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_quota_info *q = (const void *)match->data;
+ printf("quota: %llu bytes", (unsigned long long) q->quota);
+}
+
+static void
+quota_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_quota_info *q = (const void *)match->data;
+ printf("--quota %llu ", (unsigned long long) q->quota);
+}
+
+/* parse quota option */
+static int
+parse_quota(const char *s, u_int64_t * quota)
+{
+ *quota = strtoull(s, NULL, 10);
+
+#ifdef DEBUG_XT_QUOTA
+ printf("Quota: %llu\n", *quota);
+#endif
+
+ if (*quota == UINT64_MAX)
+ xtables_error(PARAMETER_PROBLEM, "quota invalid: '%s'\n", s);
+ else
+ return 1;
+}
+
+static int
+quota_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_quota_info *info = (struct xt_quota_info *) (*match)->data;
+
+ switch (c) {
+ case '1':
+ if (xtables_check_inverse(optarg, &invert, NULL, 0, argv))
+ xtables_error(PARAMETER_PROBLEM, "quota: unexpected '!'");
+ if (!parse_quota(optarg, &info->quota))
+ xtables_error(PARAMETER_PROBLEM,
+ "bad quota: '%s'", optarg);
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static struct xtables_match quota_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "quota",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof (struct xt_quota_info)),
+ .userspacesize = offsetof(struct xt_quota_info, quota),
+ .help = quota_help,
+ .parse = quota_parse,
+ .print = quota_print,
+ .save = quota_save,
+ .extra_opts = quota_opts,
+};
+
+void libxt_quota_init(void)
+{
+ xtables_register_match(&quota_match);
+}
diff --git a/extensions/libipt_quota.man b/extensions/libxt_quota.man
index 8a07ec0..f8bf77b 100644
--- a/extensions/libipt_quota.man
+++ b/extensions/libxt_quota.man
@@ -1,7 +1,6 @@
Implements network quotas by decrementing a byte counter with each
packet.
.TP
-.BI "--quota " "bytes"
+\fB\-\-quota\fP \fIbytes\fP
The quota in bytes.
.P
-KNOWN BUGS: this does not work on SMP systems.
diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c
new file mode 100644
index 0000000..651f1da
--- /dev/null
+++ b/extensions/libxt_rateest.c
@@ -0,0 +1,451 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_rateest.h>
+
+/* Ugly hack to pass info to final_check function. We should fix the API */
+static struct xt_rateest_match_info *rateest_info;
+
+static void rateest_help(void)
+{
+ printf(
+"rateest match options:\n"
+" --rateest1 name Rate estimator name\n"
+" --rateest2 name Rate estimator name\n"
+" --rateest-delta Compare difference(s) to given rate(s)\n"
+" --rateest-bps1 [bps] Compare bps\n"
+" --rateest-pps1 [pps] Compare pps\n"
+" --rateest-bps2 [bps] Compare bps\n"
+" --rateest-pps2 [pps] Compare pps\n"
+" [!] --rateest-lt Match if rate is less than given rate/estimator\n"
+" [!] --rateest-gt Match if rate is greater than given rate/estimator\n"
+" [!] --rateest-eq Match if rate is equal to given rate/estimator\n");
+}
+
+enum rateest_options {
+ OPT_RATEEST1,
+ OPT_RATEEST2,
+ OPT_RATEEST_BPS1,
+ OPT_RATEEST_PPS1,
+ OPT_RATEEST_BPS2,
+ OPT_RATEEST_PPS2,
+ OPT_RATEEST_DELTA,
+ OPT_RATEEST_LT,
+ OPT_RATEEST_GT,
+ OPT_RATEEST_EQ,
+};
+
+static const struct option rateest_opts[] = {
+ { "rateest1", 1, NULL, OPT_RATEEST1 },
+ { "rateest", 1, NULL, OPT_RATEEST1 }, /* alias for absolute mode */
+ { "rateest2", 1, NULL, OPT_RATEEST2 },
+ { "rateest-bps1", 0, NULL, OPT_RATEEST_BPS1 },
+ { "rateest-pps1", 0, NULL, OPT_RATEEST_PPS1 },
+ { "rateest-bps2", 0, NULL, OPT_RATEEST_BPS2 },
+ { "rateest-pps2", 0, NULL, OPT_RATEEST_PPS2 },
+ { "rateest-bps", 0, NULL, OPT_RATEEST_BPS2 }, /* alias for absolute mode */
+ { "rateest-pps", 0, NULL, OPT_RATEEST_PPS2 }, /* alias for absolute mode */
+ { "rateest-delta", 0, NULL, OPT_RATEEST_DELTA },
+ { "rateest-lt", 0, NULL, OPT_RATEEST_LT },
+ { "rateest-gt", 0, NULL, OPT_RATEEST_GT },
+ { "rateest-eq", 0, NULL, OPT_RATEEST_EQ },
+ { .name = NULL }
+};
+
+/* Copied from iproute. See http://physics.nist.gov/cuu/Units/binary.html */
+static const struct rate_suffix {
+ const char *name;
+ double scale;
+} suffixes[] = {
+ { "bit", 1. },
+ { "Kibit", 1024. },
+ { "kbit", 1000. },
+ { "mibit", 1024.*1024. },
+ { "mbit", 1000000. },
+ { "gibit", 1024.*1024.*1024. },
+ { "gbit", 1000000000. },
+ { "tibit", 1024.*1024.*1024.*1024. },
+ { "tbit", 1000000000000. },
+ { "Bps", 8. },
+ { "KiBps", 8.*1024. },
+ { "KBps", 8000. },
+ { "MiBps", 8.*1024*1024. },
+ { "MBps", 8000000. },
+ { "GiBps", 8.*1024.*1024.*1024. },
+ { "GBps", 8000000000. },
+ { "TiBps", 8.*1024.*1024.*1024.*1024. },
+ { "TBps", 8000000000000. },
+ { .name = NULL }
+};
+
+static int
+rateest_get_rate(u_int32_t *rate, const char *str)
+{
+ char *p;
+ double bps = strtod(str, &p);
+ const struct rate_suffix *s;
+
+ if (p == str)
+ return -1;
+
+ if (*p == '\0') {
+ *rate = bps / 8.; /* assume bytes/sec */
+ return 0;
+ }
+
+ for (s = suffixes; s->name; ++s) {
+ if (strcasecmp(s->name, p) == 0) {
+ *rate = (bps * s->scale) / 8.;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int
+rateest_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_rateest_match_info *info = (void *)(*match)->data;
+ unsigned int val;
+
+ rateest_info = info;
+
+ switch (c) {
+ case OPT_RATEEST1:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest1 twice");
+ *flags |= 1 << c;
+
+ strncpy(info->name1, optarg, sizeof(info->name1) - 1);
+ break;
+
+ case OPT_RATEEST2:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest2 twice");
+ *flags |= 1 << c;
+
+ strncpy(info->name2, optarg, sizeof(info->name2) - 1);
+ info->flags |= XT_RATEEST_MATCH_REL;
+ break;
+
+ case OPT_RATEEST_BPS1:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest-bps can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest-bps1 twice");
+ *flags |= 1 << c;
+
+ info->flags |= XT_RATEEST_MATCH_BPS;
+
+ /* The rate is optional and only required in absolute mode */
+ if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
+ break;
+
+ if (rateest_get_rate(&info->bps1, argv[optind]) < 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: could not parse rate `%s'",
+ argv[optind]);
+ optind++;
+ break;
+
+ case OPT_RATEEST_PPS1:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest-pps can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest-pps1 twice");
+ *flags |= 1 << c;
+
+ info->flags |= XT_RATEEST_MATCH_PPS;
+
+ /* The rate is optional and only required in absolute mode */
+ if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
+ break;
+
+ if (!xtables_strtoui(argv[optind], NULL, &val, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: could not parse pps `%s'",
+ argv[optind]);
+ info->pps1 = val;
+ optind++;
+ break;
+
+ case OPT_RATEEST_BPS2:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest-bps can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest-bps2 twice");
+ *flags |= 1 << c;
+
+ info->flags |= XT_RATEEST_MATCH_BPS;
+
+ /* The rate is optional and only required in absolute mode */
+ if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
+ break;
+
+ if (rateest_get_rate(&info->bps2, argv[optind]) < 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: could not parse rate `%s'",
+ argv[optind]);
+ optind++;
+ break;
+
+ case OPT_RATEEST_PPS2:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest-pps can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest-pps2 twice");
+ *flags |= 1 << c;
+
+ info->flags |= XT_RATEEST_MATCH_PPS;
+
+ /* The rate is optional and only required in absolute mode */
+ if (!argv[optind] || *argv[optind] == '-' || *argv[optind] == '!')
+ break;
+
+ if (!xtables_strtoui(argv[optind], NULL, &val, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: could not parse pps `%s'",
+ argv[optind]);
+ info->pps2 = val;
+ optind++;
+ break;
+
+ case OPT_RATEEST_DELTA:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: rateest-delta can't be inverted");
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify --rateest-delta twice");
+ *flags |= 1 << c;
+
+ info->flags |= XT_RATEEST_MATCH_DELTA;
+ break;
+
+ case OPT_RATEEST_EQ:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify lt/gt/eq twice");
+ *flags |= 1 << c;
+
+ info->mode = XT_RATEEST_MATCH_EQ;
+ if (invert)
+ info->flags |= XT_RATEEST_MATCH_INVERT;
+ break;
+
+ case OPT_RATEEST_LT:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify lt/gt/eq twice");
+ *flags |= 1 << c;
+
+ info->mode = XT_RATEEST_MATCH_LT;
+ if (invert)
+ info->flags |= XT_RATEEST_MATCH_INVERT;
+ break;
+
+ case OPT_RATEEST_GT:
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ if (*flags & (1 << c))
+ xtables_error(PARAMETER_PROBLEM,
+ "rateest: can't specify lt/gt/eq twice");
+ *flags |= 1 << c;
+
+ info->mode = XT_RATEEST_MATCH_GT;
+ if (invert)
+ info->flags |= XT_RATEEST_MATCH_INVERT;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+rateest_final_check(unsigned int flags)
+{
+ struct xt_rateest_match_info *info = rateest_info;
+
+ if (info == NULL)
+ xtables_error(PARAMETER_PROBLEM, "rateest match: "
+ "you need to specify some flags");
+ if (!(info->flags & XT_RATEEST_MATCH_REL))
+ info->flags |= XT_RATEEST_MATCH_ABS;
+}
+
+static void
+rateest_print_rate(u_int32_t rate, int numeric)
+{
+ double tmp = (double)rate*8;
+
+ if (numeric)
+ printf("%u ", rate);
+ else if (tmp >= 1000.0*1000000.0)
+ printf("%.0fMbit ", tmp/1000000.0);
+ else if (tmp >= 1000.0 * 1000.0)
+ printf("%.0fKbit ", tmp/1000.0);
+ else
+ printf("%.0fbit ", tmp);
+}
+
+static void
+rateest_print_mode(const struct xt_rateest_match_info *info,
+ const char *prefix)
+{
+ if (info->flags & XT_RATEEST_MATCH_INVERT)
+ printf("! ");
+
+ switch (info->mode) {
+ case XT_RATEEST_MATCH_EQ:
+ printf("%seq ", prefix);
+ break;
+ case XT_RATEEST_MATCH_LT:
+ printf("%slt ", prefix);
+ break;
+ case XT_RATEEST_MATCH_GT:
+ printf("%sgt ", prefix);
+ break;
+ default:
+ exit(1);
+ }
+}
+
+static void
+rateest_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_rateest_match_info *info = (const void *)match->data;
+
+ printf("rateest match ");
+
+ printf("%s ", info->name1);
+ if (info->flags & XT_RATEEST_MATCH_DELTA)
+ printf("delta ");
+
+ if (info->flags & XT_RATEEST_MATCH_BPS) {
+ printf("bps ");
+ if (info->flags & XT_RATEEST_MATCH_DELTA)
+ rateest_print_rate(info->bps1, numeric);
+ if (info->flags & XT_RATEEST_MATCH_ABS) {
+ rateest_print_mode(info, "");
+ rateest_print_rate(info->bps2, numeric);
+ }
+ }
+ if (info->flags & XT_RATEEST_MATCH_PPS) {
+ printf("pps ");
+ if (info->flags & XT_RATEEST_MATCH_DELTA)
+ printf("%u ", info->pps1);
+ if (info->flags & XT_RATEEST_MATCH_ABS) {
+ rateest_print_mode(info, "");
+ printf("%u ", info->pps2);
+ }
+ }
+
+ if (info->flags & XT_RATEEST_MATCH_REL) {
+ rateest_print_mode(info, "");
+
+ printf("%s ", info->name2);
+ if (info->flags & XT_RATEEST_MATCH_DELTA)
+ printf("delta ");
+
+ if (info->flags & XT_RATEEST_MATCH_BPS) {
+ printf("bps ");
+ if (info->flags & XT_RATEEST_MATCH_DELTA)
+ rateest_print_rate(info->bps2, numeric);
+ }
+ if (info->flags & XT_RATEEST_MATCH_PPS) {
+ printf("pps ");
+ if (info->flags & XT_RATEEST_MATCH_DELTA)
+ printf("%u ", info->pps2);
+ }
+ }
+}
+
+static void
+rateest_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_rateest_match_info *info = (const void *)match->data;
+
+ if (info->flags & XT_RATEEST_MATCH_REL) {
+ printf("--rateest1 %s ", info->name1);
+ if (info->flags & XT_RATEEST_MATCH_BPS)
+ printf("--rateest-bps ");
+ if (info->flags & XT_RATEEST_MATCH_PPS)
+ printf("--rateest-pps ");
+ rateest_print_mode(info, "--rateest-");
+ printf("--rateest2 %s ", info->name2);
+ } else {
+ printf("--rateest %s ", info->name1);
+ if (info->flags & XT_RATEEST_MATCH_BPS) {
+ printf("--rateest-bps ");
+ rateest_print_mode(info, "--rateest-");
+ rateest_print_rate(info->bps2, 0);
+ }
+ if (info->flags & XT_RATEEST_MATCH_PPS) {
+ printf("--rateest-pps ");
+ rateest_print_mode(info, "--rateest-");
+ printf("%u ", info->pps2);
+ }
+ }
+}
+
+static struct xtables_match rateest_mt_reg = {
+ .family = NFPROTO_UNSPEC,
+ .name = "rateest",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_rateest_match_info)),
+ .userspacesize = XT_ALIGN(offsetof(struct xt_rateest_match_info, est1)),
+ .help = rateest_help,
+ .parse = rateest_parse,
+ .final_check = rateest_final_check,
+ .print = rateest_print,
+ .save = rateest_save,
+ .extra_opts = rateest_opts,
+};
+
+void libxt_rateest_init(void)
+{
+ xtables_register_match(&rateest_mt_reg);
+}
diff --git a/extensions/libxt_rateest.man b/extensions/libxt_rateest.man
new file mode 100644
index 0000000..24c0673
--- /dev/null
+++ b/extensions/libxt_rateest.man
@@ -0,0 +1,55 @@
+The rate estimator can match on estimated rates as collected by the RATEEST
+target. It supports matching on absolute bps/pps values, comparing two rate
+estimators and matching on the difference between two rate estimators.
+.TP
+\fB\-\-rateest1\fP \fIname\fP
+Name of the first rate estimator.
+.TP
+\fB\-\-rateest2\fP \fIname\fP
+Name of the second rate estimator (if difference is to be calculated).
+.TP
+\fB\-\-rateest\-delta\fP
+Compare difference(s) to given rate(s)
+.TP
+\fB\-\-rateest1\-bps\fP \fIvalue\fP
+.TP
+\fB\-\-rateest2\-bps\fP \fIvalue\fP
+Compare bytes per second.
+.TP
+\fB\-\-rateest1\-pps\fP \fIvalue\fP
+.TP
+\fB\-\-rateest2\-pps\fP \fIvalue\fP
+Compare packets per second.
+.TP
+[\fB!\fP] \fB\-\-rateest\-lt\fP
+Match if rate is less than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-gt\fP
+Match if rate is greater than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-eq\fP
+Match if rate is equal to given rate/estimator.
+.PP
+Example: This is what can be used to route outgoing data connections from an
+FTP server over two lines based on the available bandwidth at the time the data
+connection was started:
+.PP
+# Estimate outgoing rates
+.PP
+iptables \-t mangle \-A POSTROUTING \-o eth0 \-j RATEEST \-\-rateest\-name eth0
+\-\-rateest\-interval 250ms \-\-rateest\-ewma 0.5s
+.PP
+iptables \-t mangle \-A POSTROUTING \-o ppp0 \-j RATEEST \-\-rateest\-name ppp0
+\-\-rateest\-interval 250ms \-\-rateest\-ewma 0.5s
+.PP
+# Mark based on available bandwidth
+.PP
+iptables \-t mangle \-A balance \-m conntrack \-\-ctstate NEW \-m helper \-\-helper ftp
+\-m rateest \-\-rateest\-delta \-\-rateest1 eth0 \-\-rateest\-bps1 2.5mbit \-\-rateest\-gt
+\-\-rateest2 ppp0 \-\-rateest\-bps2 2mbit \-j CONNMARK \-\-set\-mark 1
+.PP
+iptables \-t mangle \-A balance \-m conntrack \-\-ctstate NEW \-m helper \-\-helper ftp
+\-m rateest \-\-rateest\-delta \-\-rateest1 ppp0 \-\-rateest\-bps1 2mbit \-\-rateest\-gt
+\-\-rateest2 eth0 \-\-rateest\-bps2 2.5mbit \-j CONNMARK \-\-set\-mark 2
+.PP
+iptables \-t mangle \-A balance \-j CONNMARK \-\-restore\-mark
diff --git a/extensions/libxt_recent.c b/extensions/libxt_recent.c
new file mode 100644
index 0000000..9cf402e
--- /dev/null
+++ b/extensions/libxt_recent.c
@@ -0,0 +1,233 @@
+/* Shared library add-on to iptables to add recent matching support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_recent.h>
+
+static const struct option recent_opts[] = {
+ { .name = "set", .has_arg = 0, .val = 201 },
+ { .name = "rcheck", .has_arg = 0, .val = 202 },
+ { .name = "update", .has_arg = 0, .val = 203 },
+ { .name = "seconds", .has_arg = 1, .val = 204 },
+ { .name = "hitcount", .has_arg = 1, .val = 205 },
+ { .name = "remove", .has_arg = 0, .val = 206 },
+ { .name = "rttl", .has_arg = 0, .val = 207 },
+ { .name = "name", .has_arg = 1, .val = 208 },
+ { .name = "rsource", .has_arg = 0, .val = 209 },
+ { .name = "rdest", .has_arg = 0, .val = 210 },
+ { .name = NULL }
+};
+
+static void recent_help(void)
+{
+ printf(
+"recent match options:\n"
+"[!] --set Add source address to list, always matches.\n"
+"[!] --rcheck Match if source address in list.\n"
+"[!] --update Match if source address in list, also update last-seen time.\n"
+"[!] --remove Match if source address in list, also removes that address from list.\n"
+" --seconds seconds For check and update commands above.\n"
+" Specifies that the match will only occur if source address last seen within\n"
+" the last 'seconds' seconds.\n"
+" --hitcount hits For check and update commands above.\n"
+" Specifies that the match will only occur if source address seen hits times.\n"
+" May be used in conjunction with the seconds option.\n"
+" --rttl For check and update commands above.\n"
+" Specifies that the match will only occur if the source address and the TTL\n"
+" match between this packet and the one which was set.\n"
+" Useful if you have problems with people spoofing their source address in order\n"
+" to DoS you via this module.\n"
+" --name name Name of the recent list to be used. DEFAULT used if none given.\n"
+" --rsource Match/Save the source address of each packet in the recent list table (default).\n"
+" --rdest Match/Save the destination address of each packet in the recent list table.\n"
+"xt_recent by: Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n");
+}
+
+static void recent_init(struct xt_entry_match *match)
+{
+ struct xt_recent_mtinfo *info = (void *)(match)->data;
+
+ strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
+ /* even though XT_RECENT_NAME_LEN is currently defined as 200,
+ * better be safe, than sorry */
+ info->name[XT_RECENT_NAME_LEN-1] = '\0';
+ info->side = XT_RECENT_SOURCE;
+}
+
+#define RECENT_CMDS \
+ (XT_RECENT_SET | XT_RECENT_CHECK | \
+ XT_RECENT_UPDATE | XT_RECENT_REMOVE)
+
+static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_recent_mtinfo *info = (void *)(*match)->data;
+
+ switch (c) {
+ case 201:
+ if (*flags & RECENT_CMDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: only one of `--set', `--rcheck' "
+ "`--update' or `--remove' may be set");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->check_set |= XT_RECENT_SET;
+ if (invert) info->invert = 1;
+ *flags |= XT_RECENT_SET;
+ break;
+
+ case 202:
+ if (*flags & RECENT_CMDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: only one of `--set', `--rcheck' "
+ "`--update' or `--remove' may be set");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->check_set |= XT_RECENT_CHECK;
+ if(invert) info->invert = 1;
+ *flags |= XT_RECENT_CHECK;
+ break;
+
+ case 203:
+ if (*flags & RECENT_CMDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: only one of `--set', `--rcheck' "
+ "`--update' or `--remove' may be set");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->check_set |= XT_RECENT_UPDATE;
+ if (invert) info->invert = 1;
+ *flags |= XT_RECENT_UPDATE;
+ break;
+
+ case 204:
+ info->seconds = atoi(optarg);
+ break;
+
+ case 205:
+ info->hit_count = atoi(optarg);
+ break;
+
+ case 206:
+ if (*flags & RECENT_CMDS)
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: only one of `--set', `--rcheck' "
+ "`--update' or `--remove' may be set");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ info->check_set |= XT_RECENT_REMOVE;
+ if (invert) info->invert = 1;
+ *flags |= XT_RECENT_REMOVE;
+ break;
+
+ case 207:
+ info->check_set |= XT_RECENT_TTL;
+ *flags |= XT_RECENT_TTL;
+ break;
+
+ case 208:
+ strncpy(info->name,optarg, XT_RECENT_NAME_LEN);
+ info->name[XT_RECENT_NAME_LEN-1] = '\0';
+ break;
+
+ case 209:
+ info->side = XT_RECENT_SOURCE;
+ break;
+
+ case 210:
+ info->side = XT_RECENT_DEST;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void recent_check(unsigned int flags)
+{
+ if (!(flags & RECENT_CMDS))
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: you must specify one of `--set', `--rcheck' "
+ "`--update' or `--remove'");
+ if ((flags & XT_RECENT_TTL) &&
+ (flags & (XT_RECENT_SET | XT_RECENT_REMOVE)))
+ xtables_error(PARAMETER_PROBLEM,
+ "recent: --rttl may only be used with --rcheck or "
+ "--update");
+}
+
+static void recent_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_recent_mtinfo *info = (const void *)match->data;
+
+ if (info->invert)
+ fputc('!', stdout);
+
+ printf("recent: ");
+ if (info->check_set & XT_RECENT_SET)
+ printf("SET ");
+ if (info->check_set & XT_RECENT_CHECK)
+ printf("CHECK ");
+ if (info->check_set & XT_RECENT_UPDATE)
+ printf("UPDATE ");
+ if (info->check_set & XT_RECENT_REMOVE)
+ printf("REMOVE ");
+ if(info->seconds) printf("seconds: %d ",info->seconds);
+ if(info->hit_count) printf("hit_count: %d ",info->hit_count);
+ if (info->check_set & XT_RECENT_TTL)
+ printf("TTL-Match ");
+ if(info->name) printf("name: %s ",info->name);
+ if (info->side == XT_RECENT_SOURCE)
+ printf("side: source ");
+ if (info->side == XT_RECENT_DEST)
+ printf("side: dest");
+}
+
+static void recent_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_recent_mtinfo *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+
+ if (info->check_set & XT_RECENT_SET)
+ printf("--set ");
+ if (info->check_set & XT_RECENT_CHECK)
+ printf("--rcheck ");
+ if (info->check_set & XT_RECENT_UPDATE)
+ printf("--update ");
+ if (info->check_set & XT_RECENT_REMOVE)
+ printf("--remove ");
+ if(info->seconds) printf("--seconds %d ",info->seconds);
+ if(info->hit_count) printf("--hitcount %d ",info->hit_count);
+ if (info->check_set & XT_RECENT_TTL)
+ printf("--rttl ");
+ if(info->name) printf("--name %s ",info->name);
+ if (info->side == XT_RECENT_SOURCE)
+ printf("--rsource ");
+ if (info->side == XT_RECENT_DEST)
+ printf("--rdest ");
+}
+
+static struct xtables_match recent_mt_reg = {
+ .name = "recent",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
+ .help = recent_help,
+ .init = recent_init,
+ .parse = recent_parse,
+ .final_check = recent_check,
+ .print = recent_print,
+ .save = recent_save,
+ .extra_opts = recent_opts,
+};
+
+void libxt_recent_init(void)
+{
+ xtables_register_match(&recent_mt_reg);
+}
diff --git a/extensions/libxt_recent.man b/extensions/libxt_recent.man
new file mode 100644
index 0000000..532c328
--- /dev/null
+++ b/extensions/libxt_recent.man
@@ -0,0 +1,104 @@
+Allows you to dynamically create a list of IP addresses and then match against
+that list in a few different ways.
+.PP
+For example, you can create a "badguy" list out of people attempting to connect
+to port 139 on your firewall and then DROP all future packets from them without
+considering them.
+.PP
+\fB\-\-set\fP, \fB\-\-rcheck\fP, \fB\-\-update\fP and \fB\-\-remove\fP are
+mutually exclusive.
+.TP
+\fB\-\-name\fP \fIname\fP
+Specify the list to use for the commands. If no name is given then
+\fBDEFAULT\fR will be used.
+.TP
+[\fB!\fR] \fB\-\-set\fP
+This will add the source address of the packet to the list. If the source
+address is already in the list, this will update the existing entry. This will
+always return success (or failure if \fB!\fR is passed in).
+.TP
+\fB\-\-rsource\fP
+Match/save the source address of each packet in the recent list table. This
+is the default.
+.TP
+\fB\-\-rdest\fP
+Match/save the destination address of each packet in the recent list table.
+.TP
+[\fB!\fR] \fB\-\-rcheck\fP
+Check if the source address of the packet is currently in the list.
+.TP
+[\fB!\fR] \fB\-\-update\fP
+Like \fB\-\-rcheck\fP, except it will update the "last seen" timestamp if it
+matches.
+.TP
+[\fB!\fR] \fB\-\-remove\fP
+Check if the source address of the packet is currently in the list and if so
+that address will be removed from the list and the rule will return true. If
+the address is not found, false is returned.
+.TP
+\fB\-\-seconds\fP \fIseconds\fP
+This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and was seen within the last given number of seconds.
+.TP
+\fB\-\-hitcount\fP \fIhits\fP
+This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and packets had been received greater than or equal to
+the given value. This option may be used along with \fB\-\-seconds\fP to create
+an even narrower match requiring a certain number of hits within a specific
+time frame. The maximum value for the hitcount parameter is given by the
+"ip_pkt_list_tot" parameter of the xt_recent kernel module. Exceeding this
+value on the command line will cause the rule to be rejected.
+.TP
+\fB\-\-rttl\fP
+This option may only be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and the TTL of the current packet matches that of the
+packet which hit the \fB\-\-set\fP rule. This may be useful if you have problems
+with people faking their source address in order to DoS you via this module by
+disallowing others access to your site by sending bogus packets to you.
+.PP
+Examples:
+.IP
+iptables \-A FORWARD \-m recent \-\-name badguy \-\-rcheck \-\-seconds 60 \-j DROP
+.IP
+iptables \-A FORWARD \-p tcp \-i eth0 \-\-dport 139 \-m recent \-\-name badguy \-\-set \-j DROP
+.PP
+Steve's ipt_recent website (http://snowman.net/projects/ipt_recent/) also has
+some examples of usage.
+.PP
+\fB/proc/net/xt_recent/*\fR are the current lists of addresses and information
+about each entry of each list.
+.PP
+Each file in \fB/proc/net/xt_recent/\fR can be read from to see the current
+list or written two using the following commands to modify the list:
+.TP
+\fBecho +\fR\fIaddr\fR\fB >/proc/net/xt_recent/DEFAULT\fR
+to add \fIaddr\fR to the DEFAULT list
+.TP
+\fBecho \-\fP\fIaddr\fP\fB >/proc/net/xt_recent/DEFAULT\fP
+to remove \fIaddr\fR from the DEFAULT list
+.TP
+\fBecho / >/proc/net/xt_recent/DEFAULT\fR
+to flush the DEFAULT list (remove all entries).
+.PP
+The module itself accepts parameters, defaults shown:
+.TP
+\fBip_list_tot\fR=\fI100\fR
+Number of addresses remembered per table.
+.TP
+\fBip_pkt_list_tot\fR=\fI20\fR
+Number of packets per address remembered.
+.TP
+\fBip_list_hash_size\fR=\fI0\fR
+Hash table size. 0 means to calculate it based on ip_list_tot, default: 512.
+.TP
+\fBip_list_perms\fR=\fI0644\fR
+Permissions for /proc/net/xt_recent/* files.
+.TP
+\fBip_list_uid\fR=\fI0\fR
+Numerical UID for ownership of /proc/net/xt_recent/* files.
+.TP
+\fBip_list_gid\fR=\fI0\fR
+Numerical GID for ownership of /proc/net/xt_recent/* files.
diff --git a/extensions/libip6t_sctp.c b/extensions/libxt_sctp.c
index aee7072..dffa1b0 100644
--- a/extensions/libip6t_sctp.c
+++ b/extensions/libxt_sctp.c
@@ -14,23 +14,11 @@
#include <netdb.h>
#include <ctype.h>
-#include <ip6tables.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-#endif
+#include <netinet/in.h>
+#include <xtables.h>
#include <linux/netfilter/xt_sctp.h>
-/* Some ZS!#@:$%*#$! has replaced the ELEMCOUNT macro in ipt_sctp.h with
- * ARRAY_SIZE without noticing that this file is used from userserspace,
- * and userspace doesn't have ARRAY_SIZE */
-
-#ifndef ELEMCOUNT
-#define ELEMCOUNT ARRAY_SIZE
-#endif
-
#if 0
#define DEBUGP(format, first...) printf(format, ##first)
#define static
@@ -41,10 +29,7 @@
static void
print_chunk(u_int32_t chunknum, int numeric);
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m,
- unsigned int *nfcache)
+static void sctp_init(struct xt_entry_match *m)
{
int i;
struct xt_sctp_info *einfo = (struct xt_sctp_info *)m->data;
@@ -56,27 +41,26 @@ init(struct ip6t_entry_match *m,
}
}
-static void help(void)
+static void sctp_help(void)
{
printf(
-"SCTP match v%s options\n"
-" --source-port [!] port[:port] match source port(s)\n"
+"sctp match options\n"
+"[!] --source-port port[:port] match source port(s)\n"
" --sport ...\n"
-" --destination-port [!] port[:port] match destination port(s)\n"
+"[!] --destination-port port[:port] match destination port(s)\n"
" --dport ...\n"
-" --chunk-types [!] (all|any|none) (chunktype[:flags])+ match if all, any or none of\n"
+"[!] --chunk-types (all|any|none) (chunktype[:flags])+ match if all, any or none of\n"
" chunktypes are present\n"
-"chunktypes - DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK ALL NONE\n",
- IPTABLES_VERSION);
+"chunktypes - DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK ALL NONE\n");
}
-static struct option opts[] = {
- { .name = "source-port", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "sport", .has_arg = 1, .flag = 0, .val = '1' },
- { .name = "destination-port", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "dport", .has_arg = 1, .flag = 0, .val = '2' },
- { .name = "chunk-types", .has_arg = 1, .flag = 0, .val = '3' },
- { .name = 0 }
+static const struct option sctp_opts[] = {
+ { .name = "source-port", .has_arg = 1, .val = '1' },
+ { .name = "sport", .has_arg = 1, .val = '1' },
+ { .name = "destination-port", .has_arg = 1, .val = '2' },
+ { .name = "dport", .has_arg = 1, .val = '2' },
+ { .name = "chunk-types", .has_arg = 1, .val = '3' },
+ { .name = NULL }
};
static void
@@ -89,17 +73,17 @@ parse_sctp_ports(const char *portstring,
buffer = strdup(portstring);
DEBUGP("%s\n", portstring);
if ((cp = strchr(buffer, ':')) == NULL) {
- ports[0] = ports[1] = parse_port(buffer, "sctp");
+ ports[0] = ports[1] = xtables_parse_port(buffer, "sctp");
}
else {
*cp = '\0';
cp++;
- ports[0] = buffer[0] ? parse_port(buffer, "sctp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "sctp") : 0xFFFF;
+ ports[0] = buffer[0] ? xtables_parse_port(buffer, "sctp") : 0;
+ ports[1] = cp[0] ? xtables_parse_port(cp, "sctp") : 0xFFFF;
if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"invalid portrange (min > max)");
}
free(buffer);
@@ -112,7 +96,7 @@ struct sctp_chunk_names {
};
/*'ALL' and 'NONE' will be treated specially. */
-static struct sctp_chunk_names sctp_chunk_names[]
+static const struct sctp_chunk_names sctp_chunk_names[]
= { { .name = "DATA", .chunk_type = 0, .valid_flags = "-----UBE"},
{ .name = "INIT", .chunk_type = 1, .valid_flags = "--------"},
{ .name = "INIT_ACK", .chunk_type = 2, .valid_flags = "--------"},
@@ -128,8 +112,8 @@ static struct sctp_chunk_names sctp_chunk_names[]
{ .name = "ECN_ECNE", .chunk_type = 12, .valid_flags = "--------"},
{ .name = "ECN_CWR", .chunk_type = 13, .valid_flags = "--------"},
{ .name = "SHUTDOWN_COMPLETE", .chunk_type = 14, .valid_flags = "-------T"},
- { .name = "ASCONF", .chunk_type = 31, .valid_flags = "--------"},
- { .name = "ASCONF_ACK", .chunk_type = 30, .valid_flags = "--------"},
+ { .name = "ASCONF", .chunk_type = 193, .valid_flags = "--------"},
+ { .name = "ASCONF_ACK", .chunk_type = 128, .valid_flags = "--------"},
};
static void
@@ -155,9 +139,9 @@ save_chunk_flag_info(struct xt_sctp_flag_info *flag_info,
}
if (*flag_count == XT_NUM_SCTP_FLAGS) {
- exit_error (PARAMETER_PROBLEM,
+ xtables_error (PARAMETER_PROBLEM,
"Number of chunk types with flags exceeds currently allowed limit."
- "Increasing this limit involves changing XT_NUM_SCTP_FLAGS and"
+ "Increasing this limit involves changing IPT_NUM_SCTP_FLAGS and"
"recompiling both the kernel space and user space modules\n");
}
@@ -202,7 +186,7 @@ parse_sctp_chunk(struct xt_sctp_info *einfo,
*chunk_flags++ = 0;
}
- for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(sctp_chunk_names); ++i)
if (strcasecmp(sctp_chunk_names[i].name, ptr) == 0) {
DEBUGP("Chunk num %d\n", sctp_chunk_names[i].chunk_type);
SCTP_CHUNKMAP_SET(einfo->chunkmap,
@@ -210,9 +194,8 @@ parse_sctp_chunk(struct xt_sctp_info *einfo,
found = 1;
break;
}
- }
if (!found)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Unknown sctp chunk `%s'", ptr);
if (chunk_flags) {
@@ -230,7 +213,7 @@ parse_sctp_chunk(struct xt_sctp_info *einfo,
&(einfo->flag_count), i, bit,
isupper(chunk_flags[j]));
} else {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid flags for chunk type %d\n", i);
}
}
@@ -253,7 +236,7 @@ parse_sctp_chunks(struct xt_sctp_info *einfo,
} else if (!strcasecmp(match_type, "ONLY")) {
einfo->chunk_match_type = SCTP_CHUNK_MATCH_ONLY;
} else {
- exit_error (PARAMETER_PROBLEM,
+ xtables_error (PARAMETER_PROBLEM,
"Match type has to be one of \"ALL\", \"ANY\" or \"ONLY\"");
}
@@ -262,10 +245,8 @@ parse_sctp_chunks(struct xt_sctp_info *einfo,
}
static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ip6t_entry *entry,
- unsigned int *nfcache,
- struct ip6t_entry_match **match)
+sctp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
struct xt_sctp_info *einfo
= (struct xt_sctp_info *)(*match)->data;
@@ -273,11 +254,11 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
if (*flags & XT_SCTP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--source-port' allowed");
einfo->flags |= XT_SCTP_SRC_PORTS;
- check_inverse(optarg, &invert, &optind, 0);
- parse_sctp_ports(argv[optind-1], einfo->spts);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_sctp_ports(optarg, einfo->spts);
if (invert)
einfo->invflags |= XT_SCTP_SRC_PORTS;
*flags |= XT_SCTP_SRC_PORTS;
@@ -285,11 +266,11 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '2':
if (*flags & XT_SCTP_DEST_PORTS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--destination-port' allowed");
einfo->flags |= XT_SCTP_DEST_PORTS;
- check_inverse(optarg, &invert, &optind, 0);
- parse_sctp_ports(argv[optind-1], einfo->dpts);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_sctp_ports(optarg, einfo->dpts);
if (invert)
einfo->invflags |= XT_SCTP_DEST_PORTS;
*flags |= XT_SCTP_DEST_PORTS;
@@ -297,17 +278,17 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '3':
if (*flags & XT_SCTP_CHUNK_TYPES)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--chunk-types' allowed");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
if (!argv[optind]
|| argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"--chunk-types requires two args");
einfo->flags |= XT_SCTP_CHUNK_TYPES;
- parse_sctp_chunks(einfo, argv[optind-1], argv[optind]);
+ parse_sctp_chunks(einfo, optarg, argv[optind]);
if (invert)
einfo->invflags |= XT_SCTP_CHUNK_TYPES;
optind++;
@@ -320,11 +301,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-static void
-final_check(unsigned int flags)
-{
-}
-
static char *
port_to_service(int port)
{
@@ -400,20 +376,18 @@ print_chunk(u_int32_t chunknum, int numeric)
else {
int i;
- for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
+ for (i = 0; i < ARRAY_SIZE(sctp_chunk_names); ++i)
if (sctp_chunk_names[i].chunk_type == chunknum)
printf("%s", sctp_chunk_names[chunknum].name);
- }
}
}
static void
-print_chunks(u_int32_t chunk_match_type,
- const u_int32_t *chunkmap,
- const struct xt_sctp_flag_info *flag_info,
- int flag_count,
- int numeric)
+print_chunks(const struct xt_sctp_info *einfo, int numeric)
{
+ u_int32_t chunk_match_type = einfo->chunk_match_type;
+ const struct xt_sctp_flag_info *flag_info = einfo->flag_info;
+ int flag_count = einfo->flag_count;
int i, j;
int flag;
@@ -424,19 +398,19 @@ print_chunks(u_int32_t chunk_match_type,
default: printf("Never reach herer\n"); break;
}
- if (SCTP_CHUNKMAP_IS_CLEAR(chunkmap)) {
+ if (SCTP_CHUNKMAP_IS_CLEAR(einfo->chunkmap)) {
printf("NONE ");
goto out;
}
- if (SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)) {
+ if (SCTP_CHUNKMAP_IS_ALL_SET(einfo->chunkmap)) {
printf("ALL ");
goto out;
}
flag = 0;
for (i = 0; i < 256; i++) {
- if (SCTP_CHUNKMAP_IS_SET(chunkmap, i)) {
+ if (SCTP_CHUNKMAP_IS_SET(einfo->chunkmap, i)) {
if (flag)
printf(",");
flag = 1;
@@ -456,11 +430,8 @@ out:
return;
}
-/* Prints out the matchinfo. */
static void
-print(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match,
- int numeric)
+sctp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_sctp_info *einfo =
(const struct xt_sctp_info *)match->data;
@@ -485,15 +456,11 @@ print(const struct ip6t_ip6 *ip,
if (einfo->invflags & XT_SCTP_CHUNK_TYPES) {
printf("! ");
}
- print_chunks(einfo->chunk_match_type, einfo->chunkmap,
- einfo->flag_info, einfo->flag_count, numeric);
+ print_chunks(einfo, numeric);
}
}
-/* Saves the union xt_matchinfo in parsable form to stdout. */
-static void
-save(const struct ip6t_ip6 *ip,
- const struct ip6t_entry_match *match)
+static void sctp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_sctp_info *einfo =
(const struct xt_sctp_info *)match->data;
@@ -523,28 +490,25 @@ save(const struct ip6t_ip6 *ip,
printf("! ");
printf("--chunk-types ");
- print_chunks(einfo->chunk_match_type, einfo->chunkmap,
- einfo->flag_info, einfo->flag_count, 0);
+ print_chunks(einfo, 0);
}
}
-static
-struct ip6tables_match sctp
-= { .name = "sctp",
- .version = IPTABLES_VERSION,
- .size = IP6T_ALIGN(sizeof(struct xt_sctp_info)),
- .userspacesize = IP6T_ALIGN(sizeof(struct xt_sctp_info)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+static struct xtables_match sctp_match = {
+ .name = "sctp",
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_sctp_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_sctp_info)),
+ .help = sctp_help,
+ .init = sctp_init,
+ .parse = sctp_parse,
+ .print = sctp_print,
+ .save = sctp_save,
+ .extra_opts = sctp_opts,
};
-void _init(void)
+void libxt_sctp_init(void)
{
- register_match6(&sctp);
+ xtables_register_match(&sctp_match);
}
-
diff --git a/extensions/libipt_sctp.man b/extensions/libxt_sctp.man
index 97b467d..1ecf05c 100644
--- a/extensions/libipt_sctp.man
+++ b/extensions/libxt_sctp.man
@@ -1,9 +1,9 @@
.TP
-\fB--source-port\fR,\fB--sport \fR[\fB!\fR] \fIport\fR[\fB:\fIport\fR]
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
.TP
-\fB--destination-port\fR,\fB--dport \fR[\fB!\fR] \fIport\fR[\fB:\fIport\fR]
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
.TP
-\fB--chunk-types\fR [\fB!\fR] \fBall\fR|\fBany\fR|\fBonly \fIchunktype\fR[\fB:\fIflags\fR] [...]
+[\fB!\fP] \fB\-\-chunk\-types\fP {\fBall\fP|\fBany\fP|\fBonly\fP} \fIchunktype\fP[\fB:\fP\fIflags\fP] [...]
The flag letter in upper case indicates that the flag is to match if set,
in the lower case indicates to match if unset.
@@ -21,8 +21,8 @@ SHUTDOWN_COMPLETE T t
.P
Examples:
-iptables -A INPUT -p sctp --dport 80 -j DROP
+iptables \-A INPUT \-p sctp \-\-dport 80 \-j DROP
-iptables -A INPUT -p sctp --chunk-types any DATA,INIT -j DROP
+iptables \-A INPUT \-p sctp \-\-chunk\-types any DATA,INIT \-j DROP
-iptables -A INPUT -p sctp --chunk-types any DATA:Be -j ACCEPT
+iptables \-A INPUT \-p sctp \-\-chunk\-types any DATA:Be \-j ACCEPT
diff --git a/extensions/libxt_socket.c b/extensions/libxt_socket.c
new file mode 100644
index 0000000..340fbf6
--- /dev/null
+++ b/extensions/libxt_socket.c
@@ -0,0 +1,19 @@
+/*
+ * Shared library add-on to iptables to add early socket matching support.
+ *
+ * Copyright (C) 2007 BalaBit IT Ltd.
+ */
+#include <xtables.h>
+
+static struct xtables_match socket_mt_reg = {
+ .name = "socket",
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_IPV4,
+ .size = XT_ALIGN(0),
+ .userspacesize = XT_ALIGN(0),
+};
+
+void libxt_socket_init(void)
+{
+ xtables_register_match(&socket_mt_reg);
+}
diff --git a/extensions/libxt_socket.man b/extensions/libxt_socket.man
new file mode 100644
index 0000000..50c8854
--- /dev/null
+++ b/extensions/libxt_socket.man
@@ -0,0 +1,2 @@
+This matches if an open socket can be found by doing a socket lookup on the
+packet.
diff --git a/extensions/libxt_standard.c b/extensions/libxt_standard.c
new file mode 100644
index 0000000..302524a
--- /dev/null
+++ b/extensions/libxt_standard.c
@@ -0,0 +1,24 @@
+/* Shared library add-on to iptables for standard target support. */
+#include <stdio.h>
+#include <xtables.h>
+
+static void standard_help(void)
+{
+ printf(
+"standard match options:\n"
+"(If target is DROP, ACCEPT, RETURN or nothing)\n");
+}
+
+static struct xtables_target standard_target = {
+ .family = NFPROTO_UNSPEC,
+ .name = "standard",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(int)),
+ .userspacesize = XT_ALIGN(sizeof(int)),
+ .help = standard_help,
+};
+
+void libxt_standard_init(void)
+{
+ xtables_register_target(&standard_target);
+}
diff --git a/extensions/libxt_state.c b/extensions/libxt_state.c
new file mode 100644
index 0000000..cb81c25
--- /dev/null
+++ b/extensions/libxt_state.c
@@ -0,0 +1,158 @@
+/* Shared library add-on to iptables to add state tracking support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/xt_state.h>
+
+#ifndef XT_STATE_UNTRACKED
+#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
+#endif
+
+static void
+state_help(void)
+{
+ printf(
+"state match options:\n"
+" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
+" State(s) to match\n");
+}
+
+static const struct option state_opts[] = {
+ { "state", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static int
+state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
+{
+ if (strncasecmp(state, "INVALID", len) == 0)
+ sinfo->statemask |= XT_STATE_INVALID;
+ else if (strncasecmp(state, "NEW", len) == 0)
+ sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
+ else if (strncasecmp(state, "ESTABLISHED", len) == 0)
+ sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
+ else if (strncasecmp(state, "RELATED", len) == 0)
+ sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
+ else if (strncasecmp(state, "UNTRACKED", len) == 0)
+ sinfo->statemask |= XT_STATE_UNTRACKED;
+ else
+ return 0;
+ return 1;
+}
+
+static void
+state_parse_states(const char *arg, struct xt_state_info *sinfo)
+{
+ const char *comma;
+
+ while ((comma = strchr(arg, ',')) != NULL) {
+ if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
+ xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
+ arg = comma+1;
+ }
+ if (!*arg)
+ xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
+ "states with no spaces, e.g. "
+ "ESTABLISHED,RELATED");
+ if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
+ xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
+}
+
+static int
+state_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry,
+ struct xt_entry_match **match)
+{
+ struct xt_state_info *sinfo = (struct xt_state_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+
+ state_parse_states(optarg, sinfo);
+ if (invert)
+ sinfo->statemask = ~sinfo->statemask;
+ *flags = 1;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void state_final_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM, "You must specify \"--state\"");
+}
+
+static void state_print_state(unsigned int statemask)
+{
+ const char *sep = "";
+
+ if (statemask & XT_STATE_INVALID) {
+ printf("%sINVALID", sep);
+ sep = ",";
+ }
+ if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
+ printf("%sNEW", sep);
+ sep = ",";
+ }
+ if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
+ printf("%sRELATED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
+ printf("%sESTABLISHED", sep);
+ sep = ",";
+ }
+ if (statemask & XT_STATE_UNTRACKED) {
+ printf("%sUNTRACKED", sep);
+ sep = ",";
+ }
+ printf(" ");
+}
+
+static void
+state_print(const void *ip,
+ const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_state_info *sinfo = (const void *)match->data;
+
+ printf("state ");
+ state_print_state(sinfo->statemask);
+}
+
+static void state_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_state_info *sinfo = (const void *)match->data;
+
+ printf("--state ");
+ state_print_state(sinfo->statemask);
+}
+
+static struct xtables_match state_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "state",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_state_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
+ .help = state_help,
+ .parse = state_parse,
+ .final_check = state_final_check,
+ .print = state_print,
+ .save = state_save,
+ .extra_opts = state_opts,
+};
+
+void libxt_state_init(void)
+{
+ xtables_register_match(&state_match);
+}
diff --git a/extensions/libipt_state.man b/extensions/libxt_state.man
index 7107868..b5e719a 100644
--- a/extensions/libipt_state.man
+++ b/extensions/libxt_state.man
@@ -1,7 +1,7 @@
This module, when combined with connection tracking, allows access to
the connection tracking state for this packet.
.TP
-.BI "--state " "state"
+[\fB!\fP] \fB\-\-state\fP \fIstate\fP
Where state is a comma separated list of the connection states to
match. Possible states are
.B INVALID
diff --git a/extensions/libxt_statistic.c b/extensions/libxt_statistic.c
new file mode 100644
index 0000000..75bede2
--- /dev/null
+++ b/extensions/libxt_statistic.c
@@ -0,0 +1,180 @@
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_statistic.h>
+
+static void statistic_help(void)
+{
+ printf(
+"statistic match options:\n"
+" --mode mode Match mode (random, nth)\n"
+" random mode:\n"
+" --probability p Probability\n"
+" nth mode:\n"
+" --every n Match every nth packet\n"
+" --packet p Initial counter value (0 <= p <= n-1, default 0)\n");
+}
+
+static const struct option statistic_opts[] = {
+ { "mode", 1, NULL, '1' },
+ { "probability", 1, NULL, '2' },
+ { "every", 1, NULL, '3' },
+ { "packet", 1, NULL, '4' },
+ { .name = NULL }
+};
+
+static struct xt_statistic_info *global_info;
+
+static void statistic_mt_init(struct xt_entry_match *match)
+{
+ global_info = (void *)match->data;
+}
+
+static int
+statistic_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_statistic_info *info = (void *)(*match)->data;
+ unsigned int val;
+ double prob;
+
+ if (invert)
+ info->flags |= XT_STATISTIC_INVERT;
+
+ switch (c) {
+ case '1':
+ if (*flags & 0x1)
+ xtables_error(PARAMETER_PROBLEM, "double --mode");
+ if (!strcmp(optarg, "random"))
+ info->mode = XT_STATISTIC_MODE_RANDOM;
+ else if (!strcmp(optarg, "nth"))
+ info->mode = XT_STATISTIC_MODE_NTH;
+ else
+ xtables_error(PARAMETER_PROBLEM, "Bad mode \"%s\"", optarg);
+ *flags |= 0x1;
+ break;
+ case '2':
+ if (*flags & 0x2)
+ xtables_error(PARAMETER_PROBLEM, "double --probability");
+ prob = atof(optarg);
+ if (prob < 0 || prob > 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "--probability must be between 0 and 1");
+ info->u.random.probability = 0x80000000 * prob;
+ *flags |= 0x2;
+ break;
+ case '3':
+ if (*flags & 0x4)
+ xtables_error(PARAMETER_PROBLEM, "double --every");
+ if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "cannot parse --every `%s'", optarg);
+ info->u.nth.every = val;
+ if (info->u.nth.every == 0)
+ xtables_error(PARAMETER_PROBLEM, "--every cannot be 0");
+ info->u.nth.every--;
+ *flags |= 0x4;
+ break;
+ case '4':
+ if (*flags & 0x8)
+ xtables_error(PARAMETER_PROBLEM, "double --packet");
+ if (!xtables_strtoui(optarg, NULL, &val, 0, UINT32_MAX))
+ xtables_error(PARAMETER_PROBLEM,
+ "cannot parse --packet `%s'", optarg);
+ info->u.nth.packet = val;
+ *flags |= 0x8;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void statistic_check(unsigned int flags)
+{
+ if (!(flags & 0x1))
+ xtables_error(PARAMETER_PROBLEM, "no mode specified");
+ if ((flags & 0x2) && (flags & (0x4 | 0x8)))
+ xtables_error(PARAMETER_PROBLEM,
+ "both nth and random parameters given");
+ if (flags & 0x2 && global_info->mode != XT_STATISTIC_MODE_RANDOM)
+ xtables_error(PARAMETER_PROBLEM,
+ "--probability can only be used in random mode");
+ if (flags & 0x4 && global_info->mode != XT_STATISTIC_MODE_NTH)
+ xtables_error(PARAMETER_PROBLEM,
+ "--every can only be used in nth mode");
+ if (flags & 0x8 && global_info->mode != XT_STATISTIC_MODE_NTH)
+ xtables_error(PARAMETER_PROBLEM,
+ "--packet can only be used in nth mode");
+ if ((flags & 0x8) && !(flags & 0x4))
+ xtables_error(PARAMETER_PROBLEM,
+ "--packet can only be used with --every");
+ /* at this point, info->u.nth.every have been decreased. */
+ if (global_info->u.nth.packet > global_info->u.nth.every)
+ xtables_error(PARAMETER_PROBLEM,
+ "the --packet p must be 0 <= p <= n-1");
+
+
+ global_info->u.nth.count = global_info->u.nth.every -
+ global_info->u.nth.packet;
+}
+
+static void print_match(const struct xt_statistic_info *info, char *prefix)
+{
+ if (info->flags & XT_STATISTIC_INVERT)
+ printf("! ");
+
+ switch (info->mode) {
+ case XT_STATISTIC_MODE_RANDOM:
+ printf("%smode random %sprobability %f ", prefix, prefix,
+ 1.0 * info->u.random.probability / 0x80000000);
+ break;
+ case XT_STATISTIC_MODE_NTH:
+ printf("%smode nth %severy %u ", prefix, prefix,
+ info->u.nth.every + 1);
+ if (info->u.nth.packet)
+ printf("%spacket %u ", prefix, info->u.nth.packet);
+ break;
+ }
+}
+
+static void
+statistic_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_statistic_info *info = (const void *)match->data;
+
+ printf("statistic ");
+ print_match(info, "");
+}
+
+static void statistic_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_statistic_info *info = (const void *)match->data;
+
+ print_match(info, "--");
+}
+
+static struct xtables_match statistic_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "statistic",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_statistic_info)),
+ .userspacesize = offsetof(struct xt_statistic_info, u.nth.count),
+ .init = statistic_mt_init,
+ .help = statistic_help,
+ .parse = statistic_parse,
+ .final_check = statistic_check,
+ .print = statistic_print,
+ .save = statistic_save,
+ .extra_opts = statistic_opts,
+};
+
+void libxt_statistic_init(void)
+{
+ xtables_register_match(&statistic_match);
+}
diff --git a/extensions/libxt_statistic.man b/extensions/libxt_statistic.man
new file mode 100644
index 0000000..8fc3b29
--- /dev/null
+++ b/extensions/libxt_statistic.man
@@ -0,0 +1,30 @@
+This module matches packets based on some statistic condition.
+It supports two distinct modes settable with the
+\fB\-\-mode\fP
+option.
+.PP
+Supported options:
+.TP
+\fB\-\-mode\fP \fImode\fP
+Set the matching mode of the matching rule, supported modes are
+.B random
+and
+.B nth.
+.TP
+\fB\-\-probability\fP \fIp\fP
+Set the probability from 0 to 1 for a packet to be randomly
+matched. It works only with the
+.B random
+mode.
+.TP
+\fB\-\-every\fP \fIn\fP
+Match one packet every nth packet. It works only with the
+.B nth
+mode (see also the
+\fB\-\-packet\fP
+option).
+.TP
+\fB\-\-packet\fP \fIp\fP
+Set the initial counter value (0 <= p <= n\-1, default 0) for the
+.B nth
+mode.
diff --git a/extensions/libipt_string.c b/extensions/libxt_string.c
index 82bf748..a4099c9 100644
--- a/extensions/libipt_string.c
+++ b/extensions/libxt_string.c
@@ -20,71 +20,72 @@
* updated to work with slightly modified
* ipt_string_info.
*/
+#define _GNU_SOURCE 1
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <ctype.h>
-#include <iptables.h>
+#include <xtables.h>
#include <stddef.h>
-#include <linux/netfilter_ipv4/ipt_string.h>
+#include <linux/netfilter/xt_string.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+static void string_help(void)
{
printf(
-"STRING match v%s options:\n"
+"string match options:\n"
"--from Offset to start searching from\n"
"--to Offset to stop searching\n"
-"--algo Algorithm\n"
-"--string [!] string Match a string in a packet\n"
-"--hex-string [!] string Match a hex string in a packet\n",
-IPTABLES_VERSION);
+"--algo Algorithm\n"
+"--icase Ignore case (default: 0)\n"
+"[!] --string string Match a string in a packet\n"
+"[!] --hex-string string Match a hex string in a packet\n");
}
-static struct option opts[] = {
- { "from", 1, 0, '1' },
- { "to", 1, 0, '2' },
- { "algo", 1, 0, '3' },
- { "string", 1, 0, '4' },
- { "hex-string", 1, 0, '5' },
- {0}
+static const struct option string_opts[] = {
+ { "from", 1, NULL, '1' },
+ { "to", 1, NULL, '2' },
+ { "algo", 1, NULL, '3' },
+ { "string", 1, NULL, '4' },
+ { "hex-string", 1, NULL, '5' },
+ { "icase", 0, NULL, '6' },
+ { .name = NULL }
};
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
+static void string_init(struct xt_entry_match *m)
{
- struct ipt_string_info *i = (struct ipt_string_info *) m->data;
+ struct xt_string_info *i = (struct xt_string_info *) m->data;
if (i->to_offset == 0)
- i->to_offset = (u_int16_t) ~0UL;
+ i->to_offset = UINT16_MAX;
}
static void
-parse_string(const char *s, struct ipt_string_info *info)
+parse_string(const char *s, struct xt_string_info *info)
{
- if (strlen(s) <= IPT_STRING_MAX_PATTERN_SIZE) {
- strncpy(info->pattern, s, IPT_STRING_MAX_PATTERN_SIZE);
- info->patlen = strlen(s);
+ /* xt_string does not need \0 at the end of the pattern */
+ if (strlen(s) <= XT_STRING_MAX_PATTERN_SIZE) {
+ strncpy(info->pattern, s, XT_STRING_MAX_PATTERN_SIZE);
+ info->patlen = strnlen(s, XT_STRING_MAX_PATTERN_SIZE);
return;
}
- exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
+ xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s);
}
static void
-parse_algo(const char *s, struct ipt_string_info *info)
+parse_algo(const char *s, struct xt_string_info *info)
{
- if (strlen(s) <= IPT_STRING_MAX_ALGO_NAME_SIZE) {
- strncpy(info->algo, s, IPT_STRING_MAX_ALGO_NAME_SIZE);
+ /* xt_string needs \0 for algo name */
+ if (strlen(s) < XT_STRING_MAX_ALGO_NAME_SIZE) {
+ strncpy(info->algo, s, XT_STRING_MAX_ALGO_NAME_SIZE);
return;
}
- exit_error(PARAMETER_PROBLEM, "ALGO too long `%s'", s);
+ xtables_error(PARAMETER_PROBLEM, "ALGO too long \"%s\"", s);
}
static void
-parse_hex_string(const char *s, struct ipt_string_info *info)
+parse_hex_string(const char *s, struct xt_string_info *info)
{
int i=0, slen, sindex=0, schar;
short hex_f = 0, literal_f = 0;
@@ -93,7 +94,7 @@ parse_hex_string(const char *s, struct ipt_string_info *info)
slen = strlen(s);
if (slen == 0) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"STRING must contain at least one char");
}
@@ -101,7 +102,7 @@ parse_hex_string(const char *s, struct ipt_string_info *info)
if (s[i] == '\\' && !hex_f) {
literal_f = 1;
} else if (s[i] == '\\') {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Cannot include literals in hex data");
} else if (s[i] == '|') {
if (hex_f)
@@ -120,7 +121,7 @@ parse_hex_string(const char *s, struct ipt_string_info *info)
if (literal_f) {
if (i+1 >= slen) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Bad literal placement at end of string");
}
info->pattern[sindex] = s[i+1];
@@ -128,22 +129,22 @@ parse_hex_string(const char *s, struct ipt_string_info *info)
literal_f = 0;
} else if (hex_f) {
if (i+1 >= slen) {
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Odd number of hex digits");
}
if (i+2 >= slen) {
/* must end with a "|" */
- exit_error(PARAMETER_PROBLEM, "Invalid hex block");
+ xtables_error(PARAMETER_PROBLEM, "Invalid hex block");
}
if (! isxdigit(s[i])) /* check for valid hex char */
- exit_error(PARAMETER_PROBLEM, "Invalid hex char `%c'", s[i]);
+ xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i]);
if (! isxdigit(s[i+1])) /* check for valid hex char */
- exit_error(PARAMETER_PROBLEM, "Invalid hex char `%c'", s[i+1]);
+ xtables_error(PARAMETER_PROBLEM, "Invalid hex char '%c'", s[i+1]);
hextmp[0] = s[i];
hextmp[1] = s[i+1];
hextmp[2] = '\0';
if (! sscanf(hextmp, "%x", &schar))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Invalid hex char `%c'", s[i]);
info->pattern[sindex] = (char) schar;
if (s[i+2] == ' ')
@@ -154,8 +155,8 @@ parse_hex_string(const char *s, struct ipt_string_info *info)
info->pattern[sindex] = s[i];
i++;
}
- if (sindex > IPT_STRING_MAX_PATTERN_SIZE)
- exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
+ if (sindex > XT_STRING_MAX_PATTERN_SIZE)
+ xtables_error(PARAMETER_PROBLEM, "STRING too long \"%s\"", s);
sindex++;
}
info->patlen = sindex;
@@ -165,80 +166,92 @@ parse_hex_string(const char *s, struct ipt_string_info *info)
#define ALGO 0x2
#define FROM 0x4
#define TO 0x8
+#define ICASE 0x10
-/* Function which parses command options; returns true if it
- ate an option */
static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+string_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
- struct ipt_string_info *stringinfo = (struct ipt_string_info *)(*match)->data;
+ struct xt_string_info *stringinfo =
+ (struct xt_string_info *)(*match)->data;
+ const int revision = (*match)->u.user.revision;
switch (c) {
case '1':
if (*flags & FROM)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify multiple --from");
stringinfo->from_offset = atoi(optarg);
*flags |= FROM;
break;
case '2':
if (*flags & TO)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify multiple --to");
stringinfo->to_offset = atoi(optarg);
*flags |= TO;
break;
case '3':
if (*flags & ALGO)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify multiple --algo");
parse_algo(optarg, stringinfo);
*flags |= ALGO;
break;
case '4':
if (*flags & STRING)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify multiple --string");
- check_inverse(optarg, &invert, &optind, 0);
- parse_string(argv[optind-1], stringinfo);
- if (invert)
- stringinfo->invert = 1;
- stringinfo->patlen=strlen((char *)&stringinfo->pattern);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_string(optarg, stringinfo);
+ if (invert) {
+ if (revision == 0)
+ stringinfo->u.v0.invert = 1;
+ else
+ stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT;
+ }
*flags |= STRING;
break;
case '5':
if (*flags & STRING)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Can't specify multiple --hex-string");
- check_inverse(optarg, &invert, &optind, 0);
- parse_hex_string(argv[optind-1], stringinfo); /* sets length */
- if (invert)
- stringinfo->invert = 1;
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_hex_string(optarg, stringinfo); /* sets length */
+ if (invert) {
+ if (revision == 0)
+ stringinfo->u.v0.invert = 1;
+ else
+ stringinfo->u.v1.flags |= XT_STRING_FLAG_INVERT;
+ }
*flags |= STRING;
break;
+ case '6':
+ if (revision == 0)
+ xtables_error(VERSION_PROBLEM,
+ "Kernel doesn't support --icase");
+
+ stringinfo->u.v1.flags |= XT_STRING_FLAG_IGNORECASE;
+ *flags |= ICASE;
+ break;
+
default:
return 0;
}
return 1;
}
-
-/* Final check; must have specified --string. */
-static void
-final_check(unsigned int flags)
+static void string_check(unsigned int flags)
{
if (!(flags & STRING))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"STRING match: You must specify `--string' or "
"`--hex-string'");
if (!(flags & ALGO))
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"STRING match: You must specify `--algo'");
}
@@ -287,20 +300,20 @@ print_string(const char *str, const unsigned short int len)
printf("\" "); /* closing space and quote */
}
-/* Prints out the matchinfo. */
static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match,
- int numeric)
+string_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
- const struct ipt_string_info *info =
- (const struct ipt_string_info*) match->data;
+ const struct xt_string_info *info =
+ (const struct xt_string_info*) match->data;
+ const int revision = match->u.user.revision;
+ int invert = (revision == 0 ? info->u.v0.invert :
+ info->u.v1.flags & XT_STRING_FLAG_INVERT);
if (is_hex_string(info->pattern, info->patlen)) {
- printf("STRING match %s", (info->invert) ? "!" : "");
+ printf("STRING match %s", invert ? "!" : "");
print_hex_string(info->pattern, info->patlen);
} else {
- printf("STRING match %s", (info->invert) ? "!" : "");
+ printf("STRING match %s", invert ? "!" : "");
print_string(info->pattern, info->patlen);
}
printf("ALGO name %s ", info->algo);
@@ -308,21 +321,23 @@ print(const struct ipt_ip *ip,
printf("FROM %u ", info->from_offset);
if (info->to_offset != 0)
printf("TO %u ", info->to_offset);
+ if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE)
+ printf("ICASE ");
}
-
-/* Saves the union ipt_matchinfo in parseable form to stdout. */
-static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void string_save(const void *ip, const struct xt_entry_match *match)
{
- const struct ipt_string_info *info =
- (const struct ipt_string_info*) match->data;
+ const struct xt_string_info *info =
+ (const struct xt_string_info*) match->data;
+ const int revision = match->u.user.revision;
+ int invert = (revision == 0 ? info->u.v0.invert :
+ info->u.v1.flags & XT_STRING_FLAG_INVERT);
if (is_hex_string(info->pattern, info->patlen)) {
- printf("--hex-string %s", (info->invert) ? "! ": "");
+ printf("%s--hex-string ", (invert) ? "! ": "");
print_hex_string(info->pattern, info->patlen);
} else {
- printf("--string %s", (info->invert) ? "! ": "");
+ printf("%s--string ", (invert) ? "! ": "");
print_string(info->pattern, info->patlen);
}
printf("--algo %s ", info->algo);
@@ -330,25 +345,45 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
printf("--from %u ", info->from_offset);
if (info->to_offset != 0)
printf("--to %u ", info->to_offset);
+ if (revision > 0 && info->u.v1.flags & XT_STRING_FLAG_IGNORECASE)
+ printf("--icase ");
}
-static struct iptables_match string = {
- .name = "string",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_string_info)),
- .userspacesize = offsetof(struct ipt_string_info, config),
- .help = help,
- .init = init,
- .parse = parse,
- .final_check = final_check,
- .print = print,
- .save = save,
- .extra_opts = opts
+static struct xtables_match string_mt_reg[] = {
+ {
+ .name = "string",
+ .revision = 0,
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_string_info)),
+ .userspacesize = offsetof(struct xt_string_info, config),
+ .help = string_help,
+ .init = string_init,
+ .parse = string_parse,
+ .final_check = string_check,
+ .print = string_print,
+ .save = string_save,
+ .extra_opts = string_opts,
+ },
+ {
+ .name = "string",
+ .revision = 1,
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_string_info)),
+ .userspacesize = offsetof(struct xt_string_info, config),
+ .help = string_help,
+ .init = string_init,
+ .parse = string_parse,
+ .final_check = string_check,
+ .print = string_print,
+ .save = string_save,
+ .extra_opts = string_opts,
+ },
};
-
-void ipt_string_init(void)
+void libxt_string_init(void)
{
- register_match(&string);
+ xtables_register_matches(string_mt_reg, ARRAY_SIZE(string_mt_reg));
}
diff --git a/extensions/libipt_string.man b/extensions/libxt_string.man
index 3f3e5b7..725f3ff 100644
--- a/extensions/libipt_string.man
+++ b/extensions/libxt_string.man
@@ -1,15 +1,16 @@
This modules matches a given string by using some pattern matching strategy. It requires a linux kernel >= 2.6.14.
.TP
-.BI "--algo " "bm|kmp"
+\fB\-\-algo\fP {\fBbm\fP|\fBkmp\fP}
Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)
.TP
-.BI "--from " "offset"
+\fB\-\-from\fP \fIoffset\fP
Set the offset from which it starts looking for any matching. If not passed, default is 0.
.TP
-.BI "--to " "offset"
+\fB\-\-to\fP \fIoffset\fP
Set the offset from which it starts looking for any matching. If not passed, default is the packet size.
.TP
-.BI "--string " "pattern"
+[\fB!\fP] \fB\-\-string\fP \fIpattern\fP
Matches the given pattern.
-.BI "--hex-string " "pattern"
+.TP
+[\fB!\fP] \fB\-\-hex\-string\fP \fIpattern\fP
Matches the given pattern in hex notation.
diff --git a/extensions/libipt_tcp.c b/extensions/libxt_tcp.c
index 935212c..146b6c4 100644
--- a/extensions/libipt_tcp.c
+++ b/extensions/libxt_tcp.c
@@ -4,39 +4,36 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
#include <netinet/in.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_tcpudp.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+static void tcp_help(void)
{
printf(
-"TCP v%s options:\n"
-" --tcp-flags [!] mask comp match when TCP flags & mask == comp\n"
+"tcp match options:\n"
+"[!] --tcp-flags mask comp match when TCP flags & mask == comp\n"
" (Flags: SYN ACK FIN RST URG PSH ALL NONE)\n"
"[!] --syn match when only SYN flag set\n"
-" (equivalent to --tcp-flags SYN,RST,ACK SYN)\n"
-" --source-port [!] port[:port]\n"
+" (equivalent to --tcp-flags SYN,RST,ACK,FIN SYN)\n"
+"[!] --source-port port[:port]\n"
" --sport ...\n"
" match source port(s)\n"
-" --destination-port [!] port[:port]\n"
+"[!] --destination-port port[:port]\n"
" --dport ...\n"
" match destination port(s)\n"
-" --tcp-option [!] number match if TCP option set\n\n",
-IPTABLES_VERSION);
+"[!] --tcp-option number match if TCP option set\n");
}
-static struct option opts[] = {
- { "source-port", 1, 0, '1' },
- { "sport", 1, 0, '1' }, /* synonym */
- { "destination-port", 1, 0, '2' },
- { "dport", 1, 0, '2' }, /* synonym */
- { "syn", 0, 0, '3' },
- { "tcp-flags", 1, 0, '4' },
- { "tcp-option", 1, 0, '5' },
- {0}
+static const struct option tcp_opts[] = {
+ { "source-port", 1, NULL, '1' },
+ { "sport", 1, NULL, '1' }, /* synonym */
+ { "destination-port", 1, NULL, '2' },
+ { "dport", 1, NULL, '2' }, /* synonym */
+ { "syn", 0, NULL, '3' },
+ { "tcp-flags", 1, NULL, '4' },
+ { "tcp-option", 1, NULL, '5' },
+ { .name = NULL }
};
static void
@@ -47,16 +44,16 @@ parse_tcp_ports(const char *portstring, u_int16_t *ports)
buffer = strdup(portstring);
if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = parse_port(buffer, "tcp");
+ ports[0] = ports[1] = xtables_parse_port(buffer, "tcp");
else {
*cp = '\0';
cp++;
- ports[0] = buffer[0] ? parse_port(buffer, "tcp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "tcp") : 0xFFFF;
+ ports[0] = buffer[0] ? xtables_parse_port(buffer, "tcp") : 0;
+ ports[1] = cp[0] ? xtables_parse_port(cp, "tcp") : 0xFFFF;
if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"invalid portrange (min > max)");
}
free(buffer);
@@ -67,7 +64,7 @@ struct tcp_flag_names {
unsigned int flag;
};
-static struct tcp_flag_names tcp_flag_names[]
+static const struct tcp_flag_names tcp_flag_names[]
= { { "FIN", 0x01 },
{ "SYN", 0x02 },
{ "RST", 0x04 },
@@ -89,25 +86,22 @@ parse_tcp_flag(const char *flags)
for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
unsigned int i;
- for (i = 0;
- i < sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names);
- i++) {
+ for (i = 0; i < ARRAY_SIZE(tcp_flag_names); ++i)
if (strcasecmp(tcp_flag_names[i].name, ptr) == 0) {
ret |= tcp_flag_names[i].flag;
break;
}
- }
- if (i == sizeof(tcp_flag_names)/sizeof(struct tcp_flag_names))
- exit_error(PARAMETER_PROBLEM,
+ if (i == ARRAY_SIZE(tcp_flag_names))
+ xtables_error(PARAMETER_PROBLEM,
"Unknown TCP flag `%s'", ptr);
- }
+ }
free(buffer);
return ret;
}
static void
-parse_tcp_flags(struct ipt_tcp *tcpinfo,
+parse_tcp_flags(struct xt_tcp *tcpinfo,
const char *mask,
const char *cmp,
int invert)
@@ -116,7 +110,7 @@ parse_tcp_flags(struct ipt_tcp *tcpinfo,
tcpinfo->flg_cmp = parse_tcp_flag(cmp);
if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_FLAGS;
+ tcpinfo->invflags |= XT_TCP_INV_FLAGS;
}
static void
@@ -124,17 +118,15 @@ parse_tcp_option(const char *option, u_int8_t *result)
{
unsigned int ret;
- if (string_to_number(option, 1, 255, &ret) == -1)
- exit_error(PARAMETER_PROBLEM, "Bad TCP option `%s'", option);
+ if (!xtables_strtoui(option, NULL, &ret, 1, UINT8_MAX))
+ xtables_error(PARAMETER_PROBLEM, "Bad TCP option \"%s\"", option);
- *result = (u_int8_t)ret;
+ *result = ret;
}
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
+static void tcp_init(struct xt_entry_match *m)
{
- struct ipt_tcp *tcpinfo = (struct ipt_tcp *)m->data;
+ struct xt_tcp *tcpinfo = (struct xt_tcp *)m->data;
tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF;
}
@@ -144,42 +136,38 @@ init(struct ipt_entry_match *m, unsigned int *nfcache)
#define TCP_FLAGS 0x04
#define TCP_OPTION 0x08
-/* Function which parses command options; returns true if it
- ate an option. */
static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+tcp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
- struct ipt_tcp *tcpinfo = (struct ipt_tcp *)(*match)->data;
+ struct xt_tcp *tcpinfo = (struct xt_tcp *)(*match)->data;
switch (c) {
case '1':
if (*flags & TCP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--source-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->spts);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_tcp_ports(optarg, tcpinfo->spts);
if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_SRCPT;
+ tcpinfo->invflags |= XT_TCP_INV_SRCPT;
*flags |= TCP_SRC_PORTS;
break;
case '2':
if (*flags & TCP_DST_PORTS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--destination-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_ports(argv[optind-1], tcpinfo->dpts);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_tcp_ports(optarg, tcpinfo->dpts);
if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_DSTPT;
+ tcpinfo->invflags |= XT_TCP_INV_DSTPT;
*flags |= TCP_DST_PORTS;
break;
case '3':
if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one of `--syn' or `--tcp-flags' "
" allowed");
parse_tcp_flags(tcpinfo, "SYN,RST,ACK,FIN", "SYN", invert);
@@ -188,17 +176,17 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '4':
if (*flags & TCP_FLAGS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one of `--syn' or `--tcp-flags' "
" allowed");
- check_inverse(optarg, &invert, &optind, 0);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
if (!argv[optind]
|| argv[optind][0] == '-' || argv[optind][0] == '!')
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"--tcp-flags requires two args.");
- parse_tcp_flags(tcpinfo, argv[optind-1], argv[optind],
+ parse_tcp_flags(tcpinfo, optarg, argv[optind],
invert);
optind++;
*flags |= TCP_FLAGS;
@@ -206,12 +194,12 @@ parse(int c, char **argv, int invert, unsigned int *flags,
case '5':
if (*flags & TCP_OPTION)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--tcp-option' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_tcp_option(argv[optind-1], &tcpinfo->option);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_tcp_option(optarg, &tcpinfo->option);
if (invert)
- tcpinfo->invflags |= IPT_TCP_INV_OPTION;
+ tcpinfo->invflags |= XT_TCP_INV_OPTION;
*flags |= TCP_OPTION;
break;
@@ -222,12 +210,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
static char *
port_to_service(int port)
{
@@ -316,39 +298,36 @@ print_flags(u_int8_t mask, u_int8_t cmp, int invert, int numeric)
}
}
-/* Prints out the union ipt_matchinfo. */
static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match, int numeric)
+tcp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
- const struct ipt_tcp *tcp = (struct ipt_tcp *)match->data;
+ const struct xt_tcp *tcp = (struct xt_tcp *)match->data;
printf("tcp ");
print_ports("spt", tcp->spts[0], tcp->spts[1],
- tcp->invflags & IPT_TCP_INV_SRCPT,
+ tcp->invflags & XT_TCP_INV_SRCPT,
numeric);
print_ports("dpt", tcp->dpts[0], tcp->dpts[1],
- tcp->invflags & IPT_TCP_INV_DSTPT,
+ tcp->invflags & XT_TCP_INV_DSTPT,
numeric);
print_option(tcp->option,
- tcp->invflags & IPT_TCP_INV_OPTION,
+ tcp->invflags & XT_TCP_INV_OPTION,
numeric);
print_flags(tcp->flg_mask, tcp->flg_cmp,
- tcp->invflags & IPT_TCP_INV_FLAGS,
+ tcp->invflags & XT_TCP_INV_FLAGS,
numeric);
- if (tcp->invflags & ~IPT_TCP_INV_MASK)
+ if (tcp->invflags & ~XT_TCP_INV_MASK)
printf("Unknown invflags: 0x%X ",
- tcp->invflags & ~IPT_TCP_INV_MASK);
+ tcp->invflags & ~XT_TCP_INV_MASK);
}
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void tcp_save(const void *ip, const struct xt_entry_match *match)
{
- const struct ipt_tcp *tcpinfo = (struct ipt_tcp *)match->data;
+ const struct xt_tcp *tcpinfo = (struct xt_tcp *)match->data;
if (tcpinfo->spts[0] != 0
|| tcpinfo->spts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IPT_TCP_INV_SRCPT)
+ if (tcpinfo->invflags & XT_TCP_INV_SRCPT)
printf("! ");
if (tcpinfo->spts[0]
!= tcpinfo->spts[1])
@@ -362,7 +341,7 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
if (tcpinfo->dpts[0] != 0
|| tcpinfo->dpts[1] != 0xFFFF) {
- if (tcpinfo->invflags & IPT_TCP_INV_DSTPT)
+ if (tcpinfo->invflags & XT_TCP_INV_DSTPT)
printf("! ");
if (tcpinfo->dpts[0]
!= tcpinfo->dpts[1])
@@ -375,15 +354,15 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
}
if (tcpinfo->option
- || (tcpinfo->invflags & IPT_TCP_INV_OPTION)) {
- if (tcpinfo->invflags & IPT_TCP_INV_OPTION)
+ || (tcpinfo->invflags & XT_TCP_INV_OPTION)) {
+ if (tcpinfo->invflags & XT_TCP_INV_OPTION)
printf("! ");
printf("--tcp-option %u ", tcpinfo->option);
}
if (tcpinfo->flg_mask
- || (tcpinfo->invflags & IPT_TCP_INV_FLAGS)) {
- if (tcpinfo->invflags & IPT_TCP_INV_FLAGS)
+ || (tcpinfo->invflags & XT_TCP_INV_FLAGS)) {
+ if (tcpinfo->invflags & XT_TCP_INV_FLAGS)
printf("! ");
printf("--tcp-flags ");
if (tcpinfo->flg_mask != 0xFF) {
@@ -395,23 +374,21 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
}
}
-static struct iptables_match tcp = {
- .next = NULL,
+static struct xtables_match tcp_match = {
+ .family = NFPROTO_UNSPEC,
.name = "tcp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_tcp)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_tcp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcp)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcp)),
+ .help = tcp_help,
+ .init = tcp_init,
+ .parse = tcp_parse,
+ .print = tcp_print,
+ .save = tcp_save,
+ .extra_opts = tcp_opts,
};
-void
-ipt_tcp_init(void)
+void libxt_tcp_init(void)
{
- register_match(&tcp);
+ xtables_register_match(&tcp_match);
}
diff --git a/extensions/libipt_tcp.man b/extensions/libxt_tcp.man
index 648c81e..7a16118 100644
--- a/extensions/libipt_tcp.man
+++ b/extensions/libxt_tcp.man
@@ -1,45 +1,44 @@
-These extensions are loaded if `--protocol tcp' is specified. It
+These extensions can be used if `\-\-protocol tcp' is specified. It
provides the following options:
.TP
-.BR "--source-port " "[!] \fIport\fP[:\fIport\fP]"
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
Source port or port range specification. This can either be a service
name or a port number. An inclusive range can also be specified,
-using the format
-.IR port : port .
+using the format \fIfirst\fP\fB:\fP\fIlast\fP.
If the first port is omitted, "0" is assumed; if the last is omitted,
"65535" is assumed.
-If the second port greater then the first they will be swapped.
+If the first port is greater than the second one they will be swapped.
The flag
-.B --sport
+\fB\-\-sport\fP
is a convenient alias for this option.
.TP
-.BR "--destination-port " "[!] \fIport\fP[:\fIport\fP]"
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
Destination port or port range specification. The flag
-.B --dport
+\fB\-\-dport\fP
is a convenient alias for this option.
.TP
-.BR "--tcp-flags " "[!] \fImask\fP \fIcomp\fP"
-Match when the TCP flags are as specified. The first argument is the
+[\fB!\fP] \fB\-\-tcp\-flags\fP \fImask\fP \fIcomp\fP
+Match when the TCP flags are as specified. The first argument \fImask\fP is the
flags which we should examine, written as a comma-separated list, and
-the second argument is a comma-separated list of flags which must be
+the second argument \fIcomp\fP is a comma-separated list of flags which must be
set. Flags are:
.BR "SYN ACK FIN RST URG PSH ALL NONE" .
Hence the command
.nf
- iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST SYN
+ iptables \-A FORWARD \-p tcp \-\-tcp\-flags SYN,ACK,FIN,RST SYN
.fi
will only match packets with the SYN flag set, and the ACK, FIN and
RST flags unset.
.TP
-.B "[!] --syn"
+[\fB!\fP] \fB\-\-syn\fP
Only match TCP packets with the SYN bit set and the ACK,RST and FIN bits
cleared. Such packets are used to request TCP connection initiation;
for example, blocking such packets coming in an interface will prevent
incoming TCP connections, but outgoing TCP connections will be
unaffected.
-It is equivalent to \fB--tcp-flags SYN,RST,ACK,FIN SYN\fP.
-If the "!" flag precedes the "--syn", the sense of the
+It is equivalent to \fB\-\-tcp\-flags SYN,RST,ACK,FIN SYN\fP.
+If the "!" flag precedes the "\-\-syn", the sense of the
option is inverted.
.TP
-.BR "--tcp-option " "[!] \fInumber\fP"
+[\fB!\fP] \fB\-\-tcp\-option\fP \fInumber\fP
Match if TCP option set.
diff --git a/extensions/libxt_tcpmss.c b/extensions/libxt_tcpmss.c
new file mode 100644
index 0000000..4932dbd
--- /dev/null
+++ b/extensions/libxt_tcpmss.c
@@ -0,0 +1,128 @@
+/* Shared library add-on to iptables to add tcp MSS matching support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_tcpmss.h>
+
+static void tcpmss_help(void)
+{
+ printf(
+"tcpmss match options:\n"
+"[!] --mss value[:value] Match TCP MSS range.\n"
+" (only valid for TCP SYN or SYN/ACK packets)\n");
+}
+
+static const struct option tcpmss_opts[] = {
+ { "mss", 1, NULL, '1' },
+ { .name = NULL }
+};
+
+static u_int16_t
+parse_tcp_mssvalue(const char *mssvalue)
+{
+ unsigned int mssvaluenum;
+
+ if (xtables_strtoui(mssvalue, NULL, &mssvaluenum, 0, UINT16_MAX))
+ return mssvaluenum;
+
+ xtables_error(PARAMETER_PROBLEM,
+ "Invalid mss `%s' specified", mssvalue);
+}
+
+static void
+parse_tcp_mssvalues(const char *mssvaluestring,
+ u_int16_t *mss_min, u_int16_t *mss_max)
+{
+ char *buffer;
+ char *cp;
+
+ buffer = strdup(mssvaluestring);
+ if ((cp = strchr(buffer, ':')) == NULL)
+ *mss_min = *mss_max = parse_tcp_mssvalue(buffer);
+ else {
+ *cp = '\0';
+ cp++;
+
+ *mss_min = buffer[0] ? parse_tcp_mssvalue(buffer) : 0;
+ *mss_max = cp[0] ? parse_tcp_mssvalue(cp) : 0xFFFF;
+ }
+ free(buffer);
+}
+
+static int
+tcpmss_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_tcpmss_match_info *mssinfo =
+ (struct xt_tcpmss_match_info *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "Only one `--mss' allowed");
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_tcp_mssvalues(optarg,
+ &mssinfo->mss_min, &mssinfo->mss_max);
+ if (invert)
+ mssinfo->invert = 1;
+ *flags = 1;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void tcpmss_check(unsigned int flags)
+{
+ if (!flags)
+ xtables_error(PARAMETER_PROBLEM,
+ "tcpmss match: You must specify `--mss'");
+}
+
+static void
+tcpmss_print(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_tcpmss_match_info *info = (void *)match->data;
+
+ printf("tcpmss match %s", info->invert ? "!" : "");
+ if (info->mss_min == info->mss_max)
+ printf("%u ", info->mss_min);
+ else
+ printf("%u:%u ", info->mss_min, info->mss_max);
+}
+
+static void tcpmss_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_tcpmss_match_info *info = (void *)match->data;
+
+ printf("%s--mss ", info->invert ? "! " : "");
+ if (info->mss_min == info->mss_max)
+ printf("%u ", info->mss_min);
+ else
+ printf("%u:%u ", info->mss_min, info->mss_max);
+}
+
+static struct xtables_match tcpmss_match = {
+ .family = NFPROTO_UNSPEC,
+ .name = "tcpmss",
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tcpmss_match_info)),
+ .help = tcpmss_help,
+ .parse = tcpmss_parse,
+ .final_check = tcpmss_check,
+ .print = tcpmss_print,
+ .save = tcpmss_save,
+ .extra_opts = tcpmss_opts,
+};
+
+void libxt_tcpmss_init(void)
+{
+ xtables_register_match(&tcpmss_match);
+}
diff --git a/extensions/libipt_tcpmss.man b/extensions/libxt_tcpmss.man
index 91fe322..8ee715c 100644
--- a/extensions/libipt_tcpmss.man
+++ b/extensions/libxt_tcpmss.man
@@ -1,4 +1,4 @@
This matches the TCP MSS (maximum segment size) field of the TCP header. You can only use this on TCP SYN or SYN/ACK packets, since the MSS is only negotiated during the TCP handshake at connection startup time.
.TP
-.BI "[!] "--mss " value[:value]"
+[\fB!\fP] \fB\-\-mss\fP \fIvalue\fP[\fB:\fP\fIvalue\fP]
Match a given TCP MSS value or range.
diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c
new file mode 100644
index 0000000..185dd05
--- /dev/null
+++ b/extensions/libxt_time.c
@@ -0,0 +1,485 @@
+/*
+ * libxt_time - iptables part for xt_time
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
+ *
+ * libxt_time.c 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 or 3 of the License.
+ *
+ * Based on libipt_time.c.
+ */
+#include <sys/types.h>
+#include <getopt.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <time.h>
+#include <limits.h>
+
+#include <linux/netfilter/xt_time.h>
+#include <xtables.h>
+
+enum { /* getopt "seen" bits */
+ F_DATE_START = 1 << 0,
+ F_DATE_STOP = 1 << 1,
+ F_TIME_START = 1 << 2,
+ F_TIME_STOP = 1 << 3,
+ F_MONTHDAYS = 1 << 4,
+ F_WEEKDAYS = 1 << 5,
+ F_TIMEZONE = 1 << 6,
+};
+
+static const char *const week_days[] = {
+ NULL, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
+};
+
+static const struct option time_opts[] = {
+ {"datestart", true, NULL, 'D'},
+ {"datestop", true, NULL, 'E'},
+ {"timestart", true, NULL, 'X'},
+ {"timestop", true, NULL, 'Y'},
+ {"weekdays", true, NULL, 'w'},
+ {"monthdays", true, NULL, 'm'},
+ {"localtz", false, NULL, 'l'},
+ {"utc", false, NULL, 'u'},
+ { .name = NULL }
+};
+
+static void time_help(void)
+{
+ printf(
+"time match options:\n"
+" --datestart time Start and stop time, to be given in ISO 8601\n"
+" --datestop time (YYYY[-MM[-DD[Thh[:mm[:ss]]]]])\n"
+" --timestart time Start and stop daytime (hh:mm[:ss])\n"
+" --timestop time (between 00:00:00 and 23:59:59)\n"
+"[!] --monthdays value List of days on which to match, separated by comma\n"
+" (Possible days: 1 to 31; defaults to all)\n"
+"[!] --weekdays value List of weekdays on which to match, sep. by comma\n"
+" (Possible days: Mon,Tue,Wed,Thu,Fri,Sat,Sun or 1 to 7\n"
+" Defaults to all weekdays.)\n"
+" --localtz/--utc Time is interpreted as UTC/local time\n");
+}
+
+static void time_init(struct xt_entry_match *m)
+{
+ struct xt_time_info *info = (void *)m->data;
+
+ /* By default, we match on every day, every daytime */
+ info->monthdays_match = XT_TIME_ALL_MONTHDAYS;
+ info->weekdays_match = XT_TIME_ALL_WEEKDAYS;
+ info->daytime_start = XT_TIME_MIN_DAYTIME;
+ info->daytime_stop = XT_TIME_MAX_DAYTIME;
+
+ /* ...and have no date-begin or date-end boundary */
+ info->date_start = 0;
+ info->date_stop = INT_MAX;
+
+ /* local time is default */
+ info->flags |= XT_TIME_LOCAL_TZ;
+}
+
+static time_t time_parse_date(const char *s, bool end)
+{
+ unsigned int month = 1, day = 1, hour = 0, minute = 0, second = 0;
+ unsigned int year = end ? 2038 : 1970;
+ const char *os = s;
+ struct tm tm;
+ time_t ret;
+ char *e;
+
+ year = strtoul(s, &e, 10);
+ if ((*e != '-' && *e != '\0') || year < 1970 || year > 2038)
+ goto out;
+ if (*e == '\0')
+ goto eval;
+
+ s = e + 1;
+ month = strtoul(s, &e, 10);
+ if ((*e != '-' && *e != '\0') || month > 12)
+ goto out;
+ if (*e == '\0')
+ goto eval;
+
+ s = e + 1;
+ day = strtoul(s, &e, 10);
+ if ((*e != 'T' && *e != '\0') || day > 31)
+ goto out;
+ if (*e == '\0')
+ goto eval;
+
+ s = e + 1;
+ hour = strtoul(s, &e, 10);
+ if ((*e != ':' && *e != '\0') || hour > 23)
+ goto out;
+ if (*e == '\0')
+ goto eval;
+
+ s = e + 1;
+ minute = strtoul(s, &e, 10);
+ if ((*e != ':' && *e != '\0') || minute > 59)
+ goto out;
+ if (*e == '\0')
+ goto eval;
+
+ s = e + 1;
+ second = strtoul(s, &e, 10);
+ if (*e != '\0' || second > 59)
+ goto out;
+
+ eval:
+ tm.tm_year = year - 1900;
+ tm.tm_mon = month - 1;
+ tm.tm_mday = day;
+ tm.tm_hour = hour;
+ tm.tm_min = minute;
+ tm.tm_sec = second;
+ ret = mktime(&tm);
+ if (ret >= 0)
+ return ret;
+ perror("mktime");
+ xtables_error(OTHER_PROBLEM, "mktime returned an error");
+
+ out:
+ xtables_error(PARAMETER_PROBLEM, "Invalid date \"%s\" specified. Should "
+ "be YYYY[-MM[-DD[Thh[:mm[:ss]]]]]", os);
+ return -1;
+}
+
+static unsigned int time_parse_minutes(const char *s)
+{
+ unsigned int hour, minute, second = 0;
+ char *e;
+
+ hour = strtoul(s, &e, 10);
+ if (*e != ':' || hour > 23)
+ goto out;
+
+ s = e + 1;
+ minute = strtoul(s, &e, 10);
+ if ((*e != ':' && *e != '\0') || minute > 59)
+ goto out;
+ if (*e == '\0')
+ goto eval;
+
+ s = e + 1;
+ second = strtoul(s, &e, 10);
+ if (*e != '\0' || second > 59)
+ goto out;
+
+ eval:
+ return 60 * 60 * hour + 60 * minute + second;
+
+ out:
+ xtables_error(PARAMETER_PROBLEM, "invalid time \"%s\" specified, "
+ "should be hh:mm[:ss] format and within the boundaries", s);
+ return -1;
+}
+
+static const char *my_strseg(char *buf, unsigned int buflen,
+ const char **arg, char delim)
+{
+ const char *sep;
+
+ if (*arg == NULL || **arg == '\0')
+ return NULL;
+ sep = strchr(*arg, delim);
+ if (sep == NULL) {
+ snprintf(buf, buflen, "%s", *arg);
+ *arg = NULL;
+ return buf;
+ }
+ snprintf(buf, buflen, "%.*s", (unsigned int)(sep - *arg), *arg);
+ *arg = sep + 1;
+ return buf;
+}
+
+static uint32_t time_parse_monthdays(const char *arg)
+{
+ char day[3], *err = NULL;
+ uint32_t ret = 0;
+ unsigned int i;
+
+ while (my_strseg(day, sizeof(day), &arg, ',') != NULL) {
+ i = strtoul(day, &err, 0);
+ if ((*err != ',' && *err != '\0') || i > 31)
+ xtables_error(PARAMETER_PROBLEM,
+ "%s is not a valid day for --monthdays", day);
+ ret |= 1 << i;
+ }
+
+ return ret;
+}
+
+static unsigned int time_parse_weekdays(const char *arg)
+{
+ char day[4], *err = NULL;
+ unsigned int i, ret = 0;
+ bool valid;
+
+ while (my_strseg(day, sizeof(day), &arg, ',') != NULL) {
+ i = strtoul(day, &err, 0);
+ if (*err == '\0') {
+ if (i == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "No, the week does NOT begin with Sunday.");
+ ret |= 1 << i;
+ continue;
+ }
+
+ valid = false;
+ for (i = 1; i < ARRAY_SIZE(week_days); ++i)
+ if (strncmp(day, week_days[i], 2) == 0) {
+ ret |= 1 << i;
+ valid = true;
+ }
+
+ if (!valid)
+ xtables_error(PARAMETER_PROBLEM,
+ "%s is not a valid day specifier", day);
+ }
+
+ return ret;
+}
+
+static int time_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_time_info *info = (void *)(*match)->data;
+
+ switch (c) {
+ case 'D': /* --datestart */
+ if (*flags & F_DATE_START)
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot specify --datestart twice");
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected \"!\" with --datestart");
+ info->date_start = time_parse_date(optarg, false);
+ *flags |= F_DATE_START;
+ return 1;
+ case 'E': /* --datestop */
+ if (*flags & F_DATE_STOP)
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot specify --datestop more than once");
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "unexpected \"!\" with --datestop");
+ info->date_stop = time_parse_date(optarg, true);
+ *flags |= F_DATE_STOP;
+ return 1;
+ case 'X': /* --timestart */
+ if (*flags & F_TIME_START)
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot specify --timestart more than once");
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected \"!\" with --timestart");
+ info->daytime_start = time_parse_minutes(optarg);
+ *flags |= F_TIME_START;
+ return 1;
+ case 'Y': /* --timestop */
+ if (*flags & F_TIME_STOP)
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot specify --timestop more than once");
+ if (invert)
+ xtables_error(PARAMETER_PROBLEM,
+ "Unexpected \"!\" with --timestop");
+ info->daytime_stop = time_parse_minutes(optarg);
+ *flags |= F_TIME_STOP;
+ return 1;
+ case 'l': /* --localtz */
+ if (*flags & F_TIMEZONE)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can only specify exactly one of --localtz or --utc");
+ info->flags |= XT_TIME_LOCAL_TZ;
+ *flags |= F_TIMEZONE;
+ return 1;
+ case 'm': /* --monthdays */
+ if (*flags & F_MONTHDAYS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot specify --monthdays more than once");
+ info->monthdays_match = time_parse_monthdays(optarg);
+ if (invert)
+ info->monthdays_match ^= XT_TIME_ALL_MONTHDAYS;
+ *flags |= F_MONTHDAYS;
+ return 1;
+ case 'w': /* --weekdays */
+ if (*flags & F_WEEKDAYS)
+ xtables_error(PARAMETER_PROBLEM,
+ "Cannot specify --weekdays more than once");
+ info->weekdays_match = time_parse_weekdays(optarg);
+ if (invert)
+ info->weekdays_match ^= XT_TIME_ALL_WEEKDAYS;
+ *flags |= F_WEEKDAYS;
+ return 1;
+ case 'u': /* --utc */
+ if (*flags & F_TIMEZONE)
+ xtables_error(PARAMETER_PROBLEM,
+ "Can only specify exactly one of --localtz or --utc");
+ info->flags &= ~XT_TIME_LOCAL_TZ;
+ *flags |= F_TIMEZONE;
+ return 1;
+ }
+ return 0;
+}
+
+static void time_print_date(time_t date, const char *command)
+{
+ struct tm *t;
+
+ /* If it is the default value, do not print it. */
+ if (date == 0 || date == LONG_MAX)
+ return;
+
+ t = localtime(&date);
+ if (command != NULL)
+ /*
+ * Need a contiguous string (no whitespaces), hence using
+ * the ISO 8601 "T" variant.
+ */
+ printf("%s %04u-%02u-%02uT%02u:%02u:%02u ",
+ command, t->tm_year + 1900, t->tm_mon + 1,
+ t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
+ else
+ printf("%04u-%02u-%02u %02u:%02u:%02u ",
+ t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+}
+
+static void time_print_monthdays(uint32_t mask, bool human_readable)
+{
+ unsigned int i, nbdays = 0;
+
+ for (i = 1; i <= 31; ++i)
+ if (mask & (1 << i)) {
+ if (nbdays++ > 0)
+ printf(",");
+ printf("%u", i);
+ if (human_readable)
+ switch (i % 10) {
+ case 1:
+ printf("st");
+ break;
+ case 2:
+ printf("nd");
+ break;
+ case 3:
+ printf("rd");
+ break;
+ default:
+ printf("th");
+ break;
+ }
+ }
+ printf(" ");
+}
+
+static void time_print_weekdays(unsigned int mask)
+{
+ unsigned int i, nbdays = 0;
+
+ for (i = 1; i <= 7; ++i)
+ if (mask & (1 << i)) {
+ if (nbdays > 0)
+ printf(",%s", week_days[i]);
+ else
+ printf("%s", week_days[i]);
+ ++nbdays;
+ }
+ printf(" ");
+}
+
+static inline void divide_time(unsigned int fulltime, unsigned int *hours,
+ unsigned int *minutes, unsigned int *seconds)
+{
+ *seconds = fulltime % 60;
+ fulltime /= 60;
+ *minutes = fulltime % 60;
+ *hours = fulltime / 60;
+}
+
+static void time_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_time_info *info = (const void *)match->data;
+ unsigned int h, m, s;
+
+ printf("TIME ");
+
+ if (info->daytime_start != XT_TIME_MIN_DAYTIME ||
+ info->daytime_stop != XT_TIME_MAX_DAYTIME) {
+ divide_time(info->daytime_start, &h, &m, &s);
+ printf("from %02u:%02u:%02u ", h, m, s);
+ divide_time(info->daytime_stop, &h, &m, &s);
+ printf("to %02u:%02u:%02u ", h, m, s);
+ }
+ if (info->weekdays_match != XT_TIME_ALL_WEEKDAYS) {
+ printf("on ");
+ time_print_weekdays(info->weekdays_match);
+ }
+ if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) {
+ printf("on ");
+ time_print_monthdays(info->monthdays_match, true);
+ }
+ if (info->date_start != 0) {
+ printf("starting from ");
+ time_print_date(info->date_start, NULL);
+ }
+ if (info->date_stop != INT_MAX) {
+ printf("until date ");
+ time_print_date(info->date_stop, NULL);
+ }
+ if (!(info->flags & XT_TIME_LOCAL_TZ))
+ printf("UTC ");
+}
+
+static void time_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_time_info *info = (const void *)match->data;
+ unsigned int h, m, s;
+
+ if (info->daytime_start != XT_TIME_MIN_DAYTIME ||
+ info->daytime_stop != XT_TIME_MAX_DAYTIME) {
+ divide_time(info->daytime_start, &h, &m, &s);
+ printf("--timestart %02u:%02u:%02u ", h, m, s);
+ divide_time(info->daytime_stop, &h, &m, &s);
+ printf("--timestop %02u:%02u:%02u ", h, m, s);
+ }
+ if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) {
+ printf("--monthdays ");
+ time_print_monthdays(info->monthdays_match, false);
+ }
+ if (info->weekdays_match != XT_TIME_ALL_WEEKDAYS) {
+ printf("--weekdays ");
+ time_print_weekdays(info->weekdays_match);
+ printf(" ");
+ }
+ time_print_date(info->date_start, "--datestart");
+ time_print_date(info->date_stop, "--datestop");
+ if (!(info->flags & XT_TIME_LOCAL_TZ))
+ printf("--utc ");
+}
+
+static struct xtables_match time_match = {
+ .name = "time",
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_time_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_time_info)),
+ .help = time_help,
+ .init = time_init,
+ .parse = time_parse,
+ .print = time_print,
+ .save = time_save,
+ .extra_opts = time_opts,
+};
+
+void libxt_time_init(void)
+{
+ xtables_register_match(&time_match);
+}
diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man
new file mode 100644
index 0000000..83625a2
--- /dev/null
+++ b/extensions/libxt_time.man
@@ -0,0 +1,69 @@
+This matches if the packet arrival time/date is within a given range. All
+options are optional, but are ANDed when specified.
+.TP
+\fB\-\-datestart\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
+.TP
+\fB\-\-datestop\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
+.IP
+Only match during the given time, which must be in ISO 8601 "T" notation.
+The possible time range is 1970-01-01T00:00:00 to 2038-01-19T04:17:07.
+.IP
+If \-\-datestart or \-\-datestop are not specified, it will default to 1970-01-01
+and 2038-01-19, respectively.
+.TP
+\fB\-\-timestart\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
+.TP
+\fB\-\-timestop\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
+.IP
+Only match during the given daytime. The possible time range is 00:00:00 to
+23:59:59. Leading zeroes are allowed (e.g. "06:03") and correctly interpreted
+as base-10.
+.TP
+[\fB!\fR] \fB\-\-monthdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
+.IP
+Only match on the given days of the month. Possible values are \fB1\fR
+to \fB31\fR. Note that specifying \fB31\fR will of course not match
+on months which do not have a 31st day; the same goes for 28- or 29-day
+February.
+.TP
+[\fB!\fR] \fB\-\-weekdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
+.IP
+Only match on the given weekdays. Possible values are \fBMon\fR, \fBTue\fR,
+\fBWed\fR, \fBThu\fR, \fBFri\fR, \fBSat\fR, \fBSun\fR, or values from \fB1\fR
+to \fB7\fR, respectively. You may also use two-character variants (\fBMo\fP,
+\fBTu\fR, etc.).
+.TP
+\fB\-\-utc\fP
+.IP
+Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
+\fB\-\-timestart\fP and \fB\-\-timestop\fP to be UTC.
+.TP
+\fB\-\-localtz\fP
+.IP
+Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
+\fB\-\-timestart\fP and \fB\-\-timestop\fP to be local kernel time. (Default)
+.PP
+EXAMPLES. To match on weekends, use:
+.IP
+\-m time \-\-weekdays Sa,Su
+.PP
+Or, to match (once) on a national holiday block:
+.IP
+\-m time \-\-datestart 2007\-12\-24 \-\-datestop 2007\-12\-27
+.PP
+Since the stop time is actually inclusive, you would need the following stop
+time to not match the first second of the new day:
+.IP
+\-m time \-\-datestart 2007\-01\-01T17:00 \-\-datestop 2007\-01\-01T23:59:59
+.PP
+During lunch hour:
+.IP
+\-m time \-\-timestart 12:30 \-\-timestop 13:30
+.PP
+The fourth Friday in the month:
+.IP
+\-m time \-\-weekdays Fr \-\-monthdays 22,23,24,25,26,27,28
+.PP
+(Note that this exploits a certain mathematical property. It is not possible to
+say "fourth Thursday OR fourth Friday" in one rule. It is possible with
+multiple rules, though.)
diff --git a/extensions/libxt_tos.c b/extensions/libxt_tos.c
new file mode 100644
index 0000000..188e479
--- /dev/null
+++ b/extensions/libxt_tos.c
@@ -0,0 +1,178 @@
+/*
+ * Shared library add-on to iptables to add tos match support
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: Jan Engelhardt <jengelh@computergmbh.de>
+ */
+#include <getopt.h>
+#include <netdb.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_dscp.h>
+#include "tos_values.c"
+
+struct ipt_tos_info {
+ u_int8_t tos;
+ u_int8_t invert;
+};
+
+enum {
+ FLAG_TOS = 1 << 0,
+};
+
+static const struct option tos_mt_opts[] = {
+ {.name = "tos", .has_arg = true, .val = 't'},
+ { .name = NULL }
+};
+
+static void tos_mt_help(void)
+{
+ const struct tos_symbol_info *symbol;
+
+ printf(
+"tos match options:\n"
+"[!] --tos value[/mask] Match Type of Service/Priority field value\n"
+"[!] --tos symbol Match TOS field (IPv4 only) by symbol\n"
+" Accepted symbolic names for value are:\n");
+
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ printf(" (0x%02x) %2u %s\n",
+ symbol->value, symbol->value, symbol->name);
+
+ printf("\n");
+}
+
+static int tos_mt_parse_v0(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct ipt_tos_info *info = (void *)(*match)->data;
+ struct tos_value_mask tvm;
+
+ switch (c) {
+ case 't':
+ xtables_param_act(XTF_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
+ if (!tos_parse_symbolic(optarg, &tvm, 0xFF))
+ xtables_param_act(XTF_BAD_VALUE, "tos", "--tos", optarg);
+ if (tvm.mask != 0xFF)
+ xtables_error(PARAMETER_PROBLEM, "tos: Your kernel is "
+ "too old to support anything besides /0xFF "
+ "as a mask.");
+ info->tos = tvm.value;
+ if (invert)
+ info->invert = true;
+ *flags |= FLAG_TOS;
+ return true;
+ }
+ return false;
+}
+
+static int tos_mt_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_tos_match_info *info = (void *)(*match)->data;
+ struct tos_value_mask tvm = {.mask = 0xFF};
+
+ switch (c) {
+ case 't':
+ xtables_param_act(XTF_ONLY_ONCE, "tos", "--tos", *flags & FLAG_TOS);
+ if (!tos_parse_symbolic(optarg, &tvm, 0x3F))
+ xtables_param_act(XTF_BAD_VALUE, "tos", "--tos", optarg);
+ info->tos_value = tvm.value;
+ info->tos_mask = tvm.mask;
+ if (invert)
+ info->invert = true;
+ *flags |= FLAG_TOS;
+ return true;
+ }
+ return false;
+}
+
+static void tos_mt_check(unsigned int flags)
+{
+ if (flags == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "tos: --tos parameter required");
+}
+
+static void tos_mt_print_v0(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct ipt_tos_info *info = (const void *)match->data;
+
+ printf("tos match ");
+ if (info->invert)
+ printf("!");
+ if (numeric || !tos_try_print_symbolic("", info->tos, 0x3F))
+ printf("0x%02x ", info->tos);
+}
+
+static void tos_mt_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_tos_match_info *info = (const void *)match->data;
+
+ printf("tos match ");
+ if (info->invert)
+ printf("!");
+ if (numeric ||
+ !tos_try_print_symbolic("", info->tos_value, info->tos_mask))
+ printf("0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static void tos_mt_save_v0(const void *ip, const struct xt_entry_match *match)
+{
+ const struct ipt_tos_info *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+ printf("--tos 0x%02x ", info->tos);
+}
+
+static void tos_mt_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_tos_match_info *info = (const void *)match->data;
+
+ if (info->invert)
+ printf("! ");
+ printf("--tos 0x%02x/0x%02x ", info->tos_value, info->tos_mask);
+}
+
+static struct xtables_match tos_mt_reg[] = {
+ {
+ .version = XTABLES_VERSION,
+ .name = "tos",
+ .family = NFPROTO_IPV4,
+ .revision = 0,
+ .size = XT_ALIGN(sizeof(struct ipt_tos_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct ipt_tos_info)),
+ .help = tos_mt_help,
+ .parse = tos_mt_parse_v0,
+ .final_check = tos_mt_check,
+ .print = tos_mt_print_v0,
+ .save = tos_mt_save_v0,
+ .extra_opts = tos_mt_opts,
+ },
+ {
+ .version = XTABLES_VERSION,
+ .name = "tos",
+ .family = NFPROTO_UNSPEC,
+ .revision = 1,
+ .size = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_tos_match_info)),
+ .help = tos_mt_help,
+ .parse = tos_mt_parse,
+ .final_check = tos_mt_check,
+ .print = tos_mt_print,
+ .save = tos_mt_save,
+ .extra_opts = tos_mt_opts,
+ },
+};
+
+void libxt_tos_init(void)
+{
+ xtables_register_matches(tos_mt_reg, ARRAY_SIZE(tos_mt_reg));
+}
diff --git a/extensions/libxt_tos.man b/extensions/libxt_tos.man
new file mode 100644
index 0000000..ae73e63
--- /dev/null
+++ b/extensions/libxt_tos.man
@@ -0,0 +1,12 @@
+This module matches the 8-bit Type of Service field in the IPv4 header (i.e.
+including the "Precedence" bits) or the (also 8-bit) Priority field in the IPv6
+header.
+.TP
+[\fB!\fP] \fB\-\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets with the given TOS mark value. If a mask is specified, it is
+logically ANDed with the TOS mark before the comparison.
+.TP
+[\fB!\fP] \fB\-\-tos\fP \fIsymbol\fP
+You can specify a symbolic name when using the tos match for IPv4. The list of
+recognized TOS names can be obtained by calling iptables with \fB\-m tos \-h\fP.
+Note that this implies a mask of 0x3F, i.e. all but the ECN bits.
diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c
new file mode 100644
index 0000000..d9e2b1d
--- /dev/null
+++ b/extensions/libxt_u32.c
@@ -0,0 +1,284 @@
+/* Shared library add-on to iptables to add u32 matching,
+ * generalized matching on values found at packet offsets
+ *
+ * Detailed doc is in the kernel module source
+ * net/netfilter/xt_u32.c
+ *
+ * (C) 2002 by Don Cohen <don-netf@isis.cs3-inc.com>
+ * Released under the terms of GNU GPL v2
+ *
+ * Copyright © CC Computer Consultants GmbH, 2007
+ * Contact: <jengelh@computergmbh.de>
+ */
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <xtables.h>
+#include <linux/netfilter/xt_u32.h>
+
+static const struct option u32_opts[] = {
+ {"u32", 1, NULL, 'u'},
+ { .name = NULL }
+};
+
+static void u32_help(void)
+{
+ printf(
+ "u32 match options:\n"
+ "[!] --u32 tests\n"
+ "\t\t""tests := location \"=\" value | tests \"&&\" location \"=\" value\n"
+ "\t\t""value := range | value \",\" range\n"
+ "\t\t""range := number | number \":\" number\n"
+ "\t\t""location := number | location operator number\n"
+ "\t\t""operator := \"&\" | \"<<\" | \">>\" | \"@\"\n");
+}
+
+static void u32_dump(const struct xt_u32 *data)
+{
+ const struct xt_u32_test *ct;
+ unsigned int testind, i;
+
+ for (testind = 0; testind < data->ntests; ++testind) {
+ ct = &data->tests[testind];
+
+ if (testind > 0)
+ printf("&&");
+
+ printf("0x%x", ct->location[0].number);
+ for (i = 1; i < ct->nnums; ++i) {
+ switch (ct->location[i].nextop) {
+ case XT_U32_AND:
+ printf("&");
+ break;
+ case XT_U32_LEFTSH:
+ printf("<<");
+ break;
+ case XT_U32_RIGHTSH:
+ printf(">>");
+ break;
+ case XT_U32_AT:
+ printf("@");
+ break;
+ }
+ printf("0x%x", ct->location[i].number);
+ }
+
+ printf("=");
+ for (i = 0; i < ct->nvalues; ++i) {
+ if (i > 0)
+ printf(",");
+ if (ct->value[i].min == ct->value[i].max)
+ printf("0x%x", ct->value[i].min);
+ else
+ printf("0x%x:0x%x", ct->value[i].min,
+ ct->value[i].max);
+ }
+ }
+ printf(" ");
+}
+
+/* string_to_number() is not quite what we need here ... */
+static u_int32_t parse_number(char **s, int pos)
+{
+ u_int32_t number;
+ char *end;
+
+ errno = 0;
+ number = strtoul(*s, &end, 0);
+ if (end == *s)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %d: expected number", pos);
+ if (errno != 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %d: error reading number", pos);
+ *s = end;
+ return number;
+}
+
+static int u32_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_u32 *data = (void *)(*match)->data;
+ unsigned int testind = 0, locind = 0, valind = 0;
+ struct xt_u32_test *ct = &data->tests[testind]; /* current test */
+ char *arg = optarg; /* the argument string */
+ char *start = arg;
+ int state = 0;
+
+ if (c != 'u')
+ return 0;
+
+ data->invert = invert;
+
+ /*
+ * states:
+ * 0 = looking for numbers and operations,
+ * 1 = looking for ranges
+ */
+ while (1) {
+ /* read next operand/number or range */
+ while (isspace(*arg))
+ ++arg;
+
+ if (*arg == '\0') {
+ /* end of argument found */
+ if (state == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: abrupt end of input after location specifier");
+ if (valind == 0)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: test ended with no value specified");
+
+ ct->nnums = locind;
+ ct->nvalues = valind;
+ data->ntests = ++testind;
+
+ if (testind > XT_U32_MAXSIZE)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: too many \"&&\"s",
+ (unsigned int)(arg - start));
+ return 1;
+ }
+
+ if (state == 0) {
+ /*
+ * reading location: read a number if nothing read yet,
+ * otherwise either op number or = to end location spec
+ */
+ if (*arg == '=') {
+ if (locind == 0) {
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: "
+ "location spec missing",
+ (unsigned int)(arg - start));
+ } else {
+ ++arg;
+ state = 1;
+ }
+ } else {
+ if (locind != 0) {
+ /* need op before number */
+ if (*arg == '&') {
+ ct->location[locind].nextop = XT_U32_AND;
+ } else if (*arg == '<') {
+ if (*++arg != '<')
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: a second '<' was expected", (unsigned int)(arg - start));
+ ct->location[locind].nextop = XT_U32_LEFTSH;
+ } else if (*arg == '>') {
+ if (*++arg != '>')
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: a second '>' was expected", (unsigned int)(arg - start));
+ ct->location[locind].nextop = XT_U32_RIGHTSH;
+ } else if (*arg == '@') {
+ ct->location[locind].nextop = XT_U32_AT;
+ } else {
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: operator expected", (unsigned int)(arg - start));
+ }
+ ++arg;
+ }
+ /* now a number; string_to_number skips white space? */
+ ct->location[locind].number =
+ parse_number(&arg, arg - start);
+ if (++locind > XT_U32_MAXSIZE)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: too many operators", (unsigned int)(arg - start));
+ }
+ } else {
+ /*
+ * state 1 - reading values: read a range if nothing
+ * read yet, otherwise either ,range or && to end
+ * test spec
+ */
+ if (*arg == '&') {
+ if (*++arg != '&')
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: a second '&' was expected", (unsigned int)(arg - start));
+ if (valind == 0) {
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: value spec missing", (unsigned int)(arg - start));
+ } else {
+ ct->nnums = locind;
+ ct->nvalues = valind;
+ ct = &data->tests[++testind];
+ if (testind > XT_U32_MAXSIZE)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: too many \"&&\"s", (unsigned int)(arg - start));
+ ++arg;
+ state = 0;
+ locind = 0;
+ valind = 0;
+ }
+ } else { /* read value range */
+ if (valind > 0) { /* need , before number */
+ if (*arg != ',')
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: expected \",\" or \"&&\"", (unsigned int)(arg - start));
+ ++arg;
+ }
+ ct->value[valind].min =
+ parse_number(&arg, arg - start);
+
+ while (isspace(*arg))
+ ++arg;
+
+ if (*arg == ':') {
+ ++arg;
+ ct->value[valind].max =
+ parse_number(&arg, arg-start);
+ } else {
+ ct->value[valind].max =
+ ct->value[valind].min;
+ }
+
+ if (++valind > XT_U32_MAXSIZE)
+ xtables_error(PARAMETER_PROBLEM,
+ "u32: at char %u: too many \",\"s", (unsigned int)(arg - start));
+ }
+ }
+ }
+}
+
+static void u32_print(const void *ip, const struct xt_entry_match *match,
+ int numeric)
+{
+ const struct xt_u32 *data = (const void *)match->data;
+ printf("u32 ");
+ if (data->invert)
+ printf("! ");
+ u32_dump(data);
+}
+
+static void u32_save(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_u32 *data = (const void *)match->data;
+ if (data->invert)
+ printf("! ");
+ printf("--u32 ");
+ u32_dump(data);
+}
+
+static struct xtables_match u32_match = {
+ .name = "u32",
+ .family = NFPROTO_UNSPEC,
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_u32)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
+ .help = u32_help,
+ .parse = u32_parse,
+ .print = u32_print,
+ .save = u32_save,
+ .extra_opts = u32_opts,
+};
+
+void libxt_u32_init(void)
+{
+ xtables_register_match(&u32_match);
+}
diff --git a/extensions/libxt_u32.man b/extensions/libxt_u32.man
new file mode 100644
index 0000000..2ffab30
--- /dev/null
+++ b/extensions/libxt_u32.man
@@ -0,0 +1,129 @@
+U32 tests whether quantities of up to 4 bytes extracted from a packet have
+specified values. The specification of what to extract is general enough to
+find data at given offsets from tcp headers or payloads.
+.TP
+[\fB!\fP] \fB\-\-u32\fP \fItests\fP
+The argument amounts to a program in a small language described below.
+.IP
+tests := location "=" value | tests "&&" location "=" value
+.IP
+value := range | value "," range
+.IP
+range := number | number ":" number
+.PP
+a single number, \fIn\fR, is interpreted the same as \fIn:n\fR. \fIn:m\fR is
+interpreted as the range of numbers \fB>=n\fR and \fB<=m\fR.
+.IP "" 4
+location := number | location operator number
+.IP "" 4
+operator := "&" | "<<" | ">>" | "@"
+.PP
+The operators \fB&\fR, \fB<<\fR, \fB>>\fR and \fB&&\fR mean the same as in C.
+The \fB=\fR is really a set membership operator and the value syntax describes
+a set. The \fB@\fR operator is what allows moving to the next header and is
+described further below.
+.PP
+There are currently some artificial implementation limits on the size of the
+tests:
+.IP " *"
+no more than 10 of "\fB=\fR" (and 9 "\fB&&\fR"s) in the u32 argument
+.IP " *"
+no more than 10 ranges (and 9 commas) per value
+.IP " *"
+no more than 10 numbers (and 9 operators) per location
+.PP
+To describe the meaning of location, imagine the following machine that
+interprets it. There are three registers:
+.IP
+A is of type \fBchar *\fR, initially the address of the IP header
+.IP
+B and C are unsigned 32 bit integers, initially zero
+.PP
+The instructions are:
+.IP
+number B = number;
+.IP
+C = (*(A+B)<<24) + (*(A+B+1)<<16) + (*(A+B+2)<<8) + *(A+B+3)
+.IP
+&number C = C & number
+.IP
+<< number C = C << number
+.IP
+>> number C = C >> number
+.IP
+@number A = A + C; then do the instruction number
+.PP
+Any access of memory outside [skb\->data,skb\->end] causes the match to fail.
+Otherwise the result of the computation is the final value of C.
+.PP
+Whitespace is allowed but not required in the tests. However, the characters
+that do occur there are likely to require shell quoting, so it is a good idea
+to enclose the arguments in quotes.
+.PP
+Example:
+.IP
+match IP packets with total length >= 256
+.IP
+The IP header contains a total length field in bytes 2-3.
+.IP
+\-\-u32 "\fB0 & 0xFFFF = 0x100:0xFFFF\fP"
+.IP
+read bytes 0-3
+.IP
+AND that with 0xFFFF (giving bytes 2-3), and test whether that is in the range
+[0x100:0xFFFF]
+.PP
+Example: (more realistic, hence more complicated)
+.IP
+match ICMP packets with icmp type 0
+.IP
+First test that it is an ICMP packet, true iff byte 9 (protocol) = 1
+.IP
+\-\-u32 "\fB6 & 0xFF = 1 &&\fP ...
+.IP
+read bytes 6-9, use \fB&\fR to throw away bytes 6-8 and compare the result to
+1. Next test that it is not a fragment. (If so, it might be part of such a
+packet but we cannot always tell.) N.B.: This test is generally needed if you
+want to match anything beyond the IP header. The last 6 bits of byte 6 and all
+of byte 7 are 0 iff this is a complete packet (not a fragment). Alternatively,
+you can allow first fragments by only testing the last 5 bits of byte 6.
+.IP
+ ... \fB4 & 0x3FFF = 0 &&\fR ...
+.IP
+Last test: the first byte past the IP header (the type) is 0. This is where we
+have to use the @syntax. The length of the IP header (IHL) in 32 bit words is
+stored in the right half of byte 0 of the IP header itself.
+.IP
+ ... \fB0 >> 22 & 0x3C @ 0 >> 24 = 0\fR"
+.IP
+The first 0 means read bytes 0-3, \fB>>22\fR means shift that 22 bits to the
+right. Shifting 24 bits would give the first byte, so only 22 bits is four
+times that plus a few more bits. \fB&3C\fR then eliminates the two extra bits
+on the right and the first four bits of the first byte. For instance, if IHL=5,
+then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0-1 are (in
+binary) xxxx0101 yyzzzzzz, \fB>>22\fR gives the 10 bit value xxxx0101yy and
+\fB&3C\fR gives 010100. \fB@\fR means to use this number as a new offset into
+the packet, and read four bytes starting from there. This is the first 4 bytes
+of the ICMP payload, of which byte 0 is the ICMP type. Therefore, we simply
+shift the value 24 to the right to throw out all but the first byte and compare
+the result with 0.
+.PP
+Example:
+.IP
+TCP payload bytes 8-12 is any of 1, 2, 5 or 8
+.IP
+First we test that the packet is a tcp packet (similar to ICMP).
+.IP
+\-\-u32 "\fB6 & 0xFF = 6 &&\fP ...
+.IP
+Next, test that it is not a fragment (same as above).
+.IP
+ ... \fB0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8\fR"
+.IP
+\fB0>>22&3C\fR as above computes the number of bytes in the IP header. \fB@\fR
+makes this the new offset into the packet, which is the start of the TCP
+header. The length of the TCP header (again in 32 bit words) is the left half
+of byte 12 of the TCP header. The \fB12>>26&3C\fR computes this length in bytes
+(similar to the IP header before). "@" makes this the new offset, which is the
+start of the TCP payload. Finally, 8 reads bytes 8-12 of the payload and
+\fB=\fR checks whether the result is any of 1, 2, 5 or 8.
diff --git a/extensions/libipt_udp.c b/extensions/libxt_udp.c
index 1b36430..c75d9d8 100644
--- a/extensions/libipt_udp.c
+++ b/extensions/libxt_udp.c
@@ -4,31 +4,28 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
-#include <iptables.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
#include <netinet/in.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_tcpudp.h>
-/* Function which prints out usage message. */
-static void
-help(void)
+static void udp_help(void)
{
printf(
-"UDP v%s options:\n"
-" --source-port [!] port[:port]\n"
+"udp match options:\n"
+"[!] --source-port port[:port]\n"
" --sport ...\n"
" match source port(s)\n"
-" --destination-port [!] port[:port]\n"
+"[!] --destination-port port[:port]\n"
" --dport ...\n"
-" match destination port(s)\n",
-IPTABLES_VERSION);
+" match destination port(s)\n");
}
-static struct option opts[] = {
- { "source-port", 1, 0, '1' },
- { "sport", 1, 0, '1' }, /* synonym */
- { "destination-port", 1, 0, '2' },
- { "dport", 1, 0, '2' }, /* synonym */
- {0}
+static const struct option udp_opts[] = {
+ { "source-port", 1, NULL, '1' },
+ { "sport", 1, NULL, '1' }, /* synonym */
+ { "destination-port", 1, NULL, '2' },
+ { "dport", 1, NULL, '2' }, /* synonym */
+ { .name = NULL }
};
static void
@@ -39,26 +36,24 @@ parse_udp_ports(const char *portstring, u_int16_t *ports)
buffer = strdup(portstring);
if ((cp = strchr(buffer, ':')) == NULL)
- ports[0] = ports[1] = parse_port(buffer, "udp");
+ ports[0] = ports[1] = xtables_parse_port(buffer, "udp");
else {
*cp = '\0';
cp++;
- ports[0] = buffer[0] ? parse_port(buffer, "udp") : 0;
- ports[1] = cp[0] ? parse_port(cp, "udp") : 0xFFFF;
+ ports[0] = buffer[0] ? xtables_parse_port(buffer, "udp") : 0;
+ ports[1] = cp[0] ? xtables_parse_port(cp, "udp") : 0xFFFF;
if (ports[0] > ports[1])
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"invalid portrange (min > max)");
}
free(buffer);
}
-/* Initialize the match. */
-static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
+static void udp_init(struct xt_entry_match *m)
{
- struct ipt_udp *udpinfo = (struct ipt_udp *)m->data;
+ struct xt_udp *udpinfo = (struct xt_udp *)m->data;
udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
}
@@ -66,36 +61,32 @@ init(struct ipt_entry_match *m, unsigned int *nfcache)
#define UDP_SRC_PORTS 0x01
#define UDP_DST_PORTS 0x02
-/* Function which parses command options; returns true if it
- ate an option */
static int
-parse(int c, char **argv, int invert, unsigned int *flags,
- const struct ipt_entry *entry,
- unsigned int *nfcache,
- struct ipt_entry_match **match)
+udp_parse(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
{
- struct ipt_udp *udpinfo = (struct ipt_udp *)(*match)->data;
+ struct xt_udp *udpinfo = (struct xt_udp *)(*match)->data;
switch (c) {
case '1':
if (*flags & UDP_SRC_PORTS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--source-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_udp_ports(argv[optind-1], udpinfo->spts);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_udp_ports(optarg, udpinfo->spts);
if (invert)
- udpinfo->invflags |= IPT_UDP_INV_SRCPT;
+ udpinfo->invflags |= XT_UDP_INV_SRCPT;
*flags |= UDP_SRC_PORTS;
break;
case '2':
if (*flags & UDP_DST_PORTS)
- exit_error(PARAMETER_PROBLEM,
+ xtables_error(PARAMETER_PROBLEM,
"Only one `--destination-port' allowed");
- check_inverse(optarg, &invert, &optind, 0);
- parse_udp_ports(argv[optind-1], udpinfo->dpts);
+ xtables_check_inverse(optarg, &invert, &optind, 0, argv);
+ parse_udp_ports(optarg, udpinfo->dpts);
if (invert)
- udpinfo->invflags |= IPT_UDP_INV_DSTPT;
+ udpinfo->invflags |= XT_UDP_INV_DSTPT;
*flags |= UDP_DST_PORTS;
break;
@@ -106,12 +97,6 @@ parse(int c, char **argv, int invert, unsigned int *flags,
return 1;
}
-/* Final check; we don't care. */
-static void
-final_check(unsigned int flags)
-{
-}
-
static char *
port_to_service(int port)
{
@@ -155,33 +140,30 @@ print_ports(const char *name, u_int16_t min, u_int16_t max,
}
}
-/* Prints out the union ipt_matchinfo. */
static void
-print(const struct ipt_ip *ip,
- const struct ipt_entry_match *match, int numeric)
+udp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
- const struct ipt_udp *udp = (struct ipt_udp *)match->data;
+ const struct xt_udp *udp = (struct xt_udp *)match->data;
printf("udp ");
print_ports("spt", udp->spts[0], udp->spts[1],
- udp->invflags & IPT_UDP_INV_SRCPT,
+ udp->invflags & XT_UDP_INV_SRCPT,
numeric);
print_ports("dpt", udp->dpts[0], udp->dpts[1],
- udp->invflags & IPT_UDP_INV_DSTPT,
+ udp->invflags & XT_UDP_INV_DSTPT,
numeric);
- if (udp->invflags & ~IPT_UDP_INV_MASK)
+ if (udp->invflags & ~XT_UDP_INV_MASK)
printf("Unknown invflags: 0x%X ",
- udp->invflags & ~IPT_UDP_INV_MASK);
+ udp->invflags & ~XT_UDP_INV_MASK);
}
-/* Saves the union ipt_matchinfo in parsable form to stdout. */
-static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+static void udp_save(const void *ip, const struct xt_entry_match *match)
{
- const struct ipt_udp *udpinfo = (struct ipt_udp *)match->data;
+ const struct xt_udp *udpinfo = (struct xt_udp *)match->data;
if (udpinfo->spts[0] != 0
|| udpinfo->spts[1] != 0xFFFF) {
- if (udpinfo->invflags & IPT_UDP_INV_SRCPT)
+ if (udpinfo->invflags & XT_UDP_INV_SRCPT)
printf("! ");
if (udpinfo->spts[0]
!= udpinfo->spts[1])
@@ -195,7 +177,7 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
if (udpinfo->dpts[0] != 0
|| udpinfo->dpts[1] != 0xFFFF) {
- if (udpinfo->invflags & IPT_UDP_INV_DSTPT)
+ if (udpinfo->invflags & XT_UDP_INV_DSTPT)
printf("! ");
if (udpinfo->dpts[0]
!= udpinfo->dpts[1])
@@ -208,24 +190,21 @@ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
}
}
-static
-struct iptables_match udp = {
- .next = NULL,
+static struct xtables_match udp_match = {
+ .family = NFPROTO_UNSPEC,
.name = "udp",
- .version = IPTABLES_VERSION,
- .size = IPT_ALIGN(sizeof(struct ipt_udp)),
- .userspacesize = IPT_ALIGN(sizeof(struct ipt_udp)),
- .help = &help,
- .init = &init,
- .parse = &parse,
- .final_check = &final_check,
- .print = &print,
- .save = &save,
- .extra_opts = opts
+ .version = XTABLES_VERSION,
+ .size = XT_ALIGN(sizeof(struct xt_udp)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_udp)),
+ .help = udp_help,
+ .init = udp_init,
+ .parse = udp_parse,
+ .print = udp_print,
+ .save = udp_save,
+ .extra_opts = udp_opts,
};
-void
-ipt_udp_init(void)
+void libxt_udp_init(void)
{
- register_match(&udp);
+ xtables_register_match(&udp_match);
}
diff --git a/extensions/libxt_udp.man b/extensions/libxt_udp.man
new file mode 100644
index 0000000..5339c8e
--- /dev/null
+++ b/extensions/libxt_udp.man
@@ -0,0 +1,14 @@
+These extensions can be used if `\-\-protocol udp' is specified. It
+provides the following options:
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Source port or port range specification.
+See the description of the
+\fB\-\-source\-port\fP
+option of the TCP extension for details.
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Destination port or port range specification.
+See the description of the
+\fB\-\-destination\-port\fP
+option of the TCP extension for details.
diff --git a/extensions/matches4.man b/extensions/matches4.man
new file mode 100644
index 0000000..af6a1e9
--- /dev/null
+++ b/extensions/matches4.man
@@ -0,0 +1,1205 @@
+.SS addrtype
+This module matches packets based on their
+.B address type.
+Address types are used within the kernel networking stack and categorize
+addresses into various groups. The exact definition of that group depends on the specific layer three protocol.
+.PP
+The following address types are possible:
+.TP
+.BI "UNSPEC"
+an unspecified address (i.e. 0.0.0.0)
+.TP
+.BI "UNICAST"
+an unicast address
+.TP
+.BI "LOCAL"
+a local address
+.TP
+.BI "BROADCAST"
+a broadcast address
+.TP
+.BI "ANYCAST"
+an anycast packet
+.TP
+.BI "MULTICAST"
+a multicast address
+.TP
+.BI "BLACKHOLE"
+a blackhole address
+.TP
+.BI "UNREACHABLE"
+an unreachable address
+.TP
+.BI "PROHIBIT"
+a prohibited address
+.TP
+.BI "THROW"
+FIXME
+.TP
+.BI "NAT"
+FIXME
+.TP
+.BI "XRESOLVE"
+.TP
+[\fB!\fP] \fB\-\-src\-type\fP \fItype\fP
+Matches if the source address is of given type
+.TP
+[\fB!\fP] \fB\-\-dst\-type\fP \fItype\fP
+Matches if the destination address is of given type
+.TP
+.BI "\-\-limit\-iface\-in"
+The address type checking can be limited to the interface the packet is coming
+in. This option is only valid in the
+.BR PREROUTING ,
+.B INPUT
+and
+.B FORWARD
+chains. It cannot be specified with the
+\fB\-\-limit\-iface\-out\fP
+option.
+.TP
+\fB\-\-limit\-iface\-out\fP
+The address type checking can be limited to the interface the packet is going
+out. This option is only valid in the
+.BR POSTROUTING ,
+.B OUTPUT
+and
+.B FORWARD
+chains. It cannot be specified with the
+\fB\-\-limit\-iface\-in\fP
+option.
+.SS ah
+This module matches the SPIs in Authentication header of IPsec packets.
+.TP
+[\fB!\fP] \fB\-\-ahspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
+.SS cluster
+Allows you to deploy gateway and back-end load-sharing clusters without the
+need of load-balancers.
+.PP
+This match requires that all the nodes see the same packets. Thus, the cluster
+match decides if this node has to handle a packet given the following options:
+.TP
+\fB\-\-cluster\-total\-nodes\fP \fInum\fP
+Set number of total nodes in cluster.
+.TP
+[\fB!\fP] \fB\-\-cluster\-local\-node\fP \fInum\fP
+Set the local node number ID.
+.TP
+[\fB!\fP] \fB\-\-cluster\-local\-nodemask\fP \fImask\fP
+Set the local node number ID mask. You can use this option instead
+of \fB\-\-cluster\-local\-node\fP.
+.TP
+\fB\-\-cluster\-hash\-seed\fP \fIvalue\fP
+Set seed value of the Jenkins hash.
+.PP
+Example:
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth1 \-m cluster
+\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
+\-\-cluster\-hash\-seed 0xdeadbeef
+\-j MARK \-\-set-mark 0xffff
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth2 \-m cluster
+\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
+\-\-cluster\-hash\-seed 0xdeadbeef
+\-j MARK -\-set\-mark 0xffff
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth1
+\-m mark ! \-\-mark 0xffff \-j DROP
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth2
+\-m mark ! \-\-mark 0xffff \-j DROP
+.PP
+And the following commands to make all nodes see the same packets:
+.IP
+ip maddr add 01:00:5e:00:01:01 dev eth1
+.IP
+ip maddr add 01:00:5e:00:01:02 dev eth2
+.IP
+arptables \-A OUTPUT \-o eth1 \-\-h\-length 6
+\-j mangle \-\-mangle-mac-s 01:00:5e:00:01:01
+.IP
+arptables \-A INPUT \-i eth1 \-\-h-length 6
+\-\-destination-mac 01:00:5e:00:01:01
+\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
+.IP
+arptables \-A OUTPUT \-o eth2 \-\-h\-length 6
+\-j mangle \-\-mangle\-mac\-s 01:00:5e:00:01:02
+.IP
+arptables \-A INPUT \-i eth2 \-\-h\-length 6
+\-\-destination\-mac 01:00:5e:00:01:02
+\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
+.PP
+In the case of TCP connections, pickup facility has to be disabled
+to avoid marking TCP ACK packets coming in the reply direction as
+valid.
+.IP
+echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose
+.SS comment
+Allows you to add comments (up to 256 characters) to any rule.
+.TP
+\fB\-\-comment\fP \fIcomment\fP
+.TP
+Example:
+iptables \-A INPUT \-s 192.168.0.0/16 \-m comment \-\-comment "A privatized IP block"
+.SS connbytes
+Match by how many bytes or packets a connection (or one of the two
+flows constituting the connection) has transferred so far, or by
+average bytes per packet.
+.PP
+The counters are 64-bit and are thus not expected to overflow ;)
+.PP
+The primary use is to detect long-lived downloads and mark them to be
+scheduled using a lower priority band in traffic control.
+.PP
+The transferred bytes per connection can also be viewed through
+`conntrack \-L` and accessed via ctnetlink.
+.PP
+NOTE that for connections which have no accounting information, the match will
+always return false. The "net.netfilter.nf_conntrack_acct" sysctl flag controls
+whether \fBnew\fP connections will be byte/packet counted. Existing connection
+flows will not be gaining/losing a/the accounting structure when be sysctl flag
+is flipped.
+.TP
+[\fB!\fP] \fB\-\-connbytes\fP \fIfrom\fP[\fB:\fP\fIto\fP]
+match packets from a connection whose packets/bytes/average packet
+size is more than FROM and less than TO bytes/packets. if TO is
+omitted only FROM check is done. "!" is used to match packets not
+falling in the range.
+.TP
+\fB\-\-connbytes\-dir\fP {\fBoriginal\fP|\fBreply\fP|\fBboth\fP}
+which packets to consider
+.TP
+\fB\-\-connbytes\-mode\fP {\fBpackets\fP|\fBbytes\fP|\fBavgpkt\fP}
+whether to check the amount of packets, number of bytes transferred or
+the average size (in bytes) of all packets received so far. Note that
+when "both" is used together with "avgpkt", and data is going (mainly)
+only in one direction (for example HTTP), the average packet size will
+be about half of the actual data packets.
+.TP
+Example:
+iptables .. \-m connbytes \-\-connbytes 10000:100000 \-\-connbytes\-dir both \-\-connbytes\-mode bytes ...
+.SS connlimit
+Allows you to restrict the number of parallel connections to a server per
+client IP address (or client address block).
+.TP
+[\fB!\fP] \fB\-\-connlimit\-above\fP \fIn\fP
+Match if the number of existing connections is (not) above \fIn\fR.
+.TP
+\fB\-\-connlimit\-mask\fP \fIprefix_length\fP
+Group hosts using the prefix length. For IPv4, this must be a number between
+(including) 0 and 32. For IPv6, between 0 and 128.
+.P
+Examples:
+.TP
+# allow 2 telnet connections per client host
+iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit \-\-connlimit\-above 2 \-j REJECT
+.TP
+# you can also match the other way around:
+iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit ! \-\-connlimit\-above 2 \-j ACCEPT
+.TP
+# limit the number of parallel HTTP requests to 16 per class C sized \
+network (24 bit netmask)
+iptables \-p tcp \-\-syn \-\-dport 80 \-m connlimit \-\-connlimit\-above 16
+\-\-connlimit\-mask 24 \-j REJECT
+.TP
+# limit the number of parallel HTTP requests to 16 for the link local network
+(ipv6)
+ip6tables \-p tcp \-\-syn \-\-dport 80 \-s fe80::/64 \-m connlimit \-\-connlimit\-above
+16 \-\-connlimit\-mask 64 \-j REJECT
+.SS connmark
+This module matches the netfilter mark field associated with a connection
+(which can be set using the \fBCONNMARK\fR target below).
+.TP
+[\fB!\fP] \fB\-\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets in connections with the given mark value (if a mask is
+specified, this is logically ANDed with the mark before the comparison).
+.SS conntrack
+This module, when combined with connection tracking, allows access to the
+connection tracking state for this packet/connection.
+.TP
+[\fB!\fR] \fB\-\-ctstate\fP \fIstatelist\fP
+\fIstatelist\fR is a comma separated list of the connection states to match.
+Possible states are listed below.
+.TP
+[\fB!\fR] \fB\-\-ctproto\fP \fIl4proto\fP
+Layer-4 protocol to match (by number or name)
+.TP
+[\fB!\fR] \fB\-\-ctorigsrc\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctorigdst\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctreplsrc\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctrepldst\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+Match against original/reply source/destination address
+.TP
+[\fB!\fR] \fB\-\-ctorigsrcport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctorigdstport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctreplsrcport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctrepldstport\fP \fIport\fP
+Match against original/reply source/destination port (TCP/UDP/etc.) or GRE key.
+.TP
+[\fB!\fR] \fB\-\-ctstatus\fP \fIstatelist\fP
+\fIstatuslist\fR is a comma separated list of the connection statuses to match.
+Possible statuses are listed below.
+.TP
+[\fB!\fR] \fB\-\-ctexpire\fP \fItime\fP[\fB:\fP\fItime\fP]
+Match remaining lifetime in seconds against given value or range of values
+(inclusive)
+.TP
+\fB\-\-ctdir\fP {\fBORIGINAL\fP|\fBREPLY\fP}
+Match packets that are flowing in the specified direction. If this flag is not
+specified at all, matches packets in both directions.
+.PP
+States for \fB\-\-ctstate\fP:
+.TP
+\fBINVALID\fR
+meaning that the packet is associated with no known connection
+.TP
+\fBNEW\fR
+meaning that the packet has started a new connection, or otherwise associated
+with a connection which has not seen packets in both directions, and
+.TP
+\fBESTABLISHED\fR
+meaning that the packet is associated with a connection which has seen packets
+in both directions,
+.TP
+\fBRELATED\fR
+meaning that the packet is starting a new connection, but is associated with an
+existing connection, such as an FTP data transfer, or an ICMP error.
+.TP
+\fBSNAT\fR
+A virtual state, matching if the original source address differs from the reply
+destination.
+.TP
+\fBDNAT\fR
+A virtual state, matching if the original destination differs from the reply
+source.
+.PP
+Statuses for \fB\-\-ctstatus\fP:
+.TP
+\fBNONE\fR
+None of the below.
+.TP
+\fBEXPECTED\fR
+This is an expected connection (i.e. a conntrack helper set it up)
+.TP
+\fBSEEN_REPLY\fR
+Conntrack has seen packets in both directions.
+.TP
+\fBASSURED\fR
+Conntrack entry should never be early-expired.
+.TP
+\fBCONFIRMED\fR
+Connection is confirmed: originating packet has left box.
+.SS dccp
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-dccp\-types\fP \fImask\fP
+Match when the DCCP packet type is one of 'mask'. 'mask' is a comma-separated
+list of packet types. Packet types are:
+.BR "REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID" .
+.TP
+[\fB!\fP] \fB\-\-dccp\-option\fP \fInumber\fP
+Match if DCP option set.
+.SS dscp
+This module matches the 6 bit DSCP field within the TOS field in the
+IP header. DSCP has superseded TOS within the IETF.
+.TP
+[\fB!\fP] \fB\-\-dscp\fP \fIvalue\fP
+Match against a numeric (decimal or hex) value [0-63].
+.TP
+[\fB!\fP] \fB\-\-dscp\-class\fP \fIclass\fP
+Match the DiffServ class. This value may be any of the
+BE, EF, AFxx or CSx classes. It will then be converted
+into its according numeric value.
+.SS ecn
+This allows you to match the ECN bits of the IPv4 and TCP header. ECN is the Explicit Congestion Notification mechanism as specified in RFC3168
+.TP
+[\fB!\fP] \fB\-\-ecn\-tcp\-cwr\fP
+This matches if the TCP ECN CWR (Congestion Window Received) bit is set.
+.TP
+[\fB!\fP] \fB\-\-ecn\-tcp\-ece\fP
+This matches if the TCP ECN ECE (ECN Echo) bit is set.
+.TP
+[\fB!\fP] \fB\-\-ecn\-ip\-ect\fP \fInum\fP
+This matches a particular IPv4 ECT (ECN-Capable Transport). You have to specify
+a number between `0' and `3'.
+.SS esp
+This module matches the SPIs in ESP header of IPsec packets.
+.TP
+[\fB!\fP] \fB\-\-espspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
+.SS hashlimit
+\fBhashlimit\fR uses hash buckets to express a rate limiting match (like the
+\fBlimit\fR match) for a group of connections using a \fBsingle\fR iptables
+rule. Grouping can be done per-hostgroup (source and/or destination address)
+and/or per-port. It gives you the ability to express "\fIN\fR packets per time
+quantum per group":
+.TP
+matching on source host
+"1000 packets per second for every host in 192.168.0.0/16"
+.TP
+matching on source prot
+"100 packets per second for every service of 192.168.1.1"
+.TP
+matching on subnet
+"10000 packets per minute for every /28 subnet in 10.0.0.0/8"
+.PP
+A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and
+\fB\-\-hashlimit\-name\fP are required.
+.TP
+\fB\-\-hashlimit\-upto\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Match if the rate is below or equal to \fIamount\fR/quantum. It is specified as
+a number, with an optional time quantum suffix; the default is 3/hour.
+.TP
+\fB\-\-hashlimit\-above\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Match if the rate is above \fIamount\fR/quantum.
+.TP
+\fB\-\-hashlimit\-burst\fP \fIamount\fP
+Maximum initial number of packets to match: this number gets recharged by one
+every time the limit specified above is not reached, up to this number; the
+default is 5.
+.TP
+\fB\-\-hashlimit\-mode\fP {\fBsrcip\fP|\fBsrcport\fP|\fBdstip\fP|\fBdstport\fP}\fB,\fP...
+A comma-separated list of objects to take into consideration. If no
+\-\-hashlimit\-mode option is given, hashlimit acts like limit, but at the
+expensive of doing the hash housekeeping.
+.TP
+\fB\-\-hashlimit\-srcmask\fP \fIprefix\fP
+When \-\-hashlimit\-mode srcip is used, all source addresses encountered will be
+grouped according to the given prefix length and the so-created subnet will be
+subject to hashlimit. \fIprefix\fR must be between (inclusive) 0 and 32. Note
+that \-\-hashlimit\-srcmask 0 is basically doing the same thing as not specifying
+srcip for \-\-hashlimit\-mode, but is technically more expensive.
+.TP
+\fB\-\-hashlimit\-dstmask\fP \fIprefix\fP
+Like \-\-hashlimit\-srcmask, but for destination addresses.
+.TP
+\fB\-\-hashlimit\-name\fP \fIfoo\fP
+The name for the /proc/net/ipt_hashlimit/foo entry.
+.TP
+\fB\-\-hashlimit\-htable\-size\fP \fIbuckets\fP
+The number of buckets of the hash table
+.TP
+\fB\-\-hashlimit\-htable\-max\fP \fIentries\fP
+Maximum entries in the hash.
+.TP
+\fB\-\-hashlimit\-htable\-expire\fP \fImsec\fP
+After how many milliseconds do hash entries expire.
+.TP
+\fB\-\-hashlimit\-htable\-gcinterval\fP \fImsec\fP
+How many milliseconds between garbage collection intervals.
+.SS helper
+This module matches packets related to a specific conntrack-helper.
+.TP
+[\fB!\fP] \fB\-\-helper\fP \fIstring\fP
+Matches packets related to the specified conntrack-helper.
+.RS
+.PP
+string can be "ftp" for packets related to a ftp-session on default port.
+For other ports append \-portnr to the value, ie. "ftp\-2121".
+.PP
+Same rules apply for other conntrack-helpers.
+.RE
+.SS icmp
+This extension can be used if `\-\-protocol icmp' is specified. It
+provides the following option:
+.TP
+[\fB!\fP] \fB\-\-icmp\-type\fP {\fItype\fP[\fB/\fP\fIcode\fP]|\fItypename\fP}
+This allows specification of the ICMP type, which can be a numeric
+ICMP type, type/code pair, or one of the ICMP type names shown by the command
+.nf
+ iptables \-p icmp \-h
+.fi
+.SS iprange
+This matches on a given arbitrary range of IP addresses.
+.TP
+[\fB!\fR] \fB\-\-src\-range\fP \fIfrom\fP[\fB\-\fP\fIto\fP]
+Match source IP in the specified range.
+.TP
+[\fB!\fR] \fB\-\-dst\-range\fP \fIfrom\fP[\fB\-\fP\fIto\fP]
+Match destination IP in the specified range.
+.SS length
+This module matches the length of the layer-3 payload (e.g. layer-4 packet)
+of a packet against a specific value
+or range of values.
+.TP
+[\fB!\fP] \fB\-\-length\fP \fIlength\fP[\fB:\fP\fIlength\fP]
+.SS limit
+This module matches at a limited rate using a token bucket filter.
+A rule using this extension will match until this limit is reached
+(unless the `!' flag is used). It can be used in combination with the
+.B LOG
+target to give limited logging, for example.
+.TP
+\fB\-\-limit\fP \fIrate\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Maximum average matching rate: specified as a number, with an optional
+`/second', `/minute', `/hour', or `/day' suffix; the default is
+3/hour.
+.TP
+\fB\-\-limit\-burst\fP \fInumber\fP
+Maximum initial number of packets to match: this number gets
+recharged by one every time the limit specified above is not reached,
+up to this number; the default is 5.
+.SS mac
+.TP
+[\fB!\fP] \fB\-\-mac\-source\fP \fIaddress\fP
+Match source MAC address. It must be of the form XX:XX:XX:XX:XX:XX.
+Note that this only makes sense for packets coming from an Ethernet device
+and entering the
+.BR PREROUTING ,
+.B FORWARD
+or
+.B INPUT
+chains.
+.SS mark
+This module matches the netfilter mark field associated with a packet
+(which can be set using the
+.B MARK
+target below).
+.TP
+[\fB!\fP] \fB\-\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets with the given unsigned mark value (if a \fImask\fP is
+specified, this is logically ANDed with the \fImask\fP before the
+comparison).
+.SS multiport
+This module matches a set of source or destination ports. Up to 15
+ports can be specified. A port range (port:port) counts as two
+ports. It can only be used in conjunction with
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+[\fB!\fP] \fB\-\-source\-ports\fP,\fB\-\-sports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if the source port is one of the given ports. The flag
+\fB\-\-sports\fP
+is a convenient alias for this option. Multiple ports or port ranges are
+separated using a comma, and a port range is specified using a colon.
+\fB53,1024:65535\fP would therefore match ports 53 and all from 1024 through
+65535.
+.TP
+[\fB!\fP] \fB\-\-destination\-ports\fP,\fB\-\-dports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if the destination port is one of the given ports. The flag
+\fB\-\-dports\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-ports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if either the source or destination ports are equal to one of
+the given ports.
+.SS owner
+This module attempts to match various characteristics of the packet creator,
+for locally generated packets. This match is only valid in the OUTPUT and
+POSTROUTING chains. Forwarded packets do not have any socket associated with
+them. Packets from kernel threads do have a socket, but usually no owner.
+.TP
+[\fB!\fP] \fB\-\-uid\-owner\fP \fIusername\fP
+.TP
+[\fB!\fP] \fB\-\-uid\-owner\fP \fIuserid\fP[\fB\-\fP\fIuserid\fP]
+Matches if the packet socket's file structure (if it has one) is owned by the
+given user. You may also specify a numerical UID, or an UID range.
+.TP
+[\fB!\fP] \fB\-\-gid\-owner\fP \fIgroupname\fP
+.TP
+[\fB!\fP] \fB\-\-gid\-owner\fP \fIgroupid\fP[\fB\-\fP\fIgroupid\fP]
+Matches if the packet socket's file structure is owned by the given group.
+You may also specify a numerical GID, or a GID range.
+.TP
+[\fB!\fP] \fB\-\-socket\-exists\fP
+Matches if the packet is associated with a socket.
+.SS physdev
+This module matches on the bridge port input and output devices enslaved
+to a bridge device. This module is a part of the infrastructure that enables
+a transparent bridging IP firewall and is only useful for kernel versions
+above version 2.5.44.
+.TP
+[\fB!\fP] \fB\-\-physdev\-in\fP \fIname\fP
+Name of a bridge port via which a packet is received (only for
+packets entering the
+.BR INPUT ,
+.B FORWARD
+and
+.B PREROUTING
+chains). If the interface name ends in a "+", then any
+interface which begins with this name will match. If the packet didn't arrive
+through a bridge device, this packet won't match this option, unless '!' is used.
+.TP
+[\fB!\fP] \fB\-\-physdev\-out\fP \fIname\fP
+Name of a bridge port via which a packet is going to be sent (for packets
+entering the
+.BR FORWARD ,
+.B OUTPUT
+and
+.B POSTROUTING
+chains). If the interface name ends in a "+", then any
+interface which begins with this name will match. Note that in the
+.BR nat " and " mangle
+.B OUTPUT
+chains one cannot match on the bridge output port, however one can in the
+.B "filter OUTPUT"
+chain. If the packet won't leave by a bridge device or if it is yet unknown what
+the output device will be, then the packet won't match this option,
+unless '!' is used.
+.TP
+[\fB!\fP] \fB\-\-physdev\-is\-in\fP
+Matches if the packet has entered through a bridge interface.
+.TP
+[\fB!\fP] \fB\-\-physdev\-is\-out\fP
+Matches if the packet will leave through a bridge interface.
+.TP
+[\fB!\fP] \fB\-\-physdev\-is\-bridged\fP
+Matches if the packet is being bridged and therefore is not being routed.
+This is only useful in the FORWARD and POSTROUTING chains.
+.SS pkttype
+This module matches the link-layer packet type.
+.TP
+[\fB!\fP] \fB\-\-pkt\-type\fP {\fBunicast\fP|\fBbroadcast\fP|\fBmulticast\fP}
+.SS policy
+This modules matches the policy used by IPsec for handling a packet.
+.TP
+\fB\-\-dir\fP {\fBin\fP|\fBout\fP}
+Used to select whether to match the policy used for decapsulation or the
+policy that will be used for encapsulation.
+.B in
+is valid in the
+.B PREROUTING, INPUT and FORWARD
+chains,
+.B out
+is valid in the
+.B POSTROUTING, OUTPUT and FORWARD
+chains.
+.TP
+\fB\-\-pol\fP {\fBnone\fP|\fBipsec\fP}
+Matches if the packet is subject to IPsec processing.
+.TP
+\fB\-\-strict\fP
+Selects whether to match the exact policy or match if any rule of
+the policy matches the given policy.
+.TP
+[\fB!\fP] \fB\-\-reqid\fP \fIid\fP
+Matches the reqid of the policy rule. The reqid can be specified with
+.B setkey(8)
+using
+.B unique:id
+as level.
+.TP
+[\fB!\fP] \fB\-\-spi\fP \fIspi\fP
+Matches the SPI of the SA.
+.TP
+[\fB!\fP] \fB\-\-proto\fP {\fBah\fP|\fBesp\fP|\fBipcomp\fP}
+Matches the encapsulation protocol.
+.TP
+[\fB!\fP] \fB\-\-mode\fP {\fBtunnel\fP|\fBtransport\fP}
+Matches the encapsulation mode.
+.TP
+[\fB!\fP] \fB\-\-tunnel\-src\fP \fIaddr\fP[\fB/\fP\fImask\fP]
+Matches the source end-point address of a tunnel mode SA.
+Only valid with \fB\-\-mode tunnel\fP.
+.TP
+[\fB!\fP] \fB\-\-tunnel\-dst\fP \fIaddr\fP[\fB/\fP\fImask\fP]
+Matches the destination end-point address of a tunnel mode SA.
+Only valid with \fB\-\-mode tunnel\fP.
+.TP
+\fB\-\-next\fP
+Start the next element in the policy specification. Can only be used with
+\fB\-\-strict\fP.
+.SS quota
+Implements network quotas by decrementing a byte counter with each
+packet.
+.TP
+\fB\-\-quota\fP \fIbytes\fP
+The quota in bytes.
+.P
+.SS rateest
+The rate estimator can match on estimated rates as collected by the RATEEST
+target. It supports matching on absolute bps/pps values, comparing two rate
+estimators and matching on the difference between two rate estimators.
+.TP
+\fB\-\-rateest1\fP \fIname\fP
+Name of the first rate estimator.
+.TP
+\fB\-\-rateest2\fP \fIname\fP
+Name of the second rate estimator (if difference is to be calculated).
+.TP
+\fB\-\-rateest\-delta\fP
+Compare difference(s) to given rate(s)
+.TP
+\fB\-\-rateest1\-bps\fP \fIvalue\fP
+.TP
+\fB\-\-rateest2\-bps\fP \fIvalue\fP
+Compare bytes per second.
+.TP
+\fB\-\-rateest1\-pps\fP \fIvalue\fP
+.TP
+\fB\-\-rateest2\-pps\fP \fIvalue\fP
+Compare packets per second.
+.TP
+[\fB!\fP] \fB\-\-rateest\-lt\fP
+Match if rate is less than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-gt\fP
+Match if rate is greater than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-eq\fP
+Match if rate is equal to given rate/estimator.
+.PP
+Example: This is what can be used to route outgoing data connections from an
+FTP server over two lines based on the available bandwidth at the time the data
+connection was started:
+.PP
+# Estimate outgoing rates
+.PP
+iptables \-t mangle \-A POSTROUTING \-o eth0 \-j RATEEST \-\-rateest\-name eth0
+\-\-rateest\-interval 250ms \-\-rateest\-ewma 0.5s
+.PP
+iptables \-t mangle \-A POSTROUTING \-o ppp0 \-j RATEEST \-\-rateest\-name ppp0
+\-\-rateest\-interval 250ms \-\-rateest\-ewma 0.5s
+.PP
+# Mark based on available bandwidth
+.PP
+iptables \-t mangle \-A balance \-m conntrack \-\-ctstate NEW \-m helper \-\-helper ftp
+\-m rateest \-\-rateest\-delta \-\-rateest1 eth0 \-\-rateest\-bps1 2.5mbit \-\-rateest\-gt
+\-\-rateest2 ppp0 \-\-rateest\-bps2 2mbit \-j CONNMARK \-\-set\-mark 1
+.PP
+iptables \-t mangle \-A balance \-m conntrack \-\-ctstate NEW \-m helper \-\-helper ftp
+\-m rateest \-\-rateest\-delta \-\-rateest1 ppp0 \-\-rateest\-bps1 2mbit \-\-rateest\-gt
+\-\-rateest2 eth0 \-\-rateest\-bps2 2.5mbit \-j CONNMARK \-\-set\-mark 2
+.PP
+iptables \-t mangle \-A balance \-j CONNMARK \-\-restore\-mark
+.SS realm
+This matches the routing realm. Routing realms are used in complex routing
+setups involving dynamic routing protocols like BGP.
+.TP
+[\fB!\fP] \fB\-\-realm\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+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).
+.SS recent
+Allows you to dynamically create a list of IP addresses and then match against
+that list in a few different ways.
+.PP
+For example, you can create a "badguy" list out of people attempting to connect
+to port 139 on your firewall and then DROP all future packets from them without
+considering them.
+.PP
+\fB\-\-set\fP, \fB\-\-rcheck\fP, \fB\-\-update\fP and \fB\-\-remove\fP are
+mutually exclusive.
+.TP
+\fB\-\-name\fP \fIname\fP
+Specify the list to use for the commands. If no name is given then
+\fBDEFAULT\fR will be used.
+.TP
+[\fB!\fR] \fB\-\-set\fP
+This will add the source address of the packet to the list. If the source
+address is already in the list, this will update the existing entry. This will
+always return success (or failure if \fB!\fR is passed in).
+.TP
+\fB\-\-rsource\fP
+Match/save the source address of each packet in the recent list table. This
+is the default.
+.TP
+\fB\-\-rdest\fP
+Match/save the destination address of each packet in the recent list table.
+.TP
+[\fB!\fR] \fB\-\-rcheck\fP
+Check if the source address of the packet is currently in the list.
+.TP
+[\fB!\fR] \fB\-\-update\fP
+Like \fB\-\-rcheck\fP, except it will update the "last seen" timestamp if it
+matches.
+.TP
+[\fB!\fR] \fB\-\-remove\fP
+Check if the source address of the packet is currently in the list and if so
+that address will be removed from the list and the rule will return true. If
+the address is not found, false is returned.
+.TP
+\fB\-\-seconds\fP \fIseconds\fP
+This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and was seen within the last given number of seconds.
+.TP
+\fB\-\-hitcount\fP \fIhits\fP
+This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and packets had been received greater than or equal to
+the given value. This option may be used along with \fB\-\-seconds\fP to create
+an even narrower match requiring a certain number of hits within a specific
+time frame. The maximum value for the hitcount parameter is given by the
+"ip_pkt_list_tot" parameter of the xt_recent kernel module. Exceeding this
+value on the command line will cause the rule to be rejected.
+.TP
+\fB\-\-rttl\fP
+This option may only be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and the TTL of the current packet matches that of the
+packet which hit the \fB\-\-set\fP rule. This may be useful if you have problems
+with people faking their source address in order to DoS you via this module by
+disallowing others access to your site by sending bogus packets to you.
+.PP
+Examples:
+.IP
+iptables \-A FORWARD \-m recent \-\-name badguy \-\-rcheck \-\-seconds 60 \-j DROP
+.IP
+iptables \-A FORWARD \-p tcp \-i eth0 \-\-dport 139 \-m recent \-\-name badguy \-\-set \-j DROP
+.PP
+Steve's ipt_recent website (http://snowman.net/projects/ipt_recent/) also has
+some examples of usage.
+.PP
+\fB/proc/net/xt_recent/*\fR are the current lists of addresses and information
+about each entry of each list.
+.PP
+Each file in \fB/proc/net/xt_recent/\fR can be read from to see the current
+list or written two using the following commands to modify the list:
+.TP
+\fBecho +\fR\fIaddr\fR\fB >/proc/net/xt_recent/DEFAULT\fR
+to add \fIaddr\fR to the DEFAULT list
+.TP
+\fBecho \-\fP\fIaddr\fP\fB >/proc/net/xt_recent/DEFAULT\fP
+to remove \fIaddr\fR from the DEFAULT list
+.TP
+\fBecho / >/proc/net/xt_recent/DEFAULT\fR
+to flush the DEFAULT list (remove all entries).
+.PP
+The module itself accepts parameters, defaults shown:
+.TP
+\fBip_list_tot\fR=\fI100\fR
+Number of addresses remembered per table.
+.TP
+\fBip_pkt_list_tot\fR=\fI20\fR
+Number of packets per address remembered.
+.TP
+\fBip_list_hash_size\fR=\fI0\fR
+Hash table size. 0 means to calculate it based on ip_list_tot, default: 512.
+.TP
+\fBip_list_perms\fR=\fI0644\fR
+Permissions for /proc/net/xt_recent/* files.
+.TP
+\fBip_list_uid\fR=\fI0\fR
+Numerical UID for ownership of /proc/net/xt_recent/* files.
+.TP
+\fBip_list_gid\fR=\fI0\fR
+Numerical GID for ownership of /proc/net/xt_recent/* files.
+.SS sctp
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-chunk\-types\fP {\fBall\fP|\fBany\fP|\fBonly\fP} \fIchunktype\fP[\fB:\fP\fIflags\fP] [...]
+The flag letter in upper case indicates that the flag is to match if set,
+in the lower case indicates to match if unset.
+
+Chunk types: DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK
+
+chunk type available flags
+.br
+DATA U B E u b e
+.br
+ABORT T t
+.br
+SHUTDOWN_COMPLETE T t
+
+(lowercase means flag should be "off", uppercase means "on")
+.P
+Examples:
+
+iptables \-A INPUT \-p sctp \-\-dport 80 \-j DROP
+
+iptables \-A INPUT \-p sctp \-\-chunk\-types any DATA,INIT \-j DROP
+
+iptables \-A INPUT \-p sctp \-\-chunk\-types any DATA:Be \-j ACCEPT
+.SS set
+This module matches IP sets which can be defined by ipset(8).
+.TP
+[\fB!\fP] \fB\-\-match\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP]...
+where flags are the comma separated list of
+.BR "src"
+and/or
+.BR "dst"
+specifications and there can be no more than six of them. Hence the command
+.IP
+ iptables \-A FORWARD \-m set \-\-match\-set test src,dst
+.IP
+will match packets, for which (if the set type is ipportmap) the source
+address and destination port pair can be found in the specified set. If
+the set type of the specified set is single dimension (for example ipmap),
+then the command will match packets for which the source address can be
+found in the specified set.
+.PP
+The option \fB\-\-match\-set\fR can be replaced by \fB\-\-set\fR if that does
+not clash with an option of other extensions.
+.PP
+Use of -m set requires that ipset kernel support is provided. As standard
+kernels do not ship this currently, the ipset or Xtables-addons package needs
+to be installed.
+.SS socket
+This matches if an open socket can be found by doing a socket lookup on the
+packet.
+.SS state
+This module, when combined with connection tracking, allows access to
+the connection tracking state for this packet.
+.TP
+[\fB!\fP] \fB\-\-state\fP \fIstate\fP
+Where state is a comma separated list of the connection states to
+match. Possible states are
+.B INVALID
+meaning that the packet could not be identified for some reason which
+includes running out of memory and ICMP errors which don't correspond to any
+known connection,
+.B ESTABLISHED
+meaning that the packet is associated with a connection which has seen
+packets in both directions,
+.B NEW
+meaning that the packet has started a new connection, or otherwise
+associated with a connection which has not seen packets in both
+directions, and
+.B RELATED
+meaning that the packet is starting a new connection, but is
+associated with an existing connection, such as an FTP data transfer,
+or an ICMP error.
+.SS statistic
+This module matches packets based on some statistic condition.
+It supports two distinct modes settable with the
+\fB\-\-mode\fP
+option.
+.PP
+Supported options:
+.TP
+\fB\-\-mode\fP \fImode\fP
+Set the matching mode of the matching rule, supported modes are
+.B random
+and
+.B nth.
+.TP
+\fB\-\-probability\fP \fIp\fP
+Set the probability from 0 to 1 for a packet to be randomly
+matched. It works only with the
+.B random
+mode.
+.TP
+\fB\-\-every\fP \fIn\fP
+Match one packet every nth packet. It works only with the
+.B nth
+mode (see also the
+\fB\-\-packet\fP
+option).
+.TP
+\fB\-\-packet\fP \fIp\fP
+Set the initial counter value (0 <= p <= n\-1, default 0) for the
+.B nth
+mode.
+.SS string
+This modules matches a given string by using some pattern matching strategy. It requires a linux kernel >= 2.6.14.
+.TP
+\fB\-\-algo\fP {\fBbm\fP|\fBkmp\fP}
+Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)
+.TP
+\fB\-\-from\fP \fIoffset\fP
+Set the offset from which it starts looking for any matching. If not passed, default is 0.
+.TP
+\fB\-\-to\fP \fIoffset\fP
+Set the offset from which it starts looking for any matching. If not passed, default is the packet size.
+.TP
+[\fB!\fP] \fB\-\-string\fP \fIpattern\fP
+Matches the given pattern.
+.TP
+[\fB!\fP] \fB\-\-hex\-string\fP \fIpattern\fP
+Matches the given pattern in hex notation.
+.SS tcp
+These extensions can be used if `\-\-protocol tcp' is specified. It
+provides the following options:
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Source port or port range specification. This can either be a service
+name or a port number. An inclusive range can also be specified,
+using the format \fIfirst\fP\fB:\fP\fIlast\fP.
+If the first port is omitted, "0" is assumed; if the last is omitted,
+"65535" is assumed.
+If the first port is greater than the second one they will be swapped.
+The flag
+\fB\-\-sport\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Destination port or port range specification. The flag
+\fB\-\-dport\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-tcp\-flags\fP \fImask\fP \fIcomp\fP
+Match when the TCP flags are as specified. The first argument \fImask\fP is the
+flags which we should examine, written as a comma-separated list, and
+the second argument \fIcomp\fP is a comma-separated list of flags which must be
+set. Flags are:
+.BR "SYN ACK FIN RST URG PSH ALL NONE" .
+Hence the command
+.nf
+ iptables \-A FORWARD \-p tcp \-\-tcp\-flags SYN,ACK,FIN,RST SYN
+.fi
+will only match packets with the SYN flag set, and the ACK, FIN and
+RST flags unset.
+.TP
+[\fB!\fP] \fB\-\-syn\fP
+Only match TCP packets with the SYN bit set and the ACK,RST and FIN bits
+cleared. Such packets are used to request TCP connection initiation;
+for example, blocking such packets coming in an interface will prevent
+incoming TCP connections, but outgoing TCP connections will be
+unaffected.
+It is equivalent to \fB\-\-tcp\-flags SYN,RST,ACK,FIN SYN\fP.
+If the "!" flag precedes the "\-\-syn", the sense of the
+option is inverted.
+.TP
+[\fB!\fP] \fB\-\-tcp\-option\fP \fInumber\fP
+Match if TCP option set.
+.SS tcpmss
+This matches the TCP MSS (maximum segment size) field of the TCP header. You can only use this on TCP SYN or SYN/ACK packets, since the MSS is only negotiated during the TCP handshake at connection startup time.
+.TP
+[\fB!\fP] \fB\-\-mss\fP \fIvalue\fP[\fB:\fP\fIvalue\fP]
+Match a given TCP MSS value or range.
+.SS time
+This matches if the packet arrival time/date is within a given range. All
+options are optional, but are ANDed when specified.
+.TP
+\fB\-\-datestart\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
+.TP
+\fB\-\-datestop\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
+.IP
+Only match during the given time, which must be in ISO 8601 "T" notation.
+The possible time range is 1970-01-01T00:00:00 to 2038-01-19T04:17:07.
+.IP
+If \-\-datestart or \-\-datestop are not specified, it will default to 1970-01-01
+and 2038-01-19, respectively.
+.TP
+\fB\-\-timestart\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
+.TP
+\fB\-\-timestop\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
+.IP
+Only match during the given daytime. The possible time range is 00:00:00 to
+23:59:59. Leading zeroes are allowed (e.g. "06:03") and correctly interpreted
+as base-10.
+.TP
+[\fB!\fR] \fB\-\-monthdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
+.IP
+Only match on the given days of the month. Possible values are \fB1\fR
+to \fB31\fR. Note that specifying \fB31\fR will of course not match
+on months which do not have a 31st day; the same goes for 28- or 29-day
+February.
+.TP
+[\fB!\fR] \fB\-\-weekdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
+.IP
+Only match on the given weekdays. Possible values are \fBMon\fR, \fBTue\fR,
+\fBWed\fR, \fBThu\fR, \fBFri\fR, \fBSat\fR, \fBSun\fR, or values from \fB1\fR
+to \fB7\fR, respectively. You may also use two-character variants (\fBMo\fP,
+\fBTu\fR, etc.).
+.TP
+\fB\-\-utc\fP
+.IP
+Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
+\fB\-\-timestart\fP and \fB\-\-timestop\fP to be UTC.
+.TP
+\fB\-\-localtz\fP
+.IP
+Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
+\fB\-\-timestart\fP and \fB\-\-timestop\fP to be local kernel time. (Default)
+.PP
+EXAMPLES. To match on weekends, use:
+.IP
+\-m time \-\-weekdays Sa,Su
+.PP
+Or, to match (once) on a national holiday block:
+.IP
+\-m time \-\-datestart 2007\-12\-24 \-\-datestop 2007\-12\-27
+.PP
+Since the stop time is actually inclusive, you would need the following stop
+time to not match the first second of the new day:
+.IP
+\-m time \-\-datestart 2007\-01\-01T17:00 \-\-datestop 2007\-01\-01T23:59:59
+.PP
+During lunch hour:
+.IP
+\-m time \-\-timestart 12:30 \-\-timestop 13:30
+.PP
+The fourth Friday in the month:
+.IP
+\-m time \-\-weekdays Fr \-\-monthdays 22,23,24,25,26,27,28
+.PP
+(Note that this exploits a certain mathematical property. It is not possible to
+say "fourth Thursday OR fourth Friday" in one rule. It is possible with
+multiple rules, though.)
+.SS tos
+This module matches the 8-bit Type of Service field in the IPv4 header (i.e.
+including the "Precedence" bits) or the (also 8-bit) Priority field in the IPv6
+header.
+.TP
+[\fB!\fP] \fB\-\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets with the given TOS mark value. If a mask is specified, it is
+logically ANDed with the TOS mark before the comparison.
+.TP
+[\fB!\fP] \fB\-\-tos\fP \fIsymbol\fP
+You can specify a symbolic name when using the tos match for IPv4. The list of
+recognized TOS names can be obtained by calling iptables with \fB\-m tos \-h\fP.
+Note that this implies a mask of 0x3F, i.e. all but the ECN bits.
+.SS ttl
+This module matches the time to live field in the IP header.
+.TP
+\fB\-\-ttl\-eq\fP \fIttl\fP
+Matches the given TTL value.
+.TP
+\fB\-\-ttl\-gt\fP \fIttl\fP
+Matches if TTL is greater than the given TTL value.
+.TP
+\fB\-\-ttl\-lt\fP \fIttl\fP
+Matches if TTL is less than the given TTL value.
+.SS u32
+U32 tests whether quantities of up to 4 bytes extracted from a packet have
+specified values. The specification of what to extract is general enough to
+find data at given offsets from tcp headers or payloads.
+.TP
+[\fB!\fP] \fB\-\-u32\fP \fItests\fP
+The argument amounts to a program in a small language described below.
+.IP
+tests := location "=" value | tests "&&" location "=" value
+.IP
+value := range | value "," range
+.IP
+range := number | number ":" number
+.PP
+a single number, \fIn\fR, is interpreted the same as \fIn:n\fR. \fIn:m\fR is
+interpreted as the range of numbers \fB>=n\fR and \fB<=m\fR.
+.IP "" 4
+location := number | location operator number
+.IP "" 4
+operator := "&" | "<<" | ">>" | "@"
+.PP
+The operators \fB&\fR, \fB<<\fR, \fB>>\fR and \fB&&\fR mean the same as in C.
+The \fB=\fR is really a set membership operator and the value syntax describes
+a set. The \fB@\fR operator is what allows moving to the next header and is
+described further below.
+.PP
+There are currently some artificial implementation limits on the size of the
+tests:
+.IP " *"
+no more than 10 of "\fB=\fR" (and 9 "\fB&&\fR"s) in the u32 argument
+.IP " *"
+no more than 10 ranges (and 9 commas) per value
+.IP " *"
+no more than 10 numbers (and 9 operators) per location
+.PP
+To describe the meaning of location, imagine the following machine that
+interprets it. There are three registers:
+.IP
+A is of type \fBchar *\fR, initially the address of the IP header
+.IP
+B and C are unsigned 32 bit integers, initially zero
+.PP
+The instructions are:
+.IP
+number B = number;
+.IP
+C = (*(A+B)<<24) + (*(A+B+1)<<16) + (*(A+B+2)<<8) + *(A+B+3)
+.IP
+&number C = C & number
+.IP
+<< number C = C << number
+.IP
+>> number C = C >> number
+.IP
+@number A = A + C; then do the instruction number
+.PP
+Any access of memory outside [skb\->data,skb\->end] causes the match to fail.
+Otherwise the result of the computation is the final value of C.
+.PP
+Whitespace is allowed but not required in the tests. However, the characters
+that do occur there are likely to require shell quoting, so it is a good idea
+to enclose the arguments in quotes.
+.PP
+Example:
+.IP
+match IP packets with total length >= 256
+.IP
+The IP header contains a total length field in bytes 2-3.
+.IP
+\-\-u32 "\fB0 & 0xFFFF = 0x100:0xFFFF\fP"
+.IP
+read bytes 0-3
+.IP
+AND that with 0xFFFF (giving bytes 2-3), and test whether that is in the range
+[0x100:0xFFFF]
+.PP
+Example: (more realistic, hence more complicated)
+.IP
+match ICMP packets with icmp type 0
+.IP
+First test that it is an ICMP packet, true iff byte 9 (protocol) = 1
+.IP
+\-\-u32 "\fB6 & 0xFF = 1 &&\fP ...
+.IP
+read bytes 6-9, use \fB&\fR to throw away bytes 6-8 and compare the result to
+1. Next test that it is not a fragment. (If so, it might be part of such a
+packet but we cannot always tell.) N.B.: This test is generally needed if you
+want to match anything beyond the IP header. The last 6 bits of byte 6 and all
+of byte 7 are 0 iff this is a complete packet (not a fragment). Alternatively,
+you can allow first fragments by only testing the last 5 bits of byte 6.
+.IP
+ ... \fB4 & 0x3FFF = 0 &&\fR ...
+.IP
+Last test: the first byte past the IP header (the type) is 0. This is where we
+have to use the @syntax. The length of the IP header (IHL) in 32 bit words is
+stored in the right half of byte 0 of the IP header itself.
+.IP
+ ... \fB0 >> 22 & 0x3C @ 0 >> 24 = 0\fR"
+.IP
+The first 0 means read bytes 0-3, \fB>>22\fR means shift that 22 bits to the
+right. Shifting 24 bits would give the first byte, so only 22 bits is four
+times that plus a few more bits. \fB&3C\fR then eliminates the two extra bits
+on the right and the first four bits of the first byte. For instance, if IHL=5,
+then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0-1 are (in
+binary) xxxx0101 yyzzzzzz, \fB>>22\fR gives the 10 bit value xxxx0101yy and
+\fB&3C\fR gives 010100. \fB@\fR means to use this number as a new offset into
+the packet, and read four bytes starting from there. This is the first 4 bytes
+of the ICMP payload, of which byte 0 is the ICMP type. Therefore, we simply
+shift the value 24 to the right to throw out all but the first byte and compare
+the result with 0.
+.PP
+Example:
+.IP
+TCP payload bytes 8-12 is any of 1, 2, 5 or 8
+.IP
+First we test that the packet is a tcp packet (similar to ICMP).
+.IP
+\-\-u32 "\fB6 & 0xFF = 6 &&\fP ...
+.IP
+Next, test that it is not a fragment (same as above).
+.IP
+ ... \fB0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8\fR"
+.IP
+\fB0>>22&3C\fR as above computes the number of bytes in the IP header. \fB@\fR
+makes this the new offset into the packet, which is the start of the TCP
+header. The length of the TCP header (again in 32 bit words) is the left half
+of byte 12 of the TCP header. The \fB12>>26&3C\fR computes this length in bytes
+(similar to the IP header before). "@" makes this the new offset, which is the
+start of the TCP payload. Finally, 8 reads bytes 8-12 of the payload and
+\fB=\fR checks whether the result is any of 1, 2, 5 or 8.
+.SS udp
+These extensions can be used if `\-\-protocol udp' is specified. It
+provides the following options:
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Source port or port range specification.
+See the description of the
+\fB\-\-source\-port\fP
+option of the TCP extension for details.
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Destination port or port range specification.
+See the description of the
+\fB\-\-destination\-port\fP
+option of the TCP extension for details.
+.SS unclean
+This module takes no options, but attempts to match packets which seem
+malformed or unusual. This is regarded as experimental.
diff --git a/extensions/matches6.man b/extensions/matches6.man
new file mode 100644
index 0000000..6ca0a1b
--- /dev/null
+++ b/extensions/matches6.man
@@ -0,0 +1,1060 @@
+.SS cluster
+Allows you to deploy gateway and back-end load-sharing clusters without the
+need of load-balancers.
+.PP
+This match requires that all the nodes see the same packets. Thus, the cluster
+match decides if this node has to handle a packet given the following options:
+.TP
+\fB\-\-cluster\-total\-nodes\fP \fInum\fP
+Set number of total nodes in cluster.
+.TP
+[\fB!\fP] \fB\-\-cluster\-local\-node\fP \fInum\fP
+Set the local node number ID.
+.TP
+[\fB!\fP] \fB\-\-cluster\-local\-nodemask\fP \fImask\fP
+Set the local node number ID mask. You can use this option instead
+of \fB\-\-cluster\-local\-node\fP.
+.TP
+\fB\-\-cluster\-hash\-seed\fP \fIvalue\fP
+Set seed value of the Jenkins hash.
+.PP
+Example:
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth1 \-m cluster
+\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
+\-\-cluster\-hash\-seed 0xdeadbeef
+\-j MARK \-\-set-mark 0xffff
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth2 \-m cluster
+\-\-cluster\-total\-nodes 2 \-\-cluster\-local\-node 1
+\-\-cluster\-hash\-seed 0xdeadbeef
+\-j MARK -\-set\-mark 0xffff
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth1
+\-m mark ! \-\-mark 0xffff \-j DROP
+.IP
+iptables \-A PREROUTING \-t mangle \-i eth2
+\-m mark ! \-\-mark 0xffff \-j DROP
+.PP
+And the following commands to make all nodes see the same packets:
+.IP
+ip maddr add 01:00:5e:00:01:01 dev eth1
+.IP
+ip maddr add 01:00:5e:00:01:02 dev eth2
+.IP
+arptables \-A OUTPUT \-o eth1 \-\-h\-length 6
+\-j mangle \-\-mangle-mac-s 01:00:5e:00:01:01
+.IP
+arptables \-A INPUT \-i eth1 \-\-h-length 6
+\-\-destination-mac 01:00:5e:00:01:01
+\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
+.IP
+arptables \-A OUTPUT \-o eth2 \-\-h\-length 6
+\-j mangle \-\-mangle\-mac\-s 01:00:5e:00:01:02
+.IP
+arptables \-A INPUT \-i eth2 \-\-h\-length 6
+\-\-destination\-mac 01:00:5e:00:01:02
+\-j mangle \-\-mangle\-mac\-d 00:zz:yy:xx:5a:27
+.PP
+In the case of TCP connections, pickup facility has to be disabled
+to avoid marking TCP ACK packets coming in the reply direction as
+valid.
+.IP
+echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose
+.SS comment
+Allows you to add comments (up to 256 characters) to any rule.
+.TP
+\fB\-\-comment\fP \fIcomment\fP
+.TP
+Example:
+iptables \-A INPUT \-s 192.168.0.0/16 \-m comment \-\-comment "A privatized IP block"
+.SS connbytes
+Match by how many bytes or packets a connection (or one of the two
+flows constituting the connection) has transferred so far, or by
+average bytes per packet.
+.PP
+The counters are 64-bit and are thus not expected to overflow ;)
+.PP
+The primary use is to detect long-lived downloads and mark them to be
+scheduled using a lower priority band in traffic control.
+.PP
+The transferred bytes per connection can also be viewed through
+`conntrack \-L` and accessed via ctnetlink.
+.PP
+NOTE that for connections which have no accounting information, the match will
+always return false. The "net.netfilter.nf_conntrack_acct" sysctl flag controls
+whether \fBnew\fP connections will be byte/packet counted. Existing connection
+flows will not be gaining/losing a/the accounting structure when be sysctl flag
+is flipped.
+.TP
+[\fB!\fP] \fB\-\-connbytes\fP \fIfrom\fP[\fB:\fP\fIto\fP]
+match packets from a connection whose packets/bytes/average packet
+size is more than FROM and less than TO bytes/packets. if TO is
+omitted only FROM check is done. "!" is used to match packets not
+falling in the range.
+.TP
+\fB\-\-connbytes\-dir\fP {\fBoriginal\fP|\fBreply\fP|\fBboth\fP}
+which packets to consider
+.TP
+\fB\-\-connbytes\-mode\fP {\fBpackets\fP|\fBbytes\fP|\fBavgpkt\fP}
+whether to check the amount of packets, number of bytes transferred or
+the average size (in bytes) of all packets received so far. Note that
+when "both" is used together with "avgpkt", and data is going (mainly)
+only in one direction (for example HTTP), the average packet size will
+be about half of the actual data packets.
+.TP
+Example:
+iptables .. \-m connbytes \-\-connbytes 10000:100000 \-\-connbytes\-dir both \-\-connbytes\-mode bytes ...
+.SS connlimit
+Allows you to restrict the number of parallel connections to a server per
+client IP address (or client address block).
+.TP
+[\fB!\fP] \fB\-\-connlimit\-above\fP \fIn\fP
+Match if the number of existing connections is (not) above \fIn\fR.
+.TP
+\fB\-\-connlimit\-mask\fP \fIprefix_length\fP
+Group hosts using the prefix length. For IPv4, this must be a number between
+(including) 0 and 32. For IPv6, between 0 and 128.
+.P
+Examples:
+.TP
+# allow 2 telnet connections per client host
+iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit \-\-connlimit\-above 2 \-j REJECT
+.TP
+# you can also match the other way around:
+iptables \-A INPUT \-p tcp \-\-syn \-\-dport 23 \-m connlimit ! \-\-connlimit\-above 2 \-j ACCEPT
+.TP
+# limit the number of parallel HTTP requests to 16 per class C sized \
+network (24 bit netmask)
+iptables \-p tcp \-\-syn \-\-dport 80 \-m connlimit \-\-connlimit\-above 16
+\-\-connlimit\-mask 24 \-j REJECT
+.TP
+# limit the number of parallel HTTP requests to 16 for the link local network
+(ipv6)
+ip6tables \-p tcp \-\-syn \-\-dport 80 \-s fe80::/64 \-m connlimit \-\-connlimit\-above
+16 \-\-connlimit\-mask 64 \-j REJECT
+.SS connmark
+This module matches the netfilter mark field associated with a connection
+(which can be set using the \fBCONNMARK\fR target below).
+.TP
+[\fB!\fP] \fB\-\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets in connections with the given mark value (if a mask is
+specified, this is logically ANDed with the mark before the comparison).
+.SS conntrack
+This module, when combined with connection tracking, allows access to the
+connection tracking state for this packet/connection.
+.TP
+[\fB!\fR] \fB\-\-ctstate\fP \fIstatelist\fP
+\fIstatelist\fR is a comma separated list of the connection states to match.
+Possible states are listed below.
+.TP
+[\fB!\fR] \fB\-\-ctproto\fP \fIl4proto\fP
+Layer-4 protocol to match (by number or name)
+.TP
+[\fB!\fR] \fB\-\-ctorigsrc\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctorigdst\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctreplsrc\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+.TP
+[\fB!\fR] \fB\-\-ctrepldst\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+Match against original/reply source/destination address
+.TP
+[\fB!\fR] \fB\-\-ctorigsrcport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctorigdstport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctreplsrcport\fP \fIport\fP
+.TP
+[\fB!\fR] \fB\-\-ctrepldstport\fP \fIport\fP
+Match against original/reply source/destination port (TCP/UDP/etc.) or GRE key.
+.TP
+[\fB!\fR] \fB\-\-ctstatus\fP \fIstatelist\fP
+\fIstatuslist\fR is a comma separated list of the connection statuses to match.
+Possible statuses are listed below.
+.TP
+[\fB!\fR] \fB\-\-ctexpire\fP \fItime\fP[\fB:\fP\fItime\fP]
+Match remaining lifetime in seconds against given value or range of values
+(inclusive)
+.TP
+\fB\-\-ctdir\fP {\fBORIGINAL\fP|\fBREPLY\fP}
+Match packets that are flowing in the specified direction. If this flag is not
+specified at all, matches packets in both directions.
+.PP
+States for \fB\-\-ctstate\fP:
+.TP
+\fBINVALID\fR
+meaning that the packet is associated with no known connection
+.TP
+\fBNEW\fR
+meaning that the packet has started a new connection, or otherwise associated
+with a connection which has not seen packets in both directions, and
+.TP
+\fBESTABLISHED\fR
+meaning that the packet is associated with a connection which has seen packets
+in both directions,
+.TP
+\fBRELATED\fR
+meaning that the packet is starting a new connection, but is associated with an
+existing connection, such as an FTP data transfer, or an ICMP error.
+.TP
+\fBSNAT\fR
+A virtual state, matching if the original source address differs from the reply
+destination.
+.TP
+\fBDNAT\fR
+A virtual state, matching if the original destination differs from the reply
+source.
+.PP
+Statuses for \fB\-\-ctstatus\fP:
+.TP
+\fBNONE\fR
+None of the below.
+.TP
+\fBEXPECTED\fR
+This is an expected connection (i.e. a conntrack helper set it up)
+.TP
+\fBSEEN_REPLY\fR
+Conntrack has seen packets in both directions.
+.TP
+\fBASSURED\fR
+Conntrack entry should never be early-expired.
+.TP
+\fBCONFIRMED\fR
+Connection is confirmed: originating packet has left box.
+.SS dccp
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-dccp\-types\fP \fImask\fP
+Match when the DCCP packet type is one of 'mask'. 'mask' is a comma-separated
+list of packet types. Packet types are:
+.BR "REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID" .
+.TP
+[\fB!\fP] \fB\-\-dccp\-option\fP \fInumber\fP
+Match if DCP option set.
+.SS dscp
+This module matches the 6 bit DSCP field within the TOS field in the
+IP header. DSCP has superseded TOS within the IETF.
+.TP
+[\fB!\fP] \fB\-\-dscp\fP \fIvalue\fP
+Match against a numeric (decimal or hex) value [0-63].
+.TP
+[\fB!\fP] \fB\-\-dscp\-class\fP \fIclass\fP
+Match the DiffServ class. This value may be any of the
+BE, EF, AFxx or CSx classes. It will then be converted
+into its according numeric value.
+.SS esp
+This module matches the SPIs in ESP header of IPsec packets.
+.TP
+[\fB!\fP] \fB\-\-espspi\fP \fIspi\fP[\fB:\fP\fIspi\fP]
+.SS hashlimit
+\fBhashlimit\fR uses hash buckets to express a rate limiting match (like the
+\fBlimit\fR match) for a group of connections using a \fBsingle\fR iptables
+rule. Grouping can be done per-hostgroup (source and/or destination address)
+and/or per-port. It gives you the ability to express "\fIN\fR packets per time
+quantum per group":
+.TP
+matching on source host
+"1000 packets per second for every host in 192.168.0.0/16"
+.TP
+matching on source prot
+"100 packets per second for every service of 192.168.1.1"
+.TP
+matching on subnet
+"10000 packets per minute for every /28 subnet in 10.0.0.0/8"
+.PP
+A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and
+\fB\-\-hashlimit\-name\fP are required.
+.TP
+\fB\-\-hashlimit\-upto\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Match if the rate is below or equal to \fIamount\fR/quantum. It is specified as
+a number, with an optional time quantum suffix; the default is 3/hour.
+.TP
+\fB\-\-hashlimit\-above\fP \fIamount\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Match if the rate is above \fIamount\fR/quantum.
+.TP
+\fB\-\-hashlimit\-burst\fP \fIamount\fP
+Maximum initial number of packets to match: this number gets recharged by one
+every time the limit specified above is not reached, up to this number; the
+default is 5.
+.TP
+\fB\-\-hashlimit\-mode\fP {\fBsrcip\fP|\fBsrcport\fP|\fBdstip\fP|\fBdstport\fP}\fB,\fP...
+A comma-separated list of objects to take into consideration. If no
+\-\-hashlimit\-mode option is given, hashlimit acts like limit, but at the
+expensive of doing the hash housekeeping.
+.TP
+\fB\-\-hashlimit\-srcmask\fP \fIprefix\fP
+When \-\-hashlimit\-mode srcip is used, all source addresses encountered will be
+grouped according to the given prefix length and the so-created subnet will be
+subject to hashlimit. \fIprefix\fR must be between (inclusive) 0 and 32. Note
+that \-\-hashlimit\-srcmask 0 is basically doing the same thing as not specifying
+srcip for \-\-hashlimit\-mode, but is technically more expensive.
+.TP
+\fB\-\-hashlimit\-dstmask\fP \fIprefix\fP
+Like \-\-hashlimit\-srcmask, but for destination addresses.
+.TP
+\fB\-\-hashlimit\-name\fP \fIfoo\fP
+The name for the /proc/net/ipt_hashlimit/foo entry.
+.TP
+\fB\-\-hashlimit\-htable\-size\fP \fIbuckets\fP
+The number of buckets of the hash table
+.TP
+\fB\-\-hashlimit\-htable\-max\fP \fIentries\fP
+Maximum entries in the hash.
+.TP
+\fB\-\-hashlimit\-htable\-expire\fP \fImsec\fP
+After how many milliseconds do hash entries expire.
+.TP
+\fB\-\-hashlimit\-htable\-gcinterval\fP \fImsec\fP
+How many milliseconds between garbage collection intervals.
+.SS helper
+This module matches packets related to a specific conntrack-helper.
+.TP
+[\fB!\fP] \fB\-\-helper\fP \fIstring\fP
+Matches packets related to the specified conntrack-helper.
+.RS
+.PP
+string can be "ftp" for packets related to a ftp-session on default port.
+For other ports append \-portnr to the value, ie. "ftp\-2121".
+.PP
+Same rules apply for other conntrack-helpers.
+.RE
+.SS iprange
+This matches on a given arbitrary range of IP addresses.
+.TP
+[\fB!\fR] \fB\-\-src\-range\fP \fIfrom\fP[\fB\-\fP\fIto\fP]
+Match source IP in the specified range.
+.TP
+[\fB!\fR] \fB\-\-dst\-range\fP \fIfrom\fP[\fB\-\fP\fIto\fP]
+Match destination IP in the specified range.
+.SS length
+This module matches the length of the layer-3 payload (e.g. layer-4 packet)
+of a packet against a specific value
+or range of values.
+.TP
+[\fB!\fP] \fB\-\-length\fP \fIlength\fP[\fB:\fP\fIlength\fP]
+.SS limit
+This module matches at a limited rate using a token bucket filter.
+A rule using this extension will match until this limit is reached
+(unless the `!' flag is used). It can be used in combination with the
+.B LOG
+target to give limited logging, for example.
+.TP
+\fB\-\-limit\fP \fIrate\fP[\fB/second\fP|\fB/minute\fP|\fB/hour\fP|\fB/day\fP]
+Maximum average matching rate: specified as a number, with an optional
+`/second', `/minute', `/hour', or `/day' suffix; the default is
+3/hour.
+.TP
+\fB\-\-limit\-burst\fP \fInumber\fP
+Maximum initial number of packets to match: this number gets
+recharged by one every time the limit specified above is not reached,
+up to this number; the default is 5.
+.SS mac
+.TP
+[\fB!\fP] \fB\-\-mac\-source\fP \fIaddress\fP
+Match source MAC address. It must be of the form XX:XX:XX:XX:XX:XX.
+Note that this only makes sense for packets coming from an Ethernet device
+and entering the
+.BR PREROUTING ,
+.B FORWARD
+or
+.B INPUT
+chains.
+.SS mark
+This module matches the netfilter mark field associated with a packet
+(which can be set using the
+.B MARK
+target below).
+.TP
+[\fB!\fP] \fB\-\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets with the given unsigned mark value (if a \fImask\fP is
+specified, this is logically ANDed with the \fImask\fP before the
+comparison).
+.SS multiport
+This module matches a set of source or destination ports. Up to 15
+ports can be specified. A port range (port:port) counts as two
+ports. It can only be used in conjunction with
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+[\fB!\fP] \fB\-\-source\-ports\fP,\fB\-\-sports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if the source port is one of the given ports. The flag
+\fB\-\-sports\fP
+is a convenient alias for this option. Multiple ports or port ranges are
+separated using a comma, and a port range is specified using a colon.
+\fB53,1024:65535\fP would therefore match ports 53 and all from 1024 through
+65535.
+.TP
+[\fB!\fP] \fB\-\-destination\-ports\fP,\fB\-\-dports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if the destination port is one of the given ports. The flag
+\fB\-\-dports\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-ports\fP \fIport\fP[\fB,\fP\fIport\fP|\fB,\fP\fIport\fP\fB:\fP\fIport\fP]...
+Match if either the source or destination ports are equal to one of
+the given ports.
+.SS owner
+This module attempts to match various characteristics of the packet creator,
+for locally generated packets. This match is only valid in the OUTPUT and
+POSTROUTING chains. Forwarded packets do not have any socket associated with
+them. Packets from kernel threads do have a socket, but usually no owner.
+.TP
+[\fB!\fP] \fB\-\-uid\-owner\fP \fIusername\fP
+.TP
+[\fB!\fP] \fB\-\-uid\-owner\fP \fIuserid\fP[\fB\-\fP\fIuserid\fP]
+Matches if the packet socket's file structure (if it has one) is owned by the
+given user. You may also specify a numerical UID, or an UID range.
+.TP
+[\fB!\fP] \fB\-\-gid\-owner\fP \fIgroupname\fP
+.TP
+[\fB!\fP] \fB\-\-gid\-owner\fP \fIgroupid\fP[\fB\-\fP\fIgroupid\fP]
+Matches if the packet socket's file structure is owned by the given group.
+You may also specify a numerical GID, or a GID range.
+.TP
+[\fB!\fP] \fB\-\-socket\-exists\fP
+Matches if the packet is associated with a socket.
+.SS physdev
+This module matches on the bridge port input and output devices enslaved
+to a bridge device. This module is a part of the infrastructure that enables
+a transparent bridging IP firewall and is only useful for kernel versions
+above version 2.5.44.
+.TP
+[\fB!\fP] \fB\-\-physdev\-in\fP \fIname\fP
+Name of a bridge port via which a packet is received (only for
+packets entering the
+.BR INPUT ,
+.B FORWARD
+and
+.B PREROUTING
+chains). If the interface name ends in a "+", then any
+interface which begins with this name will match. If the packet didn't arrive
+through a bridge device, this packet won't match this option, unless '!' is used.
+.TP
+[\fB!\fP] \fB\-\-physdev\-out\fP \fIname\fP
+Name of a bridge port via which a packet is going to be sent (for packets
+entering the
+.BR FORWARD ,
+.B OUTPUT
+and
+.B POSTROUTING
+chains). If the interface name ends in a "+", then any
+interface which begins with this name will match. Note that in the
+.BR nat " and " mangle
+.B OUTPUT
+chains one cannot match on the bridge output port, however one can in the
+.B "filter OUTPUT"
+chain. If the packet won't leave by a bridge device or if it is yet unknown what
+the output device will be, then the packet won't match this option,
+unless '!' is used.
+.TP
+[\fB!\fP] \fB\-\-physdev\-is\-in\fP
+Matches if the packet has entered through a bridge interface.
+.TP
+[\fB!\fP] \fB\-\-physdev\-is\-out\fP
+Matches if the packet will leave through a bridge interface.
+.TP
+[\fB!\fP] \fB\-\-physdev\-is\-bridged\fP
+Matches if the packet is being bridged and therefore is not being routed.
+This is only useful in the FORWARD and POSTROUTING chains.
+.SS pkttype
+This module matches the link-layer packet type.
+.TP
+[\fB!\fP] \fB\-\-pkt\-type\fP {\fBunicast\fP|\fBbroadcast\fP|\fBmulticast\fP}
+.SS policy
+This modules matches the policy used by IPsec for handling a packet.
+.TP
+\fB\-\-dir\fP {\fBin\fP|\fBout\fP}
+Used to select whether to match the policy used for decapsulation or the
+policy that will be used for encapsulation.
+.B in
+is valid in the
+.B PREROUTING, INPUT and FORWARD
+chains,
+.B out
+is valid in the
+.B POSTROUTING, OUTPUT and FORWARD
+chains.
+.TP
+\fB\-\-pol\fP {\fBnone\fP|\fBipsec\fP}
+Matches if the packet is subject to IPsec processing.
+.TP
+\fB\-\-strict\fP
+Selects whether to match the exact policy or match if any rule of
+the policy matches the given policy.
+.TP
+[\fB!\fP] \fB\-\-reqid\fP \fIid\fP
+Matches the reqid of the policy rule. The reqid can be specified with
+.B setkey(8)
+using
+.B unique:id
+as level.
+.TP
+[\fB!\fP] \fB\-\-spi\fP \fIspi\fP
+Matches the SPI of the SA.
+.TP
+[\fB!\fP] \fB\-\-proto\fP {\fBah\fP|\fBesp\fP|\fBipcomp\fP}
+Matches the encapsulation protocol.
+.TP
+[\fB!\fP] \fB\-\-mode\fP {\fBtunnel\fP|\fBtransport\fP}
+Matches the encapsulation mode.
+.TP
+[\fB!\fP] \fB\-\-tunnel\-src\fP \fIaddr\fP[\fB/\fP\fImask\fP]
+Matches the source end-point address of a tunnel mode SA.
+Only valid with \fB\-\-mode tunnel\fP.
+.TP
+[\fB!\fP] \fB\-\-tunnel\-dst\fP \fIaddr\fP[\fB/\fP\fImask\fP]
+Matches the destination end-point address of a tunnel mode SA.
+Only valid with \fB\-\-mode tunnel\fP.
+.TP
+\fB\-\-next\fP
+Start the next element in the policy specification. Can only be used with
+\fB\-\-strict\fP.
+.SS quota
+Implements network quotas by decrementing a byte counter with each
+packet.
+.TP
+\fB\-\-quota\fP \fIbytes\fP
+The quota in bytes.
+.P
+.SS rateest
+The rate estimator can match on estimated rates as collected by the RATEEST
+target. It supports matching on absolute bps/pps values, comparing two rate
+estimators and matching on the difference between two rate estimators.
+.TP
+\fB\-\-rateest1\fP \fIname\fP
+Name of the first rate estimator.
+.TP
+\fB\-\-rateest2\fP \fIname\fP
+Name of the second rate estimator (if difference is to be calculated).
+.TP
+\fB\-\-rateest\-delta\fP
+Compare difference(s) to given rate(s)
+.TP
+\fB\-\-rateest1\-bps\fP \fIvalue\fP
+.TP
+\fB\-\-rateest2\-bps\fP \fIvalue\fP
+Compare bytes per second.
+.TP
+\fB\-\-rateest1\-pps\fP \fIvalue\fP
+.TP
+\fB\-\-rateest2\-pps\fP \fIvalue\fP
+Compare packets per second.
+.TP
+[\fB!\fP] \fB\-\-rateest\-lt\fP
+Match if rate is less than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-gt\fP
+Match if rate is greater than given rate/estimator.
+.TP
+[\fB!\fP] \fB\-\-rateest\-eq\fP
+Match if rate is equal to given rate/estimator.
+.PP
+Example: This is what can be used to route outgoing data connections from an
+FTP server over two lines based on the available bandwidth at the time the data
+connection was started:
+.PP
+# Estimate outgoing rates
+.PP
+iptables \-t mangle \-A POSTROUTING \-o eth0 \-j RATEEST \-\-rateest\-name eth0
+\-\-rateest\-interval 250ms \-\-rateest\-ewma 0.5s
+.PP
+iptables \-t mangle \-A POSTROUTING \-o ppp0 \-j RATEEST \-\-rateest\-name ppp0
+\-\-rateest\-interval 250ms \-\-rateest\-ewma 0.5s
+.PP
+# Mark based on available bandwidth
+.PP
+iptables \-t mangle \-A balance \-m conntrack \-\-ctstate NEW \-m helper \-\-helper ftp
+\-m rateest \-\-rateest\-delta \-\-rateest1 eth0 \-\-rateest\-bps1 2.5mbit \-\-rateest\-gt
+\-\-rateest2 ppp0 \-\-rateest\-bps2 2mbit \-j CONNMARK \-\-set\-mark 1
+.PP
+iptables \-t mangle \-A balance \-m conntrack \-\-ctstate NEW \-m helper \-\-helper ftp
+\-m rateest \-\-rateest\-delta \-\-rateest1 ppp0 \-\-rateest\-bps1 2mbit \-\-rateest\-gt
+\-\-rateest2 eth0 \-\-rateest\-bps2 2.5mbit \-j CONNMARK \-\-set\-mark 2
+.PP
+iptables \-t mangle \-A balance \-j CONNMARK \-\-restore\-mark
+.SS recent
+Allows you to dynamically create a list of IP addresses and then match against
+that list in a few different ways.
+.PP
+For example, you can create a "badguy" list out of people attempting to connect
+to port 139 on your firewall and then DROP all future packets from them without
+considering them.
+.PP
+\fB\-\-set\fP, \fB\-\-rcheck\fP, \fB\-\-update\fP and \fB\-\-remove\fP are
+mutually exclusive.
+.TP
+\fB\-\-name\fP \fIname\fP
+Specify the list to use for the commands. If no name is given then
+\fBDEFAULT\fR will be used.
+.TP
+[\fB!\fR] \fB\-\-set\fP
+This will add the source address of the packet to the list. If the source
+address is already in the list, this will update the existing entry. This will
+always return success (or failure if \fB!\fR is passed in).
+.TP
+\fB\-\-rsource\fP
+Match/save the source address of each packet in the recent list table. This
+is the default.
+.TP
+\fB\-\-rdest\fP
+Match/save the destination address of each packet in the recent list table.
+.TP
+[\fB!\fR] \fB\-\-rcheck\fP
+Check if the source address of the packet is currently in the list.
+.TP
+[\fB!\fR] \fB\-\-update\fP
+Like \fB\-\-rcheck\fP, except it will update the "last seen" timestamp if it
+matches.
+.TP
+[\fB!\fR] \fB\-\-remove\fP
+Check if the source address of the packet is currently in the list and if so
+that address will be removed from the list and the rule will return true. If
+the address is not found, false is returned.
+.TP
+\fB\-\-seconds\fP \fIseconds\fP
+This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and was seen within the last given number of seconds.
+.TP
+\fB\-\-hitcount\fP \fIhits\fP
+This option must be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and packets had been received greater than or equal to
+the given value. This option may be used along with \fB\-\-seconds\fP to create
+an even narrower match requiring a certain number of hits within a specific
+time frame. The maximum value for the hitcount parameter is given by the
+"ip_pkt_list_tot" parameter of the xt_recent kernel module. Exceeding this
+value on the command line will cause the rule to be rejected.
+.TP
+\fB\-\-rttl\fP
+This option may only be used in conjunction with one of \fB\-\-rcheck\fP or
+\fB\-\-update\fP. When used, this will narrow the match to only happen when the
+address is in the list and the TTL of the current packet matches that of the
+packet which hit the \fB\-\-set\fP rule. This may be useful if you have problems
+with people faking their source address in order to DoS you via this module by
+disallowing others access to your site by sending bogus packets to you.
+.PP
+Examples:
+.IP
+iptables \-A FORWARD \-m recent \-\-name badguy \-\-rcheck \-\-seconds 60 \-j DROP
+.IP
+iptables \-A FORWARD \-p tcp \-i eth0 \-\-dport 139 \-m recent \-\-name badguy \-\-set \-j DROP
+.PP
+Steve's ipt_recent website (http://snowman.net/projects/ipt_recent/) also has
+some examples of usage.
+.PP
+\fB/proc/net/xt_recent/*\fR are the current lists of addresses and information
+about each entry of each list.
+.PP
+Each file in \fB/proc/net/xt_recent/\fR can be read from to see the current
+list or written two using the following commands to modify the list:
+.TP
+\fBecho +\fR\fIaddr\fR\fB >/proc/net/xt_recent/DEFAULT\fR
+to add \fIaddr\fR to the DEFAULT list
+.TP
+\fBecho \-\fP\fIaddr\fP\fB >/proc/net/xt_recent/DEFAULT\fP
+to remove \fIaddr\fR from the DEFAULT list
+.TP
+\fBecho / >/proc/net/xt_recent/DEFAULT\fR
+to flush the DEFAULT list (remove all entries).
+.PP
+The module itself accepts parameters, defaults shown:
+.TP
+\fBip_list_tot\fR=\fI100\fR
+Number of addresses remembered per table.
+.TP
+\fBip_pkt_list_tot\fR=\fI20\fR
+Number of packets per address remembered.
+.TP
+\fBip_list_hash_size\fR=\fI0\fR
+Hash table size. 0 means to calculate it based on ip_list_tot, default: 512.
+.TP
+\fBip_list_perms\fR=\fI0644\fR
+Permissions for /proc/net/xt_recent/* files.
+.TP
+\fBip_list_uid\fR=\fI0\fR
+Numerical UID for ownership of /proc/net/xt_recent/* files.
+.TP
+\fBip_list_gid\fR=\fI0\fR
+Numerical GID for ownership of /proc/net/xt_recent/* files.
+.SS sctp
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+.TP
+[\fB!\fP] \fB\-\-chunk\-types\fP {\fBall\fP|\fBany\fP|\fBonly\fP} \fIchunktype\fP[\fB:\fP\fIflags\fP] [...]
+The flag letter in upper case indicates that the flag is to match if set,
+in the lower case indicates to match if unset.
+
+Chunk types: DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK
+
+chunk type available flags
+.br
+DATA U B E u b e
+.br
+ABORT T t
+.br
+SHUTDOWN_COMPLETE T t
+
+(lowercase means flag should be "off", uppercase means "on")
+.P
+Examples:
+
+iptables \-A INPUT \-p sctp \-\-dport 80 \-j DROP
+
+iptables \-A INPUT \-p sctp \-\-chunk\-types any DATA,INIT \-j DROP
+
+iptables \-A INPUT \-p sctp \-\-chunk\-types any DATA:Be \-j ACCEPT
+.SS state
+This module, when combined with connection tracking, allows access to
+the connection tracking state for this packet.
+.TP
+[\fB!\fP] \fB\-\-state\fP \fIstate\fP
+Where state is a comma separated list of the connection states to
+match. Possible states are
+.B INVALID
+meaning that the packet could not be identified for some reason which
+includes running out of memory and ICMP errors which don't correspond to any
+known connection,
+.B ESTABLISHED
+meaning that the packet is associated with a connection which has seen
+packets in both directions,
+.B NEW
+meaning that the packet has started a new connection, or otherwise
+associated with a connection which has not seen packets in both
+directions, and
+.B RELATED
+meaning that the packet is starting a new connection, but is
+associated with an existing connection, such as an FTP data transfer,
+or an ICMP error.
+.SS statistic
+This module matches packets based on some statistic condition.
+It supports two distinct modes settable with the
+\fB\-\-mode\fP
+option.
+.PP
+Supported options:
+.TP
+\fB\-\-mode\fP \fImode\fP
+Set the matching mode of the matching rule, supported modes are
+.B random
+and
+.B nth.
+.TP
+\fB\-\-probability\fP \fIp\fP
+Set the probability from 0 to 1 for a packet to be randomly
+matched. It works only with the
+.B random
+mode.
+.TP
+\fB\-\-every\fP \fIn\fP
+Match one packet every nth packet. It works only with the
+.B nth
+mode (see also the
+\fB\-\-packet\fP
+option).
+.TP
+\fB\-\-packet\fP \fIp\fP
+Set the initial counter value (0 <= p <= n\-1, default 0) for the
+.B nth
+mode.
+.SS string
+This modules matches a given string by using some pattern matching strategy. It requires a linux kernel >= 2.6.14.
+.TP
+\fB\-\-algo\fP {\fBbm\fP|\fBkmp\fP}
+Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)
+.TP
+\fB\-\-from\fP \fIoffset\fP
+Set the offset from which it starts looking for any matching. If not passed, default is 0.
+.TP
+\fB\-\-to\fP \fIoffset\fP
+Set the offset from which it starts looking for any matching. If not passed, default is the packet size.
+.TP
+[\fB!\fP] \fB\-\-string\fP \fIpattern\fP
+Matches the given pattern.
+.TP
+[\fB!\fP] \fB\-\-hex\-string\fP \fIpattern\fP
+Matches the given pattern in hex notation.
+.SS tcp
+These extensions can be used if `\-\-protocol tcp' is specified. It
+provides the following options:
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Source port or port range specification. This can either be a service
+name or a port number. An inclusive range can also be specified,
+using the format \fIfirst\fP\fB:\fP\fIlast\fP.
+If the first port is omitted, "0" is assumed; if the last is omitted,
+"65535" is assumed.
+If the first port is greater than the second one they will be swapped.
+The flag
+\fB\-\-sport\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Destination port or port range specification. The flag
+\fB\-\-dport\fP
+is a convenient alias for this option.
+.TP
+[\fB!\fP] \fB\-\-tcp\-flags\fP \fImask\fP \fIcomp\fP
+Match when the TCP flags are as specified. The first argument \fImask\fP is the
+flags which we should examine, written as a comma-separated list, and
+the second argument \fIcomp\fP is a comma-separated list of flags which must be
+set. Flags are:
+.BR "SYN ACK FIN RST URG PSH ALL NONE" .
+Hence the command
+.nf
+ iptables \-A FORWARD \-p tcp \-\-tcp\-flags SYN,ACK,FIN,RST SYN
+.fi
+will only match packets with the SYN flag set, and the ACK, FIN and
+RST flags unset.
+.TP
+[\fB!\fP] \fB\-\-syn\fP
+Only match TCP packets with the SYN bit set and the ACK,RST and FIN bits
+cleared. Such packets are used to request TCP connection initiation;
+for example, blocking such packets coming in an interface will prevent
+incoming TCP connections, but outgoing TCP connections will be
+unaffected.
+It is equivalent to \fB\-\-tcp\-flags SYN,RST,ACK,FIN SYN\fP.
+If the "!" flag precedes the "\-\-syn", the sense of the
+option is inverted.
+.TP
+[\fB!\fP] \fB\-\-tcp\-option\fP \fInumber\fP
+Match if TCP option set.
+.SS tcpmss
+This matches the TCP MSS (maximum segment size) field of the TCP header. You can only use this on TCP SYN or SYN/ACK packets, since the MSS is only negotiated during the TCP handshake at connection startup time.
+.TP
+[\fB!\fP] \fB\-\-mss\fP \fIvalue\fP[\fB:\fP\fIvalue\fP]
+Match a given TCP MSS value or range.
+.SS time
+This matches if the packet arrival time/date is within a given range. All
+options are optional, but are ANDed when specified.
+.TP
+\fB\-\-datestart\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
+.TP
+\fB\-\-datestop\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
+.IP
+Only match during the given time, which must be in ISO 8601 "T" notation.
+The possible time range is 1970-01-01T00:00:00 to 2038-01-19T04:17:07.
+.IP
+If \-\-datestart or \-\-datestop are not specified, it will default to 1970-01-01
+and 2038-01-19, respectively.
+.TP
+\fB\-\-timestart\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
+.TP
+\fB\-\-timestop\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
+.IP
+Only match during the given daytime. The possible time range is 00:00:00 to
+23:59:59. Leading zeroes are allowed (e.g. "06:03") and correctly interpreted
+as base-10.
+.TP
+[\fB!\fR] \fB\-\-monthdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
+.IP
+Only match on the given days of the month. Possible values are \fB1\fR
+to \fB31\fR. Note that specifying \fB31\fR will of course not match
+on months which do not have a 31st day; the same goes for 28- or 29-day
+February.
+.TP
+[\fB!\fR] \fB\-\-weekdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
+.IP
+Only match on the given weekdays. Possible values are \fBMon\fR, \fBTue\fR,
+\fBWed\fR, \fBThu\fR, \fBFri\fR, \fBSat\fR, \fBSun\fR, or values from \fB1\fR
+to \fB7\fR, respectively. You may also use two-character variants (\fBMo\fP,
+\fBTu\fR, etc.).
+.TP
+\fB\-\-utc\fP
+.IP
+Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
+\fB\-\-timestart\fP and \fB\-\-timestop\fP to be UTC.
+.TP
+\fB\-\-localtz\fP
+.IP
+Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
+\fB\-\-timestart\fP and \fB\-\-timestop\fP to be local kernel time. (Default)
+.PP
+EXAMPLES. To match on weekends, use:
+.IP
+\-m time \-\-weekdays Sa,Su
+.PP
+Or, to match (once) on a national holiday block:
+.IP
+\-m time \-\-datestart 2007\-12\-24 \-\-datestop 2007\-12\-27
+.PP
+Since the stop time is actually inclusive, you would need the following stop
+time to not match the first second of the new day:
+.IP
+\-m time \-\-datestart 2007\-01\-01T17:00 \-\-datestop 2007\-01\-01T23:59:59
+.PP
+During lunch hour:
+.IP
+\-m time \-\-timestart 12:30 \-\-timestop 13:30
+.PP
+The fourth Friday in the month:
+.IP
+\-m time \-\-weekdays Fr \-\-monthdays 22,23,24,25,26,27,28
+.PP
+(Note that this exploits a certain mathematical property. It is not possible to
+say "fourth Thursday OR fourth Friday" in one rule. It is possible with
+multiple rules, though.)
+.SS tos
+This module matches the 8-bit Type of Service field in the IPv4 header (i.e.
+including the "Precedence" bits) or the (also 8-bit) Priority field in the IPv6
+header.
+.TP
+[\fB!\fP] \fB\-\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Matches packets with the given TOS mark value. If a mask is specified, it is
+logically ANDed with the TOS mark before the comparison.
+.TP
+[\fB!\fP] \fB\-\-tos\fP \fIsymbol\fP
+You can specify a symbolic name when using the tos match for IPv4. The list of
+recognized TOS names can be obtained by calling iptables with \fB\-m tos \-h\fP.
+Note that this implies a mask of 0x3F, i.e. all but the ECN bits.
+.SS u32
+U32 tests whether quantities of up to 4 bytes extracted from a packet have
+specified values. The specification of what to extract is general enough to
+find data at given offsets from tcp headers or payloads.
+.TP
+[\fB!\fP] \fB\-\-u32\fP \fItests\fP
+The argument amounts to a program in a small language described below.
+.IP
+tests := location "=" value | tests "&&" location "=" value
+.IP
+value := range | value "," range
+.IP
+range := number | number ":" number
+.PP
+a single number, \fIn\fR, is interpreted the same as \fIn:n\fR. \fIn:m\fR is
+interpreted as the range of numbers \fB>=n\fR and \fB<=m\fR.
+.IP "" 4
+location := number | location operator number
+.IP "" 4
+operator := "&" | "<<" | ">>" | "@"
+.PP
+The operators \fB&\fR, \fB<<\fR, \fB>>\fR and \fB&&\fR mean the same as in C.
+The \fB=\fR is really a set membership operator and the value syntax describes
+a set. The \fB@\fR operator is what allows moving to the next header and is
+described further below.
+.PP
+There are currently some artificial implementation limits on the size of the
+tests:
+.IP " *"
+no more than 10 of "\fB=\fR" (and 9 "\fB&&\fR"s) in the u32 argument
+.IP " *"
+no more than 10 ranges (and 9 commas) per value
+.IP " *"
+no more than 10 numbers (and 9 operators) per location
+.PP
+To describe the meaning of location, imagine the following machine that
+interprets it. There are three registers:
+.IP
+A is of type \fBchar *\fR, initially the address of the IP header
+.IP
+B and C are unsigned 32 bit integers, initially zero
+.PP
+The instructions are:
+.IP
+number B = number;
+.IP
+C = (*(A+B)<<24) + (*(A+B+1)<<16) + (*(A+B+2)<<8) + *(A+B+3)
+.IP
+&number C = C & number
+.IP
+<< number C = C << number
+.IP
+>> number C = C >> number
+.IP
+@number A = A + C; then do the instruction number
+.PP
+Any access of memory outside [skb\->data,skb\->end] causes the match to fail.
+Otherwise the result of the computation is the final value of C.
+.PP
+Whitespace is allowed but not required in the tests. However, the characters
+that do occur there are likely to require shell quoting, so it is a good idea
+to enclose the arguments in quotes.
+.PP
+Example:
+.IP
+match IP packets with total length >= 256
+.IP
+The IP header contains a total length field in bytes 2-3.
+.IP
+\-\-u32 "\fB0 & 0xFFFF = 0x100:0xFFFF\fP"
+.IP
+read bytes 0-3
+.IP
+AND that with 0xFFFF (giving bytes 2-3), and test whether that is in the range
+[0x100:0xFFFF]
+.PP
+Example: (more realistic, hence more complicated)
+.IP
+match ICMP packets with icmp type 0
+.IP
+First test that it is an ICMP packet, true iff byte 9 (protocol) = 1
+.IP
+\-\-u32 "\fB6 & 0xFF = 1 &&\fP ...
+.IP
+read bytes 6-9, use \fB&\fR to throw away bytes 6-8 and compare the result to
+1. Next test that it is not a fragment. (If so, it might be part of such a
+packet but we cannot always tell.) N.B.: This test is generally needed if you
+want to match anything beyond the IP header. The last 6 bits of byte 6 and all
+of byte 7 are 0 iff this is a complete packet (not a fragment). Alternatively,
+you can allow first fragments by only testing the last 5 bits of byte 6.
+.IP
+ ... \fB4 & 0x3FFF = 0 &&\fR ...
+.IP
+Last test: the first byte past the IP header (the type) is 0. This is where we
+have to use the @syntax. The length of the IP header (IHL) in 32 bit words is
+stored in the right half of byte 0 of the IP header itself.
+.IP
+ ... \fB0 >> 22 & 0x3C @ 0 >> 24 = 0\fR"
+.IP
+The first 0 means read bytes 0-3, \fB>>22\fR means shift that 22 bits to the
+right. Shifting 24 bits would give the first byte, so only 22 bits is four
+times that plus a few more bits. \fB&3C\fR then eliminates the two extra bits
+on the right and the first four bits of the first byte. For instance, if IHL=5,
+then the IP header is 20 (4 x 5) bytes long. In this case, bytes 0-1 are (in
+binary) xxxx0101 yyzzzzzz, \fB>>22\fR gives the 10 bit value xxxx0101yy and
+\fB&3C\fR gives 010100. \fB@\fR means to use this number as a new offset into
+the packet, and read four bytes starting from there. This is the first 4 bytes
+of the ICMP payload, of which byte 0 is the ICMP type. Therefore, we simply
+shift the value 24 to the right to throw out all but the first byte and compare
+the result with 0.
+.PP
+Example:
+.IP
+TCP payload bytes 8-12 is any of 1, 2, 5 or 8
+.IP
+First we test that the packet is a tcp packet (similar to ICMP).
+.IP
+\-\-u32 "\fB6 & 0xFF = 6 &&\fP ...
+.IP
+Next, test that it is not a fragment (same as above).
+.IP
+ ... \fB0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8\fR"
+.IP
+\fB0>>22&3C\fR as above computes the number of bytes in the IP header. \fB@\fR
+makes this the new offset into the packet, which is the start of the TCP
+header. The length of the TCP header (again in 32 bit words) is the left half
+of byte 12 of the TCP header. The \fB12>>26&3C\fR computes this length in bytes
+(similar to the IP header before). "@" makes this the new offset, which is the
+start of the TCP payload. Finally, 8 reads bytes 8-12 of the payload and
+\fB=\fR checks whether the result is any of 1, 2, 5 or 8.
+.SS udp
+These extensions can be used if `\-\-protocol udp' is specified. It
+provides the following options:
+.TP
+[\fB!\fP] \fB\-\-source\-port\fP,\fB\-\-sport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Source port or port range specification.
+See the description of the
+\fB\-\-source\-port\fP
+option of the TCP extension for details.
+.TP
+[\fB!\fP] \fB\-\-destination\-port\fP,\fB\-\-dport\fP \fIport\fP[\fB:\fP\fIport\fP]
+Destination port or port range specification.
+See the description of the
+\fB\-\-destination\-port\fP
+option of the TCP extension for details.
diff --git a/extensions/rename-dups.sh b/extensions/rename-dups.sh
deleted file mode 100755
index bd940bc..0000000
--- a/extensions/rename-dups.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-t1=`mktemp`
-t2=`mktemp`
-
-ls *.c | tr [A-Z] [a-z] | sort > $t1
-cat $t1 | sort -u > $t2
-for f in `diff $t1 $t2 | grep "< " | awk -F"< " '{print $2}'`; do
- n=`echo $f | sed -e 's/t_/t_2/g'`;
- "Renaming $f --> $n.";
- p4 integrate $f $n;
- p4 delete $f;
-done;
-
-rm -f $t1 $t2
-
-
diff --git a/extensions/targets4.man b/extensions/targets4.man
new file mode 100644
index 0000000..fd44156
--- /dev/null
+++ b/extensions/targets4.man
@@ -0,0 +1,651 @@
+.SS CLASSIFY
+This module allows you to set the skb\->priority value (and thus classify the packet into a specific CBQ class).
+.TP
+\fB\-\-set\-class\fP \fImajor\fP\fB:\fP\fIminor\fP
+Set the major and minor class value. The values are always interpreted as
+hexadecimal even if no 0x prefix is given.
+.SS CLUSTERIP
+This module allows you to configure a simple cluster of nodes that share
+a certain IP and MAC address without an explicit load balancer in front of
+them. Connections are statically distributed between the nodes in this
+cluster.
+.TP
+\fB\-\-new\fP
+Create a new ClusterIP. You always have to set this on the first rule
+for a given ClusterIP.
+.TP
+\fB\-\-hashmode\fP \fImode\fP
+Specify the hashing mode. Has to be one of
+\fBsourceip\fP, \fBsourceip\-sourceport\fP, \fBsourceip\-sourceport\-destport\fP.
+.TP
+\fB\-\-clustermac\fP \fImac\fP
+Specify the ClusterIP MAC address. Has to be a link\-layer multicast address
+.TP
+\fB\-\-total\-nodes\fP \fInum\fP
+Number of total nodes within this cluster.
+.TP
+\fB\-\-local\-node\fP \fInum\fP
+Local node number within this cluster.
+.TP
+\fB\-\-hash\-init\fP \fIrnd\fP
+Specify the random seed used for hash initialization.
+.SS CONNMARK
+This module sets the netfilter mark value associated with a connection. The
+mark is 32 bits wide.
+.TP
+\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zero out the bits given by \fImask\fR and XOR \fIvalue\fR into the ctmark.
+.TP
+\fB\-\-save\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
+Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
+masks. The new nfmark value is determined as follows:
+.IP
+ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
+.IP
+i.e. \fIctmask\fR defines what bits to clear and \fInfmask\fR what bits of the
+nfmark to XOR into the ctmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.TP
+\fB\-\-restore\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
+Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
+masks. The new ctmark value is determined as follows:
+.IP
+nfmark = (nfmark & ~\fInfmask\fR) ^ (ctmark & \fIctmask\fR);
+.IP
+i.e. \fInfmask\fR defines what bits to clear and \fIctmask\fR what bits of the
+ctmark to XOR into the nfmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.IP
+\fB\-\-restore\-mark\fP is only valid in the \fBmangle\fP table.
+.PP
+The following mnemonics are available for \fB\-\-set\-xmark\fP:
+.TP
+\fB\-\-and\-mark\fP \fIbits\fP
+Binary AND the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-mark\fP \fIbits\fP
+Binary OR the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-mark\fP \fIbits\fP
+Binary XOR the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/0\fR.)
+.TP
+\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Set the connection mark. If a mask is specified then only those bits set in the
+mask are modified.
+.TP
+\fB\-\-save\-mark\fP [\fB\-\-mask\fP \fImask\fP]
+Copy the nfmark to the ctmark. If a mask is specified, only those bits are
+copied.
+.TP
+\fB\-\-restore\-mark\fP [\fB\-\-mask\fP \fImask\fP]
+Copy the ctmark to the nfmark. If a mask is specified, only those bits are
+copied. This is only valid in the \fBmangle\fR table.
+.SS CONNSECMARK
+This module copies security markings from packets to connections
+(if unlabeled), and from connections back to packets (also only
+if unlabeled). Typically used in conjunction with SECMARK, it is
+only valid in the
+.B mangle
+table.
+.TP
+\fB\-\-save\fP
+If the packet has a security marking, copy it to the connection
+if the connection is not marked.
+.TP
+\fB\-\-restore\fP
+If the packet does not have a security marking, and the connection
+does, copy the security marking from the connection to the packet.
+
+.SS DNAT
+This target is only valid in the
+.B nat
+table, in the
+.B PREROUTING
+and
+.B OUTPUT
+chains, and user-defined chains which are only called from those
+chains. It specifies that the destination address of the packet
+should be modified (and all future packets in this connection will
+also be mangled), and rules should cease being examined. It takes one
+type of option:
+.TP
+\fB\-\-to\-destination\fP [\fIipaddr\fP][\fB\-\fP\fIipaddr\fP][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
+which can specify a single new destination IP address, an inclusive
+range of IP addresses, and optionally, a port range (which is only
+valid if the rule also specifies
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP).
+If no port range is specified, then the destination port will never be
+modified. If no IP address is specified then only the destination port
+will be modified.
+
+In Kernels up to 2.6.10 you can add several \-\-to\-destination options. For
+those kernels, if you specify more than one destination address, either via an
+address range or multiple \-\-to\-destination options, a simple round-robin (one
+after another in cycle) load balancing takes place between these addresses.
+Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
+anymore.
+.TP
+\fB\-\-random\fP
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.22).
+.TP
+\fB\-\-persistent\fP
+Gives a client the same source-/destination-address for each connection.
+This supersedes the SAME target. Support for persistent mappings is available
+from 2.6.29-rc2.
+.SS DSCP
+This target allows to alter the value of the DSCP bits within the TOS
+header of the IPv4 packet. As this manipulates a packet, it can only
+be used in the mangle table.
+.TP
+\fB\-\-set\-dscp\fP \fIvalue\fP
+Set the DSCP field to a numerical value (can be decimal or hex)
+.TP
+\fB\-\-set\-dscp\-class\fP \fIclass\fP
+Set the DSCP field to a DiffServ class.
+.SS ECN
+This target allows to selectively work around known ECN blackholes.
+It can only be used in the mangle table.
+.TP
+\fB\-\-ecn\-tcp\-remove\fP
+Remove all ECN bits from the TCP header. Of course, it can only be used
+in conjunction with
+\fB\-p tcp\fP.
+.SS LOG
+Turn on kernel logging of matching packets. When this option is set
+for a rule, the Linux kernel will print some information on all
+matching packets (like most IP header fields) via the kernel log
+(where it can be read with
+.I dmesg
+or
+.IR syslogd (8)).
+This is a "non-terminating target", i.e. rule traversal continues at
+the next rule. So if you want to LOG the packets you refuse, use two
+separate rules with the same matching criteria, first using target LOG
+then DROP (or REJECT).
+.TP
+\fB\-\-log\-level\fP \fIlevel\fP
+Level of logging (numeric or see \fIsyslog.conf\fP(5)).
+.TP
+\fB\-\-log\-prefix\fP \fIprefix\fP
+Prefix log messages with the specified prefix; up to 29 letters long,
+and useful for distinguishing messages in the logs.
+.TP
+\fB\-\-log\-tcp\-sequence\fP
+Log TCP sequence numbers. This is a security risk if the log is
+readable by users.
+.TP
+\fB\-\-log\-tcp\-options\fP
+Log options from the TCP packet header.
+.TP
+\fB\-\-log\-ip\-options\fP
+Log options from the IP packet header.
+.TP
+\fB\-\-log\-uid\fP
+Log the userid of the process which generated the packet.
+.SS MARK
+This target is used to set the Netfilter mark value associated with the packet.
+The target can only be used in the \fBmangle\fR table. It can, for example, be
+used in conjunction with routing based on fwmark (needs iproute2). The mark
+field is 32 bits wide.
+.TP
+\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the packet
+mark ("nfmark"). If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.TP
+\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and ORs \fIvalue\fR into the packet
+mark. If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.PP
+The following mnemonics are available:
+.TP
+\fB\-\-and\-mark\fP \fIbits\fP
+Binary AND the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-mark\fP \fIbits\fP
+Binary OR the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-mark\fP \fIbits\fP
+Binary XOR the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/0\fR.)
+.SS MASQUERADE
+This target is only valid in the
+.B nat
+table, in the
+.B POSTROUTING
+chain. It should only be used with dynamically assigned IP (dialup)
+connections: if you have a static IP address, you should use the SNAT
+target. Masquerading is equivalent to specifying a mapping to the IP
+address of the interface the packet is going out, but also has the
+effect that connections are
+.I forgotten
+when the interface goes down. This is the correct behavior when the
+next dialup is unlikely to have the same interface address (and hence
+any established connections are lost anyway). It takes one option:
+.TP
+\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
+This specifies a range of source ports to use, overriding the default
+.B SNAT
+source port-selection heuristics (see above). This is only valid
+if the rule also specifies
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+\fB\-\-random\fP
+Randomize source port mapping
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.21).
+.RS
+.PP
+.SS MIRROR
+This is an experimental demonstration target which inverts the source
+and destination fields in the IP header and retransmits the packet.
+It is only valid in the
+.BR INPUT ,
+.B FORWARD
+and
+.B PREROUTING
+chains, and user-defined chains which are only called from those
+chains. Note that the outgoing packets are
+.B NOT
+seen by any packet filtering chains, connection tracking or NAT, to
+avoid loops and other problems.
+.SS NETMAP
+This target allows you to statically map a whole network of addresses onto
+another network of addresses. It can only be used from rules in the
+.B nat
+table.
+.TP
+\fB\-\-to\fP \fIaddress\fP[\fB/\fP\fImask\fP]
+Network address to map to. The resulting address will be constructed in the
+following way: All 'one' bits in the mask are filled in from the new `address'.
+All bits that are zero in the mask are filled in from the original address.
+.SS NFLOG
+This target provides logging of matching packets. When this target is
+set for a rule, the Linux kernel will pass the packet to the loaded
+logging backend to log the packet. This is usually used in combination
+with nfnetlink_log as logging backend, which will multicast the packet
+through a
+.IR netlink
+socket to the specified multicast group. One or more userspace processes
+may subscribe to the group to receive the packets. Like LOG, this is a
+non-terminating target, i.e. rule traversal continues at the next rule.
+.TP
+\fB\-\-nflog\-group\fP \fInlgroup\fP
+The netlink group (1 \- 2^32\-1) to which packets are (only applicable for
+nfnetlink_log). The default value is 0.
+.TP
+\fB\-\-nflog\-prefix\fP \fIprefix\fP
+A prefix string to include in the log message, up to 64 characters
+long, useful for distinguishing messages in the logs.
+.TP
+\fB\-\-nflog\-range\fP \fIsize\fP
+The number of bytes to be copied to userspace (only applicable for
+nfnetlink_log). nfnetlink_log instances may specify their own
+range, this option overrides it.
+.TP
+\fB\-\-nflog\-threshold\fP \fIsize\fP
+Number of packets to queue inside the kernel before sending them
+to userspace (only applicable for nfnetlink_log). Higher values
+result in less overhead per packet, but increase delay until the
+packets reach userspace. The default value is 1.
+.BR
+.SS NFQUEUE
+This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
+you to put a packet into any specific queue, identified by its 16-bit queue
+number.
+It can only be used with Kernel versions 2.6.14 or later, since it requires
+the
+.B
+nfnetlink_queue
+kernel support. The \fBqueue-balance\fP option was added in Linux 2.6.31.
+.TP
+\fB\-\-queue\-num\fP \fIvalue\fP
+This specifies the QUEUE number to use. Valid queue numbers are 0 to 65535. The default value is 0.
+.PP
+.TP
+\fB\-\-queue\-balance\fP \fIvalue\fP\fB:\fP\fIvalue\fP
+This specifies a range of queues to use. Packets are then balanced across the given queues.
+This is useful for multicore systems: start multiple instances of the userspace program on
+queues x, x+1, .. x+n and use "\-\-queue\-balance \fIx\fP\fB:\fP\fIx+n\fP".
+Packets belonging to the same connection are put into the same nfqueue.
+.SS NOTRACK
+This target disables connection tracking for all packets matching that rule.
+.PP
+It can only be used in the
+.B raw
+table.
+.SS RATEEST
+The RATEEST target collects statistics, performs rate estimation calculation
+and saves the results for later evaluation using the \fBrateest\fP match.
+.TP
+\fB\-\-rateest\-name\fP \fIname\fP
+Count matched packets into the pool referred to by \fIname\fP, which is freely
+choosable.
+.TP
+\fB\-\-rateest\-interval\fP \fIamount\fP{\fBs\fP|\fBms\fP|\fBus\fP}
+Rate measurement interval, in seconds, milliseconds or microseconds.
+.TP
+\fB\-\-rateest\-ewmalog\fP \fIvalue\fP
+Rate measurement averaging time constant.
+.SS REDIRECT
+This target is only valid in the
+.B nat
+table, in the
+.B PREROUTING
+and
+.B OUTPUT
+chains, and user-defined chains which are only called from those
+chains. It redirects the packet to the machine itself by changing the
+destination IP to the primary address of the incoming interface
+(locally-generated packets are mapped to the 127.0.0.1 address).
+.TP
+\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
+This specifies a destination port or range of ports to use: without
+this, the destination port is never altered. This is only valid
+if the rule also specifies
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP.
+.TP
+\fB\-\-random\fP
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.22).
+.RS
+.PP
+.SS REJECT
+This is used to send back an error packet in response to the matched
+packet: otherwise it is equivalent to
+.B DROP
+so it is a terminating TARGET, ending rule traversal.
+This target is only valid in the
+.BR INPUT ,
+.B FORWARD
+and
+.B OUTPUT
+chains, and user-defined chains which are only called from those
+chains. The following option controls the nature of the error packet
+returned:
+.TP
+\fB\-\-reject\-with\fP \fItype\fP
+The type given can be
+\fBicmp\-net\-unreachable\fP,
+\fBicmp\-host\-unreachable\fP,
+\fBicmp\-port\-unreachable\fP,
+\fBicmp\-proto\-unreachable\fP,
+\fBicmp\-net\-prohibited\fP,
+\fBicmp\-host\-prohibited\fP or
+\fBicmp\-admin\-prohibited\fP (*)
+which return the appropriate ICMP error message (\fBport\-unreachable\fP is
+the default). The option
+\fBtcp\-reset\fP
+can be used on rules which only match the TCP protocol: this causes a
+TCP RST packet to be sent back. This is mainly useful for blocking
+.I ident
+(113/tcp) probes which frequently occur when sending mail to broken mail
+hosts (which won't accept your mail otherwise).
+.PP
+(*) Using icmp\-admin\-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT
+.SS SAME
+Similar to SNAT/DNAT depending on chain: it takes a range of addresses
+(`\-\-to 1.2.3.4\-1.2.3.7') and gives a client the same
+source-/destination-address for each connection.
+.PP
+N.B.: The DNAT target's \fB\-\-persistent\fP option replaced the SAME target.
+.TP
+\fB\-\-to\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP]
+Addresses to map source to. May be specified more than once for
+multiple ranges.
+.TP
+\fB\-\-nodst\fP
+Don't use the destination-ip in the calculations when selecting the
+new source-ip
+.TP
+\fB\-\-random\fP
+Port mapping will be forcibly randomized to avoid attacks based on
+port prediction (kernel >= 2.6.21).
+.SS SECMARK
+This is used to set the security mark value associated with the
+packet for use by security subsystems such as SELinux. It is only
+valid in the
+.B mangle
+table. The mark is 32 bits wide.
+.TP
+\fB\-\-selctx\fP \fIsecurity_context\fP
+.SS SET
+This modules adds and/or deletes entries from IP sets which can be defined
+by ipset(8).
+.TP
+\fB\-\-add\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
+add the address(es)/port(s) of the packet to the sets
+.TP
+\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
+delete the address(es)/port(s) of the packet from the sets
+.IP
+where flags are
+.BR "src"
+and/or
+.BR "dst"
+specifications and there can be no more than six of them.
+.PP
+Use of -j SET requires that ipset kernel support is provided. As standard
+kernels do not ship this currently, the ipset or Xtables-addons package needs
+to be installed.
+.SS SNAT
+This target is only valid in the
+.B nat
+table, in the
+.B POSTROUTING
+chain. It specifies that the source address of the packet should be
+modified (and all future packets in this connection will also be
+mangled), and rules should cease being examined. It takes one type
+of option:
+.TP
+\fB\-\-to\-source\fP \fIipaddr\fP[\fB\-\fP\fIipaddr\fP][\fB:\fP\fIport\fP[\fB\-\fP\fIport\fP]]
+which can specify a single new source IP address, an inclusive range
+of IP addresses, and optionally, a port range (which is only valid if
+the rule also specifies
+\fB\-p tcp\fP
+or
+\fB\-p udp\fP).
+If no port range is specified, then source ports below 512 will be
+mapped to other ports below 512: those between 512 and 1023 inclusive
+will be mapped to ports below 1024, and other ports will be mapped to
+1024 or above. Where possible, no port alteration will
+
+In Kernels up to 2.6.10, you can add several \-\-to\-source options. For those
+kernels, if you specify more than one source address, either via an address
+range or multiple \-\-to\-source options, a simple round-robin (one after another
+in cycle) takes place between these addresses.
+Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges
+anymore.
+.TP
+\fB\-\-random\fP
+If option
+\fB\-\-random\fP
+is used then port mapping will be randomized (kernel >= 2.6.21).
+.TP
+\fB\-\-persistent\fP
+Gives a client the same source-/destination-address for each connection.
+This supersedes the SAME target. Support for persistent mappings is available
+from 2.6.29-rc2.
+.SS TCPMSS
+This target allows to alter the MSS value of TCP SYN packets, to control
+the maximum size for that connection (usually limiting it to your
+outgoing interface's MTU minus 40 for IPv4 or 60 for IPv6, respectively).
+Of course, it can only be used
+in conjunction with
+\fB\-p tcp\fP.
+It is only valid in the
+.BR mangle
+table.
+.br
+This target is used to overcome criminally braindead ISPs or servers
+which block "ICMP Fragmentation Needed" or "ICMPv6 Packet Too Big"
+packets. The symptoms of this
+problem are that everything works fine from your Linux
+firewall/router, but machines behind it can never exchange large
+packets:
+.PD 0
+.RS 0.1i
+.TP 0.3i
+1)
+Web browsers connect, then hang with no data received.
+.TP
+2)
+Small mail works fine, but large emails hang.
+.TP
+3)
+ssh works fine, but scp hangs after initial handshaking.
+.RE
+.PD
+Workaround: activate this option and add a rule to your firewall
+configuration like:
+.IP
+ iptables \-t mangle \-A FORWARD \-p tcp \-\-tcp\-flags SYN,RST SYN
+ \-j TCPMSS \-\-clamp\-mss\-to\-pmtu
+.TP
+\fB\-\-set\-mss\fP \fIvalue\fP
+Explicitly sets MSS option to specified value. If the MSS of the packet is
+already lower than \fIvalue\fP, it will \fBnot\fP be increased (from Linux
+2.6.25 onwards) to avoid more problems with hosts relying on a proper MSS.
+.TP
+\fB\-\-clamp\-mss\-to\-pmtu\fP
+Automatically clamp MSS value to (path_MTU \- 40 for IPv4; \-60 for IPv6).
+This may not function as desired where asymmetric routes with differing
+path MTU exist \(em the kernel uses the path MTU which it would use to send
+packets from itself to the source and destination IP addresses. Prior to
+Linux 2.6.25, only the path MTU to the destination IP address was
+considered by this option; subsequent kernels also consider the path MTU
+to the source IP address.
+.PP
+These options are mutually exclusive.
+.SS TCPOPTSTRIP
+This target will strip TCP options off a TCP packet. (It will actually replace
+them by NO-OPs.) As such, you will need to add the \fB\-p tcp\fP parameters.
+.TP
+\fB\-\-strip\-options\fP \fIoption\fP[\fB,\fP\fIoption\fP...]
+Strip the given option(s). The options may be specified by TCP option number or
+by symbolic name. The list of recognized options can be obtained by calling
+iptables with \fB\-j TCPOPTSTRIP \-h\fP.
+.SS TOS
+This module sets the Type of Service field in the IPv4 header (including the
+"precedence" bits) or the Priority field in the IPv6 header. Note that TOS
+shares the same bits as DSCP and ECN. The TOS target is only valid in the
+\fBmangle\fR table.
+.TP
+\fB\-\-set\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the
+TOS/Priority field. If \fImask\fR is omitted, 0xFF is assumed.
+.TP
+\fB\-\-set\-tos\fP \fIsymbol\fP
+You can specify a symbolic name when using the TOS target for IPv4. It implies
+a mask of 0xFF. The list of recognized TOS names can be obtained by calling
+iptables with \fB\-j TOS \-h\fP.
+.PP
+The following mnemonics are available:
+.TP
+\fB\-\-and\-tos\fP \fIbits\fP
+Binary AND the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-tos\fP \fIbits\fP
+Binary OR the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-tos\fP \fIbits\fP
+Binary XOR the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos\fP
+\fIbits\fR\fB/0\fR.)
+.SS TPROXY
+This target is only valid in the \fBmangle\fR table, in the \fBPREROUTING\fR
+chain and user-defined chains which are only called from this chain. It
+redirects the packet to a local socket without changing the packet header in
+any way. It can also change the mark value which can then be used in advanced
+routing rules.
+It takes three options:
+.TP
+\fB\-\-on\-port\fP \fIport\fP
+This specifies a destination port to use. It is a required option, 0 means the
+new destination port is the same as the original. This is only valid if the
+rule also specifies \fB\-p tcp\fP or \fB\-p udp\fP.
+.TP
+\fB\-\-on\-ip\fP \fIaddress\fP
+This specifies a destination address to use. By default the address is the IP
+address of the incoming interface. This is only valid if the rule also
+specifies \fB\-p tcp\fP or \fB\-p udp\fP.
+.TP
+\fB\-\-tproxy\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Marks packets with the given value/mask. The fwmark value set here can be used
+by advanced routing. (Required for transparent proxying to work: otherwise
+these packets will get forwarded, which is probably not what you want.)
+.SS TRACE
+This target marks packes so that the kernel will log every rule which match
+the packets as those traverse the tables, chains, rules. (The ipt_LOG or
+ip6t_LOG module
+is required for the logging.) 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.
+.SS TTL
+This is used to modify the IPv4 TTL header field. The TTL field determines
+how many hops (routers) a packet can traverse until it's time to live is
+exceeded.
+.PP
+Setting or incrementing the TTL field can potentially be very dangerous,
+so it should be avoided at any cost.
+.PP
+.B Don't ever set or increment the value on packets that leave your local network!
+.B mangle
+table.
+.TP
+\fB\-\-ttl\-set\fP \fIvalue\fP
+Set the TTL value to `value'.
+.TP
+\fB\-\-ttl\-dec\fP \fIvalue\fP
+Decrement the TTL value `value' times.
+.TP
+\fB\-\-ttl\-inc\fP \fIvalue\fP
+Increment the TTL value `value' times.
+.SS ULOG
+This target provides userspace logging of matching packets. When this
+target is set for a rule, the Linux kernel will multicast this packet
+through a
+.IR netlink
+socket. One or more userspace processes may then subscribe to various
+multicast groups and receive the packets.
+Like LOG, this is a "non-terminating target", i.e. rule traversal
+continues at the next rule.
+.TP
+\fB\-\-ulog\-nlgroup\fP \fInlgroup\fP
+This specifies the netlink group (1-32) to which the packet is sent.
+Default value is 1.
+.TP
+\fB\-\-ulog\-prefix\fP \fIprefix\fP
+Prefix log messages with the specified prefix; up to 32 characters
+long, and useful for distinguishing messages in the logs.
+.TP
+\fB\-\-ulog\-cprange\fP \fIsize\fP
+Number of bytes to be copied to userspace. A value of 0 always copies
+the entire packet, regardless of its size. Default is 0.
+.TP
+\fB\-\-ulog\-qthreshold\fP \fIsize\fP
+Number of packet to queue inside kernel. Setting this value to, e.g. 10
+accumulates ten packets inside the kernel and transmits them as one
+netlink multipart message to userspace. Default is 1 (for backwards
+compatibility).
+.br
diff --git a/extensions/targets6.man b/extensions/targets6.man
new file mode 100644
index 0000000..8d40482
--- /dev/null
+++ b/extensions/targets6.man
@@ -0,0 +1,288 @@
+.SS CLASSIFY
+This module allows you to set the skb\->priority value (and thus classify the packet into a specific CBQ class).
+.TP
+\fB\-\-set\-class\fP \fImajor\fP\fB:\fP\fIminor\fP
+Set the major and minor class value. The values are always interpreted as
+hexadecimal even if no 0x prefix is given.
+.SS CONNMARK
+This module sets the netfilter mark value associated with a connection. The
+mark is 32 bits wide.
+.TP
+\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zero out the bits given by \fImask\fR and XOR \fIvalue\fR into the ctmark.
+.TP
+\fB\-\-save\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
+Copy the packet mark (nfmark) to the connection mark (ctmark) using the given
+masks. The new nfmark value is determined as follows:
+.IP
+ctmark = (ctmark & ~ctmask) ^ (nfmark & nfmask)
+.IP
+i.e. \fIctmask\fR defines what bits to clear and \fInfmask\fR what bits of the
+nfmark to XOR into the ctmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.TP
+\fB\-\-restore\-mark\fP [\fB\-\-nfmask\fP \fInfmask\fP] [\fB\-\-ctmask\fP \fIctmask\fP]
+Copy the connection mark (ctmark) to the packet mark (nfmark) using the given
+masks. The new ctmark value is determined as follows:
+.IP
+nfmark = (nfmark & ~\fInfmask\fR) ^ (ctmark & \fIctmask\fR);
+.IP
+i.e. \fInfmask\fR defines what bits to clear and \fIctmask\fR what bits of the
+ctmark to XOR into the nfmark. \fIctmask\fR and \fInfmask\fR default to
+0xFFFFFFFF.
+.IP
+\fB\-\-restore\-mark\fP is only valid in the \fBmangle\fP table.
+.PP
+The following mnemonics are available for \fB\-\-set\-xmark\fP:
+.TP
+\fB\-\-and\-mark\fP \fIbits\fP
+Binary AND the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-mark\fP \fIbits\fP
+Binary OR the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-mark\fP \fIbits\fP
+Binary XOR the ctmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/0\fR.)
+.TP
+\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Set the connection mark. If a mask is specified then only those bits set in the
+mask are modified.
+.TP
+\fB\-\-save\-mark\fP [\fB\-\-mask\fP \fImask\fP]
+Copy the nfmark to the ctmark. If a mask is specified, only those bits are
+copied.
+.TP
+\fB\-\-restore\-mark\fP [\fB\-\-mask\fP \fImask\fP]
+Copy the ctmark to the nfmark. If a mask is specified, only those bits are
+copied. This is only valid in the \fBmangle\fR table.
+.SS CONNSECMARK
+This module copies security markings from packets to connections
+(if unlabeled), and from connections back to packets (also only
+if unlabeled). Typically used in conjunction with SECMARK, it is
+only valid in the
+.B mangle
+table.
+.TP
+\fB\-\-save\fP
+If the packet has a security marking, copy it to the connection
+if the connection is not marked.
+.TP
+\fB\-\-restore\fP
+If the packet does not have a security marking, and the connection
+does, copy the security marking from the connection to the packet.
+
+.SS DSCP
+This target allows to alter the value of the DSCP bits within the TOS
+header of the IPv4 packet. As this manipulates a packet, it can only
+be used in the mangle table.
+.TP
+\fB\-\-set\-dscp\fP \fIvalue\fP
+Set the DSCP field to a numerical value (can be decimal or hex)
+.TP
+\fB\-\-set\-dscp\-class\fP \fIclass\fP
+Set the DSCP field to a DiffServ class.
+.SS MARK
+This target is used to set the Netfilter mark value associated with the packet.
+The target can only be used in the \fBmangle\fR table. It can, for example, be
+used in conjunction with routing based on fwmark (needs iproute2). The mark
+field is 32 bits wide.
+.TP
+\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the packet
+mark ("nfmark"). If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.TP
+\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and ORs \fIvalue\fR into the packet
+mark. If \fImask\fR is omitted, 0xFFFFFFFF is assumed.
+.PP
+The following mnemonics are available:
+.TP
+\fB\-\-and\-mark\fP \fIbits\fP
+Binary AND the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-mark\fP \fIbits\fP
+Binary OR the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-mark\fP \fIbits\fP
+Binary XOR the nfmark with \fIbits\fR. (Mnemonic for \fB\-\-set\-xmark\fP
+\fIbits\fR\fB/0\fR.)
+.SS NFLOG
+This target provides logging of matching packets. When this target is
+set for a rule, the Linux kernel will pass the packet to the loaded
+logging backend to log the packet. This is usually used in combination
+with nfnetlink_log as logging backend, which will multicast the packet
+through a
+.IR netlink
+socket to the specified multicast group. One or more userspace processes
+may subscribe to the group to receive the packets. Like LOG, this is a
+non-terminating target, i.e. rule traversal continues at the next rule.
+.TP
+\fB\-\-nflog\-group\fP \fInlgroup\fP
+The netlink group (1 \- 2^32\-1) to which packets are (only applicable for
+nfnetlink_log). The default value is 0.
+.TP
+\fB\-\-nflog\-prefix\fP \fIprefix\fP
+A prefix string to include in the log message, up to 64 characters
+long, useful for distinguishing messages in the logs.
+.TP
+\fB\-\-nflog\-range\fP \fIsize\fP
+The number of bytes to be copied to userspace (only applicable for
+nfnetlink_log). nfnetlink_log instances may specify their own
+range, this option overrides it.
+.TP
+\fB\-\-nflog\-threshold\fP \fIsize\fP
+Number of packets to queue inside the kernel before sending them
+to userspace (only applicable for nfnetlink_log). Higher values
+result in less overhead per packet, but increase delay until the
+packets reach userspace. The default value is 1.
+.BR
+.SS NFQUEUE
+This target is an extension of the QUEUE target. As opposed to QUEUE, it allows
+you to put a packet into any specific queue, identified by its 16-bit queue
+number.
+It can only be used with Kernel versions 2.6.14 or later, since it requires
+the
+.B
+nfnetlink_queue
+kernel support. The \fBqueue-balance\fP option was added in Linux 2.6.31.
+.TP
+\fB\-\-queue\-num\fP \fIvalue\fP
+This specifies the QUEUE number to use. Valid queue numbers are 0 to 65535. The default value is 0.
+.PP
+.TP
+\fB\-\-queue\-balance\fP \fIvalue\fP\fB:\fP\fIvalue\fP
+This specifies a range of queues to use. Packets are then balanced across the given queues.
+This is useful for multicore systems: start multiple instances of the userspace program on
+queues x, x+1, .. x+n and use "\-\-queue\-balance \fIx\fP\fB:\fP\fIx+n\fP".
+Packets belonging to the same connection are put into the same nfqueue.
+.SS NOTRACK
+This target disables connection tracking for all packets matching that rule.
+.PP
+It can only be used in the
+.B raw
+table.
+.SS RATEEST
+The RATEEST target collects statistics, performs rate estimation calculation
+and saves the results for later evaluation using the \fBrateest\fP match.
+.TP
+\fB\-\-rateest\-name\fP \fIname\fP
+Count matched packets into the pool referred to by \fIname\fP, which is freely
+choosable.
+.TP
+\fB\-\-rateest\-interval\fP \fIamount\fP{\fBs\fP|\fBms\fP|\fBus\fP}
+Rate measurement interval, in seconds, milliseconds or microseconds.
+.TP
+\fB\-\-rateest\-ewmalog\fP \fIvalue\fP
+Rate measurement averaging time constant.
+.SS SECMARK
+This is used to set the security mark value associated with the
+packet for use by security subsystems such as SELinux. It is only
+valid in the
+.B mangle
+table. The mark is 32 bits wide.
+.TP
+\fB\-\-selctx\fP \fIsecurity_context\fP
+.SS TCPMSS
+This target allows to alter the MSS value of TCP SYN packets, to control
+the maximum size for that connection (usually limiting it to your
+outgoing interface's MTU minus 40 for IPv4 or 60 for IPv6, respectively).
+Of course, it can only be used
+in conjunction with
+\fB\-p tcp\fP.
+It is only valid in the
+.BR mangle
+table.
+.br
+This target is used to overcome criminally braindead ISPs or servers
+which block "ICMP Fragmentation Needed" or "ICMPv6 Packet Too Big"
+packets. The symptoms of this
+problem are that everything works fine from your Linux
+firewall/router, but machines behind it can never exchange large
+packets:
+.PD 0
+.RS 0.1i
+.TP 0.3i
+1)
+Web browsers connect, then hang with no data received.
+.TP
+2)
+Small mail works fine, but large emails hang.
+.TP
+3)
+ssh works fine, but scp hangs after initial handshaking.
+.RE
+.PD
+Workaround: activate this option and add a rule to your firewall
+configuration like:
+.IP
+ iptables \-t mangle \-A FORWARD \-p tcp \-\-tcp\-flags SYN,RST SYN
+ \-j TCPMSS \-\-clamp\-mss\-to\-pmtu
+.TP
+\fB\-\-set\-mss\fP \fIvalue\fP
+Explicitly sets MSS option to specified value. If the MSS of the packet is
+already lower than \fIvalue\fP, it will \fBnot\fP be increased (from Linux
+2.6.25 onwards) to avoid more problems with hosts relying on a proper MSS.
+.TP
+\fB\-\-clamp\-mss\-to\-pmtu\fP
+Automatically clamp MSS value to (path_MTU \- 40 for IPv4; \-60 for IPv6).
+This may not function as desired where asymmetric routes with differing
+path MTU exist \(em the kernel uses the path MTU which it would use to send
+packets from itself to the source and destination IP addresses. Prior to
+Linux 2.6.25, only the path MTU to the destination IP address was
+considered by this option; subsequent kernels also consider the path MTU
+to the source IP address.
+.PP
+These options are mutually exclusive.
+.SS TCPOPTSTRIP
+This target will strip TCP options off a TCP packet. (It will actually replace
+them by NO-OPs.) As such, you will need to add the \fB\-p tcp\fP parameters.
+.TP
+\fB\-\-strip\-options\fP \fIoption\fP[\fB,\fP\fIoption\fP...]
+Strip the given option(s). The options may be specified by TCP option number or
+by symbolic name. The list of recognized options can be obtained by calling
+iptables with \fB\-j TCPOPTSTRIP \-h\fP.
+.SS TOS
+This module sets the Type of Service field in the IPv4 header (including the
+"precedence" bits) or the Priority field in the IPv6 header. Note that TOS
+shares the same bits as DSCP and ECN. The TOS target is only valid in the
+\fBmangle\fR table.
+.TP
+\fB\-\-set\-tos\fP \fIvalue\fP[\fB/\fP\fImask\fP]
+Zeroes out the bits given by \fImask\fR and XORs \fIvalue\fR into the
+TOS/Priority field. If \fImask\fR is omitted, 0xFF is assumed.
+.TP
+\fB\-\-set\-tos\fP \fIsymbol\fP
+You can specify a symbolic name when using the TOS target for IPv4. It implies
+a mask of 0xFF. The list of recognized TOS names can be obtained by calling
+iptables with \fB\-j TOS \-h\fP.
+.PP
+The following mnemonics are available:
+.TP
+\fB\-\-and\-tos\fP \fIbits\fP
+Binary AND the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos
+0/\fR\fIinvbits\fR, where \fIinvbits\fR is the binary negation of \fIbits\fR.)
+.TP
+\fB\-\-or\-tos\fP \fIbits\fP
+Binary OR the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos\fP
+\fIbits\fR\fB/\fR\fIbits\fR.)
+.TP
+\fB\-\-xor\-tos\fP \fIbits\fP
+Binary XOR the TOS value with \fIbits\fR. (Mnemonic for \fB\-\-set\-tos\fP
+\fIbits\fR\fB/0\fR.)
+.SS TRACE
+This target marks packes so that the kernel will log every rule which match
+the packets as those traverse the tables, chains, rules. (The ipt_LOG or
+ip6t_LOG module
+is required for the logging.) 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.
diff --git a/extensions/tos_values.c b/extensions/tos_values.c
new file mode 100644
index 0000000..e8f1563
--- /dev/null
+++ b/extensions/tos_values.c
@@ -0,0 +1,96 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <linux/ip.h>
+
+#ifndef IPTOS_NORMALSVC
+# define IPTOS_NORMALSVC 0
+#endif
+
+struct tos_value_mask {
+ uint8_t value, mask;
+};
+
+static const struct tos_symbol_info {
+ unsigned char value;
+ const char *name;
+} tos_symbol_names[] = {
+ {IPTOS_LOWDELAY, "Minimize-Delay"},
+ {IPTOS_THROUGHPUT, "Maximize-Throughput"},
+ {IPTOS_RELIABILITY, "Maximize-Reliability"},
+ {IPTOS_MINCOST, "Minimize-Cost"},
+ {IPTOS_NORMALSVC, "Normal-Service"},
+ { .name = NULL }
+};
+
+/*
+ * tos_parse_numeric - parse sth. like "15/255"
+ *
+ * @s: input string
+ * @info: accompanying structure
+ * @bits: number of bits that are allowed
+ * (8 for IPv4 TOS field, 4 for IPv6 Priority Field)
+ */
+static bool tos_parse_numeric(const char *str, struct tos_value_mask *tvm,
+ unsigned int bits)
+{
+ const unsigned int max = (1 << bits) - 1;
+ unsigned int value;
+ char *end;
+
+ xtables_strtoui(str, &end, &value, 0, max);
+ tvm->value = value;
+ tvm->mask = max;
+
+ if (*end == '/') {
+ const char *p = end + 1;
+
+ if (!xtables_strtoui(p, &end, &value, 0, max))
+ xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
+ str);
+ tvm->mask = value;
+ }
+
+ if (*end != '\0')
+ xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
+ return true;
+}
+
+static bool tos_parse_symbolic(const char *str, struct tos_value_mask *tvm,
+ unsigned int def_mask)
+{
+ const unsigned int max = UINT8_MAX;
+ const struct tos_symbol_info *symbol;
+ char *tmp;
+
+ if (xtables_strtoui(str, &tmp, NULL, 0, max))
+ return tos_parse_numeric(str, tvm, max);
+
+ /* Do not consider ECN bits */
+ tvm->mask = def_mask;
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ if (strcasecmp(str, symbol->name) == 0) {
+ tvm->value = symbol->value;
+ return true;
+ }
+
+ xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", str);
+ return false;
+}
+
+static bool tos_try_print_symbolic(const char *prefix,
+ u_int8_t value, u_int8_t mask)
+{
+ const struct tos_symbol_info *symbol;
+
+ if (mask != 0x3F)
+ return false;
+
+ for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
+ if (value == symbol->value) {
+ printf("%s%s ", prefix, symbol->name);
+ return true;
+ }
+
+ return false;
+}