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