aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2006-01-12 16:30:04 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-12 17:06:43 -0500
commit2e4e6a17af35be359cc8f1c924f8f198fbd478cc (patch)
treecb4b5438dcf9ff9d57518a26124308bcbfffd214 /net/netfilter
parent880b005f294454d989783d0984dc554dfe3c8214 (diff)
[NETFILTER] x_tables: Abstraction layer for {ip,ip6,arp}_tables
This monster-patch tries to do the best job for unifying the data structures and backend interfaces for the three evil clones ip_tables, ip6_tables and arp_tables. In an ideal world we would never have allowed this kind of copy+paste programming... but well, our world isn't (yet?) ideal. o introduce a new x_tables module o {ip,arp,ip6}_tables depend on this x_tables module o registration functions for tables, matches and targets are only wrappers around x_tables provided functions o all matches/targets that are used from ip_tables and ip6_tables are now implemented as xt_FOOBAR.c files and provide module aliases to ipt_FOOBAR and ip6t_FOOBAR o header files for xt_matches are in include/linux/netfilter/, include/linux/netfilter_{ipv4,ipv6} contains compatibility wrappers around the xt_FOOBAR.h headers Based on this patchset we're going to further unify the code, gradually getting rid of all the layer 3 specific assumptions. Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/Kconfig258
-rw-r--r--net/netfilter/Makefile37
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/x_tables.c624
-rw-r--r--net/netfilter/xt_CLASSIFY.c109
-rw-r--r--net/netfilter/xt_CONNMARK.c141
-rw-r--r--net/netfilter/xt_MARK.c191
-rw-r--r--net/netfilter/xt_NFQUEUE.c107
-rw-r--r--net/netfilter/xt_NOTRACK.c92
-rw-r--r--net/netfilter/xt_comment.c80
-rw-r--r--net/netfilter/xt_connbytes.c180
-rw-r--r--net/netfilter/xt_connmark.c109
-rw-r--r--net/netfilter/xt_conntrack.c238
-rw-r--r--net/netfilter/xt_dccp.c221
-rw-r--r--net/netfilter/xt_helper.c188
-rw-r--r--net/netfilter/xt_length.c98
-rw-r--r--net/netfilter/xt_limit.c175
-rw-r--r--net/netfilter/xt_mac.c100
-rw-r--r--net/netfilter/xt_mark.c91
-rw-r--r--net/netfilter/xt_physdev.c155
-rw-r--r--net/netfilter/xt_pkttype.c82
-rw-r--r--net/netfilter/xt_realm.c79
-rw-r--r--net/netfilter/xt_sctp.c250
-rw-r--r--net/netfilter/xt_state.c96
-rw-r--r--net/netfilter/xt_string.c111
-rw-r--r--net/netfilter/xt_tcpmss.c172
-rw-r--r--net/netfilter/xt_tcpudp.c333
27 files changed, 4316 insertions, 5 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 7d55f9cbd853..99c0a0fa4a97 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -103,3 +103,261 @@ config NF_CT_NETLINK
103 This option enables support for a netlink-based userspace interface 103 This option enables support for a netlink-based userspace interface
104 104
105endmenu 105endmenu
106
107config NETFILTER_XTABLES
108 tristate "Netfilter Xtables support (required for ip_tables)"
109 help
110 This is required if you intend to use any of ip_tables,
111 ip6_tables or arp_tables.
112
113# alphabetically ordered list of targets
114
115config NETFILTER_XT_TARGET_CLASSIFY
116 tristate '"CLASSIFY" target support'
117 depends on NETFILTER_XTABLES
118 help
119 This option adds a `CLASSIFY' target, which enables the user to set
120 the priority of a packet. Some qdiscs can use this value for
121 classification, among these are:
122
123 atm, cbq, dsmark, pfifo_fast, htb, prio
124
125 To compile it as a module, choose M here. If unsure, say N.
126
127config NETFILTER_XT_TARGET_CONNMARK
128 tristate '"CONNMARK" target support'
129 depends on NETFILTER_XTABLES
130 depends on IP_NF_MANGLE || IP6_NF_MANGLE
131 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4)
132 help
133 This option adds a `CONNMARK' target, which allows one to manipulate
134 the connection mark value. Similar to the MARK target, but
135 affects the connection mark value rather than the packet mark value.
136
137 If you want to compile it as a module, say M here and read
138 <file:Documentation/modules.txt>. The module will be called
139 ipt_CONNMARK.o. If unsure, say `N'.
140
141config NETFILTER_XT_TARGET_MARK
142 tristate '"MARK" target support'
143 depends on NETFILTER_XTABLES
144 help
145 This option adds a `MARK' target, which allows you to create rules
146 in the `mangle' table which alter the netfilter mark (nfmark) field
147 associated with the packet prior to routing. This can change
148 the routing method (see `Use netfilter MARK value as routing
149 key') and can also be used by other subsystems to change their
150 behavior.
151
152 To compile it as a module, choose M here. If unsure, say N.
153
154config NETFILTER_XT_TARGET_NFQUEUE
155 tristate '"NFQUEUE" target Support'
156 depends on NETFILTER_XTABLES
157 help
158 This Target replaced the old obsolete QUEUE target.
159
160 As opposed to QUEUE, it supports 65535 different queues,
161 not just one.
162
163 To compile it as a module, choose M here. If unsure, say N.
164
165config NETFILTER_XT_TARGET_NOTRACK
166 tristate '"NOTRACK" target support'
167 depends on NETFILTER_XTABLES
168 depends on IP_NF_RAW || IP6_NF_RAW
169 depends on IP_NF_CONNTRACK || NF_CONNTRACK
170 help
171 The NOTRACK target allows a select rule to specify
172 which packets *not* to enter the conntrack/NAT
173 subsystem with all the consequences (no ICMP error tracking,
174 no protocol helpers for the selected packets).
175
176 If you want to compile it as a module, say M here and read
177 <file:Documentation/modules.txt>. If unsure, say `N'.
178
179config NETFILTER_XT_MATCH_COMMENT
180 tristate '"comment" match support'
181 depends on NETFILTER_XTABLES
182 help
183 This option adds a `comment' dummy-match, which allows you to put
184 comments in your iptables ruleset.
185
186 If you want to compile it as a module, say M here and read
187 <file:Documentation/modules.txt>. If unsure, say `N'.
188
189config NETFILTER_XT_MATCH_CONNBYTES
190 tristate '"connbytes" per-connection counter match support'
191 depends on NETFILTER_XTABLES
192 depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT
193 help
194 This option adds a `connbytes' match, which allows you to match the
195 number of bytes and/or packets for each direction within a connection.
196
197 If you want to compile it as a module, say M here and read
198 <file:Documentation/modules.txt>. If unsure, say `N'.
199
200config NETFILTER_XT_MATCH_CONNMARK
201 tristate '"connmark" connection mark match support'
202 depends on NETFILTER_XTABLES
203 depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK
204 help
205 This option adds a `connmark' match, which allows you to match the
206 connection mark value previously set for the session by `CONNMARK'.
207
208 If you want to compile it as a module, say M here and read
209 <file:Documentation/modules.txt>. The module will be called
210 ipt_connmark.o. If unsure, say `N'.
211
212config NETFILTER_XT_MATCH_CONNTRACK
213 tristate '"conntrack" connection tracking match support'
214 depends on NETFILTER_XTABLES
215 depends on IP_NF_CONNTRACK || NF_CONNTRACK
216 help
217 This is a general conntrack match module, a superset of the state match.
218
219 It allows matching on additional conntrack information, which is
220 useful in complex configurations, such as NAT gateways with multiple
221 internet links or tunnels.
222
223 To compile it as a module, choose M here. If unsure, say N.
224
225config NETFILTER_XT_MATCH_DCCP
226 tristate '"DCCP" protocol match support'
227 depends on NETFILTER_XTABLES
228 help
229 With this option enabled, you will be able to use the iptables
230 `dccp' match in order to match on DCCP source/destination ports
231 and DCCP flags.
232
233 If you want to compile it as a module, say M here and read
234 <file:Documentation/modules.txt>. If unsure, say `N'.
235
236config NETFILTER_XT_MATCH_HELPER
237 tristate '"helper" match support'
238 depends on NETFILTER_XTABLES
239 depends on IP_NF_CONNTRACK || NF_CONNTRACK
240 help
241 Helper matching allows you to match packets in dynamic connections
242 tracked by a conntrack-helper, ie. ip_conntrack_ftp
243
244 To compile it as a module, choose M here. If unsure, say Y.
245
246config NETFILTER_XT_MATCH_LENGTH
247 tristate '"length" match support'
248 depends on NETFILTER_XTABLES
249 help
250 This option allows you to match the length of a packet against a
251 specific value or range of values.
252
253 To compile it as a module, choose M here. If unsure, say N.
254
255config NETFILTER_XT_MATCH_LIMIT
256 tristate '"limit" match support'
257 depends on NETFILTER_XTABLES
258 help
259 limit matching allows you to control the rate at which a rule can be
260 matched: mainly useful in combination with the LOG target ("LOG
261 target support", below) and to avoid some Denial of Service attacks.
262
263 To compile it as a module, choose M here. If unsure, say N.
264
265config NETFILTER_XT_MATCH_MAC
266 tristate '"mac" address match support'
267 depends on NETFILTER_XTABLES
268 help
269 MAC matching allows you to match packets based on the source
270 Ethernet address of the packet.
271
272 To compile it as a module, choose M here. If unsure, say N.
273
274config NETFILTER_XT_MATCH_MARK
275 tristate '"mark" match support'
276 depends on NETFILTER_XTABLES
277 help
278 Netfilter mark matching allows you to match packets based on the
279 `nfmark' value in the packet. This can be set by the MARK target
280 (see below).
281
282 To compile it as a module, choose M here. If unsure, say N.
283
284config NETFILTER_XT_MATCH_PHYSDEV
285 tristate '"physdev" match support'
286 depends on NETFILTER_XTABLES && BRIDGE_NETFILTER
287 help
288 Physdev packet matching matches against the physical bridge ports
289 the IP packet arrived on or will leave by.
290
291 To compile it as a module, choose M here. If unsure, say N.
292
293config NETFILTER_XT_MATCH_PKTTYPE
294 tristate '"pkttype" packet type match support'
295 depends on NETFILTER_XTABLES
296 help
297 Packet type matching allows you to match a packet by
298 its "class", eg. BROADCAST, MULTICAST, ...
299
300 Typical usage:
301 iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
302
303 To compile it as a module, choose M here. If unsure, say N.
304
305config NETFILTER_XT_MATCH_REALM
306 tristate '"realm" match support'
307 depends on NETFILTER_XTABLES
308 select NET_CLS_ROUTE
309 help
310 This option adds a `realm' match, which allows you to use the realm
311 key from the routing subsystem inside iptables.
312
313 This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
314 in tc world.
315
316 If you want to compile it as a module, say M here and read
317 <file:Documentation/modules.txt>. If unsure, say `N'.
318
319config NETFILTER_XT_MATCH_SCTP
320 tristate '"sctp" protocol match support'
321 depends on NETFILTER_XTABLES
322 help
323 With this option enabled, you will be able to use the
324 `sctp' match in order to match on SCTP source/destination ports
325 and SCTP chunk types.
326
327 If you want to compile it as a module, say M here and read
328 <file:Documentation/modules.txt>. If unsure, say `N'.
329
330config NETFILTER_XT_MATCH_STATE
331 tristate '"state" match support'
332 depends on NETFILTER_XTABLES
333 depends on IP_NF_CONNTRACK || NF_CONNTRACK
334 help
335 Connection state matching allows you to match packets based on their
336 relationship to a tracked connection (ie. previous packets). This
337 is a powerful tool for packet classification.
338
339 To compile it as a module, choose M here. If unsure, say N.
340
341config NETFILTER_XT_MATCH_STRING
342 tristate '"string" match support'
343 depends on NETFILTER_XTABLES
344 select TEXTSEARCH
345 select TEXTSEARCH_KMP
346 select TEXTSEARCH_BM
347 select TEXTSEARCH_FSM
348 help
349 This option adds a `string' match, which allows you to look for
350 pattern matchings in packets.
351
352 To compile it as a module, choose M here. If unsure, say N.
353
354config NETFILTER_XT_MATCH_TCPMSS
355 tristate '"tcpmss" match support'
356 depends on NETFILTER_XTABLES
357 help
358 This option adds a `tcpmss' match, which allows you to examine the
359 MSS value of TCP SYN packets, which control the maximum packet size
360 for that connection.
361
362 To compile it as a module, choose M here. If unsure, say N.
363
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index cb2183145c37..746172ebc91b 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,4 +1,5 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o
2 3
3obj-$(CONFIG_NETFILTER) = netfilter.o 4obj-$(CONFIG_NETFILTER) = netfilter.o
4 5
@@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
6obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 7obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
7obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 8obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
8 9
9nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o 10# connection tracking
10
11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o 11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
12obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
13 12
14# SCTP protocol connection tracking 13# SCTP protocol connection tracking
15obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o 14obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
16 15
17# netlink interface for nf_conntrack 16# netlink interface for nf_conntrack
18obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 17obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
18
19# connection tracking helpers
20obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
21
22# generic X tables
23obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
24
25# targets
26obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
27obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
28obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
29obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
30obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
31
32# matches
33obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
34obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
35obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
36obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
37obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
38obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
39obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
45obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
46obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
47obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
48obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
49obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 3531d142f693..617599aeeead 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -821,7 +821,7 @@ module_exit(fini);
821 821
822/* Some modules need us, but don't depend directly on any symbol. 822/* Some modules need us, but don't depend directly on any symbol.
823 They should call this. */ 823 They should call this. */
824void need_nf_conntrack(void) 824void need_conntrack(void)
825{ 825{
826} 826}
827 827
@@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
841EXPORT_SYMBOL(nf_ct_invert_tuplepr); 841EXPORT_SYMBOL(nf_ct_invert_tuplepr);
842EXPORT_SYMBOL(nf_conntrack_alter_reply); 842EXPORT_SYMBOL(nf_conntrack_alter_reply);
843EXPORT_SYMBOL(nf_conntrack_destroyed); 843EXPORT_SYMBOL(nf_conntrack_destroyed);
844EXPORT_SYMBOL(need_nf_conntrack); 844EXPORT_SYMBOL(need_conntrack);
845EXPORT_SYMBOL(nf_conntrack_helper_register); 845EXPORT_SYMBOL(nf_conntrack_helper_register);
846EXPORT_SYMBOL(nf_conntrack_helper_unregister); 846EXPORT_SYMBOL(nf_conntrack_helper_unregister);
847EXPORT_SYMBOL(nf_ct_iterate_cleanup); 847EXPORT_SYMBOL(nf_ct_iterate_cleanup);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
new file mode 100644
index 000000000000..d7817afc6b96
--- /dev/null
+++ b/net/netfilter/x_tables.c
@@ -0,0 +1,624 @@
1/*
2 * x_tables core - Backend for {ip,ip6,arp}_tables
3 *
4 * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org>
5 *
6 * Based on existing ip_tables code which is
7 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
8 * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 */
15
16#include <linux/config.h>
17#include <linux/kernel.h>
18#include <linux/socket.h>
19#include <linux/net.h>
20#include <linux/proc_fs.h>
21#include <linux/seq_file.h>
22#include <linux/string.h>
23#include <linux/vmalloc.h>
24
25#include <linux/netfilter/x_tables.h>
26#include <linux/netfilter_arp.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
30MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
31
32#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
33
34struct xt_af {
35 struct semaphore mutex;
36 struct list_head match;
37 struct list_head target;
38 struct list_head tables;
39};
40
41static struct xt_af *xt;
42
43#ifdef DEBUG_IP_FIREWALL_USER
44#define duprintf(format, args...) printk(format , ## args)
45#else
46#define duprintf(format, args...)
47#endif
48
49enum {
50 TABLE,
51 TARGET,
52 MATCH,
53};
54
55/* Registration hooks for targets. */
56int
57xt_register_target(int af, struct xt_target *target)
58{
59 int ret;
60
61 ret = down_interruptible(&xt[af].mutex);
62 if (ret != 0)
63 return ret;
64 list_add(&target->list, &xt[af].target);
65 up(&xt[af].mutex);
66 return ret;
67}
68EXPORT_SYMBOL(xt_register_target);
69
70void
71xt_unregister_target(int af, struct xt_target *target)
72{
73 down(&xt[af].mutex);
74 LIST_DELETE(&xt[af].target, target);
75 up(&xt[af].mutex);
76}
77EXPORT_SYMBOL(xt_unregister_target);
78
79int
80xt_register_match(int af, struct xt_match *match)
81{
82 int ret;
83
84 ret = down_interruptible(&xt[af].mutex);
85 if (ret != 0)
86 return ret;
87
88 list_add(&match->list, &xt[af].match);
89 up(&xt[af].mutex);
90
91 return ret;
92}
93EXPORT_SYMBOL(xt_register_match);
94
95void
96xt_unregister_match(int af, struct xt_match *match)
97{
98 down(&xt[af].mutex);
99 LIST_DELETE(&xt[af].match, match);
100 up(&xt[af].mutex);
101}
102EXPORT_SYMBOL(xt_unregister_match);
103
104
105/*
106 * These are weird, but module loading must not be done with mutex
107 * held (since they will register), and we have to have a single
108 * function to use try_then_request_module().
109 */
110
111/* Find match, grabs ref. Returns ERR_PTR() on error. */
112struct xt_match *xt_find_match(int af, const char *name, u8 revision)
113{
114 struct xt_match *m;
115 int err = 0;
116
117 if (down_interruptible(&xt[af].mutex) != 0)
118 return ERR_PTR(-EINTR);
119
120 list_for_each_entry(m, &xt[af].match, list) {
121 if (strcmp(m->name, name) == 0) {
122 if (m->revision == revision) {
123 if (try_module_get(m->me)) {
124 up(&xt[af].mutex);
125 return m;
126 }
127 } else
128 err = -EPROTOTYPE; /* Found something. */
129 }
130 }
131 up(&xt[af].mutex);
132 return ERR_PTR(err);
133}
134EXPORT_SYMBOL(xt_find_match);
135
136/* Find target, grabs ref. Returns ERR_PTR() on error. */
137struct xt_target *xt_find_target(int af, const char *name, u8 revision)
138{
139 struct xt_target *t;
140 int err = 0;
141
142 if (down_interruptible(&xt[af].mutex) != 0)
143 return ERR_PTR(-EINTR);
144
145 list_for_each_entry(t, &xt[af].target, list) {
146 if (strcmp(t->name, name) == 0) {
147 if (t->revision == revision) {
148 if (try_module_get(t->me)) {
149 up(&xt[af].mutex);
150 return t;
151 }
152 } else
153 err = -EPROTOTYPE; /* Found something. */
154 }
155 }
156 up(&xt[af].mutex);
157 return ERR_PTR(err);
158}
159EXPORT_SYMBOL(xt_find_target);
160
161static const char *xt_prefix[NPROTO] = {
162 [AF_INET] = "ipt_%s",
163 [AF_INET6] = "ip6t_%s",
164 [NF_ARP] = "arpt_%s",
165};
166
167struct xt_target *xt_request_find_target(int af, const char *name, u8 revision)
168{
169 struct xt_target *target;
170
171 target = try_then_request_module(xt_find_target(af, name, revision),
172 xt_prefix[af], name);
173 if (IS_ERR(target) || !target)
174 return NULL;
175 return target;
176}
177EXPORT_SYMBOL_GPL(xt_request_find_target);
178
179static int match_revfn(int af, const char *name, u8 revision, int *bestp)
180{
181 struct xt_match *m;
182 int have_rev = 0;
183
184 list_for_each_entry(m, &xt[af].match, list) {
185 if (strcmp(m->name, name) == 0) {
186 if (m->revision > *bestp)
187 *bestp = m->revision;
188 if (m->revision == revision)
189 have_rev = 1;
190 }
191 }
192 return have_rev;
193}
194
195static int target_revfn(int af, const char *name, u8 revision, int *bestp)
196{
197 struct xt_target *t;
198 int have_rev = 0;
199
200 list_for_each_entry(t, &xt[af].target, list) {
201 if (strcmp(t->name, name) == 0) {
202 if (t->revision > *bestp)
203 *bestp = t->revision;
204 if (t->revision == revision)
205 have_rev = 1;
206 }
207 }
208 return have_rev;
209}
210
211/* Returns true or false (if no such extension at all) */
212int xt_find_revision(int af, const char *name, u8 revision, int target,
213 int *err)
214{
215 int have_rev, best = -1;
216
217 if (down_interruptible(&xt[af].mutex) != 0) {
218 *err = -EINTR;
219 return 1;
220 }
221 if (target == 1)
222 have_rev = target_revfn(af, name, revision, &best);
223 else
224 have_rev = match_revfn(af, name, revision, &best);
225 up(&xt[af].mutex);
226
227 /* Nothing at all? Return 0 to try loading module. */
228 if (best == -1) {
229 *err = -ENOENT;
230 return 0;
231 }
232
233 *err = best;
234 if (!have_rev)
235 *err = -EPROTONOSUPPORT;
236 return 1;
237}
238EXPORT_SYMBOL_GPL(xt_find_revision);
239
240struct xt_table_info *xt_alloc_table_info(unsigned int size)
241{
242 struct xt_table_info *newinfo;
243 int cpu;
244
245 /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
246 if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages)
247 return NULL;
248
249 newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL);
250 if (!newinfo)
251 return NULL;
252
253 newinfo->size = size;
254
255 for_each_cpu(cpu) {
256 if (size <= PAGE_SIZE)
257 newinfo->entries[cpu] = kmalloc_node(size,
258 GFP_KERNEL,
259 cpu_to_node(cpu));
260 else
261 newinfo->entries[cpu] = vmalloc_node(size,
262 cpu_to_node(cpu));
263
264 if (newinfo->entries[cpu] == NULL) {
265 xt_free_table_info(newinfo);
266 return NULL;
267 }
268 }
269
270 return newinfo;
271}
272EXPORT_SYMBOL(xt_alloc_table_info);
273
274void xt_free_table_info(struct xt_table_info *info)
275{
276 int cpu;
277
278 for_each_cpu(cpu) {
279 if (info->size <= PAGE_SIZE)
280 kfree(info->entries[cpu]);
281 else
282 vfree(info->entries[cpu]);
283 }
284 kfree(info);
285}
286EXPORT_SYMBOL(xt_free_table_info);
287
288/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
289struct xt_table *xt_find_table_lock(int af, const char *name)
290{
291 struct xt_table *t;
292
293 if (down_interruptible(&xt[af].mutex) != 0)
294 return ERR_PTR(-EINTR);
295
296 list_for_each_entry(t, &xt[af].tables, list)
297 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
298 return t;
299 up(&xt[af].mutex);
300 return NULL;
301}
302EXPORT_SYMBOL_GPL(xt_find_table_lock);
303
304void xt_table_unlock(struct xt_table *table)
305{
306 up(&xt[table->af].mutex);
307}
308EXPORT_SYMBOL_GPL(xt_table_unlock);
309
310
311struct xt_table_info *
312xt_replace_table(struct xt_table *table,
313 unsigned int num_counters,
314 struct xt_table_info *newinfo,
315 int *error)
316{
317 struct xt_table_info *oldinfo, *private;
318
319 /* Do the substitution. */
320 write_lock_bh(&table->lock);
321 private = table->private;
322 /* Check inside lock: is the old number correct? */
323 if (num_counters != private->number) {
324 duprintf("num_counters != table->private->number (%u/%u)\n",
325 num_counters, private->number);
326 write_unlock_bh(&table->lock);
327 *error = -EAGAIN;
328 return NULL;
329 }
330 oldinfo = private;
331 table->private = newinfo;
332 newinfo->initial_entries = oldinfo->initial_entries;
333 write_unlock_bh(&table->lock);
334
335 return oldinfo;
336}
337EXPORT_SYMBOL_GPL(xt_replace_table);
338
339int xt_register_table(struct xt_table *table,
340 struct xt_table_info *bootstrap,
341 struct xt_table_info *newinfo)
342{
343 int ret;
344 struct xt_table_info *private;
345
346 ret = down_interruptible(&xt[table->af].mutex);
347 if (ret != 0)
348 return ret;
349
350 /* Don't autoload: we'd eat our tail... */
351 if (list_named_find(&xt[table->af].tables, table->name)) {
352 ret = -EEXIST;
353 goto unlock;
354 }
355
356 /* Simplifies replace_table code. */
357 table->private = bootstrap;
358 if (!xt_replace_table(table, 0, newinfo, &ret))
359 goto unlock;
360
361 private = table->private;
362 duprintf("table->private->number = %u\n", private->number);
363
364 /* save number of initial entries */
365 private->initial_entries = private->number;
366
367 rwlock_init(&table->lock);
368 list_prepend(&xt[table->af].tables, table);
369
370 ret = 0;
371 unlock:
372 up(&xt[table->af].mutex);
373 return ret;
374}
375EXPORT_SYMBOL_GPL(xt_register_table);
376
377void *xt_unregister_table(struct xt_table *table)
378{
379 struct xt_table_info *private;
380
381 down(&xt[table->af].mutex);
382 private = table->private;
383 LIST_DELETE(&xt[table->af].tables, table);
384 up(&xt[table->af].mutex);
385
386 return private;
387}
388EXPORT_SYMBOL_GPL(xt_unregister_table);
389
390#ifdef CONFIG_PROC_FS
391static char *xt_proto_prefix[NPROTO] = {
392 [AF_INET] = "ip",
393 [AF_INET6] = "ip6",
394 [NF_ARP] = "arp",
395};
396
397static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos)
398{
399 struct list_head *head = list->next;
400
401 if (!head || list_empty(list))
402 return NULL;
403
404 while (pos && (head = head->next)) {
405 if (head == list)
406 return NULL;
407 pos--;
408 }
409 return pos ? NULL : head;
410}
411
412static struct list_head *type2list(u_int16_t af, u_int16_t type)
413{
414 struct list_head *list;
415
416 switch (type) {
417 case TARGET:
418 list = &xt[af].target;
419 break;
420 case MATCH:
421 list = &xt[af].match;
422 break;
423 case TABLE:
424 list = &xt[af].tables;
425 break;
426 default:
427 list = NULL;
428 break;
429 }
430
431 return list;
432}
433
434static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos)
435{
436 struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private;
437 u_int16_t af = (unsigned long)pde->data & 0xffff;
438 u_int16_t type = (unsigned long)pde->data >> 16;
439 struct list_head *list;
440
441 if (af >= NPROTO)
442 return NULL;
443
444 list = type2list(af, type);
445 if (!list)
446 return NULL;
447
448 if (down_interruptible(&xt[af].mutex) != 0)
449 return NULL;
450
451 return xt_get_idx(list, seq, *pos);
452}
453
454static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
455{
456 struct proc_dir_entry *pde = seq->private;
457 u_int16_t af = (unsigned long)pde->data & 0xffff;
458 u_int16_t type = (unsigned long)pde->data >> 16;
459 struct list_head *list;
460
461 if (af >= NPROTO)
462 return NULL;
463
464 list = type2list(af, type);
465 if (!list)
466 return NULL;
467
468 (*pos)++;
469 return xt_get_idx(list, seq, *pos);
470}
471
472static void xt_tgt_seq_stop(struct seq_file *seq, void *v)
473{
474 struct proc_dir_entry *pde = seq->private;
475 u_int16_t af = (unsigned long)pde->data & 0xffff;
476
477 up(&xt[af].mutex);
478}
479
480static int xt_name_seq_show(struct seq_file *seq, void *v)
481{
482 char *name = (char *)v + sizeof(struct list_head);
483
484 if (strlen(name))
485 return seq_printf(seq, "%s\n", name);
486 else
487 return 0;
488}
489
490static struct seq_operations xt_tgt_seq_ops = {
491 .start = xt_tgt_seq_start,
492 .next = xt_tgt_seq_next,
493 .stop = xt_tgt_seq_stop,
494 .show = xt_name_seq_show,
495};
496
497static int xt_tgt_open(struct inode *inode, struct file *file)
498{
499 int ret;
500
501 ret = seq_open(file, &xt_tgt_seq_ops);
502 if (!ret) {
503 struct seq_file *seq = file->private_data;
504 struct proc_dir_entry *pde = PDE(inode);
505
506 seq->private = pde;
507 }
508
509 return ret;
510}
511
512static struct file_operations xt_file_ops = {
513 .owner = THIS_MODULE,
514 .open = xt_tgt_open,
515 .read = seq_read,
516 .llseek = seq_lseek,
517 .release = seq_release,
518};
519
520#define FORMAT_TABLES "_tables_names"
521#define FORMAT_MATCHES "_tables_matches"
522#define FORMAT_TARGETS "_tables_targets"
523
524#endif /* CONFIG_PROC_FS */
525
526int xt_proto_init(int af)
527{
528#ifdef CONFIG_PROC_FS
529 char buf[XT_FUNCTION_MAXNAMELEN];
530 struct proc_dir_entry *proc;
531#endif
532
533 if (af >= NPROTO)
534 return -EINVAL;
535
536
537#ifdef CONFIG_PROC_FS
538 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
539 strlcat(buf, FORMAT_TABLES, sizeof(buf));
540 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
541 if (!proc)
542 goto out;
543 proc->data = (void *) ((unsigned long) af | (TABLE << 16));
544
545
546 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
547 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
548 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
549 if (!proc)
550 goto out_remove_tables;
551 proc->data = (void *) ((unsigned long) af | (MATCH << 16));
552
553 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
554 strlcat(buf, FORMAT_TARGETS, sizeof(buf));
555 proc = proc_net_fops_create(buf, 0440, &xt_file_ops);
556 if (!proc)
557 goto out_remove_matches;
558 proc->data = (void *) ((unsigned long) af | (TARGET << 16));
559#endif
560
561 return 0;
562
563#ifdef CONFIG_PROC_FS
564out_remove_matches:
565 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
566 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
567 proc_net_remove(buf);
568
569out_remove_tables:
570 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
571 strlcat(buf, FORMAT_TABLES, sizeof(buf));
572 proc_net_remove(buf);
573out:
574 return -1;
575#endif
576}
577EXPORT_SYMBOL_GPL(xt_proto_init);
578
579void xt_proto_fini(int af)
580{
581#ifdef CONFIG_PROC_FS
582 char buf[XT_FUNCTION_MAXNAMELEN];
583
584 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
585 strlcat(buf, FORMAT_TABLES, sizeof(buf));
586 proc_net_remove(buf);
587
588 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
589 strlcat(buf, FORMAT_TARGETS, sizeof(buf));
590 proc_net_remove(buf);
591
592 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
593 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
594 proc_net_remove(buf);
595#endif /*CONFIG_PROC_FS*/
596}
597EXPORT_SYMBOL_GPL(xt_proto_fini);
598
599
600static int __init xt_init(void)
601{
602 int i;
603
604 xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL);
605 if (!xt)
606 return -ENOMEM;
607
608 for (i = 0; i < NPROTO; i++) {
609 init_MUTEX(&xt[i].mutex);
610 INIT_LIST_HEAD(&xt[i].target);
611 INIT_LIST_HEAD(&xt[i].match);
612 INIT_LIST_HEAD(&xt[i].tables);
613 }
614 return 0;
615}
616
617static void __exit xt_fini(void)
618{
619 kfree(xt);
620}
621
622module_init(xt_init);
623module_exit(xt_fini);
624
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
new file mode 100644
index 000000000000..78ee266a12ee
--- /dev/null
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -0,0 +1,109 @@
1/*
2 * This is a module which is used for setting the skb->priority field
3 * of an skb for qdisc classification.
4 */
5
6/* (C) 2001-2002 Patrick McHardy <kaber@trash.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/ip.h>
16#include <net/checksum.h>
17
18#include <linux/netfilter/x_tables.h>
19#include <linux/netfilter/xt_CLASSIFY.h>
20
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_LICENSE("GPL");
23MODULE_DESCRIPTION("iptables qdisc classification target module");
24MODULE_ALIAS("ipt_CLASSIFY");
25
26static unsigned int
27target(struct sk_buff **pskb,
28 const struct net_device *in,
29 const struct net_device *out,
30 unsigned int hooknum,
31 const void *targinfo,
32 void *userinfo)
33{
34 const struct xt_classify_target_info *clinfo = targinfo;
35
36 if ((*pskb)->priority != clinfo->priority)
37 (*pskb)->priority = clinfo->priority;
38
39 return XT_CONTINUE;
40}
41
42static int
43checkentry(const char *tablename,
44 const void *e,
45 void *targinfo,
46 unsigned int targinfosize,
47 unsigned int hook_mask)
48{
49 if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){
50 printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n",
51 targinfosize,
52 XT_ALIGN(sizeof(struct xt_classify_target_info)));
53 return 0;
54 }
55
56 if (hook_mask & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) |
57 (1 << NF_IP_POST_ROUTING))) {
58 printk(KERN_ERR "CLASSIFY: only valid in LOCAL_OUT, FORWARD "
59 "and POST_ROUTING.\n");
60 return 0;
61 }
62
63 if (strcmp(tablename, "mangle") != 0) {
64 printk(KERN_ERR "CLASSIFY: can only be called from "
65 "\"mangle\" table, not \"%s\".\n",
66 tablename);
67 return 0;
68 }
69
70 return 1;
71}
72
73static struct xt_target classify_reg = {
74 .name = "CLASSIFY",
75 .target = target,
76 .checkentry = checkentry,
77 .me = THIS_MODULE,
78};
79static struct xt_target classify6_reg = {
80 .name = "CLASSIFY",
81 .target = target,
82 .checkentry = checkentry,
83 .me = THIS_MODULE,
84};
85
86
87static int __init init(void)
88{
89 int ret;
90
91 ret = xt_register_target(AF_INET, &classify_reg);
92 if (ret)
93 return ret;
94
95 ret = xt_register_target(AF_INET6, &classify6_reg);
96 if (ret)
97 xt_unregister_target(AF_INET, &classify_reg);
98
99 return ret;
100}
101
102static void __exit fini(void)
103{
104 xt_unregister_target(AF_INET, &classify_reg);
105 xt_unregister_target(AF_INET6, &classify6_reg);
106}
107
108module_init(init);
109module_exit(fini);
diff --git a/net/netfilter/xt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c
new file mode 100644
index 000000000000..22506e376be5
--- /dev/null
+++ b/net/netfilter/xt_CONNMARK.c
@@ -0,0 +1,141 @@
1/* This kernel module is used to modify the connection mark values, or
2 * to optionally restore the skb nfmark from the connection mark
3 *
4 * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
5 * by Henrik Nordstrom <hno@marasystems.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/module.h>
22#include <linux/skbuff.h>
23#include <linux/ip.h>
24#include <net/checksum.h>
25
26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
27MODULE_DESCRIPTION("IP tables CONNMARK matching module");
28MODULE_LICENSE("GPL");
29MODULE_ALIAS("ipt_CONNMARK");
30
31#include <linux/netfilter/x_tables.h>
32#include <linux/netfilter/xt_CONNMARK.h>
33#include <net/netfilter/nf_conntrack_compat.h>
34
35static unsigned int
36target(struct sk_buff **pskb,
37 const struct net_device *in,
38 const struct net_device *out,
39 unsigned int hooknum,
40 const void *targinfo,
41 void *userinfo)
42{
43 const struct xt_connmark_target_info *markinfo = targinfo;
44 u_int32_t diff;
45 u_int32_t nfmark;
46 u_int32_t newmark;
47 u_int32_t ctinfo;
48 u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo);
49
50 if (ctmark) {
51 switch(markinfo->mode) {
52 case XT_CONNMARK_SET:
53 newmark = (*ctmark & ~markinfo->mask) | markinfo->mark;
54 if (newmark != *ctmark)
55 *ctmark = newmark;
56 break;
57 case XT_CONNMARK_SAVE:
58 newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
59 if (*ctmark != newmark)
60 *ctmark = newmark;
61 break;
62 case XT_CONNMARK_RESTORE:
63 nfmark = (*pskb)->nfmark;
64 diff = (*ctmark ^ nfmark) & markinfo->mask;
65 if (diff != 0)
66 (*pskb)->nfmark = nfmark ^ diff;
67 break;
68 }
69 }
70
71 return XT_CONTINUE;
72}
73
74static int
75checkentry(const char *tablename,
76 const void *entry,
77 void *targinfo,
78 unsigned int targinfosize,
79 unsigned int hook_mask)
80{
81 struct xt_connmark_target_info *matchinfo = targinfo;
82 if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) {
83 printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
84 targinfosize,
85 XT_ALIGN(sizeof(struct xt_connmark_target_info)));
86 return 0;
87 }
88
89 if (matchinfo->mode == XT_CONNMARK_RESTORE) {
90 if (strcmp(tablename, "mangle") != 0) {
91 printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
92 return 0;
93 }
94 }
95
96 if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) {
97 printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n");
98 return 0;
99 }
100
101 return 1;
102}
103
104static struct xt_target connmark_reg = {
105 .name = "CONNMARK",
106 .target = &target,
107 .checkentry = &checkentry,
108 .me = THIS_MODULE
109};
110static struct xt_target connmark6_reg = {
111 .name = "CONNMARK",
112 .target = &target,
113 .checkentry = &checkentry,
114 .me = THIS_MODULE
115};
116
117static int __init init(void)
118{
119 int ret;
120
121 need_conntrack();
122
123 ret = xt_register_target(AF_INET, &connmark_reg);
124 if (ret)
125 return ret;
126
127 ret = xt_register_target(AF_INET6, &connmark6_reg);
128 if (ret)
129 xt_unregister_target(AF_INET, &connmark_reg);
130
131 return ret;
132}
133
134static void __exit fini(void)
135{
136 xt_unregister_target(AF_INET, &connmark_reg);
137 xt_unregister_target(AF_INET6, &connmark6_reg);
138}
139
140module_init(init);
141module_exit(fini);
diff --git a/net/netfilter/xt_MARK.c b/net/netfilter/xt_MARK.c
new file mode 100644
index 000000000000..0c11ee9550f3
--- /dev/null
+++ b/net/netfilter/xt_MARK.c
@@ -0,0 +1,191 @@
1/* This is a module which is used for setting the NFMARK field of an skb. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/ip.h>
13#include <net/checksum.h>
14
15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter/xt_MARK.h>
17
18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20MODULE_DESCRIPTION("ip[6]tables MARK modification module");
21MODULE_ALIAS("ipt_MARK");
22MODULE_ALIAS("ip6t_MARK");
23
24static unsigned int
25target_v0(struct sk_buff **pskb,
26 const struct net_device *in,
27 const struct net_device *out,
28 unsigned int hooknum,
29 const void *targinfo,
30 void *userinfo)
31{
32 const struct xt_mark_target_info *markinfo = targinfo;
33
34 if((*pskb)->nfmark != markinfo->mark)
35 (*pskb)->nfmark = markinfo->mark;
36
37 return XT_CONTINUE;
38}
39
40static unsigned int
41target_v1(struct sk_buff **pskb,
42 const struct net_device *in,
43 const struct net_device *out,
44 unsigned int hooknum,
45 const void *targinfo,
46 void *userinfo)
47{
48 const struct xt_mark_target_info_v1 *markinfo = targinfo;
49 int mark = 0;
50
51 switch (markinfo->mode) {
52 case XT_MARK_SET:
53 mark = markinfo->mark;
54 break;
55
56 case XT_MARK_AND:
57 mark = (*pskb)->nfmark & markinfo->mark;
58 break;
59
60 case XT_MARK_OR:
61 mark = (*pskb)->nfmark | markinfo->mark;
62 break;
63 }
64
65 if((*pskb)->nfmark != mark)
66 (*pskb)->nfmark = mark;
67
68 return XT_CONTINUE;
69}
70
71
72static int
73checkentry_v0(const char *tablename,
74 const void *entry,
75 void *targinfo,
76 unsigned int targinfosize,
77 unsigned int hook_mask)
78{
79 struct xt_mark_target_info *markinfo = targinfo;
80
81 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) {
82 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
83 targinfosize,
84 XT_ALIGN(sizeof(struct xt_mark_target_info)));
85 return 0;
86 }
87
88 if (strcmp(tablename, "mangle") != 0) {
89 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
90 return 0;
91 }
92
93 if (markinfo->mark > 0xffffffff) {
94 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
95 return 0;
96 }
97
98 return 1;
99}
100
101static int
102checkentry_v1(const char *tablename,
103 const void *entry,
104 void *targinfo,
105 unsigned int targinfosize,
106 unsigned int hook_mask)
107{
108 struct xt_mark_target_info_v1 *markinfo = targinfo;
109
110 if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){
111 printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
112 targinfosize,
113 XT_ALIGN(sizeof(struct xt_mark_target_info_v1)));
114 return 0;
115 }
116
117 if (strcmp(tablename, "mangle") != 0) {
118 printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
119 return 0;
120 }
121
122 if (markinfo->mode != XT_MARK_SET
123 && markinfo->mode != XT_MARK_AND
124 && markinfo->mode != XT_MARK_OR) {
125 printk(KERN_WARNING "MARK: unknown mode %u\n",
126 markinfo->mode);
127 return 0;
128 }
129
130 if (markinfo->mark > 0xffffffff) {
131 printk(KERN_WARNING "MARK: Only supports 32bit wide mark\n");
132 return 0;
133 }
134
135 return 1;
136}
137
138static struct xt_target ipt_mark_reg_v0 = {
139 .name = "MARK",
140 .target = target_v0,
141 .checkentry = checkentry_v0,
142 .me = THIS_MODULE,
143 .revision = 0,
144};
145
146static struct xt_target ipt_mark_reg_v1 = {
147 .name = "MARK",
148 .target = target_v1,
149 .checkentry = checkentry_v1,
150 .me = THIS_MODULE,
151 .revision = 1,
152};
153
154static struct xt_target ip6t_mark_reg_v0 = {
155 .name = "MARK",
156 .target = target_v0,
157 .checkentry = checkentry_v0,
158 .me = THIS_MODULE,
159 .revision = 0,
160};
161
162static int __init init(void)
163{
164 int err;
165
166 err = xt_register_target(AF_INET, &ipt_mark_reg_v0);
167 if (err)
168 return err;
169
170 err = xt_register_target(AF_INET, &ipt_mark_reg_v1);
171 if (err)
172 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
173
174 err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0);
175 if (err) {
176 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
177 xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
178 }
179
180 return err;
181}
182
183static void __exit fini(void)
184{
185 xt_unregister_target(AF_INET, &ipt_mark_reg_v0);
186 xt_unregister_target(AF_INET, &ipt_mark_reg_v1);
187 xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0);
188}
189
190module_init(init);
191module_exit(fini);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
new file mode 100644
index 000000000000..8b76b6f8d1e4
--- /dev/null
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -0,0 +1,107 @@
1/* iptables module for using new netfilter netlink queue
2 *
3 * (C) 2005 by Harald Welte <laforge@netfilter.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#include <linux/netfilter.h>
15#include <linux/netfilter_arp.h>
16#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_NFQUEUE.h>
18
19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
20MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target");
21MODULE_LICENSE("GPL");
22MODULE_ALIAS("ipt_NFQUEUE");
23MODULE_ALIAS("ip6t_NFQUEUE");
24MODULE_ALIAS("arpt_NFQUEUE");
25
26static unsigned int
27target(struct sk_buff **pskb,
28 const struct net_device *in,
29 const struct net_device *out,
30 unsigned int hooknum,
31 const void *targinfo,
32 void *userinfo)
33{
34 const struct xt_NFQ_info *tinfo = targinfo;
35
36 return NF_QUEUE_NR(tinfo->queuenum);
37}
38
39static int
40checkentry(const char *tablename,
41 const void *entry,
42 void *targinfo,
43 unsigned int targinfosize,
44 unsigned int hook_mask)
45{
46 if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) {
47 printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n",
48 targinfosize,
49 XT_ALIGN(sizeof(struct xt_NFQ_info)));
50 return 0;
51 }
52
53 return 1;
54}
55
56static struct xt_target ipt_NFQ_reg = {
57 .name = "NFQUEUE",
58 .target = target,
59 .checkentry = checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_target ip6t_NFQ_reg = {
64 .name = "NFQUEUE",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
68};
69
70static struct xt_target arpt_NFQ_reg = {
71 .name = "NFQUEUE",
72 .target = target,
73 .checkentry = checkentry,
74 .me = THIS_MODULE,
75};
76
77static int __init init(void)
78{
79 int ret;
80 ret = xt_register_target(AF_INET, &ipt_NFQ_reg);
81 if (ret)
82 return ret;
83 ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg);
84 if (ret)
85 goto out_ip;
86 ret = xt_register_target(NF_ARP, &arpt_NFQ_reg);
87 if (ret)
88 goto out_ip6;
89
90 return ret;
91out_ip6:
92 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
93out_ip:
94 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
95
96 return ret;
97}
98
99static void __exit fini(void)
100{
101 xt_unregister_target(NF_ARP, &arpt_NFQ_reg);
102 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
103 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
104}
105
106module_init(init);
107module_exit(fini);
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c
new file mode 100644
index 000000000000..24d477afa939
--- /dev/null
+++ b/net/netfilter/xt_NOTRACK.c
@@ -0,0 +1,92 @@
1/* This is a module which is used for setting up fake conntracks
2 * on packets so that they are not seen by the conntrack/NAT code.
3 */
4#include <linux/module.h>
5#include <linux/skbuff.h>
6
7#include <linux/netfilter/x_tables.h>
8#include <net/netfilter/nf_conntrack_compat.h>
9
10MODULE_LICENSE("GPL");
11MODULE_ALIAS("ipt_NOTRACK");
12
13static unsigned int
14target(struct sk_buff **pskb,
15 const struct net_device *in,
16 const struct net_device *out,
17 unsigned int hooknum,
18 const void *targinfo,
19 void *userinfo)
20{
21 /* Previously seen (loopback)? Ignore. */
22 if ((*pskb)->nfct != NULL)
23 return XT_CONTINUE;
24
25 /* Attach fake conntrack entry.
26 If there is a real ct entry correspondig to this packet,
27 it'll hang aroun till timing out. We don't deal with it
28 for performance reasons. JK */
29 nf_ct_untrack(*pskb);
30 (*pskb)->nfctinfo = IP_CT_NEW;
31 nf_conntrack_get((*pskb)->nfct);
32
33 return XT_CONTINUE;
34}
35
36static int
37checkentry(const char *tablename,
38 const void *entry,
39 void *targinfo,
40 unsigned int targinfosize,
41 unsigned int hook_mask)
42{
43 if (targinfosize != 0) {
44 printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
45 targinfosize);
46 return 0;
47 }
48
49 if (strcmp(tablename, "raw") != 0) {
50 printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
51 return 0;
52 }
53
54 return 1;
55}
56
57static struct xt_target notrack_reg = {
58 .name = "NOTRACK",
59 .target = target,
60 .checkentry = checkentry,
61 .me = THIS_MODULE,
62};
63static struct xt_target notrack6_reg = {
64 .name = "NOTRACK",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
68};
69
70static int __init init(void)
71{
72 int ret;
73
74 ret = xt_register_target(AF_INET, &notrack_reg);
75 if (ret)
76 return ret;
77
78 ret = xt_register_target(AF_INET6, &notrack6_reg);
79 if (ret)
80 xt_unregister_target(AF_INET, &notrack_reg);
81
82 return ret;
83}
84
85static void __exit fini(void)
86{
87 xt_unregister_target(AF_INET6, &notrack6_reg);
88 xt_unregister_target(AF_INET, &notrack_reg);
89}
90
91module_init(init);
92module_exit(fini);
diff --git a/net/netfilter/xt_comment.c b/net/netfilter/xt_comment.c
new file mode 100644
index 000000000000..4ba6fd65c6e9
--- /dev/null
+++ b/net/netfilter/xt_comment.c
@@ -0,0 +1,80 @@
1/*
2 * Implements a dummy match to allow attaching comments to rules
3 *
4 * 2003-05-13 Brad Fisher (brad@info-link.net)
5 */
6
7#include <linux/module.h>
8#include <linux/skbuff.h>
9#include <linux/netfilter/x_tables.h>
10#include <linux/netfilter/xt_comment.h>
11
12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
13MODULE_DESCRIPTION("iptables comment match module");
14MODULE_LICENSE("GPL");
15MODULE_ALIAS("ipt_comment");
16MODULE_ALIAS("ip6t_comment");
17
18static int
19match(const struct sk_buff *skb,
20 const struct net_device *in,
21 const struct net_device *out,
22 const void *matchinfo,
23 int offset,
24 unsigned int protooff,
25 int *hotdrop)
26{
27 /* We always match */
28 return 1;
29}
30
31static int
32checkentry(const char *tablename,
33 const void *ip,
34 void *matchinfo,
35 unsigned int matchsize,
36 unsigned int hook_mask)
37{
38 /* Check the size */
39 if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info)))
40 return 0;
41 return 1;
42}
43
44static struct xt_match comment_match = {
45 .name = "comment",
46 .match = match,
47 .checkentry = checkentry,
48 .me = THIS_MODULE
49};
50
51static struct xt_match comment6_match = {
52 .name = "comment",
53 .match = match,
54 .checkentry = checkentry,
55 .me = THIS_MODULE
56};
57
58static int __init init(void)
59{
60 int ret;
61
62 ret = xt_register_match(AF_INET, &comment_match);
63 if (ret)
64 return ret;
65
66 ret = xt_register_match(AF_INET6, &comment6_match);
67 if (ret)
68 xt_unregister_match(AF_INET, &comment_match);
69
70 return ret;
71}
72
73static void __exit fini(void)
74{
75 xt_unregister_match(AF_INET, &comment_match);
76 xt_unregister_match(AF_INET6, &comment6_match);
77}
78
79module_init(init);
80module_exit(fini);
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
new file mode 100644
index 000000000000..150d2a4b0f71
--- /dev/null
+++ b/net/netfilter/xt_connbytes.c
@@ -0,0 +1,180 @@
1/* Kernel module to match connection tracking byte counter.
2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
3 *
4 * 2004-07-20 Harald Welte <laforge@netfilter.org>
5 * - reimplemented to use per-connection accounting counters
6 * - add functionality to match number of packets
7 * - add functionality to match average packet size
8 * - add support to match directions seperately
9 * 2005-10-16 Harald Welte <laforge@netfilter.org>
10 * - Port to x_tables
11 *
12 */
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <net/netfilter/nf_conntrack_compat.h>
16#include <linux/netfilter/x_tables.h>
17#include <linux/netfilter/xt_connbytes.h>
18
19#include <asm/div64.h>
20#include <asm/bitops.h>
21
22MODULE_LICENSE("GPL");
23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
24MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
25MODULE_ALIAS("ipt_connbytes");
26
27/* 64bit divisor, dividend and result. dynamic precision */
28static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor)
29{
30 u_int32_t d = divisor;
31
32 if (divisor > 0xffffffffULL) {
33 unsigned int shift = fls(divisor >> 32);
34
35 d = divisor >> shift;
36 dividend >>= shift;
37 }
38
39 do_div(dividend, d);
40 return dividend;
41}
42
43static int
44match(const struct sk_buff *skb,
45 const struct net_device *in,
46 const struct net_device *out,
47 const void *matchinfo,
48 int offset,
49 unsigned int protoff,
50 int *hotdrop)
51{
52 const struct xt_connbytes_info *sinfo = matchinfo;
53 u_int64_t what = 0; /* initialize to make gcc happy */
54 const struct ip_conntrack_counter *counters;
55
56 if (!(counters = nf_ct_get_counters(skb)))
57 return 0; /* no match */
58
59 switch (sinfo->what) {
60 case XT_CONNBYTES_PKTS:
61 switch (sinfo->direction) {
62 case XT_CONNBYTES_DIR_ORIGINAL:
63 what = counters[IP_CT_DIR_ORIGINAL].packets;
64 break;
65 case XT_CONNBYTES_DIR_REPLY:
66 what = counters[IP_CT_DIR_REPLY].packets;
67 break;
68 case XT_CONNBYTES_DIR_BOTH:
69 what = counters[IP_CT_DIR_ORIGINAL].packets;
70 what += counters[IP_CT_DIR_REPLY].packets;
71 break;
72 }
73 break;
74 case XT_CONNBYTES_BYTES:
75 switch (sinfo->direction) {
76 case XT_CONNBYTES_DIR_ORIGINAL:
77 what = counters[IP_CT_DIR_ORIGINAL].bytes;
78 break;
79 case XT_CONNBYTES_DIR_REPLY:
80 what = counters[IP_CT_DIR_REPLY].bytes;
81 break;
82 case XT_CONNBYTES_DIR_BOTH:
83 what = counters[IP_CT_DIR_ORIGINAL].bytes;
84 what += counters[IP_CT_DIR_REPLY].bytes;
85 break;
86 }
87 break;
88 case XT_CONNBYTES_AVGPKT:
89 switch (sinfo->direction) {
90 case XT_CONNBYTES_DIR_ORIGINAL:
91 what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes,
92 counters[IP_CT_DIR_ORIGINAL].packets);
93 break;
94 case XT_CONNBYTES_DIR_REPLY:
95 what = div64_64(counters[IP_CT_DIR_REPLY].bytes,
96 counters[IP_CT_DIR_REPLY].packets);
97 break;
98 case XT_CONNBYTES_DIR_BOTH:
99 {
100 u_int64_t bytes;
101 u_int64_t pkts;
102 bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
103 counters[IP_CT_DIR_REPLY].bytes;
104 pkts = counters[IP_CT_DIR_ORIGINAL].packets+
105 counters[IP_CT_DIR_REPLY].packets;
106
107 /* FIXME_THEORETICAL: what to do if sum
108 * overflows ? */
109
110 what = div64_64(bytes, pkts);
111 }
112 break;
113 }
114 break;
115 }
116
117 if (sinfo->count.to)
118 return (what <= sinfo->count.to && what >= sinfo->count.from);
119 else
120 return (what >= sinfo->count.from);
121}
122
123static int check(const char *tablename,
124 const void *ip,
125 void *matchinfo,
126 unsigned int matchsize,
127 unsigned int hook_mask)
128{
129 const struct xt_connbytes_info *sinfo = matchinfo;
130
131 if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info)))
132 return 0;
133
134 if (sinfo->what != XT_CONNBYTES_PKTS &&
135 sinfo->what != XT_CONNBYTES_BYTES &&
136 sinfo->what != XT_CONNBYTES_AVGPKT)
137 return 0;
138
139 if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
140 sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
141 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
142 return 0;
143
144 return 1;
145}
146
147static struct xt_match connbytes_match = {
148 .name = "connbytes",
149 .match = &match,
150 .checkentry = &check,
151 .me = THIS_MODULE
152};
153static struct xt_match connbytes6_match = {
154 .name = "connbytes",
155 .match = &match,
156 .checkentry = &check,
157 .me = THIS_MODULE
158};
159
160static int __init init(void)
161{
162 int ret;
163 ret = xt_register_match(AF_INET, &connbytes_match);
164 if (ret)
165 return ret;
166
167 ret = xt_register_match(AF_INET6, &connbytes6_match);
168 if (ret)
169 xt_unregister_match(AF_INET, &connbytes_match);
170 return ret;
171}
172
173static void __exit fini(void)
174{
175 xt_unregister_match(AF_INET, &connbytes_match);
176 xt_unregister_match(AF_INET6, &connbytes6_match);
177}
178
179module_init(init);
180module_exit(fini);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
new file mode 100644
index 000000000000..d06e925032da
--- /dev/null
+++ b/net/netfilter/xt_connmark.c
@@ -0,0 +1,109 @@
1/* This kernel module matches connection mark values set by the
2 * CONNMARK target
3 *
4 * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
5 * by Henrik Nordstrom <hno@marasystems.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/module.h>
23#include <linux/skbuff.h>
24
25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
26MODULE_DESCRIPTION("IP tables connmark match module");
27MODULE_LICENSE("GPL");
28MODULE_ALIAS("ipt_connmark");
29
30#include <linux/netfilter/x_tables.h>
31#include <linux/netfilter/xt_connmark.h>
32#include <net/netfilter/nf_conntrack_compat.h>
33
34static int
35match(const struct sk_buff *skb,
36 const struct net_device *in,
37 const struct net_device *out,
38 const void *matchinfo,
39 int offset,
40 unsigned int protoff,
41 int *hotdrop)
42{
43 const struct xt_connmark_info *info = matchinfo;
44 u_int32_t ctinfo;
45 const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo);
46 if (!ctmark)
47 return 0;
48
49 return (((*ctmark) & info->mask) == info->mark) ^ info->invert;
50}
51
52static int
53checkentry(const char *tablename,
54 const void *ip,
55 void *matchinfo,
56 unsigned int matchsize,
57 unsigned int hook_mask)
58{
59 struct xt_connmark_info *cm =
60 (struct xt_connmark_info *)matchinfo;
61 if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info)))
62 return 0;
63
64 if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
65 printk(KERN_WARNING "connmark: only support 32bit mark\n");
66 return 0;
67 }
68
69 return 1;
70}
71
72static struct xt_match connmark_match = {
73 .name = "connmark",
74 .match = &match,
75 .checkentry = &checkentry,
76 .me = THIS_MODULE
77};
78static struct xt_match connmark6_match = {
79 .name = "connmark",
80 .match = &match,
81 .checkentry = &checkentry,
82 .me = THIS_MODULE
83};
84
85
86static int __init init(void)
87{
88 int ret;
89
90 need_conntrack();
91
92 ret = xt_register_match(AF_INET, &connmark_match);
93 if (ret)
94 return ret;
95
96 ret = xt_register_match(AF_INET6, &connmark6_match);
97 if (ret)
98 xt_unregister_match(AF_INET, &connmark_match);
99 return ret;
100}
101
102static void __exit fini(void)
103{
104 xt_unregister_match(AF_INET6, &connmark6_match);
105 xt_unregister_match(AF_INET, &connmark_match);
106}
107
108module_init(init);
109module_exit(fini);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
new file mode 100644
index 000000000000..ffdebc95eb95
--- /dev/null
+++ b/net/netfilter/xt_conntrack.c
@@ -0,0 +1,238 @@
1/* Kernel module to match connection tracking information.
2 * Superset of Rusty's minimalistic state match.
3 *
4 * (C) 2001 Marc Boucher (marc@mbsi.ca).
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13
14#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
15#include <linux/netfilter_ipv4/ip_conntrack.h>
16#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
17#else
18#include <net/netfilter/nf_conntrack.h>
19#endif
20
21#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter/xt_conntrack.h>
23
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
26MODULE_DESCRIPTION("iptables connection tracking match module");
27MODULE_ALIAS("ipt_conntrack");
28
29#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
30
31static int
32match(const struct sk_buff *skb,
33 const struct net_device *in,
34 const struct net_device *out,
35 const void *matchinfo,
36 int offset,
37 unsigned int protoff,
38 int *hotdrop)
39{
40 const struct xt_conntrack_info *sinfo = matchinfo;
41 struct ip_conntrack *ct;
42 enum ip_conntrack_info ctinfo;
43 unsigned int statebit;
44
45 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
46
47#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
48
49 if (ct == &ip_conntrack_untracked)
50 statebit = XT_CONNTRACK_STATE_UNTRACKED;
51 else if (ct)
52 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
53 else
54 statebit = XT_CONNTRACK_STATE_INVALID;
55
56 if(sinfo->flags & XT_CONNTRACK_STATE) {
57 if (ct) {
58 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
59 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)
60 statebit |= XT_CONNTRACK_STATE_SNAT;
61
62 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip !=
63 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)
64 statebit |= XT_CONNTRACK_STATE_DNAT;
65 }
66
67 if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
68 return 0;
69 }
70
71 if(sinfo->flags & XT_CONNTRACK_PROTO) {
72 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
73 return 0;
74 }
75
76 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
77 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
78 return 0;
79 }
80
81 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
82 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
83 return 0;
84 }
85
86 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
87 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
88 return 0;
89 }
90
91 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
92 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
93 return 0;
94 }
95
96 if(sinfo->flags & XT_CONNTRACK_STATUS) {
97 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
98 return 0;
99 }
100
101 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
102 unsigned long expires;
103
104 if(!ct)
105 return 0;
106
107 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
108
109 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
110 return 0;
111 }
112
113 return 1;
114}
115
116#else /* CONFIG_IP_NF_CONNTRACK */
117static int
118match(const struct sk_buff *skb,
119 const struct net_device *in,
120 const struct net_device *out,
121 const void *matchinfo,
122 int offset,
123 unsigned int protoff,
124 int *hotdrop)
125{
126 const struct xt_conntrack_info *sinfo = matchinfo;
127 struct nf_conn *ct;
128 enum ip_conntrack_info ctinfo;
129 unsigned int statebit;
130
131 ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
132
133#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
134
135 if (ct == &nf_conntrack_untracked)
136 statebit = XT_CONNTRACK_STATE_UNTRACKED;
137 else if (ct)
138 statebit = XT_CONNTRACK_STATE_BIT(ctinfo);
139 else
140 statebit = XT_CONNTRACK_STATE_INVALID;
141
142 if(sinfo->flags & XT_CONNTRACK_STATE) {
143 if (ct) {
144 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip !=
145 ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip)
146 statebit |= XT_CONNTRACK_STATE_SNAT;
147
148 if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip !=
149 ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip)
150 statebit |= XT_CONNTRACK_STATE_DNAT;
151 }
152
153 if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE))
154 return 0;
155 }
156
157 if(sinfo->flags & XT_CONNTRACK_PROTO) {
158 if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO))
159 return 0;
160 }
161
162 if(sinfo->flags & XT_CONNTRACK_ORIGSRC) {
163 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC))
164 return 0;
165 }
166
167 if(sinfo->flags & XT_CONNTRACK_ORIGDST) {
168 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST))
169 return 0;
170 }
171
172 if(sinfo->flags & XT_CONNTRACK_REPLSRC) {
173 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC))
174 return 0;
175 }
176
177 if(sinfo->flags & XT_CONNTRACK_REPLDST) {
178 if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST))
179 return 0;
180 }
181
182 if(sinfo->flags & XT_CONNTRACK_STATUS) {
183 if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS))
184 return 0;
185 }
186
187 if(sinfo->flags & XT_CONNTRACK_EXPIRES) {
188 unsigned long expires;
189
190 if(!ct)
191 return 0;
192
193 expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0;
194
195 if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES))
196 return 0;
197 }
198
199 return 1;
200}
201
202#endif /* CONFIG_NF_IP_CONNTRACK */
203
204static int check(const char *tablename,
205 const void *ip,
206 void *matchinfo,
207 unsigned int matchsize,
208 unsigned int hook_mask)
209{
210 if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info)))
211 return 0;
212
213 return 1;
214}
215
216static struct xt_match conntrack_match = {
217 .name = "conntrack",
218 .match = &match,
219 .checkentry = &check,
220 .me = THIS_MODULE,
221};
222
223static int __init init(void)
224{
225 int ret;
226 need_conntrack();
227 ret = xt_register_match(AF_INET, &conntrack_match);
228
229 return ret;
230}
231
232static void __exit fini(void)
233{
234 xt_unregister_match(AF_INET, &conntrack_match);
235}
236
237module_init(init);
238module_exit(fini);
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
new file mode 100644
index 000000000000..779f42fc9524
--- /dev/null
+++ b/net/netfilter/xt_dccp.c
@@ -0,0 +1,221 @@
1/*
2 * iptables module for DCCP protocol header matching
3 *
4 * (C) 2005 by Harald Welte <laforge@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/spinlock.h>
14#include <net/ip.h>
15#include <linux/dccp.h>
16
17#include <linux/netfilter/x_tables.h>
18#include <linux/netfilter/xt_dccp.h>
19
20#include <linux/netfilter_ipv4/ip_tables.h>
21#include <linux/netfilter_ipv6/ip6_tables.h>
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
25MODULE_DESCRIPTION("Match for DCCP protocol packets");
26MODULE_ALIAS("ipt_dccp");
27
28#define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
29 || (!!((invflag) & (option)) ^ (cond)))
30
31static unsigned char *dccp_optbuf;
32static DEFINE_SPINLOCK(dccp_buflock);
33
34static inline int
35dccp_find_option(u_int8_t option,
36 const struct sk_buff *skb,
37 unsigned int protoff,
38 const struct dccp_hdr *dh,
39 int *hotdrop)
40{
41 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
42 unsigned char *op;
43 unsigned int optoff = __dccp_hdr_len(dh);
44 unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh);
45 unsigned int i;
46
47 if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) {
48 *hotdrop = 1;
49 return 0;
50 }
51
52 if (!optlen)
53 return 0;
54
55 spin_lock_bh(&dccp_buflock);
56 op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf);
57 if (op == NULL) {
58 /* If we don't have the whole header, drop packet. */
59 spin_unlock_bh(&dccp_buflock);
60 *hotdrop = 1;
61 return 0;
62 }
63
64 for (i = 0; i < optlen; ) {
65 if (op[i] == option) {
66 spin_unlock_bh(&dccp_buflock);
67 return 1;
68 }
69
70 if (op[i] < 2)
71 i++;
72 else
73 i += op[i+1]?:1;
74 }
75
76 spin_unlock_bh(&dccp_buflock);
77 return 0;
78}
79
80
81static inline int
82match_types(const struct dccp_hdr *dh, u_int16_t typemask)
83{
84 return (typemask & (1 << dh->dccph_type));
85}
86
87static inline int
88match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff,
89 const struct dccp_hdr *dh, int *hotdrop)
90{
91 return dccp_find_option(option, skb, protoff, dh, hotdrop);
92}
93
94static int
95match(const struct sk_buff *skb,
96 const struct net_device *in,
97 const struct net_device *out,
98 const void *matchinfo,
99 int offset,
100 unsigned int protoff,
101 int *hotdrop)
102{
103 const struct xt_dccp_info *info =
104 (const struct xt_dccp_info *)matchinfo;
105 struct dccp_hdr _dh, *dh;
106
107 if (offset)
108 return 0;
109
110 dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh);
111 if (dh == NULL) {
112 *hotdrop = 1;
113 return 0;
114 }
115
116 return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0])
117 && (ntohs(dh->dccph_sport) <= info->spts[1])),
118 XT_DCCP_SRC_PORTS, info->flags, info->invflags)
119 && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0])
120 && (ntohs(dh->dccph_dport) <= info->dpts[1])),
121 XT_DCCP_DEST_PORTS, info->flags, info->invflags)
122 && DCCHECK(match_types(dh, info->typemask),
123 XT_DCCP_TYPE, info->flags, info->invflags)
124 && DCCHECK(match_option(info->option, skb, protoff, dh,
125 hotdrop),
126 XT_DCCP_OPTION, info->flags, info->invflags);
127}
128
129static int
130checkentry(const char *tablename,
131 const void *inf,
132 void *matchinfo,
133 unsigned int matchsize,
134 unsigned int hook_mask)
135{
136 const struct ipt_ip *ip = inf;
137 const struct xt_dccp_info *info;
138
139 info = (const struct xt_dccp_info *)matchinfo;
140
141 return ip->proto == IPPROTO_DCCP
142 && !(ip->invflags & XT_INV_PROTO)
143 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
144 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
145 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
146 && !(info->invflags & ~info->flags);
147}
148
149static int
150checkentry6(const char *tablename,
151 const void *inf,
152 void *matchinfo,
153 unsigned int matchsize,
154 unsigned int hook_mask)
155{
156 const struct ip6t_ip6 *ip = inf;
157 const struct xt_dccp_info *info;
158
159 info = (const struct xt_dccp_info *)matchinfo;
160
161 return ip->proto == IPPROTO_DCCP
162 && !(ip->invflags & XT_INV_PROTO)
163 && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info))
164 && !(info->flags & ~XT_DCCP_VALID_FLAGS)
165 && !(info->invflags & ~XT_DCCP_VALID_FLAGS)
166 && !(info->invflags & ~info->flags);
167}
168
169
170static struct xt_match dccp_match =
171{
172 .name = "dccp",
173 .match = &match,
174 .checkentry = &checkentry,
175 .me = THIS_MODULE,
176};
177static struct xt_match dccp6_match =
178{
179 .name = "dccp",
180 .match = &match,
181 .checkentry = &checkentry6,
182 .me = THIS_MODULE,
183};
184
185
186static int __init init(void)
187{
188 int ret;
189
190 /* doff is 8 bits, so the maximum option size is (4*256). Don't put
191 * this in BSS since DaveM is worried about locked TLB's for kernel
192 * BSS. */
193 dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL);
194 if (!dccp_optbuf)
195 return -ENOMEM;
196 ret = xt_register_match(AF_INET, &dccp_match);
197 if (ret)
198 goto out_kfree;
199 ret = xt_register_match(AF_INET6, &dccp6_match);
200 if (ret)
201 goto out_unreg;
202
203 return ret;
204
205out_unreg:
206 xt_unregister_match(AF_INET, &dccp_match);
207out_kfree:
208 kfree(dccp_optbuf);
209
210 return ret;
211}
212
213static void __exit fini(void)
214{
215 xt_unregister_match(AF_INET6, &dccp6_match);
216 xt_unregister_match(AF_INET, &dccp_match);
217 kfree(dccp_optbuf);
218}
219
220module_init(init);
221module_exit(fini);
diff --git a/net/netfilter/xt_helper.c b/net/netfilter/xt_helper.c
new file mode 100644
index 000000000000..38b6715e1db4
--- /dev/null
+++ b/net/netfilter/xt_helper.c
@@ -0,0 +1,188 @@
1/* iptables module to match on related connections */
2/*
3 * (C) 2001 Martin Josefsson <gandalf@wlug.westbo.se>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * 19 Mar 2002 Harald Welte <laforge@gnumonks.org>:
10 * - Port to newnat infrastructure
11 */
12
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/netfilter.h>
16#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
17#include <linux/netfilter_ipv4/ip_conntrack.h>
18#include <linux/netfilter_ipv4/ip_conntrack_core.h>
19#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
20#else
21#include <net/netfilter/nf_conntrack.h>
22#include <net/netfilter/nf_conntrack_core.h>
23#include <net/netfilter/nf_conntrack_helper.h>
24#endif
25#include <linux/netfilter/x_tables.h>
26#include <linux/netfilter/xt_helper.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
30MODULE_DESCRIPTION("iptables helper match module");
31MODULE_ALIAS("ipt_helper");
32MODULE_ALIAS("ip6t_helper");
33
34#if 0
35#define DEBUGP printk
36#else
37#define DEBUGP(format, args...)
38#endif
39
40#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE)
41static int
42match(const struct sk_buff *skb,
43 const struct net_device *in,
44 const struct net_device *out,
45 const void *matchinfo,
46 int offset,
47 unsigned int protoff,
48 int *hotdrop)
49{
50 const struct xt_helper_info *info = matchinfo;
51 struct ip_conntrack *ct;
52 enum ip_conntrack_info ctinfo;
53 int ret = info->invert;
54
55 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
56 if (!ct) {
57 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
58 return ret;
59 }
60
61 if (!ct->master) {
62 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
63 return ret;
64 }
65
66 read_lock_bh(&ip_conntrack_lock);
67 if (!ct->master->helper) {
68 DEBUGP("xt_helper: master ct %p has no helper\n",
69 exp->expectant);
70 goto out_unlock;
71 }
72
73 DEBUGP("master's name = %s , info->name = %s\n",
74 ct->master->helper->name, info->name);
75
76 if (info->name[0] == '\0')
77 ret ^= 1;
78 else
79 ret ^= !strncmp(ct->master->helper->name, info->name,
80 strlen(ct->master->helper->name));
81out_unlock:
82 read_unlock_bh(&ip_conntrack_lock);
83 return ret;
84}
85
86#else /* CONFIG_IP_NF_CONNTRACK */
87
88static int
89match(const struct sk_buff *skb,
90 const struct net_device *in,
91 const struct net_device *out,
92 const void *matchinfo,
93 int offset,
94 unsigned int protoff,
95 int *hotdrop)
96{
97 const struct xt_helper_info *info = matchinfo;
98 struct nf_conn *ct;
99 enum ip_conntrack_info ctinfo;
100 int ret = info->invert;
101
102 ct = nf_ct_get((struct sk_buff *)skb, &ctinfo);
103 if (!ct) {
104 DEBUGP("xt_helper: Eek! invalid conntrack?\n");
105 return ret;
106 }
107
108 if (!ct->master) {
109 DEBUGP("xt_helper: conntrack %p has no master\n", ct);
110 return ret;
111 }
112
113 read_lock_bh(&nf_conntrack_lock);
114 if (!ct->master->helper) {
115 DEBUGP("xt_helper: master ct %p has no helper\n",
116 exp->expectant);
117 goto out_unlock;
118 }
119
120 DEBUGP("master's name = %s , info->name = %s\n",
121 ct->master->helper->name, info->name);
122
123 if (info->name[0] == '\0')
124 ret ^= 1;
125 else
126 ret ^= !strncmp(ct->master->helper->name, info->name,
127 strlen(ct->master->helper->name));
128out_unlock:
129 read_unlock_bh(&nf_conntrack_lock);
130 return ret;
131}
132#endif
133
134static int check(const char *tablename,
135 const void *inf,
136 void *matchinfo,
137 unsigned int matchsize,
138 unsigned int hook_mask)
139{
140 struct xt_helper_info *info = matchinfo;
141
142 info->name[29] = '\0';
143
144 /* verify size */
145 if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info)))
146 return 0;
147
148 return 1;
149}
150
151static struct xt_match helper_match = {
152 .name = "helper",
153 .match = &match,
154 .checkentry = &check,
155 .me = THIS_MODULE,
156};
157static struct xt_match helper6_match = {
158 .name = "helper",
159 .match = &match,
160 .checkentry = &check,
161 .me = THIS_MODULE,
162};
163
164static int __init init(void)
165{
166 int ret;
167 need_conntrack();
168
169 ret = xt_register_match(AF_INET, &helper_match);
170 if (ret < 0)
171 return ret;
172
173 ret = xt_register_match(AF_INET6, &helper6_match);
174 if (ret < 0)
175 xt_unregister_match(AF_INET, &helper_match);
176
177 return ret;
178}
179
180static void __exit fini(void)
181{
182 xt_unregister_match(AF_INET, &helper_match);
183 xt_unregister_match(AF_INET6, &helper6_match);
184}
185
186module_init(init);
187module_exit(fini);
188
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c
new file mode 100644
index 000000000000..ab6c710cf88f
--- /dev/null
+++ b/net/netfilter/xt_length.c
@@ -0,0 +1,98 @@
1/* Kernel module to match packet length. */
2/* (C) 1999-2001 James Morris <jmorros@intercode.com.au>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <net/ip.h>
12
13#include <linux/netfilter/xt_length.h>
14#include <linux/netfilter/x_tables.h>
15
16MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
17MODULE_DESCRIPTION("IP tables packet length matching module");
18MODULE_LICENSE("GPL");
19MODULE_ALIAS("ipt_length");
20MODULE_ALIAS("ip6t_length");
21
22static int
23match(const struct sk_buff *skb,
24 const struct net_device *in,
25 const struct net_device *out,
26 const void *matchinfo,
27 int offset,
28 unsigned int protoff,
29 int *hotdrop)
30{
31 const struct xt_length_info *info = matchinfo;
32 u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
33
34 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
35}
36
37static int
38match6(const struct sk_buff *skb,
39 const struct net_device *in,
40 const struct net_device *out,
41 const void *matchinfo,
42 int offset,
43 unsigned int protoff,
44 int *hotdrop)
45{
46 const struct xt_length_info *info = matchinfo;
47 u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr);
48
49 return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
50}
51
52static int
53checkentry(const char *tablename,
54 const void *ip,
55 void *matchinfo,
56 unsigned int matchsize,
57 unsigned int hook_mask)
58{
59 if (matchsize != XT_ALIGN(sizeof(struct xt_length_info)))
60 return 0;
61
62 return 1;
63}
64
65static struct xt_match length_match = {
66 .name = "length",
67 .match = &match,
68 .checkentry = &checkentry,
69 .me = THIS_MODULE,
70};
71static struct xt_match length6_match = {
72 .name = "length",
73 .match = &match6,
74 .checkentry = &checkentry,
75 .me = THIS_MODULE,
76};
77
78static int __init init(void)
79{
80 int ret;
81 ret = xt_register_match(AF_INET, &length_match);
82 if (ret)
83 return ret;
84 ret = xt_register_match(AF_INET6, &length6_match);
85 if (ret)
86 xt_unregister_match(AF_INET, &length_match);
87
88 return ret;
89}
90
91static void __exit fini(void)
92{
93 xt_unregister_match(AF_INET, &length_match);
94 xt_unregister_match(AF_INET6, &length6_match);
95}
96
97module_init(init);
98module_exit(fini);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
new file mode 100644
index 000000000000..15e40506bc3a
--- /dev/null
+++ b/net/netfilter/xt_limit.c
@@ -0,0 +1,175 @@
1/* Kernel module to control the rate
2 *
3 * 2 September 1999: Changed from the target RATE to the match
4 * `limit', removed logging. Did I mention that
5 * Alexey is a fucking genius?
6 * Rusty Russell (rusty@rustcorp.com.au). */
7
8/* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
9 * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/module.h>
17#include <linux/skbuff.h>
18#include <linux/spinlock.h>
19#include <linux/interrupt.h>
20
21#include <linux/netfilter/x_tables.h>
22#include <linux/netfilter/xt_limit.h>
23
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("iptables rate limit match");
27MODULE_ALIAS("ipt_limit");
28MODULE_ALIAS("ip6t_limit");
29
30/* The algorithm used is the Simple Token Bucket Filter (TBF)
31 * see net/sched/sch_tbf.c in the linux source tree
32 */
33
34static DEFINE_SPINLOCK(limit_lock);
35
36/* Rusty: This is my (non-mathematically-inclined) understanding of
37 this algorithm. The `average rate' in jiffies becomes your initial
38 amount of credit `credit' and the most credit you can ever have
39 `credit_cap'. The `peak rate' becomes the cost of passing the
40 test, `cost'.
41
42 `prev' tracks the last packet hit: you gain one credit per jiffy.
43 If you get credit balance more than this, the extra credit is
44 discarded. Every time the match passes, you lose `cost' credits;
45 if you don't have that many, the test fails.
46
47 See Alexey's formal explanation in net/sched/sch_tbf.c.
48
49 To get the maxmum range, we multiply by this factor (ie. you get N
50 credits per jiffy). We want to allow a rate as low as 1 per day
51 (slowest userspace tool allows), which means
52 CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32. ie. */
53#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
54
55/* Repeated shift and or gives us all 1s, final shift and add 1 gives
56 * us the power of 2 below the theoretical max, so GCC simply does a
57 * shift. */
58#define _POW2_BELOW2(x) ((x)|((x)>>1))
59#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
60#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
61#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
62#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
63#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
64
65#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
66
67static int
68ipt_limit_match(const struct sk_buff *skb,
69 const struct net_device *in,
70 const struct net_device *out,
71 const void *matchinfo,
72 int offset,
73 unsigned int protoff,
74 int *hotdrop)
75{
76 struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master;
77 unsigned long now = jiffies;
78
79 spin_lock_bh(&limit_lock);
80 r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
81 if (r->credit > r->credit_cap)
82 r->credit = r->credit_cap;
83
84 if (r->credit >= r->cost) {
85 /* We're not limited. */
86 r->credit -= r->cost;
87 spin_unlock_bh(&limit_lock);
88 return 1;
89 }
90
91 spin_unlock_bh(&limit_lock);
92 return 0;
93}
94
95/* Precision saver. */
96static u_int32_t
97user2credits(u_int32_t user)
98{
99 /* If multiplying would overflow... */
100 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
101 /* Divide first. */
102 return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
103
104 return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE;
105}
106
107static int
108ipt_limit_checkentry(const char *tablename,
109 const void *inf,
110 void *matchinfo,
111 unsigned int matchsize,
112 unsigned int hook_mask)
113{
114 struct xt_rateinfo *r = matchinfo;
115
116 if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo)))
117 return 0;
118
119 /* Check for overflow. */
120 if (r->burst == 0
121 || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
122 printk("Overflow in xt_limit, try lower: %u/%u\n",
123 r->avg, r->burst);
124 return 0;
125 }
126
127 /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
128 128. */
129 r->prev = jiffies;
130 r->credit = user2credits(r->avg * r->burst); /* Credits full. */
131 r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
132 r->cost = user2credits(r->avg);
133
134 /* For SMP, we only want to use one set of counters. */
135 r->master = r;
136
137 return 1;
138}
139
140static struct xt_match ipt_limit_reg = {
141 .name = "limit",
142 .match = ipt_limit_match,
143 .checkentry = ipt_limit_checkentry,
144 .me = THIS_MODULE,
145};
146static struct xt_match limit6_reg = {
147 .name = "limit",
148 .match = ipt_limit_match,
149 .checkentry = ipt_limit_checkentry,
150 .me = THIS_MODULE,
151};
152
153static int __init init(void)
154{
155 int ret;
156
157 ret = xt_register_match(AF_INET, &ipt_limit_reg);
158 if (ret)
159 return ret;
160
161 ret = xt_register_match(AF_INET6, &limit6_reg);
162 if (ret)
163 xt_unregister_match(AF_INET, &ipt_limit_reg);
164
165 return ret;
166}
167
168static void __exit fini(void)
169{
170 xt_unregister_match(AF_INET, &ipt_limit_reg);
171 xt_unregister_match(AF_INET6, &limit6_reg);
172}
173
174module_init(init);
175module_exit(fini);
diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c
new file mode 100644
index 000000000000..0461dcb5fc7a
--- /dev/null
+++ b/net/netfilter/xt_mac.c
@@ -0,0 +1,100 @@
1/* Kernel module to match MAC address parameters. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/if_ether.h>
14#include <linux/etherdevice.h>
15
16#include <linux/netfilter_ipv4.h>
17#include <linux/netfilter/xt_mac.h>
18#include <linux/netfilter/x_tables.h>
19
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
22MODULE_DESCRIPTION("iptables mac matching module");
23MODULE_ALIAS("ipt_mac");
24MODULE_ALIAS("ip6t_mac");
25
26static int
27match(const struct sk_buff *skb,
28 const struct net_device *in,
29 const struct net_device *out,
30 const void *matchinfo,
31 int offset,
32 unsigned int protoff,
33 int *hotdrop)
34{
35 const struct xt_mac_info *info = matchinfo;
36
37 /* Is mac pointer valid? */
38 return (skb->mac.raw >= skb->head
39 && (skb->mac.raw + ETH_HLEN) <= skb->data
40 /* If so, compare... */
41 && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr))
42 ^ info->invert));
43}
44
45static int
46ipt_mac_checkentry(const char *tablename,
47 const void *inf,
48 void *matchinfo,
49 unsigned int matchsize,
50 unsigned int hook_mask)
51{
52 /* FORWARD isn't always valid, but it's nice to be able to do --RR */
53 if (hook_mask
54 & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN)
55 | (1 << NF_IP_FORWARD))) {
56 printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n");
57 return 0;
58 }
59
60 if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info)))
61 return 0;
62
63 return 1;
64}
65
66static struct xt_match mac_match = {
67 .name = "mac",
68 .match = &match,
69 .checkentry = &ipt_mac_checkentry,
70 .me = THIS_MODULE,
71};
72static struct xt_match mac6_match = {
73 .name = "mac",
74 .match = &match,
75 .checkentry = &ipt_mac_checkentry,
76 .me = THIS_MODULE,
77};
78
79static int __init init(void)
80{
81 int ret;
82 ret = xt_register_match(AF_INET, &mac_match);
83 if (ret)
84 return ret;
85
86 ret = xt_register_match(AF_INET6, &mac6_match);
87 if (ret)
88 xt_unregister_match(AF_INET, &mac_match);
89
90 return ret;
91}
92
93static void __exit fini(void)
94{
95 xt_unregister_match(AF_INET, &mac_match);
96 xt_unregister_match(AF_INET6, &mac6_match);
97}
98
99module_init(init);
100module_exit(fini);
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
new file mode 100644
index 000000000000..2a0ac62b72c8
--- /dev/null
+++ b/net/netfilter/xt_mark.c
@@ -0,0 +1,91 @@
1/* Kernel module to match NFMARK values. */
2
3/* (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/module.h>
11#include <linux/skbuff.h>
12
13#include <linux/netfilter/xt_mark.h>
14#include <linux/netfilter/x_tables.h>
15
16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
18MODULE_DESCRIPTION("iptables mark matching module");
19MODULE_ALIAS("ipt_mark");
20MODULE_ALIAS("ip6t_mark");
21
22static int
23match(const struct sk_buff *skb,
24 const struct net_device *in,
25 const struct net_device *out,
26 const void *matchinfo,
27 int offset,
28 unsigned int protoff,
29 int *hotdrop)
30{
31 const struct xt_mark_info *info = matchinfo;
32
33 return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
34}
35
36static int
37checkentry(const char *tablename,
38 const void *entry,
39 void *matchinfo,
40 unsigned int matchsize,
41 unsigned int hook_mask)
42{
43 struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
44
45 if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info)))
46 return 0;
47
48 if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
49 printk(KERN_WARNING "mark: only supports 32bit mark\n");
50 return 0;
51 }
52
53 return 1;
54}
55
56static struct xt_match mark_match = {
57 .name = "mark",
58 .match = &match,
59 .checkentry = &checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_match mark6_match = {
64 .name = "mark",
65 .match = &match,
66 .checkentry = &checkentry,
67 .me = THIS_MODULE,
68};
69
70static int __init init(void)
71{
72 int ret;
73 ret = xt_register_match(AF_INET, &mark_match);
74 if (ret)
75 return ret;
76
77 ret = xt_register_match(AF_INET6, &mark6_match);
78 if (ret)
79 xt_unregister_match(AF_INET, &mark_match);
80
81 return ret;
82}
83
84static void __exit fini(void)
85{
86 xt_unregister_match(AF_INET, &mark_match);
87 xt_unregister_match(AF_INET6, &mark6_match);
88}
89
90module_init(init);
91module_exit(fini);
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
new file mode 100644
index 000000000000..19bb57c14dfe
--- /dev/null
+++ b/net/netfilter/xt_physdev.c
@@ -0,0 +1,155 @@
1/* Kernel module to match the bridge port in and
2 * out device for IP packets coming into contact with a bridge. */
3
4/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/netfilter/xt_physdev.h>
14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter_bridge.h>
16#define MATCH 1
17#define NOMATCH 0
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
21MODULE_DESCRIPTION("iptables bridge physical device match module");
22MODULE_ALIAS("ipt_physdev");
23MODULE_ALIAS("ip6t_physdev");
24
25static int
26match(const struct sk_buff *skb,
27 const struct net_device *in,
28 const struct net_device *out,
29 const void *matchinfo,
30 int offset,
31 unsigned int protoff,
32 int *hotdrop)
33{
34 int i;
35 static const char nulldevname[IFNAMSIZ];
36 const struct xt_physdev_info *info = matchinfo;
37 unsigned int ret;
38 const char *indev, *outdev;
39 struct nf_bridge_info *nf_bridge;
40
41 /* Not a bridged IP packet or no info available yet:
42 * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
43 * the destination device will be a bridge. */
44 if (!(nf_bridge = skb->nf_bridge)) {
45 /* Return MATCH if the invert flags of the used options are on */
46 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
47 !(info->invert & XT_PHYSDEV_OP_BRIDGED))
48 return NOMATCH;
49 if ((info->bitmask & XT_PHYSDEV_OP_ISIN) &&
50 !(info->invert & XT_PHYSDEV_OP_ISIN))
51 return NOMATCH;
52 if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) &&
53 !(info->invert & XT_PHYSDEV_OP_ISOUT))
54 return NOMATCH;
55 if ((info->bitmask & XT_PHYSDEV_OP_IN) &&
56 !(info->invert & XT_PHYSDEV_OP_IN))
57 return NOMATCH;
58 if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
59 !(info->invert & XT_PHYSDEV_OP_OUT))
60 return NOMATCH;
61 return MATCH;
62 }
63
64 /* This only makes sense in the FORWARD and POSTROUTING chains */
65 if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) &&
66 (!!(nf_bridge->mask & BRNF_BRIDGED) ^
67 !(info->invert & XT_PHYSDEV_OP_BRIDGED)))
68 return NOMATCH;
69
70 if ((info->bitmask & XT_PHYSDEV_OP_ISIN &&
71 (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) ||
72 (info->bitmask & XT_PHYSDEV_OP_ISOUT &&
73 (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
74 return NOMATCH;
75
76 if (!(info->bitmask & XT_PHYSDEV_OP_IN))
77 goto match_outdev;
78 indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
79 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
80 ret |= (((const unsigned int *)indev)[i]
81 ^ ((const unsigned int *)info->physindev)[i])
82 & ((const unsigned int *)info->in_mask)[i];
83 }
84
85 if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN))
86 return NOMATCH;
87
88match_outdev:
89 if (!(info->bitmask & XT_PHYSDEV_OP_OUT))
90 return MATCH;
91 outdev = nf_bridge->physoutdev ?
92 nf_bridge->physoutdev->name : nulldevname;
93 for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
94 ret |= (((const unsigned int *)outdev)[i]
95 ^ ((const unsigned int *)info->physoutdev)[i])
96 & ((const unsigned int *)info->out_mask)[i];
97 }
98
99 return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT);
100}
101
102static int
103checkentry(const char *tablename,
104 const void *ip,
105 void *matchinfo,
106 unsigned int matchsize,
107 unsigned int hook_mask)
108{
109 const struct xt_physdev_info *info = matchinfo;
110
111 if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info)))
112 return 0;
113 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
114 info->bitmask & ~XT_PHYSDEV_OP_MASK)
115 return 0;
116 return 1;
117}
118
119static struct xt_match physdev_match = {
120 .name = "physdev",
121 .match = &match,
122 .checkentry = &checkentry,
123 .me = THIS_MODULE,
124};
125
126static struct xt_match physdev6_match = {
127 .name = "physdev",
128 .match = &match,
129 .checkentry = &checkentry,
130 .me = THIS_MODULE,
131};
132
133static int __init init(void)
134{
135 int ret;
136
137 ret = xt_register_match(AF_INET, &physdev_match);
138 if (ret < 0)
139 return ret;
140
141 ret = xt_register_match(AF_INET6, &physdev6_match);
142 if (ret < 0)
143 xt_unregister_match(AF_INET, &physdev_match);
144
145 return ret;
146}
147
148static void __exit fini(void)
149{
150 xt_unregister_match(AF_INET, &physdev_match);
151 xt_unregister_match(AF_INET6, &physdev6_match);
152}
153
154module_init(init);
155module_exit(fini);
diff --git a/net/netfilter/xt_pkttype.c b/net/netfilter/xt_pkttype.c
new file mode 100644
index 000000000000..ab1b2630f97d
--- /dev/null
+++ b/net/netfilter/xt_pkttype.c
@@ -0,0 +1,82 @@
1/* (C) 1999-2001 Michal Ludvig <michal@logix.cz>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8#include <linux/module.h>
9#include <linux/skbuff.h>
10#include <linux/if_ether.h>
11#include <linux/if_packet.h>
12
13#include <linux/netfilter/xt_pkttype.h>
14#include <linux/netfilter/x_tables.h>
15
16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
19MODULE_ALIAS("ipt_pkttype");
20MODULE_ALIAS("ip6t_pkttype");
21
22static int match(const struct sk_buff *skb,
23 const struct net_device *in,
24 const struct net_device *out,
25 const void *matchinfo,
26 int offset,
27 unsigned int protoff,
28 int *hotdrop)
29{
30 const struct xt_pkttype_info *info = matchinfo;
31
32 return (skb->pkt_type == info->pkttype) ^ info->invert;
33}
34
35static int checkentry(const char *tablename,
36 const void *ip,
37 void *matchinfo,
38 unsigned int matchsize,
39 unsigned int hook_mask)
40{
41 if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info)))
42 return 0;
43
44 return 1;
45}
46
47static struct xt_match pkttype_match = {
48 .name = "pkttype",
49 .match = &match,
50 .checkentry = &checkentry,
51 .me = THIS_MODULE,
52};
53static struct xt_match pkttype6_match = {
54 .name = "pkttype",
55 .match = &match,
56 .checkentry = &checkentry,
57 .me = THIS_MODULE,
58};
59
60
61static int __init init(void)
62{
63 int ret;
64 ret = xt_register_match(AF_INET, &pkttype_match);
65 if (ret)
66 return ret;
67
68 ret = xt_register_match(AF_INET6, &pkttype6_match);
69 if (ret)
70 xt_unregister_match(AF_INET, &pkttype_match);
71
72 return ret;
73}
74
75static void __exit fini(void)
76{
77 xt_unregister_match(AF_INET, &pkttype_match);
78 xt_unregister_match(AF_INET6, &pkttype6_match);
79}
80
81module_init(init);
82module_exit(fini);
diff --git a/net/netfilter/xt_realm.c b/net/netfilter/xt_realm.c
new file mode 100644
index 000000000000..2b7e1781d34d
--- /dev/null
+++ b/net/netfilter/xt_realm.c
@@ -0,0 +1,79 @@
1/* IP tables module for matching the routing realm
2 *
3 * $Id: ipt_realm.c,v 1.3 2004/03/05 13:25:40 laforge Exp $
4 *
5 * (C) 2003 by Sampsa Ranta <sampsa@netsonic.fi>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/skbuff.h>
14#include <linux/netdevice.h>
15#include <net/route.h>
16
17#include <linux/netfilter_ipv4.h>
18#include <linux/netfilter/xt_realm.h>
19#include <linux/netfilter/x_tables.h>
20
21MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
22MODULE_LICENSE("GPL");
23MODULE_DESCRIPTION("X_tables realm match");
24MODULE_ALIAS("ipt_realm");
25
26static int
27match(const struct sk_buff *skb,
28 const struct net_device *in,
29 const struct net_device *out,
30 const void *matchinfo,
31 int offset,
32 unsigned int protoff,
33 int *hotdrop)
34{
35 const struct xt_realm_info *info = matchinfo;
36 struct dst_entry *dst = skb->dst;
37
38 return (info->id == (dst->tclassid & info->mask)) ^ info->invert;
39}
40
41static int check(const char *tablename,
42 const void *ip,
43 void *matchinfo,
44 unsigned int matchsize,
45 unsigned int hook_mask)
46{
47 if (hook_mask
48 & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
49 (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) {
50 printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
51 "LOCAL_IN or FORWARD.\n");
52 return 0;
53 }
54 if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) {
55 printk("xt_realm: invalid matchsize.\n");
56 return 0;
57 }
58 return 1;
59}
60
61static struct xt_match realm_match = {
62 .name = "realm",
63 .match = match,
64 .checkentry = check,
65 .me = THIS_MODULE
66};
67
68static int __init init(void)
69{
70 return xt_register_match(AF_INET, &realm_match);
71}
72
73static void __exit fini(void)
74{
75 xt_unregister_match(AF_INET, &realm_match);
76}
77
78module_init(init);
79module_exit(fini);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
new file mode 100644
index 000000000000..10fbfc5ba758
--- /dev/null
+++ b/net/netfilter/xt_sctp.c
@@ -0,0 +1,250 @@
1#include <linux/module.h>
2#include <linux/skbuff.h>
3#include <net/ip.h>
4#include <net/ipv6.h>
5#include <linux/sctp.h>
6
7#include <linux/netfilter/x_tables.h>
8#include <linux/netfilter/xt_sctp.h>
9#include <linux/netfilter_ipv4/ip_tables.h>
10#include <linux/netfilter_ipv6/ip6_tables.h>
11
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Kiran Kumar Immidi");
14MODULE_DESCRIPTION("Match for SCTP protocol packets");
15MODULE_ALIAS("ipt_sctp");
16
17#ifdef DEBUG_SCTP
18#define duprintf(format, args...) printk(format , ## args)
19#else
20#define duprintf(format, args...)
21#endif
22
23#define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
24 || (!!((invflag) & (option)) ^ (cond)))
25
26static int
27match_flags(const struct xt_sctp_flag_info *flag_info,
28 const int flag_count,
29 u_int8_t chunktype,
30 u_int8_t chunkflags)
31{
32 int i;
33
34 for (i = 0; i < flag_count; i++) {
35 if (flag_info[i].chunktype == chunktype) {
36 return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
37 }
38 }
39
40 return 1;
41}
42
43static inline int
44match_packet(const struct sk_buff *skb,
45 unsigned int offset,
46 const u_int32_t *chunkmap,
47 int chunk_match_type,
48 const struct xt_sctp_flag_info *flag_info,
49 const int flag_count,
50 int *hotdrop)
51{
52 u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
53 sctp_chunkhdr_t _sch, *sch;
54
55#ifdef DEBUG_SCTP
56 int i = 0;
57#endif
58
59 if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) {
60 SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap);
61 }
62
63 do {
64 sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
65 if (sch == NULL) {
66 duprintf("Dropping invalid SCTP packet.\n");
67 *hotdrop = 1;
68 return 0;
69 }
70
71 duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
72 ++i, offset, sch->type, htons(sch->length), sch->flags);
73
74 offset += (htons(sch->length) + 3) & ~3;
75
76 duprintf("skb->len: %d\toffset: %d\n", skb->len, offset);
77
78 if (SCTP_CHUNKMAP_IS_SET(chunkmap, sch->type)) {
79 switch (chunk_match_type) {
80 case SCTP_CHUNK_MATCH_ANY:
81 if (match_flags(flag_info, flag_count,
82 sch->type, sch->flags)) {
83 return 1;
84 }
85 break;
86
87 case SCTP_CHUNK_MATCH_ALL:
88 if (match_flags(flag_info, flag_count,
89 sch->type, sch->flags)) {
90 SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
91 }
92 break;
93
94 case SCTP_CHUNK_MATCH_ONLY:
95 if (!match_flags(flag_info, flag_count,
96 sch->type, sch->flags)) {
97 return 0;
98 }
99 break;
100 }
101 } else {
102 switch (chunk_match_type) {
103 case SCTP_CHUNK_MATCH_ONLY:
104 return 0;
105 }
106 }
107 } while (offset < skb->len);
108
109 switch (chunk_match_type) {
110 case SCTP_CHUNK_MATCH_ALL:
111 return SCTP_CHUNKMAP_IS_CLEAR(chunkmap);
112 case SCTP_CHUNK_MATCH_ANY:
113 return 0;
114 case SCTP_CHUNK_MATCH_ONLY:
115 return 1;
116 }
117
118 /* This will never be reached, but required to stop compiler whine */
119 return 0;
120}
121
122static int
123match(const struct sk_buff *skb,
124 const struct net_device *in,
125 const struct net_device *out,
126 const void *matchinfo,
127 int offset,
128 unsigned int protoff,
129 int *hotdrop)
130{
131 const struct xt_sctp_info *info;
132 sctp_sctphdr_t _sh, *sh;
133
134 info = (const struct xt_sctp_info *)matchinfo;
135
136 if (offset) {
137 duprintf("Dropping non-first fragment.. FIXME\n");
138 return 0;
139 }
140
141 sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh);
142 if (sh == NULL) {
143 duprintf("Dropping evil TCP offset=0 tinygram.\n");
144 *hotdrop = 1;
145 return 0;
146 }
147 duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest));
148
149 return SCCHECK(((ntohs(sh->source) >= info->spts[0])
150 && (ntohs(sh->source) <= info->spts[1])),
151 XT_SCTP_SRC_PORTS, info->flags, info->invflags)
152 && SCCHECK(((ntohs(sh->dest) >= info->dpts[0])
153 && (ntohs(sh->dest) <= info->dpts[1])),
154 XT_SCTP_DEST_PORTS, info->flags, info->invflags)
155 && SCCHECK(match_packet(skb, protoff,
156 info->chunkmap, info->chunk_match_type,
157 info->flag_info, info->flag_count,
158 hotdrop),
159 XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
160}
161
162static int
163checkentry(const char *tablename,
164 const void *inf,
165 void *matchinfo,
166 unsigned int matchsize,
167 unsigned int hook_mask)
168{
169 const struct xt_sctp_info *info;
170 const struct ipt_ip *ip = inf;
171
172 info = (const struct xt_sctp_info *)matchinfo;
173
174 return ip->proto == IPPROTO_SCTP
175 && !(ip->invflags & XT_INV_PROTO)
176 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
177 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
178 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
179 && !(info->invflags & ~info->flags)
180 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
181 (info->chunk_match_type &
182 (SCTP_CHUNK_MATCH_ALL
183 | SCTP_CHUNK_MATCH_ANY
184 | SCTP_CHUNK_MATCH_ONLY)));
185}
186
187static int
188checkentry6(const char *tablename,
189 const void *inf,
190 void *matchinfo,
191 unsigned int matchsize,
192 unsigned int hook_mask)
193{
194 const struct xt_sctp_info *info;
195 const struct ip6t_ip6 *ip = inf;
196
197 info = (const struct xt_sctp_info *)matchinfo;
198
199 return ip->proto == IPPROTO_SCTP
200 && !(ip->invflags & XT_INV_PROTO)
201 && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info))
202 && !(info->flags & ~XT_SCTP_VALID_FLAGS)
203 && !(info->invflags & ~XT_SCTP_VALID_FLAGS)
204 && !(info->invflags & ~info->flags)
205 && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) ||
206 (info->chunk_match_type &
207 (SCTP_CHUNK_MATCH_ALL
208 | SCTP_CHUNK_MATCH_ANY
209 | SCTP_CHUNK_MATCH_ONLY)));
210}
211
212
213static struct xt_match sctp_match =
214{
215 .name = "sctp",
216 .match = &match,
217 .checkentry = &checkentry,
218 .me = THIS_MODULE
219};
220static struct xt_match sctp6_match =
221{
222 .name = "sctp",
223 .match = &match,
224 .checkentry = &checkentry6,
225 .me = THIS_MODULE
226};
227
228
229static int __init init(void)
230{
231 int ret;
232 ret = xt_register_match(AF_INET, &sctp_match);
233 if (ret)
234 return ret;
235
236 ret = xt_register_match(AF_INET6, &sctp6_match);
237 if (ret)
238 xt_unregister_match(AF_INET, &sctp_match);
239
240 return ret;
241}
242
243static void __exit fini(void)
244{
245 xt_unregister_match(AF_INET6, &sctp6_match);
246 xt_unregister_match(AF_INET, &sctp_match);
247}
248
249module_init(init);
250module_exit(fini);
diff --git a/net/netfilter/xt_state.c b/net/netfilter/xt_state.c
new file mode 100644
index 000000000000..39ce808d40ef
--- /dev/null
+++ b/net/netfilter/xt_state.c
@@ -0,0 +1,96 @@
1/* Kernel module to match connection tracking information. */
2
3/* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2005 Netfilter Core Team <coreteam@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <net/netfilter/nf_conntrack_compat.h>
14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter/xt_state.h>
16
17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
19MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module");
20MODULE_ALIAS("ipt_state");
21MODULE_ALIAS("ip6t_state");
22
23static int
24match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 const struct xt_state_info *sinfo = matchinfo;
33 enum ip_conntrack_info ctinfo;
34 unsigned int statebit;
35
36 if (nf_ct_is_untracked(skb))
37 statebit = XT_STATE_UNTRACKED;
38 else if (!nf_ct_get_ctinfo(skb, &ctinfo))
39 statebit = XT_STATE_INVALID;
40 else
41 statebit = XT_STATE_BIT(ctinfo);
42
43 return (sinfo->statemask & statebit);
44}
45
46static int check(const char *tablename,
47 const void *ip,
48 void *matchinfo,
49 unsigned int matchsize,
50 unsigned int hook_mask)
51{
52 if (matchsize != XT_ALIGN(sizeof(struct xt_state_info)))
53 return 0;
54
55 return 1;
56}
57
58static struct xt_match state_match = {
59 .name = "state",
60 .match = &match,
61 .checkentry = &check,
62 .me = THIS_MODULE,
63};
64
65static struct xt_match state6_match = {
66 .name = "state",
67 .match = &match,
68 .checkentry = &check,
69 .me = THIS_MODULE,
70};
71
72static int __init init(void)
73{
74 int ret;
75
76 need_conntrack();
77
78 ret = xt_register_match(AF_INET, &state_match);
79 if (ret < 0)
80 return ret;
81
82 ret = xt_register_match(AF_INET6, &state6_match);
83 if (ret < 0)
84 xt_unregister_match(AF_INET,&state_match);
85
86 return ret;
87}
88
89static void __exit fini(void)
90{
91 xt_unregister_match(AF_INET, &state_match);
92 xt_unregister_match(AF_INET6, &state6_match);
93}
94
95module_init(init);
96module_exit(fini);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
new file mode 100644
index 000000000000..7c7d5c8807d6
--- /dev/null
+++ b/net/netfilter/xt_string.c
@@ -0,0 +1,111 @@
1/* String matching match for iptables
2 *
3 * (C) 2005 Pablo Neira Ayuso <pablo@eurodev.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/skbuff.h>
14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter/xt_string.h>
16#include <linux/textsearch.h>
17
18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
19MODULE_DESCRIPTION("IP tables string match module");
20MODULE_LICENSE("GPL");
21MODULE_ALIAS("ipt_string");
22MODULE_ALIAS("ip6t_string");
23
24static int match(const struct sk_buff *skb,
25 const struct net_device *in,
26 const struct net_device *out,
27 const void *matchinfo,
28 int offset,
29 unsigned int protoff,
30 int *hotdrop)
31{
32 struct ts_state state;
33 struct xt_string_info *conf = (struct xt_string_info *) matchinfo;
34
35 memset(&state, 0, sizeof(struct ts_state));
36
37 return (skb_find_text((struct sk_buff *)skb, conf->from_offset,
38 conf->to_offset, conf->config, &state)
39 != UINT_MAX) && !conf->invert;
40}
41
42#define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m)
43
44static int checkentry(const char *tablename,
45 const void *ip,
46 void *matchinfo,
47 unsigned int matchsize,
48 unsigned int hook_mask)
49{
50 struct xt_string_info *conf = matchinfo;
51 struct ts_config *ts_conf;
52
53 if (matchsize != XT_ALIGN(sizeof(struct xt_string_info)))
54 return 0;
55
56 /* Damn, can't handle this case properly with iptables... */
57 if (conf->from_offset > conf->to_offset)
58 return 0;
59
60 ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen,
61 GFP_KERNEL, TS_AUTOLOAD);
62 if (IS_ERR(ts_conf))
63 return 0;
64
65 conf->config = ts_conf;
66
67 return 1;
68}
69
70static void destroy(void *matchinfo, unsigned int matchsize)
71{
72 textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config);
73}
74
75static struct xt_match string_match = {
76 .name = "string",
77 .match = match,
78 .checkentry = checkentry,
79 .destroy = destroy,
80 .me = THIS_MODULE
81};
82static struct xt_match string6_match = {
83 .name = "string",
84 .match = match,
85 .checkentry = checkentry,
86 .destroy = destroy,
87 .me = THIS_MODULE
88};
89
90static int __init init(void)
91{
92 int ret;
93
94 ret = xt_register_match(AF_INET, &string_match);
95 if (ret)
96 return ret;
97 ret = xt_register_match(AF_INET6, &string6_match);
98 if (ret)
99 xt_unregister_match(AF_INET, &string_match);
100
101 return ret;
102}
103
104static void __exit fini(void)
105{
106 xt_unregister_match(AF_INET, &string_match);
107 xt_unregister_match(AF_INET6, &string6_match);
108}
109
110module_init(init);
111module_exit(fini);
diff --git a/net/netfilter/xt_tcpmss.c b/net/netfilter/xt_tcpmss.c
new file mode 100644
index 000000000000..acf7f533e9f1
--- /dev/null
+++ b/net/netfilter/xt_tcpmss.c
@@ -0,0 +1,172 @@
1/* Kernel module to match TCP MSS values. */
2
3/* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca>
4 * Portions (C) 2005 by Harald Welte <laforge@netfilter.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <net/tcp.h>
14
15#include <linux/netfilter/xt_tcpmss.h>
16#include <linux/netfilter/x_tables.h>
17
18#include <linux/netfilter_ipv4/ip_tables.h>
19#include <linux/netfilter_ipv6/ip6_tables.h>
20
21#define TH_SYN 0x02
22
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
25MODULE_DESCRIPTION("iptables TCP MSS match module");
26MODULE_ALIAS("ipt_tcpmss");
27
28/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */
29static inline int
30mssoption_match(u_int16_t min, u_int16_t max,
31 const struct sk_buff *skb,
32 unsigned int protoff,
33 int invert,
34 int *hotdrop)
35{
36 struct tcphdr _tcph, *th;
37 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
38 u8 _opt[15 * 4 - sizeof(_tcph)], *op;
39 unsigned int i, optlen;
40
41 /* If we don't have the whole header, drop packet. */
42 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
43 if (th == NULL)
44 goto dropit;
45
46 /* Malformed. */
47 if (th->doff*4 < sizeof(*th))
48 goto dropit;
49
50 optlen = th->doff*4 - sizeof(*th);
51 if (!optlen)
52 goto out;
53
54 /* Truncated options. */
55 op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt);
56 if (op == NULL)
57 goto dropit;
58
59 for (i = 0; i < optlen; ) {
60 if (op[i] == TCPOPT_MSS
61 && (optlen - i) >= TCPOLEN_MSS
62 && op[i+1] == TCPOLEN_MSS) {
63 u_int16_t mssval;
64
65 mssval = (op[i+2] << 8) | op[i+3];
66
67 return (mssval >= min && mssval <= max) ^ invert;
68 }
69 if (op[i] < 2) i++;
70 else i += op[i+1]?:1;
71 }
72out:
73 return invert;
74
75 dropit:
76 *hotdrop = 1;
77 return 0;
78}
79
80static int
81match(const struct sk_buff *skb,
82 const struct net_device *in,
83 const struct net_device *out,
84 const void *matchinfo,
85 int offset,
86 unsigned int protoff,
87 int *hotdrop)
88{
89 const struct xt_tcpmss_match_info *info = matchinfo;
90
91 return mssoption_match(info->mss_min, info->mss_max, skb, protoff,
92 info->invert, hotdrop);
93}
94
95static int
96checkentry(const char *tablename,
97 const void *ipinfo,
98 void *matchinfo,
99 unsigned int matchsize,
100 unsigned int hook_mask)
101{
102 const struct ipt_ip *ip = ipinfo;
103 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
104 return 0;
105
106 /* Must specify -p tcp */
107 if (ip->proto != IPPROTO_TCP || (ip->invflags & IPT_INV_PROTO)) {
108 printk("tcpmss: Only works on TCP packets\n");
109 return 0;
110 }
111
112 return 1;
113}
114
115static int
116checkentry6(const char *tablename,
117 const void *ipinfo,
118 void *matchinfo,
119 unsigned int matchsize,
120 unsigned int hook_mask)
121{
122 const struct ip6t_ip6 *ip = ipinfo;
123
124 if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info)))
125 return 0;
126
127 /* Must specify -p tcp */
128 if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) {
129 printk("tcpmss: Only works on TCP packets\n");
130 return 0;
131 }
132
133 return 1;
134}
135
136static struct xt_match tcpmss_match = {
137 .name = "tcpmss",
138 .match = &match,
139 .checkentry = &checkentry,
140 .me = THIS_MODULE,
141};
142
143static struct xt_match tcpmss6_match = {
144 .name = "tcpmss",
145 .match = &match,
146 .checkentry = &checkentry6,
147 .me = THIS_MODULE,
148};
149
150
151static int __init init(void)
152{
153 int ret;
154 ret = xt_register_match(AF_INET, &tcpmss_match);
155 if (ret)
156 return ret;
157
158 ret = xt_register_match(AF_INET6, &tcpmss6_match);
159 if (ret)
160 xt_unregister_match(AF_INET, &tcpmss_match);
161
162 return ret;
163}
164
165static void __exit fini(void)
166{
167 xt_unregister_match(AF_INET6, &tcpmss6_match);
168 xt_unregister_match(AF_INET, &tcpmss_match);
169}
170
171module_init(init);
172module_exit(fini);
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c
new file mode 100644
index 000000000000..33f86fd6f3e6
--- /dev/null
+++ b/net/netfilter/xt_tcpudp.c
@@ -0,0 +1,333 @@
1#include <linux/types.h>
2#include <linux/module.h>
3#include <net/ip.h>
4#include <net/ipv6.h>
5#include <net/tcp.h>
6#include <net/udp.h>
7#include <linux/netfilter/x_tables.h>
8#include <linux/netfilter/xt_tcpudp.h>
9#include <linux/netfilter_ipv4/ip_tables.h>
10#include <linux/netfilter_ipv6/ip6_tables.h>
11
12MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6");
13MODULE_LICENSE("GPL");
14MODULE_ALIAS("xt_tcp");
15MODULE_ALIAS("xt_udp");
16MODULE_ALIAS("ipt_udp");
17MODULE_ALIAS("ipt_tcp");
18MODULE_ALIAS("ip6t_udp");
19MODULE_ALIAS("ip6t_tcp");
20
21#ifdef DEBUG_IP_FIREWALL_USER
22#define duprintf(format, args...) printk(format , ## args)
23#else
24#define duprintf(format, args...)
25#endif
26
27
28/* Returns 1 if the port is matched by the range, 0 otherwise */
29static inline int
30port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
31{
32 int ret;
33
34 ret = (port >= min && port <= max) ^ invert;
35 return ret;
36}
37
38static int
39tcp_find_option(u_int8_t option,
40 const struct sk_buff *skb,
41 unsigned int protoff,
42 unsigned int optlen,
43 int invert,
44 int *hotdrop)
45{
46 /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
47 u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
48 unsigned int i;
49
50 duprintf("tcp_match: finding option\n");
51
52 if (!optlen)
53 return invert;
54
55 /* If we don't have the whole header, drop packet. */
56 op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr),
57 optlen, _opt);
58 if (op == NULL) {
59 *hotdrop = 1;
60 return 0;
61 }
62
63 for (i = 0; i < optlen; ) {
64 if (op[i] == option) return !invert;
65 if (op[i] < 2) i++;
66 else i += op[i+1]?:1;
67 }
68
69 return invert;
70}
71
72static int
73tcp_match(const struct sk_buff *skb,
74 const struct net_device *in,
75 const struct net_device *out,
76 const void *matchinfo,
77 int offset,
78 unsigned int protoff,
79 int *hotdrop)
80{
81 struct tcphdr _tcph, *th;
82 const struct xt_tcp *tcpinfo = matchinfo;
83
84 if (offset) {
85 /* To quote Alan:
86
87 Don't allow a fragment of TCP 8 bytes in. Nobody normal
88 causes this. Its a cracker trying to break in by doing a
89 flag overwrite to pass the direction checks.
90 */
91 if (offset == 1) {
92 duprintf("Dropping evil TCP offset=1 frag.\n");
93 *hotdrop = 1;
94 }
95 /* Must not be a fragment. */
96 return 0;
97 }
98
99#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
100
101 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
102 if (th == NULL) {
103 /* We've been asked to examine this packet, and we
104 can't. Hence, no choice but to drop. */
105 duprintf("Dropping evil TCP offset=0 tinygram.\n");
106 *hotdrop = 1;
107 return 0;
108 }
109
110 if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
111 ntohs(th->source),
112 !!(tcpinfo->invflags & XT_TCP_INV_SRCPT)))
113 return 0;
114 if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
115 ntohs(th->dest),
116 !!(tcpinfo->invflags & XT_TCP_INV_DSTPT)))
117 return 0;
118 if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
119 == tcpinfo->flg_cmp,
120 XT_TCP_INV_FLAGS))
121 return 0;
122 if (tcpinfo->option) {
123 if (th->doff * 4 < sizeof(_tcph)) {
124 *hotdrop = 1;
125 return 0;
126 }
127 if (!tcp_find_option(tcpinfo->option, skb, protoff,
128 th->doff*4 - sizeof(_tcph),
129 tcpinfo->invflags & XT_TCP_INV_OPTION,
130 hotdrop))
131 return 0;
132 }
133 return 1;
134}
135
136/* Called when user tries to insert an entry of this type. */
137static int
138tcp_checkentry(const char *tablename,
139 const void *info,
140 void *matchinfo,
141 unsigned int matchsize,
142 unsigned int hook_mask)
143{
144 const struct ipt_ip *ip = info;
145 const struct xt_tcp *tcpinfo = matchinfo;
146
147 /* Must specify proto == TCP, and no unknown invflags */
148 return ip->proto == IPPROTO_TCP
149 && !(ip->invflags & XT_INV_PROTO)
150 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
151 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
152}
153
154/* Called when user tries to insert an entry of this type. */
155static int
156tcp6_checkentry(const char *tablename,
157 const void *entry,
158 void *matchinfo,
159 unsigned int matchsize,
160 unsigned int hook_mask)
161{
162 const struct ip6t_ip6 *ipv6 = entry;
163 const struct xt_tcp *tcpinfo = matchinfo;
164
165 /* Must specify proto == TCP, and no unknown invflags */
166 return ipv6->proto == IPPROTO_TCP
167 && !(ipv6->invflags & XT_INV_PROTO)
168 && matchsize == XT_ALIGN(sizeof(struct xt_tcp))
169 && !(tcpinfo->invflags & ~XT_TCP_INV_MASK);
170}
171
172
173static int
174udp_match(const struct sk_buff *skb,
175 const struct net_device *in,
176 const struct net_device *out,
177 const void *matchinfo,
178 int offset,
179 unsigned int protoff,
180 int *hotdrop)
181{
182 struct udphdr _udph, *uh;
183 const struct xt_udp *udpinfo = matchinfo;
184
185 /* Must not be a fragment. */
186 if (offset)
187 return 0;
188
189 uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
190 if (uh == NULL) {
191 /* We've been asked to examine this packet, and we
192 can't. Hence, no choice but to drop. */
193 duprintf("Dropping evil UDP tinygram.\n");
194 *hotdrop = 1;
195 return 0;
196 }
197
198 return port_match(udpinfo->spts[0], udpinfo->spts[1],
199 ntohs(uh->source),
200 !!(udpinfo->invflags & XT_UDP_INV_SRCPT))
201 && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
202 ntohs(uh->dest),
203 !!(udpinfo->invflags & XT_UDP_INV_DSTPT));
204}
205
206/* Called when user tries to insert an entry of this type. */
207static int
208udp_checkentry(const char *tablename,
209 const void *info,
210 void *matchinfo,
211 unsigned int matchinfosize,
212 unsigned int hook_mask)
213{
214 const struct ipt_ip *ip = info;
215 const struct xt_udp *udpinfo = matchinfo;
216
217 /* Must specify proto == UDP, and no unknown invflags */
218 if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) {
219 duprintf("ipt_udp: Protocol %u != %u\n", ip->proto,
220 IPPROTO_UDP);
221 return 0;
222 }
223 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
224 duprintf("ipt_udp: matchsize %u != %u\n",
225 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
226 return 0;
227 }
228 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
229 duprintf("ipt_udp: unknown flags %X\n",
230 udpinfo->invflags);
231 return 0;
232 }
233
234 return 1;
235}
236
237/* Called when user tries to insert an entry of this type. */
238static int
239udp6_checkentry(const char *tablename,
240 const void *entry,
241 void *matchinfo,
242 unsigned int matchinfosize,
243 unsigned int hook_mask)
244{
245 const struct ip6t_ip6 *ipv6 = entry;
246 const struct xt_udp *udpinfo = matchinfo;
247
248 /* Must specify proto == UDP, and no unknown invflags */
249 if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) {
250 duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
251 IPPROTO_UDP);
252 return 0;
253 }
254 if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) {
255 duprintf("ip6t_udp: matchsize %u != %u\n",
256 matchinfosize, XT_ALIGN(sizeof(struct xt_udp)));
257 return 0;
258 }
259 if (udpinfo->invflags & ~XT_UDP_INV_MASK) {
260 duprintf("ip6t_udp: unknown flags %X\n",
261 udpinfo->invflags);
262 return 0;
263 }
264
265 return 1;
266}
267
268static struct xt_match tcp_matchstruct = {
269 .name = "tcp",
270 .match = &tcp_match,
271 .checkentry = &tcp_checkentry,
272 .me = THIS_MODULE,
273};
274static struct xt_match tcp6_matchstruct = {
275 .name = "tcp",
276 .match = &tcp_match,
277 .checkentry = &tcp6_checkentry,
278 .me = THIS_MODULE,
279};
280
281static struct xt_match udp_matchstruct = {
282 .name = "udp",
283 .match = &udp_match,
284 .checkentry = &udp_checkentry,
285 .me = THIS_MODULE,
286};
287static struct xt_match udp6_matchstruct = {
288 .name = "udp",
289 .match = &udp_match,
290 .checkentry = &udp6_checkentry,
291 .me = THIS_MODULE,
292};
293
294static int __init init(void)
295{
296 int ret;
297 ret = xt_register_match(AF_INET, &tcp_matchstruct);
298 if (ret)
299 return ret;
300
301 ret = xt_register_match(AF_INET6, &tcp6_matchstruct);
302 if (ret)
303 goto out_unreg_tcp;
304
305 ret = xt_register_match(AF_INET, &udp_matchstruct);
306 if (ret)
307 goto out_unreg_tcp6;
308
309 ret = xt_register_match(AF_INET6, &udp6_matchstruct);
310 if (ret)
311 goto out_unreg_udp;
312
313 return ret;
314
315out_unreg_udp:
316 xt_unregister_match(AF_INET, &tcp_matchstruct);
317out_unreg_tcp6:
318 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
319out_unreg_tcp:
320 xt_unregister_match(AF_INET, &tcp_matchstruct);
321 return ret;
322}
323
324static void __exit fini(void)
325{
326 xt_unregister_match(AF_INET6, &udp6_matchstruct);
327 xt_unregister_match(AF_INET, &udp_matchstruct);
328 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
329 xt_unregister_match(AF_INET, &tcp_matchstruct);
330}
331
332module_init(init);
333module_exit(fini);