]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.7-pom-ng-20040629.patch
- obsolete
[packages/kernel.git] / 2.6.7-pom-ng-20040629.patch
1 --- linux-2.6.9-rc1/include/linux/netfilter_ipv4/ip_conntrack.h.orig    2004-08-29 16:44:31.000000000 +0200
2 +++ linux-2.6.9-rc1/include/linux/netfilter_ipv4/ip_conntrack.h 2004-08-29 19:58:04.869439888 +0200
3 @@ -220,6 +220,10 @@
4         } nat;
5  #endif /* CONFIG_IP_NF_NAT_NEEDED */
6  
7 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
8 +       unsigned long mark;
9 +#endif
10 +
11  };
12  
13  /* get master conntrack via master expectation */
14 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ip_queue.h linux-2.6.7/include/linux/netfilter_ipv4/ip_queue.h
15 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ip_queue.h     2004-06-16 07:20:03.000000000 +0200
16 +++ linux-2.6.7/include/linux/netfilter_ipv4/ip_queue.h 2004-06-29 12:35:08.141268712 +0200
17 @@ -47,10 +47,20 @@
18         unsigned char payload[0];       /* Optional replacement packet */
19  } ipq_verdict_msg_t;
20  
21 +typedef struct ipq_vwmark_msg {
22 +       unsigned int value;             /* Verdict to hand to netfilter */
23 +       unsigned long id;               /* Packet ID for this verdict */
24 +       size_t data_len;                /* Length of replacement data */
25 +       unsigned char payload[0];       /* Optional replacement packet */
26 +       unsigned long nfmark;           /* Mark for the Packet */
27 +} ipq_vwmark_msg_t;
28 +
29 +
30  typedef struct ipq_peer_msg {
31         union {
32                 ipq_verdict_msg_t verdict;
33                 ipq_mode_msg_t mode;
34 +                ipq_vwmark_msg_t vwmark;
35         } msg;
36  } ipq_peer_msg_t;
37  
38 @@ -67,6 +77,7 @@
39  #define IPQM_MODE      (IPQM_BASE + 1)         /* Mode request from peer */
40  #define IPQM_VERDICT   (IPQM_BASE + 2)         /* Verdict from peer */ 
41  #define IPQM_PACKET    (IPQM_BASE + 3)         /* Packet from kernel */
42 -#define IPQM_MAX       (IPQM_BASE + 4)
43 +#define IPQM_VWMARK    (IPQM_BASE + 4)         /* Verdict and mark from peer */
44 +#define IPQM_MAX       (IPQM_BASE + 5)
45  
46  #endif /*_IP_QUEUE_H*/
47 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_CONNMARK.h
48 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h 1970-01-01 01:00:00.000000000 +0100
49 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_CONNMARK.h     2004-06-29 12:34:21.508357992 +0200
50 @@ -0,0 +1,25 @@
51 +#ifndef _IPT_CONNMARK_H_target
52 +#define _IPT_CONNMARK_H_target
53 +
54 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
55 + * by Henrik Nordstrom <hno@marasystems.com>
56 + *
57 + * This program is free software; you can redistribute it and/or modify
58 + * it under the terms of the GNU General Public License as published by
59 + * the Free Software Foundation; either version 2 of the License, or
60 + * (at your option) any later version.
61 + */
62 +
63 +enum {
64 +       IPT_CONNMARK_SET = 0,
65 +       IPT_CONNMARK_SAVE,
66 +       IPT_CONNMARK_RESTORE
67 +};
68 +
69 +struct ipt_connmark_target_info {
70 +       unsigned long mark;
71 +       unsigned long mask;
72 +       u_int8_t mode;
73 +};
74 +
75 +#endif /*_IPT_CONNMARK_H_target*/
76 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_IPMARK.h
77 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_IPMARK.h   1970-01-01 01:00:00.000000000 +0100
78 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_IPMARK.h       2004-06-29 12:34:27.607430792 +0200
79 @@ -0,0 +1,13 @@
80 +#ifndef _IPT_IPMARK_H_target
81 +#define _IPT_IPMARK_H_target
82 +
83 +struct ipt_ipmark_target_info {
84 +       unsigned long andmask;
85 +       unsigned long ormask;
86 +       unsigned int addr;
87 +};
88 +
89 +#define IPT_IPMARK_SRC    0
90 +#define IPT_IPMARK_DST    1
91 +
92 +#endif /*_IPT_IPMARK_H_target*/
93 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ROUTE.h
94 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ROUTE.h    1970-01-01 01:00:00.000000000 +0100
95 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ROUTE.h        2004-06-29 12:34:33.507533840 +0200
96 @@ -0,0 +1,22 @@
97 +/* Header file for iptables ipt_ROUTE target
98 + *
99 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
100 + *
101 + * This software is distributed under GNU GPL v2, 1991
102 + */
103 +#ifndef _IPT_ROUTE_H_target
104 +#define _IPT_ROUTE_H_target
105 +
106 +#define IPT_ROUTE_IFNAMSIZ 16
107 +
108 +struct ipt_route_target_info {
109 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
110 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
111 +       u_int32_t gw;                           /* IP address of gateway */
112 +       u_int8_t  flags;
113 +};
114 +
115 +/* Values for "flags" field */
116 +#define IPT_ROUTE_CONTINUE        0x01
117 +
118 +#endif /*_IPT_ROUTE_H_target*/
119 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h
120 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_TTL.h      1970-01-01 01:00:00.000000000 +0100
121 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_TTL.h  2004-06-29 12:32:03.616320768 +0200
122 @@ -0,0 +1,21 @@
123 +/* TTL modification module for IP tables
124 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
125 +
126 +#ifndef _IPT_TTL_H
127 +#define _IPT_TTL_H
128 +
129 +enum {
130 +       IPT_TTL_SET = 0,
131 +       IPT_TTL_INC,
132 +       IPT_TTL_DEC
133 +};
134 +
135 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
136 +
137 +struct ipt_TTL_info {
138 +       u_int8_t        mode;
139 +       u_int8_t        ttl;
140 +};
141 +
142 +
143 +#endif
144 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_XOR.h
145 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_XOR.h      1970-01-01 01:00:00.000000000 +0100
146 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_XOR.h  2004-06-29 12:34:46.048627304 +0200
147 @@ -0,0 +1,9 @@
148 +#ifndef _IPT_XOR_H
149 +#define _IPT_XOR_H
150 +
151 +struct ipt_XOR_info {
152 +       char            key[30];
153 +       u_int8_t        block_size;
154 +};
155 +
156 +#endif /* _IPT_XOR_H */
157 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_connlimit.h
158 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connlimit.h        1970-01-01 01:00:00.000000000 +0100
159 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_connlimit.h    2004-06-29 12:32:05.986960376 +0200
160 @@ -0,0 +1,12 @@
161 +#ifndef _IPT_CONNLIMIT_H
162 +#define _IPT_CONNLIMIT_H
163 +
164 +struct ipt_connlimit_data;
165 +
166 +struct ipt_connlimit_info {
167 +       int limit;
168 +       int inverse;
169 +       u_int32_t mask;
170 +       struct ipt_connlimit_data *data;
171 +};
172 +#endif /* _IPT_CONNLIMIT_H */
173 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_connmark.h
174 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_connmark.h 1970-01-01 01:00:00.000000000 +0100
175 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_connmark.h     2004-06-29 12:34:21.510357688 +0200
176 @@ -0,0 +1,18 @@
177 +#ifndef _IPT_CONNMARK_H
178 +#define _IPT_CONNMARK_H
179 +
180 +/* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
181 + * by Henrik Nordstrom <hno@marasystems.com>
182 + *
183 + * This program is free software; you can redistribute it and/or modify
184 + * it under the terms of the GNU General Public License as published by
185 + * the Free Software Foundation; either version 2 of the License, or
186 + * (at your option) any later version.
187 + */
188 +
189 +struct ipt_connmark_info {
190 +       unsigned long mark, mask;
191 +       u_int8_t invert;
192 +};
193 +
194 +#endif /*_IPT_CONNMARK_H*/
195 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h
196 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
197 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_dstlimit.h     2004-06-29 12:32:07.241769616 +0200
198 @@ -0,0 +1,39 @@
199 +#ifndef _IPT_DSTLIMIT_H
200 +#define _IPT_DSTLIMIT_H
201 +
202 +/* timings are in milliseconds. */
203 +#define IPT_DSTLIMIT_SCALE 10000
204 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
205 +   seconds, or one every 59 hours. */
206 +
207 +/* details of this structure hidden by the implementation */
208 +struct ipt_dstlimit_htable;
209 +
210 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
211 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
212 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
213 +
214 +struct dstlimit_cfg {
215 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
216 +       u_int32_t avg;    /* Average secs between packets * scale */
217 +       u_int32_t burst;  /* Period multiplier for upper limit. */
218 +
219 +       /* user specified */
220 +       u_int32_t size;         /* how many buckets */
221 +       u_int32_t max;          /* max number of entries */
222 +       u_int32_t gc_interval;  /* gc interval */
223 +       u_int32_t expire;       /* when do entries expire? */
224 +};
225 +
226 +struct ipt_dstlimit_info {
227 +       char name [IFNAMSIZ];           /* name */
228 +       struct dstlimit_cfg cfg;
229 +       struct ipt_dstlimit_htable *hinfo;
230 +
231 +       /* Used internally by the kernel */
232 +       union {
233 +               void *ptr;
234 +               struct ipt_dstlimit_info *master;
235 +       } u;
236 +};
237 +#endif /*_IPT_DSTLIMIT_H*/
238 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h
239 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
240 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_fuzzy.h        2004-06-29 12:32:08.818529912 +0200
241 @@ -0,0 +1,21 @@
242 +#ifndef _IPT_FUZZY_H
243 +#define _IPT_FUZZY_H
244 +
245 +#include <linux/param.h>
246 +#include <linux/types.h>
247 +
248 +#define MAXFUZZYRATE 10000000
249 +#define MINFUZZYRATE 3
250 +
251 +struct ipt_fuzzy_info {
252 +       u_int32_t minimum_rate;
253 +       u_int32_t maximum_rate;
254 +       u_int32_t packets_total;
255 +       u_int32_t bytes_total;
256 +       u_int32_t previous_time;
257 +       u_int32_t present_time;
258 +       u_int32_t mean_rate;
259 +       u_int8_t acceptance_rate;
260 +};
261 +
262 +#endif /*_IPT_FUZZY_H*/
263 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h
264 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_ipv4options.h      1970-01-01 01:00:00.000000000 +0100
265 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_ipv4options.h  2004-06-29 12:32:14.110725376 +0200
266 @@ -0,0 +1,21 @@
267 +#ifndef __ipt_ipv4options_h_included__
268 +#define __ipt_ipv4options_h_included__
269 +
270 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
271 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
272 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
273 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
274 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
275 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
276 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
277 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
278 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
279 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
280 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
281 +
282 +struct ipt_ipv4options_info {
283 +       u_int16_t options;
284 +};
285 +
286 +
287 +#endif /* __ipt_ipv4options_h_included__ */
288 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h
289 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_mport.h    1970-01-01 01:00:00.000000000 +0100
290 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_mport.h        2004-06-29 12:32:15.539508168 +0200
291 @@ -0,0 +1,24 @@
292 +#ifndef _IPT_MPORT_H
293 +#define _IPT_MPORT_H
294 +#include <linux/netfilter_ipv4/ip_tables.h>
295 +
296 +#define IPT_MPORT_SOURCE (1<<0)
297 +#define IPT_MPORT_DESTINATION (1<<1)
298 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
299 +
300 +#define IPT_MULTI_PORTS        15
301 +
302 +/* Must fit inside union ipt_matchinfo: 32 bytes */
303 +/* every entry in ports[] except for the last one has one bit in pflags
304 + * associated with it. If this bit is set, the port is the first port of
305 + * a portrange, with the next entry being the last.
306 + * End of list is marked with pflags bit set and port=65535.
307 + * If 14 ports are used (last one does not have a pflag), the last port
308 + * is repeated to fill the last entry in ports[] */
309 +struct ipt_mport
310 +{
311 +       u_int8_t flags:2;                       /* Type of comparison */
312 +       u_int16_t pflags:14;                    /* Port flags */
313 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
314 +};
315 +#endif /*_IPT_MPORT_H*/
316 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h
317 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_nth.h      1970-01-01 01:00:00.000000000 +0100
318 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_nth.h  2004-06-29 12:32:16.697332152 +0200
319 @@ -0,0 +1,19 @@
320 +#ifndef _IPT_NTH_H
321 +#define _IPT_NTH_H
322 +
323 +#include <linux/param.h>
324 +#include <linux/types.h>
325 +
326 +#ifndef IPT_NTH_NUM_COUNTERS
327 +#define IPT_NTH_NUM_COUNTERS 16
328 +#endif
329 +
330 +struct ipt_nth_info {
331 +       u_int8_t every;
332 +       u_int8_t not;
333 +       u_int8_t startat;
334 +       u_int8_t counter;
335 +       u_int8_t packet;
336 +};
337 +
338 +#endif /*_IPT_NTH_H*/
339 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_policy.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_policy.h
340 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_policy.h   1970-01-01 01:00:00.000000000 +0100
341 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_policy.h       2004-06-29 12:35:40.044418696 +0200
342 @@ -0,0 +1,52 @@
343 +#ifndef _IPT_POLICY_H
344 +#define _IPT_POLICY_H
345 +
346 +#define POLICY_MAX_ELEM        4
347 +
348 +enum ipt_policy_flags
349 +{
350 +       POLICY_MATCH_IN         = 0x1,
351 +       POLICY_MATCH_OUT        = 0x2,
352 +       POLICY_MATCH_NONE       = 0x4,
353 +       POLICY_MATCH_STRICT     = 0x8,
354 +};
355 +
356 +enum ipt_policy_modes
357 +{
358 +       POLICY_MODE_TRANSPORT,
359 +       POLICY_MODE_TUNNEL
360 +};
361 +
362 +struct ipt_policy_spec
363 +{
364 +       u_int8_t        saddr:1,
365 +                       daddr:1,
366 +                       proto:1,
367 +                       mode:1,
368 +                       spi:1,
369 +                       reqid:1;
370 +};
371 +
372 +struct ipt_policy_elem
373 +{
374 +       u_int32_t       saddr;
375 +       u_int32_t       smask;
376 +       u_int32_t       daddr;
377 +       u_int32_t       dmask;
378 +       u_int32_t       spi;
379 +       u_int32_t       reqid;
380 +       u_int8_t        proto;
381 +       u_int8_t        mode;
382 +
383 +       struct ipt_policy_spec  match;
384 +       struct ipt_policy_spec  invert;
385 +};
386 +
387 +struct ipt_policy_info
388 +{
389 +       struct ipt_policy_elem pol[POLICY_MAX_ELEM];
390 +       u_int16_t flags;
391 +       u_int16_t len;
392 +};
393 +
394 +#endif /* _IPT_POLICY_H */
395 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h
396 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_psd.h      1970-01-01 01:00:00.000000000 +0100
397 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_psd.h  2004-06-29 12:32:18.293089560 +0200
398 @@ -0,0 +1,40 @@
399 +#ifndef _IPT_PSD_H
400 +#define _IPT_PSD_H
401 +
402 +#include <linux/param.h>
403 +#include <linux/types.h>
404 +
405 +/*
406 + * High port numbers have a lower weight to reduce the frequency of false
407 + * positives, such as from passive mode FTP transfers.
408 + */
409 +#define PORT_WEIGHT_PRIV               3
410 +#define PORT_WEIGHT_HIGH               1
411 +
412 +/*
413 + * Port scan detection thresholds: at least COUNT ports need to be scanned
414 + * from the same source, with no longer than DELAY ticks between ports.
415 + */
416 +#define SCAN_MIN_COUNT                 7
417 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
418 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
419 +#define SCAN_DELAY_THRESHOLD           (300) /* old usage of HZ here was erroneously and broke under uml */
420 +
421 +/*
422 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
423 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
424 + * HASH_MAX source addresses per the same hash value.
425 + */
426 +#define LIST_SIZE                      0x100
427 +#define HASH_LOG                       9
428 +#define HASH_SIZE                      (1 << HASH_LOG)
429 +#define HASH_MAX                       0x10
430 +
431 +struct ipt_psd_info {
432 +       unsigned int weight_threshold;
433 +       unsigned int delay_threshold;
434 +       unsigned short lo_ports_weight;
435 +       unsigned short hi_ports_weight;
436 +};
437 +
438 +#endif /*_IPT_PSD_H*/
439 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h
440 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_quota.h    1970-01-01 01:00:00.000000000 +0100
441 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_quota.h        2004-06-29 12:32:19.477909440 +0200
442 @@ -0,0 +1,11 @@
443 +#ifndef _IPT_QUOTA_H
444 +#define _IPT_QUOTA_H
445 +
446 +/* print debug info in both kernel/netfilter module & iptable library */
447 +//#define DEBUG_IPT_QUOTA
448 +
449 +struct ipt_quota_info {
450 +        u_int64_t quota;
451 +};
452 +
453 +#endif /*_IPT_QUOTA_H*/
454 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_string.h
455 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_string.h   1970-01-01 01:00:00.000000000 +0100
456 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_string.h       2004-06-29 12:36:14.589167096 +0200
457 @@ -0,0 +1,21 @@
458 +#ifndef _IPT_STRING_H
459 +#define _IPT_STRING_H
460 +
461 +/* *** PERFORMANCE TWEAK ***
462 + * Packet size and search string threshold,
463 + * above which sublinear searches is used. */
464 +#define IPT_STRING_HAYSTACK_THRESH     100
465 +#define IPT_STRING_NEEDLE_THRESH       20
466 +
467 +#define BM_MAX_NLEN 256
468 +#define BM_MAX_HLEN 1024
469 +
470 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
471 +
472 +struct ipt_string_info {
473 +    char string[BM_MAX_NLEN];
474 +    u_int16_t invert;
475 +    u_int16_t len;
476 +};
477 +
478 +#endif /* _IPT_STRING_H */
479 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h
480 --- linux-2.6.7.org/include/linux/netfilter_ipv4/ipt_time.h     1970-01-01 01:00:00.000000000 +0100
481 +++ linux-2.6.7/include/linux/netfilter_ipv4/ipt_time.h 2004-06-29 12:32:41.025633688 +0200
482 @@ -0,0 +1,15 @@
483 +#ifndef __ipt_time_h_included__
484 +#define __ipt_time_h_included__
485 +
486 +
487 +struct ipt_time_info {
488 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
489 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
490 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
491 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
492 +       time_t    date_start;
493 +       time_t    date_stop;
494 +};
495 +
496 +
497 +#endif /* __ipt_time_h_included__ */
498 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h
499 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_HL.h      1970-01-01 01:00:00.000000000 +0100
500 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_HL.h  2004-06-29 12:31:59.776904448 +0200
501 @@ -0,0 +1,22 @@
502 +/* Hop Limit modification module for ip6tables
503 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
504 + * Based on HW's TTL module */
505 +
506 +#ifndef _IP6T_HL_H
507 +#define _IP6T_HL_H
508 +
509 +enum {
510 +       IP6T_HL_SET = 0,
511 +       IP6T_HL_INC,
512 +       IP6T_HL_DEC
513 +};
514 +
515 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
516 +
517 +struct ip6t_HL_info {
518 +       u_int8_t        mode;
519 +       u_int8_t        hop_limit;
520 +};
521 +
522 +
523 +#endif
524 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h
525 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h   1970-01-01 01:00:00.000000000 +0100
526 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_ROUTE.h       2004-06-29 12:34:33.509533536 +0200
527 @@ -0,0 +1,22 @@
528 +/* Header file for iptables ip6t_ROUTE target
529 + *
530 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
531 + *
532 + * This software is distributed under GNU GPL v2, 1991
533 + */
534 +#ifndef _IPT_ROUTE_H_target
535 +#define _IPT_ROUTE_H_target
536 +
537 +#define IP6T_ROUTE_IFNAMSIZ 16
538 +
539 +struct ip6t_route_target_info {
540 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
541 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
542 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
543 +       u_int8_t  flags;
544 +};
545 +
546 +/* Values for "flags" field */
547 +#define IP6T_ROUTE_CONTINUE        0x01
548 +
549 +#endif /*_IP6T_ROUTE_H_target*/
550 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h
551 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h   1970-01-01 01:00:00.000000000 +0100
552 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_fuzzy.h       2004-06-29 12:32:08.820529608 +0200
553 @@ -0,0 +1,21 @@
554 +#ifndef _IP6T_FUZZY_H
555 +#define _IP6T_FUZZY_H
556 +
557 +#include <linux/param.h>
558 +#include <linux/types.h>
559 +
560 +#define MAXFUZZYRATE 10000000
561 +#define MINFUZZYRATE 3
562 +
563 +struct ip6t_fuzzy_info {
564 +       u_int32_t minimum_rate;
565 +       u_int32_t maximum_rate;
566 +       u_int32_t packets_total;
567 +       u_int32_t bytes_total;
568 +       u_int32_t previous_time;
569 +       u_int32_t present_time;
570 +       u_int32_t mean_rate;
571 +       u_int8_t acceptance_rate;
572 +};
573 +
574 +#endif /*_IP6T_FUZZY_H*/
575 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h
576 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_nth.h     1970-01-01 01:00:00.000000000 +0100
577 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_nth.h 2004-06-29 12:32:16.699331848 +0200
578 @@ -0,0 +1,19 @@
579 +#ifndef _IP6T_NTH_H
580 +#define _IP6T_NTH_H
581 +
582 +#include <linux/param.h>
583 +#include <linux/types.h>
584 +
585 +#ifndef IP6T_NTH_NUM_COUNTERS
586 +#define IP6T_NTH_NUM_COUNTERS 16
587 +#endif
588 +
589 +struct ip6t_nth_info {
590 +       u_int8_t every;
591 +       u_int8_t not;
592 +       u_int8_t startat;
593 +       u_int8_t counter;
594 +       u_int8_t packet;
595 +};
596 +
597 +#endif /*_IP6T_NTH_H*/
598 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_owner.h
599 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_owner.h   2004-06-16 07:19:37.000000000 +0200
600 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_owner.h       2004-06-29 12:35:37.769764496 +0200
601 @@ -6,12 +6,14 @@
602  #define IP6T_OWNER_GID 0x02
603  #define IP6T_OWNER_PID 0x04
604  #define IP6T_OWNER_SID 0x08
605 +#define IP6T_OWNER_COMM 0x10
606  
607  struct ip6t_owner_info {
608      uid_t uid;
609      gid_t gid;
610      pid_t pid;
611      pid_t sid;
612 +    char comm[16];
613      u_int8_t match, invert;    /* flags */
614  };
615  
616 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_policy.h linux-2.6.7/include/linux/netfilter_ipv6/ip6t_policy.h
617 --- linux-2.6.7.org/include/linux/netfilter_ipv6/ip6t_policy.h  1970-01-01 01:00:00.000000000 +0100
618 +++ linux-2.6.7/include/linux/netfilter_ipv6/ip6t_policy.h      2004-06-29 12:35:40.046418392 +0200
619 @@ -0,0 +1,52 @@
620 +#ifndef _IP6T_POLICY_H
621 +#define _IP6T_POLICY_H
622 +
623 +#define POLICY_MAX_ELEM        4
624 +
625 +enum ip6t_policy_flags
626 +{
627 +       POLICY_MATCH_IN         = 0x1,
628 +       POLICY_MATCH_OUT        = 0x2,
629 +       POLICY_MATCH_NONE       = 0x4,
630 +       POLICY_MATCH_STRICT     = 0x8,
631 +};
632 +
633 +enum ip6t_policy_modes
634 +{
635 +       POLICY_MODE_TRANSPORT,
636 +       POLICY_MODE_TUNNEL
637 +};
638 +
639 +struct ip6t_policy_spec
640 +{
641 +       u_int8_t        saddr:1,
642 +                       daddr:1,
643 +                       proto:1,
644 +                       mode:1,
645 +                       spi:1,
646 +                       reqid:1;
647 +};
648 +
649 +struct ip6t_policy_elem
650 +{
651 +       struct in6_addr saddr;
652 +       struct in6_addr smask;
653 +       struct in6_addr daddr;
654 +       struct in6_addr dmask;
655 +       u_int32_t       spi;
656 +       u_int32_t       reqid;
657 +       u_int8_t        proto;
658 +       u_int8_t        mode;
659 +
660 +       struct ip6t_policy_spec match;
661 +       struct ip6t_policy_spec invert;
662 +};
663 +
664 +struct ip6t_policy_info
665 +{
666 +       struct ip6t_policy_elem pol[POLICY_MAX_ELEM];
667 +       u_int16_t flags;
668 +       u_int16_t len;
669 +};
670 +
671 +#endif /* _IP6T_POLICY_H */
672 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/linux/sysctl.h linux-2.6.7/include/linux/sysctl.h
673 --- linux-2.6.7.org/include/linux/sysctl.h      2004-06-29 12:24:13.353811536 +0200
674 +++ linux-2.6.7/include/linux/sysctl.h  2004-06-29 12:32:11.293153712 +0200
675 @@ -424,6 +424,7 @@
676         NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_SENT=24,
677         NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
678         NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
679 +       NET_IPV4_NF_CONNTRACK_COUNT=27,
680  };
681   
682  /* /proc/sys/net/ipv6 */
683 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/tcp.h linux-2.6.7/include/net/tcp.h
684 --- linux-2.6.7.org/include/net/tcp.h   2004-06-29 12:24:13.429799984 +0200
685 +++ linux-2.6.7/include/net/tcp.h       2004-06-29 12:35:34.488263360 +0200
686 @@ -163,6 +163,7 @@
687  extern void tcp_bucket_unlock(struct sock *sk);
688  extern int tcp_port_rover;
689  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
690 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
691  
692  /* These are AF independent. */
693  static __inline__ int tcp_bhashfn(__u16 lport)
694 diff -Nur --exclude '*.orig' linux-2.6.7.org/include/net/udp.h linux-2.6.7/include/net/udp.h
695 --- linux-2.6.7.org/include/net/udp.h   2004-06-16 07:19:51.000000000 +0200
696 +++ linux-2.6.7/include/net/udp.h       2004-06-29 12:35:34.490263056 +0200
697 @@ -74,6 +74,8 @@
698  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
699  extern int     udp_disconnect(struct sock *sk, int flags);
700  
701 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
702 +
703  DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
704  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
705  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
706 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Kconfig linux-2.6.7/net/ipv4/netfilter/Kconfig
707 --- linux-2.6.7.org/net/ipv4/netfilter/Kconfig  2004-06-29 12:24:13.000000000 +0200
708 +++ linux-2.6.7/net/ipv4/netfilter/Kconfig      2004-06-29 12:36:14.610163904 +0200
709 @@ -206,6 +206,11 @@
710  
711           To compile it as a module, choose M here.  If unsure, say N.
712  
713 +config IP_NF_MATCH_UNCLEAN
714 +       tristate  'unclean match support (EXPERIMENTAL)'
715 +       depends on EXPERIMENTAL && IP_NF_IPTABLES
716 +         help
717 +
718  config IP_NF_MATCH_TTL
719         tristate "TTL match support"
720         depends on IP_NF_IPTABLES
721 @@ -627,5 +632,246 @@
722           If you want to compile it as a module, say M here and read
723           Documentation/modules.txt.  If unsure, say `N'.
724  
725 +config IP_NF_TARGET_IPV4OPTSSTRIP
726 +       tristate  'IPV4OPTSSTRIP target support'
727 +       depends on IP_NF_MANGLE
728 +       help
729 +         This option adds an IPV4OPTSSTRIP target.
730 +         This target allows you to strip all IP options in a packet.
731 +        
732 +         If you want to compile it as a module, say M here and read
733 +         Documentation/modules.txt.  If unsure, say `N'.
734 +
735 +config IP_NF_TARGET_TTL
736 +       tristate  'TTL target support'
737 +       depends on IP_NF_MANGLE
738 +       help
739 +         This option adds a `TTL' target, which enables the user to set
740 +         the TTL value or increment / decrement the TTL value by a given
741 +         amount.
742 +       
743 +         If you want to compile it as a module, say M here and read
744 +         Documentation/modules.txt.  If unsure, say `N'.
745 +
746 +config IP_NF_MATCH_CONNLIMIT
747 +       tristate  'Connections/IP limit match support'
748 +       depends on IP_NF_IPTABLES
749 +       help
750 +         This match allows you to restrict the number of parallel TCP
751 +         connections to a server per client IP address (or address block).
752 +       
753 +         If you want to compile it as a module, say M here and read
754 +         Documentation/modules.txt.  If unsure, say `N'.
755 +
756 +config IP_NF_MATCH_DSTLIMIT
757 +       tristate  'dstlimit match support'
758 +       depends on IP_NF_IPTABLES
759 +
760 +config IP_NF_MATCH_FUZZY
761 +       tristate  'fuzzy match support'
762 +       depends on IP_NF_IPTABLES
763 +       help
764 +         This option adds a `fuzzy' match, which allows you to match
765 +         packets according to a fuzzy logic based law.
766 +       
767 +         If you want to compile it as a module, say M here and read
768 +         Documentation/modules.txt.  If unsure, say `N'.
769 +
770 +config IP_NF_MATCH_IPV4OPTIONS
771 +       tristate  'IPV4OPTIONS match support'
772 +       depends on IP_NF_IPTABLES
773 +       help
774 +         This option adds a IPV4OPTIONS match.
775 +         It allows you to filter options like source routing,
776 +         record route, timestamp and router-altert.
777 +       
778 +         If you say Y here, try iptables -m ipv4options --help for more information.
779 +        
780 +         If you want to compile it as a module, say M here and read
781 +         Documentation/modules.txt.  If unsure, say `N'.
782 +
783 +config IP_NF_MATCH_MPORT
784 +       tristate  'Multiple port with ranges match support'
785 +       depends on IP_NF_IPTABLES
786 +       help
787 +         This is an enhanced multiport match which supports port
788 +         ranges as well as single ports.
789 +       
790 +         If you want to compile it as a module, say M here and read
791 +         Documentation/modules.txt.  If unsure, say `N'.
792 +
793 +config IP_NF_MATCH_NTH
794 +       tristate  'Nth match support'
795 +       depends on IP_NF_IPTABLES
796 +       help
797 +         This option adds a `Nth' match, which allow you to make
798 +         rules that match every Nth packet.  By default there are 
799 +         16 different counters.
800 +       
801 +         [options]
802 +          --every     Nth              Match every Nth packet
803 +         [--counter]  num              Use counter 0-15 (default:0)
804 +         [--start]    num              Initialize the counter at the number 'num'
805 +                                       instead of 0. Must be between 0 and Nth-1
806 +         [--packet]   num              Match on 'num' packet. Must be between 0
807 +                                       and Nth-1.
808 +       
809 +                                       If --packet is used for a counter than
810 +                                       there must be Nth number of --packet
811 +                                       rules, covering all values between 0 and
812 +                                       Nth-1 inclusively.
813 +        
814 +         If you want to compile it as a module, say M here and read
815 +         Documentation/modules.txt.  If unsure, say `N'.
816 +
817 +config IP_NF_MATCH_PSD
818 +       tristate  'psd match support'
819 +       depends on IP_NF_IPTABLES
820 +       help
821 +         This option adds a `psd' match, which allows you to create rules in
822 +         any iptables table wich will detect TCP and UDP port scans.
823 +        
824 +         If you want to compile it as a module, say M here and read
825 +         Documentation/modules.txt.  If unsure, say `N'.
826 +
827 +config IP_NF_MATCH_QUOTA
828 +       tristate  'quota match support'
829 +       depends on IP_NF_IPTABLES
830 +       help
831 +         This match implements network quotas.
832 +       
833 +         If you want to compile it as a module, say M here and read
834 +         Documentation/modules.txt.  If unsure, say `N'.
835 +       
836 +
837 +config IP_NF_MATCH_SCTP
838 +       tristate  'SCTP protocol match support'
839 +       depends on IP_NF_IPTABLES
840 +
841 +config IP_NF_MATCH_TIME
842 +       tristate  'TIME match support'
843 +       depends on IP_NF_IPTABLES
844 +       help
845 +         This option adds a `time' match, which allows you
846 +         to match based on the packet arrival time/date
847 +         (arrival time/date at the machine which netfilter is running on) or
848 +         departure time/date (for locally generated packets).
849 +       
850 +         If you say Y here, try iptables -m time --help for more information.
851 +        
852 +         If you want to compile it as a module, say M here and read
853 +         Documentation/modules.txt.  If unsure, say `N'.
854 +
855 +config IP_NF_CONNTRACK_MARK
856 +       bool  'Connection mark tracking support'
857 +       help
858 +         This option enables support for connection marks, used by the
859 +         `CONNMARK' target and `connmark' match. Similar to the mark value
860 +         of packets, but this mark value is kept in the conntrack session
861 +         instead of the individual packets.
862 +       
863 +config IP_NF_TARGET_CONNMARK
864 +       tristate  'CONNMARK target support'
865 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_MANGLE
866 +       help
867 +         This option adds a `CONNMARK' target, which allows one to manipulate
868 +         the connection mark value.  Similar to the MARK target, but
869 +         affects the connection mark value rather than the packet mark value.
870 +       
871 +         If you want to compile it as a module, say M here and read
872 +         Documentation/modules.txt.  The module will be called
873 +         ipt_CONNMARK.o.  If unsure, say `N'.
874 +       
875 +config IP_NF_MATCH_CONNMARK
876 +       tristate  ' Connection mark match support'
877 +       depends on IP_NF_CONNTRACK_MARK && IP_NF_IPTABLES
878 +       help
879 +         This option adds a `connmark' match, which allows you to match the
880 +         connection mark value previously set for the session by `CONNMARK'. 
881 +       
882 +         If you want to compile it as a module, say M here and read
883 +         Documentation/modules.txt.  The module will be called
884 +         ipt_connmark.o.  If unsure, say `N'.
885 +
886 +config IP_NF_TARGET_IPMARK
887 +       tristate  'IPMARK target support'
888 +       depends on IP_NF_MANGLE
889 +       help
890 +         This option adds a `IPMARK' target, which allows you to create rules
891 +         in the `mangle' table which alter the netfilter mark (nfmark) field
892 +         basing on the source or destination ip address of the packet.
893 +         This is very useful for very fast massive mangling and marking.
894 +       
895 +         If you want to compile it as a module, say M here and read
896 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
897 +
898 +config IP_NF_TARGET_ROUTE
899 +       tristate  'ROUTE target support'
900 +       depends on IP_NF_MANGLE
901 +       help
902 +         This option adds a `ROUTE' target, which enables you to setup unusual
903 +         routes. For example, the ROUTE lets you route a received packet through 
904 +         an interface or towards a host, even if the regular destination of the 
905 +         packet is the router itself. The ROUTE target is also able to change the 
906 +         incoming interface of a packet.
907 +       
908 +         The target can be or not a final target. It has to be used inside the 
909 +         mangle table.
910 +         
911 +         If you want to compile it as a module, say M here and read
912 +         Documentation/modules.txt.  The module will be called ipt_ROUTE.o.
913 +         If unsure, say `N'.
914 +
915 +config IP_NF_TARGET_TARPIT
916 +       tristate 'TARPIT target support'
917 +       depends on IP_NF_FILTER
918 +       help
919 +         Adds a TARPIT target to iptables, which captures and holds
920 +         incoming TCP connections using no local per-connection resources.
921 +         Connections are accepted, but immediately switched to the persist
922 +         state (0 byte window), in which the remote side stops sending data
923 +         and asks to continue every 60-240 seconds.  Attempts to close the
924 +         connection are ignored, forcing the remote side to time out the
925 +         connection in 12-24 minutes.
926 +       
927 +         This offers similar functionality to LaBrea
928 +         <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
929 +         hardware or IPs.  Any TCP port that you would normally DROP or REJECT
930 +         can instead become a tarpit.
931 +
932 +config IP_NF_TARGET_XOR
933 +       tristate  'XOR target support'
934 +       depends on IP_NF_MANGLE
935 +       help
936 +         This option adds a `XOR' target, which can encrypt TCP and 
937 +         UDP traffic using a simple XOR encryption.
938 +       
939 +         If you want to compile it as a module, say M here and read
940 +         Documentation/modules.txt.  If unsure, say `N'.
941 +
942 +config IP_NF_MATCH_POLICY
943 +       tristate "IPsec policy match support"
944 +       depends on IP_NF_IPTABLES && XFRM
945 +       help
946 +         Policy matching allows you to match packets based on the
947 +         IPsec policy that was used during decapsulation/will
948 +         be used during encapsulation.
949 +
950 +         To compile it as a module, choose M here.  If unsure, say N.
951 +
952 +config IP_NF_CT_PROTO_SCTP
953 +       tristate  'SCTP protocol connection tracking support'
954 +       depends on IP_NF_CONNTRACK
955 +
956 +config IP_NF_MATCH_STRING
957 +       tristate  'String match support'
958 +       depends on IP_NF_IPTABLES
959 +       help
960 +         String matching alows you to match packets which contain a
961 +         specified string of characters.
962 +       
963 +         If you want to compile it as a module, say M here and read
964 +         Documentation/modules.txt.  If unsure, say `N'.
965 +
966  endmenu
967  
968 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/Makefile linux-2.6.7/net/ipv4/netfilter/Makefile
969 --- linux-2.6.7.org/net/ipv4/netfilter/Makefile 2004-06-29 12:24:13.000000000 +0200
970 +++ linux-2.6.7/net/ipv4/netfilter/Makefile     2004-06-29 12:36:14.615163144 +0200
971 @@ -47,14 +47,22 @@
972  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
973  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
974  obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
975 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
976 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
977  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
978  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
979  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
980  
981  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
982  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
983 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
984  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
985  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
986 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
987 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
988 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
989 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
990 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
991  
992  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
993  
994 @@ -64,28 +72,40 @@
995  
996  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
997  
998 +obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
999 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
1000  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1001  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1002 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
1003 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1004  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1005  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1006  obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1007  obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
1008  
1009  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1010 +obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
1011  
1012  # targets
1013  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
1014 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
1015  obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
1016  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
1017  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
1018  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
1019 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
1020  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
1021  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
1022 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
1023  obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
1024  obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
1025  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1026  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1027  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1028 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
1029 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
1030 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1031 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1032  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1033  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1034  obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
1035 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c
1036 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_core.c      2004-06-29 12:24:13.000000000 +0200
1037 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_core.c  2004-06-29 12:34:21.572348264 +0200
1038 @@ -718,6 +719,9 @@
1039                 __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
1040                 conntrack->master = expected;
1041                 expected->sibling = conntrack;
1042 +#if CONFIG_IP_NF_CONNTRACK_MARK
1043 +               conntrack->mark = expected->expectant->mark;
1044 +#endif
1045                 LIST_DELETE(&ip_conntrack_expect_list, expected);
1046                 expected->expectant->expecting--;
1047                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
1048 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c
1049 --- linux-2.6.7.org/net/ipv4/netfilter/ip_conntrack_standalone.c        2004-06-29 12:24:13.000000000 +0200
1050 +++ linux-2.6.7/net/ipv4/netfilter/ip_conntrack_standalone.c    2004-06-29 12:34:21.566349176 +0200
1051 @@ -169,7 +169,15 @@
1052                 if (seq_printf(s, "[ASSURED] "))
1053                         return 1;
1054  
1055 -       if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
1056 +       if (seq_printf(s, "use=%u ", atomic_read(&conntrack->ct_general.use)))
1057 +               return 1;
1058 +
1059 +#ifdef CONFIG_IP_NF_CONNTRACK_MARK
1060 +       if (seq_printf(s, "mark=%ld ", conntrack->mark))
1061 +               return 1;
1062 +#endif
1063 +
1064 +       if (seq_printf(s, "\n"))
1065                 return 1;
1066  
1067         return 0;
1068 @@ -494,6 +502,7 @@
1069  
1070  /* From ip_conntrack_core.c */
1071  extern int ip_conntrack_max;
1072 +extern atomic_t ip_conntrack_count;
1073  extern unsigned int ip_conntrack_htable_size;
1074  
1075  /* From ip_conntrack_proto_tcp.c */
1076 @@ -537,6 +546,14 @@
1077                 .proc_handler   = &proc_dointvec,
1078         },
1079         {
1080 +               .ctl_name       = NET_IPV4_NF_CONNTRACK_COUNT,
1081 +               .procname       = "ip_conntrack_count",
1082 +               .data           = &ip_conntrack_count,
1083 +               .maxlen         = sizeof(int),
1084 +               .mode           = 0444,
1085 +               .proc_handler   = &proc_dointvec,
1086 +       },
1087 +       {
1088                 .ctl_name       = NET_IPV4_NF_CONNTRACK_BUCKETS,
1089                 .procname       = "ip_conntrack_buckets",
1090                 .data           = &ip_conntrack_htable_size,
1091 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_queue.c linux-2.6.7/net/ipv4/netfilter/ip_queue.c
1092 --- linux-2.6.7.org/net/ipv4/netfilter/ip_queue.c       2004-06-16 07:20:26.000000000 +0200
1093 +++ linux-2.6.7/net/ipv4/netfilter/ip_queue.c   2004-06-29 12:35:08.146267952 +0200
1094 @@ -421,6 +421,33 @@
1095  }
1096  
1097  static int
1098 +ipq_set_vwmark(struct ipq_vwmark_msg *vmsg, unsigned int len)
1099 +{
1100 +       struct ipq_queue_entry *entry;
1101 +
1102 +       if (vmsg->value > NF_MAX_VERDICT)
1103 +               return -EINVAL;
1104 +
1105 +       entry = ipq_find_dequeue_entry(id_cmp, vmsg->id);
1106 +       if (entry == NULL)
1107 +               return -ENOENT;
1108 +       else {
1109 +               int verdict = vmsg->value;
1110 +               
1111 +               if (vmsg->data_len && vmsg->data_len == len)
1112 +                       if (ipq_mangle_ipv4((ipq_verdict_msg_t *)vmsg, entry) < 0)
1113 +                               verdict = NF_DROP;
1114 +
1115 +               /* set mark of associated skb */
1116 +               entry->skb->nfmark = vmsg->nfmark;
1117 +               
1118 +               ipq_issue_verdict(entry, verdict);
1119 +               return 0;
1120 +       }
1121 +}
1122 +
1123 +
1124 +static int
1125  ipq_receive_peer(struct ipq_peer_msg *pmsg,
1126                   unsigned char type, unsigned int len)
1127  {
1128 @@ -442,6 +469,14 @@
1129                         status = ipq_set_verdict(&pmsg->msg.verdict,
1130                                                  len - sizeof(*pmsg));
1131                         break;
1132 +        case IPQM_VWMARK:
1133 +               if (pmsg->msg.verdict.value > NF_MAX_VERDICT)
1134 +                       status = -EINVAL;
1135 +               else
1136 +                       status = ipq_set_vwmark(&pmsg->msg.vwmark,
1137 +                                                len - sizeof(*pmsg));
1138 +                       break;
1139 +
1140         default:
1141                 status = -EINVAL;
1142         }
1143 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ip_tables.c linux-2.6.7/net/ipv4/netfilter/ip_tables.c
1144 --- linux-2.6.7.org/net/ipv4/netfilter/ip_tables.c      2004-06-29 12:24:13.000000000 +0200
1145 +++ linux-2.6.7/net/ipv4/netfilter/ip_tables.c  2004-06-29 12:35:27.076390136 +0200
1146 @@ -8,6 +8,10 @@
1147   * it under the terms of the GNU General Public License version 2 as
1148   * published by the Free Software Foundation.
1149   *
1150 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
1151 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
1152 + *     - mark_source_chains speedup for complex chains
1153 + *
1154   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
1155   *     - increase module usage count as soon as we have rules inside
1156   *       a table
1157 @@ -495,6 +499,9 @@
1158  {
1159         unsigned int hook;
1160  
1161 +       /* keep track of where we have been: */
1162 +       unsigned char *been = vmalloc(newinfo->size);
1163 +
1164         /* No recursion; use packet counter to save back ptrs (reset
1165            to 0 as we leave), and comefrom to save source hook bitmask */
1166         for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
1167 @@ -507,6 +514,7 @@
1168  
1169                 /* Set initial back pointer. */
1170                 e->counters.pcnt = pos;
1171 +               memset(been, 0, newinfo->size);
1172  
1173                 for (;;) {
1174                         struct ipt_standard_target *t
1175 @@ -515,6 +523,7 @@
1176                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
1177                                 printk("iptables: loop hook %u pos %u %08X.\n",
1178                                        hook, pos, e->comefrom);
1179 +                               vfree(been);
1180                                 return 0;
1181                         }
1182                         e->comefrom
1183 @@ -562,10 +571,14 @@
1184                         } else {
1185                                 int newpos = t->verdict;
1186  
1187 -                               if (strcmp(t->target.u.user.name,
1188 +                               if ( (pos < 0 || pos >= newinfo->size
1189 +                                     || !been[pos]) 
1190 +                                   && strcmp(t->target.u.user.name,
1191                                            IPT_STANDARD_TARGET) == 0
1192                                     && newpos >= 0) {
1193                                         /* This a jump; chase it. */
1194 +                                       if (pos >= 0 && pos < newinfo->size)
1195 +                                               been[pos]++;
1196                                         duprintf("Jump rule %u -> %u\n",
1197                                                  pos, newpos);
1198                                 } else {
1199 @@ -581,6 +594,7 @@
1200                 next:
1201                 duprintf("Finished chain %u\n", hook);
1202         }
1203 +       vfree(been);
1204         return 1;
1205  }
1206  
1207 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.6.7/net/ipv4/netfilter/ipt_CONNMARK.c
1208 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_CONNMARK.c   1970-01-01 01:00:00.000000000 +0100
1209 +++ linux-2.6.7/net/ipv4/netfilter/ipt_CONNMARK.c       2004-06-29 12:34:21.512357384 +0200
1210 @@ -0,0 +1,118 @@
1211 +/* This kernel module is used to modify the connection mark values, or
1212 + * to optionally restore the skb nfmark from the connection mark
1213 + *
1214 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
1215 + * by Henrik Nordstrom <hno@marasystems.com>
1216 + *
1217 + * This program is free software; you can redistribute it and/or modify
1218 + * it under the terms of the GNU General Public License as published by
1219 + * the Free Software Foundation; either version 2 of the License, or
1220 + * (at your option) any later version.
1221 + *
1222 + * This program is distributed in the hope that it will be useful,
1223 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1224 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1225 + * GNU General Public License for more details.
1226 + *
1227 + * You should have received a copy of the GNU General Public License
1228 + * along with this program; if not, write to the Free Software
1229 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1230 + */
1231 +#include <linux/module.h>
1232 +#include <linux/skbuff.h>
1233 +#include <linux/ip.h>
1234 +#include <net/checksum.h>
1235 +
1236 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
1237 +MODULE_DESCRIPTION("IP tables CONNMARK matching module");
1238 +MODULE_LICENSE("GPL");
1239 +
1240 +#include <linux/netfilter_ipv4/ip_tables.h>
1241 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
1242 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1243 +
1244 +static unsigned int
1245 +target(struct sk_buff **pskb,
1246 +       const struct net_device *in,
1247 +       const struct net_device *out,
1248 +       unsigned int hooknum,
1249 +       const void *targinfo,
1250 +       void *userinfo)
1251 +{
1252 +       const struct ipt_connmark_target_info *markinfo = targinfo;
1253 +       unsigned long diff;
1254 +       unsigned long nfmark;
1255 +       unsigned long newmark;
1256 +
1257 +       enum ip_conntrack_info ctinfo;
1258 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
1259 +       if (ct) {
1260 +           switch(markinfo->mode) {
1261 +           case IPT_CONNMARK_SET:
1262 +               newmark = (ct->mark & ~markinfo->mask) | markinfo->mark;
1263 +               if (newmark != ct->mark)
1264 +                   ct->mark = newmark;
1265 +               break;
1266 +           case IPT_CONNMARK_SAVE:
1267 +               newmark = (ct->mark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask);
1268 +               if (ct->mark != newmark)
1269 +                   ct->mark = newmark;
1270 +               break;
1271 +           case IPT_CONNMARK_RESTORE:
1272 +               nfmark = (*pskb)->nfmark;
1273 +               diff = (ct->mark ^ nfmark & markinfo->mask);
1274 +               if (diff != 0) {
1275 +                   (*pskb)->nfmark = nfmark ^ diff;
1276 +                   (*pskb)->nfcache |= NFC_ALTERED;
1277 +               }
1278 +               break;
1279 +           }
1280 +       }
1281 +
1282 +       return IPT_CONTINUE;
1283 +}
1284 +
1285 +static int
1286 +checkentry(const char *tablename,
1287 +          const struct ipt_entry *e,
1288 +          void *targinfo,
1289 +          unsigned int targinfosize,
1290 +          unsigned int hook_mask)
1291 +{
1292 +       struct ipt_connmark_target_info *matchinfo = targinfo;
1293 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
1294 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
1295 +                      targinfosize,
1296 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
1297 +               return 0;
1298 +       }
1299 +
1300 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
1301 +           if (strcmp(tablename, "mangle") != 0) {
1302 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1303 +                   return 0;
1304 +           }
1305 +       }
1306 +
1307 +       return 1;
1308 +}
1309 +
1310 +static struct ipt_target ipt_connmark_reg = {
1311 +       .name = "CONNMARK",
1312 +       .target = &target,
1313 +       .checkentry = &checkentry,
1314 +       .me = THIS_MODULE
1315 +};
1316 +
1317 +static int __init init(void)
1318 +{
1319 +       return ipt_register_target(&ipt_connmark_reg);
1320 +}
1321 +
1322 +static void __exit fini(void)
1323 +{
1324 +       ipt_unregister_target(&ipt_connmark_reg);
1325 +}
1326 +
1327 +module_init(init);
1328 +module_exit(fini);
1329 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.6.7/net/ipv4/netfilter/ipt_IPMARK.c
1330 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPMARK.c     1970-01-01 01:00:00.000000000 +0100
1331 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPMARK.c 2004-06-29 12:34:27.609430488 +0200
1332 @@ -0,0 +1,81 @@
1333 +/* This is a module which is used for setting the NFMARK field of an skb. */
1334 +#include <linux/module.h>
1335 +#include <linux/skbuff.h>
1336 +#include <linux/ip.h>
1337 +#include <net/checksum.h>
1338 +
1339 +#include <linux/netfilter_ipv4/ip_tables.h>
1340 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
1341 +
1342 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
1343 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
1344 +MODULE_LICENSE("GPL");
1345 +
1346 +static unsigned int
1347 +target(struct sk_buff **pskb,
1348 +       const struct net_device *in,
1349 +       const struct net_device *out,
1350 +       unsigned int hooknum,
1351 +       const void *targinfo,
1352 +       void *userinfo)
1353 +{
1354 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
1355 +       struct iphdr *iph = (*pskb)->nh.iph;
1356 +       unsigned long mark;
1357 +
1358 +       if (ipmarkinfo->addr == IPT_IPMARK_SRC)
1359 +               mark = (unsigned long) ntohl(iph->saddr);
1360 +       else
1361 +               mark = (unsigned long) ntohl(iph->daddr);
1362 +
1363 +       mark &= ipmarkinfo->andmask;
1364 +       mark |= ipmarkinfo->ormask;
1365 +       
1366 +       if ((*pskb)->nfmark != mark) {
1367 +               (*pskb)->nfmark = mark;
1368 +               (*pskb)->nfcache |= NFC_ALTERED;
1369 +       }
1370 +       return IPT_CONTINUE;
1371 +}
1372 +
1373 +static int
1374 +checkentry(const char *tablename,
1375 +          const struct ipt_entry *e,
1376 +           void *targinfo,
1377 +           unsigned int targinfosize,
1378 +           unsigned int hook_mask)
1379 +{
1380 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
1381 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
1382 +                      targinfosize,
1383 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
1384 +               return 0;
1385 +       }
1386 +
1387 +       if (strcmp(tablename, "mangle") != 0) {
1388 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1389 +               return 0;
1390 +       }
1391 +
1392 +       return 1;
1393 +}
1394 +
1395 +static struct ipt_target ipt_ipmark_reg = { 
1396 +       .name = "IPMARK",
1397 +       .target = target,
1398 +       .checkentry = checkentry,
1399 +       .me = THIS_MODULE
1400 +};
1401 +
1402 +static int __init init(void)
1403 +{
1404 +       return ipt_register_target(&ipt_ipmark_reg);
1405 +}
1406 +
1407 +static void __exit fini(void)
1408 +{
1409 +       ipt_unregister_target(&ipt_ipmark_reg);
1410 +}
1411 +
1412 +module_init(init);
1413 +module_exit(fini);
1414 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
1415 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      1970-01-01 01:00:00.000000000 +0100
1416 +++ linux-2.6.7/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  2004-06-29 12:32:01.665617320 +0200
1417 @@ -0,0 +1,89 @@
1418 +/**
1419 + * Strip all IP options in the IP packet header.
1420 + *
1421 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
1422 + * This software is distributed under GNU GPL v2, 1991
1423 + */
1424 +
1425 +#include <linux/module.h>
1426 +#include <linux/skbuff.h>
1427 +#include <net/ip.h>
1428 +#include <net/checksum.h>
1429 +
1430 +#include <linux/netfilter_ipv4/ip_tables.h>
1431 +
1432 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
1433 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
1434 +MODULE_LICENSE("GPL");
1435 +
1436 +static unsigned int
1437 +target(struct sk_buff **pskb,
1438 +       const struct net_device *in,
1439 +       const struct net_device *out,
1440 +       unsigned int hooknum,
1441 +       const void *targinfo,
1442 +       void *userinfo)
1443 +{
1444 +       struct iphdr *iph;
1445 +       struct sk_buff *skb;
1446 +       struct ip_options *opt;
1447 +       unsigned char *optiph;
1448 +       int l;
1449 +       
1450 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
1451 +               return NF_DROP;
1452
1453 +       skb = (*pskb);
1454 +       iph = (*pskb)->nh.iph;
1455 +       optiph = skb->nh.raw;
1456 +       l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
1457 +
1458 +       /* if no options in packet then nothing to clear. */
1459 +       if (iph->ihl * 4 == sizeof(struct iphdr))
1460 +               return IPT_CONTINUE;
1461 +
1462 +       /* else clear all options */
1463 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
1464 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
1465 +       opt = &(IPCB(skb)->opt);
1466 +       opt->is_data = 0;
1467 +       opt->optlen = l;
1468 +
1469 +       skb->nfcache |= NFC_ALTERED;
1470 +
1471 +        return IPT_CONTINUE;
1472 +}
1473 +
1474 +static int
1475 +checkentry(const char *tablename,
1476 +          const struct ipt_entry *e,
1477 +           void *targinfo,
1478 +           unsigned int targinfosize,
1479 +           unsigned int hook_mask)
1480 +{
1481 +       if (strcmp(tablename, "mangle")) {
1482 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1483 +               return 0;
1484 +       }
1485 +       /* nothing else to check because no parameters */
1486 +       return 1;
1487 +}
1488 +
1489 +static struct ipt_target ipt_ipv4optsstrip_reg = { 
1490 +       .name = "IPV4OPTSSTRIP",
1491 +       .target = target,
1492 +       .checkentry = checkentry,
1493 +       .me = THIS_MODULE };
1494 +
1495 +static int __init init(void)
1496 +{
1497 +       return ipt_register_target(&ipt_ipv4optsstrip_reg);
1498 +}
1499 +
1500 +static void __exit fini(void)
1501 +{
1502 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
1503 +}
1504 +
1505 +module_init(init);
1506 +module_exit(fini);
1507 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.6.7/net/ipv4/netfilter/ipt_ROUTE.c
1508 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ROUTE.c      1970-01-01 01:00:00.000000000 +0100
1509 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ROUTE.c  2004-06-29 12:34:33.511533232 +0200
1510 @@ -0,0 +1,393 @@
1511 +/*
1512 + * This implements the ROUTE target, which enables you to setup unusual
1513 + * routes not supported by the standard kernel routing table.
1514 + *
1515 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
1516 + *
1517 + * v 1.9 2004/05/14
1518 + *
1519 + * This software is distributed under GNU GPL v2, 1991
1520 + */
1521 +
1522 +#include <linux/module.h>
1523 +#include <linux/skbuff.h>
1524 +#include <linux/ip.h>
1525 +#include <linux/netfilter_ipv4/ip_tables.h>
1526 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
1527 +#include <linux/netdevice.h>
1528 +#include <linux/route.h>
1529 +#include <net/ip.h>
1530 +#include <net/route.h>
1531 +#include <net/icmp.h>
1532 +#include <net/checksum.h>
1533 +
1534 +#if 0
1535 +#define DEBUGP printk
1536 +#else
1537 +#define DEBUGP(format, args...)
1538 +#endif
1539 +
1540 +MODULE_LICENSE("GPL");
1541 +MODULE_AUTHOR("Cedric de Launois <delaunois@info.ucl.ac.be>");
1542 +MODULE_DESCRIPTION("iptables ROUTE target module");
1543 +
1544 +/* Try to route the packet according to the routing keys specified in
1545 + * route_info. Keys are :
1546 + *  - ifindex : 
1547 + *      0 if no oif preferred, 
1548 + *      otherwise set to the index of the desired oif
1549 + *  - route_info->gw :
1550 + *      0 if no gateway specified,
1551 + *      otherwise set to the next host to which the pkt must be routed
1552 + * If success, skb->dev is the output device to which the packet must 
1553 + * be sent and skb->dst is not NULL
1554 + *
1555 + * RETURN: -1 if an error occured
1556 + *          1 if the packet was succesfully routed to the 
1557 + *            destination desired
1558 + *          0 if the kernel routing table could not route the packet
1559 + *            according to the keys specified
1560 + */
1561 +static int route(struct sk_buff *skb,
1562 +                unsigned int ifindex,
1563 +                const struct ipt_route_target_info *route_info)
1564 +{
1565 +       int err;
1566 +       struct rtable *rt;
1567 +       struct iphdr *iph = skb->nh.iph;
1568 +       struct flowi fl = {
1569 +               .oif = ifindex,
1570 +               .nl_u = {
1571 +                       .ip4_u = {
1572 +                               .daddr = iph->daddr,
1573 +                               .saddr = 0,
1574 +                               .tos = RT_TOS(iph->tos),
1575 +                               .scope = RT_SCOPE_UNIVERSE,
1576 +                       }
1577 +               } 
1578 +       };
1579 +       
1580 +       /* The destination address may be overloaded by the target */
1581 +       if (route_info->gw)
1582 +               fl.fld_dst = route_info->gw;
1583 +       
1584 +       /* Trying to route the packet using the standard routing table. */
1585 +       if ((err = ip_route_output_key(&rt, &fl))) {
1586 +               if (net_ratelimit()) 
1587 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
1588 +               return -1;
1589 +       }
1590 +       
1591 +       /* Drop old route. */
1592 +       dst_release(skb->dst);
1593 +       skb->dst = NULL;
1594 +
1595 +       /* Success if no oif specified or if the oif correspond to the 
1596 +        * one desired */
1597 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
1598 +               skb->dst = &rt->u.dst;
1599 +               skb->dev = skb->dst->dev;
1600 +               return 1;
1601 +       }
1602 +       
1603 +       /* The interface selected by the routing table is not the one
1604 +        * specified by the user. This may happen because the dst address
1605 +        * is one of our own addresses.
1606 +        */
1607 +       if (net_ratelimit()) 
1608 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
1609 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
1610 +       
1611 +       return 0;
1612 +}
1613 +
1614 +
1615 +/* Stolen from ip_finish_output2
1616 + * PRE : skb->dev is set to the device we are leaving by
1617 + *       skb->dst is not NULL
1618 + * POST: the packet is sent with the link layer header pushed
1619 + *       the packet is destroyed
1620 + */
1621 +static void ip_direct_send(struct sk_buff *skb)
1622 +{
1623 +       struct dst_entry *dst = skb->dst;
1624 +       struct hh_cache *hh = dst->hh;
1625 +
1626 +       if (hh) {
1627 +               read_lock_bh(&hh->hh_lock);
1628 +               memcpy(skb->data - 16, hh->hh_data, 16);
1629 +               read_unlock_bh(&hh->hh_lock);
1630 +               skb_push(skb, hh->hh_len);
1631 +               hh->hh_output(skb);
1632 +       } else if (dst->neighbour)
1633 +               dst->neighbour->output(skb);
1634 +       else {
1635 +               if (net_ratelimit())
1636 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
1637 +               kfree_skb(skb);
1638 +       }
1639 +}
1640 +
1641 +
1642 +/* PRE : skb->dev is set to the device we are leaving by
1643 + * POST: - the packet is directly sent to the skb->dev device, without 
1644 + *         pushing the link layer header.
1645 + *       - the packet is destroyed
1646 + */
1647 +static inline int dev_direct_send(struct sk_buff *skb)
1648 +{
1649 +       return dev_queue_xmit(skb);
1650 +}
1651 +
1652 +
1653 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
1654 +                             struct sk_buff *skb) 
1655 +{
1656 +       unsigned int ifindex = 0;
1657 +       struct net_device *dev_out = NULL;
1658 +
1659 +       /* The user set the interface name to use.
1660 +        * Getting the current interface index.
1661 +        */
1662 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
1663 +               ifindex = dev_out->ifindex;
1664 +       } else {
1665 +               /* Unknown interface name : packet dropped */
1666 +               if (net_ratelimit()) 
1667 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
1668 +               return NF_DROP;
1669 +       }
1670 +
1671 +       /* Trying the standard way of routing packets */
1672 +       switch (route(skb, ifindex, route_info)) {
1673 +       case 1:
1674 +               dev_put(dev_out);
1675 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
1676 +                       return IPT_CONTINUE;
1677 +
1678 +               ip_direct_send(skb);
1679 +               return NF_STOLEN;
1680 +
1681 +       case 0:
1682 +               /* Failed to send to oif. Trying the hard way */
1683 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
1684 +                       return NF_DROP;
1685 +
1686 +               if (net_ratelimit()) 
1687 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
1688 +                              ifindex);
1689 +
1690 +               /* We have to force the use of an interface.
1691 +                * This interface must be a tunnel interface since
1692 +                * otherwise we can't guess the hw address for
1693 +                * the packet. For a tunnel interface, no hw address
1694 +                * is needed.
1695 +                */
1696 +               if ((dev_out->type != ARPHRD_TUNNEL)
1697 +                   && (dev_out->type != ARPHRD_IPGRE)) {
1698 +                       if (net_ratelimit()) 
1699 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
1700 +                       dev_put(dev_out);
1701 +                       return NF_DROP;
1702 +               }
1703 +       
1704 +               /* Send the packet. This will also free skb
1705 +                * Do not go through the POST_ROUTING hook because 
1706 +                * skb->dst is not set and because it will probably
1707 +                * get confused by the destination IP address.
1708 +                */
1709 +               skb->dev = dev_out;
1710 +               dev_direct_send(skb);
1711 +               dev_put(dev_out);
1712 +               return NF_STOLEN;
1713 +               
1714 +       default:
1715 +               /* Unexpected error */
1716 +               dev_put(dev_out);
1717 +               return NF_DROP;
1718 +       }
1719 +}
1720 +
1721 +
1722 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
1723 +                             struct sk_buff *skb) 
1724 +{
1725 +       struct net_device *dev_in = NULL;
1726 +
1727 +       /* Getting the current interface index. */
1728 +       if (!(dev_in = dev_get_by_name(route_info->iif))) {
1729 +               if (net_ratelimit()) 
1730 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->iif);
1731 +               return NF_DROP;
1732 +       }
1733 +
1734 +       skb->dev = dev_in;
1735 +       dst_release(skb->dst);
1736 +       skb->dst = NULL;
1737 +
1738 +       netif_rx(skb);
1739 +       dev_put(dev_in);
1740 +       return NF_STOLEN;
1741 +}
1742 +
1743 +
1744 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
1745 +                            struct sk_buff *skb) 
1746 +{
1747 +       if (route(skb, 0, route_info)!=1)
1748 +               return NF_DROP;
1749 +
1750 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
1751 +               return IPT_CONTINUE;
1752 +
1753 +       ip_direct_send(skb);
1754 +       return NF_STOLEN;
1755 +}
1756 +
1757 +
1758 +static unsigned int ipt_route_target(struct sk_buff **pskb,
1759 +                                    const struct net_device *in,
1760 +                                    const struct net_device *out,
1761 +                                    unsigned int hooknum,
1762 +                                    const void *targinfo,
1763 +                                    void *userinfo)
1764 +{
1765 +       const struct ipt_route_target_info *route_info = targinfo;
1766 +       struct sk_buff *skb = *pskb;
1767 +
1768 +       /* If we are at PREROUTING or INPUT hook
1769 +        * the TTL isn't decreased by the IP stack
1770 +        */
1771 +       if (hooknum == NF_IP_PRE_ROUTING ||
1772 +           hooknum == NF_IP_LOCAL_IN) {
1773 +
1774 +               struct iphdr *iph = skb->nh.iph;
1775 +
1776 +               if (iph->ttl <= 1) {
1777 +                       struct rtable *rt;
1778 +                       struct flowi fl = {
1779 +                               .oif = 0,
1780 +                               .nl_u = {
1781 +                                       .ip4_u = {
1782 +                                               .daddr = iph->daddr,
1783 +                                               .saddr = iph->saddr,
1784 +                                               .tos = RT_TOS(iph->tos),
1785 +                                               .scope = ((iph->tos & RTO_ONLINK) ?
1786 +                                                         RT_SCOPE_LINK :
1787 +                                                         RT_SCOPE_UNIVERSE)
1788 +                                       }
1789 +                               } 
1790 +                       };
1791 +
1792 +                       if (ip_route_output_key(&rt, &fl)) {
1793 +                               return NF_DROP;
1794 +                       }
1795 +
1796 +                       if (skb->dev == rt->u.dst.dev) {
1797 +                               /* Drop old route. */
1798 +                               dst_release(skb->dst);
1799 +                               skb->dst = &rt->u.dst;
1800 +
1801 +                               /* this will traverse normal stack, and 
1802 +                                * thus call conntrack on the icmp packet */
1803 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
1804 +                                         ICMP_EXC_TTL, 0);
1805 +                       }
1806 +
1807 +                       return NF_DROP;
1808 +               }
1809 +
1810 +               /*
1811 +                * If we are at INPUT the checksum must be recalculated since
1812 +                * the length could change as the result of a defragmentation.
1813 +                */
1814 +               if(hooknum == NF_IP_LOCAL_IN) {
1815 +                       iph->ttl = iph->ttl - 1;
1816 +                       iph->check = 0;
1817 +                       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
1818 +               } else {
1819 +                       ip_decrease_ttl(iph);
1820 +               }
1821 +       }
1822 +
1823 +       /* Tell conntrack to forget this packet since it may get confused 
1824 +        * when a packet is leaving with dst address == our address.
1825 +        * Good idea ? Dunno. Need advice.
1826 +        */
1827 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
1828 +               nf_conntrack_put(skb->nfct);
1829 +               skb->nfct = NULL;
1830 +               skb->nfcache = 0;
1831 +#ifdef CONFIG_NETFILTER_DEBUG
1832 +               skb->nf_debug = 0;
1833 +#endif
1834 +       }
1835 +
1836 +       if (route_info->oif[0] != '\0') 
1837 +               return route_oif(route_info, *pskb);
1838 +       
1839 +       if (route_info->iif[0] != '\0') 
1840 +               return route_iif(route_info, *pskb);
1841 +
1842 +       if (route_info->gw) 
1843 +               return route_gw(route_info, *pskb);
1844 +
1845 +       if (net_ratelimit()) 
1846 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
1847 +
1848 +       return IPT_CONTINUE;
1849 +}
1850 +
1851 +
1852 +static int ipt_route_checkentry(const char *tablename,
1853 +                               const struct ipt_entry *e,
1854 +                               void *targinfo,
1855 +                               unsigned int targinfosize,
1856 +                               unsigned int hook_mask)
1857 +{
1858 +       if (strcmp(tablename, "mangle") != 0) {
1859 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
1860 +                      tablename);
1861 +               return 0;
1862 +       }
1863 +
1864 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
1865 +                           | (1 << NF_IP_LOCAL_IN)
1866 +                           | (1 << NF_IP_FORWARD)
1867 +                           | (1 << NF_IP_LOCAL_OUT)
1868 +                           | (1 << NF_IP_POST_ROUTING))) {
1869 +               printk("ipt_ROUTE: bad hook\n");
1870 +               return 0;
1871 +       }
1872 +
1873 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
1874 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
1875 +                      targinfosize,
1876 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
1877 +               return 0;
1878 +       }
1879 +
1880 +       return 1;
1881 +}
1882 +
1883 +
1884 +static struct ipt_target ipt_route_reg = { 
1885 +       .name = "ROUTE",
1886 +       .target = ipt_route_target,
1887 +       .checkentry = ipt_route_checkentry,
1888 +       .me = THIS_MODULE,
1889 +};
1890 +
1891 +static int __init init(void)
1892 +{
1893 +       return ipt_register_target(&ipt_route_reg);
1894 +}
1895 +
1896 +
1897 +static void __exit fini(void)
1898 +{
1899 +       ipt_unregister_target(&ipt_route_reg);
1900 +}
1901 +
1902 +module_init(init);
1903 +module_exit(fini);
1904 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.6.7/net/ipv4/netfilter/ipt_TARPIT.c
1905 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TARPIT.c     1970-01-01 01:00:00.000000000 +0100
1906 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TARPIT.c 2004-06-29 12:34:39.109682184 +0200
1907 @@ -0,0 +1,290 @@
1908 +/* 
1909 + * Kernel module to capture and hold incoming TCP connections using 
1910 + * no local per-connection resources.
1911 + * 
1912 + * Based on ipt_REJECT.c and offering functionality similar to 
1913 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
1914 + * 
1915 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
1916 + * 
1917 + * This program is free software; you can redistribute it and/or modify
1918 + * it under the terms of the GNU General Public License as published by
1919 + * the Free Software Foundation; either version 2 of the License, or
1920 + * (at your option) any later version.
1921 + *
1922 + * This program is distributed in the hope that it will be useful,
1923 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1924 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1925 + * GNU General Public License for more details.
1926 + *
1927 + * You should have received a copy of the GNU General Public License
1928 + * along with this program; if not, write to the Free Software
1929 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1930 + * 
1931 + * Goal:
1932 + * - Allow incoming TCP connections to be established.
1933 + * - Passing data should result in the connection being switched to the 
1934 + *   persist state (0 byte window), in which the remote side stops sending 
1935 + *   data and asks to continue every 60 seconds.
1936 + * - Attempts to shut down the connection should be ignored completely, so 
1937 + *   the remote side ends up having to time it out.
1938 + *
1939 + * This means:
1940 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
1941 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
1942 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
1943 + */
1944 +
1945 +#include <linux/config.h>
1946 +#include <linux/module.h>
1947 +#include <linux/skbuff.h>
1948 +#include <linux/ip.h>
1949 +#include <net/ip.h>
1950 +#include <net/tcp.h>
1951 +#include <net/icmp.h>
1952 +struct in_device;
1953 +#include <net/route.h>
1954 +#include <linux/random.h>
1955 +#include <linux/netfilter_ipv4/ip_tables.h>
1956 +
1957 +#if 0
1958 +#define DEBUGP printk
1959 +#else
1960 +#define DEBUGP(format, args...)
1961 +#endif
1962 +
1963 +MODULE_LICENSE("GPL");
1964 +MODULE_AUTHOR("Aaron Hopkins <tools@die.net>");
1965 +
1966 +/* Stolen from ip_finish_output2 */
1967 +static int ip_direct_send(struct sk_buff *skb)
1968 +{
1969 +       struct dst_entry *dst = skb->dst;
1970 +       struct hh_cache *hh = dst->hh;
1971 +
1972 +       if (hh) {    
1973 +               read_lock_bh(&hh->hh_lock);
1974 +               memcpy(skb->data - 16, hh->hh_data, 16);
1975 +                read_unlock_bh(&hh->hh_lock);
1976 +                skb_push(skb, hh->hh_len);
1977 +                return hh->hh_output(skb);
1978 +        } else if (dst->neighbour)
1979 +                return dst->neighbour->output(skb);
1980 +
1981 +       if (net_ratelimit())
1982 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
1983 +        kfree_skb(skb);
1984 +        return -EINVAL;
1985 +}
1986 +
1987 +
1988 +/* Send reply */
1989 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
1990 +{
1991 +       struct sk_buff *nskb;
1992 +       struct rtable *nrt;
1993 +       struct tcphdr *otcph, *ntcph;
1994 +       struct flowi fl = {};
1995 +       unsigned int otcplen;
1996 +       u_int16_t tmp;
1997 +
1998 +       /* A truncated TCP header isn't going to be useful */
1999 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
2000 +               return;
2001 +
2002 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
2003 +                                  + oskb->nh.iph->ihl);
2004 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
2005 +
2006 +       /* No replies for RST or FIN */
2007 +       if (otcph->rst || otcph->fin)
2008 +               return;
2009 +
2010 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
2011 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
2012 +               return;
2013 +
2014 +       /* Check checksum. */
2015 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
2016 +                        oskb->nh.iph->daddr,
2017 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
2018 +               return;
2019 +
2020 +       /* Copy skb (even if skb is about to be dropped, we can't just
2021 +           clone it because there may be other things, such as tcpdump,
2022 +           interested in it) */
2023 +       nskb = skb_copy(oskb, GFP_ATOMIC);
2024 +       if (!nskb)
2025 +               return;
2026 +
2027 +       /* This packet will not be the same as the other: clear nf fields */
2028 +       nf_conntrack_put(nskb->nfct);
2029 +       nskb->nfct = NULL;
2030 +       nskb->nfcache = 0;
2031 +#ifdef CONFIG_NETFILTER_DEBUG
2032 +       nskb->nf_debug = 0;
2033 +#endif
2034 +
2035 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
2036 +
2037 +       /* Truncate to length (no data) */
2038 +       ntcph->doff = sizeof(struct tcphdr)/4;
2039 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
2040 +       nskb->nh.iph->tot_len = htons(nskb->len);
2041 +
2042 +       /* Swap source and dest */
2043 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
2044 +       tmp = ntcph->source;
2045 +       ntcph->source = ntcph->dest;
2046 +       ntcph->dest = tmp;
2047 +
2048 +       /* Use supplied sequence number or make a new one */
2049 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
2050 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
2051 +                                                       nskb->nh.iph->daddr, 
2052 +                                                       ntcph->source, 
2053 +                                                       ntcph->dest));
2054 +
2055 +       /* Our SYN-ACKs must have a >0 window */
2056 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
2057 +
2058 +       ntcph->urg_ptr = 0;
2059 +
2060 +       /* Reset flags */
2061 +       ((u_int8_t *)ntcph)[13] = 0;
2062 +
2063 +       if (otcph->syn && otcph->ack) {
2064 +               ntcph->rst = 1;
2065 +               ntcph->ack_seq = 0;
2066 +       } else {
2067 +               ntcph->syn = otcph->syn;
2068 +               ntcph->ack = 1;
2069 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
2070 +       }
2071 +
2072 +       /* Adjust TCP checksum */
2073 +       ntcph->check = 0;
2074 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
2075 +                                  nskb->nh.iph->saddr,
2076 +                                  nskb->nh.iph->daddr,
2077 +                                  csum_partial((char *)ntcph,
2078 +                                               sizeof(struct tcphdr), 0));
2079 +
2080 +       /* Adjust IP TTL */
2081 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
2082 +
2083 +       /* Set DF, id = 0 */
2084 +       nskb->nh.iph->frag_off = htons(IP_DF);
2085 +       nskb->nh.iph->id = 0;
2086 +
2087 +       /* Adjust IP checksum */
2088 +       nskb->nh.iph->check = 0;
2089 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
2090 +                                          nskb->nh.iph->ihl);
2091 +
2092 +       fl.nl_u.ip4_u.daddr = nskb->nh.iph->daddr;
2093 +       fl.nl_u.ip4_u.saddr = local ? nskb->nh.iph->saddr : 0;
2094 +       fl.nl_u.ip4_u.tos = RT_TOS(nskb->nh.iph->tos) | RTO_CONN;
2095 +       fl.oif = 0;
2096 +
2097 +       if (ip_route_output_key(&nrt, &fl))
2098 +               goto free_nskb;
2099 +
2100 +       dst_release(nskb->dst);
2101 +       nskb->dst = &nrt->u.dst;
2102 +
2103 +       /* "Never happens" */
2104 +       if (nskb->len > dst_pmtu(nskb->dst))
2105 +               goto free_nskb;
2106 +
2107 +       ip_direct_send (nskb);
2108 +
2109 +       return;
2110 +
2111 + free_nskb:
2112 +       kfree_skb(nskb);
2113 +}
2114 +
2115 +
2116 +static unsigned int tarpit(struct sk_buff **pskb,
2117 +                          const struct net_device *in,
2118 +                          const struct net_device *out,
2119 +                          unsigned int hooknum,
2120 +                          const void *targinfo,
2121 +                          void *userinfo)
2122 +{
2123 +       struct sk_buff *skb = *pskb;
2124 +       struct rtable *rt = (struct rtable*)skb->dst;
2125 +
2126 +       /* Do we have an input route cache entry? */
2127 +       if (!rt)
2128 +               return NF_DROP;
2129 +
2130 +        /* No replies to physical multicast/broadcast */
2131 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
2132 +               return NF_DROP;
2133 +
2134 +        /* Now check at the protocol level */
2135 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
2136 +                return NF_DROP;
2137 +
2138 +       /* Our naive response construction doesn't deal with IP
2139 +           options, and probably shouldn't try. */
2140 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
2141 +               return NF_DROP;
2142 +
2143 +        /* We aren't interested in fragments */
2144 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
2145 +                return NF_DROP;
2146 +
2147 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
2148 +
2149 +       return NF_DROP;
2150 +}
2151 +
2152 +
2153 +static int check(const char *tablename,
2154 +                const struct ipt_entry *e,
2155 +                void *targinfo,
2156 +                unsigned int targinfosize,
2157 +                unsigned int hook_mask)
2158 +{
2159 +       /* Only allow these for input/forward packet filtering. */
2160 +       if (strcmp(tablename, "filter") != 0) {
2161 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
2162 +               return 0;
2163 +       }
2164 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
2165 +                           | (1 << NF_IP_FORWARD))) != 0) {
2166 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
2167 +               return 0;
2168 +       }
2169 +
2170 +       /* Must specify that it's a TCP packet */
2171 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
2172 +               DEBUGP("TARPIT: not valid for non-tcp\n");
2173 +               return 0;
2174 +       }
2175 +
2176 +       return 1;
2177 +}
2178 +
2179 +static struct ipt_target ipt_tarpit_reg = { 
2180 +       .name = "TARPIT",
2181 +       .target = tarpit,
2182 +       .checkentry = check,
2183 +       .me = THIS_MODULE
2184 +};
2185 +
2186 +static int __init init(void)
2187 +{
2188 +       return ipt_register_target(&ipt_tarpit_reg);
2189 +}
2190 +
2191 +static void __exit fini(void)
2192 +{
2193 +       ipt_unregister_target(&ipt_tarpit_reg);
2194 +}
2195 +
2196 +module_init(init);
2197 +module_exit(fini);
2198 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c
2199 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_TTL.c        1970-01-01 01:00:00.000000000 +0100
2200 +++ linux-2.6.7/net/ipv4/netfilter/ipt_TTL.c    2004-06-29 12:32:03.618320464 +0200
2201 @@ -0,0 +1,120 @@
2202 +/* TTL modification target for IP tables
2203 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
2204 + *
2205 + * Version: $Revision$
2206 + *
2207 + * This software is distributed under the terms of GNU GPL
2208 + */
2209 +
2210 +#include <linux/module.h>
2211 +#include <linux/skbuff.h>
2212 +#include <linux/ip.h>
2213 +#include <net/checksum.h>
2214 +
2215 +#include <linux/netfilter_ipv4/ip_tables.h>
2216 +#include <linux/netfilter_ipv4/ipt_TTL.h>
2217 +
2218 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
2219 +MODULE_DESCRIPTION("IP tables TTL modification module");
2220 +MODULE_LICENSE("GPL");
2221 +
2222 +static unsigned int 
2223 +ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, 
2224 +               const struct net_device *out, unsigned int hooknum, 
2225 +               const void *targinfo, void *userinfo)
2226 +{
2227 +       struct iphdr *iph;
2228 +       const struct ipt_TTL_info *info = targinfo;
2229 +       u_int16_t diffs[2];
2230 +       int new_ttl;
2231 +
2232 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
2233 +               return NF_DROP;
2234 +
2235 +       iph = (*pskb)->nh.iph;
2236 +                        
2237 +       switch (info->mode) {
2238 +               case IPT_TTL_SET:
2239 +                       new_ttl = info->ttl;
2240 +                       break;
2241 +               case IPT_TTL_INC:
2242 +                       new_ttl = iph->ttl + info->ttl;
2243 +                       if (new_ttl > 255)
2244 +                               new_ttl = 255;
2245 +                       break;
2246 +               case IPT_TTL_DEC:
2247 +                       new_ttl = iph->ttl + info->ttl;
2248 +                       if (new_ttl < 0)
2249 +                               new_ttl = 0;
2250 +                       break;
2251 +               default:
2252 +                       new_ttl = iph->ttl;
2253 +                       break;
2254 +       }
2255 +
2256 +       if (new_ttl != iph->ttl) {
2257 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
2258 +               iph->ttl = new_ttl;
2259 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
2260 +               iph->check = csum_fold(csum_partial((char *)diffs,
2261 +                                                   sizeof(diffs),
2262 +                                                   iph->check^0xFFFF));
2263 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
2264 +       }
2265 +
2266 +       return IPT_CONTINUE;
2267 +}
2268 +
2269 +static int ipt_ttl_checkentry(const char *tablename,
2270 +               const struct ipt_entry *e,
2271 +               void *targinfo,
2272 +               unsigned int targinfosize,
2273 +               unsigned int hook_mask)
2274 +{
2275 +       struct ipt_TTL_info *info = targinfo;
2276 +
2277 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
2278 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
2279 +                               targinfosize,
2280 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
2281 +               return 0;       
2282 +       }       
2283 +
2284 +       if (strcmp(tablename, "mangle")) {
2285 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
2286 +               return 0;
2287 +       }
2288 +
2289 +       if (info->mode > IPT_TTL_MAXMODE) {
2290 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
2291 +                       info->mode);
2292 +               return 0;
2293 +       }
2294 +
2295 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
2296 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
2297 +               return 0;
2298 +       }
2299 +       
2300 +       return 1;
2301 +}
2302 +
2303 +static struct ipt_target ipt_TTL = { 
2304 +       .name = "TTL",
2305 +       .target = ipt_ttl_target, 
2306 +       .checkentry = ipt_ttl_checkentry, 
2307 +       .me = THIS_MODULE 
2308 +};
2309 +
2310 +static int __init init(void)
2311 +{
2312 +       return ipt_register_target(&ipt_TTL);
2313 +}
2314 +
2315 +static void __exit fini(void)
2316 +{
2317 +       ipt_unregister_target(&ipt_TTL);
2318 +}
2319 +
2320 +module_init(init);
2321 +module_exit(fini);
2322 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_XOR.c linux-2.6.7/net/ipv4/netfilter/ipt_XOR.c
2323 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_XOR.c        1970-01-01 01:00:00.000000000 +0100
2324 +++ linux-2.6.7/net/ipv4/netfilter/ipt_XOR.c    2004-06-29 12:34:46.050627000 +0200
2325 @@ -0,0 +1,117 @@
2326 +/* XOR target for IP tables
2327 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
2328 + * Based on ipt_TTL.c
2329 + *
2330 + * Version 1.0
2331 + *
2332 + * This software is distributed under the terms of GNU GPL
2333 + */
2334 +
2335 +#include <linux/module.h>
2336 +#include <linux/skbuff.h>
2337 +#include <linux/ip.h>
2338 +#include <linux/tcp.h>
2339 +#include <linux/udp.h>
2340 +
2341 +#include <linux/netfilter_ipv4/ip_tables.h>
2342 +#include <linux/netfilter_ipv4/ipt_XOR.h>
2343 +
2344 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
2345 +MODULE_DESCRIPTION("IP tables XOR module");
2346 +MODULE_LICENSE("GPL");
2347 +
2348 +static unsigned int 
2349 +ipt_xor_target(struct sk_buff **pskb, 
2350 +               const struct net_device *in, const struct net_device *out, 
2351 +               unsigned int hooknum, const void *targinfo, void *userinfo)
2352 +{
2353 +       struct ipt_XOR_info *info = (void *) targinfo;
2354 +       struct iphdr *iph;
2355 +       struct tcphdr *tcph;
2356 +       struct udphdr *udph;
2357 +       int i, j, k;
2358 +
2359 +       if (!skb_ip_make_writable(pskb, (*pskb)->len))
2360 +               return NF_DROP;
2361 +
2362 +       iph = (*pskb)->nh.iph;
2363 +  
2364 +       if (iph->protocol == IPPROTO_TCP) {
2365 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
2366 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
2367 +                       for (k=0; k<=info->block_size; k++) {
2368 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
2369 +                                               info->key[j];
2370 +                               i++;
2371 +                       }
2372 +                       j++;
2373 +                       if (info->key[j] == 0x00)
2374 +                               j = 0;
2375 +               }
2376 +       } else if (iph->protocol == IPPROTO_UDP) {
2377 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
2378 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
2379 +                       for (k=0; k<=info->block_size; k++) {
2380 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
2381 +                                               info->key[j];
2382 +                               i++;
2383 +                       }
2384 +                       j++;
2385 +                       if (info->key[j] == 0x00)
2386 +                               j = 0;
2387 +               }
2388 +       }
2389 +  
2390 +       return IPT_CONTINUE;
2391 +}
2392 +
2393 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
2394 +               void *targinfo, unsigned int targinfosize, 
2395 +               unsigned int hook_mask)
2396 +{
2397 +       struct ipt_XOR_info *info = targinfo;
2398 +
2399 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
2400 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
2401 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
2402 +               return 0;
2403 +       }       
2404 +
2405 +       if (strcmp(tablename, "mangle")) {
2406 +               printk(KERN_WARNING "XOR: can only be called from"
2407 +                               "\"mangle\" table, not \"%s\"\n", tablename);
2408 +               return 0; 
2409 +       }
2410 +
2411 +       if (!strcmp(info->key, "")) {
2412 +               printk(KERN_WARNING "XOR: You must specify a key");
2413 +               return 0;
2414 +       }
2415 +
2416 +       if (info->block_size == 0) {
2417 +               printk(KERN_WARNING "XOR: You must specify a block-size");
2418 +               return 0;
2419 +       }
2420 +
2421 +       return 1;
2422 +}
2423 +
2424 +static struct ipt_target ipt_XOR = { 
2425 +       .name = "XOR",
2426 +       .target = ipt_xor_target, 
2427 +       .checkentry = ipt_xor_checkentry,
2428 +       .me = THIS_MODULE,
2429 +};
2430 +
2431 +static int __init init(void)
2432 +{
2433 +       return ipt_register_target(&ipt_XOR);
2434 +}
2435 +
2436 +static void __exit fini(void)
2437 +{
2438 +       ipt_unregister_target(&ipt_XOR);
2439 +}
2440 +
2441 +module_init(init);
2442 +module_exit(fini);
2443 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_connlimit.c
2444 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_connlimit.c  1970-01-01 01:00:00.000000000 +0100
2445 +++ linux-2.6.7/net/ipv4/netfilter/ipt_connlimit.c      2004-06-29 12:32:05.988960072 +0200
2446 @@ -0,0 +1,230 @@
2447 +/*
2448 + * netfilter module to limit the number of parallel tcp
2449 + * connections per IP address.
2450 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
2451 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
2452 + *             only ignore TIME_WAIT or gone connections
2453 + *
2454 + * based on ...
2455 + *
2456 + * Kernel module to match connection tracking information.
2457 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
2458 + */
2459 +#include <linux/module.h>
2460 +#include <linux/skbuff.h>
2461 +#include <linux/list.h>
2462 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2463 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
2464 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
2465 +#include <linux/netfilter_ipv4/ip_tables.h>
2466 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
2467 +
2468 +#define DEBUG 0
2469 +
2470 +MODULE_LICENSE("GPL");
2471 +
2472 +/* we'll save the tuples of all connections we care about */
2473 +struct ipt_connlimit_conn
2474 +{
2475 +        struct list_head list;
2476 +       struct ip_conntrack_tuple tuple;
2477 +};
2478 +
2479 +struct ipt_connlimit_data {
2480 +       spinlock_t lock;
2481 +       struct list_head iphash[256];
2482 +};
2483 +
2484 +static int ipt_iphash(u_int32_t addr)
2485 +{
2486 +       int hash;
2487 +
2488 +       hash  =  addr        & 0xff;
2489 +       hash ^= (addr >>  8) & 0xff;
2490 +       hash ^= (addr >> 16) & 0xff;
2491 +       hash ^= (addr >> 24) & 0xff;
2492 +       return hash;
2493 +}
2494 +
2495 +static int count_them(struct ipt_connlimit_data *data,
2496 +                     u_int32_t addr, u_int32_t mask,
2497 +                     struct ip_conntrack *ct)
2498 +{
2499 +#if DEBUG
2500 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
2501 +                                    "fin_wait", "time_wait", "close", "close_wait",
2502 +                                    "last_ack", "listen" };
2503 +#endif
2504 +       int addit = 1, matches = 0;
2505 +       struct ip_conntrack_tuple tuple;
2506 +       struct ip_conntrack_tuple_hash *found;
2507 +       struct ipt_connlimit_conn *conn;
2508 +       struct list_head *hash,*lh;
2509 +
2510 +       spin_lock(&data->lock);
2511 +       tuple = ct->tuplehash[0].tuple;
2512 +       hash = &data->iphash[ipt_iphash(addr & mask)];
2513 +
2514 +       /* check the saved connections */
2515 +       for (lh = hash->next; lh != hash; lh = lh->next) {
2516 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
2517 +               found = ip_conntrack_find_get(&conn->tuple,ct);
2518 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
2519 +                   found != NULL &&
2520 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
2521 +                       /* Just to be sure we have it only once in the list.
2522 +                          We should'nt see tuples twice unless someone hooks this
2523 +                          into a table without "-p tcp --syn" */
2524 +                       addit = 0;
2525 +               }
2526 +#if DEBUG
2527 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
2528 +                      ipt_iphash(addr & mask),
2529 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
2530 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
2531 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
2532 +#endif
2533 +               if (NULL == found) {
2534 +                       /* this one is gone */
2535 +                       lh = lh->prev;
2536 +                       list_del(lh->next);
2537 +                       kfree(conn);
2538 +                       continue;
2539 +               }
2540 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
2541 +                       /* we don't care about connections which are
2542 +                          closed already -> ditch it */
2543 +                       lh = lh->prev;
2544 +                       list_del(lh->next);
2545 +                       kfree(conn);
2546 +                       nf_conntrack_put(&found->ctrack->infos[0]);
2547 +                       continue;
2548 +               }
2549 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
2550 +                       /* same source IP address -> be counted! */
2551 +                       matches++;
2552 +               }
2553 +               nf_conntrack_put(&found->ctrack->infos[0]);
2554 +       }
2555 +       if (addit) {
2556 +               /* save the new connection in our list */
2557 +#if DEBUG
2558 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
2559 +                      ipt_iphash(addr & mask),
2560 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
2561 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
2562 +#endif
2563 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
2564 +               if (NULL == conn)
2565 +                       return -1;
2566 +               memset(conn,0,sizeof(*conn));
2567 +               INIT_LIST_HEAD(&conn->list);
2568 +               conn->tuple = tuple;
2569 +               list_add(&conn->list,hash);
2570 +               matches++;
2571 +       }
2572 +       spin_unlock(&data->lock);
2573 +       return matches;
2574 +}
2575 +
2576 +static int
2577 +match(const struct sk_buff *skb,
2578 +      const struct net_device *in,
2579 +      const struct net_device *out,
2580 +      const void *matchinfo,
2581 +      int offset,
2582 +      int *hotdrop)
2583 +{
2584 +       const struct ipt_connlimit_info *info = matchinfo;
2585 +       int connections, match;
2586 +       struct ip_conntrack *ct;
2587 +       enum ip_conntrack_info ctinfo;
2588 +
2589 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2590 +       if (NULL == ct) {
2591 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
2592 +               *hotdrop = 1;
2593 +               return 0;
2594 +       }
2595 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
2596 +       if (-1 == connections) {
2597 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
2598 +               *hotdrop = 1; /* let's free some memory :-) */
2599 +               return 0;
2600 +       }
2601 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
2602 +#if DEBUG
2603 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
2604 +              "connections=%d limit=%d match=%s\n",
2605 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
2606 +              connections, info->limit, match ? "yes" : "no");
2607 +#endif
2608 +
2609 +       return match;
2610 +}
2611 +
2612 +static int check(const char *tablename,
2613 +                const struct ipt_ip *ip,
2614 +                void *matchinfo,
2615 +                unsigned int matchsize,
2616 +                unsigned int hook_mask)
2617 +{
2618 +       struct ipt_connlimit_info *info = matchinfo;
2619 +       int i;
2620 +
2621 +       /* verify size */
2622 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
2623 +               return 0;
2624 +
2625 +       /* refuse anything but tcp */
2626 +       if (ip->proto != IPPROTO_TCP)
2627 +               return 0;
2628 +
2629 +       /* init private data */
2630 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
2631 +       spin_lock_init(&(info->data->lock));
2632 +       for (i = 0; i < 256; i++)
2633 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
2634 +       
2635 +       return 1;
2636 +}
2637 +
2638 +static void destroy(void *matchinfo, unsigned int matchinfosize)
2639 +{
2640 +       struct ipt_connlimit_info *info = matchinfo;
2641 +       struct ipt_connlimit_conn *conn;
2642 +       struct list_head *hash;
2643 +       int i;
2644 +
2645 +       /* cleanup */
2646 +       for (i = 0; i < 256; i++) {
2647 +               hash = &(info->data->iphash[i]);
2648 +               while (hash != hash->next) {
2649 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
2650 +                       list_del(hash->next);
2651 +                       kfree(conn);
2652 +               }
2653 +       }
2654 +       kfree(info->data);
2655 +}
2656 +
2657 +static struct ipt_match connlimit_match = { 
2658 +       .name = "connlimit",
2659 +       .match = &match,
2660 +       .checkentry = &check,
2661 +       .destroy = &destroy,
2662 +       .me = THIS_MODULE
2663 +};
2664 +
2665 +static int __init init(void)
2666 +{
2667 +       return ipt_register_match(&connlimit_match);
2668 +}
2669 +
2670 +static void __exit fini(void)
2671 +{
2672 +       ipt_unregister_match(&connlimit_match);
2673 +}
2674 +
2675 +module_init(init);
2676 +module_exit(fini);
2677 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_connmark.c linux-2.6.7/net/ipv4/netfilter/ipt_connmark.c
2678 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_connmark.c   1970-01-01 01:00:00.000000000 +0100
2679 +++ linux-2.6.7/net/ipv4/netfilter/ipt_connmark.c       2004-06-29 12:34:21.514357080 +0200
2680 @@ -0,0 +1,81 @@
2681 +/* This kernel module matches connection mark values set by the
2682 + * CONNMARK target
2683 + *
2684 + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
2685 + * by Henrik Nordstrom <hno@marasystems.com>
2686 + *
2687 + * This program is free software; you can redistribute it and/or modify
2688 + * it under the terms of the GNU General Public License as published by
2689 + * the Free Software Foundation; either version 2 of the License, or
2690 + * (at your option) any later version.
2691 + *
2692 + * This program is distributed in the hope that it will be useful,
2693 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2694 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2695 + * GNU General Public License for more details.
2696 + *
2697 + * You should have received a copy of the GNU General Public License
2698 + * along with this program; if not, write to the Free Software
2699 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2700 + */
2701 +
2702 +#include <linux/module.h>
2703 +#include <linux/skbuff.h>
2704 +
2705 +MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
2706 +MODULE_DESCRIPTION("IP tables connmark match module");
2707 +MODULE_LICENSE("GPL");
2708 +
2709 +#include <linux/netfilter_ipv4/ip_tables.h>
2710 +#include <linux/netfilter_ipv4/ipt_connmark.h>
2711 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2712 +
2713 +static int
2714 +match(const struct sk_buff *skb,
2715 +      const struct net_device *in,
2716 +      const struct net_device *out,
2717 +      const void *matchinfo,
2718 +      int offset,
2719 +      int *hotdrop)
2720 +{
2721 +       const struct ipt_connmark_info *info = matchinfo;
2722 +       enum ip_conntrack_info ctinfo;
2723 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2724 +       if (!ct)
2725 +               return 0;
2726 +
2727 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
2728 +}
2729 +
2730 +static int
2731 +checkentry(const char *tablename,
2732 +          const struct ipt_ip *ip,
2733 +          void *matchinfo,
2734 +          unsigned int matchsize,
2735 +          unsigned int hook_mask)
2736 +{
2737 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
2738 +               return 0;
2739 +
2740 +       return 1;
2741 +}
2742 +
2743 +static struct ipt_match connmark_match = {
2744 +       .name = "connmark",
2745 +       .match = &match,
2746 +       .checkentry = &checkentry,
2747 +       .me = THIS_MODULE
2748 +};
2749 +
2750 +static int __init init(void)
2751 +{
2752 +       return ipt_register_match(&connmark_match);
2753 +}
2754 +
2755 +static void __exit fini(void)
2756 +{
2757 +       ipt_unregister_match(&connmark_match);
2758 +}
2759 +
2760 +module_init(init);
2761 +module_exit(fini);
2762 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c
2763 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_dstlimit.c   1970-01-01 01:00:00.000000000 +0100
2764 +++ linux-2.6.7/net/ipv4/netfilter/ipt_dstlimit.c       2004-06-29 12:32:07.243769312 +0200
2765 @@ -0,0 +1,690 @@
2766 +/* iptables match extension to limit the number of packets per second
2767 + * seperately for each destination.
2768 + *
2769 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2770 + *
2771 + * $Id$
2772 + *
2773 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2774 + *
2775 + * based on ipt_limit.c by:
2776 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
2777 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
2778 + * Rusty Russell       <rusty@rustcorp.com.au>
2779 + *
2780 + * The general idea is to create a hash table for every dstip and have a
2781 + * seperate limit counter per tuple.  This way you can do something like 'limit
2782 + * the number of syn packets for each of my internal addresses.
2783 + *
2784 + * Ideally this would just be implemented as a general 'hash' match, which would
2785 + * allow us to attach any iptables target to it's hash buckets.  But this is
2786 + * not possible in the current iptables architecture.  As always, pkttables for
2787 + * 2.7.x will help ;)
2788 + */
2789 +#include <linux/module.h>
2790 +#include <linux/skbuff.h>
2791 +#include <linux/spinlock.h>
2792 +#include <linux/random.h>
2793 +#include <linux/jhash.h>
2794 +#include <linux/slab.h>
2795 +#include <linux/vmalloc.h>
2796 +#include <linux/tcp.h>
2797 +#include <linux/udp.h>
2798 +#include <linux/proc_fs.h>
2799 +#include <linux/seq_file.h>
2800 +
2801 +#define ASSERT_READ_LOCK(x) 
2802 +#define ASSERT_WRITE_LOCK(x) 
2803 +#include <linux/netfilter_ipv4/lockhelp.h>
2804 +#include <linux/netfilter_ipv4/listhelp.h>
2805 +
2806 +#include <linux/netfilter_ipv4/ip_tables.h>
2807 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2808 +
2809 +/* FIXME: this is just for IP_NF_ASSERRT */
2810 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2811 +
2812 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2813 +
2814 +MODULE_LICENSE("GPL");
2815 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2816 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2817 +
2818 +/* need to declare this at the top */
2819 +static struct proc_dir_entry *dstlimit_procdir;
2820 +static struct file_operations dl_file_ops;
2821 +
2822 +/* hash table crap */
2823 +
2824 +struct dsthash_dst {
2825 +       u_int32_t src_ip;
2826 +       u_int32_t dst_ip;
2827 +       u_int16_t port;
2828 +};
2829 +
2830 +struct dsthash_ent {
2831 +       /* static / read-only parts in the beginning */
2832 +       struct list_head list;
2833 +       struct dsthash_dst dst;
2834 +
2835 +       /* modified structure members in the end */
2836 +       unsigned long expires;          /* precalculated expiry time */
2837 +       struct {
2838 +               unsigned long prev;     /* last modification */
2839 +               u_int32_t credit;
2840 +               u_int32_t credit_cap, cost;
2841 +       } rateinfo;
2842 +};
2843 +
2844 +struct ipt_dstlimit_htable {
2845 +       struct list_head list;          /* global list of all htables */
2846 +       atomic_t use;
2847 +
2848 +       struct dstlimit_cfg cfg;        /* config */
2849 +
2850 +       /* used internally */
2851 +       spinlock_t lock;                /* lock for list_head */
2852 +       u_int32_t rnd;                  /* random seed for hash */
2853 +       struct timer_list timer;        /* timer for gc */
2854 +       atomic_t count;                 /* number entries in table */
2855 +
2856 +       /* seq_file stuff */
2857 +       struct proc_dir_entry *pde;
2858 +
2859 +       struct list_head hash[0];       /* hashtable itself */
2860 +};
2861 +
2862 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
2863 +static LIST_HEAD(dstlimit_htables);
2864 +static kmem_cache_t *dstlimit_cachep;
2865 +
2866 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
2867 +{
2868 +       return (ent->dst.dst_ip == b->dst_ip 
2869 +               && ent->dst.port == b->port
2870 +               && ent->dst.src_ip == b->src_ip);
2871 +}
2872 +
2873 +static inline u_int32_t
2874 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
2875 +{
2876 +       return (jhash_3words(dst->dst_ip, dst->port, 
2877 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
2878 +}
2879 +
2880 +static inline struct dsthash_ent *
2881 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2882 +{
2883 +       struct dsthash_ent *ent;
2884 +       u_int32_t hash = hash_dst(ht, dst);
2885 +       MUST_BE_LOCKED(&ht->lock);
2886 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
2887 +       return ent;
2888 +}
2889 +
2890 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
2891 +static struct dsthash_ent *
2892 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2893 +{
2894 +       struct dsthash_ent *ent;
2895 +
2896 +       /* initialize hash with random val at the time we allocate
2897 +        * the first hashtable entry */
2898 +       if (!ht->rnd)
2899 +               get_random_bytes(&ht->rnd, 4);
2900 +
2901 +       if (ht->cfg.max &&
2902 +           atomic_read(&ht->count) >= ht->cfg.max) {
2903 +               /* FIXME: do something. question is what.. */
2904 +               if (net_ratelimit())
2905 +                       printk(KERN_WARNING 
2906 +                               "ipt_dstlimit: max count of %u reached\n", 
2907 +                               ht->cfg.max);
2908 +               return NULL;
2909 +       }
2910 +
2911 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
2912 +       if (!ent) {
2913 +               if (net_ratelimit())
2914 +                       printk(KERN_ERR 
2915 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
2916 +               return NULL;
2917 +       }
2918 +
2919 +       atomic_inc(&ht->count);
2920 +
2921 +       ent->dst.dst_ip = dst->dst_ip;
2922 +       ent->dst.port = dst->port;
2923 +       ent->dst.src_ip = dst->src_ip;
2924 +
2925 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
2926 +
2927 +       return ent;
2928 +}
2929 +
2930 +static inline void 
2931 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
2932 +{
2933 +       MUST_BE_LOCKED(&ht->lock);
2934 +
2935 +       list_del(&ent->list);
2936 +       kmem_cache_free(dstlimit_cachep, ent);
2937 +       atomic_dec(&ht->count);
2938 +}
2939 +static void htable_gc(unsigned long htlong);
2940 +
2941 +static int htable_create(struct ipt_dstlimit_info *minfo)
2942 +{
2943 +       int i;
2944 +       unsigned int size;
2945 +       struct ipt_dstlimit_htable *hinfo;
2946 +
2947 +       if (minfo->cfg.size)
2948 +               size = minfo->cfg.size;
2949 +       else {
2950 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
2951 +                        / sizeof(struct list_head));
2952 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
2953 +                       size = 8192;
2954 +               if (size < 16)
2955 +                       size = 16;
2956 +       }
2957 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
2958 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
2959 +                       + (sizeof(struct list_head) * size));
2960 +       if (!hinfo) {
2961 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
2962 +               return -1;
2963 +       }
2964 +       minfo->hinfo = hinfo;
2965 +
2966 +       /* copy match config into hashtable config */
2967 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
2968 +       hinfo->cfg.size = size;
2969 +       if (!hinfo->cfg.max)
2970 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
2971 +       else if (hinfo->cfg.max < hinfo->cfg.size)
2972 +               hinfo->cfg.max = hinfo->cfg.size;
2973 +
2974 +       for (i = 0; i < hinfo->cfg.size; i++)
2975 +               INIT_LIST_HEAD(&hinfo->hash[i]);
2976 +
2977 +       atomic_set(&hinfo->count, 0);
2978 +       atomic_set(&hinfo->use, 1);
2979 +       hinfo->rnd = 0;
2980 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
2981 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
2982 +       if (!hinfo->pde) {
2983 +               vfree(hinfo);
2984 +               return -1;
2985 +       }
2986 +       hinfo->pde->proc_fops = &dl_file_ops;
2987 +       hinfo->pde->data = hinfo;
2988 +
2989 +       init_timer(&hinfo->timer);
2990 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
2991 +       hinfo->timer.data = (unsigned long )hinfo;
2992 +       hinfo->timer.function = htable_gc;
2993 +       add_timer(&hinfo->timer);
2994 +
2995 +       WRITE_LOCK(&dstlimit_lock);
2996 +       list_add(&hinfo->list, &dstlimit_htables);
2997 +       WRITE_UNLOCK(&dstlimit_lock);
2998 +
2999 +       return 0;
3000 +}
3001 +
3002 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
3003 +{
3004 +       return 1;
3005 +}
3006 +
3007 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
3008 +{
3009 +       return (jiffies >= he->expires);
3010 +}
3011 +
3012 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
3013 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
3014 +                                             struct dsthash_ent *he))
3015 +{
3016 +       int i;
3017 +
3018 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
3019 +
3020 +       /* lock hash table and iterate over it */
3021 +       LOCK_BH(&ht->lock);
3022 +       for (i = 0; i < ht->cfg.size; i++) {
3023 +               struct dsthash_ent *dh, *n;
3024 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
3025 +                       if ((*select)(ht, dh))
3026 +                               __dsthash_free(ht, dh);
3027 +               }
3028 +       }
3029 +       UNLOCK_BH(&ht->lock);
3030 +}
3031 +
3032 +/* hash table garbage collector, run by timer */
3033 +static void htable_gc(unsigned long htlong)
3034 +{
3035 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
3036 +
3037 +       htable_selective_cleanup(ht, select_gc);
3038 +
3039 +       /* re-add the timer accordingly */
3040 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
3041 +       add_timer(&ht->timer);
3042 +}
3043 +
3044 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
3045 +{
3046 +       /* remove timer, if it is pending */
3047 +       if (timer_pending(&hinfo->timer))
3048 +               del_timer(&hinfo->timer);
3049 +
3050 +       /* remove proc entry */
3051 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
3052 +
3053 +       htable_selective_cleanup(hinfo, select_all);
3054 +       vfree(hinfo);
3055 +}
3056 +
3057 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
3058 +{
3059 +       struct ipt_dstlimit_htable *hinfo;
3060 +
3061 +       READ_LOCK(&dstlimit_lock);
3062 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
3063 +               if (!strcmp(name, hinfo->pde->name)) {
3064 +                       atomic_inc(&hinfo->use);
3065 +                       READ_UNLOCK(&dstlimit_lock);
3066 +                       return hinfo;
3067 +               }
3068 +       }
3069 +       READ_UNLOCK(&dstlimit_lock);
3070 +
3071 +       return NULL;
3072 +}
3073 +
3074 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
3075 +{
3076 +       if (atomic_dec_and_test(&hinfo->use)) {
3077 +               WRITE_LOCK(&dstlimit_lock);
3078 +               list_del(&hinfo->list);
3079 +               WRITE_UNLOCK(&dstlimit_lock);
3080 +               htable_destroy(hinfo);
3081 +       }
3082 +}
3083 +
3084 +
3085 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
3086 + * see net/sched/sch_tbf.c in the linux source tree
3087 + */
3088 +
3089 +/* Rusty: This is my (non-mathematically-inclined) understanding of
3090 +   this algorithm.  The `average rate' in jiffies becomes your initial
3091 +   amount of credit `credit' and the most credit you can ever have
3092 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
3093 +   test, `cost'.
3094 +
3095 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
3096 +   If you get credit balance more than this, the extra credit is
3097 +   discarded.  Every time the match passes, you lose `cost' credits;
3098 +   if you don't have that many, the test fails.
3099 +
3100 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
3101 +
3102 +   To get the maximum range, we multiply by this factor (ie. you get N
3103 +   credits per jiffy).  We want to allow a rate as low as 1 per day
3104 +   (slowest userspace tool allows), which means
3105 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
3106 +*/
3107 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
3108 +
3109 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
3110 + * us the power of 2 below the theoretical max, so GCC simply does a
3111 + * shift. */
3112 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
3113 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
3114 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
3115 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
3116 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
3117 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
3118 +
3119 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
3120 +
3121 +/* Precision saver. */
3122 +static inline u_int32_t
3123 +user2credits(u_int32_t user)
3124 +{
3125 +       /* If multiplying would overflow... */
3126 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
3127 +               /* Divide first. */
3128 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
3129 +
3130 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
3131 +}
3132 +
3133 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
3134 +{
3135 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
3136 +                                       * CREDITS_PER_JIFFY;
3137 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
3138 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
3139 +}
3140 +
3141 +static int
3142 +dstlimit_match(const struct sk_buff *skb,
3143 +               const struct net_device *in,
3144 +               const struct net_device *out,
3145 +               const void *matchinfo,
3146 +               int offset,
3147 +               int *hotdrop)
3148 +{
3149 +       struct ipt_dstlimit_info *r = 
3150 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
3151 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
3152 +       unsigned long now = jiffies;
3153 +       struct dsthash_ent *dh;
3154 +       struct dsthash_dst dst;
3155 +
3156 +       memset(&dst, 0, sizeof(dst));
3157 +
3158 +       /* dest ip is always in hash */
3159 +       dst.dst_ip = skb->nh.iph->daddr;
3160 +
3161 +       /* source ip only if respective hashmode, otherwise set to
3162 +        * zero */
3163 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
3164 +               dst.src_ip = skb->nh.iph->saddr;
3165 +
3166 +       /* dest port only if respective mode */
3167 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
3168 +               u16 ports[2];
3169 +
3170 +               /* Must not be a fragment. */
3171 +               if (offset)
3172 +                       return 0;
3173 +
3174 +               /* Must be big enough to read ports (both UDP and TCP have
3175 +                  them at the start). */
3176 +               if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3177 +                       /* We've been asked to examine this packet, and we
3178 +                          can't.  Hence, no choice but to drop. */
3179 +                       *hotdrop = 1;
3180 +                       return 0;
3181 +               }
3182 +
3183 +               switch (skb->nh.iph->protocol) {
3184 +                       struct tcphdr *th;
3185 +                       struct udphdr *uh;
3186 +               case IPPROTO_TCP:
3187 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
3188 +                       dst.port = th->dest;
3189 +                       break;
3190 +               case IPPROTO_UDP:
3191 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
3192 +                       dst.port = uh->dest;
3193 +                       break;
3194 +               default:
3195 +                       break;
3196 +               }
3197 +       } 
3198 +
3199 +       LOCK_BH(&hinfo->lock);
3200 +       dh = __dsthash_find(hinfo, &dst);
3201 +       if (!dh) {
3202 +               dh = __dsthash_alloc_init(hinfo, &dst);
3203 +
3204 +               if (!dh) {
3205 +                       /* enomem... don't match == DROP */
3206 +                       if (net_ratelimit())
3207 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
3208 +                       UNLOCK_BH(&hinfo->lock);
3209 +                       return 0;
3210 +               }
3211 +
3212 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
3213 +
3214 +               dh->rateinfo.prev = jiffies;
3215 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
3216 +                                                       hinfo->cfg.burst);
3217 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
3218 +                                                       hinfo->cfg.burst);
3219 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
3220 +
3221 +               UNLOCK_BH(&hinfo->lock);
3222 +               return 1;
3223 +       }
3224 +
3225 +       /* update expiration timeout */
3226 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
3227 +
3228 +       rateinfo_recalc(dh, now);
3229 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
3230 +               /* We're underlimit. */
3231 +               dh->rateinfo.credit -= dh->rateinfo.cost;
3232 +               UNLOCK_BH(&hinfo->lock);
3233 +               return 1;
3234 +       }
3235 +
3236 +               UNLOCK_BH(&hinfo->lock);
3237 +
3238 +       /* default case: we're overlimit, thus don't match */
3239 +       return 0;
3240 +}
3241 +
3242 +static int
3243 +dstlimit_checkentry(const char *tablename,
3244 +                    const struct ipt_ip *ip,
3245 +                    void *matchinfo,
3246 +                    unsigned int matchsize,
3247 +                    unsigned int hook_mask)
3248 +{
3249 +       struct ipt_dstlimit_info *r = matchinfo;
3250 +
3251 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
3252 +               return 0;
3253 +
3254 +       /* Check for overflow. */
3255 +       if (r->cfg.burst == 0
3256 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
3257 +                                       user2credits(r->cfg.avg)) {
3258 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
3259 +                      r->cfg.avg, r->cfg.burst);
3260 +               return 0;
3261 +       }
3262 +
3263 +       if (r->cfg.mode == 0 
3264 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
3265 +                         |IPT_DSTLIMIT_HASH_DIP
3266 +                         |IPT_DSTLIMIT_HASH_SIP))
3267 +               return 0;
3268 +
3269 +       if (!r->cfg.gc_interval)
3270 +               return 0;
3271 +       
3272 +       if (!r->cfg.expire)
3273 +               return 0;
3274 +
3275 +       r->hinfo = htable_find_get(r->name);
3276 +       if (!r->hinfo && (htable_create(r) != 0)) {
3277 +               return 0;
3278 +       }
3279 +
3280 +       /* Ugly hack: For SMP, we only want to use one set */
3281 +       r->u.master = r;
3282 +
3283 +       return 1;
3284 +}
3285 +
3286 +static void
3287 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
3288 +{
3289 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
3290 +
3291 +       htable_put(r->hinfo);
3292 +}
3293 +
3294 +static struct ipt_match ipt_dstlimit = { 
3295 +       .list = { .prev = NULL, .next = NULL }, 
3296 +       .name = "dstlimit", 
3297 +       .match = dstlimit_match, 
3298 +       .checkentry = dstlimit_checkentry, 
3299 +       .destroy = dstlimit_destroy,
3300 +       .me = THIS_MODULE 
3301 +};
3302 +
3303 +/* PROC stuff */
3304 +
3305 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
3306 +{
3307 +       struct proc_dir_entry *pde = s->private;
3308 +       struct ipt_dstlimit_htable *htable = pde->data;
3309 +       unsigned int *bucket;
3310 +
3311 +       LOCK_BH(&htable->lock);
3312 +       if (*pos >= htable->cfg.size)
3313 +               return NULL;
3314 +
3315 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
3316 +       if (!bucket)
3317 +               return ERR_PTR(-ENOMEM);
3318 +
3319 +       *bucket = *pos;
3320 +       return bucket;
3321 +}
3322 +
3323 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
3324 +{
3325 +       struct proc_dir_entry *pde = s->private;
3326 +       struct ipt_dstlimit_htable *htable = pde->data;
3327 +       unsigned int *bucket = (unsigned int *)v;
3328 +
3329 +       *pos = ++(*bucket);
3330 +       if (*pos >= htable->cfg.size) {
3331 +               kfree(v);
3332 +               return NULL;
3333 +       }
3334 +       return bucket;
3335 +}
3336 +
3337 +static void dl_seq_stop(struct seq_file *s, void *v)
3338 +{
3339 +       struct proc_dir_entry *pde = s->private;
3340 +       struct ipt_dstlimit_htable *htable = pde->data;
3341 +       unsigned int *bucket = (unsigned int *)v;
3342 +
3343 +       kfree(bucket);
3344 +
3345 +       UNLOCK_BH(&htable->lock);
3346 +}
3347 +
3348 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
3349 +{
3350 +       /* recalculate to show accurate numbers */
3351 +       rateinfo_recalc(ent, jiffies);
3352 +
3353 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
3354 +                       (ent->expires - jiffies)/HZ,
3355 +                       NIPQUAD(ent->dst.src_ip),
3356 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
3357 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
3358 +                       ent->rateinfo.cost);
3359 +}
3360 +
3361 +static int dl_seq_show(struct seq_file *s, void *v)
3362 +{
3363 +       struct proc_dir_entry *pde = s->private;
3364 +       struct ipt_dstlimit_htable *htable = pde->data;
3365 +       unsigned int *bucket = (unsigned int *)v;
3366 +
3367 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
3368 +                     struct dsthash_ent *, s)) {
3369 +               /* buffer was filled and unable to print that tuple */
3370 +               return 1;
3371 +       }
3372 +       return 0;
3373 +}
3374 +
3375 +static struct seq_operations dl_seq_ops = {
3376 +       .start = dl_seq_start,
3377 +       .next  = dl_seq_next,
3378 +       .stop  = dl_seq_stop,
3379 +       .show  = dl_seq_show
3380 +};
3381 +
3382 +static int dl_proc_open(struct inode *inode, struct file *file)
3383 +{
3384 +       int ret = seq_open(file, &dl_seq_ops);
3385 +
3386 +       if (!ret) {
3387 +               struct seq_file *sf = file->private_data;
3388 +               sf->private = PDE(inode);
3389 +       }
3390 +       return ret;
3391 +}
3392 +
3393 +static struct file_operations dl_file_ops = {
3394 +       .owner   = THIS_MODULE,
3395 +       .open    = dl_proc_open,
3396 +       .read    = seq_read,
3397 +       .llseek  = seq_lseek,
3398 +       .release = seq_release
3399 +};
3400 +
3401 +static int init_or_fini(int fini)
3402 +{
3403 +       int ret = 0;
3404 +
3405 +       if (fini)
3406 +               goto cleanup;
3407 +
3408 +       if (ipt_register_match(&ipt_dstlimit)) {
3409 +               ret = -EINVAL;
3410 +               goto cleanup_nothing;
3411 +       }
3412 +
3413 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
3414 +        * quite small ? */
3415 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
3416 +                                           sizeof(struct dsthash_ent), 0,
3417 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
3418 +       if (!dstlimit_cachep) {
3419 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
3420 +               ret = -ENOMEM;
3421 +               goto cleanup_unreg_match;
3422 +       }
3423 +
3424 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
3425 +       if (!dstlimit_procdir) {
3426 +               printk(KERN_ERR "Unable to create proc dir entry\n");
3427 +               ret = -ENOMEM;
3428 +               goto cleanup_free_slab;
3429 +       }
3430 +
3431 +       return ret;
3432 +
3433 +cleanup:
3434 +       remove_proc_entry("ipt_dstlimit", proc_net);
3435 +cleanup_free_slab:
3436 +       kmem_cache_destroy(dstlimit_cachep);
3437 +cleanup_unreg_match:
3438 +       ipt_unregister_match(&ipt_dstlimit);
3439 +cleanup_nothing:
3440 +       return ret;
3441 +       
3442 +}
3443 +
3444 +static int __init init(void)
3445 +{
3446 +       return init_or_fini(0);
3447 +}
3448 +
3449 +static void __exit fini(void)
3450 +{
3451 +       init_or_fini(1);
3452 +}
3453 +
3454 +module_init(init);
3455 +module_exit(fini);
3456 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c
3457 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
3458 +++ linux-2.6.7/net/ipv4/netfilter/ipt_fuzzy.c  2004-06-29 12:32:08.822529304 +0200
3459 @@ -0,0 +1,185 @@
3460 +/*
3461 + *  This module implements a simple TSK FLC 
3462 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
3463 + * to limit , in an adaptive and flexible way , the packet rate crossing 
3464 + * a given stream . It serves as an initial and very simple (but effective)
3465 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
3466 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
3467 + * into our code in a precise , adaptive and efficient manner. 
3468 + *  The goal is very similar to that of "limit" match , but using techniques of
3469 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
3470 + * avoiding over and undershoots - and stuff like that .
3471 + *
3472 + *
3473 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
3474 + * 2002-08-17  : Changed to eliminate floating point operations .
3475 + * 2002-08-23  : Coding style changes .
3476 +*/
3477 +
3478 +#include <linux/module.h>
3479 +#include <linux/skbuff.h>
3480 +#include <linux/ip.h>
3481 +#include <linux/random.h>
3482 +#include <net/tcp.h>
3483 +#include <linux/spinlock.h>
3484 +#include <linux/netfilter_ipv4/ip_tables.h>
3485 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
3486 +
3487 +/*
3488 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
3489 + Expressed in percentage
3490 +*/
3491 +
3492 +#define PAR_LOW                1/100
3493 +#define PAR_HIGH       1
3494 +
3495 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
3496 +
3497 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
3498 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
3499 +MODULE_LICENSE("GPL");
3500 +
3501 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3502 +{
3503 +       if (tx >= maxi)
3504 +               return 100;
3505 +
3506 +       if (tx <= mini)
3507 +               return 0;
3508 +
3509 +       return ( (100*(tx-mini)) / (maxi-mini) );
3510 +}
3511 +
3512 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
3513 +{
3514 +       if (tx <= mini)
3515 +               return 100;
3516 +
3517 +       if (tx >= maxi)
3518 +               return 0;
3519 +
3520 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) );
3521 +}
3522 +
3523 +static int
3524 +ipt_fuzzy_match(const struct sk_buff *pskb,
3525 +              const struct net_device *in,
3526 +              const struct net_device *out,
3527 +              const void *matchinfo,
3528 +              int offset,
3529 +              int *hotdrop)
3530 +{
3531 +       /* From userspace */
3532 +       
3533 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
3534 +
3535 +       u_int8_t random_number;
3536 +       unsigned long amount;
3537 +       u_int8_t howhigh, howlow;
3538 +       
3539 +
3540 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
3541 +
3542 +       info->bytes_total += pskb->len;
3543 +       info->packets_total++;
3544 +
3545 +       info->present_time = jiffies;
3546 +       
3547 +       if (info->present_time >= info->previous_time)
3548 +               amount = info->present_time - info->previous_time;
3549 +       else { 
3550 +               /* There was a transition : I choose to re-sample 
3551 +                  and keep the old acceptance rate...
3552 +               */
3553 +
3554 +               amount = 0;
3555 +               info->previous_time = info->present_time;
3556 +               info->bytes_total = info->packets_total = 0;
3557 +       };
3558 +       
3559 +       if (amount > HZ/10) /* More than 100 ms elapsed ... */
3560 +       {
3561 +
3562 +               info->mean_rate = (u_int32_t) ((HZ*info->packets_total)  \
3563 +                                       / amount );
3564 +
3565 +               info->previous_time = info->present_time;
3566 +               info->bytes_total = info->packets_total = 0;
3567 +
3568 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
3569 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
3570 +
3571 +               info->acceptance_rate = (u_int8_t) \
3572 +                          (howhigh*PAR_LOW + PAR_HIGH*howlow);
3573 +
3574 +               /* In fact , the above defuzzification would require a denominator
3575 +                  proportional to (howhigh+howlow) but , in this particular case ,
3576 +                  that expression is constant .
3577 +                  An imediate consequence is that it isn't necessary to call 
3578 +                  both mf_high and mf_low - but to keep things understandable ,
3579 +                  I did so .  */ 
3580 +
3581 +       }
3582 +       
3583 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
3584 +
3585 +
3586 +       if ( info->acceptance_rate < 100 )
3587 +       {                
3588 +               get_random_bytes((void *)(&random_number), 1);
3589 +
3590 +               /*  If within the acceptance , it can pass => don't match */
3591 +               if (random_number <= (255 * info->acceptance_rate) / 100)
3592 +                       return 0;
3593 +               else
3594 +                       return 1; /* It can't pass ( It matches ) */
3595 +       } ;
3596 +
3597 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
3598 +       
3599 +}
3600 +
3601 +static int
3602 +ipt_fuzzy_checkentry(const char *tablename,
3603 +                  const struct ipt_ip *e,
3604 +                  void *matchinfo,
3605 +                  unsigned int matchsize,
3606 +                  unsigned int hook_mask)
3607 +{
3608 +       
3609 +       const struct ipt_fuzzy_info *info = matchinfo;
3610 +
3611 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
3612 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
3613 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
3614 +               return 0;
3615 +       }
3616 +
3617 +       if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
3618 +           || (info->minimum_rate >= info->maximum_rate )) {
3619 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
3620 +               return 0;
3621 +       }
3622 +
3623 +       return 1;
3624 +}
3625 +
3626 +static struct ipt_match ipt_fuzzy_reg = { 
3627 +       .name = "fuzzy",
3628 +       .match = ipt_fuzzy_match,
3629 +       .checkentry = ipt_fuzzy_checkentry,
3630 +       .me = THIS_MODULE
3631 +};
3632 +
3633 +static int __init init(void)
3634 +{
3635 +       return ipt_register_match(&ipt_fuzzy_reg);
3636 +}
3637 +
3638 +static void __exit fini(void)
3639 +{
3640 +       ipt_unregister_match(&ipt_fuzzy_reg);
3641 +}
3642 +
3643 +module_init(init);
3644 +module_exit(fini);
3645 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c
3646 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_ipv4options.c        1970-01-01 01:00:00.000000000 +0100
3647 +++ linux-2.6.7/net/ipv4/netfilter/ipt_ipv4options.c    2004-06-29 12:32:14.112725072 +0200
3648 @@ -0,0 +1,172 @@
3649 +/*
3650 +  This is a module which is used to match ipv4 options.
3651 +  This file is distributed under the terms of the GNU General Public
3652 +  License (GPL). Copies of the GPL can be obtained from:
3653 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
3654 +
3655 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
3656 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
3657 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
3658 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
3659 +  19-february-2004 Harald Welte <laforge@netfilter.org> : merge with 2.6.x
3660 +*/
3661 +
3662 +#include <linux/module.h>
3663 +#include <linux/skbuff.h>
3664 +#include <net/ip.h>
3665 +
3666 +#include <linux/netfilter_ipv4/ip_tables.h>
3667 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
3668 +
3669 +MODULE_LICENSE("GPL");
3670 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3671 +
3672 +static int
3673 +match(const struct sk_buff *skb,
3674 +      const struct net_device *in,
3675 +      const struct net_device *out,
3676 +      const void *matchinfo,
3677 +      int offset,
3678 +      int *hotdrop)
3679 +{
3680 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3681 +       const struct iphdr *iph = skb->nh.iph;
3682 +       const struct ip_options *opt;
3683 +
3684 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
3685 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
3686 +
3687 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
3688 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3689 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3690 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3691 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3692 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
3693 +                       return 0;
3694 +               return 1;
3695 +       }
3696 +       else {
3697 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
3698 +                       /* there are options, and we don't need to care which one */
3699 +                       return 1;
3700 +               else {
3701 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
3702 +                               /* there are options but we don't want any ! */
3703 +                               return 0;
3704 +               }
3705 +       }
3706 +
3707 +       opt = &(IPCB(skb)->opt);
3708 +
3709 +       /* source routing */
3710 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
3711 +               if (!((opt->srr) & (opt->is_strictroute)))
3712 +                       return 0;
3713 +       }
3714 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
3715 +               if (!((opt->srr) & (!opt->is_strictroute)))
3716 +                       return 0;
3717 +       }
3718 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
3719 +               if (opt->srr)
3720 +                       return 0;
3721 +       }
3722 +       /* record route */
3723 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
3724 +               if (!opt->rr)
3725 +                       return 0;
3726 +       }
3727 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
3728 +               if (opt->rr)
3729 +                       return 0;
3730 +       }
3731 +       /* timestamp */
3732 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
3733 +               if (!opt->ts)
3734 +                       return 0;
3735 +       }
3736 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3737 +               if (opt->ts)
3738 +                       return 0;
3739 +       }
3740 +       /* router-alert option  */
3741 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3742 +               if (!opt->router_alert)
3743 +                       return 0;
3744 +       }
3745 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3746 +               if (opt->router_alert)
3747 +                       return 0;
3748 +       }
3749 +
3750 +       /* we match ! */
3751 +       return 1;
3752 +}
3753 +
3754 +static int
3755 +checkentry(const char *tablename,
3756 +          const struct ipt_ip *ip,
3757 +          void *matchinfo,
3758 +          unsigned int matchsize,
3759 +          unsigned int hook_mask)
3760 +{
3761 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3762 +       /* Check the size */
3763 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3764 +               return 0;
3765 +       /* Now check the coherence of the data ... */
3766 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3767 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3768 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3769 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3770 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3771 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3772 +               return 0; /* opposites */
3773 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3774 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3775 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3776 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3777 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3778 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3779 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3780 +               return 0; /* opposites */
3781 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3782 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3783 +               return 0; /* cannot match in the same time loose and strict source routing */
3784 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3785 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3786 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3787 +               return 0; /* opposites */
3788 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3789 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3790 +               return 0; /* opposites */
3791 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3792 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3793 +               return 0; /* opposites */
3794 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3795 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3796 +               return 0; /* opposites */
3797 +
3798 +       /* everything looks ok. */
3799 +       return 1;
3800 +}
3801 +
3802 +static struct ipt_match ipv4options_match = { 
3803 +       .name = "ipv4options",
3804 +       .match = match,
3805 +       .checkentry = checkentry,
3806 +       .me = THIS_MODULE
3807 +};
3808 +
3809 +static int __init init(void)
3810 +{
3811 +       return ipt_register_match(&ipv4options_match);
3812 +}
3813 +
3814 +static void __exit fini(void)
3815 +{
3816 +       ipt_unregister_match(&ipv4options_match);
3817 +}
3818 +
3819 +module_init(init);
3820 +module_exit(fini);
3821 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.7/net/ipv4/netfilter/ipt_mport.c
3822 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_mport.c      1970-01-01 01:00:00.000000000 +0100
3823 +++ linux-2.6.7/net/ipv4/netfilter/ipt_mport.c  2004-06-29 12:32:15.541507864 +0200
3824 @@ -0,0 +1,116 @@
3825 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3826 +   the same place so we can treat them as equal. */
3827 +#include <linux/module.h>
3828 +#include <linux/types.h>
3829 +#include <linux/udp.h>
3830 +#include <linux/skbuff.h>
3831 +
3832 +#include <linux/netfilter_ipv4/ipt_mport.h>
3833 +#include <linux/netfilter_ipv4/ip_tables.h>
3834 +
3835 +MODULE_LICENSE("GPL");
3836 +
3837 +#if 0
3838 +#define duprintf(format, args...) printk(format , ## args)
3839 +#else
3840 +#define duprintf(format, args...)
3841 +#endif
3842 +
3843 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3844 +static inline int
3845 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
3846 +{
3847 +       unsigned int i;
3848 +        unsigned int m;
3849 +        u_int16_t pflags = minfo->pflags;
3850 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
3851 +                u_int16_t s, e;
3852 +
3853 +                if (pflags & m
3854 +                    && minfo->ports[i] == 65535)
3855 +                        return 0;
3856 +
3857 +                s = minfo->ports[i];
3858 +
3859 +                if (pflags & m) {
3860 +                        e = minfo->ports[++i];
3861 +                        m <<= 1;
3862 +                } else
3863 +                        e = s;
3864 +
3865 +                if (minfo->flags & IPT_MPORT_SOURCE
3866 +                    && src >= s && src <= e)
3867 +                        return 1;
3868 +
3869 +               if (minfo->flags & IPT_MPORT_DESTINATION
3870 +                   && dst >= s && dst <= e)
3871 +                       return 1;
3872 +       }
3873 +
3874 +       return 0;
3875 +}
3876 +
3877 +static int
3878 +match(const struct sk_buff *skb,
3879 +      const struct net_device *in,
3880 +      const struct net_device *out,
3881 +      const void *matchinfo,
3882 +      int offset,
3883 +      int *hotdrop)
3884 +{
3885 +       u16 ports[2];
3886 +       const struct ipt_mport *minfo = matchinfo;
3887 +
3888 +       if (offset)
3889 +               return 0;
3890 +
3891 +       /* Must be big enough to read ports (both UDP and TCP have
3892 +           them at the start). */
3893 +       if (skb_copy_bits(skb, skb->nh.iph->ihl*4, ports, sizeof(ports)) < 0) {
3894 +               /* We've been asked to examine this packet, and we
3895 +                  can't.  Hence, no choice but to drop. */
3896 +                       duprintf("ipt_multiport:"
3897 +                                " Dropping evil offset=0 tinygram.\n");
3898 +                       *hotdrop = 1;
3899 +                       return 0;
3900 +       }
3901 +
3902 +       return ports_match(minfo, ntohs(ports[0]), ntohs(ports[1]));
3903 +}
3904 +
3905 +/* Called when user tries to insert an entry of this type. */
3906 +static int
3907 +checkentry(const char *tablename,
3908 +          const struct ipt_ip *ip,
3909 +          void *matchinfo,
3910 +          unsigned int matchsize,
3911 +          unsigned int hook_mask)
3912 +{
3913 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
3914 +               return 0;
3915 +
3916 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
3917 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
3918 +               && !(ip->invflags & IPT_INV_PROTO)
3919 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
3920 +}
3921 +
3922 +static struct ipt_match mport_match = { 
3923 +       .name = "mport",
3924 +       .match = &match,
3925 +       .checkentry = &checkentry,
3926 +       .me = THIS_MODULE
3927 +};
3928 +
3929 +static int __init init(void)
3930 +{
3931 +       return ipt_register_match(&mport_match);
3932 +}
3933 +
3934 +static void __exit fini(void)
3935 +{
3936 +       ipt_unregister_match(&mport_match);
3937 +}
3938 +
3939 +module_init(init);
3940 +module_exit(fini);
3941 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.7/net/ipv4/netfilter/ipt_nth.c
3942 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_nth.c        1970-01-01 01:00:00.000000000 +0100
3943 +++ linux-2.6.7/net/ipv4/netfilter/ipt_nth.c    2004-06-29 12:32:16.701331544 +0200
3944 @@ -0,0 +1,166 @@
3945 +/*
3946 +  This is a module which is used for match support for every Nth packet
3947 +  This file is distributed under the terms of the GNU General Public
3948 +  License (GPL). Copies of the GPL can be obtained from:
3949 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
3950 +
3951 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
3952 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
3953 +        * added support for multiple counters
3954 +        * added support for matching on individual packets
3955 +          in the counter cycle
3956 +  2004-02-19 Harald Welte <laforge@netfilter.org>
3957 +       * port to 2.6.x
3958 +
3959 +*/
3960 +
3961 +#include <linux/module.h>
3962 +#include <linux/skbuff.h>
3963 +#include <linux/ip.h>
3964 +#include <net/tcp.h>
3965 +#include <linux/spinlock.h>
3966 +#include <linux/netfilter_ipv4/ip_tables.h>
3967 +#include <linux/netfilter_ipv4/ipt_nth.h>
3968 +
3969 +MODULE_LICENSE("GPL");
3970 +MODULE_AUTHOR("Fabrice Marie <fabrice@netfilter.org>");
3971 +
3972 +/*
3973 + * State information.
3974 + */
3975 +struct state {
3976 +       spinlock_t lock;
3977 +       u_int16_t number;
3978 +};
3979 +
3980 +static struct state states[IPT_NTH_NUM_COUNTERS];
3981 +
3982 +static int
3983 +ipt_nth_match(const struct sk_buff *pskb,
3984 +             const struct net_device *in,
3985 +             const struct net_device *out,
3986 +             const void *matchinfo,
3987 +             int offset,
3988 +             int *hotdrop)
3989 +{
3990 +       /* Parameters from userspace */
3991 +       const struct ipt_nth_info *info = matchinfo;
3992 +        unsigned counter = info->counter;
3993 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
3994 +       {
3995 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3996 +               return 0;
3997 +        };
3998 +
3999 +        spin_lock(&states[counter].lock);
4000 +
4001 +        /* Are we matching every nth packet?*/
4002 +        if (info->packet == 0xFF)
4003 +        {
4004 +               /* We're matching every nth packet and only every nth packet*/
4005 +               /* Do we match or invert match? */
4006 +               if (info->not == 0)
4007 +               {
4008 +                       if (states[counter].number == 0)
4009 +                       {
4010 +                               ++states[counter].number;
4011 +                               goto match;
4012 +                       }
4013 +                       if (states[counter].number >= info->every)
4014 +                               states[counter].number = 0; /* reset the counter */
4015 +                       else
4016 +                               ++states[counter].number;
4017 +                       goto dontmatch;
4018 +               }
4019 +               else
4020 +               {
4021 +                       if (states[counter].number == 0)
4022 +                       {
4023 +                               ++states[counter].number;
4024 +                               goto dontmatch;
4025 +                       }
4026 +                       if (states[counter].number >= info->every)
4027 +                               states[counter].number = 0;
4028 +                       else
4029 +                               ++states[counter].number;
4030 +                       goto match;
4031 +               }
4032 +        }
4033 +        else
4034 +        {
4035 +               /* We're using the --packet, so there must be a rule for every value */
4036 +               if (states[counter].number == info->packet)
4037 +               {
4038 +                       /* only increment the counter when a match happens */
4039 +                       if (states[counter].number >= info->every)
4040 +                               states[counter].number = 0; /* reset the counter */
4041 +                       else
4042 +                               ++states[counter].number;
4043 +                       goto match;
4044 +               }
4045 +               else
4046 +                       goto dontmatch;
4047 +       }
4048 +
4049 + dontmatch:
4050 +       /* don't match */
4051 +       spin_unlock(&states[counter].lock);
4052 +       return 0;
4053 +
4054 + match:
4055 +       spin_unlock(&states[counter].lock);
4056 +       return 1;
4057 +}
4058 +
4059 +static int
4060 +ipt_nth_checkentry(const char *tablename,
4061 +                  const struct ipt_ip *e,
4062 +                  void *matchinfo,
4063 +                  unsigned int matchsize,
4064 +                  unsigned int hook_mask)
4065 +{
4066 +       /* Parameters from userspace */
4067 +       const struct ipt_nth_info *info = matchinfo;
4068 +        unsigned counter = info->counter;
4069 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
4070 +       {
4071 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
4072 +                       return 0;
4073 +               };
4074 +
4075 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
4076 +               printk("nth: matchsize %u != %u\n", matchsize,
4077 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
4078 +               return 0;
4079 +       }
4080 +
4081 +       states[counter].number = info->startat;
4082 +
4083 +       return 1;
4084 +}
4085 +
4086 +static struct ipt_match ipt_nth_reg = { 
4087 +       .name = "nth",
4088 +       .match = ipt_nth_match,
4089 +       .checkentry = ipt_nth_checkentry,
4090 +       .me = THIS_MODULE
4091 +};
4092 +
4093 +static int __init init(void)
4094 +{
4095 +       unsigned counter;
4096 +
4097 +       memset(&states, 0, sizeof(states));
4098 +        for (counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
4099 +               spin_lock_init(&(states[counter].lock));
4100 +
4101 +       return ipt_register_match(&ipt_nth_reg);
4102 +}
4103 +
4104 +static void __exit fini(void)
4105 +{
4106 +       ipt_unregister_match(&ipt_nth_reg);
4107 +}
4108 +
4109 +module_init(init);
4110 +module_exit(fini);
4111 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_owner.c linux-2.6.7/net/ipv4/netfilter/ipt_owner.c
4112 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_owner.c      2004-06-29 12:24:13.000000000 +0200
4113 +++ linux-2.6.7/net/ipv4/netfilter/ipt_owner.c  2004-06-29 12:35:34.494262448 +0200
4114 @@ -6,12 +6,19 @@
4115   * This program is free software; you can redistribute it and/or modify
4116   * it under the terms of the GNU General Public License version 2 as
4117   * published by the Free Software Foundation.
4118 + *
4119 + * 03/26/2003 Patrick McHardy <kaber@trash.net>        : LOCAL_IN support
4120   */
4121  
4122  #include <linux/module.h>
4123  #include <linux/skbuff.h>
4124  #include <linux/file.h>
4125 +#include <linux/ip.h>
4126 +#include <linux/tcp.h>
4127 +#include <linux/udp.h>
4128  #include <net/sock.h>
4129 +#include <net/tcp.h>
4130 +#include <net/udp.h>
4131  
4132  #include <linux/netfilter_ipv4/ipt_owner.h>
4133  #include <linux/netfilter_ipv4/ip_tables.h>
4134 @@ -21,7 +28,7 @@
4135  MODULE_DESCRIPTION("iptables owner match");
4136  
4137  static int
4138 -match_comm(const struct sk_buff *skb, const char *comm)
4139 +match_comm(const struct sock *sk, const char *comm)
4140  {
4141         struct task_struct *g, *p;
4142         struct files_struct *files;
4143 @@ -38,7 +45,7 @@
4144                         spin_lock(&files->file_lock);
4145                         for (i=0; i < files->max_fds; i++) {
4146                                 if (fcheck_files(files, i) ==
4147 -                                   skb->sk->sk_socket->file) {
4148 +                                   sk->sk_socket->file) {
4149                                         spin_unlock(&files->file_lock);
4150                                         task_unlock(p);
4151                                         read_unlock(&tasklist_lock);
4152 @@ -54,7 +61,7 @@
4153  }
4154  
4155  static int
4156 -match_pid(const struct sk_buff *skb, pid_t pid)
4157 +match_pid(const struct sock *sk, pid_t pid)
4158  {
4159         struct task_struct *p;
4160         struct files_struct *files;
4161 @@ -70,7 +77,7 @@
4162                 spin_lock(&files->file_lock);
4163                 for (i=0; i < files->max_fds; i++) {
4164                         if (fcheck_files(files, i) ==
4165 -                           skb->sk->sk_socket->file) {
4166 +                           sk->sk_socket->file) {
4167                                 spin_unlock(&files->file_lock);
4168                                 task_unlock(p);
4169                                 read_unlock(&tasklist_lock);
4170 @@ -86,10 +93,10 @@
4171  }
4172  
4173  static int
4174 -match_sid(const struct sk_buff *skb, pid_t sid)
4175 +match_sid(const struct sock *sk, pid_t sid)
4176  {
4177         struct task_struct *g, *p;
4178 -       struct file *file = skb->sk->sk_socket->file;
4179 +       struct file *file = sk->sk_socket->file;
4180         int i, found=0;
4181  
4182         read_lock(&tasklist_lock);
4183 @@ -129,41 +136,71 @@
4184        int *hotdrop)
4185  {
4186         const struct ipt_owner_info *info = matchinfo;
4187 +       struct iphdr *iph = skb->nh.iph;
4188 +       struct sock *sk = NULL;
4189 +       int ret = 0;
4190 +
4191 +       if (out) {
4192 +               sk = skb->sk;
4193 +       } else {
4194 +               if (iph->protocol == IPPROTO_TCP) {
4195 +                       struct tcphdr *tcph =
4196 +                               (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
4197 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
4198 +                                          iph->daddr, tcph->dest,
4199 +                                          skb->dev->ifindex);
4200 +                       if (sk && sk->sk_state == TCP_TIME_WAIT) {
4201 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
4202 +                               return ret;
4203 +                       }
4204 +               } else if (iph->protocol == IPPROTO_UDP) {
4205 +                       struct udphdr *udph =
4206 +                               (struct udphdr *)((u_int32_t *)iph + iph->ihl);
4207 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
4208 +                                          udph->dest, skb->dev->ifindex);
4209 +               }
4210 +       }
4211  
4212 -       if (!skb->sk || !skb->sk->sk_socket || !skb->sk->sk_socket->file)
4213 -               return 0;
4214 +       if (!sk || !sk->sk_socket || !sk->sk_socket->file)
4215 +               goto out;
4216  
4217         if(info->match & IPT_OWNER_UID) {
4218 -               if ((skb->sk->sk_socket->file->f_uid != info->uid) ^
4219 +               if ((sk->sk_socket->file->f_uid != info->uid) ^
4220                     !!(info->invert & IPT_OWNER_UID))
4221 -                       return 0;
4222 +                       goto out;
4223         }
4224  
4225         if(info->match & IPT_OWNER_GID) {
4226 -               if ((skb->sk->sk_socket->file->f_gid != info->gid) ^
4227 +               if ((sk->sk_socket->file->f_gid != info->gid) ^
4228                     !!(info->invert & IPT_OWNER_GID))
4229 -                       return 0;
4230 +                       goto out;
4231         }
4232  
4233         if(info->match & IPT_OWNER_PID) {
4234 -               if (!match_pid(skb, info->pid) ^
4235 +               if (!match_pid(sk, info->pid) ^
4236                     !!(info->invert & IPT_OWNER_PID))
4237 -                       return 0;
4238 +                       goto out;
4239         }
4240  
4241         if(info->match & IPT_OWNER_SID) {
4242 -               if (!match_sid(skb, info->sid) ^
4243 +               if (!match_sid(sk, info->sid) ^
4244                     !!(info->invert & IPT_OWNER_SID))
4245 -                       return 0;
4246 +                       goto out;
4247         }
4248  
4249         if(info->match & IPT_OWNER_COMM) {
4250 -               if (!match_comm(skb, info->comm) ^
4251 +               if (!match_comm(sk, info->comm) ^
4252                     !!(info->invert & IPT_OWNER_COMM))
4253 -                       return 0;
4254 +                       goto out;
4255         }
4256  
4257 -       return 1;
4258 +       ret = 1;
4259 +
4260 +out:
4261 +       if (in && sk)
4262 +               sock_put(sk);
4263 +
4264 +       return ret;
4265  }
4266  
4267  static int
4268 @@ -173,11 +210,19 @@
4269             unsigned int matchsize,
4270             unsigned int hook_mask)
4271  {
4272 -        if (hook_mask
4273 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
4274 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
4275 -                return 0;
4276 -        }
4277 +       if (hook_mask
4278 +           & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
4279 +           (1 << NF_IP_LOCAL_IN))) {
4280 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
4281 +                      "or POST_ROUTING.\n");
4282 +               return 0;
4283 +       }
4284 +
4285 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
4286 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
4287 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
4288 +               return 0;
4289 +       }
4290  
4291         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info))) {
4292                 printk("Matchsize %u != %Zu\n", matchsize,
4293 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_policy.c linux-2.6.7/net/ipv4/netfilter/ipt_policy.c
4294 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_policy.c     1970-01-01 01:00:00.000000000 +0100
4295 +++ linux-2.6.7/net/ipv4/netfilter/ipt_policy.c 2004-06-29 12:35:40.048418088 +0200
4296 @@ -0,0 +1,176 @@
4297 +/* IP tables module for matching IPsec policy
4298 + *
4299 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
4300 + *
4301 + * This program is free software; you can redistribute it and/or modify
4302 + * it under the terms of the GNU General Public License version 2 as
4303 + * published by the Free Software Foundation.
4304 + */
4305 +
4306 +#include <linux/kernel.h>
4307 +#include <linux/config.h>
4308 +#include <linux/module.h>
4309 +#include <linux/skbuff.h>
4310 +#include <linux/init.h>
4311 +#include <net/xfrm.h>
4312 +
4313 +#include <linux/netfilter_ipv4.h>
4314 +#include <linux/netfilter_ipv4/ipt_policy.h>
4315 +#include <linux/netfilter_ipv4/ip_tables.h>
4316 +
4317 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
4318 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
4319 +MODULE_LICENSE("GPL");
4320 +
4321 +
4322 +static inline int
4323 +match_xfrm_state(struct xfrm_state *x, const struct ipt_policy_elem *e)
4324 +{
4325 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
4326 +
4327 +       if (MISMATCH(saddr, x->props.saddr.a4 & e->smask) ||
4328 +           MISMATCH(daddr, x->id.daddr.a4 & e->dmask) ||
4329 +           MISMATCH(proto, x->id.proto) ||
4330 +           MISMATCH(mode, x->props.mode) ||
4331 +           MISMATCH(spi, x->id.spi) ||
4332 +           MISMATCH(reqid, x->props.reqid))
4333 +               return 0;
4334 +       return 1;
4335 +}
4336 +
4337 +static int
4338 +match_policy_in(const struct sk_buff *skb, const struct ipt_policy_info *info)
4339 +{
4340 +       const struct ipt_policy_elem *e;
4341 +       struct sec_path *sp = skb->sp;
4342 +       int strict = info->flags & POLICY_MATCH_STRICT;
4343 +       int i, pos;
4344 +
4345 +       if (sp == NULL)
4346 +               return -1;
4347 +       if (strict && info->len != sp->len)
4348 +               return 0;
4349 +
4350 +       for (i = sp->len - 1; i >= 0; i--) {
4351 +               pos = strict ? i - sp->len + 1 : 0;
4352 +               if (pos >= info->len)
4353 +                       return 0;
4354 +               e = &info->pol[pos];
4355 +
4356 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
4357 +                       if (!strict)
4358 +                               return 1;
4359 +               } else if (strict)
4360 +                       return 0;
4361 +       }
4362 +
4363 +       return strict ? 1 : 0;
4364 +}
4365 +
4366 +static int
4367 +match_policy_out(const struct sk_buff *skb, const struct ipt_policy_info *info)
4368 +{
4369 +       const struct ipt_policy_elem *e;
4370 +       struct dst_entry *dst = skb->dst;
4371 +       int strict = info->flags & POLICY_MATCH_STRICT;
4372 +       int i, pos;
4373 +
4374 +       if (dst->xfrm == NULL)
4375 +               return -1;
4376 +
4377 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
4378 +               pos = strict ? i : 0;
4379 +               if (pos >= info->len)
4380 +                       return 0;
4381 +               e = &info->pol[pos];
4382 +
4383 +               if (match_xfrm_state(dst->xfrm, e)) {
4384 +                       if (!strict)
4385 +                               return 1;
4386 +               } else if (strict)
4387 +                       return 0;
4388 +       }
4389 +
4390 +       return strict ? 1 : 0;
4391 +}
4392 +
4393 +static int match(const struct sk_buff *skb,
4394 +                 const struct net_device *in,
4395 +                 const struct net_device *out,
4396 +                 const void *matchinfo, int offset, int *hotdrop)
4397 +{
4398 +       const struct ipt_policy_info *info = matchinfo;
4399 +       int ret;
4400 +
4401 +       if (info->flags & POLICY_MATCH_IN)
4402 +               ret = match_policy_in(skb, info);
4403 +       else
4404 +               ret = match_policy_out(skb, info);
4405 +
4406 +       if (ret < 0) {
4407 +               if (info->flags & POLICY_MATCH_NONE)
4408 +                       ret = 1;
4409 +               else
4410 +                       ret = 0;
4411 +       } else if (info->flags & POLICY_MATCH_NONE)
4412 +               ret = 0;
4413 +
4414 +       return ret;
4415 +}
4416 +
4417 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
4418 +                      void *matchinfo, unsigned int matchsize,
4419 +                      unsigned int hook_mask)
4420 +{
4421 +       struct ipt_policy_info *info = matchinfo;
4422 +
4423 +       if (matchsize != IPT_ALIGN(sizeof(*info))) {
4424 +               printk(KERN_ERR "ipt_policy: matchsize %u != %u\n",
4425 +                      matchsize, IPT_ALIGN(sizeof(*info)));
4426 +               return 0;
4427 +       }
4428 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
4429 +               printk(KERN_ERR "ipt_policy: neither incoming nor "
4430 +                               "outgoing policy selected\n");
4431 +               return 0;
4432 +       }
4433 +       if (hook_mask & (1 << NF_IP_PRE_ROUTING | 1 << NF_IP_LOCAL_IN)
4434 +           && info->flags & POLICY_MATCH_OUT) {
4435 +               printk(KERN_ERR "ipt_policy: output policy not valid in "
4436 +                               "PRE_ROUTING and INPUT\n");
4437 +               return 0;
4438 +       }
4439 +       if (hook_mask & (1 << NF_IP_POST_ROUTING | 1 << NF_IP_LOCAL_OUT)
4440 +           && info->flags & POLICY_MATCH_IN) {
4441 +               printk(KERN_ERR "ipt_policy: input policy not valid in "
4442 +                               "POST_ROUTING and OUTPUT\n");
4443 +               return 0;
4444 +       }
4445 +       if (info->len > POLICY_MAX_ELEM) {
4446 +               printk(KERN_ERR "ipt_policy: too many policy elements\n");
4447 +               return 0;
4448 +       }
4449 +
4450 +       return 1;
4451 +}
4452 +
4453 +static struct ipt_match policy_match =
4454 +{
4455 +       .name           = "policy",
4456 +       .match          = match,
4457 +       .checkentry     = checkentry,
4458 +       .me             = THIS_MODULE,
4459 +};
4460 +
4461 +static int __init init(void)
4462 +{
4463 +       return ipt_register_match(&policy_match);
4464 +}
4465 +
4466 +static void __exit fini(void)
4467 +{
4468 +       ipt_unregister_match(&policy_match);
4469 +}
4470 +
4471 +module_init(init);
4472 +module_exit(fini);
4473 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.7/net/ipv4/netfilter/ipt_psd.c
4474 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_psd.c        1970-01-01 01:00:00.000000000 +0100
4475 +++ linux-2.6.7/net/ipv4/netfilter/ipt_psd.c    2004-06-29 12:32:18.295089256 +0200
4476 @@ -0,0 +1,358 @@
4477 +/*
4478 +  This is a module which is used for PSD (portscan detection)
4479 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
4480 +  and LOG target module.
4481 +
4482 +  Copyright (C) 2000,2001 astaro AG
4483 +
4484 +  This file is distributed under the terms of the GNU General Public
4485 +  License (GPL). Copies of the GPL can be obtained from:
4486 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
4487 +
4488 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
4489 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
4490 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
4491 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
4492 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
4493 +  2004-05-05 Martijn Lievaart <m@rtij.nl> : ported to 2.6
4494 +*/
4495 +
4496 +#include <linux/module.h>
4497 +#include <linux/skbuff.h>
4498 +#include <linux/ip.h>
4499 +#include <net/tcp.h>
4500 +#include <linux/spinlock.h>
4501 +#include <linux/netfilter_ipv4/ip_tables.h>
4502 +#include <linux/netfilter_ipv4/ipt_psd.h>
4503 +
4504 +#if 0
4505 +#define DEBUGP printk
4506 +#else
4507 +#define DEBUGP(format, args...)
4508 +#endif
4509 +
4510 +MODULE_LICENSE("GPL");
4511 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
4512 +
4513 +#define HF_DADDR_CHANGING   0x01
4514 +#define HF_SPORT_CHANGING   0x02
4515 +#define HF_TOS_CHANGING            0x04
4516 +#define HF_TTL_CHANGING            0x08
4517 +
4518 +/*
4519 + * Information we keep per each target port
4520 + */
4521 +struct port {
4522 +       u_int16_t number;      /* port number */
4523 +       u_int8_t proto;        /* protocol number */
4524 +       u_int8_t and_flags;    /* tcp ANDed flags */
4525 +       u_int8_t or_flags;     /* tcp ORed flags */
4526 +};
4527 +
4528 +/*
4529 + * Information we keep per each source address.
4530 + */
4531 +struct host {
4532 +       struct host *next;              /* Next entry with the same hash */
4533 +       clock_t timestamp;              /* Last update time */
4534 +       struct in_addr src_addr;        /* Source address */
4535 +       struct in_addr dest_addr;       /* Destination address */
4536 +       unsigned short src_port;        /* Source port */
4537 +       int count;                      /* Number of ports in the list */
4538 +       int weight;                     /* Total weight of ports in the list */
4539 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
4540 +       unsigned char tos;              /* TOS */
4541 +       unsigned char ttl;              /* TTL */
4542 +       unsigned char flags;            /* HF_ flags bitmask */
4543 +};
4544 +
4545 +/*
4546 + * State information.
4547 + */
4548 +static struct {
4549 +       spinlock_t lock;
4550 +       struct host list[LIST_SIZE];    /* List of source addresses */
4551 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
4552 +       int index;                      /* Oldest entry to be replaced */
4553 +} state;
4554 +
4555 +/*
4556 + * Convert an IP address into a hash table index.
4557 + */
4558 +static inline int hashfunc(struct in_addr addr)
4559 +{
4560 +       unsigned int value;
4561 +       int hash;
4562 +
4563 +       value = addr.s_addr;
4564 +       hash = 0;
4565 +       do {
4566 +               hash ^= value;
4567 +       } while ((value >>= HASH_LOG));
4568 +
4569 +       return hash & (HASH_SIZE - 1);
4570 +}
4571 +
4572 +static int
4573 +ipt_psd_match(const struct sk_buff *pskb,
4574 +             const struct net_device *in,
4575 +             const struct net_device *out,
4576 +             const void *matchinfo,
4577 +             int offset,
4578 +             int *hotdrop)
4579 +{
4580 +       struct iphdr *ip_hdr;
4581 +       struct tcphdr *tcp_hdr;
4582 +       struct in_addr addr;
4583 +       u_int16_t src_port,dest_port;
4584 +       u_int8_t tcp_flags, proto;
4585 +       clock_t now;
4586 +       struct host *curr, *last, **head;
4587 +       int hash, index, count;
4588 +
4589 +       /* Parameters from userspace */
4590 +       const struct ipt_psd_info *psdinfo = matchinfo;
4591 +
4592 +       /* IP header */
4593 +       ip_hdr = pskb->nh.iph;
4594 +
4595 +       /* Sanity check */
4596 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
4597 +               DEBUGP("PSD: sanity check failed\n");
4598 +               return 0;
4599 +       }
4600 +
4601 +       /* TCP or UDP ? */
4602 +       proto = ip_hdr->protocol;
4603 +
4604 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
4605 +               DEBUGP("PSD: protocol not supported\n");
4606 +               return 0;
4607 +       }
4608 +
4609 +       /* Get the source address, source & destination ports, and TCP flags */
4610 +
4611 +       addr.s_addr = ip_hdr->saddr;
4612 +
4613 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
4614 +
4615 +       /* Yep, it´s dirty */
4616 +       src_port = tcp_hdr->source;
4617 +       dest_port = tcp_hdr->dest;
4618 +
4619 +       if (proto == IPPROTO_TCP) {
4620 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
4621 +       }
4622 +       else {
4623 +               tcp_flags = 0x00;
4624 +       }
4625 +
4626 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
4627 +        * them spoof us. [DHCP needs this feature - HW] */
4628 +       if (!addr.s_addr) {
4629 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
4630 +               return 0;
4631 +       }
4632 +
4633 +       /* Use jiffies here not to depend on someone setting the time while we're
4634 +        * running; we need to be careful with possible return value overflows. */
4635 +       now = jiffies;
4636 +
4637 +       spin_lock(&state.lock);
4638 +
4639 +       /* Do we know this source address already? */
4640 +       count = 0;
4641 +       last = NULL;
4642 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
4643 +               do {
4644 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
4645 +                       count++;
4646 +                       if (curr->next) last = curr;
4647 +               } while ((curr = curr->next));
4648 +
4649 +       if (curr) {
4650 +
4651 +               /* We know this address, and the entry isn't too old. Update it. */
4652 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
4653 +                   time_after_eq(now, curr->timestamp)) {
4654 +
4655 +                       /* Just update the appropriate list entry if we've seen this port already */
4656 +                       for (index = 0; index < curr->count; index++) {
4657 +                               if (curr->ports[index].number == dest_port) {
4658 +                                       curr->ports[index].proto = proto;
4659 +                                       curr->ports[index].and_flags &= tcp_flags;
4660 +                                       curr->ports[index].or_flags |= tcp_flags;
4661 +                                       goto out_no_match;
4662 +                               }
4663 +                       }
4664 +
4665 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
4666 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
4667 +                               goto out_no_match;
4668 +
4669 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
4670 +                       curr->timestamp = now;
4671 +
4672 +                       /* Logged this scan already? Then drop the packet. */
4673 +                       if (curr->weight >= psdinfo->weight_threshold)
4674 +                               goto out_match;
4675 +
4676 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
4677 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
4678 +                               curr->flags |= HF_DADDR_CHANGING;
4679 +                       if (curr->src_port != src_port)
4680 +                               curr->flags |= HF_SPORT_CHANGING;
4681 +                       if (curr->tos != ip_hdr->tos)
4682 +                               curr->flags |= HF_TOS_CHANGING;
4683 +                       if (curr->ttl != ip_hdr->ttl)
4684 +                               curr->flags |= HF_TTL_CHANGING;
4685 +
4686 +                       /* Update the total weight */
4687 +                       curr->weight += (ntohs(dest_port) < 1024) ?
4688 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
4689 +
4690 +                       /* Got enough destination ports to decide that this is a scan? */
4691 +                       /* Then log it and drop the packet. */
4692 +                       if (curr->weight >= psdinfo->weight_threshold)
4693 +                               goto out_match;
4694 +
4695 +                       /* Remember the new port */
4696 +                       if (curr->count < SCAN_MAX_COUNT) {
4697 +                               curr->ports[curr->count].number = dest_port;
4698 +                               curr->ports[curr->count].proto = proto;
4699 +                               curr->ports[curr->count].and_flags = tcp_flags;
4700 +                               curr->ports[curr->count].or_flags = tcp_flags;
4701 +                               curr->count++;
4702 +                       }
4703 +
4704 +                       goto out_no_match;
4705 +               }
4706 +
4707 +               /* We know this address, but the entry is outdated. Mark it unused, and
4708 +                * remove from the hash table. We'll allocate a new entry instead since
4709 +                * this one might get re-used too soon. */
4710 +               curr->src_addr.s_addr = 0;
4711 +               if (last)
4712 +                       last->next = last->next->next;
4713 +               else if (*head)
4714 +                       *head = (*head)->next;
4715 +               last = NULL;
4716 +       }
4717 +
4718 +       /* We don't need an ACK from a new source address */
4719 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
4720 +               goto out_no_match;
4721 +
4722 +       /* Got too many source addresses with the same hash value? Then remove the
4723 +        * oldest one from the hash table, so that they can't take too much of our
4724 +        * CPU time even with carefully chosen spoofed IP addresses. */
4725 +       if (count >= HASH_MAX && last) last->next = NULL;
4726 +
4727 +       /* We're going to re-use the oldest list entry, so remove it from the hash
4728 +        * table first (if it is really already in use, and isn't removed from the
4729 +        * hash table already because of the HASH_MAX check above). */
4730 +
4731 +       /* First, find it */
4732 +       if (state.list[state.index].src_addr.s_addr)
4733 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
4734 +       else
4735 +               head = &last;
4736 +       last = NULL;
4737 +       if ((curr = *head))
4738 +       do {
4739 +               if (curr == &state.list[state.index]) break;
4740 +               last = curr;
4741 +       } while ((curr = curr->next));
4742 +
4743 +       /* Then, remove it */
4744 +       if (curr) {
4745 +               if (last)
4746 +                       last->next = last->next->next;
4747 +               else if (*head)
4748 +                       *head = (*head)->next;
4749 +       }
4750 +
4751 +       /* Get our list entry */
4752 +       curr = &state.list[state.index++];
4753 +       if (state.index >= LIST_SIZE) state.index = 0;
4754 +
4755 +       /* Link it into the hash table */
4756 +       head = &state.hash[hash];
4757 +       curr->next = *head;
4758 +       *head = curr;
4759 +
4760 +       /* And fill in the fields */
4761 +       curr->timestamp = now;
4762 +       curr->src_addr = addr;
4763 +       curr->dest_addr.s_addr = ip_hdr->daddr;
4764 +       curr->src_port = src_port;
4765 +       curr->count = 1;
4766 +       curr->weight = (ntohs(dest_port) < 1024) ?
4767 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
4768 +       curr->ports[0].number = dest_port;
4769 +       curr->ports[0].proto = proto;
4770 +       curr->ports[0].and_flags = tcp_flags;
4771 +       curr->ports[0].or_flags = tcp_flags;
4772 +       curr->tos = ip_hdr->tos;
4773 +       curr->ttl = ip_hdr->ttl;
4774 +
4775 +out_no_match:
4776 +       spin_unlock(&state.lock);
4777 +       return 0;
4778 +
4779 +out_match:
4780 +       spin_unlock(&state.lock);
4781 +       return 1;
4782 +}
4783 +
4784 +static int ipt_psd_checkentry(const char *tablename,
4785 +                             const struct ipt_ip *e,
4786 +                             void *matchinfo,
4787 +                             unsigned int matchsize,
4788 +                             unsigned int hook_mask)
4789 +{
4790 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
4791 +
4792 +       /* we accept TCP only */
4793 +/*     if (e->ip.proto != IPPROTO_TCP) { */
4794 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
4795 +/*             return 0; */
4796 +/*     } */
4797 +
4798 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
4799 +               DEBUGP("PSD: matchsize %u != %u\n",
4800 +                      matchsize,
4801 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
4802 +               return 0;
4803 +       }
4804 +
4805 +       return 1;
4806 +}
4807 +
4808 +static struct ipt_match ipt_psd_reg = {
4809 +       .name = "psd",
4810 +       .match = ipt_psd_match,
4811 +       .checkentry = ipt_psd_checkentry,
4812 +       .me = THIS_MODULE };
4813 +
4814 +static int __init init(void)
4815 +{
4816 +       if (ipt_register_match(&ipt_psd_reg))
4817 +               return -EINVAL;
4818 +
4819 +       memset(&state, 0, sizeof(state));
4820 +
4821 +       spin_lock_init(&(state.lock));
4822 +
4823 +       printk("netfilter PSD loaded - (c) astaro AG\n");
4824 +       return 0;
4825 +}
4826 +
4827 +static void __exit fini(void)
4828 +{
4829 +       ipt_unregister_match(&ipt_psd_reg);
4830 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
4831 +}
4832 +
4833 +module_init(init);
4834 +module_exit(fini);
4835 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.7/net/ipv4/netfilter/ipt_quota.c
4836 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_quota.c      1970-01-01 01:00:00.000000000 +0100
4837 +++ linux-2.6.7/net/ipv4/netfilter/ipt_quota.c  2004-06-29 12:32:19.479909136 +0200
4838 @@ -0,0 +1,91 @@
4839 +/* 
4840 + * netfilter module to enforce network quotas
4841 + *
4842 + * Sam Johnston <samj@samj.net>
4843 + */
4844 +#include <linux/module.h>
4845 +#include <linux/skbuff.h>
4846 +#include <linux/spinlock.h>
4847 +#include <linux/interrupt.h>
4848 +
4849 +#include <linux/netfilter_ipv4/ip_tables.h>
4850 +#include <linux/netfilter_ipv4/ipt_quota.h>
4851 +
4852 +MODULE_LICENSE("GPL");
4853 +MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
4854 +
4855 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
4856 +
4857 +static int
4858 +match(const struct sk_buff *skb,
4859 +      const struct net_device *in,
4860 +      const struct net_device *out,
4861 +      const void *matchinfo,
4862 +      int offset, int *hotdrop)
4863 +{
4864 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
4865 +       unsigned int datalen;
4866 +
4867 +       if (skb->len < sizeof(struct iphdr))
4868 +               return NF_ACCEPT;
4869 +       
4870 +       datalen = skb->len - skb->nh.iph->ihl*4;
4871 +
4872 +        spin_lock_bh(&quota_lock);
4873 +
4874 +        if (q->quota >= datalen) {
4875 +                /* we can afford this one */
4876 +                q->quota -= datalen;
4877 +                spin_unlock_bh(&quota_lock);
4878 +
4879 +#ifdef DEBUG_IPT_QUOTA
4880 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
4881 +#endif
4882 +                return 1;
4883 +        }
4884 +
4885 +        /* so we do not allow even small packets from now on */
4886 +        q->quota = 0;
4887 +
4888 +#ifdef DEBUG_IPT_QUOTA
4889 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
4890 +#endif
4891 +
4892 +        spin_unlock_bh(&quota_lock);
4893 +        return 0;
4894 +}
4895 +
4896 +static int
4897 +checkentry(const char *tablename,
4898 +           const struct ipt_ip *ip,
4899 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
4900 +{
4901 +        /* TODO: spinlocks? sanity checks? */
4902 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
4903 +                return 0;
4904 +
4905 +        return 1;
4906 +}
4907 +
4908 +static struct ipt_match quota_match = {
4909 +       .name = "quota",
4910 +       .match = match,
4911 +       .checkentry = checkentry,
4912 +       .me = THIS_MODULE
4913 +};
4914 +
4915 +static int __init
4916 +init(void)
4917 +{
4918 +        return ipt_register_match(&quota_match);
4919 +}
4920 +
4921 +static void __exit
4922 +fini(void)
4923 +{
4924 +        ipt_unregister_match(&quota_match);
4925 +}
4926 +
4927 +module_init(init);
4928 +module_exit(fini);
4929 +
4930 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_string.c linux-2.6.7/net/ipv4/netfilter/ipt_string.c
4931 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_string.c     1970-01-01 01:00:00.000000000 +0100
4932 +++ linux-2.6.7/net/ipv4/netfilter/ipt_string.c 2004-06-29 12:36:14.591166792 +0200
4933 @@ -0,0 +1,183 @@
4934 +/* Kernel module to match a string into a packet.
4935 + *
4936 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
4937 + * 
4938 + * ChangeLog
4939 + *     24.03.2004: Eric Lauriault <elauri@lacitec.on.ca>
4940 + *             Initial 2.6 port
4941 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
4942 + *             Fixed SMP re-entrancy problem using per-cpu data areas
4943 + *             for the skip/shift tables.
4944 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
4945 + *             Fixed kernel panic, due to overrunning boyer moore string
4946 + *             tables. Also slightly tweaked heuristic for deciding what
4947 + *             search algo to use.
4948 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
4949 + *             Implemented Boyer Moore Sublinear search algorithm
4950 + *             alongside the existing linear search based on memcmp().
4951 + *             Also a quick check to decide which method to use on a per
4952 + *             packet basis.
4953 + */
4954 +
4955 +#include <linux/smp.h>
4956 +#include <linux/percpu.h>
4957 +#include <linux/module.h>
4958 +#include <linux/skbuff.h>
4959 +#include <linux/file.h>
4960 +#include <net/sock.h>
4961 +
4962 +#include <linux/netfilter_ipv4/ip_tables.h>
4963 +#include <linux/netfilter_ipv4/ipt_string.h>
4964 +
4965 +MODULE_LICENSE("GPL");
4966 +
4967 +struct string_per_cpu {
4968 +       int skip[BM_MAX_HLEN];
4969 +       int shift[BM_MAX_HLEN];
4970 +       int len[BM_MAX_HLEN];
4971 +};
4972 +
4973 +static DEFINE_PER_CPU(struct string_per_cpu, bm_string_data);
4974 +
4975 +
4976 +/* Boyer Moore Sublinear string search - VERY FAST */
4977 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
4978 +{
4979 +       int M1, right_end, sk, sh;  
4980 +       int ended, j, i;
4981 +
4982 +       int *skip, *shift, *len;
4983 +       
4984 +       /* use data suitable for this CPU */
4985 +       shift=__get_cpu_var(bm_string_data).shift;
4986 +       skip=__get_cpu_var(bm_string_data).skip;
4987 +       len=__get_cpu_var(bm_string_data).len;
4988 +       
4989 +       /* Setup skip/shift tables */
4990 +       M1 = right_end = needle_len-1;
4991 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
4992 +       for (i = 0; needle[i]; i++) skip[(int)needle[i]] = M1 - i;
4993 +
4994 +       for (i = 1; i < needle_len; i++) {   
4995 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
4996 +               len[i] = j;  
4997 +       }  
4998 +
4999 +       shift[0] = 1;  
5000 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
5001 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
5002 +       ended = 0;  
5003 +       
5004 +       for (i = 0; i < needle_len; i++) {  
5005 +               if (len[i] == M1 - i) ended = i;  
5006 +               if (ended) shift[i] = ended;  
5007 +       }  
5008 +
5009 +       /* Do the search*/  
5010 +       while (right_end < haystack_len)
5011 +       {
5012 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
5013 +               if (i == needle_len) {
5014 +                       return haystack+(right_end - M1);
5015 +               }
5016 +               
5017 +               sk = skip[(int)haystack[right_end - i]];  
5018 +               sh = shift[i];
5019 +               right_end = max(right_end - i + sk, right_end + sh);  
5020 +       }
5021 +
5022 +       return NULL;
5023 +}  
5024 +
5025 +/* Linear string search based on memcmp() */
5026 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
5027 +{
5028 +       char *k = haystack + (haystack_len-needle_len);
5029 +       char *t = haystack;
5030 +       
5031 +       while ( t <= k ) {
5032 +               if (memcmp(t, needle, needle_len) == 0)
5033 +                       return t;
5034 +               t++;
5035 +       }
5036 +
5037 +       return NULL;
5038 +}
5039 +
5040 +static int
5041 +match(const struct sk_buff *skb,
5042 +      const struct net_device *in,
5043 +      const struct net_device *out,
5044 +      const void *matchinfo,
5045 +      int offset,
5046 +      int *hotdrop)
5047 +{
5048 +       const struct ipt_string_info *info = matchinfo;
5049 +       struct iphdr *ip = skb->nh.iph;
5050 +       int hlen, nlen;
5051 +       char *needle, *haystack;
5052 +       proc_ipt_search search=search_linear;
5053 +
5054 +       if ( !ip ) return 0;
5055 +
5056 +       /* get lenghts, and validate them */
5057 +       nlen=info->len;
5058 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
5059 +       if ( nlen > hlen ) return 0;
5060 +
5061 +       needle=(char *)&info->string;
5062 +       haystack=(char *)ip+(ip->ihl*4);
5063 +
5064 +       /* The sublinear search comes in to its own
5065 +        * on the larger packets */
5066 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
5067 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
5068 +               if ( hlen < BM_MAX_HLEN ) {
5069 +                       search=search_sublinear;
5070 +               }else{
5071 +                       if (net_ratelimit())
5072 +                               printk(KERN_INFO "ipt_string: Packet too big "
5073 +                                       "to attempt sublinear string search "
5074 +                                       "(%d bytes)\n", hlen );
5075 +               }
5076 +       }
5077 +       
5078 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
5079 +}
5080 +
5081 +static int
5082 +checkentry(const char *tablename,
5083 +           const struct ipt_ip *ip,
5084 +           void *matchinfo,
5085 +           unsigned int matchsize,
5086 +           unsigned int hook_mask)
5087 +{
5088 +
5089 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
5090 +               return 0;
5091 +
5092 +       return 1;
5093 +}
5094 +
5095 +static struct ipt_match string_match = {
5096 +    .name = "string",
5097 +    .match = &match,
5098 +    .checkentry = &checkentry,
5099 +    .me = THIS_MODULE
5100 +};
5101 +
5102 +
5103 +static int __init init(void)
5104 +{
5105 +       return ipt_register_match(&string_match);
5106 +}
5107 +
5108 +static void __exit fini(void)
5109 +{
5110 +       ipt_unregister_match(&string_match);
5111 +}
5112 +
5113 +module_init(init);
5114 +module_exit(fini);
5115 +
5116 +
5117 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c linux-2.6.7/net/ipv4/netfilter/ipt_time.c
5118 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_time.c       1970-01-01 01:00:00.000000000 +0100
5119 +++ linux-2.6.7/net/ipv4/netfilter/ipt_time.c   2004-06-29 12:32:41.027633384 +0200
5120 @@ -0,0 +1,189 @@
5121 +/*
5122 +  This is a module which is used for time matching
5123 +  It is using some modified code from dietlibc (localtime() function)
5124 +  that you can find at http://www.fefe.de/dietlibc/
5125 +  This file is distributed under the terms of the GNU General Public
5126 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
5127 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
5128 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
5129 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
5130 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
5131 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
5132 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
5133 +  2004-05-02 Fabrice : added support for date matching, from an idea of Fabien COELHO.
5134 +*/
5135 +
5136 +#include <linux/module.h>
5137 +#include <linux/skbuff.h>
5138 +#include <linux/netfilter_ipv4/ip_tables.h>
5139 +#include <linux/netfilter_ipv4/ipt_time.h>
5140 +#include <linux/time.h>
5141 +
5142 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5143 +MODULE_DESCRIPTION("Match arrival timestamp/date");
5144 +MODULE_LICENSE("GPL");
5145 +
5146 +struct tm
5147 +{
5148 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
5149 +       int tm_min;                   /* Minutes.     [0-59] */
5150 +       int tm_hour;                  /* Hours.       [0-23] */
5151 +       int tm_mday;                  /* Day.         [1-31] */
5152 +       int tm_mon;                   /* Month.       [0-11] */
5153 +       int tm_year;                  /* Year - 1900.  */
5154 +       int tm_wday;                  /* Day of week. [0-6] */
5155 +       int tm_yday;                  /* Days in year.[0-365] */
5156 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
5157 +
5158 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
5159 +       const char *tm_zone;          /* we don't care, we count from GMT */
5160 +};
5161 +
5162 +void
5163 +localtime(const time_t *timepr, struct tm *r);
5164 +
5165 +static int
5166 +match(const struct sk_buff *skb,
5167 +      const struct net_device *in,
5168 +      const struct net_device *out,
5169 +      const void *matchinfo,
5170 +      int offset,
5171 +      const void *hdr,
5172 +      u_int16_t datalen,
5173 +      int *hotdrop)
5174 +{
5175 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
5176 +       struct tm currenttime;                          /* time human readable */
5177 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
5178 +       u_int16_t packet_time;
5179 +       struct timeval kerneltimeval;
5180 +       time_t packet_local_time;
5181 +
5182 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
5183 +       if (info->kerneltime)
5184 +       {
5185 +               do_gettimeofday(&kerneltimeval);
5186 +               packet_local_time = kerneltimeval.tv_sec;
5187 +       }
5188 +       else
5189 +               packet_local_time = skb->stamp.tv_sec;
5190 +
5191 +       /* First we make sure we are in the date start-stop boundaries */
5192 +       if ((packet_local_time < info->date_start) || (packet_local_time > info->date_stop))
5193 +               return 0; /* We are outside the date boundaries */
5194 +
5195 +       /* Transform the timestamp of the packet, in a human readable form */
5196 +       localtime(&packet_local_time, &currenttime);
5197 +
5198 +       /* check if we match this timestamp, we start by the days... */
5199 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
5200 +               return 0; /* the day doesn't match */
5201 +
5202 +       /* ... check the time now */
5203 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
5204 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
5205 +               return 0;
5206 +
5207 +       /* here we match ! */
5208 +       return 1;
5209 +}
5210 +
5211 +static int
5212 +checkentry(const char *tablename,
5213 +           const struct ipt_ip *ip,
5214 +           void *matchinfo,
5215 +           unsigned int matchsize,
5216 +           unsigned int hook_mask)
5217 +{
5218 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
5219 +
5220 +       /* First, check that we are in the correct hooks */
5221 +       if (hook_mask
5222 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5223 +       {
5224 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
5225 +               return 0;
5226 +       }
5227 +       /* we use the kerneltime if we are in forward or output */
5228 +       info->kerneltime = 1;
5229 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
5230 +               /* we use the skb time */
5231 +               info->kerneltime = 0;
5232 +
5233 +       /* Check the size */
5234 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
5235 +               return 0;
5236 +       /* Now check the coherence of the data ... */
5237 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
5238 +           (info->time_stop  > 1439))
5239 +       {
5240 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
5241 +               return 0;
5242 +       }
5243 +
5244 +       return 1;
5245 +}
5246 +
5247 +static struct ipt_match time_match
5248 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
5249 +
5250 +static int __init init(void)
5251 +{
5252 +       printk("ipt_time loading\n");
5253 +       return ipt_register_match(&time_match);
5254 +}
5255 +
5256 +static void __exit fini(void)
5257 +{
5258 +       ipt_unregister_match(&time_match);
5259 +       printk("ipt_time unloaded\n");
5260 +}
5261 +
5262 +module_init(init);
5263 +module_exit(fini);
5264 +
5265 +
5266 +/* The part below is borowed and modified from dietlibc */
5267 +
5268 +/* seconds per day */
5269 +#define SPD 24*60*60
5270 +
5271 +void
5272 +localtime(const time_t *timepr, struct tm *r) {
5273 +       time_t i;
5274 +       time_t timep;
5275 +       extern struct timezone sys_tz;
5276 +       const unsigned int __spm[12] =
5277 +               { 0,
5278 +                 (31),
5279 +                 (31+28),
5280 +                 (31+28+31),
5281 +                 (31+28+31+30),
5282 +                 (31+28+31+30+31),
5283 +                 (31+28+31+30+31+30),
5284 +                 (31+28+31+30+31+30+31),
5285 +                 (31+28+31+30+31+30+31+31),
5286 +                 (31+28+31+30+31+30+31+31+30),
5287 +                 (31+28+31+30+31+30+31+31+30+31),
5288 +                 (31+28+31+30+31+30+31+31+30+31+30),
5289 +               };
5290 +       register time_t work;
5291 +
5292 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
5293 +       work=timep%(SPD);
5294 +       r->tm_sec=work%60; work/=60;
5295 +       r->tm_min=work%60; r->tm_hour=work/60;
5296 +       work=timep/(SPD);
5297 +       r->tm_wday=(4+work)%7;
5298 +       for (i=1970; ; ++i) {
5299 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
5300 +               if (work>k)
5301 +                       work-=k;
5302 +               else
5303 +                       break;
5304 +       }
5305 +       r->tm_year=i-1900;
5306 +       for (i=11; i && __spm[i]>work; --i) ;
5307 +       r->tm_mon=i;
5308 +       r->tm_mday=work-__spm[i]+1;
5309 +}
5310 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/netfilter/ipt_unclean.c linux-2.6.7/net/ipv4/netfilter/ipt_unclean.c
5311 --- linux-2.6.7.org/net/ipv4/netfilter/ipt_unclean.c    1970-01-01 01:00:00.000000000 +0100
5312 +++ linux-2.6.7/net/ipv4/netfilter/ipt_unclean.c        2004-06-29 12:36:11.004712016 +0200
5313 @@ -0,0 +1,604 @@
5314 +/* Kernel module to match suspect packets. */
5315 +#include <linux/module.h>
5316 +#include <linux/skbuff.h>
5317 +#include <net/ip.h>
5318 +#include <linux/udp.h>
5319 +#include <linux/tcp.h>
5320 +#include <linux/icmp.h>
5321 +#include <net/checksum.h>
5322 +
5323 +#include <linux/netfilter_ipv4/ip_tables.h>
5324 +
5325 +#define limpk(format, args...)                                          \
5326 +do {                                                                    \
5327 +       if (net_ratelimit())                                             \
5328 +               printk("ipt_unclean: %s" format,                         \
5329 +                      embedded ? "(embedded packet) " : "" , ## args);  \
5330 +} while(0)
5331 +
5332 +enum icmp_error_status
5333 +{
5334 +       ICMP_MAY_BE_ERROR,
5335 +       ICMP_IS_ERROR,
5336 +       ICMP_NOT_ERROR
5337 +};
5338 +
5339 +struct icmp_info
5340 +{
5341 +       size_t min_len, max_len;
5342 +       enum icmp_error_status err;
5343 +       u_int8_t min_code, max_code;
5344 +};
5345 +
5346 +static int
5347 +check_ip(struct iphdr *iph, size_t length, int embedded);
5348 +
5349 +/* ICMP-specific checks. */
5350 +static int
5351 +check_icmp(const struct icmphdr *icmph,
5352 +          u_int16_t datalen,
5353 +          unsigned int offset,
5354 +          int more_frags,
5355 +          int embedded)
5356 +{
5357 +       static struct icmp_info info[]
5358 +               = { [ICMP_ECHOREPLY]
5359 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
5360 +                   [ICMP_DEST_UNREACH]
5361 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 15 },
5362 +                   [ICMP_SOURCE_QUENCH]
5363 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 0 },
5364 +                   [ICMP_REDIRECT]
5365 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 3 },
5366 +                   [ICMP_ECHO]
5367 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0  },
5368 +                   /* Router advertisement. */
5369 +                   [9]
5370 +                   = { 8, 8 + 255 * 8, ICMP_NOT_ERROR, 0, 0 },
5371 +                   /* Router solicitation. */
5372 +                   [10]
5373 +                   = { 8, 8, ICMP_NOT_ERROR, 0, 0 },
5374 +                   [ICMP_TIME_EXCEEDED]
5375 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1  },
5376 +                   [ICMP_PARAMETERPROB]
5377 +                   = { 8 + 28, 65536, ICMP_IS_ERROR, 0, 1 },
5378 +                   [ICMP_TIMESTAMP]
5379 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
5380 +                   [ICMP_TIMESTAMPREPLY]
5381 +                   = { 20, 20, ICMP_NOT_ERROR, 0, 0 },
5382 +                   [ICMP_INFO_REQUEST]
5383 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
5384 +                   [ICMP_INFO_REPLY]
5385 +                   = { 8, 65536, ICMP_NOT_ERROR, 0, 0 },
5386 +                   [ICMP_ADDRESS]
5387 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 },
5388 +                   [ICMP_ADDRESSREPLY]
5389 +                   = { 12, 12, ICMP_NOT_ERROR, 0, 0 } };
5390 +
5391 +       /* Can't do anything if it's a fragment. */
5392 +       if (offset)
5393 +               return 1;
5394 +
5395 +       /* Must cover type and code. */
5396 +       if (datalen < 2) {
5397 +               limpk("ICMP len=%u too short\n", datalen);
5398 +               return 0;
5399 +       }
5400 +
5401 +       /* If not embedded. */
5402 +       if (!embedded) {
5403 +               /* Bad checksum?  Don't print, just ignore. */
5404 +               if (!more_frags
5405 +                   && ip_compute_csum((unsigned char *) icmph, datalen) != 0)
5406 +                       return 0;
5407 +
5408 +               /* CHECK: Truncated ICMP (even if first fragment). */
5409 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
5410 +                   && info[icmph->type].min_len != 0
5411 +                   && datalen < info[icmph->type].min_len) {
5412 +                       limpk("ICMP type %u len %u too short\n",
5413 +                             icmph->type, datalen);
5414 +                       return 0;
5415 +               }
5416 +
5417 +               /* CHECK: Check within known error ICMPs. */
5418 +               if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
5419 +                   && info[icmph->type].err == ICMP_IS_ERROR) {
5420 +                       /* CHECK: Embedded packet must be at least
5421 +                          length of iph + 8 bytes. */
5422 +                       struct iphdr *inner = (void *)icmph + 8;
5423 +
5424 +                       /* datalen > 8 since all ICMP_IS_ERROR types
5425 +                           have min length > 8 */
5426 +                       if (datalen - 8 < sizeof(struct iphdr)) {
5427 +                               limpk("ICMP error internal way too short\n");
5428 +                               return 0;
5429 +                       }
5430 +                       if (datalen - 8 < inner->ihl*4 + 8) {
5431 +                               limpk("ICMP error internal too short\n");
5432 +                               return 0;
5433 +                       }
5434 +                       if (!check_ip(inner, datalen - 8, 1))
5435 +                               return 0;
5436 +               }
5437 +       } else {
5438 +               /* CHECK: Can't embed ICMP unless known non-error. */
5439 +               if (icmph->type >= sizeof(info)/sizeof(struct icmp_info)
5440 +                   || info[icmph->type].err != ICMP_NOT_ERROR) {
5441 +                       limpk("ICMP type %u not embeddable\n",
5442 +                             icmph->type);
5443 +                       return 0;
5444 +               }
5445 +       }
5446 +
5447 +       /* CHECK: Invalid ICMP codes. */
5448 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
5449 +           && (icmph->code < info[icmph->type].min_code
5450 +               || icmph->code > info[icmph->type].max_code)) {
5451 +               limpk("ICMP type=%u code=%u\n",
5452 +                     icmph->type, icmph->code);
5453 +               return 0;
5454 +       }
5455 +
5456 +       /* CHECK: Above maximum length. */
5457 +       if (icmph->type < sizeof(info)/sizeof(struct icmp_info)
5458 +           && info[icmph->type].max_len != 0
5459 +           && datalen > info[icmph->type].max_len) {
5460 +               limpk("ICMP type=%u too long: %u bytes\n",
5461 +                     icmph->type, datalen);
5462 +               return 0;
5463 +       }
5464 +
5465 +       switch (icmph->type) {
5466 +       case ICMP_PARAMETERPROB: {
5467 +               /* CHECK: Problem param must be within error packet's
5468 +                * IP header. */
5469 +               struct iphdr *iph = (void *)icmph + 8;
5470 +               u_int32_t arg = ntohl(icmph->un.gateway);
5471 +
5472 +               if (icmph->code == 0) {
5473 +                       /* Code 0 means that upper 8 bits is pointer
5474 +                           to problem. */
5475 +                       if ((arg >> 24) >= iph->ihl*4) {
5476 +                               limpk("ICMP PARAMETERPROB ptr = %u\n",
5477 +                                     ntohl(icmph->un.gateway) >> 24);
5478 +                               return 0;
5479 +                       }
5480 +                       arg &= 0x00FFFFFF;
5481 +               }
5482 +
5483 +               /* CHECK: Rest must be zero. */
5484 +               if (arg) {
5485 +                       limpk("ICMP PARAMETERPROB nonzero arg = %u\n",
5486 +                             arg);
5487 +                       return 0;
5488 +               }
5489 +               break;
5490 +       }
5491 +
5492 +       case ICMP_TIME_EXCEEDED:
5493 +       case ICMP_SOURCE_QUENCH:
5494 +               /* CHECK: Unused must be zero. */
5495 +               if (icmph->un.gateway != 0) {
5496 +                       limpk("ICMP type=%u unused = %u\n",
5497 +                             icmph->type, ntohl(icmph->un.gateway));
5498 +                       return 0;
5499 +               }
5500 +               break;
5501 +       }
5502 +
5503 +       return 1;
5504 +}
5505 +
5506 +/* UDP-specific checks. */
5507 +static int
5508 +check_udp(const struct iphdr *iph,
5509 +         const struct udphdr *udph,
5510 +         u_int16_t datalen,
5511 +         unsigned int offset,
5512 +         int more_frags,
5513 +         int embedded)
5514 +{
5515 +       /* Can't do anything if it's a fragment. */
5516 +       if (offset)
5517 +               return 1;
5518 +
5519 +       /* CHECK: Must cover UDP header. */
5520 +       if (datalen < sizeof(struct udphdr)) {
5521 +               limpk("UDP len=%u too short\n", datalen);
5522 +               return 0;
5523 +       }
5524 +
5525 +       /* Bad checksum?  Don't print, just say it's unclean. */
5526 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
5527 +       if (!more_frags && !embedded && udph->check
5528 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP,
5529 +                                csum_partial((char *)udph, datalen, 0)) != 0)
5530 +               return 0;
5531 +
5532 +       /* CHECK: Destination port can't be zero. */
5533 +       if (!udph->dest) {
5534 +               limpk("UDP zero destination port\n");
5535 +               return 0;
5536 +       }
5537 +
5538 +       if (!more_frags) {
5539 +               if (!embedded) {
5540 +                       /* CHECK: UDP length must match. */
5541 +                       if (ntohs(udph->len) != datalen) {
5542 +                               limpk("UDP len too short %u vs %u\n",
5543 +                                     ntohs(udph->len), datalen);
5544 +                               return 0;
5545 +                       }
5546 +               } else {
5547 +                       /* CHECK: UDP length be >= this truncated pkt. */
5548 +                       if (ntohs(udph->len) < datalen) {
5549 +                               limpk("UDP len too long %u vs %u\n",
5550 +                                     ntohs(udph->len), datalen);
5551 +                               return 0;
5552 +                       }
5553 +               }
5554 +       } else {
5555 +               /* CHECK: UDP length must be > this frag's length. */
5556 +               if (ntohs(udph->len) <= datalen) {
5557 +                       limpk("UDP fragment len too short %u vs %u\n",
5558 +                             ntohs(udph->len), datalen);
5559 +                       return 0;
5560 +               }
5561 +       }
5562 +
5563 +       return 1;
5564 +}
5565 +
5566 +#define        TH_FIN  0x01
5567 +#define        TH_SYN  0x02
5568 +#define        TH_RST  0x04
5569 +#define        TH_PUSH 0x08
5570 +#define        TH_ACK  0x10
5571 +#define        TH_URG  0x20
5572 +#define        TH_ECE  0x40
5573 +#define        TH_CWR  0x80
5574 +
5575 +/* table of valid flag combinations - ECE and CWR are always valid */
5576 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
5577 +{
5578 +       [TH_SYN]                        = 1,
5579 +       [TH_SYN|TH_ACK]                 = 1,
5580 +       [TH_RST]                        = 1,
5581 +       [TH_RST|TH_ACK]                 = 1,
5582 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
5583 +       [TH_FIN|TH_ACK]                 = 1,
5584 +       [TH_ACK]                        = 1,
5585 +       [TH_ACK|TH_PUSH]                = 1,
5586 +       [TH_ACK|TH_URG]                 = 1,
5587 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
5588 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
5589 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
5590 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
5591 +};
5592 +
5593 +/* TCP-specific checks. */
5594 +static int
5595 +check_tcp(const struct iphdr *iph,
5596 +         const struct tcphdr *tcph,
5597 +         u_int16_t datalen,
5598 +         unsigned int offset,
5599 +         int more_frags,
5600 +         int embedded)
5601 +{
5602 +       u_int8_t *opt = (u_int8_t *)tcph;
5603 +       u_int8_t *endhdr = (u_int8_t *)tcph + tcph->doff * 4;
5604 +       u_int8_t tcpflags;
5605 +       int end_of_options = 0;
5606 +       size_t i;
5607 +
5608 +       /* CHECK: Can't have offset=1: used to override TCP syn-checks. */
5609 +       /* In fact, this is caught below (offset < 516). */
5610 +
5611 +       /* Can't do anything if it's a fragment. */
5612 +       if (offset)
5613 +               return 1;
5614 +
5615 +       /* CHECK: Smaller than minimal TCP hdr. */
5616 +       if (datalen < sizeof(struct tcphdr)) {
5617 +               if (!embedded) {
5618 +                       limpk("Packet length %u < TCP header.\n", datalen);
5619 +                       return 0;
5620 +               }
5621 +               /* Must have ports available (datalen >= 8), from
5622 +                   check_icmp which set embedded = 1 */
5623 +               /* CHECK: TCP ports inside ICMP error */
5624 +               if (!tcph->source || !tcph->dest) {
5625 +                       limpk("Zero TCP ports %u/%u.\n",
5626 +                             htons(tcph->source), htons(tcph->dest));
5627 +                       return 0;
5628 +               }
5629 +               return 1;
5630 +       }
5631 +
5632 +       /* CHECK: Smaller than actual TCP hdr. */
5633 +       if (datalen < tcph->doff * 4) {
5634 +               if (!embedded) {
5635 +                       limpk("Packet length %u < actual TCP header.\n",
5636 +                             datalen);
5637 +                       return 0;
5638 +               } else
5639 +                       return 1;
5640 +       }
5641 +
5642 +       /* Bad checksum?  Don't print, just say it's unclean. */
5643 +       /* FIXME: SRC ROUTE packets won't match checksum --RR */
5644 +       if (!more_frags && !embedded
5645 +           && csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_TCP,
5646 +                                csum_partial((char *)tcph, datalen, 0)) != 0)
5647 +               return 0;
5648 +
5649 +       /* CHECK: TCP ports non-zero */
5650 +       if (!tcph->source || !tcph->dest) {
5651 +               limpk("Zero TCP ports %u/%u.\n",
5652 +                     htons(tcph->source), htons(tcph->dest));
5653 +               return 0;
5654 +       }
5655 +
5656 +       /* CHECK: TCP reserved bits zero. */
5657 +       if(tcp_flag_word(tcph) & TCP_RESERVED_BITS) {
5658 +               limpk("TCP reserved bits not zero\n");
5659 +               return 0;
5660 +       }
5661 +
5662 +       /* CHECK: TCP flags. */
5663 +       tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
5664 +       if (!tcp_valid_flags[tcpflags]) {
5665 +               limpk("TCP flags bad: %u\n", tcpflags);
5666 +               return 0;
5667 +       }
5668 +
5669 +       for (i = sizeof(struct tcphdr); i < tcph->doff * 4; ) {
5670 +               switch (opt[i]) {
5671 +               case 0:
5672 +                       end_of_options = 1;
5673 +                       i++;
5674 +                       break;
5675 +               case 1:
5676 +                       i++;
5677 +                       break;
5678 +               default:
5679 +                       /* CHECK: options after EOO. */
5680 +                       if (end_of_options) {
5681 +                               limpk("TCP option %u after end\n",
5682 +                                     opt[i]);
5683 +                               return 0;
5684 +                       }
5685 +                       /* CHECK: options at tail. */
5686 +                       else if (i+1 >= tcph->doff * 4) {
5687 +                               limpk("TCP option %u at tail\n",
5688 +                                     opt[i]);
5689 +                               return 0;
5690 +                       }
5691 +                       /* CHECK: zero-length options. */
5692 +                       else if (opt[i+1] == 0) {
5693 +                               limpk("TCP option %u 0 len\n",
5694 +                                     opt[i]);
5695 +                               return 0;
5696 +                       }
5697 +                       /* CHECK: oversize options. */
5698 +                       else if (&opt[i] + opt[i+1] > endhdr) {
5699 +                               limpk("TCP option %u at %Zu too long\n",
5700 +                                     (unsigned int) opt[i], i);
5701 +                               return 0;
5702 +                       }
5703 +                       /* Move to next option */
5704 +                       i += opt[i+1];
5705 +               }
5706 +       }
5707 +
5708 +       return 1;
5709 +}
5710 +
5711 +/* Returns 1 if ok */
5712 +/* Standard IP checks. */
5713 +static int
5714 +check_ip(struct iphdr *iph, size_t length, int embedded)
5715 +{
5716 +       u_int8_t *opt = (u_int8_t *)iph;
5717 +       u_int8_t *endhdr = (u_int8_t *)iph + iph->ihl * 4;
5718 +       int end_of_options = 0;
5719 +       void *protoh;
5720 +       size_t datalen;
5721 +       unsigned int i;
5722 +       unsigned int offset;
5723 +
5724 +       /* Should only happen for local outgoing raw-socket packets. */
5725 +       /* CHECK: length >= ip header. */
5726 +       if (length < sizeof(struct iphdr) || length < iph->ihl * 4) {
5727 +               limpk("Packet length %Zu < IP header.\n", length);
5728 +               return 0;
5729 +       }
5730 +
5731 +       offset = ntohs(iph->frag_off) & IP_OFFSET;
5732 +       protoh = (void *)iph + iph->ihl * 4;
5733 +       datalen = length - iph->ihl * 4;
5734 +
5735 +       /* CHECK: Embedded fragment. */
5736 +       if (embedded && offset) {
5737 +               limpk("Embedded fragment.\n");
5738 +               return 0;
5739 +       }
5740 +
5741 +       for (i = sizeof(struct iphdr); i < iph->ihl * 4; ) {
5742 +               switch (opt[i]) {
5743 +               case 0:
5744 +                       end_of_options = 1;
5745 +                       i++;
5746 +                       break;
5747 +               case 1:
5748 +                       i++;
5749 +                       break;
5750 +               default:
5751 +                       /* CHECK: options after EOO. */
5752 +                       if (end_of_options) {
5753 +                               limpk("IP option %u after end\n",
5754 +                                     opt[i]);
5755 +                               return 0;
5756 +                       }
5757 +                       /* CHECK: options at tail. */
5758 +                       else if (i+1 >= iph->ihl * 4) {
5759 +                               limpk("IP option %u at tail\n",
5760 +                                     opt[i]);
5761 +                               return 0;
5762 +                       }
5763 +                       /* CHECK: zero-length or one-length options. */
5764 +                       else if (opt[i+1] < 2) {
5765 +                               limpk("IP option %u %u len\n",
5766 +                                     opt[i], opt[i+1]);
5767 +                               return 0;
5768 +                       }
5769 +                       /* CHECK: oversize options. */
5770 +                       else if (&opt[i] + opt[i+1] > endhdr) {
5771 +                               limpk("IP option %u at %u too long\n",
5772 +                                     opt[i], i);
5773 +                               return 0;
5774 +                       }
5775 +                       /* Move to next option */
5776 +                       i += opt[i+1];
5777 +               }
5778 +       }
5779 +
5780 +       /* Fragment checks. */
5781 +
5782 +       /* CHECK: More fragments, but doesn't fill 8-byte boundary. */
5783 +       if ((ntohs(iph->frag_off) & IP_MF)
5784 +           && (ntohs(iph->tot_len) % 8) != 0) {
5785 +               limpk("Truncated fragment %u long.\n", ntohs(iph->tot_len));
5786 +               return 0;
5787 +       }
5788 +
5789 +       /* CHECK: Oversize fragment a-la Ping of Death. */
5790 +       if (offset * 8 + datalen > 65535) {
5791 +               limpk("Oversize fragment to %u.\n", offset * 8);
5792 +               return 0;
5793 +       }
5794 +
5795 +       /* CHECK: DF set and offset or MF set. */
5796 +       if ((ntohs(iph->frag_off) & IP_DF)
5797 +           && (offset || (ntohs(iph->frag_off) & IP_MF))) {
5798 +               limpk("DF set and offset=%u, MF=%u.\n",
5799 +                     offset, ntohs(iph->frag_off) & IP_MF);
5800 +               return 0;
5801 +       }
5802 +
5803 +       /* CHECK: Zero-sized fragments. */
5804 +       if ((offset || (ntohs(iph->frag_off) & IP_MF))
5805 +           && datalen == 0) {
5806 +               limpk("Zero size fragment offset=%u\n", offset);
5807 +               return 0;
5808 +       }
5809 +
5810 +       /* Note: we can have even middle fragments smaller than this:
5811 +          consider a large packet passing through a 600MTU then
5812 +          576MTU link: this gives a fragment of 24 data bytes.  But
5813 +          everyone packs fragments largest first, hence a fragment
5814 +          can't START before 576 - MAX_IP_HEADER_LEN. */
5815 +
5816 +       /* Used to be min-size 576: I recall Alan Cox saying ax25 goes
5817 +          down to 128 (576 taken from RFC 791: All hosts must be
5818 +          prepared to accept datagrams of up to 576 octets).  Use 128
5819 +          here. */
5820 +#define MIN_LIKELY_MTU 128
5821 +       /* CHECK: Min size of first frag = 128. */
5822 +       if ((ntohs(iph->frag_off) & IP_MF)
5823 +           && offset == 0
5824 +           && ntohs(iph->tot_len) < MIN_LIKELY_MTU) {
5825 +               limpk("First fragment size %u < %u\n", ntohs(iph->tot_len),
5826 +                     MIN_LIKELY_MTU);
5827 +               return 0;
5828 +       }
5829 +
5830 +       /* CHECK: Min offset of frag = 128 - IP hdr len. */
5831 +       if (offset && offset * 8 < MIN_LIKELY_MTU - iph->ihl * 4) {
5832 +               limpk("Fragment starts at %u < %u\n", offset * 8,
5833 +                     MIN_LIKELY_MTU - iph->ihl * 4);
5834 +               return 0;
5835 +       }
5836 +
5837 +       /* CHECK: Protocol specification non-zero. */
5838 +       if (iph->protocol == 0) {
5839 +               limpk("Zero protocol\n");
5840 +               return 0;
5841 +       }
5842 +
5843 +       /* CHECK: Do not use what is unused.
5844 +        * First bit of fragmentation flags should be unused.
5845 +        * May be used by OS fingerprinting tools.
5846 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
5847 +        */
5848 +       if (ntohs(iph->frag_off)>>15) {
5849 +               limpk("IP unused bit set\n");
5850 +               return 0;
5851 +       }
5852 +
5853 +       /* Per-protocol checks. */
5854 +       switch (iph->protocol) {
5855 +       case IPPROTO_ICMP:
5856 +               return check_icmp(protoh, datalen, offset,
5857 +                                 (ntohs(iph->frag_off) & IP_MF),
5858 +                                 embedded);
5859 +
5860 +       case IPPROTO_UDP:
5861 +               return check_udp(iph, protoh, datalen, offset,
5862 +                                (ntohs(iph->frag_off) & IP_MF),
5863 +                                embedded);
5864 +
5865 +       case IPPROTO_TCP:
5866 +               return check_tcp(iph, protoh, datalen, offset,
5867 +                                (ntohs(iph->frag_off) & IP_MF),
5868 +                                embedded);
5869 +       default:
5870 +               /* Ignorance is bliss. */
5871 +               return 1;
5872 +       }
5873 +}
5874 +
5875 +static int
5876 +match(const struct sk_buff *skb,
5877 +      const struct net_device *in,
5878 +      const struct net_device *out,
5879 +      const void *matchinfo,
5880 +      int offset,
5881 +      const void *hdr,
5882 +      u_int16_t datalen,
5883 +      int *hotdrop)
5884 +{
5885 +       return !check_ip(skb->nh.iph, skb->len, 0);
5886 +}
5887 +
5888 +/* Called when user tries to insert an entry of this type. */
5889 +static int
5890 +checkentry(const char *tablename,
5891 +          const struct ipt_ip *ip,
5892 +          void *matchinfo,
5893 +          unsigned int matchsize,
5894 +          unsigned int hook_mask)
5895 +{
5896 +       if (matchsize != IPT_ALIGN(0))
5897 +               return 0;
5898 +
5899 +       return 1;
5900 +}
5901 +
5902 +static struct ipt_match unclean_match
5903 += { { NULL, NULL }, "unclean", &match, &checkentry, NULL, THIS_MODULE };
5904 +
5905 +static int __init init(void)
5906 +{
5907 +       return ipt_register_match(&unclean_match);
5908 +}
5909 +
5910 +static void __exit fini(void)
5911 +{
5912 +       ipt_unregister_match(&unclean_match);
5913 +}
5914 +
5915 +module_init(init);
5916 +module_exit(fini);
5917 +MODULE_LICENSE("GPL");
5918 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/tcp_ipv4.c linux-2.6.7/net/ipv4/tcp_ipv4.c
5919 --- linux-2.6.7.org/net/ipv4/tcp_ipv4.c 2004-06-29 12:24:14.000000000 +0200
5920 +++ linux-2.6.7/net/ipv4/tcp_ipv4.c     2004-06-29 12:35:34.503261080 +0200
5921 @@ -2642,6 +2642,7 @@
5922  EXPORT_SYMBOL(tcp_v4_connect);
5923  EXPORT_SYMBOL(tcp_v4_do_rcv);
5924  EXPORT_SYMBOL(tcp_v4_lookup_listener);
5925 +EXPORT_SYMBOL(tcp_v4_lookup);
5926  EXPORT_SYMBOL(tcp_v4_rebuild_header);
5927  EXPORT_SYMBOL(tcp_v4_remember_stamp);
5928  EXPORT_SYMBOL(tcp_v4_send_check);
5929 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv4/udp.c linux-2.6.7/net/ipv4/udp.c
5930 --- linux-2.6.7.org/net/ipv4/udp.c      2004-06-29 12:24:14.000000000 +0200
5931 +++ linux-2.6.7/net/ipv4/udp.c  2004-06-29 12:35:34.509260168 +0200
5932 @@ -1560,6 +1560,7 @@
5933  EXPORT_SYMBOL(udp_port_rover);
5934  EXPORT_SYMBOL(udp_prot);
5935  EXPORT_SYMBOL(udp_sendmsg);
5936 +EXPORT_SYMBOL(udp_v4_lookup);
5937  
5938  #ifdef CONFIG_PROC_FS
5939  EXPORT_SYMBOL(udp_proc_register);
5940 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Kconfig linux-2.6.7/net/ipv6/netfilter/Kconfig
5941 --- linux-2.6.7.org/net/ipv6/netfilter/Kconfig  2004-06-16 07:19:52.000000000 +0200
5942 +++ linux-2.6.7/net/ipv6/netfilter/Kconfig      2004-06-29 12:35:40.081413072 +0200
5943 @@ -230,5 +230,83 @@
5944           <file:Documentation/modules.txt>.  If unsure, say `N'.
5945           help
5946  
5947 +config IP6_NF_TARGET_HL
5948 +       tristate  'HL target support'
5949 +       depends on IP6_NF_MANGLE
5950 +       help
5951 +         This option adds a `HL' target, which allows you to modify the value of
5952 +         IPv6 Hop Limit field.
5953 +       
5954 +         If you want to compile it as a module, say M here and read
5955 +         <file:Documentation/modules.txt>.  If unsure, say `N'.
5956 +
5957 +config IP6_NF_TARGET_REJECT
5958 +       tristate  'REJECT target support'
5959 +       depends on IP6_NF_FILTER
5960 +       help
5961 +         The REJECT target allows a filtering rule to specify that an ICMPv6
5962 +         error should be issued in response to an incoming packet, rather
5963 +         than silently being dropped.
5964 +       
5965 +         If you want to compile it as a module, say M here and read
5966 +         Documentation/modules.txt.  If unsure, say `N'.
5967 +
5968 +config IP6_NF_MATCH_FUZZY
5969 +       tristate  'Fuzzy match support'
5970 +       depends on IP6_NF_FILTER
5971 +       help
5972 +         This option adds a `fuzzy' match, which allows you to match
5973 +         packets according to a fuzzy logic based law.
5974 +       
5975 +         If you want to compile it as a module, say M here and read
5976 +         Documentation/modules.txt.  If unsure, say `N'.
5977 +
5978 +config IP6_NF_MATCH_NTH
5979 +       tristate  'Nth match support'
5980 +       depends on IP6_NF_IPTABLES
5981 +       help
5982 +         This option adds a `Nth' match, which allow you to make
5983 +         rules that match every Nth packet.  By default there are 
5984 +         16 different counters.
5985 +       
5986 +         [options]
5987 +          --every     Nth              Match every Nth packet
5988 +         [--counter]  num              Use counter 0-15 (default:0)
5989 +         [--start]    num              Initialize the counter at the number 'num'
5990 +                                       instead of 0. Must be between 0 and Nth-1
5991 +         [--packet]   num              Match on 'num' packet. Must be between 0
5992 +                                       and Nth-1.
5993 +       
5994 +                                       If --packet is used for a counter than
5995 +                                       there must be Nth number of --packet
5996 +                                       rules, covering all values between 0 and
5997 +                                       Nth-1 inclusively.
5998 +        
5999 +         If you want to compile it as a module, say M here and read
6000 +         Documentation/modules.txt.  If unsure, say `N'.
6001 +
6002 +config IP6_NF_TARGET_ROUTE
6003 +       tristate '    ROUTE target support'
6004 +       depends on IP6_NF_MANGLE
6005 +       help
6006 +         This option adds a `ROUTE' target, which enables you to setup unusual
6007 +         routes. The ROUTE target is also able to change the incoming interface
6008 +         of a packet.
6009 +       
6010 +         The target can be or not a final target. It has to be used inside the 
6011 +         mangle table.
6012 +         
6013 +         Not working as a module.
6014 +
6015 +config IP6_NF_MATCH_POLICY
6016 +       tristate "IPsec policy match support"
6017 +       depends on IP6_NF_IPTABLES && XFRM
6018 +       help
6019 +         Policy matching allows you to match packets based on the
6020 +         IPsec policy that was used during decapsulation/will
6021 +         be used during encapsulation.
6022 +
6023 +         To compile it as a module, choose M here.  If unsure, say N.
6024 +
6025  endmenu
6026  
6027 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/Makefile linux-2.6.7/net/ipv6/netfilter/Makefile
6028 --- linux-2.6.7.org/net/ipv6/netfilter/Makefile 2004-06-16 07:19:36.000000000 +0200
6029 +++ linux-2.6.7/net/ipv6/netfilter/Makefile     2004-06-29 12:35:40.083412768 +0200
6030 @@ -8,18 +8,25 @@
6031  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
6032  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
6033  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
6034 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
6035  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
6036  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
6037  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
6038  obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
6039  obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
6040 +obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
6041  obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
6042  obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
6043  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
6044  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
6045  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
6046  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
6047 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
6048 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
6049  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
6050  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
6051 +
6052 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
6053 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
6054  obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
6055  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
6056 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c
6057 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_HL.c        1970-01-01 01:00:00.000000000 +0100
6058 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_HL.c    2004-06-29 12:31:59.778904144 +0200
6059 @@ -0,0 +1,105 @@
6060 +/* 
6061 + * Hop Limit modification target for ip6tables
6062 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
6063 + * Based on HW's TTL module
6064 + *
6065 + * This software is distributed under the terms of GNU GPL
6066 + */
6067 +
6068 +#include <linux/module.h>
6069 +#include <linux/skbuff.h>
6070 +#include <linux/ip.h>
6071 +
6072 +#include <linux/netfilter_ipv6/ip6_tables.h>
6073 +#include <linux/netfilter_ipv6/ip6t_HL.h>
6074 +
6075 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
6076 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
6077 +MODULE_LICENSE("GPL");
6078 +
6079 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
6080 +               const struct net_device *in, const struct net_device *out,
6081 +               const void *targinfo, void *userinfo)
6082 +{
6083 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
6084 +       const struct ip6t_HL_info *info = targinfo;
6085 +       u_int16_t diffs[2];
6086 +       int new_hl;
6087 +                        
6088 +       switch (info->mode) {
6089 +               case IP6T_HL_SET:
6090 +                       new_hl = info->hop_limit;
6091 +                       break;
6092 +               case IP6T_HL_INC:
6093 +                       new_hl = ip6h->hop_limit + info->hop_limit;
6094 +                       if (new_hl > 255)
6095 +                               new_hl = 255;
6096 +                       break;
6097 +               case IP6T_HL_DEC:
6098 +                       new_hl = ip6h->hop_limit + info->hop_limit;
6099 +                       if (new_hl < 0)
6100 +                               new_hl = 0;
6101 +                       break;
6102 +               default:
6103 +                       new_hl = ip6h->hop_limit;
6104 +                       break;
6105 +       }
6106 +
6107 +       if (new_hl != ip6h->hop_limit) {
6108 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
6109 +               ip6h->hop_limit = new_hl;
6110 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
6111 +       }
6112 +
6113 +       return IP6T_CONTINUE;
6114 +}
6115 +
6116 +static int ip6t_hl_checkentry(const char *tablename,
6117 +               const struct ip6t_entry *e,
6118 +               void *targinfo,
6119 +               unsigned int targinfosize,
6120 +               unsigned int hook_mask)
6121 +{
6122 +       struct ip6t_HL_info *info = targinfo;
6123 +
6124 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
6125 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
6126 +                               targinfosize,
6127 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
6128 +               return 0;       
6129 +       }       
6130 +
6131 +       if (strcmp(tablename, "mangle")) {
6132 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
6133 +               return 0;
6134 +       }
6135 +
6136 +       if (info->mode > IP6T_HL_MAXMODE) {
6137 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
6138 +                       info->mode);
6139 +               return 0;
6140 +       }
6141 +
6142 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
6143 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
6144 +               return 0;
6145 +       }
6146 +       
6147 +       return 1;
6148 +}
6149 +
6150 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
6151 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
6152 +
6153 +static int __init init(void)
6154 +{
6155 +       return ip6t_register_target(&ip6t_HL);
6156 +}
6157 +
6158 +static void __exit fini(void)
6159 +{
6160 +       ip6t_unregister_target(&ip6t_HL);
6161 +}
6162 +
6163 +module_init(init);
6164 +module_exit(fini);
6165 diff -uNr linux-2.6.9-rc1.orig/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.9-rc1/include/linux/netfilter_ipv6/ip6t_REJECT.h
6166 --- linux-2.6.9-rc1.orig/include/linux/netfilter_ipv6/ip6t_REJECT.h     1970-01-01 01:00:00.000000000 +0100
6167 +++ linux-2.6.9-rc1/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-08-29 11:44:11.277430632 +0200
6168 @@ -0,0 +1,18 @@
6169 +#ifndef _IP6T_REJECT_H
6170 +#define _IP6T_REJECT_H
6171 +
6172 +enum ip6t_reject_with {
6173 +       IP6T_ICMP6_NO_ROUTE,
6174 +       IP6T_ICMP6_ADM_PROHIBITED,
6175 +       IP6T_ICMP6_NOT_NEIGHBOUR,
6176 +       IP6T_ICMP6_ADDR_UNREACH,
6177 +       IP6T_ICMP6_PORT_UNREACH,
6178 +       IP6T_ICMP6_ECHOREPLY,
6179 +       IP6T_TCP_RESET
6180 +};
6181 +
6182 +struct ip6t_reject_info {
6183 +       enum ip6t_reject_with with;      /* reject type */
6184 +};
6185 +
6186 +#endif /*_IP6T_REJECT_H*/
6187 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c
6188 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_REJECT.c    1970-01-01 01:00:00.000000000 +0100
6189 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_REJECT.c        2004-06-29 12:32:02.720456960 +0200
6190 @@ -0,0 +1,458 @@
6191 +/*
6192 + * IP6 tables REJECT target module
6193 + * Linux INET6 implementation
6194 + *
6195 + * Copyright (C)2003 USAGI/WIDE Project
6196 + *
6197 + * Authors:
6198 + *     Yasuyuki Kozakai        <yasuyuki.kozakai@toshiba.co.jp>
6199 + *
6200 + * Based on net/ipv4/netfilter/ipt_REJECT.c
6201 + *
6202 + * This program is free software; you can redistribute it and/or
6203 + * modify it under the terms of the GNU General Public License
6204 + * as published by the Free Software Foundation; either version
6205 + * 2 of the License, or (at your option) any later version.
6206 + */
6207 +
6208 +#include <linux/config.h>
6209 +#include <linux/module.h>
6210 +#include <linux/skbuff.h>
6211 +#include <linux/icmpv6.h>
6212 +#include <net/ipv6.h>
6213 +#include <net/tcp.h>
6214 +#include <net/icmp.h>
6215 +#include <net/ip6_fib.h>
6216 +#include <net/ip6_route.h>
6217 +#include <net/flow.h>
6218 +#include <linux/netfilter_ipv6/ip6_tables.h>
6219 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
6220 +
6221 +MODULE_AUTHOR("Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>");
6222 +MODULE_DESCRIPTION("IP6 tables REJECT target module");
6223 +MODULE_LICENSE("GPL");
6224 +
6225 +#if 0
6226 +#define DEBUGP printk
6227 +#else
6228 +#define DEBUGP(format, args...)
6229 +#endif
6230 +
6231 +#if 0
6232 +static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
6233 +{
6234 +       void (*attach)(struct sk_buff *, struct nf_ct_info *);
6235 +       if (nfct && (attach = ip6_ct_attach) != NULL) {
6236 +               mb();
6237 +               attach(new_skb, nfct);
6238 +       }
6239 +}
6240 +#endif
6241 +
6242 +static int maybe_reroute(struct sk_buff *skb)
6243 +{
6244 +       if (skb->nfcache & NFC_ALTERED){
6245 +               if (ip6_route_me_harder(skb) != 0){
6246 +                       kfree_skb(skb);
6247 +                       return -EINVAL;
6248 +               }
6249 +       }
6250 +
6251 +       return dst_output(skb);
6252 +}
6253 +
6254 +/* Send RST reply */
6255 +static void send_reset(struct sk_buff *oldskb)
6256 +{
6257 +       struct sk_buff *nskb;
6258 +       struct tcphdr otcph, *tcph;
6259 +       unsigned int otcplen, tcphoff, hh_len;
6260 +       int needs_ack;
6261 +       struct ipv6hdr *oip6h = oldskb->nh.ipv6h, *ip6h;
6262 +       struct dst_entry *dst = NULL;
6263 +       u8 proto;
6264 +       struct flowi fl;
6265 +       proto = oip6h->nexthdr;
6266 +       int err;
6267 +
6268 +       if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
6269 +           (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
6270 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6271 +               return;
6272 +       }
6273 +
6274 +       tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data),
6275 +                                  &proto, oldskb->len - ((u8*)(oip6h+1)
6276 +                                                         - oldskb->data));
6277 +
6278 +       if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
6279 +               DEBUGP("ip6t_REJECT: Can't get TCP header.\n");
6280 +               return;
6281 +       }
6282 +
6283 +       otcplen = oldskb->len - tcphoff;
6284 +
6285 +       /* IP header checks: fragment, too short. */
6286 +       if ((proto != IPPROTO_TCP) || (otcplen < sizeof(struct tcphdr))) {
6287 +               DEBUGP("ip6t_REJECT: proto(%d) != IPPROTO_TCP, or too short. otcplen = %d\n",
6288 +                       proto, otcplen);
6289 +               return;
6290 +       }
6291 +
6292 +       if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) {
6293 +               if (net_ratelimit())
6294 +                       printk("ip6t_REJECT: Can't copy tcp header\n");
6295 +               return;
6296 +       }
6297 +
6298 +       /* No RST for RST. */
6299 +       if (otcph.rst) {
6300 +               DEBUGP("ip6t_REJECT: RST is set\n");
6301 +               return;
6302 +       }
6303 +
6304 +       /* Check checksum. */
6305 +       if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
6306 +                           skb_checksum(oldskb, tcphoff, otcplen, 0))) {
6307 +               DEBUGP("ip6t_REJECT: TCP checksum is invalid\n");
6308 +               return;
6309 +       }
6310 +
6311 +       memset(&fl, 0, sizeof(fl));
6312 +       fl.proto = IPPROTO_TCP;
6313 +       ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
6314 +       ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
6315 +       fl.fl_ip_sport = otcph.dest;
6316 +       fl.fl_ip_dport = otcph.source;
6317 +       err = ip6_dst_lookup(NULL, &dst, &fl);
6318 +       if (err) {
6319 +               if (net_ratelimit())
6320 +                       printk("ip6t_REJECT: can't find dst. err = %d\n", err);
6321 +               return;
6322 +       }
6323 +
6324 +       hh_len = (dst->dev->hard_header_len + 15)&~15;
6325 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
6326 +                        + sizeof(struct tcphdr) + dst->trailer_len,
6327 +                        GFP_ATOMIC);
6328 +
6329 +       if (!nskb) {
6330 +               if (net_ratelimit())
6331 +                       printk("ip6t_REJECT: Can't alloc skb\n");
6332 +               dst_release(dst);
6333 +               return;
6334 +       }
6335 +
6336 +       nskb->dst = dst;
6337 +       dst_hold(dst);
6338 +
6339 +       skb_reserve(nskb, hh_len + dst->header_len);
6340 +
6341 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6342 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
6343 +       ip6h->version = 6;
6344 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6345 +       ip6h->nexthdr = IPPROTO_TCP;
6346 +       ip6h->payload_len = htons(sizeof(struct tcphdr));
6347 +       ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr);
6348 +       ipv6_addr_copy(&ip6h->daddr, &oip6h->saddr);
6349 +
6350 +       tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
6351 +       /* Truncate to length (no data) */
6352 +       tcph->doff = sizeof(struct tcphdr)/4;
6353 +       tcph->source = otcph.dest;
6354 +       tcph->dest = otcph.source;
6355 +
6356 +       if (otcph.ack) {
6357 +               needs_ack = 0;
6358 +               tcph->seq = otcph.ack_seq;
6359 +               tcph->ack_seq = 0;
6360 +       } else {
6361 +               needs_ack = 1;
6362 +               tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
6363 +                                     + otcplen - (otcph.doff<<2));
6364 +               tcph->seq = 0;
6365 +       }
6366 +
6367 +       /* Reset flags */
6368 +       ((u_int8_t *)tcph)[13] = 0;
6369 +       tcph->rst = 1;
6370 +       tcph->ack = needs_ack;
6371 +       tcph->window = 0;
6372 +       tcph->urg_ptr = 0;
6373 +       tcph->check = 0;
6374 +
6375 +       /* Adjust TCP checksum */
6376 +       tcph->check = csum_ipv6_magic(&nskb->nh.ipv6h->saddr,
6377 +                                     &nskb->nh.ipv6h->daddr,
6378 +                                     sizeof(struct tcphdr), IPPROTO_TCP,
6379 +                                     csum_partial((char *)tcph,
6380 +                                                  sizeof(struct tcphdr), 0));
6381 +
6382 +#if 0
6383 +       connection_attach(nskb, oldskb->nfct);
6384 +#endif
6385 +
6386 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6387 +               maybe_reroute);
6388 +
6389 +       dst_release(dst);
6390 +}
6391 +
6392 +static void send_unreach(struct sk_buff *skb_in, unsigned char code)
6393 +{
6394 +       struct ipv6hdr *ip6h, *hdr = skb_in->nh.ipv6h;
6395 +       struct icmp6hdr *icmp6h;
6396 +       struct dst_entry *dst = NULL;
6397 +       struct rt6_info *rt;
6398 +       int tmo;
6399 +       __u32 csum;
6400 +       unsigned int len, datalen, hh_len;
6401 +       int saddr_type, daddr_type;
6402 +       unsigned int ptr, ip6off;
6403 +       u8 proto;
6404 +       struct flowi fl;
6405 +       struct sk_buff *nskb;
6406 +       char *data;
6407 +
6408 +       saddr_type = ipv6_addr_type(&hdr->saddr);
6409 +       daddr_type = ipv6_addr_type(&hdr->daddr);
6410 +
6411 +       if ((!(saddr_type & IPV6_ADDR_UNICAST)) ||
6412 +           (!(daddr_type & IPV6_ADDR_UNICAST))) {
6413 +               DEBUGP("ip6t_REJECT: addr is not unicast.\n");
6414 +               return;
6415 +       }
6416 +
6417 +       ip6off = skb_in->nh.raw - skb_in->data;
6418 +       proto = hdr->nexthdr;
6419 +       ptr = ipv6_skip_exthdr(skb_in, ip6off + sizeof(struct ipv6hdr), &proto,
6420 +                              skb_in->len - ip6off);
6421 +
6422 +       if ((ptr < 0) || (ptr > skb_in->len)) {
6423 +               ptr = ip6off + sizeof(struct ipv6hdr);
6424 +               proto = hdr->nexthdr;
6425 +       } else if (proto == IPPROTO_ICMPV6) {
6426 +                u8 type;
6427 +
6428 +                if (skb_copy_bits(skb_in, ptr + offsetof(struct icmp6hdr,
6429 +                                                     icmp6_type), &type, 1)) {
6430 +                       DEBUGP("ip6t_REJECT: Can't get ICMPv6 type\n");
6431 +                       return;
6432 +               }
6433 +
6434 +               if (!(type & ICMPV6_INFOMSG_MASK)) {
6435 +                       DEBUGP("ip6t_REJECT: no reply to icmp error\n");
6436 +                       return;
6437 +               }
6438 +        } else if (proto == IPPROTO_UDP) {
6439 +               int plen = skb_in->len - (ptr - ip6off);
6440 +               uint16_t check;
6441 +
6442 +               if (plen < sizeof(struct udphdr)) {
6443 +                       DEBUGP("ip6t_REJECT: too short\n");
6444 +                       return;
6445 +               }
6446 +
6447 +               if (skb_copy_bits(skb_in, ptr + offsetof(struct udphdr, check),
6448 +                                 &check, 2)) {
6449 +                       if (net_ratelimit())
6450 +                               printk("ip6t_REJECT: can't get copy from skb");
6451 +                       return;
6452 +               }
6453 +
6454 +               if (check &&
6455 +                   csum_ipv6_magic(&hdr->saddr, &hdr->daddr, plen,
6456 +                                   IPPROTO_UDP,
6457 +                                   skb_checksum(skb_in, ptr, plen, 0))) {
6458 +                       DEBUGP("ip6t_REJECT: UDP checksum is invalid.\n");
6459 +                       return;
6460 +               }
6461 +       }
6462 +
6463 +       memset(&fl, 0, sizeof(fl));
6464 +       fl.proto = IPPROTO_ICMPV6;
6465 +       ipv6_addr_copy(&fl.fl6_src, &hdr->daddr);
6466 +       ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
6467 +       fl.fl_icmp_type = ICMPV6_DEST_UNREACH;
6468 +       fl.fl_icmp_code = code;
6469 +
6470 +       if (ip6_dst_lookup(NULL, &dst, &fl)) {
6471 +               return;
6472 +       }
6473 +
6474 +       rt = (struct rt6_info *)dst;
6475 +       tmo = 1*HZ;
6476 +
6477 +       if (rt->rt6i_dst.plen < 128)
6478 +               tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
6479 +
6480 +       if (!xrlim_allow(dst, tmo)) {
6481 +               if (net_ratelimit())
6482 +                       printk("ip6t_REJECT: rate limitted\n");
6483 +               goto dst_release_out;
6484 +       }
6485 +
6486 +       len = skb_in->len + sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr);
6487 +
6488 +       if (len > dst_pmtu(dst))
6489 +               len = dst_pmtu(dst);
6490 +       if (len > IPV6_MIN_MTU)
6491 +               len = IPV6_MIN_MTU;
6492 +
6493 +       datalen = len - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr);
6494 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
6495 +
6496 +       nskb = alloc_skb(hh_len + 15 + dst->header_len + dst->trailer_len + len,
6497 +                        GFP_ATOMIC);
6498 +
6499 +       if (!nskb) {
6500 +               if (net_ratelimit())
6501 +                       printk("ip6t_REJECT: can't alloc skb\n");
6502 +               goto dst_release_out;
6503 +       }
6504 +
6505 +       nskb->priority = 0;
6506 +       nskb->dst = dst;
6507 +       dst_hold(dst);
6508 +
6509 +       skb_reserve(nskb, hh_len + dst->header_len);
6510 +
6511 +       ip6h = nskb->nh.ipv6h = (struct ipv6hdr *)
6512 +                                       skb_put(nskb, sizeof(struct ipv6hdr));
6513 +       ip6h->version = 6;
6514 +       ip6h->hop_limit = dst_metric(dst, RTAX_HOPLIMIT);
6515 +       ip6h->nexthdr = IPPROTO_ICMPV6;
6516 +       ip6h->payload_len = htons(datalen + sizeof(struct icmp6hdr));
6517 +       ipv6_addr_copy(&ip6h->saddr, &hdr->daddr);
6518 +       ipv6_addr_copy(&ip6h->daddr, &hdr->saddr);
6519 +
6520 +       icmp6h = (struct icmp6hdr *) skb_put(nskb, sizeof(struct icmp6hdr));
6521 +       icmp6h->icmp6_type = ICMPV6_DEST_UNREACH;
6522 +       icmp6h->icmp6_code = code;
6523 +       icmp6h->icmp6_cksum = 0;
6524 +
6525 +       data = skb_put(nskb, datalen);
6526 +
6527 +       csum = csum_partial((unsigned char *)icmp6h, sizeof(struct icmp6hdr), 0);
6528 +       csum = skb_copy_and_csum_bits(skb_in, ip6off, data, datalen, csum);
6529 +       icmp6h->icmp6_cksum = csum_ipv6_magic(&hdr->saddr, &hdr->daddr,
6530 +                                            datalen + sizeof(struct icmp6hdr),
6531 +                                            IPPROTO_ICMPV6, csum);
6532 +
6533 +#if 0
6534 +       connection_attach(nskb, skb_in->nfct);
6535 +#endif
6536 +       NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
6537 +               maybe_reroute);
6538 +
6539 +dst_release_out:
6540 +       dst_release(dst);
6541 +}
6542 +
6543 +static unsigned int reject6_target(struct sk_buff **pskb,
6544 +                          unsigned int hooknum,
6545 +                          const struct net_device *in,
6546 +                          const struct net_device *out,
6547 +                          const void *targinfo,
6548 +                          void *userinfo)
6549 +{
6550 +       const struct ip6t_reject_info *reject = targinfo;
6551 +
6552 +       DEBUGP(KERN_DEBUG "%s: medium point\n", __FUNCTION__);
6553 +       /* WARNING: This code causes reentry within ip6tables.
6554 +          This means that the ip6tables jump stack is now crap.  We
6555 +          must return an absolute verdict. --RR */
6556 +       switch (reject->with) {
6557 +       case IP6T_ICMP6_NO_ROUTE:
6558 +               send_unreach(*pskb, ICMPV6_NOROUTE);
6559 +               break;
6560 +       case IP6T_ICMP6_ADM_PROHIBITED:
6561 +               send_unreach(*pskb, ICMPV6_ADM_PROHIBITED);
6562 +               break;
6563 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
6564 +               send_unreach(*pskb, ICMPV6_NOT_NEIGHBOUR);
6565 +               break;
6566 +       case IP6T_ICMP6_ADDR_UNREACH:
6567 +               send_unreach(*pskb, ICMPV6_ADDR_UNREACH);
6568 +               break;
6569 +       case IP6T_ICMP6_PORT_UNREACH:
6570 +               send_unreach(*pskb, ICMPV6_PORT_UNREACH);
6571 +               break;
6572 +       case IP6T_ICMP6_ECHOREPLY:
6573 +               /* Do nothing */
6574 +               break;
6575 +       case IP6T_TCP_RESET:
6576 +               send_reset(*pskb);
6577 +               break;
6578 +       default:
6579 +               if (net_ratelimit())
6580 +                       printk(KERN_WARNING "ip6t_REJECT: case %u not handled yet\n", reject->with);
6581 +               break;
6582 +       }
6583 +
6584 +       return NF_DROP;
6585 +}
6586 +
6587 +static int check(const char *tablename,
6588 +                const struct ip6t_entry *e,
6589 +                void *targinfo,
6590 +                unsigned int targinfosize,
6591 +                unsigned int hook_mask)
6592 +{
6593 +       const struct ip6t_reject_info *rejinfo = targinfo;
6594 +
6595 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
6596 +               DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize);
6597 +               return 0;
6598 +       }
6599 +
6600 +       /* Only allow these for packet filtering. */
6601 +       if (strcmp(tablename, "filter") != 0) {
6602 +               DEBUGP("ip6t_REJECT: bad table `%s'.\n", tablename);
6603 +               return 0;
6604 +       }
6605 +
6606 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
6607 +                          | (1 << NF_IP6_FORWARD)
6608 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
6609 +               DEBUGP("ip6t_REJECT: bad hook mask %X\n", hook_mask);
6610 +               return 0;
6611 +       }
6612 +
6613 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
6614 +               printk("ip6t_REJECT: ECHOREPLY is not supported.\n");
6615 +               return 0;
6616 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
6617 +               /* Must specify that it's a TCP packet */
6618 +               if (e->ipv6.proto != IPPROTO_TCP
6619 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
6620 +                       DEBUGP("ip6t_REJECT: TCP_RESET illegal for non-tcp\n");
6621 +                       return 0;
6622 +               }
6623 +       }
6624 +
6625 +       return 1;
6626 +}
6627 +
6628 +static struct ip6t_target ip6t_reject_reg = {
6629 +       .name           = "REJECT",
6630 +       .target         = reject6_target,
6631 +       .checkentry     = check,
6632 +       .me             = THIS_MODULE
6633 +};
6634 +
6635 +static int __init init(void)
6636 +{
6637 +       if (ip6t_register_target(&ip6t_reject_reg))
6638 +               return -EINVAL;
6639 +       return 0;
6640 +}
6641 +
6642 +static void __exit fini(void)
6643 +{
6644 +       ip6t_unregister_target(&ip6t_reject_reg);
6645 +}
6646 +
6647 +module_init(init);
6648 +module_exit(fini);
6649 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.6.7/net/ipv6/netfilter/ip6t_ROUTE.c
6650 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_ROUTE.c     1970-01-01 01:00:00.000000000 +0100
6651 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_ROUTE.c 2004-06-29 12:34:33.513532928 +0200
6652 @@ -0,0 +1,289 @@
6653 +/*
6654 + * This implements the ROUTE v6 target, which enables you to setup unusual
6655 + * routes not supported by the standard kernel routing table.
6656 + *
6657 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
6658 + *
6659 + * v 1.0 2003/08/05
6660 + *
6661 + * This software is distributed under GNU GPL v2, 1991
6662 + */
6663 +
6664 +#include <linux/module.h>
6665 +#include <linux/skbuff.h>
6666 +#include <linux/ipv6.h>
6667 +#include <linux/netfilter_ipv6/ip6_tables.h>
6668 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
6669 +#include <linux/netdevice.h>
6670 +#include <net/ipv6.h>
6671 +#include <net/ndisc.h>
6672 +#include <net/ip6_route.h>
6673 +#include <linux/icmpv6.h>
6674 +
6675 +#if 1
6676 +#define DEBUGP printk
6677 +#else
6678 +#define DEBUGP(format, args...)
6679 +#endif
6680 +
6681 +#define NIP6(addr) \
6682 +       ntohs((addr).s6_addr16[0]), \
6683 +       ntohs((addr).s6_addr16[1]), \
6684 +       ntohs((addr).s6_addr16[2]), \
6685 +       ntohs((addr).s6_addr16[3]), \
6686 +       ntohs((addr).s6_addr16[4]), \
6687 +       ntohs((addr).s6_addr16[5]), \
6688 +       ntohs((addr).s6_addr16[6]), \
6689 +       ntohs((addr).s6_addr16[7])
6690 +
6691 +/* Route the packet according to the routing keys specified in
6692 + * route_info. Keys are :
6693 + *  - ifindex : 
6694 + *      0 if no oif preferred, 
6695 + *      otherwise set to the index of the desired oif
6696 + *  - route_info->gw :
6697 + *      0 if no gateway specified,
6698 + *      otherwise set to the next host to which the pkt must be routed
6699 + * If success, skb->dev is the output device to which the packet must 
6700 + * be sent and skb->dst is not NULL
6701 + *
6702 + * RETURN:  1 if the packet was succesfully routed to the 
6703 + *            destination desired
6704 + *          0 if the kernel routing table could not route the packet
6705 + *            according to the keys specified
6706 + */
6707 +static int 
6708 +route6(struct sk_buff *skb,
6709 +       unsigned int ifindex,
6710 +       const struct ip6t_route_target_info *route_info)
6711 +{
6712 +       struct rt6_info *rt = NULL;
6713 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
6714 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
6715 +
6716 +       DEBUGP("ip6t_ROUTE: called with: ");
6717 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
6718 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
6719 +       DEBUGP("OUT=%s\n", route_info->oif);
6720 +       
6721 +       if (ipv6_addr_any(gw))
6722 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
6723 +       else
6724 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
6725 +
6726 +       if (!rt)
6727 +               goto no_route;
6728 +
6729 +       DEBUGP("ip6t_ROUTE: routing gives: ");
6730 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
6731 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
6732 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
6733 +
6734 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
6735 +               goto wrong_route;
6736 +       
6737 +       if (!rt->rt6i_nexthop) {
6738 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
6739 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
6740 +       }
6741 +
6742 +       /* Drop old route. */
6743 +       dst_release(skb->dst);
6744 +       skb->dst = &rt->u.dst;
6745 +       skb->dev = rt->rt6i_dev;
6746 +       return 1;
6747 +
6748 + wrong_route:
6749 +       dst_release(&rt->u.dst);
6750 + no_route:
6751 +       if (!net_ratelimit())
6752 +               return 0;
6753 +
6754 +       printk("ip6t_ROUTE: no explicit route found ");
6755 +       if (ifindex)
6756 +               printk("via interface %s ", route_info->oif);
6757 +       if (!ipv6_addr_any(gw))
6758 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
6759 +       printk("\n");
6760 +       return 0;
6761 +}
6762 +
6763 +
6764 +/* Stolen from ip6_output_finish
6765 + * PRE : skb->dev is set to the device we are leaving by
6766 + *       skb->dst is not NULL
6767 + * POST: the packet is sent with the link layer header pushed
6768 + *       the packet is destroyed
6769 + */
6770 +static void ip_direct_send(struct sk_buff *skb)
6771 +{
6772 +       struct dst_entry *dst = skb->dst;
6773 +       struct hh_cache *hh = dst->hh;
6774 +
6775 +       if (hh) {
6776 +               read_lock_bh(&hh->hh_lock);
6777 +               memcpy(skb->data - 16, hh->hh_data, 16);
6778 +               read_unlock_bh(&hh->hh_lock);
6779 +               skb_push(skb, hh->hh_len);
6780 +               hh->hh_output(skb);
6781 +       } else if (dst->neighbour)
6782 +               dst->neighbour->output(skb);
6783 +       else {
6784 +               if (net_ratelimit())
6785 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
6786 +               kfree_skb(skb);
6787 +       }
6788 +}
6789 +
6790 +
6791 +static unsigned int 
6792 +route6_oif(const struct ip6t_route_target_info *route_info,
6793 +          struct sk_buff *skb) 
6794 +{
6795 +       unsigned int ifindex = 0;
6796 +       struct net_device *dev_out = NULL;
6797 +
6798 +       /* The user set the interface name to use.
6799 +        * Getting the current interface index.
6800 +        */
6801 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
6802 +               ifindex = dev_out->ifindex;
6803 +       } else {
6804 +               /* Unknown interface name : packet dropped */
6805 +               if (net_ratelimit()) 
6806 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
6807 +
6808 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
6809 +                       return IP6T_CONTINUE;
6810 +               else
6811 +                       return NF_DROP;
6812 +       }
6813 +
6814 +       /* Trying the standard way of routing packets */
6815 +       if (route6(skb, ifindex, route_info)) {
6816 +               dev_put(dev_out);
6817 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
6818 +                       return IP6T_CONTINUE;
6819 +               
6820 +               ip_direct_send(skb);
6821 +               return NF_STOLEN;
6822 +       } else 
6823 +               return NF_DROP;
6824 +}
6825 +
6826 +
6827 +static unsigned int 
6828 +route6_gw(const struct ip6t_route_target_info *route_info,
6829 +         struct sk_buff *skb) 
6830 +{
6831 +       if (route6(skb, 0, route_info)) {
6832 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
6833 +                       return IP6T_CONTINUE;
6834 +
6835 +               ip_direct_send(skb);
6836 +               return NF_STOLEN;
6837 +       } else
6838 +               return NF_DROP;
6839 +}
6840 +
6841 +
6842 +static unsigned int 
6843 +ip6t_route_target(struct sk_buff **pskb,
6844 +                 unsigned int hooknum,
6845 +                 const struct net_device *in,
6846 +                 const struct net_device *out,
6847 +                 const void *targinfo,
6848 +                 void *userinfo)
6849 +{
6850 +       const struct ip6t_route_target_info *route_info = targinfo;
6851 +       struct sk_buff *skb = *pskb;
6852 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
6853 +
6854 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
6855 +               goto do_it;
6856 +
6857 +       /* If we are at PREROUTING or INPUT hook
6858 +        * the TTL isn't decreased by the IP stack
6859 +        */
6860 +       if (hooknum == NF_IP6_PRE_ROUTING ||
6861 +           hooknum == NF_IP6_LOCAL_IN) {
6862 +
6863 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
6864 +
6865 +               if (ipv6h->hop_limit <= 1) {
6866 +                       /* Force OUTPUT device used as source address */
6867 +                       skb->dev = skb->dst->dev;
6868 +
6869 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
6870 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
6871 +
6872 +                       return NF_DROP;
6873 +               }
6874 +
6875 +               ipv6h->hop_limit--;
6876 +       }
6877 +
6878 +
6879 + do_it:
6880 +       if (route_info->oif[0]) 
6881 +               return route6_oif(route_info, *pskb);
6882 +       
6883 +       if (!ipv6_addr_any(gw))
6884 +               return route6_gw(route_info, *pskb);
6885 +
6886 +       if (net_ratelimit()) 
6887 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
6888 +
6889 +       return IP6T_CONTINUE;
6890 +}
6891 +
6892 +
6893 +static int 
6894 +ip6t_route_checkentry(const char *tablename,
6895 +                     const struct ip6t_entry *e,
6896 +                     void *targinfo,
6897 +                     unsigned int targinfosize,
6898 +                     unsigned int hook_mask)
6899 +{
6900 +       if (strcmp(tablename, "mangle") != 0) {
6901 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
6902 +               return 0;
6903 +       }
6904 +
6905 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
6906 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
6907 +                      targinfosize,
6908 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
6909 +               return 0;
6910 +       }
6911 +
6912 +       return 1;
6913 +}
6914 +
6915 +
6916 +static struct ip6t_target ip6t_route_reg = {
6917 +       .name       = "ROUTE",
6918 +       .target     = ip6t_route_target,
6919 +       .checkentry = ip6t_route_checkentry,
6920 +       .me         = THIS_MODULE
6921 +};
6922 +
6923 +
6924 +static int __init init(void)
6925 +{
6926 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
6927 +       if (ip6t_register_target(&ip6t_route_reg))
6928 +               return -EINVAL;
6929 +
6930 +       return 0;
6931 +}
6932 +
6933 +
6934 +static void __exit fini(void)
6935 +{
6936 +       ip6t_unregister_target(&ip6t_route_reg);
6937 +}
6938 +
6939 +module_init(init);
6940 +module_exit(fini);
6941 +MODULE_LICENSE("GPL");
6942 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c
6943 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_fuzzy.c     1970-01-01 01:00:00.000000000 +0100
6944 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_fuzzy.c 2004-06-29 12:32:08.824529000 +0200
6945 @@ -0,0 +1,189 @@
6946 +/*
6947 + * This module implements a simple TSK FLC
6948 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
6949 + * to limit , in an adaptive and flexible way , the packet rate crossing
6950 + * a given stream . It serves as an initial and very simple (but effective)
6951 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
6952 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
6953 + * into our code in a precise , adaptive and efficient manner.
6954 + *  The goal is very similar to that of "limit" match , but using techniques of
6955 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
6956 + * avoiding over and undershoots - and stuff like that .
6957 + *
6958 + *
6959 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
6960 + * 2002-08-17  : Changed to eliminate floating point operations .
6961 + * 2002-08-23  : Coding style changes .
6962 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
6963 + */
6964 +
6965 +#include <linux/module.h>
6966 +#include <linux/skbuff.h>
6967 +#include <linux/ipv6.h>
6968 +#include <linux/random.h>
6969 +#include <net/tcp.h>
6970 +#include <linux/spinlock.h>
6971 +#include <linux/netfilter_ipv6/ip6_tables.h>
6972 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
6973 +
6974 +/*
6975 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6976 + Expressed in percentage
6977 +*/
6978 +
6979 +#define PAR_LOW                1/100
6980 +#define PAR_HIGH       1
6981 +
6982 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
6983 +
6984 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
6985 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
6986 +MODULE_LICENSE("GPL");
6987 +
6988 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6989 +{
6990 +       if (tx >= maxi) return 100;
6991 +
6992 +       if (tx <= mini) return 0;
6993 +
6994 +       return ((100 * (tx-mini)) / (maxi-mini));
6995 +}
6996 +
6997 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6998 +{
6999 +       if (tx <= mini) return 100;
7000 +
7001 +       if (tx >= maxi) return 0;
7002 +
7003 +       return ((100 * (maxi - tx)) / (maxi - mini));
7004 +
7005 +}
7006 +
7007 +static int
7008 +ip6t_fuzzy_match(const struct sk_buff *pskb,
7009 +              const struct net_device *in,
7010 +              const struct net_device *out,
7011 +              const void *matchinfo,
7012 +              int offset,
7013 +              const void *hdr,
7014 +              u_int16_t datalen,
7015 +              int *hotdrop)
7016 +{
7017 +       /* From userspace */
7018 +
7019 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
7020 +
7021 +       u_int8_t random_number;
7022 +       unsigned long amount;
7023 +       u_int8_t howhigh, howlow;
7024 +
7025 +
7026 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
7027 +
7028 +       info->bytes_total += pskb->len;
7029 +       info->packets_total++;
7030 +
7031 +       info->present_time = jiffies;
7032 +
7033 +       if (info->present_time >= info->previous_time)
7034 +               amount = info->present_time - info->previous_time;
7035 +       else {
7036 +               /* There was a transition : I choose to re-sample
7037 +                  and keep the old acceptance rate...
7038 +               */
7039 +
7040 +               amount = 0;
7041 +               info->previous_time = info->present_time;
7042 +               info->bytes_total = info->packets_total = 0;
7043 +            };
7044 +
7045 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
7046 +
7047 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
7048 +                                       / amount);
7049 +
7050 +               info->previous_time = info->present_time;
7051 +               info->bytes_total = info->packets_total = 0;
7052 +
7053 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
7054 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
7055 +
7056 +               info->acceptance_rate = (u_int8_t) \
7057 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
7058 +
7059 +       /* In fact, the above defuzzification would require a denominator
7060 +        * proportional to (howhigh+howlow) but, in this particular case,
7061 +        * that expression is constant.
7062 +        * An imediate consequence is that it is not necessary to call
7063 +        * both mf_high and mf_low - but to keep things understandable,
7064 +        * I did so.
7065 +        */
7066 +
7067 +       }
7068 +
7069 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
7070 +
7071 +
7072 +       if (info->acceptance_rate < 100)
7073 +       {
7074 +               get_random_bytes((void *)(&random_number), 1);
7075 +
7076 +               /*  If within the acceptance , it can pass => don't match */
7077 +               if (random_number <= (255 * info->acceptance_rate) / 100)
7078 +                       return 0;
7079 +               else
7080 +                       return 1; /* It can't pass (It matches) */
7081 +       };
7082 +
7083 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
7084 +
7085 +}
7086 +
7087 +static int
7088 +ip6t_fuzzy_checkentry(const char *tablename,
7089 +                  const struct ip6t_ip6 *ip,
7090 +                  void *matchinfo,
7091 +                  unsigned int matchsize,
7092 +                  unsigned int hook_mask)
7093 +{
7094 +
7095 +       const struct ip6t_fuzzy_info *info = matchinfo;
7096 +
7097 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
7098 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
7099 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
7100 +               return 0;
7101 +       }
7102 +
7103 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
7104 +        || (info->minimum_rate >= info->maximum_rate)) {
7105 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
7106 +               return 0;
7107 +       }
7108 +
7109 +       return 1;
7110 +}
7111 +
7112 +static struct ip6t_match ip6t_fuzzy_reg = {
7113 +       {NULL, NULL},
7114 +       "fuzzy",
7115 +       ip6t_fuzzy_match,
7116 +       ip6t_fuzzy_checkentry,
7117 +       NULL,
7118 +       THIS_MODULE };
7119 +
7120 +static int __init init(void)
7121 +{
7122 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
7123 +               return -EINVAL;
7124 +
7125 +       return 0;
7126 +}
7127 +
7128 +static void __exit fini(void)
7129 +{
7130 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
7131 +}
7132 +
7133 +module_init(init);
7134 +module_exit(fini);
7135 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c
7136 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_nth.c       1970-01-01 01:00:00.000000000 +0100
7137 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_nth.c   2004-06-29 12:32:16.703331240 +0200
7138 @@ -0,0 +1,173 @@
7139 +/*
7140 +  This is a module which is used for match support for every Nth packet
7141 +  This file is distributed under the terms of the GNU General Public
7142 +  License (GPL). Copies of the GPL can be obtained from:
7143 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
7144 +
7145 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
7146 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
7147 +        * added support for multiple counters
7148 +        * added support for matching on individual packets
7149 +          in the counter cycle
7150 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
7151 +
7152 +*/
7153 +
7154 +#include <linux/module.h>
7155 +#include <linux/skbuff.h>
7156 +#include <linux/ip.h>
7157 +#include <net/tcp.h>
7158 +#include <linux/spinlock.h>
7159 +#include <linux/netfilter_ipv6/ip6_tables.h>
7160 +#include <linux/netfilter_ipv6/ip6t_nth.h>
7161 +
7162 +MODULE_LICENSE("GPL");
7163 +
7164 +/*
7165 + * State information.
7166 + */
7167 +struct state {
7168 +       spinlock_t lock;
7169 +       u_int16_t number;
7170 +};
7171 +
7172 +static struct state states[IP6T_NTH_NUM_COUNTERS];
7173 +
7174 +static int
7175 +ip6t_nth_match(const struct sk_buff *pskb,
7176 +             const struct net_device *in,
7177 +             const struct net_device *out,
7178 +             const void *matchinfo,
7179 +             int offset,
7180 +             const void *hdr,
7181 +             u_int16_t datalen,
7182 +             int *hotdrop)
7183 +{
7184 +       /* Parameters from userspace */
7185 +       const struct ip6t_nth_info *info = matchinfo;
7186 +        unsigned counter = info->counter;
7187 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
7188 +       {
7189 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
7190 +               return 0;
7191 +        };
7192 +
7193 +        spin_lock(&states[counter].lock);
7194 +
7195 +        /* Are we matching every nth packet?*/
7196 +        if (info->packet == 0xFF)
7197 +        {
7198 +               /* We're matching every nth packet and only every nth packet*/
7199 +               /* Do we match or invert match? */
7200 +               if (info->not == 0)
7201 +               {
7202 +                       if (states[counter].number == 0)
7203 +                       {
7204 +                               ++states[counter].number;
7205 +                               goto match;
7206 +                       }
7207 +                       if (states[counter].number >= info->every)
7208 +                               states[counter].number = 0; /* reset the counter */
7209 +                       else
7210 +                               ++states[counter].number;
7211 +                       goto dontmatch;
7212 +               }
7213 +               else
7214 +               {
7215 +                       if (states[counter].number == 0)
7216 +                       {
7217 +                               ++states[counter].number;
7218 +                               goto dontmatch;
7219 +                       }
7220 +                       if (states[counter].number >= info->every)
7221 +                               states[counter].number = 0;
7222 +                       else
7223 +                               ++states[counter].number;
7224 +                       goto match;
7225 +               }
7226 +        }
7227 +        else
7228 +        {
7229 +               /* We're using the --packet, so there must be a rule for every value */
7230 +               if (states[counter].number == info->packet)
7231 +               {
7232 +                       /* only increment the counter when a match happens */
7233 +                       if (states[counter].number >= info->every)
7234 +                               states[counter].number = 0; /* reset the counter */
7235 +                       else
7236 +                               ++states[counter].number;
7237 +                       goto match;
7238 +               }
7239 +               else
7240 +                       goto dontmatch;
7241 +       }
7242 +
7243 + dontmatch:
7244 +       /* don't match */
7245 +       spin_unlock(&states[counter].lock);
7246 +       return 0;
7247 +
7248 + match:
7249 +       spin_unlock(&states[counter].lock);
7250 +       return 1;
7251 +}
7252 +
7253 +static int
7254 +ip6t_nth_checkentry(const char *tablename,
7255 +                  const struct ip6t_ip6 *e,
7256 +                  void *matchinfo,
7257 +                  unsigned int matchsize,
7258 +                  unsigned int hook_mask)
7259 +{
7260 +       /* Parameters from userspace */
7261 +       const struct ip6t_nth_info *info = matchinfo;
7262 +        unsigned counter = info->counter;
7263 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
7264 +       {
7265 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
7266 +                       return 0;
7267 +               };
7268 +
7269 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
7270 +               printk("nth: matchsize %u != %u\n", matchsize,
7271 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
7272 +               return 0;
7273 +       }
7274 +
7275 +       states[counter].number = info->startat;
7276 +
7277 +       return 1;
7278 +}
7279 +
7280 +static struct ip6t_match ip6t_nth_reg = { 
7281 +       {NULL, NULL},
7282 +       "nth",
7283 +       ip6t_nth_match,
7284 +       ip6t_nth_checkentry,
7285 +       NULL,
7286 +       THIS_MODULE };
7287 +
7288 +static int __init init(void)
7289 +{
7290 +       unsigned counter;
7291 +        memset(&states, 0, sizeof(states));
7292 +       if (ip6t_register_match(&ip6t_nth_reg))
7293 +               return -EINVAL;
7294 +
7295 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
7296 +       {
7297 +               spin_lock_init(&(states[counter].lock));
7298 +        };
7299 +
7300 +       printk("ip6t_nth match loaded\n");
7301 +       return 0;
7302 +}
7303 +
7304 +static void __exit fini(void)
7305 +{
7306 +       ip6t_unregister_match(&ip6t_nth_reg);
7307 +       printk("ip6t_nth match unloaded\n");
7308 +}
7309 +
7310 +module_init(init);
7311 +module_exit(fini);
7312 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_owner.c linux-2.6.7/net/ipv6/netfilter/ip6t_owner.c
7313 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_owner.c     2004-06-29 12:24:14.000000000 +0200
7314 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_owner.c 2004-06-29 12:35:37.772764040 +0200
7315 @@ -21,6 +21,39 @@
7316  MODULE_LICENSE("GPL");
7317  
7318  static int
7319 +match_comm(const struct sk_buff *skb, const char *comm)
7320 +{
7321 +       struct task_struct *p, *g;
7322 +       struct files_struct *files;
7323 +       int i;
7324 +
7325 +       read_lock(&tasklist_lock);
7326 +       do_each_thread(g, p) {
7327 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
7328 +                       continue;
7329 +
7330 +               task_lock(p);
7331 +               files = p->files;
7332 +               if(files) {
7333 +                       read_lock(&files->file_lock);
7334 +                       for (i=0; i < files->max_fds; i++) {
7335 +                               if (fcheck_files(files, i) ==
7336 +                                   skb->sk->sk_socket->file) {
7337 +                                       read_unlock(&files->file_lock);
7338 +                                       task_unlock(p);
7339 +                                       read_unlock(&tasklist_lock);
7340 +                                       return 1;
7341 +                               }
7342 +                       }
7343 +                       read_unlock(&files->file_lock);
7344 +               }
7345 +               task_unlock(p);
7346 +       } while_each_thread(g, p);
7347 +       read_unlock(&tasklist_lock);
7348 +       return 0;
7349 +}
7350 +
7351 +static int
7352  match_pid(const struct sk_buff *skb, pid_t pid)
7353  {
7354         struct task_struct *p;
7355 @@ -125,6 +158,12 @@
7356                         return 0;
7357         }
7358  
7359 +       if(info->match & IP6T_OWNER_COMM) {
7360 +               if (!match_comm(skb, info->comm) ^
7361 +                   !!(info->invert & IP6T_OWNER_COMM))
7362 +                       return 0;
7363 +       }
7364 +
7365         return 1;
7366  }
7367  
7368 diff -Nur --exclude '*.orig' linux-2.6.7.org/net/ipv6/netfilter/ip6t_policy.c linux-2.6.7/net/ipv6/netfilter/ip6t_policy.c
7369 --- linux-2.6.7.org/net/ipv6/netfilter/ip6t_policy.c    1970-01-01 01:00:00.000000000 +0100
7370 +++ linux-2.6.7/net/ipv6/netfilter/ip6t_policy.c        2004-06-29 12:35:40.050417784 +0200
7371 @@ -0,0 +1,201 @@
7372 +/* IP tables module for matching IPsec policy
7373 + *
7374 + * Copyright (c) 2004 Patrick McHardy, <kaber@trash.net>
7375 + *
7376 + * This program is free software; you can redistribute it and/or modify
7377 + * it under the terms of the GNU General Public License version 2 as
7378 + * published by the Free Software Foundation.
7379 + */
7380 +
7381 +#include <linux/kernel.h>
7382 +#include <linux/config.h>
7383 +#include <linux/module.h>
7384 +#include <linux/skbuff.h>
7385 +#include <linux/init.h>
7386 +#include <net/xfrm.h>
7387 +
7388 +#include <linux/netfilter_ipv6.h>
7389 +#include <linux/netfilter_ipv6/ip6t_policy.h>
7390 +#include <linux/netfilter_ipv6/ip6_tables.h>
7391 +
7392 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
7393 +MODULE_DESCRIPTION("IPtables IPsec policy matching module");
7394 +MODULE_LICENSE("GPL");
7395 +
7396 +
7397 +static inline int ip6_masked_addrcmp(struct in6_addr addr1,
7398 +                                     struct in6_addr mask,
7399 +                                     struct in6_addr addr2)
7400 +{
7401 +       int i;
7402 +
7403 +       for (i = 0; i < 16; i++) {
7404 +               if ((addr1.s6_addr[i] & mask.s6_addr[i]) !=
7405 +                   (addr2.s6_addr[i] & mask.s6_addr[i]))
7406 +                       return 1;
7407 +       }
7408 +       return 0;
7409 +}
7410 +
7411 +
7412 +static inline int
7413 +match_xfrm_state(struct xfrm_state *x, const struct ip6t_policy_elem *e)
7414 +{
7415 +#define MISMATCH(x,y)  (e->match.x && ((e->x != (y)) ^ e->invert.x))
7416 +       
7417 +       struct in6_addr xfrm_saddr, xfrm_daddr;
7418 +       
7419 +       if ((e->match.saddr
7420 +            && (ip6_masked_addrcmp(xfrm_saddr, e->saddr, e->smask))
7421 +               ^ e->invert.saddr ) ||
7422 +           (e->match.daddr
7423 +            && (ip6_masked_addrcmp(xfrm_daddr, e->daddr, e->dmask))
7424 +               ^ e->invert.daddr ) ||
7425 +           MISMATCH(proto, x->id.proto) ||
7426 +           MISMATCH(mode, x->props.mode) ||
7427 +           MISMATCH(spi, x->id.spi) ||
7428 +           MISMATCH(reqid, x->props.reqid))
7429 +               return 0;
7430 +       return 1;
7431 +}
7432 +
7433 +static int
7434 +match_policy_in(const struct sk_buff *skb, const struct ip6t_policy_info *info)
7435 +{
7436 +       const struct ip6t_policy_elem *e;
7437 +       struct sec_path *sp = skb->sp;
7438 +       int strict = info->flags & POLICY_MATCH_STRICT;
7439 +       int i, pos;
7440 +
7441 +       if (sp == NULL)
7442 +               return -1;
7443 +       if (strict && info->len != sp->len)
7444 +               return 0;
7445 +
7446 +       for (i = sp->len - 1; i >= 0; i--) {
7447 +               pos = strict ? i - sp->len + 1 : 0;
7448 +               if (pos >= info->len)
7449 +                       return 0;
7450 +               e = &info->pol[pos];
7451 +
7452 +               if (match_xfrm_state(sp->x[i].xvec, e)) {
7453 +                       if (!strict)
7454 +                               return 1;
7455 +               } else if (strict)
7456 +                       return 0;
7457 +       }
7458 +
7459 +       return strict ? 1 : 0;
7460 +}
7461 +
7462 +static int
7463 +match_policy_out(const struct sk_buff *skb, const struct ip6t_policy_info *info)
7464 +{
7465 +       const struct ip6t_policy_elem *e;
7466 +       struct dst_entry *dst = skb->dst;
7467 +       int strict = info->flags & POLICY_MATCH_STRICT;
7468 +       int i, pos;
7469 +
7470 +       if (dst->xfrm == NULL)
7471 +               return -1;
7472 +
7473 +       for (i = 0; dst && dst->xfrm; dst = dst->child, i++) {
7474 +               pos = strict ? i : 0;
7475 +               if (pos >= info->len)
7476 +                       return 0;
7477 +               e = &info->pol[pos];
7478 +
7479 +               if (match_xfrm_state(dst->xfrm, e)) {
7480 +                       if (!strict)
7481 +                               return 1;
7482 +               } else if (strict)
7483 +                       return 0;
7484 +       }
7485 +
7486 +       return strict ? 1 : 0;
7487 +}
7488 +
7489 +static int match(const struct sk_buff *skb,
7490 +                 const struct net_device *in,
7491 +                 const struct net_device *out,
7492 +                 const void *matchinfo,
7493 +                int offset,
7494 +                const void *hdr,
7495 +                u_int16_t datalen,
7496 +                int *hotdrop)
7497 +{
7498 +       const struct ip6t_policy_info *info = matchinfo;
7499 +       int ret;
7500 +
7501 +       if (info->flags & POLICY_MATCH_IN)
7502 +               ret = match_policy_in(skb, info);
7503 +       else
7504 +               ret = match_policy_out(skb, info);
7505 +
7506 +       if (ret < 0) {
7507 +               if (info->flags & POLICY_MATCH_NONE)
7508 +                       ret = 1;
7509 +               else
7510 +                       ret = 0;
7511 +       } else if (info->flags & POLICY_MATCH_NONE)
7512 +               ret = 0;
7513 +
7514 +       return ret;
7515 +}
7516 +
7517 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
7518 +                      void *matchinfo, unsigned int matchsize,
7519 +                      unsigned int hook_mask)
7520 +{
7521 +       struct ip6t_policy_info *info = matchinfo;
7522 +
7523 +       if (matchsize != IP6T_ALIGN(sizeof(*info))) {
7524 +               printk(KERN_ERR "ip6t_policy: matchsize %u != %u\n",
7525 +                      matchsize, IP6T_ALIGN(sizeof(*info)));
7526 +               return 0;
7527 +       }
7528 +       if (!(info->flags & (POLICY_MATCH_IN|POLICY_MATCH_OUT))) {
7529 +               printk(KERN_ERR "ip6t_policy: neither incoming nor "
7530 +                               "outgoing policy selected\n");
7531 +               return 0;
7532 +       }
7533 +       if (hook_mask & (1 << NF_IP6_PRE_ROUTING | 1 << NF_IP6_LOCAL_IN)
7534 +           && info->flags & POLICY_MATCH_OUT) {
7535 +               printk(KERN_ERR "ip6t_policy: output policy not valid in "
7536 +                               "PRE_ROUTING and INPUT\n");
7537 +               return 0;
7538 +       }
7539 +       if (hook_mask & (1 << NF_IP6_POST_ROUTING | 1 << NF_IP6_LOCAL_OUT)
7540 +           && info->flags & POLICY_MATCH_IN) {
7541 +               printk(KERN_ERR "ip6t_policy: input policy not valid in "
7542 +                               "POST_ROUTING and OUTPUT\n");
7543 +               return 0;
7544 +       }
7545 +       if (info->len > POLICY_MAX_ELEM) {
7546 +               printk(KERN_ERR "ip6t_policy: too many policy elements\n");
7547 +               return 0;
7548 +       }
7549 +
7550 +       return 1;
7551 +}
7552 +
7553 +static struct ip6t_match policy_match =
7554 +{
7555 +       .name           = "policy",
7556 +       .match          = match,
7557 +       .checkentry     = checkentry,
7558 +       .me             = THIS_MODULE,
7559 +};
7560 +
7561 +static int __init init(void)
7562 +{
7563 +       return ip6t_register_match(&policy_match);
7564 +}
7565 +
7566 +static void __exit fini(void)
7567 +{
7568 +       ip6t_unregister_match(&policy_match);
7569 +}
7570 +
7571 +module_init(init);
7572 +module_exit(fini);
This page took 0.728305 seconds and 3 git commands to generate.