]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.x-patch-o-matic-ng-base-20040216.patch
- minor fix. it builds but linking needs fix.
[packages/kernel.git] / 2.6.x-patch-o-matic-ng-base-20040216.patch
1 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ip_pool.h
2 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ip_pool.h  1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ip_pool.h      2004-02-16 11:07:21.518803072 +0100
4 @@ -0,0 +1,64 @@
5 +#ifndef _IP_POOL_H
6 +#define _IP_POOL_H
7 +
8 +/***************************************************************************/
9 +/*  This program is free software; you can redistribute it and/or modify   */
10 +/*  it under the terms of the GNU General Public License as published by   */
11 +/*  the Free Software Foundation; either version 2 of the License, or     */
12 +/*  (at your option) any later version.                                           */
13 +/*                                                                        */
14 +/*  This program is distributed in the hope that it will be useful,       */
15 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
16 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
17 +/*  GNU General Public License for more details.                          */
18 +/*                                                                        */
19 +/*  You should have received a copy of the GNU General Public License     */
20 +/*  along with this program; if not, write to the Free Software                   */
21 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
22 +/***************************************************************************/
23 +
24 +/* A sockopt of such quality has hardly ever been seen before on the open
25 + * market!  This little beauty, hardly ever used: above 64, so it's
26 + * traditionally used for firewalling, not touched (even once!) by the
27 + * 2.0, 2.2 and 2.4 kernels!
28 + *
29 + * Comes with its own certificate of authenticity, valid anywhere in the
30 + * Free world!
31 + *
32 + * Rusty, 19.4.2000
33 + */
34 +#define SO_IP_POOL 81
35 +
36 +typedef int ip_pool_t;                 /* pool index */
37 +#define IP_POOL_NONE   ((ip_pool_t)-1)
38 +
39 +struct ip_pool_request {
40 +       int op;
41 +       ip_pool_t index;
42 +       u_int32_t addr;
43 +       u_int32_t addr2;
44 +};
45 +
46 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
47 +
48 +#define IP_POOL_BAD001         0x00000010
49 +
50 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
51 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
52 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
53 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
54 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
55 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
56 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
57 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
58 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
59 +
60 +#ifdef __KERNEL__
61 +
62 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
63 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
64 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
65 +
66 +#endif
67 +
68 +#endif /*_IP_POOL_H*/
69 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h
70 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h      1970-01-01 01:00:00.000000000 +0100
71 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_NETLINK.h  2004-02-16 11:07:05.880548139 +0100
72 @@ -0,0 +1,27 @@
73 +#ifndef _IPT_FWMON_H
74 +#define _IPT_FWMON_H
75 +
76 +/* Bitmask macros */
77 +#define MASK(x,y) (x & y)
78 +#define MASK_SET(x,y) x |= y
79 +#define MASK_UNSET(x,y) x &= ~y
80 +
81 +#define USE_MARK       0x00000001
82 +#define USE_DROP       0x00000002
83 +#define USE_SIZE       0x00000004
84 +
85 +struct ipt_nldata
86 +{      
87 +       unsigned int flags;
88 +       unsigned int mark;
89 +       unsigned int size;
90 +};
91 +
92 +/* Old header */
93 +struct netlink_t {
94 +       unsigned int len;
95 +       unsigned int mark;
96 +       char iface[IFNAMSIZ];
97 +};
98 +
99 +#endif /*_IPT_FWMON_H*/
100 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_TTL.h
101 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_TTL.h  1970-01-01 01:00:00.000000000 +0100
102 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_TTL.h      2004-02-16 11:07:09.253740328 +0100
103 @@ -0,0 +1,21 @@
104 +/* TTL modification module for IP tables
105 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
106 +
107 +#ifndef _IPT_TTL_H
108 +#define _IPT_TTL_H
109 +
110 +enum {
111 +       IPT_TTL_SET = 0,
112 +       IPT_TTL_INC,
113 +       IPT_TTL_DEC
114 +};
115 +
116 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
117 +
118 +struct ipt_TTL_info {
119 +       u_int8_t        mode;
120 +       u_int8_t        ttl;
121 +};
122 +
123 +
124 +#endif
125 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h
126 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_connlimit.h    1970-01-01 01:00:00.000000000 +0100
127 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_connlimit.h        2004-02-16 11:07:11.549190614 +0100
128 @@ -0,0 +1,12 @@
129 +#ifndef _IPT_CONNLIMIT_H
130 +#define _IPT_CONNLIMIT_H
131 +
132 +struct ipt_connlimit_data;
133 +
134 +struct ipt_connlimit_info {
135 +       int limit;
136 +       int inverse;
137 +       u_int32_t mask;
138 +       struct ipt_connlimit_data *data;
139 +};
140 +#endif /* _IPT_CONNLIMIT_H */
141 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h
142 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h     1970-01-01 01:00:00.000000000 +0100
143 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-02-16 11:07:13.230787904 +0100
144 @@ -0,0 +1,36 @@
145 +#ifndef _IPT_DSTLIMIT_H
146 +#define _IPT_DSTLIMIT_H
147 +
148 +/* timings are in milliseconds. */
149 +#define IPT_DSTLIMIT_SCALE 10000
150 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
151 +   seconds, or one every 59 hours. */
152 +
153 +/* details of this structure hidden by the implementation */
154 +struct ipt_dstlimit_htable;
155 +
156 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
157 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
158 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
159 +
160 +struct ipt_dstlimit_info {
161 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
162 +       u_int32_t avg;    /* Average secs between packets * scale */
163 +       u_int32_t burst;  /* Period multiplier for upper limit. */
164 +
165 +       /* user specified */
166 +       unsigned int size;              /* how many buckets */
167 +       unsigned int max;               /* max number of entries */
168 +       unsigned int gc_interval;       /* gc interval */
169 +       unsigned int expire;            /* when do entries expire? */
170 +       char name [IFNAMSIZ];           /* name */
171 +
172 +       struct ipt_dstlimit_htable *hinfo;
173 +
174 +       /* Used internally by the kernel */
175 +       union {
176 +               void *ptr;
177 +               struct ipt_dstlimit_info *master;
178 +       } u;
179 +};
180 +#endif /*_IPT_DSTLIMIT_H*/
181 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h
182 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h        1970-01-01 01:00:00.000000000 +0100
183 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_fuzzy.h    2004-02-16 11:07:14.925382080 +0100
184 @@ -0,0 +1,21 @@
185 +#ifndef _IPT_FUZZY_H
186 +#define _IPT_FUZZY_H
187 +
188 +#include <linux/param.h>
189 +#include <linux/types.h>
190 +
191 +#define MAXFUZZYRATE 10000000
192 +#define MINFUZZYRATE 3
193 +
194 +struct ipt_fuzzy_info {
195 +       u_int32_t minimum_rate;
196 +       u_int32_t maximum_rate;
197 +       u_int32_t packets_total;
198 +       u_int32_t bytes_total;
199 +       u_int32_t previous_time;
200 +       u_int32_t present_time;
201 +       u_int32_t mean_rate;
202 +       u_int8_t acceptance_rate;
203 +};
204 +
205 +#endif /*_IPT_FUZZY_H*/
206 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h
207 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h  1970-01-01 01:00:00.000000000 +0100
208 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_ipv4options.h      2004-02-16 11:07:16.164085433 +0100
209 @@ -0,0 +1,21 @@
210 +#ifndef __ipt_ipv4options_h_included__
211 +#define __ipt_ipv4options_h_included__
212 +
213 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
214 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
215 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
216 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
217 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
218 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
219 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
220 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
221 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
222 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
223 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
224 +
225 +struct ipt_ipv4options_info {
226 +       u_int16_t options;
227 +};
228 +
229 +
230 +#endif /* __ipt_ipv4options_h_included__ */
231 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_mport.h
232 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_mport.h        1970-01-01 01:00:00.000000000 +0100
233 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_mport.h    2004-02-16 11:07:17.665725817 +0100
234 @@ -0,0 +1,24 @@
235 +#ifndef _IPT_MPORT_H
236 +#define _IPT_MPORT_H
237 +#include <linux/netfilter_ipv4/ip_tables.h>
238 +
239 +#define IPT_MPORT_SOURCE (1<<0)
240 +#define IPT_MPORT_DESTINATION (1<<1)
241 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
242 +
243 +#define IPT_MULTI_PORTS        15
244 +
245 +/* Must fit inside union ipt_matchinfo: 32 bytes */
246 +/* every entry in ports[] except for the last one has one bit in pflags
247 + * associated with it. If this bit is set, the port is the first port of
248 + * a portrange, with the next entry being the last.
249 + * End of list is marked with pflags bit set and port=65535.
250 + * If 14 ports are used (last one does not have a pflag), the last port
251 + * is repeated to fill the last entry in ports[] */
252 +struct ipt_mport
253 +{
254 +       u_int8_t flags:2;                       /* Type of comparison */
255 +       u_int16_t pflags:14;                    /* Port flags */
256 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
257 +};
258 +#endif /*_IPT_MPORT_H*/
259 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_nth.h
260 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_nth.h  1970-01-01 01:00:00.000000000 +0100
261 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_nth.h      2004-02-16 11:07:18.796455028 +0100
262 @@ -0,0 +1,19 @@
263 +#ifndef _IPT_NTH_H
264 +#define _IPT_NTH_H
265 +
266 +#include <linux/param.h>
267 +#include <linux/types.h>
268 +
269 +#ifndef IPT_NTH_NUM_COUNTERS
270 +#define IPT_NTH_NUM_COUNTERS 16
271 +#endif
272 +
273 +struct ipt_nth_info {
274 +       u_int8_t every;
275 +       u_int8_t not;
276 +       u_int8_t startat;
277 +       u_int8_t counter;
278 +       u_int8_t packet;
279 +};
280 +
281 +#endif /*_IPT_NTH_H*/
282 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_osf.h
283 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_osf.h  1970-01-01 01:00:00.000000000 +0100
284 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_osf.h      2004-02-16 11:07:19.917186632 +0100
285 @@ -0,0 +1,130 @@
286 +/*
287 + * ipt_osf.h
288 + *
289 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
290 + *
291 + *
292 + * This program is free software; you can redistribute it and/or modify
293 + * it under the terms of the GNU General Public License as published by
294 + * the Free Software Foundation; either version 2 of the License, or
295 + * (at your option) any later version.
296 + *
297 + * This program is distributed in the hope that it will be useful,
298 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
299 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
300 + * GNU General Public License for more details.
301 + *
302 + * You should have received a copy of the GNU General Public License
303 + * along with this program; if not, write to the Free Software
304 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
305 + */
306 +
307 +#ifndef _IPT_OSF_H
308 +#define _IPT_OSF_H
309 +
310 +#define MAXGENRELEN            32
311 +#define MAXDETLEN              64
312 +
313 +#define IPT_OSF_GENRE          1
314 +#define IPT_OSF_SMART          2
315 +#define IPT_OSF_LOG            4
316 +
317 +#define IPT_OSF_LOGLEVEL_ALL           0
318 +#define IPT_OSF_LOGLEVEL_FIRST 1
319 +
320 +#include <linux/list.h>
321 +
322 +struct ipt_osf_info
323 +{
324 +       char                    genre[MAXGENRELEN];
325 +       int                     len;
326 +       unsigned long           flags;
327 +       int                     loglevel;
328 +       int                     invert; /* UNSUPPORTED */
329 +};
330 +
331 +struct osf_wc
332 +{
333 +       char                    wc;
334 +       unsigned long           val;
335 +};
336 +
337 +/* This struct represents IANA options
338 + * http://www.iana.org/assignments/tcp-parameters
339 + */
340 +struct osf_opt
341 +{
342 +       unsigned char           kind;
343 +       unsigned char           length;
344 +       struct osf_wc           wc;
345 +};
346 +
347 +#ifdef __KERNEL__
348 +
349 +struct osf_finger
350 +{
351 +       struct list_head        flist;
352 +       struct osf_wc           wss;
353 +       unsigned char           ttl;
354 +       unsigned char           df;
355 +       unsigned long           ss;
356 +       char                    genre[MAXGENRELEN];
357 +       char                    version[MAXGENRELEN], subtype[MAXGENRELEN];
358 +       
359 +       /* Not needed, but for consistency with original table from Michal Zalewski */
360 +       char                    details[MAXDETLEN]; 
361 +
362 +       int                     opt_num;
363 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
364 +
365 +};
366 +
367 +/* Defines for IANA option kinds */
368 +
369 +#define OSFOPT_EOL             0       /* End of options */
370 +#define OSFOPT_NOP             1       /* NOP */
371 +#define OSFOPT_MSS             2       /* Maximum segment size */
372 +#define OSFOPT_WSO             3       /* Window scale option */
373 +#define OSFOPT_SACKP           4       /* SACK permitted */
374 +#define OSFOPT_SACK            5       /* SACK */
375 +#define OSFOPT_ECHO            6       
376 +#define OSFOPT_ECHOREPLY       7
377 +#define OSFOPT_TS              8       /* Timestamp option */
378 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
379 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
380 +/* Others are not used in current OSF */
381 +
382 +static struct osf_opt IANA_opts[] = 
383 +{
384 +       {0, 1,},
385 +       {1, 1,},
386 +       {2, 4,},
387 +       {3, 3,},
388 +       {4, 2,},
389 +       {5, 1 ,}, /* SACK length is not defined */
390 +       {6, 6,},
391 +       {7, 6,},
392 +       {8, 10,},
393 +       {9, 2,},
394 +       {10, 3,},
395 +       {11, 1,}, /* CC: Suppose 1 */
396 +       {12, 1,}, /* the same */
397 +       {13, 1,}, /* and here too */
398 +       {14, 3,},
399 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
400 +       {16, 1,},
401 +       {17, 1,},
402 +       {18, 3,},
403 +       {19, 18,},
404 +       {20, 1,},
405 +       {21, 1,},
406 +       {22, 1,},
407 +       {23, 1,},
408 +       {24, 1,},
409 +       {25, 1,},
410 +       {26, 1,},
411 +};
412 +
413 +#endif /* __KERNEL__ */
414 +
415 +#endif /* _IPT_OSF_H */
416 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_pool.h
417 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
418 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_pool.h     2004-02-16 11:07:21.518803072 +0100
419 @@ -0,0 +1,25 @@
420 +#ifndef _IPT_POOL_H
421 +#define _IPT_POOL_H
422 +
423 +#include <linux/netfilter_ipv4/ip_pool.h>
424 +
425 +#define IPT_POOL_INV_SRC       0x00000001
426 +#define IPT_POOL_INV_DST       0x00000002
427 +#define IPT_POOL_DEL_SRC       0x00000004
428 +#define IPT_POOL_DEL_DST       0x00000008
429 +#define IPT_POOL_INV_MOD_SRC   0x00000010
430 +#define IPT_POOL_INV_MOD_DST   0x00000020
431 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
432 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
433 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
434 +#define IPT_POOL_MOD_DST_DROP  0x00000200
435 +
436 +/* match info */
437 +struct ipt_pool_info
438 +{
439 +       ip_pool_t src;
440 +       ip_pool_t dst;
441 +       unsigned flags;
442 +};
443 +
444 +#endif /*_IPT_POOL_H*/
445 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_psd.h
446 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_psd.h  1970-01-01 01:00:00.000000000 +0100
447 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_psd.h      2004-02-16 11:07:22.387595011 +0100
448 @@ -0,0 +1,40 @@
449 +#ifndef _IPT_PSD_H
450 +#define _IPT_PSD_H
451 +
452 +#include <linux/param.h>
453 +#include <linux/types.h>
454 +
455 +/*
456 + * High port numbers have a lower weight to reduce the frequency of false
457 + * positives, such as from passive mode FTP transfers.
458 + */
459 +#define PORT_WEIGHT_PRIV               3
460 +#define PORT_WEIGHT_HIGH               1
461 +
462 +/*
463 + * Port scan detection thresholds: at least COUNT ports need to be scanned
464 + * from the same source, with no longer than DELAY ticks between ports.
465 + */
466 +#define SCAN_MIN_COUNT                 7
467 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
468 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
469 +#define SCAN_DELAY_THRESHOLD           (HZ * 3)
470 +
471 +/*
472 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
473 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
474 + * HASH_MAX source addresses per the same hash value.
475 + */
476 +#define LIST_SIZE                      0x100
477 +#define HASH_LOG                       9
478 +#define HASH_SIZE                      (1 << HASH_LOG)
479 +#define HASH_MAX                       0x10
480 +
481 +struct ipt_psd_info {
482 +       unsigned int weight_threshold;
483 +       unsigned int delay_threshold;
484 +       unsigned short lo_ports_weight;
485 +       unsigned short hi_ports_weight;
486 +};
487 +
488 +#endif /*_IPT_PSD_H*/
489 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_quota.h
490 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_quota.h        1970-01-01 01:00:00.000000000 +0100
491 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_quota.h    2004-02-16 11:07:23.219395809 +0100
492 @@ -0,0 +1,11 @@
493 +#ifndef _IPT_QUOTA_H
494 +#define _IPT_QUOTA_H
495 +
496 +/* print debug info in both kernel/netfilter module & iptable library */
497 +//#define DEBUG_IPT_QUOTA
498 +
499 +struct ipt_quota_info {
500 +        u_int64_t quota;
501 +};
502 +
503 +#endif /*_IPT_QUOTA_H*/
504 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_random.h
505 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_random.h       1970-01-01 01:00:00.000000000 +0100
506 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_random.h   2004-02-16 11:07:24.378118313 +0100
507 @@ -0,0 +1,11 @@
508 +#ifndef _IPT_RAND_H
509 +#define _IPT_RAND_H
510 +
511 +#include <linux/param.h>
512 +#include <linux/types.h>
513 +
514 +struct ipt_rand_info {
515 +       u_int8_t average;
516 +};
517 +
518 +#endif /*_IPT_RAND_H*/
519 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_realm.h
520 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_realm.h        1970-01-01 01:00:00.000000000 +0100
521 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_realm.h    2004-02-16 11:07:26.369641375 +0100
522 @@ -0,0 +1,9 @@
523 +#ifndef _IPT_REALM_H
524 +#define _IPT_REALM_H
525 +
526 +struct ipt_realm_info {
527 +       u_int32_t id;
528 +       u_int32_t mask;
529 +       u_int8_t invert;
530 +};
531 +#endif /*_IPT_REALM_H*/
532 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_time.h
533 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
534 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_time.h     2004-02-16 11:07:27.150454383 +0100
535 @@ -0,0 +1,13 @@
536 +#ifndef __ipt_time_h_included__
537 +#define __ipt_time_h_included__
538 +
539 +
540 +struct ipt_time_info {
541 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
542 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
543 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
544 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
545 +};
546 +
547 +
548 +#endif /* __ipt_time_h_included__ */
549 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_u32.h
550 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv4/ipt_u32.h  1970-01-01 01:00:00.000000000 +0100
551 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv4/ipt_u32.h      2004-02-16 11:07:28.175208970 +0100
552 @@ -0,0 +1,40 @@
553 +#ifndef _IPT_U32_H
554 +#define _IPT_U32_H
555 +#include <linux/netfilter_ipv4/ip_tables.h>
556 +
557 +enum ipt_u32_ops
558 +{
559 +       IPT_U32_AND,
560 +       IPT_U32_LEFTSH,
561 +       IPT_U32_RIGHTSH,
562 +       IPT_U32_AT
563 +};
564 +
565 +struct ipt_u32_location_element
566 +{
567 +       u_int32_t number;
568 +       u_int8_t nextop;
569 +};
570 +struct ipt_u32_value_element
571 +{
572 +       u_int32_t min;
573 +       u_int32_t max;
574 +};
575 +/* *** any way to allow for an arbitrary number of elements?
576 +   for now I settle for a limit of 10 of each */
577 +#define U32MAXSIZE 10
578 +struct ipt_u32_test
579 +{
580 +       u_int8_t nnums;
581 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
582 +       u_int8_t nvalues;
583 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
584 +};
585 +
586 +struct ipt_u32
587 +{
588 +       u_int8_t ntests;
589 +       struct ipt_u32_test tests[U32MAXSIZE+1];
590 +};
591 +
592 +#endif /*_IPT_U32_H*/
593 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_HL.h
594 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_HL.h  1970-01-01 01:00:00.000000000 +0100
595 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_HL.h      2004-02-16 11:06:53.521507853 +0100
596 @@ -0,0 +1,22 @@
597 +/* Hop Limit modification module for ip6tables
598 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
599 + * Based on HW's TTL module */
600 +
601 +#ifndef _IP6T_HL_H
602 +#define _IP6T_HL_H
603 +
604 +enum {
605 +       IP6T_HL_SET = 0,
606 +       IP6T_HL_INC,
607 +       IP6T_HL_DEC
608 +};
609 +
610 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
611 +
612 +struct ip6t_HL_info {
613 +       u_int8_t        mode;
614 +       u_int8_t        hop_limit;
615 +};
616 +
617 +
618 +#endif
619 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h
620 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-02-15 03:44:09.000000000 +0100
621 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-02-16 11:07:07.812085576 +0100
622 @@ -2,15 +2,17 @@
623  #define _IP6T_REJECT_H
624  
625  enum ip6t_reject_with {
626 -       IP6T_ICMP_NET_UNREACHABLE,
627 -       IP6T_ICMP_HOST_UNREACHABLE,
628 -       IP6T_ICMP_PROT_UNREACHABLE,
629 -       IP6T_ICMP_PORT_UNREACHABLE,
630 -       IP6T_ICMP_ECHOREPLY
631 +       IP6T_ICMP6_NO_ROUTE,
632 +       IP6T_ICMP6_ADM_PROHIBITED,
633 +       IP6T_ICMP6_NOT_NEIGHBOUR,
634 +       IP6T_ICMP6_ADDR_UNREACH,
635 +       IP6T_ICMP6_PORT_UNREACH,
636 +       IP6T_ICMP6_ECHOREPLY,
637 +       IP6T_TCP_RESET
638  };
639  
640  struct ip6t_reject_info {
641         enum ip6t_reject_with with;      /* reject type */
642  };
643  
644 -#endif /*_IPT_REJECT_H*/
645 +#endif /*_IP6T_REJECT_H*/
646 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
647 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h       1970-01-01 01:00:00.000000000 +0100
648 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_fuzzy.h   2004-02-16 11:07:14.925382080 +0100
649 @@ -0,0 +1,21 @@
650 +#ifndef _IP6T_FUZZY_H
651 +#define _IP6T_FUZZY_H
652 +
653 +#include <linux/param.h>
654 +#include <linux/types.h>
655 +
656 +#define MAXFUZZYRATE 10000000
657 +#define MINFUZZYRATE 3
658 +
659 +struct ip6t_fuzzy_info {
660 +       u_int32_t minimum_rate;
661 +       u_int32_t maximum_rate;
662 +       u_int32_t packets_total;
663 +       u_int32_t bytes_total;
664 +       u_int32_t previous_time;
665 +       u_int32_t present_time;
666 +       u_int32_t mean_rate;
667 +       u_int8_t acceptance_rate;
668 +};
669 +
670 +#endif /*_IP6T_FUZZY_H*/
671 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_nth.h
672 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
673 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_nth.h     2004-02-16 11:07:18.796455028 +0100
674 @@ -0,0 +1,19 @@
675 +#ifndef _IP6T_NTH_H
676 +#define _IP6T_NTH_H
677 +
678 +#include <linux/param.h>
679 +#include <linux/types.h>
680 +
681 +#ifndef IP6T_NTH_NUM_COUNTERS
682 +#define IP6T_NTH_NUM_COUNTERS 16
683 +#endif
684 +
685 +struct ip6t_nth_info {
686 +       u_int8_t every;
687 +       u_int8_t not;
688 +       u_int8_t startat;
689 +       u_int8_t counter;
690 +       u_int8_t packet;
691 +};
692 +
693 +#endif /*_IP6T_NTH_H*/
694 diff -Nur linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_random.h
695 --- linux-2.6.3-rc3.org/include/linux/netfilter_ipv6/ip6t_random.h      1970-01-01 01:00:00.000000000 +0100
696 +++ linux-2.6.3-rc3/include/linux/netfilter_ipv6/ip6t_random.h  2004-02-16 11:07:24.378118313 +0100
697 @@ -0,0 +1,11 @@
698 +#ifndef _IP6T_RAND_H
699 +#define _IP6T_RAND_H
700 +
701 +#include <linux/param.h>
702 +#include <linux/types.h>
703 +
704 +struct ip6t_rand_info {
705 +       u_int8_t average;
706 +};
707 +
708 +#endif /*_IP6T_RAND_H*/
709 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/Kconfig linux-2.6.3-rc3/net/ipv4/netfilter/Kconfig
710 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/Kconfig      2004-02-16 10:08:59.000000000 +0100
711 +++ linux-2.6.3-rc3/net/ipv4/netfilter/Kconfig  2004-02-16 11:07:28.178208252 +0100
712 @@ -588,5 +588,384 @@
713  
714           To compile it as a module, choose M here.  If unsure, say N.
715  
716 +config IP_NF_TARGET_IPV4OPTSSTRIP
717 +       tristate  'IPV4OPTSSTRIP target support'
718 +       depends on IP_NF_MANGLE
719 +         help
720 +         This option adds CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP, which supplies a target
721 +         module that will allow you to strip all the IP options from a packet.
722 +         
723 +         The target doesn't take any option, and therefore is extremly easy to use :
724 +         
725 +         # iptables -t mangle -A PREROUTING -j IPV4OPTSSTRIP
726 +         # iptables -t mangle --list -n
727 +         Chain PREROUTING (policy ACCEPT)
728 +         target     prot opt source               destination
729 +         IPV4OPTSSTRIP  all  --  0.0.0.0/0            0.0.0.0/0
730 +         
731 +         Chain OUTPUT (policy ACCEPT)
732 +         target     prot opt source               destination
733 +
734 +config IP_NF_TARGET_NETLINK
735 +       tristate  'NETLINK target support'
736 +       depends on IP_NF_FILTER
737 +         help
738 +         CONFIG_IP_NF_TARGET_NETLINK adds a NETLINK target that sends dropped packets to
739 +         userspace via a netlink socket.  Apps such as fwmon
740 +         (http://firestorm.geek-ware.co.uk) can then recieve and dislpay these packets.
741 +         This option is basically a re-implementation of the ipchains -o option.
742 +
743 +config IP_NF_TARGET_TTL
744 +       tristate  'TTL target support'
745 +       depends on IP_NF_MANGLE
746 +         help
747 +         This adds an iptables TTL manipulation target, which enables the user
748 +         to set the TTL value of an IP packet or to increment / decrement it 
749 +         by a given value.
750 +
751 +config IP_NF_MATCH_CONNLIMIT
752 +       tristate  'Connections/IP limit match support'
753 +       depends on IP_NF_IPTABLES
754 +         help
755 +         This adds an iptables match which allows you to restrict the
756 +         number of parallel TCP connections to a server per client IP address
757 +         (or address block).
758 +         
759 +         Examples:
760 +         
761 +         # allow 2 telnet connections per client host
762 +         iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
763 +         
764 +         # you can also match the other way around:
765 +         iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
766 +         
767 +         # limit the nr of parallel http requests to 16 per class C sized
768 +         # network (24 bit netmask)
769 +         iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 \
770 +               --connlimit-mask 24 -j REJECT
771 +
772 +config IP_NF_MATCH_DSTLIMIT
773 +       tristate  'dstlimit match support'
774 +       depends on IP_NF_IPTABLES
775 +         help
776 +         
777 +         This patch adds a new match called 'dstlimit'.  
778 +         The idea is to have something like 'limit', but either per 
779 +         destination-ip or per (destip,destport) tuple.
780 +         
781 +         It gives you the ability to say 
782 +               '1000 packets per second for every host in 192.168.0.0/16'
783 +               '100 packets per second for every service of 192.168.1.1'
784 +         
785 +         Parameters are:
786 +               --dstlimit <rate>
787 +                       A rate just like the limit match
788 +               --dstlimit-burst <num>
789 +                       Burst value, just like limit match
790 +               --dstlimit-mode destip | destip-destport
791 +                       Limit per IP or per port
792 +               --dstlimit-name foo
793 +                       The name for the /proc/net/ipt_dstlimit/foo entry
794 +               --dstlimit-htable-size <num>
795 +                       The number of buckets of the hash table
796 +               --dstlimit-htable-max <num>
797 +                       Maximum entries in the hash
798 +               --dstlimit-htable-expire <num>
799 +                       After how many miliseconds do hash entries expire
800 +               --dstlimit-htable-gcinterval <num>
801 +                       How many miliseconds between garbage collection intervals
802 +         
803 +
804 +config IP_NF_MATCH_FUZZY
805 +       tristate  'fuzzy match support'
806 +       depends on IP_NF_IPTABLES
807 +         help
808 +         This option adds a `fuzzy' match which allows you to match packets according to
809 +         a dynamic profile implemented by means of a simple Fuzzy Logic Controller (FLC)
810 +
811 +config IP_NF_MATCH_IPV4OPTIONS
812 +       tristate  'IPV4OPTIONS match support'
813 +       depends on IP_NF_IPTABLES
814 +         help
815 +         This option adds an iptables 'ipv4options' match, which allows you to
816 +         match on IPv4 header options like source routing, record route, timestamp and
817 +         router-alert.
818 +         
819 +         Suppported options are:
820 +         --ssrr
821 +           To match packets with the flag strict source routing.
822 +         --lsrr
823 +           To match packets with the flag loose source routing.
824 +         --no-srr
825 +           To match packets with no flag for source routing.
826 +         [!] --rr
827 +           To match packets with the RR flag.
828 +         [!] --ts
829 +           To match packets with the TS flag.
830 +         [!] --ra
831 +           To match packets with the router-alert option.
832 +         [!] --any-opt
833 +           To match a packet with at least one IP option, or no IP option
834 +           at all if ! is chosen.
835 +         
836 +         Example:
837 +           $ iptables -A input -m ipv4options --rr -j DROP
838 +           will drop packets with the record-route flag.
839 +         
840 +           $ iptables -A input -m ipv4options --ts -j DROP
841 +           will drop packets with the timestamp flag.
842 +
843 +config IP_NF_MATCH_MPORT
844 +       tristate  'Multiple port with ranges match support'
845 +       depends on IP_NF_IPTABLES
846 +         help
847 +         This module is an enhanced multiport match. It has support for byte
848 +         ranges as well as for single ports.
849 +         Up to 15 ports are allowed. Note that a portrange uses up 2 port values.
850 +         
851 +         Examples:
852 +         # iptables -A FORWARD -p tcp -m mport --ports 23:42,65
853 +
854 +config IP_NF_MATCH_NTH
855 +       tristate  'Nth match support'
856 +       depends on IP_NF_IPTABLES
857 +         help
858 +         This option adds an iptables `Nth' match, which allows you to match every Nth
859 +         packet encountered.  By default there are 16 different counters that can be
860 +         used.
861 +         
862 +         This match functions in one of two ways
863 +         1) Match ever Nth packet, and only the Nth packet.
864 +            example:
865 +             iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
866 +            This rule will drop every 10th packet.
867 +         2) Unique rule for every packet.  This is an easy and quick
868 +            method to produce load-balancing for both inbound and outbound.
869 +            example:
870 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
871 +                      --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
872 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
873 +                      --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
874 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
875 +                      --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
876 +            This example evenly splits connections between the three SNAT
877 +            addresses.
878 +         
879 +            By using the mangle table and iproute2, you can setup complex
880 +            load-balanced routing.  There's lot of other uses.  Be creative!
881 +         
882 +         Suppported options are:
883 +            --every     Nth         Match every Nth packet
884 +           [--counter]  num         Use counter 0-15 (default:0)
885 +           [--start]    num         Initialize the counter at the number 'num'
886 +                                    instead of 0. Must be between 0 and Nth-1
887 +           [--packet]   num         Match on 'num' packet. Must be between 0
888 +                                    and Nth-1.
889 +                                    If --packet is used for a counter than
890 +                                    there must be Nth number of --packet
891 +                                    rules, covering all values between 0 and
892 +                                    Nth-1 inclusively.
893 +
894 +config IP_NF_MATCH_OSF
895 +       tristate  'OSF match support'
896 +       depends on IP_NF_IPTABLES
897 +         help
898 +         The idea of passive OS fingerprint matching exists for quite a long time,
899 +         but was created as extension fo OpenBSD pf only some weeks ago.
900 +         Original idea was lurked in some OpenBSD mailing list (thanks
901 +         grange@open...) and than adopted for Linux netfilter in form of this code.
902 +         
903 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
904 +         his excellent p0f and than changed a bit for more convenience.
905 +         
906 +         This module compares some data(WS, MSS, options and it's order, ttl,
907 +         df and others) from first SYN packet (actually from packets with SYN
908 +         bit set) with hardcoded in fingers[] table ones.
909 +         
910 +         Example: (Of course this only an example, do not get inspired by this)
911 +         
912 +         # iptables -N LINUX
913 +         # iptables -A LINUX -j LOG --log-prefix "Linux"
914 +         
915 +         # iptables -A INPUT -p tcp -m osf --genre Linux -j LINUX
916 +         # iptables -A INPUT -p tcp -m osf --genre FreeBSD -j REJECT
917 +         
918 +         NOTE: -p tcp is obviously required as it is a TCP match.
919 +         
920 +         OSF also has:
921 +         --log 1/0. 
922 +               If present, OSF will log determined genres even if they don't match
923 +               desired one.    
924 +               0 - log all determined entries, 
925 +               1 - only first one.
926 +               
927 +               Example:
928 +               #iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
929 +         
930 +               In syslog you find something like this:
931 +               ipt_osf: Windows [Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
932 +               ipt_osf: Unknown: 16384:106:1:48:020405B401010402 44.33.22.11:1239 -> 11.22.33.44:80
933 +         
934 +           --smart
935 +               if present, OSF will use some smartness to determine remote OS.
936 +               Now only not use TTL( with it far remote machines can be determined).
937 +         
938 +         Fingerprints can be loaded through /proc/sys/net/ipv4/osf file.
939 +         Only one fingerprint per open/close.
940 +         
941 +         Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
942 +
943 +config IP_POOL_STATISTICS
944 +       bool  'enable statistics on pool usage'
945 +       depends on IP_NF_POOL!=n
946 +
947 +config IP_NF_POOL
948 +       tristate  'IP address pool support'
949 +       depends on IP_NF_IPTABLES
950 +         help
951 +         CONFIG_IP_NF_POOL provides a match which lets you use bitmaps with one bit per
952 +         address from some range of IP addresses; the match depends on whether a checked
953 +         source or destination address has its bit set in the pool.  It also provides a
954 +         POOL target, which can be used to add or remove the addresses of a packet
955 +         to/from a pool.
956 +         
957 +         There is also a POOL netfilter target, which can be used to set or remove the
958 +         addresses of a packet from a pool.
959 +         
960 +         To define and use pools, you need userlevel utilities: a patched iptables, and
961 +         the program ippool(8), which defines the pools and their bounds.  The current
962 +         release of pool matching is ippool-0.0.2, and can be found in the archives of
963 +         the netfilter mailing list at http://lists.netfilter.org/.
964 +
965 +config IP_NF_MATCH_PSD
966 +       tristate  'psd match support'
967 +       depends on IP_NF_IPTABLES
968 +         help
969 +         This option adds a `psd' match, which supplies portscan
970 +         detection match (psd). This match will attempt to detect TCP and UDP
971 +         port scans. This match was derived from Solar Designer's scanlogd.
972 +         
973 +         Suppported options are:
974 +         
975 +         --psd-weight-threshold <threshold>
976 +         
977 +           Total weight of the latest TCP/UDP packets with different
978 +           destination ports coming from the same host to be treated as port
979 +           scan sequence.
980 +         
981 +         --psd-delay-threshold <delay>
982 +         
983 +           Delay (in hundredths of second) for the packets with different
984 +           destination ports coming from the same host to be treated as
985 +           possible port scan subsequence.
986 +         
987 +         --psd-lo-ports-weight <weight>
988 +         
989 +           Weight of the packet with privileged (<=1024) destination port.
990 +         
991 +         --psd-hi-ports-weight <weight>
992 +         
993 +           Weight of the packet with non-priviliged destination port.
994 +
995 +config IP_NF_MATCH_QUOTA
996 +       tristate  'quota match support'
997 +       depends on IP_NF_IPTABLES
998 +         help
999 +         This option adds CONFIG_IP_NF_MATCH_QUOTA, which implements network
1000 +         quotas by decrementing a byte counter with each packet.
1001 +         
1002 +         Supported options are:
1003 +         --quota <bytes>
1004 +           The quota in bytes.
1005 +         
1006 +         KNOWN BUGS: this does not work on SMP systems.
1007 +         
1008 +
1009 +config IP_NF_MATCH_RANDOM
1010 +       tristate  'random match support'
1011 +       depends on IP_NF_IPTABLES
1012 +         help
1013 +         This option adds a `random' match,
1014 +         which allow you to match packets randomly
1015 +         following a given probability. 
1016 +         
1017 +         Suppported options are:
1018 +         
1019 +         [--average]   percent will match randomly packets with a probability of
1020 +                       'percent'. default is 50%
1021 +
1022 +config IP_NF_MATCH_REALM
1023 +       tristate  'realm match support'
1024 +       depends on IP_NF_IPTABLES
1025 +         help
1026 +         realm match: uses realm key from routing as match criteria similiar to
1027 +                      one in packet classifier
1028 +         
1029 +         /** snip from packet classifier documentation */
1030 +         Routing tables based classifier
1031 +         CONFIG_NET_CLS_ROUTE4
1032 +           If you say Y here, you will be able to classify outgoing packets
1033 +           according to the route table entry they matched. If unsure, say Y.
1034 +         /** end snip **/
1035 +         
1036 +         
1037 +         # Example
1038 +         # add route
1039 +         /sbin/ip route add 194.29.194.0/24 via 194.29.192.1 realm 10
1040 +         
1041 +         # source realm is in realm with mask 0xFFFF0000,
1042 +         # destination is in realm with mask 0x0000FFFF
1043 +         
1044 +         # match destination realm
1045 +         /usr/local/sbin/iptables -A OUTPUT -m realm --realm 10 -j LOG
1046 +         
1047 +         # match realm of source, this is also determinated by routing,
1048 +         /usr/local/sbin/iptables -A INPUT -m realm --realm 655360 -j LOG
1049 +         
1050 +         THIS PATCH REQUIRES CONFIG_NET_CLS_ROUTE TO BE SET
1051 +
1052 +config IP_NF_MATCH_TIME
1053 +       tristate  'TIME match support'
1054 +       depends on IP_NF_IPTABLES
1055 +         help
1056 +         
1057 +         This option adds CONFIG_IP_NF_MATCH_TIME, which supplies a time match module.
1058 +         This match allows you to filter based on the packet arrival time
1059 +         (arrival time at the machine which the netfilter is running on) or
1060 +         departure time (for locally generated packets).
1061 +         
1062 +         Supported options are:
1063 +         --timestart HH:MM
1064 +           The starting point of the time match frame.
1065 +         
1066 +         --timestop HH:MM
1067 +           The stopping point of the time match frame
1068 +         
1069 +         --days Tue,Mon...
1070 +           Days of the week to match separated by a coma, no space
1071 +           (one of Sun,Mon,Tue,Wed,Thu,Fri,Sat)
1072 +         
1073 +         Example:
1074 +           -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon,Tue,Wed,Thu,Fri
1075 +           will match packets that have an arrival timestamp in the range 8:00->18:00 from Monday
1076 +           to Friday.
1077 +         
1078 +           -A OUTPUT -m time --timestart 8:00 --timestop 18:00 --Days Mon
1079 +           will match the packets (locally generated) that have a departure timestamp
1080 +           in the range 8:00->18:00 on Monday only.
1081 +
1082 +config IP_NF_MATCH_U32
1083 +       tristate  'U32 match support'
1084 +       depends on IP_NF_IPTABLES
1085 +         help
1086 +         
1087 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
1088 +         AND them with specified masks, shift them by specified amounts and
1089 +         test whether the results are in any of a set of specified ranges.
1090 +         The specification of what to extract is general enough to skip over
1091 +         headers with lengths stored in the packet, as in IP or TCP header
1092 +         lengths.
1093 +         Details and examples are in the kernel module source.
1094 +
1095  endmenu
1096  
1097 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/Makefile linux-2.6.3-rc3/net/ipv4/netfilter/Makefile
1098 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/Makefile     2004-02-16 10:08:59.000000000 +0100
1099 +++ linux-2.6.3-rc3/net/ipv4/netfilter/Makefile 2004-02-16 11:07:28.178208252 +0100
1100 @@ -42,15 +42,38 @@
1101  # matches
1102  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1103  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1104 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
1105 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
1106  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
1107 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
1108  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
1109  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
1110  
1111  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1112  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1113 +
1114 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1115 +
1116  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1117  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1118  
1119 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1120 +
1121 +
1122 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
1123 +
1124 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1125 +
1126 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1127 +
1128 +
1129 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1130 +
1131 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1132 +
1133 +
1134 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1135 +
1136  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1137  
1138  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1139 @@ -59,10 +82,15 @@
1140  
1141  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1142  
1143 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1144 +
1145 +
1146  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1147  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1148 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1149  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1150  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1151 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1152  
1153  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1154  
1155 @@ -80,6 +108,9 @@
1156  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1157  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1158  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1159 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1160 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1161 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1162  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1163  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1164  
1165 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.3-rc3/net/ipv4/netfilter/ip_pool.c
1166 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ip_pool.c    1970-01-01 01:00:00.000000000 +0100
1167 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ip_pool.c        2004-02-16 11:07:21.518803072 +0100
1168 @@ -0,0 +1,334 @@
1169 +/* Kernel module for IP pool management */
1170 +
1171 +#include <linux/module.h>
1172 +#include <linux/ip.h>
1173 +#include <linux/skbuff.h>
1174 +#include <linux/netfilter_ipv4/ip_tables.h>
1175 +#include <linux/netfilter_ipv4/ip_pool.h>
1176 +#include <linux/errno.h>
1177 +#include <asm/uaccess.h>
1178 +#include <asm/bitops.h>
1179 +#include <linux/interrupt.h>
1180 +#include <linux/spinlock.h>
1181 +
1182 +#if 0
1183 +#define DP printk
1184 +#else
1185 +#define DP(format, args...)
1186 +#endif
1187 +
1188 +MODULE_LICENSE("GPL");
1189 +
1190 +#define NR_POOL 16
1191 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
1192 +
1193 +struct ip_pool {
1194 +       u_int32_t first_ip;     /* host byte order, included in range */
1195 +       u_int32_t last_ip;      /* host byte order, included in range */
1196 +       void *members;          /* the bitmap proper */
1197 +       int nr_use;             /* total nr. of tests through this */
1198 +       int nr_match;           /* total nr. of matches through this */
1199 +       rwlock_t lock;
1200 +};
1201 +
1202 +static struct ip_pool *POOL;
1203 +
1204 +static inline struct ip_pool *lookup(ip_pool_t index)
1205 +{
1206 +       if (index < 0 || index >= nr_pool) {
1207 +               DP("ip_pool:lookup: bad index %d\n", index);
1208 +               return 0;
1209 +       }
1210 +       return POOL+index;
1211 +}
1212 +
1213 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
1214 +{
1215 +        struct ip_pool *pool = lookup(index);
1216 +       int res = 0;
1217 +
1218 +       if (!pool || !pool->members)
1219 +               return 0;
1220 +       read_lock_bh(&pool->lock);
1221 +       if (pool->members) {
1222 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
1223 +                       addr -= pool->first_ip;
1224 +                       if (test_bit(addr, pool->members)) {
1225 +                               res = 1;
1226 +#ifdef CONFIG_IP_POOL_STATISTICS
1227 +                               pool->nr_match++;
1228 +#endif
1229 +                       }
1230 +               }
1231 +#ifdef CONFIG_IP_POOL_STATISTICS
1232 +               pool->nr_use++;
1233 +#endif
1234 +       }
1235 +       read_unlock_bh(&pool->lock);
1236 +       return res;
1237 +}
1238 +EXPORT_SYMBOL(ip_pool_match);
1239 +
1240 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
1241 +{
1242 +       struct ip_pool *pool;
1243 +       int res = -1;
1244 +
1245 +       pool = lookup(index);
1246 +       if (    !pool || !pool->members
1247 +            || addr < pool->first_ip || addr > pool->last_ip)
1248 +               return -1;
1249 +       read_lock_bh(&pool->lock);
1250 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
1251 +               addr -= pool->first_ip;
1252 +               res = isdel
1253 +                       ? (0 != test_and_clear_bit(addr, pool->members))
1254 +                       : (0 != test_and_set_bit(addr, pool->members));
1255 +       }
1256 +       read_unlock_bh(&pool->lock);
1257 +       return res;
1258 +}
1259 +
1260 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
1261 +{
1262 +       int res = pool_change(index,addr,isdel);
1263 +
1264 +       if (!isdel) res = !res;
1265 +       return res;
1266 +}
1267 +EXPORT_SYMBOL(ip_pool_mod);
1268 +
1269 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
1270 +{
1271 +       return 4*((((b-a+8)/8)+3)/4);
1272 +}
1273 +
1274 +static inline int poolbytes(ip_pool_t index)
1275 +{
1276 +       struct ip_pool *pool = lookup(index);
1277 +
1278 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
1279 +}
1280 +
1281 +static int setpool(
1282 +       struct sock *sk,
1283 +       int optval,
1284 +       void *user,
1285 +       unsigned int len
1286 +) {
1287 +       struct ip_pool_request req;
1288 +
1289 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
1290 +       if (!capable(CAP_NET_ADMIN))
1291 +               return -EPERM;
1292 +       if (optval != SO_IP_POOL)
1293 +               return -EBADF;
1294 +       if (len != sizeof(req))
1295 +               return -EINVAL;
1296 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
1297 +               return -EFAULT;
1298 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
1299 +       return -EINVAL;
1300 +}
1301 +
1302 +static int getpool(
1303 +       struct sock *sk,
1304 +       int optval,
1305 +       void *user,
1306 +       int *len
1307 +) {
1308 +       struct ip_pool_request req;
1309 +       struct ip_pool *pool;
1310 +       ip_pool_t i;
1311 +       int newbytes;
1312 +       void *newmembers;
1313 +       int res;
1314 +
1315 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
1316 +       if (!capable(CAP_NET_ADMIN))
1317 +               return -EINVAL;
1318 +       if (optval != SO_IP_POOL)
1319 +               return -EINVAL;
1320 +       if (*len != sizeof(req)) {
1321 +               return -EFAULT;
1322 +       }
1323 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
1324 +               return -EFAULT;
1325 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
1326 +       if (req.op < IP_POOL_BAD001) {
1327 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
1328 +               return -EFAULT;
1329 +       }
1330 +       switch(req.op) {
1331 +       case IP_POOL_HIGH_NR:
1332 +               DP("ip_pool HIGH_NR\n");
1333 +               req.index = IP_POOL_NONE;
1334 +               for (i=0; i<nr_pool; i++)
1335 +                       if (POOL[i].members)
1336 +                               req.index = i;
1337 +               return copy_to_user(user, &req, sizeof(req));
1338 +       case IP_POOL_LOOKUP:
1339 +               DP("ip_pool LOOKUP\n");
1340 +               pool = lookup(req.index);
1341 +               if (!pool)
1342 +                       return -EINVAL;
1343 +               if (!pool->members)
1344 +                       return -EBADF;
1345 +               req.addr = htonl(pool->first_ip);
1346 +               req.addr2 = htonl(pool->last_ip);
1347 +               return copy_to_user(user, &req, sizeof(req));
1348 +       case IP_POOL_USAGE:
1349 +               DP("ip_pool USE\n");
1350 +               pool = lookup(req.index);
1351 +               if (!pool)
1352 +                       return -EINVAL;
1353 +               if (!pool->members)
1354 +                       return -EBADF;
1355 +               req.addr = pool->nr_use;
1356 +               req.addr2 = pool->nr_match;
1357 +               return copy_to_user(user, &req, sizeof(req));
1358 +       case IP_POOL_TEST_ADDR:
1359 +               DP("ip_pool TEST 0x%08x\n", req.addr);
1360 +               pool = lookup(req.index);
1361 +               if (!pool)
1362 +                       return -EINVAL;
1363 +               res = 0;
1364 +               read_lock_bh(&pool->lock);
1365 +               if (!pool->members) {
1366 +                       DP("ip_pool TEST_ADDR no members in pool\n");
1367 +                       res = -EBADF;
1368 +                       goto unlock_and_return_res;
1369 +               }
1370 +               req.addr = ntohl(req.addr);
1371 +               if (req.addr < pool->first_ip) {
1372 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
1373 +                       res = -ERANGE;
1374 +                       goto unlock_and_return_res;
1375 +               }
1376 +               if (req.addr > pool->last_ip) {
1377 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
1378 +                       res = -ERANGE;
1379 +                       goto unlock_and_return_res;
1380 +               }
1381 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
1382 +                                       pool->members));
1383 +               read_unlock_bh(&pool->lock);
1384 +               return copy_to_user(user, &req, sizeof(req));
1385 +       case IP_POOL_FLUSH:
1386 +               DP("ip_pool FLUSH not yet implemented.\n");
1387 +               return -EBUSY;
1388 +       case IP_POOL_DESTROY:
1389 +               DP("ip_pool DESTROY not yet implemented.\n");
1390 +               return -EBUSY;
1391 +       case IP_POOL_INIT:
1392 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
1393 +               pool = lookup(req.index);
1394 +               if (!pool)
1395 +                       return -EINVAL;
1396 +               req.addr = ntohl(req.addr);
1397 +               req.addr2 = ntohl(req.addr2);
1398 +               if (req.addr > req.addr2) {
1399 +                       DP("ip_pool INIT bad ip range\n");
1400 +                       return -EINVAL;
1401 +               }
1402 +               newbytes = bitmap_bytes(req.addr, req.addr2);
1403 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
1404 +               if (!newmembers) {
1405 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
1406 +                       return -ENOMEM;
1407 +               }
1408 +               memset(newmembers, 0, newbytes);
1409 +               write_lock_bh(&pool->lock);
1410 +               if (pool->members) {
1411 +                       DP("ip_pool INIT pool %d exists\n", req.index);
1412 +                       kfree(newmembers);
1413 +                       res = -EBUSY;
1414 +                       goto unlock_and_return_res;
1415 +               }
1416 +               pool->first_ip = req.addr;
1417 +               pool->last_ip = req.addr2;
1418 +               pool->nr_use = 0;
1419 +               pool->nr_match = 0;
1420 +               pool->members = newmembers;
1421 +               write_unlock_bh(&pool->lock);
1422 +               return 0;
1423 +       case IP_POOL_ADD_ADDR:
1424 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
1425 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
1426 +               return copy_to_user(user, &req, sizeof(req));
1427 +       case IP_POOL_DEL_ADDR:
1428 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
1429 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
1430 +               return copy_to_user(user, &req, sizeof(req));
1431 +       default:
1432 +               DP("ip_pool:getpool bad op %d\n", req.op);
1433 +               return -EINVAL;
1434 +       }
1435 +       return -EINVAL;
1436 +
1437 +unlock_and_return_res:
1438 +       if (pool)
1439 +               read_unlock_bh(&pool->lock);
1440 +       return res;
1441 +}
1442 +
1443 +static struct nf_sockopt_ops so_pool
1444 += { { NULL, NULL }, PF_INET,
1445 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
1446 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
1447 +    0, NULL };
1448 +
1449 +MODULE_PARM(nr_pool, "i");
1450 +
1451 +static int __init init(void)
1452 +{
1453 +       ip_pool_t i;
1454 +       int res;
1455 +
1456 +       if (nr_pool < 1) {
1457 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
1458 +               return -EINVAL;
1459 +       }
1460 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
1461 +       if (!POOL) {
1462 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
1463 +                       nr_pool);
1464 +               return -ENOMEM;
1465 +       }
1466 +       for (i=0; i<nr_pool; i++) {
1467 +               POOL[i].first_ip = 0;
1468 +               POOL[i].last_ip = 0;
1469 +               POOL[i].members = 0;
1470 +               POOL[i].nr_use = 0;
1471 +               POOL[i].nr_match = 0;
1472 +               POOL[i].lock = RW_LOCK_UNLOCKED;
1473 +       }
1474 +       res = nf_register_sockopt(&so_pool);
1475 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
1476 +       if (res != 0) {
1477 +               kfree(POOL);
1478 +               POOL = 0;
1479 +       }
1480 +       return res;
1481 +}
1482 +
1483 +static void __exit fini(void)
1484 +{
1485 +       ip_pool_t i;
1486 +
1487 +       DP("ip_pool:fini BYEBYE\n");
1488 +       nf_unregister_sockopt(&so_pool);
1489 +       for (i=0; i<nr_pool; i++) {
1490 +               if (POOL[i].members) {
1491 +                       kfree(POOL[i].members);
1492 +                       POOL[i].members = 0;
1493 +               }
1494 +       }
1495 +       kfree(POOL);
1496 +       POOL = 0;
1497 +       DP("ip_pool:fini these are the famous last words\n");
1498 +       return;
1499 +}
1500 +
1501 +module_init(init);
1502 +module_exit(fini);
1503 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
1504 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  1970-01-01 01:00:00.000000000 +0100
1505 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      2004-02-16 11:06:57.518550655 +0100
1506 @@ -0,0 +1,84 @@
1507 +/**
1508 + * Strip all IP options in the IP packet header.
1509 + *
1510 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
1511 + * This software is distributed under GNU GPL v2, 1991
1512 + */
1513 +
1514 +#include <linux/module.h>
1515 +#include <linux/skbuff.h>
1516 +#include <linux/ip.h>
1517 +#include <net/checksum.h>
1518 +
1519 +#include <linux/netfilter_ipv4/ip_tables.h>
1520 +
1521 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
1522 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
1523 +MODULE_LICENSE("GPL");
1524 +
1525 +static unsigned int
1526 +target(struct sk_buff **pskb,
1527 +       unsigned int hooknum,
1528 +       const struct net_device *in,
1529 +       const struct net_device *out,
1530 +       const void *targinfo,
1531 +       void *userinfo)
1532 +{
1533 +       struct iphdr *iph = (*pskb)->nh.iph;
1534 +       struct sk_buff *skb = (*pskb);
1535 +       struct ip_options * opt;
1536 +       unsigned char * optiph = skb->nh.raw;
1537 +       int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
1538 +       
1539 +
1540 +       /* if no options in packet then nothing to clear. */
1541 +       if (iph->ihl * 4 == sizeof(struct iphdr))
1542 +               return IPT_CONTINUE;
1543 +
1544 +       /* else clear all options */
1545 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
1546 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
1547 +       opt = &(IPCB(skb)->opt);
1548 +       opt->is_data = 0;
1549 +       opt->optlen = l;
1550 +
1551 +       skb->nfcache |= NFC_ALTERED;
1552 +
1553 +        return IPT_CONTINUE;
1554 +}
1555 +
1556 +static int
1557 +checkentry(const char *tablename,
1558 +          const struct ipt_entry *e,
1559 +           void *targinfo,
1560 +           unsigned int targinfosize,
1561 +           unsigned int hook_mask)
1562 +{
1563 +       if (strcmp(tablename, "mangle")) {
1564 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1565 +               return 0;
1566 +       }
1567 +       /* nothing else to check because no parameters */
1568 +       return 1;
1569 +}
1570 +
1571 +static struct ipt_target ipt_ipv4optsstrip_reg
1572 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
1573 +
1574 +static int __init init(void)
1575 +{
1576 +       if (ipt_register_target(&ipt_ipv4optsstrip_reg))
1577 +               return -EINVAL;
1578 +       printk("ipt_IPV4OPTSSTRIP loaded\n");
1579 +
1580 +       return 0;
1581 +}
1582 +
1583 +static void __exit fini(void)
1584 +{
1585 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
1586 +       printk("ipt_IPV4OPTSSTRIP unloaded\n");
1587 +}
1588 +
1589 +module_init(init);
1590 +module_exit(fini);
1591 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_NETLINK.c
1592 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_NETLINK.c        1970-01-01 01:00:00.000000000 +0100
1593 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_NETLINK.c    2004-02-16 11:07:05.880548139 +0100
1594 @@ -0,0 +1,119 @@
1595 +#include <linux/module.h>
1596 +#include <linux/version.h>
1597 +#include <linux/config.h>
1598 +#include <linux/socket.h>
1599 +#include <linux/skbuff.h>
1600 +#include <linux/kernel.h>
1601 +#include <linux/netlink.h>
1602 +#include <linux/netdevice.h>
1603 +#include <linux/mm.h>
1604 +#include <linux/socket.h>
1605 +#include <linux/netfilter_ipv4/ip_tables.h>
1606 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
1607 +#include <net/sock.h>
1608 +
1609 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
1610 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
1611 +MODULE_LICENSE("GPL");
1612 +
1613 +#if 0
1614 +#define DEBUGP printk
1615 +#else
1616 +#define DEBUGP(format, args...)
1617 +#endif
1618 +
1619 +static struct sock *ipfwsk;
1620 +
1621 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
1622 +                                   unsigned int hooknum,
1623 +                                   const struct net_device *in,
1624 +                                   const struct net_device *out,
1625 +                                   const void *targinfo, void *userinfo)
1626 +{
1627 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
1628 +       struct iphdr *ip = (*pskb)->nh.iph;
1629 +       struct sk_buff *outskb;
1630 +       struct netlink_t nlhdr;
1631 +       size_t len=0;
1632 +
1633 +       /* Allocate a socket buffer */
1634 +       if ( MASK(nld->flags, USE_SIZE) )
1635 +               len = nld->size+sizeof(nlhdr);
1636 +       else
1637 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
1638 +
1639 +       outskb=alloc_skb(len, GFP_ATOMIC);
1640 +
1641 +       if (outskb) {
1642 +               nlhdr.len=len;
1643 +               
1644 +               if ( MASK(nld->flags, USE_MARK) )
1645 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
1646 +               else
1647 +                       nlhdr.mark=(*pskb)->nfmark;
1648 +               
1649 +               if ( in && in->name ) {
1650 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
1651 +               }else if ( out && out->name ){
1652 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
1653 +               }
1654 +
1655 +               skb_put(outskb, len);
1656 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
1657 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
1658 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
1659 +       }else{
1660 +               if (net_ratelimit())
1661 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
1662 +       }
1663 +
1664 +       if ( MASK(nld->flags, USE_DROP) )
1665 +               return NF_DROP;
1666 +
1667 +       return IPT_CONTINUE;
1668 +}
1669 +
1670 +static int ipt_netlink_checkentry(const char *tablename,
1671 +                              const struct ipt_entry *e,
1672 +                              void *targinfo,
1673 +                              unsigned int targinfosize,
1674 +                              unsigned int hookmask)
1675 +{
1676 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
1677 +
1678 +       return 1;
1679 +}
1680 +
1681 +static struct ipt_target ipt_netlink_reg = { 
1682 +       {NULL, NULL},
1683 +       "NETLINK",
1684 +       ipt_netlink_target,
1685 +       ipt_netlink_checkentry,
1686 +       NULL,
1687 +       THIS_MODULE
1688 +};
1689 +
1690 +static int __init init(void)
1691 +{
1692 +       DEBUGP("ipt_NETLINK: init module\n");   
1693 +
1694 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
1695 +               return -EINVAL;
1696 +       }
1697 +
1698 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
1699 +               return -EINVAL;
1700 +       }
1701 +
1702 +       return 0;
1703 +}
1704 +
1705 +static void __exit fini(void)
1706 +{
1707 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
1708 +       ipt_unregister_target(&ipt_netlink_reg);
1709 +//     if(ipfwsk->socket) sock_release(ipfwsk->socket);
1710 +}
1711 +
1712 +module_init(init);
1713 +module_exit(fini);
1714 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_POOL.c
1715 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_POOL.c   1970-01-01 01:00:00.000000000 +0100
1716 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_POOL.c       2004-02-16 11:07:21.518803072 +0100
1717 @@ -0,0 +1,116 @@
1718 +/* ipt_POOL.c - netfilter target to manipulate IP pools
1719 + *
1720 + * This target can be used almost everywhere. It acts on some specified
1721 + * IP pool, adding or deleting some IP address in the pool. The address
1722 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
1723 + * of the packet under inspection.
1724 + *
1725 + * The target normally returns IPT_CONTINUE.
1726 + */
1727 +
1728 +#include <linux/types.h>
1729 +#include <linux/ip.h>
1730 +#include <linux/timer.h>
1731 +#include <linux/module.h>
1732 +#include <linux/netfilter.h>
1733 +#include <linux/netdevice.h>
1734 +#include <linux/if.h>
1735 +#include <linux/inetdevice.h>
1736 +#include <net/protocol.h>
1737 +#include <net/checksum.h>
1738 +#include <linux/netfilter_ipv4.h>
1739 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
1740 +#include <linux/netfilter_ipv4/ipt_pool.h>
1741 +
1742 +#if 0
1743 +#define DEBUGP printk
1744 +#else
1745 +#define DEBUGP(format, args...)
1746 +#endif
1747 +
1748 +/*** NOTE NOTE NOTE NOTE ***
1749 +**
1750 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
1751 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
1752 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
1753 +** is modified for the source IP address of the packet under inspection.
1754 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
1755 +**
1756 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
1757 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
1758 +**
1759 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
1760 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
1761 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
1762 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
1763 +*/
1764 +
1765 +static int
1766 +do_check(const char *tablename,
1767 +              const struct ipt_entry *e,
1768 +              void *targinfo,
1769 +              unsigned int targinfosize,
1770 +              unsigned int hook_mask)
1771 +{
1772 +       const struct ipt_pool_info *ipi = targinfo;
1773 +
1774 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
1775 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
1776 +               return 0;
1777 +       }
1778 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
1779 +       return 1;
1780 +}
1781 +
1782 +static unsigned int
1783 +do_target(struct sk_buff **pskb,
1784 +               unsigned int hooknum,
1785 +               const struct net_device *in,
1786 +               const struct net_device *out,
1787 +               const void *targinfo,
1788 +               void *userinfo)
1789 +{
1790 +       const struct ipt_pool_info *ipi = targinfo;
1791 +       int modified;
1792 +       unsigned int verdict = IPT_CONTINUE;
1793 +
1794 +       if (ipi->src != IP_POOL_NONE) {
1795 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
1796 +                                       ipi->flags & IPT_POOL_DEL_SRC);
1797 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
1798 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
1799 +                               verdict = NF_ACCEPT;
1800 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
1801 +                               verdict = NF_DROP;
1802 +               }
1803 +       }
1804 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
1805 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
1806 +                                       ipi->flags & IPT_POOL_DEL_DST);
1807 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
1808 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
1809 +                               verdict = NF_ACCEPT;
1810 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
1811 +                               verdict = NF_DROP;
1812 +               }
1813 +       }
1814 +       return verdict;
1815 +}
1816 +
1817 +static struct ipt_target pool_reg
1818 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
1819 +
1820 +static int __init init(void)
1821 +{
1822 +       DEBUGP("init ipt_POOL\n");
1823 +       return ipt_register_target(&pool_reg);
1824 +}
1825 +
1826 +static void __exit fini(void)
1827 +{
1828 +       DEBUGP("fini ipt_POOL\n");
1829 +       ipt_unregister_target(&pool_reg);
1830 +}
1831 +
1832 +module_init(init);
1833 +module_exit(fini);
1834 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_TTL.c
1835 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_TTL.c    1970-01-01 01:00:00.000000000 +0100
1836 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_TTL.c        2004-02-16 11:07:09.253740328 +0100
1837 @@ -0,0 +1,110 @@
1838 +/* TTL modification target for IP tables
1839 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
1840 + *
1841 + * Version: 1.8
1842 + *
1843 + * This software is distributed under the terms of GNU GPL
1844 + */
1845 +
1846 +#include <linux/module.h>
1847 +#include <linux/skbuff.h>
1848 +#include <linux/ip.h>
1849 +#include <net/checksum.h>
1850 +
1851 +#include <linux/netfilter_ipv4/ip_tables.h>
1852 +#include <linux/netfilter_ipv4/ipt_TTL.h>
1853 +
1854 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
1855 +MODULE_DESCRIPTION("IP tables TTL modification module");
1856 +MODULE_LICENSE("GPL");
1857 +
1858 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
1859 +               const struct net_device *in, const struct net_device *out,
1860 +               const void *targinfo, void *userinfo)
1861 +{
1862 +       struct iphdr *iph = (*pskb)->nh.iph;
1863 +       const struct ipt_TTL_info *info = targinfo;
1864 +       u_int16_t diffs[2];
1865 +       int new_ttl;
1866 +                        
1867 +       switch (info->mode) {
1868 +               case IPT_TTL_SET:
1869 +                       new_ttl = info->ttl;
1870 +                       break;
1871 +               case IPT_TTL_INC:
1872 +                       new_ttl = iph->ttl + info->ttl;
1873 +                       if (new_ttl > 255)
1874 +                               new_ttl = 255;
1875 +                       break;
1876 +               case IPT_TTL_DEC:
1877 +                       new_ttl = iph->ttl + info->ttl;
1878 +                       if (new_ttl < 0)
1879 +                               new_ttl = 0;
1880 +                       break;
1881 +               default:
1882 +                       new_ttl = iph->ttl;
1883 +                       break;
1884 +       }
1885 +
1886 +       if (new_ttl != iph->ttl) {
1887 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
1888 +               iph->ttl = new_ttl;
1889 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
1890 +               iph->check = csum_fold(csum_partial((char *)diffs,
1891 +                                                   sizeof(diffs),
1892 +                                                   iph->check^0xFFFF));
1893 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
1894 +       }
1895 +
1896 +       return IPT_CONTINUE;
1897 +}
1898 +
1899 +static int ipt_ttl_checkentry(const char *tablename,
1900 +               const struct ipt_entry *e,
1901 +               void *targinfo,
1902 +               unsigned int targinfosize,
1903 +               unsigned int hook_mask)
1904 +{
1905 +       struct ipt_TTL_info *info = targinfo;
1906 +
1907 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
1908 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
1909 +                               targinfosize,
1910 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
1911 +               return 0;       
1912 +       }       
1913 +
1914 +       if (strcmp(tablename, "mangle")) {
1915 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
1916 +               return 0;
1917 +       }
1918 +
1919 +       if (info->mode > IPT_TTL_MAXMODE) {
1920 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
1921 +                       info->mode);
1922 +               return 0;
1923 +       }
1924 +
1925 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
1926 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
1927 +               return 0;
1928 +       }
1929 +       
1930 +       return 1;
1931 +}
1932 +
1933 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL", 
1934 +       ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
1935 +
1936 +static int __init init(void)
1937 +{
1938 +       return ipt_register_target(&ipt_TTL);
1939 +}
1940 +
1941 +static void __exit fini(void)
1942 +{
1943 +       ipt_unregister_target(&ipt_TTL);
1944 +}
1945 +
1946 +module_init(init);
1947 +module_exit(fini);
1948 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_connlimit.c
1949 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_connlimit.c      1970-01-01 01:00:00.000000000 +0100
1950 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_connlimit.c  2004-02-16 11:07:11.549190614 +0100
1951 @@ -0,0 +1,227 @@
1952 +/*
1953 + * netfilter module to limit the number of parallel tcp
1954 + * connections per IP address.
1955 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
1956 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
1957 + *             only ignore TIME_WAIT or gone connections
1958 + *
1959 + * based on ...
1960 + *
1961 + * Kernel module to match connection tracking information.
1962 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
1963 + */
1964 +#include <linux/module.h>
1965 +#include <linux/skbuff.h>
1966 +#include <linux/list.h>
1967 +#include <linux/netfilter_ipv4/ip_conntrack.h>
1968 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
1969 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
1970 +#include <linux/netfilter_ipv4/ip_tables.h>
1971 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
1972 +
1973 +#define DEBUG 0
1974 +
1975 +MODULE_LICENSE("GPL");
1976 +
1977 +/* we'll save the tuples of all connections we care about */
1978 +struct ipt_connlimit_conn
1979 +{
1980 +        struct list_head list;
1981 +       struct ip_conntrack_tuple tuple;
1982 +};
1983 +
1984 +struct ipt_connlimit_data {
1985 +       spinlock_t lock;
1986 +       struct list_head iphash[256];
1987 +};
1988 +
1989 +static int ipt_iphash(u_int32_t addr)
1990 +{
1991 +       int hash;
1992 +
1993 +       hash  =  addr        & 0xff;
1994 +       hash ^= (addr >>  8) & 0xff;
1995 +       hash ^= (addr >> 16) & 0xff;
1996 +       hash ^= (addr >> 24) & 0xff;
1997 +       return hash;
1998 +}
1999 +
2000 +static int count_them(struct ipt_connlimit_data *data,
2001 +                     u_int32_t addr, u_int32_t mask,
2002 +                     struct ip_conntrack *ct)
2003 +{
2004 +#if DEBUG
2005 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
2006 +                                    "fin_wait", "time_wait", "close", "close_wait",
2007 +                                    "last_ack", "listen" };
2008 +#endif
2009 +       int addit = 1, matches = 0;
2010 +       struct ip_conntrack_tuple tuple;
2011 +       struct ip_conntrack_tuple_hash *found;
2012 +       struct ipt_connlimit_conn *conn;
2013 +       struct list_head *hash,*lh;
2014 +
2015 +       spin_lock(&data->lock);
2016 +       tuple = ct->tuplehash[0].tuple;
2017 +       hash = &data->iphash[ipt_iphash(addr & mask)];
2018 +
2019 +       /* check the saved connections */
2020 +       for (lh = hash->next; lh != hash; lh = lh->next) {
2021 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
2022 +               found = ip_conntrack_find_get(&conn->tuple,ct);
2023 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
2024 +                   found != NULL &&
2025 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
2026 +                       /* Just to be sure we have it only once in the list.
2027 +                          We should'nt see tuples twice unless someone hooks this
2028 +                          into a table without "-p tcp --syn" */
2029 +                       addit = 0;
2030 +               }
2031 +#if DEBUG
2032 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
2033 +                      ipt_iphash(addr & mask),
2034 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
2035 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
2036 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
2037 +#endif
2038 +               if (NULL == found) {
2039 +                       /* this one is gone */
2040 +                       lh = lh->prev;
2041 +                       list_del(lh->next);
2042 +                       kfree(conn);
2043 +                       continue;
2044 +               }
2045 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
2046 +                       /* we don't care about connections which are
2047 +                          closed already -> ditch it */
2048 +                       lh = lh->prev;
2049 +                       list_del(lh->next);
2050 +                       kfree(conn);
2051 +                       nf_conntrack_put(&found->ctrack->infos[0]);
2052 +                       continue;
2053 +               }
2054 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
2055 +                       /* same source IP address -> be counted! */
2056 +                       matches++;
2057 +               }
2058 +               nf_conntrack_put(&found->ctrack->infos[0]);
2059 +       }
2060 +       if (addit) {
2061 +               /* save the new connection in our list */
2062 +#if DEBUG
2063 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
2064 +                      ipt_iphash(addr & mask),
2065 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
2066 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
2067 +#endif
2068 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
2069 +               if (NULL == conn)
2070 +                       return -1;
2071 +               memset(conn,0,sizeof(*conn));
2072 +               INIT_LIST_HEAD(&conn->list);
2073 +               conn->tuple = tuple;
2074 +               list_add(&conn->list,hash);
2075 +               matches++;
2076 +       }
2077 +       spin_unlock(&data->lock);
2078 +       return matches;
2079 +}
2080 +
2081 +static int
2082 +match(const struct sk_buff *skb,
2083 +      const struct net_device *in,
2084 +      const struct net_device *out,
2085 +      const void *matchinfo,
2086 +      int offset,
2087 +      const void *hdr,
2088 +      u_int16_t datalen,
2089 +      int *hotdrop)
2090 +{
2091 +       const struct ipt_connlimit_info *info = matchinfo;
2092 +       int connections, match;
2093 +       struct ip_conntrack *ct;
2094 +       enum ip_conntrack_info ctinfo;
2095 +
2096 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
2097 +       if (NULL == ct) {
2098 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
2099 +               *hotdrop = 1;
2100 +               return 0;
2101 +       }
2102 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
2103 +       if (-1 == connections) {
2104 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
2105 +               *hotdrop = 1; /* let's free some memory :-) */
2106 +               return 0;
2107 +       }
2108 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
2109 +#if DEBUG
2110 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
2111 +              "connections=%d limit=%d match=%s\n",
2112 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
2113 +              connections, info->limit, match ? "yes" : "no");
2114 +#endif
2115 +
2116 +       return match;
2117 +}
2118 +
2119 +static int check(const char *tablename,
2120 +                const struct ipt_ip *ip,
2121 +                void *matchinfo,
2122 +                unsigned int matchsize,
2123 +                unsigned int hook_mask)
2124 +{
2125 +       struct ipt_connlimit_info *info = matchinfo;
2126 +       int i;
2127 +
2128 +       /* verify size */
2129 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
2130 +               return 0;
2131 +
2132 +       /* refuse anything but tcp */
2133 +       if (ip->proto != IPPROTO_TCP)
2134 +               return 0;
2135 +
2136 +       /* init private data */
2137 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
2138 +       spin_lock_init(&(info->data->lock));
2139 +       for (i = 0; i < 256; i++)
2140 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
2141 +       
2142 +       return 1;
2143 +}
2144 +
2145 +static void destroy(void *matchinfo, unsigned int matchinfosize)
2146 +{
2147 +       struct ipt_connlimit_info *info = matchinfo;
2148 +       struct ipt_connlimit_conn *conn;
2149 +       struct list_head *hash;
2150 +       int i;
2151 +
2152 +       /* cleanup */
2153 +       for (i = 0; i < 256; i++) {
2154 +               hash = &(info->data->iphash[i]);
2155 +               while (hash != hash->next) {
2156 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
2157 +                       list_del(hash->next);
2158 +                       kfree(conn);
2159 +               }
2160 +       }
2161 +       kfree(info->data);
2162 +}
2163 +
2164 +static struct ipt_match connlimit_match
2165 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
2166 +
2167 +static int __init init(void)
2168 +{
2169 +       return ipt_register_match(&connlimit_match);
2170 +}
2171 +
2172 +static void __exit fini(void)
2173 +{
2174 +       ipt_unregister_match(&connlimit_match);
2175 +}
2176 +
2177 +module_init(init);
2178 +module_exit(fini);
2179 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_dstlimit.c
2180 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_dstlimit.c       1970-01-01 01:00:00.000000000 +0100
2181 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_dstlimit.c   2004-02-16 11:07:13.230787904 +0100
2182 @@ -0,0 +1,623 @@
2183 +/* iptables match extension to limit the number of packets per second
2184 + * seperately for each destination.
2185 + *
2186 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
2187 + *
2188 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
2189 + *
2190 + * based on ipt_limit.c by:
2191 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
2192 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
2193 + * Rusty Russell       <rusty@rustcorp.com.au>
2194 + *
2195 + * The general idea is to create a hash table for every dstip and have a
2196 + * seperate limit counter per tuple.  This way you can do something like 'limit
2197 + * the number of syn packets for each of my internal addresses.
2198 + *
2199 + * Ideally this would just be implemented as a general 'hash' match, which would
2200 + * allow us to attach any iptables target to it's hash buckets.  But this is
2201 + * not possible in the current iptables architecture.  As always, pkttables for
2202 + * 2.7.x will help ;)
2203 + */
2204 +#include <linux/module.h>
2205 +#include <linux/skbuff.h>
2206 +#include <linux/spinlock.h>
2207 +#include <linux/random.h>
2208 +#include <linux/jhash.h>
2209 +#include <linux/slab.h>
2210 +#include <linux/vmalloc.h>
2211 +#include <linux/tcp.h>
2212 +#include <linux/udp.h>
2213 +#include <linux/proc_fs.h>
2214 +#include <linux/seq_file.h>
2215 +
2216 +#define ASSERT_READ_LOCK(x) 
2217 +#define ASSERT_WRITE_LOCK(x) 
2218 +#include <linux/netfilter_ipv4/lockhelp.h>
2219 +#include <linux/netfilter_ipv4/listhelp.h>
2220 +
2221 +#include <linux/netfilter_ipv4/ip_tables.h>
2222 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
2223 +
2224 +/* FIXME: this is just for IP_NF_ASSERRT */
2225 +#include <linux/netfilter_ipv4/ip_conntrack.h>
2226 +
2227 +#define MS2JIFFIES(x) ((x*HZ)/1000)
2228 +
2229 +MODULE_LICENSE("GPL");
2230 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
2231 +MODULE_DESCRIPTION("iptables match for limiting per destination");
2232 +
2233 +/* need to declare this at the top */
2234 +static struct proc_dir_entry *dstlimit_procdir;
2235 +static struct file_operations dl_file_ops;
2236 +
2237 +/* hash table crap */
2238 +
2239 +struct dsthash_dst {
2240 +       u_int32_t src_ip;
2241 +       u_int32_t dst_ip;
2242 +       u_int16_t port;
2243 +};
2244 +
2245 +struct dsthash_ent {
2246 +       /* static / read-only parts in the beginning */
2247 +       struct list_head list;
2248 +       struct dsthash_dst dst;
2249 +
2250 +       /* modified structure members in the end */
2251 +       unsigned long expires;          /* precalculated expiry time */
2252 +       struct {
2253 +               unsigned long prev;     /* last modification */
2254 +               u_int32_t credit;
2255 +               u_int32_t credit_cap, cost;
2256 +       } rateinfo;
2257 +};
2258 +
2259 +struct ipt_dstlimit_htable {
2260 +       struct ipt_dstlimit_info *minfo; /* public structure */
2261 +
2262 +       /* used internally */
2263 +       spinlock_t lock;                /* lock for list_head */
2264 +       u_int32_t rnd;                  /* random seed for hash */
2265 +       struct timer_list timer;        /* timer for gc */
2266 +       atomic_t count;                 /* number entries in table */
2267 +
2268 +       /* seq_file stuff */
2269 +       struct proc_dir_entry *pde;
2270 +
2271 +       struct list_head hash[0];       /* hashtable itself */
2272 +};
2273 +
2274 +static kmem_cache_t *dstlimit_cachep;
2275 +
2276 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
2277 +{
2278 +       return (ent->dst.dst_ip == b->dst_ip 
2279 +               && ent->dst.port == b->port
2280 +               && ent->dst.src_ip == b->src_ip);
2281 +}
2282 +
2283 +static inline u_int32_t
2284 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
2285 +{
2286 +       return (jhash_3words(dst->dst_ip, dst->port, 
2287 +                            dst->src_ip, ht->rnd) % ht->minfo->size);
2288 +}
2289 +
2290 +static inline struct dsthash_ent *
2291 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2292 +{
2293 +       struct dsthash_ent *ent;
2294 +       u_int32_t hash = hash_dst(ht, dst);
2295 +       MUST_BE_LOCKED(&ht->lock);
2296 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
2297 +       return ent;
2298 +}
2299 +
2300 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
2301 +static struct dsthash_ent *
2302 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
2303 +{
2304 +       struct dsthash_ent *ent;
2305 +
2306 +       /* initialize hash with random val at the time we allocate
2307 +        * the first hashtable entry */
2308 +       if (!ht->rnd)
2309 +               get_random_bytes(&ht->rnd, 4);
2310 +
2311 +       if (ht->minfo->max &&
2312 +           atomic_read(&ht->count) >= ht->minfo->max) {
2313 +               /* FIXME: do something. question is what.. */
2314 +               if (net_ratelimit())
2315 +                       printk("max count of %u reached\n", ht->minfo->max);
2316 +               return NULL;
2317 +       }
2318 +
2319 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
2320 +       if (!ent) {
2321 +               if (net_ratelimit())
2322 +                       printk("Can't allocate dsthash_ent\n");
2323 +               return NULL;
2324 +       }
2325 +
2326 +       atomic_inc(&ht->count);
2327 +
2328 +       ent->dst.dst_ip = dst->dst_ip;
2329 +       ent->dst.port = dst->port;
2330 +       ent->dst.src_ip = dst->src_ip;
2331 +
2332 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
2333 +
2334 +       return ent;
2335 +}
2336 +
2337 +static inline void 
2338 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
2339 +{
2340 +       MUST_BE_LOCKED(&ht->lock);
2341 +
2342 +       list_del(&ent->list);
2343 +       kmem_cache_free(dstlimit_cachep, ent);
2344 +       atomic_dec(&ht->count);
2345 +}
2346 +
2347 +static void htable_gc(unsigned long htlong);
2348 +
2349 +static int htable_create(struct ipt_dstlimit_info *minfo)
2350 +{
2351 +       int i;
2352 +       struct ipt_dstlimit_htable *hinfo;
2353 +
2354 +       if (!minfo->size) {
2355 +               minfo->size = (((num_physpages << PAGE_SHIFT) / 16384)
2356 +                           / sizeof(struct list_head));
2357 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
2358 +                       minfo->size = 8192;
2359 +               if (minfo->size < 16)
2360 +                       minfo->size = 16;
2361 +       }
2362 +       if (!minfo->max)
2363 +               minfo->max = 8 * minfo->size;
2364 +       else if (minfo->max < minfo->size)
2365 +               minfo->max = minfo->size;
2366 +
2367 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
2368 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
2369 +                       + (sizeof(struct list_head) * minfo->size));
2370 +       if (!hinfo) {
2371 +               printk(KERN_ERR "Unable to create ipt_dstlimit hash\n");
2372 +               return -1;
2373 +       }
2374 +
2375 +       for (i = 0; i < minfo->size; i++)
2376 +               INIT_LIST_HEAD(&hinfo->hash[i]);
2377 +
2378 +       minfo->hinfo = hinfo;
2379 +
2380 +       hinfo->minfo = minfo;
2381 +       atomic_set(&hinfo->count, 0);
2382 +       hinfo->rnd = 0;
2383 +
2384 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
2385 +
2386 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
2387 +       if (!hinfo->pde) {
2388 +               vfree(hinfo);
2389 +               return -1;
2390 +       }
2391 +       hinfo->pde->proc_fops = &dl_file_ops;
2392 +       hinfo->pde->data = hinfo;
2393 +
2394 +       init_timer(&hinfo->timer);
2395 +       hinfo->timer.expires = jiffies + MS2JIFFIES(minfo->gc_interval);
2396 +       hinfo->timer.data = (unsigned long )hinfo;
2397 +       hinfo->timer.function = htable_gc;
2398 +       add_timer(&hinfo->timer);
2399 +
2400 +       return 0;
2401 +}
2402 +
2403 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2404 +{
2405 +       return 1;
2406 +}
2407 +
2408 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
2409 +{
2410 +       return (jiffies >= he->expires);
2411 +}
2412 +
2413 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
2414 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
2415 +                                             struct dsthash_ent *he))
2416 +{
2417 +       int i;
2418 +
2419 +       IP_NF_ASSERT(ht->minfo->size && ht->minfo->max);
2420 +
2421 +       /* lock hash table and iterate over it */
2422 +       LOCK_BH(&ht->lock);
2423 +       for (i = 0; i < ht->minfo->size; i++) {
2424 +               struct dsthash_ent *dh, *n;
2425 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
2426 +                       if ((*select)(ht, dh))
2427 +                               __dsthash_free(ht, dh);
2428 +               }
2429 +       }
2430 +       UNLOCK_BH(&ht->lock);
2431 +}
2432 +
2433 +/* hash table garbage collector, run by timer */
2434 +static void htable_gc(unsigned long htlong)
2435 +{
2436 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
2437 +
2438 +       htable_selective_cleanup(ht, select_gc);
2439 +
2440 +       /* re-add the timer accordingly */
2441 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->minfo->gc_interval);
2442 +       add_timer(&ht->timer);
2443 +}
2444 +
2445 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
2446 + * see net/sched/sch_tbf.c in the linux source tree
2447 + */
2448 +
2449 +/* Rusty: This is my (non-mathematically-inclined) understanding of
2450 +   this algorithm.  The `average rate' in jiffies becomes your initial
2451 +   amount of credit `credit' and the most credit you can ever have
2452 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
2453 +   test, `cost'.
2454 +
2455 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
2456 +   If you get credit balance more than this, the extra credit is
2457 +   discarded.  Every time the match passes, you lose `cost' credits;
2458 +   if you don't have that many, the test fails.
2459 +
2460 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
2461 +
2462 +   To get the maximum range, we multiply by this factor (ie. you get N
2463 +   credits per jiffy).  We want to allow a rate as low as 1 per day
2464 +   (slowest userspace tool allows), which means
2465 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
2466 +*/
2467 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
2468 +
2469 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
2470 + * us the power of 2 below the theoretical max, so GCC simply does a
2471 + * shift. */
2472 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
2473 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
2474 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
2475 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
2476 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
2477 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
2478 +
2479 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
2480 +
2481 +/* Precision saver. */
2482 +static inline u_int32_t
2483 +user2credits(u_int32_t user)
2484 +{
2485 +       /* If multiplying would overflow... */
2486 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
2487 +               /* Divide first. */
2488 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
2489 +
2490 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
2491 +}
2492 +
2493 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
2494 +{
2495 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
2496 +                                       * CREDITS_PER_JIFFY;
2497 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
2498 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
2499 +}
2500 +
2501 +static int
2502 +dstlimit_match(const struct sk_buff *skb,
2503 +               const struct net_device *in,
2504 +               const struct net_device *out,
2505 +               const void *matchinfo,
2506 +               int offset,
2507 +               const void *hdr,
2508 +               u_int16_t datalen,
2509 +               int *hotdrop)
2510 +{
2511 +       struct ipt_dstlimit_info *r = 
2512 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
2513 +       unsigned long now = jiffies;
2514 +       struct dsthash_ent *dh;
2515 +       struct dsthash_dst dst;
2516 +
2517 +       memset(&dst, 0, sizeof(dst));
2518 +
2519 +       /* dest ip is always in hash */
2520 +       dst.dst_ip = skb->nh.iph->daddr;
2521 +
2522 +       /* source ip only if respective hashmode, otherwise set to
2523 +        * zero */
2524 +       if (r->mode & IPT_DSTLIMIT_HASH_SIP)
2525 +               dst.src_ip = skb->nh.iph->saddr;
2526 +
2527 +       /* dest port only if respective mode */
2528 +       if (r->mode & IPT_DSTLIMIT_HASH_DPT) {
2529 +               switch (skb->nh.iph->protocol) {
2530 +                       struct tcphdr *th;
2531 +                       struct udphdr *uh;
2532 +               case IPPROTO_TCP:
2533 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2534 +                       dst.port = th->dest;
2535 +                       break;
2536 +               case IPPROTO_UDP:
2537 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
2538 +                       dst.port = uh->dest;
2539 +                       break;
2540 +               default:
2541 +                       break;
2542 +               }
2543 +       } 
2544 +
2545 +       LOCK_BH(&r->hinfo->lock);
2546 +       dh = __dsthash_find(r->hinfo, &dst);
2547 +       if (!dh) {
2548 +               dh = __dsthash_alloc_init(r->hinfo, &dst);
2549 +
2550 +               if (!dh) {
2551 +                       /* enomem... don't match == DROP */
2552 +                       if (net_ratelimit())
2553 +                               printk("%s: ENOMEM\n", __FUNCTION__);
2554 +                       UNLOCK_BH(&r->hinfo->lock);
2555 +                       return 0;
2556 +               }
2557 +
2558 +               dh->expires = jiffies + MS2JIFFIES(r->expire);
2559 +
2560 +               dh->rateinfo.prev = jiffies;
2561 +               dh->rateinfo.credit = user2credits(r->avg * r->burst);
2562 +               dh->rateinfo.credit_cap = user2credits(r->avg * r->burst);
2563 +               dh->rateinfo.cost = user2credits(r->avg);
2564 +
2565 +               UNLOCK_BH(&r->hinfo->lock);
2566 +               return 0;
2567 +       }
2568 +
2569 +       /* update expiration timeout */
2570 +       dh->expires = now + MS2JIFFIES(r->expire);
2571 +
2572 +       rateinfo_recalc(dh, now);
2573 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
2574 +               /* We're underlimit. */
2575 +               dh->rateinfo.credit -= dh->rateinfo.cost;
2576 +               UNLOCK_BH(&r->hinfo->lock);
2577 +               return 1;
2578 +       }
2579 +
2580 +               UNLOCK_BH(&r->hinfo->lock);
2581 +
2582 +       /* default case: we're overlimit, thus don't match */
2583 +       return 0;
2584 +}
2585 +
2586 +static int
2587 +dstlimit_checkentry(const char *tablename,
2588 +                    const struct ipt_ip *ip,
2589 +                    void *matchinfo,
2590 +                    unsigned int matchsize,
2591 +                    unsigned int hook_mask)
2592 +{
2593 +       struct ipt_dstlimit_info *r = matchinfo;
2594 +
2595 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
2596 +               return 0;
2597 +
2598 +       /* Check for overflow. */
2599 +       if (r->burst == 0
2600 +           || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
2601 +               printk("Overflow in ipt_dstlimit, try lower: %u/%u\n",
2602 +                      r->avg, r->burst);
2603 +               return 0;
2604 +       }
2605 +
2606 +       if (r->mode == 0 
2607 +           || r->mode > (IPT_DSTLIMIT_HASH_DPT
2608 +                         |IPT_DSTLIMIT_HASH_DIP
2609 +                         |IPT_DSTLIMIT_HASH_SIP))
2610 +               return 0;
2611 +
2612 +       if (!r->gc_interval)
2613 +               return 0;
2614 +       
2615 +       if (!r->expire)
2616 +               return 0;
2617 +
2618 +       if (htable_create(r) != 0) {
2619 +               printk("Unable to create dstlimit htable\n");
2620 +               return 0;
2621 +       }
2622 +
2623 +       /* Ugly hack: For SMP, we only want to use one set */
2624 +       r->u.master = r;
2625 +
2626 +       return 1;
2627 +}
2628 +
2629 +static void
2630 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
2631 +{
2632 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
2633 +
2634 +       r = r->u.master;
2635 +
2636 +       /* remove timer, if it is pending */
2637 +       if (timer_pending(&r->hinfo->timer))
2638 +               del_timer(&r->hinfo->timer);
2639 +
2640 +       /* remove proc entry */
2641 +       remove_proc_entry(r->name, dstlimit_procdir);
2642 +
2643 +       htable_selective_cleanup(r->hinfo, select_all);
2644 +       vfree(&r->hinfo);
2645 +}
2646 +
2647 +static struct ipt_match ipt_dstlimit = { 
2648 +       .list = { .prev = NULL, .next = NULL }, 
2649 +       .name = "dstlimit", 
2650 +       .match = dstlimit_match, 
2651 +       .checkentry = dstlimit_checkentry, 
2652 +       .destroy = dstlimit_destroy,
2653 +       .me = THIS_MODULE 
2654 +};
2655 +
2656 +/* PROC stuff */
2657 +
2658 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
2659 +{
2660 +       struct proc_dir_entry *pde = s->private;
2661 +       struct ipt_dstlimit_htable *htable = pde->data;
2662 +       unsigned int *bucket;
2663 +
2664 +       LOCK_BH(&htable->lock);
2665 +       if (*pos >= htable->minfo->size)
2666 +               return NULL;
2667 +
2668 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
2669 +       if (!bucket)
2670 +               return ERR_PTR(-ENOMEM);
2671 +
2672 +       *bucket = *pos;
2673 +       return bucket;
2674 +}
2675 +
2676 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
2677 +{
2678 +       struct proc_dir_entry *pde = s->private;
2679 +       struct ipt_dstlimit_htable *htable = pde->data;
2680 +       unsigned int *bucket = (unsigned int *)v;
2681 +
2682 +       *pos = ++(*bucket);
2683 +       if (*pos >= htable->minfo->size) {
2684 +               kfree(v);
2685 +               return NULL;
2686 +       }
2687 +       return bucket;
2688 +}
2689 +
2690 +static void dl_seq_stop(struct seq_file *s, void *v)
2691 +{
2692 +       struct proc_dir_entry *pde = s->private;
2693 +       struct ipt_dstlimit_htable *htable = pde->data;
2694 +
2695 +       UNLOCK_BH(&htable->lock);
2696 +}
2697 +
2698 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
2699 +{
2700 +       /* recalculate to show accurate numbers */
2701 +       rateinfo_recalc(ent, jiffies);
2702 +
2703 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
2704 +                       (ent->expires - jiffies)/HZ,
2705 +                       NIPQUAD(ent->dst.src_ip),
2706 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
2707 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
2708 +                       ent->rateinfo.cost);
2709 +}
2710 +
2711 +static int dl_seq_show(struct seq_file *s, void *v)
2712 +{
2713 +       struct proc_dir_entry *pde = s->private;
2714 +       struct ipt_dstlimit_htable *htable = pde->data;
2715 +       unsigned int *bucket = (unsigned int *)v;
2716 +
2717 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
2718 +                     struct dsthash_ent *, s)) {
2719 +               /* buffer was filled and unable to print that tuple */
2720 +               return 1;
2721 +       }
2722 +       return 0;
2723 +}
2724 +
2725 +static struct seq_operations dl_seq_ops = {
2726 +       .start = dl_seq_start,
2727 +       .next  = dl_seq_next,
2728 +       .stop  = dl_seq_stop,
2729 +       .show  = dl_seq_show
2730 +};
2731 +
2732 +static int dl_proc_open(struct inode *inode, struct file *file)
2733 +{
2734 +       int ret = seq_open(file, &dl_seq_ops);
2735 +
2736 +       if (!ret) {
2737 +               struct seq_file *sf = file->private_data;
2738 +               sf->private = PDE(inode);
2739 +       }
2740 +       return ret;
2741 +}
2742 +
2743 +static struct file_operations dl_file_ops = {
2744 +       .owner   = THIS_MODULE,
2745 +       .open    = dl_proc_open,
2746 +       .read    = seq_read,
2747 +       .llseek  = seq_lseek,
2748 +       .release = seq_release
2749 +};
2750 +
2751 +static int init_or_fini(int fini)
2752 +{
2753 +       int ret = 0;
2754 +
2755 +       if (fini)
2756 +               goto cleanup;
2757 +
2758 +       if (ipt_register_match(&ipt_dstlimit)) {
2759 +               ret = -EINVAL;
2760 +               goto cleanup_nothing;
2761 +       }
2762 +
2763 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
2764 +        * quite small ? */
2765 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
2766 +                                           sizeof(struct dsthash_ent), 0,
2767 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
2768 +       if (!dstlimit_cachep) {
2769 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
2770 +               ret = -ENOMEM;
2771 +               goto cleanup_unreg_match;
2772 +       }
2773 +
2774 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
2775 +       if (!dstlimit_procdir) {
2776 +               printk(KERN_ERR "Unable to create proc dir entry\n");
2777 +               ret = -ENOMEM;
2778 +               goto cleanup_free_slab;
2779 +       }
2780 +
2781 +       return ret;
2782 +
2783 +cleanup:
2784 +       remove_proc_entry("ipt_dstlimit", proc_net);
2785 +cleanup_free_slab:
2786 +       kmem_cache_destroy(dstlimit_cachep);
2787 +cleanup_unreg_match:
2788 +       ipt_unregister_match(&ipt_dstlimit);
2789 +cleanup_nothing:
2790 +       return ret;
2791 +       
2792 +}
2793 +
2794 +static int __init init(void)
2795 +{
2796 +       return init_or_fini(0);
2797 +}
2798 +
2799 +static void __exit fini(void)
2800 +{
2801 +       init_or_fini(1);
2802 +}
2803 +
2804 +module_init(init);
2805 +module_exit(fini);
2806 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_fuzzy.c
2807 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_fuzzy.c  1970-01-01 01:00:00.000000000 +0100
2808 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_fuzzy.c      2004-02-16 11:07:14.925382080 +0100
2809 @@ -0,0 +1,190 @@
2810 +/*
2811 + *  This module implements a simple TSK FLC 
2812 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
2813 + * to limit , in an adaptive and flexible way , the packet rate crossing 
2814 + * a given stream . It serves as an initial and very simple (but effective)
2815 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
2816 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
2817 + * into our code in a precise , adaptive and efficient manner. 
2818 + *  The goal is very similar to that of "limit" match , but using techniques of
2819 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
2820 + * avoiding over and undershoots - and stuff like that .
2821 + *
2822 + *
2823 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
2824 + * 2002-08-17  : Changed to eliminate floating point operations .
2825 + * 2002-08-23  : Coding style changes .
2826 +*/
2827 +
2828 +#include <linux/module.h>
2829 +#include <linux/skbuff.h>
2830 +#include <linux/ip.h>
2831 +#include <linux/random.h>
2832 +#include <net/tcp.h>
2833 +#include <linux/spinlock.h>
2834 +#include <linux/netfilter_ipv4/ip_tables.h>
2835 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
2836 +
2837 +/*
2838 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
2839 + Expressed in percentage
2840 +*/
2841 +
2842 +#define PAR_LOW                1/100
2843 +#define PAR_HIGH       1
2844 +
2845 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
2846 +
2847 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
2848 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
2849 +MODULE_LICENSE("GPL");
2850 +
2851 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
2852 +{
2853 +       if (tx >= maxi) return 100;
2854 +
2855 +       if (tx <= mini) return 0;
2856 +
2857 +       return ( (100*(tx-mini)) / (maxi-mini) ) ;
2858 +}
2859 +
2860 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
2861 +{
2862 +       if (tx <= mini) return 100;
2863 +
2864 +       if (tx >= maxi) return 0;
2865 +
2866 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) ) ;
2867 +
2868 +}
2869 +
2870 +static int
2871 +ipt_fuzzy_match(const struct sk_buff *pskb,
2872 +              const struct net_device *in,
2873 +              const struct net_device *out,
2874 +              const void *matchinfo,
2875 +              int offset,
2876 +              const void *hdr,
2877 +              u_int16_t datalen,
2878 +              int *hotdrop)
2879 +{
2880 +       /* From userspace */
2881 +       
2882 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
2883 +
2884 +       u_int8_t random_number;
2885 +       unsigned long amount ;
2886 +       u_int8_t howhigh , howlow ;
2887 +       
2888 +
2889 +       spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
2890 +
2891 +       info->bytes_total += pskb->len ;
2892 +       info->packets_total++ ;
2893 +
2894 +       info->present_time = jiffies ;
2895 +       
2896 +       if ( info->present_time >= info->previous_time )
2897 +               amount = info->present_time - info->previous_time ;
2898 +       else { 
2899 +               /* There was a transition : I choose to re-sample 
2900 +                  and keep the old acceptance rate...
2901 +               */
2902 +
2903 +               amount = 0 ;
2904 +               info->previous_time = info->present_time ;
2905 +               info->bytes_total = info->packets_total = 0;
2906 +            };
2907 +       
2908 +       if (  amount > HZ/10 ) /* More than 100 ms elapsed ... */
2909 +               {
2910 +
2911 +       info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total )  \
2912 +                                       / amount ) ;
2913 +
2914 +               info->previous_time = info->present_time ;
2915 +               info->bytes_total = info->packets_total = 0 ;
2916 +
2917 +       howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
2918 +       howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
2919 +
2920 +    info->acceptance_rate = (u_int8_t) \
2921 +                          ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
2922 +
2923 +    /* In fact , the above defuzzification would require a denominator
2924 +       proportional to (howhigh+howlow) but , in this particular case ,
2925 +       that expression is constant .
2926 +        An imediate consequence is that it isn't necessary to call 
2927 +       both mf_high and mf_low - but to keep things understandable ,
2928 +       I did so .
2929 +     */ 
2930 +
2931 +               }
2932 +       
2933 +       spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
2934 +
2935 +
2936 +       if ( info->acceptance_rate < 100 )
2937 +       {                
2938 +               get_random_bytes((void *)(&random_number), 1);
2939 +
2940 +               /*  If within the acceptance , it can pass => don't match */
2941 +               if ( random_number <= (255 * info->acceptance_rate) / 100 )
2942 +                       return 0 ;
2943 +               else
2944 +                       return 1; /* It can't pass ( It matches ) */
2945 +       } ;
2946 +
2947 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
2948 +       
2949 +}
2950 +
2951 +static int
2952 +ipt_fuzzy_checkentry(const char *tablename,
2953 +                  const struct ipt_ip *e,
2954 +                  void *matchinfo,
2955 +                  unsigned int matchsize,
2956 +                  unsigned int hook_mask)
2957 +{
2958 +       
2959 +       const struct ipt_fuzzy_info *info = matchinfo;
2960 +
2961 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
2962 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
2963 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
2964 +               return 0;
2965 +       }
2966 +
2967 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
2968 +       || (info->minimum_rate >= info->maximum_rate ))
2969 +               {
2970 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
2971 +               return 0;
2972 +               }
2973 +
2974 +       return 1;
2975 +}
2976 +
2977 +static struct ipt_match ipt_fuzzy_reg = { 
2978 +       {NULL, NULL},
2979 +       "fuzzy",
2980 +       ipt_fuzzy_match,
2981 +       ipt_fuzzy_checkentry,
2982 +       NULL,
2983 +       THIS_MODULE };
2984 +
2985 +static int __init init(void)
2986 +{
2987 +       if (ipt_register_match(&ipt_fuzzy_reg))
2988 +               return -EINVAL;
2989 +
2990 +       return 0;
2991 +}
2992 +
2993 +static void __exit fini(void)
2994 +{
2995 +       ipt_unregister_match(&ipt_fuzzy_reg);
2996 +}
2997 +
2998 +module_init(init);
2999 +module_exit(fini);
3000 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_ipv4options.c
3001 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_ipv4options.c    1970-01-01 01:00:00.000000000 +0100
3002 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_ipv4options.c        2004-02-16 11:07:16.165085194 +0100
3003 @@ -0,0 +1,170 @@
3004 +/*
3005 +  This is a module which is used to match ipv4 options.
3006 +  This file is distributed under the terms of the GNU General Public
3007 +  License (GPL). Copies of the GPL can be obtained from:
3008 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
3009 +
3010 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
3011 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
3012 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
3013 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
3014 +*/
3015 +
3016 +#include <linux/module.h>
3017 +#include <linux/skbuff.h>
3018 +#include <net/ip.h>
3019 +
3020 +#include <linux/netfilter_ipv4/ip_tables.h>
3021 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
3022 +
3023 +MODULE_LICENSE("GPL");
3024 +
3025 +static int
3026 +match(const struct sk_buff *skb,
3027 +      const struct net_device *in,
3028 +      const struct net_device *out,
3029 +      const void *matchinfo,
3030 +      int offset,
3031 +      const void *hdr,
3032 +      u_int16_t datalen,
3033 +      int *hotdrop)
3034 +{
3035 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3036 +       const struct iphdr *iph = skb->nh.iph;
3037 +       const struct ip_options *opt;
3038 +
3039 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
3040 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
3041 +
3042 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
3043 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3044 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3045 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3046 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3047 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
3048 +                       return 0;
3049 +               return 1;
3050 +       }
3051 +       else {
3052 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
3053 +                       /* there are options, and we don't need to care which one */
3054 +                       return 1;
3055 +               else {
3056 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
3057 +                               /* there are options but we don't want any ! */
3058 +                               return 0;
3059 +               }
3060 +       }
3061 +
3062 +       opt = &(IPCB(skb)->opt);
3063 +
3064 +       /* source routing */
3065 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
3066 +               if (!((opt->srr) & (opt->is_strictroute)))
3067 +                       return 0;
3068 +       }
3069 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
3070 +               if (!((opt->srr) & (!opt->is_strictroute)))
3071 +                       return 0;
3072 +       }
3073 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
3074 +               if (opt->srr)
3075 +                       return 0;
3076 +       }
3077 +       /* record route */
3078 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
3079 +               if (!opt->rr)
3080 +                       return 0;
3081 +       }
3082 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
3083 +               if (opt->rr)
3084 +                       return 0;
3085 +       }
3086 +       /* timestamp */
3087 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
3088 +               if (!opt->ts)
3089 +                       return 0;
3090 +       }
3091 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
3092 +               if (opt->ts)
3093 +                       return 0;
3094 +       }
3095 +       /* router-alert option  */
3096 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
3097 +               if (!opt->router_alert)
3098 +                       return 0;
3099 +       }
3100 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
3101 +               if (opt->router_alert)
3102 +                       return 0;
3103 +       }
3104 +
3105 +       /* we match ! */
3106 +       return 1;
3107 +}
3108 +
3109 +static int
3110 +checkentry(const char *tablename,
3111 +          const struct ipt_ip *ip,
3112 +          void *matchinfo,
3113 +          unsigned int matchsize,
3114 +          unsigned int hook_mask)
3115 +{
3116 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
3117 +       /* Check the size */
3118 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
3119 +               return 0;
3120 +       /* Now check the coherence of the data ... */
3121 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
3122 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
3123 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
3124 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
3125 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
3126 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
3127 +               return 0; /* opposites */
3128 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
3129 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
3130 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3131 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
3132 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
3133 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
3134 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
3135 +               return 0; /* opposites */
3136 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
3137 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
3138 +               return 0; /* cannot match in the same time loose and strict source routing */
3139 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
3140 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
3141 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
3142 +               return 0; /* opposites */
3143 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
3144 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
3145 +               return 0; /* opposites */
3146 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
3147 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
3148 +               return 0; /* opposites */
3149 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
3150 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
3151 +               return 0; /* opposites */
3152 +
3153 +       /* everything looks ok. */
3154 +       return 1;
3155 +}
3156 +
3157 +static struct ipt_match ipv4options_match
3158 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
3159 +
3160 +static int __init init(void)
3161 +{
3162 +       printk("ipt_ipv4options loading\n");
3163 +       return ipt_register_match(&ipv4options_match);
3164 +}
3165 +
3166 +static void __exit fini(void)
3167 +{
3168 +       ipt_unregister_match(&ipv4options_match);
3169 +       printk("ipt_ipv4options unloaded\n");
3170 +}
3171 +
3172 +module_init(init);
3173 +module_exit(fini);
3174 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_mport.c
3175 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_mport.c  1970-01-01 01:00:00.000000000 +0100
3176 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_mport.c      2004-02-16 11:07:17.665725817 +0100
3177 @@ -0,0 +1,112 @@
3178 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
3179 +   the same place so we can treat them as equal. */
3180 +#include <linux/module.h>
3181 +#include <linux/types.h>
3182 +#include <linux/udp.h>
3183 +#include <linux/skbuff.h>
3184 +
3185 +#include <linux/netfilter_ipv4/ipt_mport.h>
3186 +#include <linux/netfilter_ipv4/ip_tables.h>
3187 +
3188 +MODULE_LICENSE("GPL");
3189 +
3190 +#if 0
3191 +#define duprintf(format, args...) printk(format , ## args)
3192 +#else
3193 +#define duprintf(format, args...)
3194 +#endif
3195 +
3196 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
3197 +static inline int
3198 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
3199 +{
3200 +       unsigned int i;
3201 +        unsigned int m;
3202 +        u_int16_t pflags = minfo->pflags;
3203 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
3204 +                u_int16_t s, e;
3205 +
3206 +                if (pflags & m
3207 +                    && minfo->ports[i] == 65535)
3208 +                        return 0;
3209 +
3210 +                s = minfo->ports[i];
3211 +
3212 +                if (pflags & m) {
3213 +                        e = minfo->ports[++i];
3214 +                        m <<= 1;
3215 +                } else
3216 +                        e = s;
3217 +
3218 +                if (minfo->flags & IPT_MPORT_SOURCE
3219 +                    && src >= s && src <= e)
3220 +                        return 1;
3221 +
3222 +               if (minfo->flags & IPT_MPORT_DESTINATION
3223 +                   && dst >= s && dst <= e)
3224 +                       return 1;
3225 +       }
3226 +
3227 +       return 0;
3228 +}
3229 +
3230 +static int
3231 +match(const struct sk_buff *skb,
3232 +      const struct net_device *in,
3233 +      const struct net_device *out,
3234 +      const void *matchinfo,
3235 +      int offset,
3236 +      const void *hdr,
3237 +      u_int16_t datalen,
3238 +      int *hotdrop)
3239 +{
3240 +       const struct udphdr *udp = hdr;
3241 +       const struct ipt_mport *minfo = matchinfo;
3242 +
3243 +       /* Must be big enough to read ports. */
3244 +       if (offset == 0 && datalen < sizeof(struct udphdr)) {
3245 +               /* We've been asked to examine this packet, and we
3246 +                  can't.  Hence, no choice but to drop. */
3247 +                       duprintf("ipt_mport:"
3248 +                                " Dropping evil offset=0 tinygram.\n");
3249 +                       *hotdrop = 1;
3250 +                       return 0;
3251 +       }
3252 +
3253 +       /* Must not be a fragment. */
3254 +       return !offset
3255 +               && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
3256 +}
3257 +
3258 +/* Called when user tries to insert an entry of this type. */
3259 +static int
3260 +checkentry(const char *tablename,
3261 +          const struct ipt_ip *ip,
3262 +          void *matchinfo,
3263 +          unsigned int matchsize,
3264 +          unsigned int hook_mask)
3265 +{
3266 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
3267 +               return 0;
3268 +
3269 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
3270 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
3271 +               && !(ip->invflags & IPT_INV_PROTO)
3272 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
3273 +}
3274 +
3275 +static struct ipt_match mport_match
3276 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
3277 +
3278 +static int __init init(void)
3279 +{
3280 +       return ipt_register_match(&mport_match);
3281 +}
3282 +
3283 +static void __exit fini(void)
3284 +{
3285 +       ipt_unregister_match(&mport_match);
3286 +}
3287 +
3288 +module_init(init);
3289 +module_exit(fini);
3290 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_nth.c
3291 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_nth.c    1970-01-01 01:00:00.000000000 +0100
3292 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_nth.c        2004-02-16 11:07:18.803453352 +0100
3293 @@ -0,0 +1,172 @@
3294 +/*
3295 +  This is a module which is used for match support for every Nth packet
3296 +  This file is distributed under the terms of the GNU General Public
3297 +  License (GPL). Copies of the GPL can be obtained from:
3298 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
3299 +
3300 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
3301 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
3302 +        * added support for multiple counters
3303 +        * added support for matching on individual packets
3304 +          in the counter cycle
3305 +
3306 +*/
3307 +
3308 +#include <linux/module.h>
3309 +#include <linux/skbuff.h>
3310 +#include <linux/ip.h>
3311 +#include <net/tcp.h>
3312 +#include <linux/spinlock.h>
3313 +#include <linux/netfilter_ipv4/ip_tables.h>
3314 +#include <linux/netfilter_ipv4/ipt_nth.h>
3315 +
3316 +MODULE_LICENSE("GPL");
3317 +
3318 +/*
3319 + * State information.
3320 + */
3321 +struct state {
3322 +       spinlock_t lock;
3323 +       u_int16_t number;
3324 +};
3325 +
3326 +static struct state states[IPT_NTH_NUM_COUNTERS];
3327 +
3328 +static int
3329 +ipt_nth_match(const struct sk_buff *pskb,
3330 +             const struct net_device *in,
3331 +             const struct net_device *out,
3332 +             const void *matchinfo,
3333 +             int offset,
3334 +             const void *hdr,
3335 +             u_int16_t datalen,
3336 +             int *hotdrop)
3337 +{
3338 +       /* Parameters from userspace */
3339 +       const struct ipt_nth_info *info = matchinfo;
3340 +        unsigned counter = info->counter;
3341 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
3342 +       {
3343 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3344 +               return 0;
3345 +        };
3346 +
3347 +        spin_lock(&states[counter].lock);
3348 +
3349 +        /* Are we matching every nth packet?*/
3350 +        if (info->packet == 0xFF)
3351 +        {
3352 +               /* We're matching every nth packet and only every nth packet*/
3353 +               /* Do we match or invert match? */
3354 +               if (info->not == 0)
3355 +               {
3356 +                       if (states[counter].number == 0)
3357 +                       {
3358 +                               ++states[counter].number;
3359 +                               goto match;
3360 +                       }
3361 +                       if (states[counter].number >= info->every)
3362 +                               states[counter].number = 0; /* reset the counter */
3363 +                       else
3364 +                               ++states[counter].number;
3365 +                       goto dontmatch;
3366 +               }
3367 +               else
3368 +               {
3369 +                       if (states[counter].number == 0)
3370 +                       {
3371 +                               ++states[counter].number;
3372 +                               goto dontmatch;
3373 +                       }
3374 +                       if (states[counter].number >= info->every)
3375 +                               states[counter].number = 0;
3376 +                       else
3377 +                               ++states[counter].number;
3378 +                       goto match;
3379 +               }
3380 +        }
3381 +        else
3382 +        {
3383 +               /* We're using the --packet, so there must be a rule for every value */
3384 +               if (states[counter].number == info->packet)
3385 +               {
3386 +                       /* only increment the counter when a match happens */
3387 +                       if (states[counter].number >= info->every)
3388 +                               states[counter].number = 0; /* reset the counter */
3389 +                       else
3390 +                               ++states[counter].number;
3391 +                       goto match;
3392 +               }
3393 +               else
3394 +                       goto dontmatch;
3395 +       }
3396 +
3397 + dontmatch:
3398 +       /* don't match */
3399 +       spin_unlock(&states[counter].lock);
3400 +       return 0;
3401 +
3402 + match:
3403 +       spin_unlock(&states[counter].lock);
3404 +       return 1;
3405 +}
3406 +
3407 +static int
3408 +ipt_nth_checkentry(const char *tablename,
3409 +                  const struct ipt_ip *e,
3410 +                  void *matchinfo,
3411 +                  unsigned int matchsize,
3412 +                  unsigned int hook_mask)
3413 +{
3414 +       /* Parameters from userspace */
3415 +       const struct ipt_nth_info *info = matchinfo;
3416 +        unsigned counter = info->counter;
3417 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
3418 +       {
3419 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
3420 +                       return 0;
3421 +               };
3422 +
3423 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
3424 +               printk("nth: matchsize %u != %u\n", matchsize,
3425 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
3426 +               return 0;
3427 +       }
3428 +
3429 +       states[counter].number = info->startat;
3430 +
3431 +       return 1;
3432 +}
3433 +
3434 +static struct ipt_match ipt_nth_reg = { 
3435 +       {NULL, NULL},
3436 +       "nth",
3437 +       ipt_nth_match,
3438 +       ipt_nth_checkentry,
3439 +       NULL,
3440 +       THIS_MODULE };
3441 +
3442 +static int __init init(void)
3443 +{
3444 +       unsigned counter;
3445 +        memset(&states, 0, sizeof(states));
3446 +       if (ipt_register_match(&ipt_nth_reg))
3447 +               return -EINVAL;
3448 +
3449 +        for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
3450 +       {
3451 +               spin_lock_init(&(states[counter].lock));
3452 +        };
3453 +
3454 +       printk("ipt_nth match loaded\n");
3455 +       return 0;
3456 +}
3457 +
3458 +static void __exit fini(void)
3459 +{
3460 +       ipt_unregister_match(&ipt_nth_reg);
3461 +       printk("ipt_nth match unloaded\n");
3462 +}
3463 +
3464 +module_init(init);
3465 +module_exit(fini);
3466 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_osf.c
3467 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_osf.c    1970-01-01 01:00:00.000000000 +0100
3468 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_osf.c        2004-02-16 11:07:19.917186632 +0100
3469 @@ -0,0 +1,733 @@
3470 +/*
3471 + * ipt_osf.c
3472 + *
3473 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
3474 + *
3475 + *
3476 + * This program is free software; you can redistribute it and/or modify
3477 + * it under the terms of the GNU General Public License as published by
3478 + * the Free Software Foundation; either version 2 of the License, or
3479 + * (at your option) any later version.
3480 + *
3481 + * This program is distributed in the hope that it will be useful,
3482 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3483 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3484 + * GNU General Public License for more details.
3485 + *
3486 + * You should have received a copy of the GNU General Public License
3487 + * along with this program; if not, write to the Free Software
3488 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3489 + */
3490 +
3491 +/*
3492 + * OS fingerprint matching module.
3493 + * It simply compares various parameters from SYN packet with
3494 + * some hardcoded ones.
3495 + *
3496 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
3497 + * for his p0f.
3498 + */
3499 +
3500 +#include <linux/config.h>
3501 +#include <linux/kernel.h>
3502 +#include <linux/smp.h>
3503 +#include <linux/module.h>
3504 +#include <linux/skbuff.h>
3505 +#include <linux/file.h>
3506 +#include <linux/ip.h>
3507 +#include <linux/proc_fs.h>
3508 +#include <linux/fs.h>
3509 +#include <linux/slab.h>
3510 +#include <linux/spinlock.h>
3511 +#include <linux/ctype.h>
3512 +#include <linux/list.h>
3513 +
3514 +#include <net/sock.h>
3515 +#include <net/ip.h>
3516 +
3517 +#include <linux/netfilter_ipv4/ip_tables.h>
3518 +
3519 +#include <linux/netfilter_ipv4/ipt_osf.h>
3520 +
3521 +#define OSF_DEBUG
3522 +
3523 +#ifdef OSF_DEBUG
3524 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
3525 +#define loga(x...)             printk(x)
3526 +#else
3527 +#define log(x...)              do {} while(0)
3528 +#define loga(x...)             do {} while(0)
3529 +#endif
3530 +
3531 +#define FMATCH_WRONG           0
3532 +#define FMATCH_OK              1
3533 +#define FMATCH_OPT_WRONG       2
3534 +
3535 +#define OPTDEL                 ','
3536 +#define OSFPDEL                ':'
3537 +#define MAXOPTSTRLEN           128
3538 +#define OSFFLUSH               "FLUSH"
3539 +
3540 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
3541 +static struct list_head        finger_list;    
3542 +
3543 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
3544 +                     const void *, int, const void *, u_int16_t, int *);
3545 +static int checkentry(const char *, const struct ipt_ip *, void *,
3546 +                          unsigned int, unsigned int);
3547 +
3548 +static struct ipt_match osf_match = 
3549 +{ 
3550 +       { NULL, NULL }, 
3551 +       "osf", 
3552 +       &match, 
3553 +       &checkentry, 
3554 +       NULL, 
3555 +       THIS_MODULE 
3556 +};
3557 +
3558 +static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
3559 +{
3560 +       if (flags & IPT_OSF_SMART)
3561 +               return 1;
3562 +       else
3563 +               return (ip_ttl == f_ttl);
3564 +}
3565 +
3566 +static int
3567 +match(const struct sk_buff *skb,
3568 +      const struct net_device *in,
3569 +      const struct net_device *out,
3570 +      const void *matchinfo,
3571 +      int offset,
3572 +      const void *hdr,
3573 +      u_int16_t datalen,
3574 +      int *hotdrop)
3575 +{
3576 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
3577 +       struct iphdr *ip = skb->nh.iph;
3578 +       struct tcphdr *tcp;
3579 +       int fmatch = FMATCH_WRONG, fcount = 0;
3580 +       unsigned long totlen, optsize = 0, window;
3581 +       unsigned char df, *optp = NULL, *_optp = NULL;
3582 +       char check_WSS = 0;
3583 +       struct list_head *ent;
3584 +       struct osf_finger *f;
3585 +
3586 +       if (!ip || !info)
3587 +               return 0;
3588 +                               
3589 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
3590 +
3591 +       if (!tcp->syn)
3592 +               return 0;
3593 +       else if (tcp->ack)
3594 +               return 0;
3595 +       
3596 +       totlen = ntohs(ip->tot_len);
3597 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
3598 +       window = ntohs(tcp->window);
3599 +       
3600 +       if (tcp->doff*4 > sizeof(struct tcphdr))
3601 +       {
3602 +               _optp = optp = (char *)(tcp+1);
3603 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
3604 +       }
3605 +
3606 +       
3607 +       /* Actually we can create hash/table of all genres and search
3608 +        * only in appropriate part, but here is initial variant,
3609 +        * so will use slow path.
3610 +        */
3611 +       read_lock(&osf_lock);
3612 +       list_for_each(ent, &finger_list)
3613 +       {
3614 +               f = list_entry(ent, struct osf_finger, flist);
3615 +       
3616 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
3617 +                       continue;
3618 +
3619 +               optp = _optp;
3620 +               fmatch = FMATCH_WRONG;
3621 +
3622 +               if (totlen == f->ss && df == f->df && 
3623 +                       smart_dec(info->flags, ip->ttl, f->ttl))
3624 +               {
3625 +                       unsigned long foptsize;
3626 +                       int optnum;
3627 +                       unsigned short mss = 0;
3628 +
3629 +                       check_WSS = 0;
3630 +
3631 +                       switch (f->wss.wc)
3632 +                       {
3633 +                               case 0:   check_WSS = 0; break;
3634 +                               case 'S': check_WSS = 1; break;
3635 +                               case 'T': check_WSS = 2; break;
3636 +                               case '%': check_WSS = 3; break;
3637 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
3638 +                                                        f->wss.wc, f->genre, f->details);
3639 +                                        check_WSS = 4;
3640 +                                        break;
3641 +                       }
3642 +                       if (check_WSS == 4)
3643 +                               continue;
3644 +
3645 +                       /* Check options */
3646 +
3647 +                       foptsize = 0;
3648 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
3649 +                               foptsize += f->opt[optnum].length;
3650 +
3651 +                               
3652 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
3653 +                               continue;
3654 +
3655 +                       if (!optp)
3656 +                       {
3657 +                               fmatch = FMATCH_OK;
3658 +                               loga("\tYEP : matching without options.\n");
3659 +                               if ((info->flags & IPT_OSF_LOG) && 
3660 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
3661 +                                       break;
3662 +                               else
3663 +                                       continue;
3664 +                       }
3665 +                       
3666 +
3667 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
3668 +                       {
3669 +                               if (f->opt[optnum].kind == (*optp))
3670 +                               {
3671 +                                       unsigned char len = f->opt[optnum].length;
3672 +                                       unsigned char *optend = optp + len;
3673 +
3674 +                                       fmatch = FMATCH_OK;
3675 +
3676 +                                       if (*optp == OSFOPT_MSS) /* MSS */
3677 +                                               mss = ntohs(*(unsigned short *)(optp+2));
3678 +                                       
3679 +                                       if (len != 1)
3680 +                                       {
3681 +                                               /* Skip kind and length fields*/
3682 +                                               optp += 2; 
3683 +
3684 +                                               if (f->opt[optnum].wc.wc != 0)
3685 +                                               {
3686 +                                                       unsigned long tmp = 0;
3687 +                                                       
3688 +                                                       /* Hmmm... It looks a bit ugly. :) */
3689 +                                                       memcpy(&tmp, &f->opt[optnum].wc.val, 
3690 +                                                               (len > sizeof(unsigned long)?
3691 +                                                                       sizeof(unsigned long):len));
3692 +
3693 +                                                       tmp = ntohl(tmp);
3694 +                                                       if (tmp != f->opt[optnum].wc.val)
3695 +                                                               fmatch = FMATCH_OPT_WRONG;
3696 +                                               }
3697 +                                       }
3698 +
3699 +                                       optp = optend;
3700 +                               }
3701 +                               else
3702 +                                       fmatch = FMATCH_OPT_WRONG;
3703 +
3704 +                               if (fmatch != FMATCH_OK)
3705 +                                       break;
3706 +                       }
3707 +
3708 +                       if (fmatch != FMATCH_OPT_WRONG)
3709 +                       {
3710 +                               fmatch = FMATCH_WRONG;
3711 +
3712 +                               switch (check_WSS)
3713 +                               {
3714 +                                       case 0:
3715 +                                               if (window == f->wss.val)
3716 +                                                       fmatch = FMATCH_OK;
3717 +                                               break;
3718 +                                       case 1: /* MSS */
3719 +                                               if (window == f->wss.val*mss)
3720 +                                                       fmatch = FMATCH_OK;
3721 +                                               break;
3722 +                                       case 2: /* MTU */
3723 +                                               if (window == f->wss.val*(mss+40))
3724 +                                                       fmatch = FMATCH_OK;
3725 +                                               break;
3726 +                                       case 3: /* MOD */
3727 +                                               if (window % f->wss.val == 0)
3728 +                                                       fmatch = FMATCH_OK;
3729 +                                               break;
3730 +                               }
3731 +                       }
3732 +                                       
3733 +
3734 +                       if (fmatch == FMATCH_OK)
3735 +                       {
3736 +                               fcount++;
3737 +                               log("%s [%s]: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
3738 +                                       f->genre, f->details,
3739 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
3740 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest));
3741 +                               if ((info->flags & IPT_OSF_LOG) && 
3742 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
3743 +                                       break;
3744 +                       }
3745 +               }
3746 +       }
3747 +       if (!fcount && (info->flags & IPT_OSF_LOG))
3748 +       {
3749 +               log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
3750 +               if (optp)
3751 +               {
3752 +                       unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
3753 +                       unsigned int i, optsize;
3754 +
3755 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
3756 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
3757 +                                         opt, optsize) < 0)
3758 +                               loga("TRUNCATED");
3759 +                       else
3760 +                               for (i = 0; i < optsize; i++)
3761 +                                       loga("%02X", opt[i]);
3762 +                       
3763 +               }  
3764 +               loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
3765 +                       NIPQUAD(ip->saddr), ntohs(tcp->source),
3766 +                       NIPQUAD(ip->daddr), ntohs(tcp->dest));
3767 +       }
3768 +       read_unlock(&osf_lock);
3769 +
3770 +       return (fmatch == FMATCH_OK)?1:0;
3771 +}
3772 +
3773 +static int
3774 +checkentry(const char *tablename,
3775 +           const struct ipt_ip *ip,
3776 +           void *matchinfo,
3777 +           unsigned int matchsize,
3778 +           unsigned int hook_mask)
3779 +{
3780 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
3781 +               return 0;
3782 +       if (ip->proto != IPPROTO_TCP)
3783 +              return 0;
3784 +
3785 +       return 1;
3786 +}
3787 +
3788 +static char * osf_strchr(char *ptr, char c)
3789 +{
3790 +       char *tmp;
3791 +
3792 +       tmp = strchr(ptr, c);
3793 +
3794 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
3795 +               tmp++;
3796 +
3797 +       return tmp;
3798 +}
3799 +
3800 +static struct osf_finger * finger_alloc(void)
3801 +{
3802 +       struct osf_finger *f;
3803 +
3804 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
3805 +       if (f)
3806 +               memset(f, 0, sizeof(struct osf_finger));
3807 +       
3808 +       return f;
3809 +}
3810 +
3811 +static void finger_free(struct osf_finger *f)
3812 +{
3813 +       memset(f, 0, sizeof(struct osf_finger));
3814 +       kfree(f);
3815 +}
3816 +
3817 +
3818 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
3819 +{
3820 +       int i, op;
3821 +       char *ptr, wc;
3822 +       unsigned long val;
3823 +
3824 +       ptr = &obuf[0];
3825 +       i = 0;
3826 +       while (ptr != NULL && i < olen)
3827 +       {
3828 +               val = 0;
3829 +               op = 0;
3830 +               wc = 0;
3831 +               switch (obuf[i])
3832 +               {
3833 +                       case 'N': 
3834 +                               op = OSFOPT_NOP;
3835 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3836 +                               if (ptr)
3837 +                               {
3838 +                                       *ptr = '\0';
3839 +                                       ptr++;
3840 +                                       i += (int)(ptr-&obuf[i]);
3841 +
3842 +                               }
3843 +                               else
3844 +                                       i++;
3845 +                               break;
3846 +                       case 'S': 
3847 +                               op = OSFOPT_SACKP;
3848 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3849 +                               if (ptr)
3850 +                               {
3851 +                                       *ptr = '\0';
3852 +                                       ptr++;
3853 +                                       i += (int)(ptr-&obuf[i]);
3854 +
3855 +                               }
3856 +                               else
3857 +                                       i++;
3858 +                               break;
3859 +                       case 'T': 
3860 +                               op = OSFOPT_TS;
3861 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3862 +                               if (ptr)
3863 +                               {
3864 +                                       *ptr = '\0';
3865 +                                       ptr++;
3866 +                                       i += (int)(ptr-&obuf[i]);
3867 +
3868 +                               }
3869 +                               else
3870 +                                       i++;
3871 +                               break;
3872 +                       case 'W': 
3873 +                               op = OSFOPT_WSO;
3874 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3875 +                               if (ptr)
3876 +                               {
3877 +                                       switch (obuf[i+1])
3878 +                                       {
3879 +                                               case '%':       wc = '%'; break;
3880 +                                               case 'S':       wc = 'S'; break;
3881 +                                               case 'T':       wc = 'T'; break;
3882 +                                               default:        wc = 0; break;
3883 +                                       }
3884 +                                       
3885 +                                       *ptr = '\0';
3886 +                                       ptr++;
3887 +                                       if (wc)
3888 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
3889 +                                       else
3890 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
3891 +                                       i += (int)(ptr-&obuf[i]);
3892 +
3893 +                               }
3894 +                               else
3895 +                                       i++;
3896 +                               break;
3897 +                       case 'M': 
3898 +                               op = OSFOPT_MSS;
3899 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3900 +                               if (ptr)
3901 +                               {
3902 +                                       if (obuf[i+1] == '%')
3903 +                                               wc = '%';
3904 +                                       *ptr = '\0';
3905 +                                       ptr++;
3906 +                                       if (wc)
3907 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
3908 +                                       else
3909 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
3910 +                                       i += (int)(ptr-&obuf[i]);
3911 +
3912 +                               }
3913 +                               else
3914 +                                       i++;
3915 +                               break;
3916 +                       case 'E': 
3917 +                               op = OSFOPT_EOL;
3918 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3919 +                               if (ptr)
3920 +                               {
3921 +                                       *ptr = '\0';
3922 +                                       ptr++;
3923 +                                       i += (int)(ptr-&obuf[i]);
3924 +
3925 +                               }
3926 +                               else
3927 +                                       i++;
3928 +                               break;
3929 +                       default:
3930 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
3931 +                               if (ptr)
3932 +                               {
3933 +                                       ptr++;
3934 +                                       i += (int)(ptr-&obuf[i]);
3935 +
3936 +                               }
3937 +                               else
3938 +                                       i++;
3939 +                               break;
3940 +               }
3941 +
3942 +               opt[*optnum].kind       = IANA_opts[op].kind;
3943 +               opt[*optnum].length     = IANA_opts[op].length;
3944 +               opt[*optnum].wc.wc      = wc;
3945 +               opt[*optnum].wc.val     = val;
3946 +
3947 +               (*optnum)++;
3948 +       }
3949 +}
3950 +
3951 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
3952 +{
3953 +       struct list_head *ent;
3954 +       struct osf_finger *f = NULL;
3955 +       int i;
3956 +       
3957 +       *eof = 1;
3958 +       count = 0;
3959 +
3960 +       read_lock_bh(&osf_lock);
3961 +       list_for_each(ent, &finger_list)
3962 +       {
3963 +               f = list_entry(ent, struct osf_finger, flist);
3964 +
3965 +               log("%s [%s]", f->genre, f->details);
3966 +               
3967 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
3968 +                                       f->genre, f->version,
3969 +                                       f->subtype, f->details);
3970 +               
3971 +               if (f->opt_num)
3972 +               {
3973 +                       loga(" OPT: ");
3974 +                       //count += sprintf(buf+count, " OPT: ");
3975 +                       for (i=0; i<f->opt_num; ++i)
3976 +                       {
3977 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
3978 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
3979 +                               loga("%d.%c%lu; ", 
3980 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
3981 +                       }
3982 +               }
3983 +               loga("\n");
3984 +               count += sprintf(buf+count, "\n");
3985 +       }
3986 +       read_unlock_bh(&osf_lock);
3987 +
3988 +       return count;
3989 +}
3990 +
3991 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
3992 +{
3993 +       int cnt;
3994 +       unsigned long i;
3995 +       char obuf[MAXOPTSTRLEN];
3996 +       struct osf_finger *finger;
3997 +       struct list_head *ent, *n;
3998 +
3999 +       char *pbeg, *pend;
4000 +
4001 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
4002 +       {
4003 +               int i = 0;
4004 +               write_lock_bh(&osf_lock);
4005 +               list_for_each_safe(ent, n, &finger_list)
4006 +               {
4007 +                       i++;
4008 +                       finger = list_entry(ent, struct osf_finger, flist);
4009 +                       list_del(&finger->flist);
4010 +                       finger_free(finger);
4011 +               }
4012 +               write_unlock_bh(&osf_lock);
4013 +       
4014 +               log("Flushed %d entries.\n", i);
4015 +               
4016 +               return count;
4017 +       }
4018 +
4019 +       
4020 +       cnt = 0;
4021 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
4022 +               if (buffer[i] == ':')
4023 +                       cnt++;
4024 +
4025 +       if (cnt != 8 || i != count)
4026 +       {
4027 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
4028 +                       cnt, i, count);
4029 +               return count;
4030 +       }
4031 +
4032 +       memset(obuf, 0, sizeof(obuf));
4033 +       
4034 +       finger = finger_alloc();
4035 +       if (!finger)
4036 +       {
4037 +               log("Failed to allocate new fingerprint entry.\n");
4038 +               return -ENOMEM;
4039 +       }
4040 +
4041 +       pbeg = (char *)buffer;
4042 +       pend = osf_strchr(pbeg, OSFPDEL);
4043 +       if (pend)
4044 +       {
4045 +               *pend = '\0';
4046 +               if (pbeg[0] == 'S')
4047 +               {
4048 +                       finger->wss.wc = 'S';
4049 +                       if (pbeg[1] == '%')
4050 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4051 +                       else if (pbeg[1] == '*')
4052 +                               finger->wss.val = 0;
4053 +                       else 
4054 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4055 +               }
4056 +               else if (pbeg[0] == 'T')
4057 +               {
4058 +                       finger->wss.wc = 'T';
4059 +                       if (pbeg[1] == '%')
4060 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
4061 +                       else if (pbeg[1] == '*')
4062 +                               finger->wss.val = 0;
4063 +                       else 
4064 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
4065 +               }
4066 +               if (isdigit(pbeg[0]))
4067 +               {
4068 +                       finger->wss.wc = 0;
4069 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
4070 +               }
4071 +
4072 +               pbeg = pend+1;
4073 +       }
4074 +       pend = osf_strchr(pbeg, OSFPDEL);
4075 +       if (pend)
4076 +       {
4077 +               *pend = '\0';
4078 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
4079 +               pbeg = pend+1;
4080 +       }
4081 +       pend = osf_strchr(pbeg, OSFPDEL);
4082 +       if (pend)
4083 +       {
4084 +               *pend = '\0';
4085 +               finger->df = simple_strtoul(pbeg, NULL, 10);
4086 +               pbeg = pend+1;
4087 +       }
4088 +       pend = osf_strchr(pbeg, OSFPDEL);
4089 +       if (pend)
4090 +       {
4091 +               *pend = '\0';
4092 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
4093 +               pbeg = pend+1;
4094 +       }
4095 +
4096 +       pend = osf_strchr(pbeg, OSFPDEL);
4097 +       if (pend)
4098 +       {
4099 +               *pend = '\0';
4100 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
4101 +               pbeg = pend+1;
4102 +       }
4103 +
4104 +       pend = osf_strchr(pbeg, OSFPDEL);
4105 +       if (pend)
4106 +       {
4107 +               *pend = '\0';
4108 +               if (pbeg[0] == '@' || pbeg[0] == '*')
4109 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
4110 +               else
4111 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
4112 +               pbeg = pend+1;
4113 +       }
4114 +       
4115 +       pend = osf_strchr(pbeg, OSFPDEL);
4116 +       if (pend)
4117 +       {
4118 +               *pend = '\0';
4119 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
4120 +               pbeg = pend+1;
4121 +       }
4122 +       
4123 +       pend = osf_strchr(pbeg, OSFPDEL);
4124 +       if (pend)
4125 +       {
4126 +               *pend = '\0';
4127 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
4128 +               pbeg = pend+1;
4129 +       }
4130 +
4131 +       cnt = snprintf(finger->details, 
4132 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
4133 +                       "%s", pbeg);
4134 +       
4135 +       log("%s - %s[%s] : %s\n", 
4136 +               finger->genre, finger->version,
4137 +               finger->subtype, finger->details);
4138 +       
4139 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
4140 +       
4141 +
4142 +       write_lock_bh(&osf_lock);
4143 +       list_add_tail(&finger->flist, &finger_list);
4144 +       write_unlock_bh(&osf_lock);
4145 +
4146 +       return count;
4147 +}
4148 +
4149 +static int __init osf_init(void)
4150 +{
4151 +       int err;
4152 +       struct proc_dir_entry *p;
4153 +
4154 +       log("Startng OS fingerprint matching module.\n");
4155 +
4156 +       INIT_LIST_HEAD(&finger_list);
4157 +       
4158 +       err = ipt_register_match(&osf_match);
4159 +       if (err)
4160 +       {
4161 +               log("Failed to register OS fingerprint matching module.\n");
4162 +               return -ENXIO;
4163 +       }
4164 +
4165 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
4166 +       if (!p)
4167 +       {
4168 +               ipt_unregister_match(&osf_match);
4169 +               return -ENXIO;
4170 +       }
4171 +
4172 +       p->write_proc = osf_proc_write;
4173 +       p->read_proc  = osf_proc_read;
4174 +
4175 +       return 0;
4176 +}
4177 +
4178 +static void __exit osf_fini(void)
4179 +{
4180 +       struct list_head *ent, *n;
4181 +       struct osf_finger *f;
4182 +       
4183 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
4184 +       ipt_unregister_match(&osf_match);
4185 +
4186 +       list_for_each_safe(ent, n, &finger_list)
4187 +       {
4188 +               f = list_entry(ent, struct osf_finger, flist);
4189 +               list_del(&f->flist);
4190 +               finger_free(f);
4191 +       }
4192 +       
4193 +       log("OS fingerprint matching module finished.\n");
4194 +}
4195 +
4196 +module_init(osf_init);
4197 +module_exit(osf_fini);
4198 +
4199 +MODULE_LICENSE("GPL");
4200 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
4201 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
4202 +
4203 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_pool.c
4204 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_pool.c   1970-01-01 01:00:00.000000000 +0100
4205 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_pool.c       2004-02-16 11:07:21.519802833 +0100
4206 @@ -0,0 +1,71 @@
4207 +/* Kernel module to match an IP address pool. */
4208 +
4209 +#include <linux/module.h>
4210 +#include <linux/ip.h>
4211 +#include <linux/skbuff.h>
4212 +
4213 +#include <linux/netfilter_ipv4/ip_tables.h>
4214 +#include <linux/netfilter_ipv4/ip_pool.h>
4215 +#include <linux/netfilter_ipv4/ipt_pool.h>
4216 +
4217 +static inline int match_pool(
4218 +       ip_pool_t index,
4219 +       __u32 addr,
4220 +       int inv
4221 +) {
4222 +       if (ip_pool_match(index, ntohl(addr)))
4223 +               inv = !inv;
4224 +       return inv;
4225 +}
4226 +
4227 +static int match(
4228 +       const struct sk_buff *skb,
4229 +       const struct net_device *in,
4230 +       const struct net_device *out,
4231 +       const void *matchinfo,
4232 +       int offset,
4233 +       const void *hdr,
4234 +       u_int16_t datalen,
4235 +       int *hotdrop
4236 +) {
4237 +       const struct ipt_pool_info *info = matchinfo;
4238 +       const struct iphdr *iph = skb->nh.iph;
4239 +
4240 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
4241 +                                               info->flags&IPT_POOL_INV_SRC))
4242 +               return 0;
4243 +
4244 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
4245 +                                               info->flags&IPT_POOL_INV_DST))
4246 +               return 0;
4247 +
4248 +       return 1;
4249 +}
4250 +
4251 +static int checkentry(
4252 +       const char *tablename,
4253 +       const struct ipt_ip *ip,
4254 +       void *matchinfo,
4255 +       unsigned int matchsize,
4256 +       unsigned int hook_mask
4257 +) {
4258 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
4259 +               return 0;
4260 +       return 1;
4261 +}
4262 +
4263 +static struct ipt_match pool_match
4264 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
4265 +
4266 +static int __init init(void)
4267 +{
4268 +       return ipt_register_match(&pool_match);
4269 +}
4270 +
4271 +static void __exit fini(void)
4272 +{
4273 +       ipt_unregister_match(&pool_match);
4274 +}
4275 +
4276 +module_init(init);
4277 +module_exit(fini);
4278 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_psd.c
4279 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_psd.c    1970-01-01 01:00:00.000000000 +0100
4280 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_psd.c        2004-02-16 11:07:22.387595011 +0100
4281 @@ -0,0 +1,361 @@
4282 +/*
4283 +  This is a module which is used for PSD (portscan detection)
4284 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
4285 +  and LOG target module.
4286 +
4287 +  Copyright (C) 2000,2001 astaro AG
4288 +
4289 +  This file is distributed under the terms of the GNU General Public
4290 +  License (GPL). Copies of the GPL can be obtained from:
4291 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
4292 +
4293 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
4294 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
4295 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
4296 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
4297 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
4298 +*/
4299 +
4300 +#include <linux/module.h>
4301 +#include <linux/skbuff.h>
4302 +#include <linux/ip.h>
4303 +#include <net/tcp.h>
4304 +#include <linux/spinlock.h>
4305 +#include <linux/netfilter_ipv4/ip_tables.h>
4306 +#include <linux/netfilter_ipv4/ipt_psd.h>
4307 +
4308 +#if 0
4309 +#define DEBUGP printk
4310 +#else
4311 +#define DEBUGP(format, args...)
4312 +#endif
4313 +
4314 +MODULE_LICENSE("GPL");
4315 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
4316 +
4317 +#define HF_DADDR_CHANGING   0x01
4318 +#define HF_SPORT_CHANGING   0x02
4319 +#define HF_TOS_CHANGING            0x04
4320 +#define HF_TTL_CHANGING            0x08
4321 +            
4322 +/*
4323 + * Information we keep per each target port
4324 + */
4325 +struct port {
4326 +       u_int16_t number;      /* port number */ 
4327 +       u_int8_t proto;        /* protocol number */
4328 +       u_int8_t and_flags;    /* tcp ANDed flags */
4329 +       u_int8_t or_flags;     /* tcp ORed flags */
4330 +};
4331 +
4332 +/*
4333 + * Information we keep per each source address.
4334 + */
4335 +struct host {
4336 +       struct host *next;              /* Next entry with the same hash */
4337 +       clock_t timestamp;              /* Last update time */
4338 +       struct in_addr src_addr;        /* Source address */
4339 +       struct in_addr dest_addr;       /* Destination address */
4340 +       unsigned short src_port;        /* Source port */
4341 +       int count;                      /* Number of ports in the list */
4342 +       int weight;                     /* Total weight of ports in the list */
4343 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
4344 +       unsigned char tos;              /* TOS */
4345 +       unsigned char ttl;              /* TTL */
4346 +       unsigned char flags;            /* HF_ flags bitmask */
4347 +};
4348 +
4349 +/*
4350 + * State information.
4351 + */
4352 +static struct {
4353 +       spinlock_t lock;
4354 +       struct host list[LIST_SIZE];    /* List of source addresses */
4355 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
4356 +       int index;                      /* Oldest entry to be replaced */
4357 +} state;
4358 +
4359 +/*
4360 + * Convert an IP address into a hash table index.
4361 + */
4362 +static inline int hashfunc(struct in_addr addr)
4363 +{
4364 +       unsigned int value;
4365 +       int hash;
4366 +
4367 +       value = addr.s_addr;
4368 +       hash = 0;
4369 +       do {
4370 +               hash ^= value;
4371 +       } while ((value >>= HASH_LOG));
4372 +
4373 +       return hash & (HASH_SIZE - 1);
4374 +}
4375 +
4376 +static int
4377 +ipt_psd_match(const struct sk_buff *pskb,
4378 +             const struct net_device *in,
4379 +             const struct net_device *out,
4380 +             const void *matchinfo,
4381 +             int offset,
4382 +             const void *hdr,
4383 +             u_int16_t datalen,
4384 +             int *hotdrop)
4385 +{
4386 +       struct iphdr *ip_hdr;
4387 +       struct tcphdr *tcp_hdr;
4388 +       struct in_addr addr;
4389 +       u_int16_t src_port,dest_port;
4390 +       u_int8_t tcp_flags, proto;
4391 +       clock_t now;
4392 +       struct host *curr, *last, **head;
4393 +       int hash, index, count;
4394 +
4395 +       /* Parameters from userspace */
4396 +       const struct ipt_psd_info *psdinfo = matchinfo;
4397 +
4398 +       /* IP header */
4399 +       ip_hdr = pskb->nh.iph;
4400 +
4401 +       /* Sanity check */
4402 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
4403 +               DEBUGP("PSD: sanity check failed\n");
4404 +               return 0;
4405 +       }
4406 +
4407 +       /* TCP or UDP ? */
4408 +       proto = ip_hdr->protocol;
4409 +
4410 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
4411 +               DEBUGP("PSD: protocol not supported\n");
4412 +               return 0;
4413 +       }
4414 +
4415 +       /* Get the source address, source & destination ports, and TCP flags */
4416 +
4417 +       addr.s_addr = ip_hdr->saddr;
4418 +
4419 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
4420 +
4421 +       /* Yep, it´s dirty */
4422 +       src_port = tcp_hdr->source;
4423 +       dest_port = tcp_hdr->dest;
4424 +
4425 +       if (proto == IPPROTO_TCP) {
4426 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
4427 +       }
4428 +       else {
4429 +               tcp_flags = 0x00;
4430 +       }
4431 +
4432 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
4433 +        * them spoof us. [DHCP needs this feature - HW] */
4434 +       if (!addr.s_addr) {
4435 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
4436 +               return 0;
4437 +       }
4438 +
4439 +       /* Use jiffies here not to depend on someone setting the time while we're
4440 +        * running; we need to be careful with possible return value overflows. */
4441 +       now = jiffies;
4442 +
4443 +       spin_lock(&state.lock);
4444 +
4445 +       /* Do we know this source address already? */
4446 +       count = 0;
4447 +       last = NULL;
4448 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
4449 +               do {
4450 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
4451 +                       count++;
4452 +                       if (curr->next) last = curr;
4453 +               } while ((curr = curr->next));
4454 +
4455 +       if (curr) {
4456 +
4457 +               /* We know this address, and the entry isn't too old. Update it. */
4458 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
4459 +                   time_after_eq(now, curr->timestamp)) {
4460 +
4461 +                       /* Just update the appropriate list entry if we've seen this port already */
4462 +                       for (index = 0; index < curr->count; index++) {
4463 +                               if (curr->ports[index].number == dest_port) {
4464 +                                       curr->ports[index].proto = proto;
4465 +                                       curr->ports[index].and_flags &= tcp_flags;
4466 +                                       curr->ports[index].or_flags |= tcp_flags;
4467 +                                       goto out_no_match;
4468 +                               }
4469 +                       }
4470 +
4471 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
4472 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
4473 +                               goto out_no_match;
4474 +
4475 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
4476 +                       curr->timestamp = now;
4477 +
4478 +                       /* Logged this scan already? Then drop the packet. */
4479 +                       if (curr->weight >= psdinfo->weight_threshold)
4480 +                               goto out_match;
4481 +
4482 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
4483 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
4484 +                               curr->flags |= HF_DADDR_CHANGING;
4485 +                       if (curr->src_port != src_port)
4486 +                               curr->flags |= HF_SPORT_CHANGING;
4487 +                       if (curr->tos != ip_hdr->tos)
4488 +                               curr->flags |= HF_TOS_CHANGING;
4489 +                       if (curr->ttl != ip_hdr->ttl)
4490 +                               curr->flags |= HF_TTL_CHANGING;
4491 +
4492 +                       /* Update the total weight */
4493 +                       curr->weight += (ntohs(dest_port) < 1024) ?
4494 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
4495 +
4496 +                       /* Got enough destination ports to decide that this is a scan? */
4497 +                       /* Then log it and drop the packet. */
4498 +                       if (curr->weight >= psdinfo->weight_threshold)
4499 +                               goto out_match;
4500 +
4501 +                       /* Remember the new port */
4502 +                       if (curr->count < SCAN_MAX_COUNT) {
4503 +                               curr->ports[curr->count].number = dest_port;
4504 +                               curr->ports[curr->count].proto = proto;
4505 +                               curr->ports[curr->count].and_flags = tcp_flags;
4506 +                               curr->ports[curr->count].or_flags = tcp_flags;
4507 +                               curr->count++;
4508 +                       }
4509 +
4510 +                       goto out_no_match;
4511 +               }
4512 +
4513 +               /* We know this address, but the entry is outdated. Mark it unused, and
4514 +                * remove from the hash table. We'll allocate a new entry instead since
4515 +                * this one might get re-used too soon. */
4516 +               curr->src_addr.s_addr = 0;
4517 +               if (last)
4518 +                       last->next = last->next->next;
4519 +               else if (*head)
4520 +                       *head = (*head)->next;
4521 +               last = NULL;
4522 +       }
4523 +
4524 +       /* We don't need an ACK from a new source address */
4525 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
4526 +               goto out_no_match;
4527 +
4528 +       /* Got too many source addresses with the same hash value? Then remove the
4529 +        * oldest one from the hash table, so that they can't take too much of our
4530 +        * CPU time even with carefully chosen spoofed IP addresses. */
4531 +       if (count >= HASH_MAX && last) last->next = NULL;
4532 +
4533 +       /* We're going to re-use the oldest list entry, so remove it from the hash
4534 +        * table first (if it is really already in use, and isn't removed from the
4535 +        * hash table already because of the HASH_MAX check above). */
4536 +
4537 +       /* First, find it */
4538 +       if (state.list[state.index].src_addr.s_addr)
4539 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
4540 +       else
4541 +               head = &last;
4542 +       last = NULL;
4543 +       if ((curr = *head))
4544 +       do {
4545 +               if (curr == &state.list[state.index]) break;
4546 +               last = curr;
4547 +       } while ((curr = curr->next));
4548 +
4549 +       /* Then, remove it */
4550 +       if (curr) {
4551 +               if (last)
4552 +                       last->next = last->next->next;
4553 +               else if (*head)
4554 +                       *head = (*head)->next;
4555 +       }
4556 +
4557 +       /* Get our list entry */
4558 +       curr = &state.list[state.index++];
4559 +       if (state.index >= LIST_SIZE) state.index = 0;
4560 +
4561 +       /* Link it into the hash table */
4562 +       head = &state.hash[hash];
4563 +       curr->next = *head;
4564 +       *head = curr;
4565 +
4566 +       /* And fill in the fields */
4567 +       curr->timestamp = now;
4568 +       curr->src_addr = addr;
4569 +       curr->dest_addr.s_addr = ip_hdr->daddr;
4570 +       curr->src_port = src_port;
4571 +       curr->count = 1;
4572 +       curr->weight = (ntohs(dest_port) < 1024) ?
4573 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
4574 +       curr->ports[0].number = dest_port;
4575 +       curr->ports[0].proto = proto;
4576 +       curr->ports[0].and_flags = tcp_flags;
4577 +       curr->ports[0].or_flags = tcp_flags;
4578 +       curr->tos = ip_hdr->tos;
4579 +       curr->ttl = ip_hdr->ttl;
4580 +
4581 +out_no_match:
4582 +       spin_unlock(&state.lock);
4583 +       return 0;
4584 +
4585 +out_match:
4586 +       spin_unlock(&state.lock);
4587 +       return 1;
4588 +}
4589 +
4590 +static int ipt_psd_checkentry(const char *tablename,
4591 +                             const struct ipt_ip *e,
4592 +                             void *matchinfo,
4593 +                             unsigned int matchsize,
4594 +                             unsigned int hook_mask)
4595 +{
4596 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
4597 +
4598 +       /* we accept TCP only */
4599 +/*     if (e->ip.proto != IPPROTO_TCP) { */
4600 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
4601 +/*             return 0; */
4602 +/*     } */
4603 +
4604 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
4605 +               DEBUGP("PSD: matchsize %u != %u\n",
4606 +                      matchsize,
4607 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
4608 +               return 0;
4609 +       }
4610 +
4611 +       return 1;
4612 +}
4613 +
4614 +static struct ipt_match ipt_psd_reg = { 
4615 +       {NULL, NULL},
4616 +       "psd",
4617 +       ipt_psd_match,
4618 +       ipt_psd_checkentry,
4619 +       NULL,
4620 +       THIS_MODULE };
4621 +
4622 +static int __init init(void)
4623 +{
4624 +       if (ipt_register_match(&ipt_psd_reg))
4625 +               return -EINVAL;
4626 +
4627 +       memset(&state, 0, sizeof(state));
4628 +
4629 +       spin_lock_init(&(state.lock));
4630 +
4631 +       printk("netfilter PSD loaded - (c) astaro AG\n");
4632 +       return 0;
4633 +}
4634 +
4635 +static void __exit fini(void)
4636 +{
4637 +       ipt_unregister_match(&ipt_psd_reg);
4638 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
4639 +}
4640 +
4641 +module_init(init);
4642 +module_exit(fini);
4643 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_quota.c
4644 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_quota.c  1970-01-01 01:00:00.000000000 +0100
4645 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_quota.c      2004-02-16 11:07:23.219395809 +0100
4646 @@ -0,0 +1,81 @@
4647 +/* 
4648 + * netfilter module to enforce network quotas
4649 + *
4650 + * Sam Johnston <samj@samj.net>
4651 + */
4652 +#include <linux/module.h>
4653 +#include <linux/skbuff.h>
4654 +#include <linux/spinlock.h>
4655 +#include <linux/interrupt.h>
4656 +
4657 +#include <linux/netfilter_ipv4/ip_tables.h>
4658 +#include <linux/netfilter_ipv4/ipt_quota.h>
4659 +
4660 +MODULE_LICENSE("GPL");
4661 +
4662 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
4663 +
4664 +static int
4665 +match(const struct sk_buff *skb,
4666 +      const struct net_device *in,
4667 +      const struct net_device *out,
4668 +      const void *matchinfo,
4669 +      int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
4670 +{
4671 +
4672 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
4673 +
4674 +        spin_lock_bh(&quota_lock);
4675 +
4676 +        if (q->quota >= datalen) {
4677 +                /* we can afford this one */
4678 +                q->quota -= datalen;
4679 +                spin_unlock_bh(&quota_lock);
4680 +
4681 +#ifdef DEBUG_IPT_QUOTA
4682 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
4683 +#endif
4684 +                return 1;
4685 +        }
4686 +
4687 +        /* so we do not allow even small packets from now on */
4688 +        q->quota = 0;
4689 +
4690 +#ifdef DEBUG_IPT_QUOTA
4691 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
4692 +#endif
4693 +
4694 +        spin_unlock_bh(&quota_lock);
4695 +        return 0;
4696 +}
4697 +
4698 +static int
4699 +checkentry(const char *tablename,
4700 +           const struct ipt_ip *ip,
4701 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
4702 +{
4703 +        /* TODO: spinlocks? sanity checks? */
4704 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
4705 +                return 0;
4706 +
4707 +        return 1;
4708 +}
4709 +
4710 +static struct ipt_match quota_match
4711 +    = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
4712 +
4713 +static int __init
4714 +init(void)
4715 +{
4716 +        return ipt_register_match(&quota_match);
4717 +}
4718 +
4719 +static void __exit
4720 +fini(void)
4721 +{
4722 +        ipt_unregister_match(&quota_match);
4723 +}
4724 +
4725 +module_init(init);
4726 +module_exit(fini);
4727 +
4728 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_random.c
4729 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
4730 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_random.c     2004-02-16 11:07:24.379118074 +0100
4731 @@ -0,0 +1,96 @@
4732 +/*
4733 +  This is a module which is used for a "random" match support.
4734 +  This file is distributed under the terms of the GNU General Public
4735 +  License (GPL). Copies of the GPL can be obtained from:
4736 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
4737 +
4738 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
4739 +*/
4740 +
4741 +#include <linux/module.h>
4742 +#include <linux/skbuff.h>
4743 +#include <linux/ip.h>
4744 +#include <linux/random.h>
4745 +#include <net/tcp.h>
4746 +#include <linux/spinlock.h>
4747 +#include <linux/netfilter_ipv4/ip_tables.h>
4748 +#include <linux/netfilter_ipv4/ipt_random.h>
4749 +
4750 +MODULE_LICENSE("GPL");
4751 +
4752 +static int
4753 +ipt_rand_match(const struct sk_buff *pskb,
4754 +              const struct net_device *in,
4755 +              const struct net_device *out,
4756 +              const void *matchinfo,
4757 +              int offset,
4758 +              const void *hdr,
4759 +              u_int16_t datalen,
4760 +              int *hotdrop)
4761 +{
4762 +       /* Parameters from userspace */
4763 +       const struct ipt_rand_info *info = matchinfo;
4764 +       u_int8_t random_number;
4765 +
4766 +       /* get 1 random number from the kernel random number generation routine */
4767 +       get_random_bytes((void *)(&random_number), 1);
4768 +
4769 +       /* Do we match ? */
4770 +       if (random_number <= info->average)
4771 +               return 1;
4772 +       else
4773 +               return 0;
4774 +}
4775 +
4776 +static int
4777 +ipt_rand_checkentry(const char *tablename,
4778 +                  const struct ipt_ip *e,
4779 +                  void *matchinfo,
4780 +                  unsigned int matchsize,
4781 +                  unsigned int hook_mask)
4782 +{
4783 +       /* Parameters from userspace */
4784 +       const struct ipt_rand_info *info = matchinfo;
4785 +
4786 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
4787 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
4788 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
4789 +               return 0;
4790 +       }
4791 +
4792 +       /* must be  1 <= average % <= 99 */
4793 +       /* 1  x 2.55 = 2   */
4794 +       /* 99 x 2.55 = 252 */
4795 +       if ((info->average < 2) || (info->average > 252)) {
4796 +               printk("ipt_random:  invalid average %u\n", info->average);
4797 +               return 0;
4798 +       }
4799 +
4800 +       return 1;
4801 +}
4802 +
4803 +static struct ipt_match ipt_rand_reg = { 
4804 +       {NULL, NULL},
4805 +       "random",
4806 +       ipt_rand_match,
4807 +       ipt_rand_checkentry,
4808 +       NULL,
4809 +       THIS_MODULE };
4810 +
4811 +static int __init init(void)
4812 +{
4813 +       if (ipt_register_match(&ipt_rand_reg))
4814 +               return -EINVAL;
4815 +
4816 +       printk("ipt_random match loaded\n");
4817 +       return 0;
4818 +}
4819 +
4820 +static void __exit fini(void)
4821 +{
4822 +       ipt_unregister_match(&ipt_rand_reg);
4823 +       printk("ipt_random match unloaded\n");
4824 +}
4825 +
4826 +module_init(init);
4827 +module_exit(fini);
4828 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_realm.c
4829 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_realm.c  1970-01-01 01:00:00.000000000 +0100
4830 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_realm.c      2004-02-16 11:07:26.369641375 +0100
4831 @@ -0,0 +1,68 @@
4832 +/* Kernel module to match realm from routing. */
4833 +#include <linux/module.h>
4834 +#include <linux/skbuff.h>
4835 +#include <linux/netdevice.h>
4836 +#include <net/route.h>
4837 +
4838 +#include <linux/netfilter_ipv4/ipt_realm.h>
4839 +#include <linux/netfilter_ipv4/ip_tables.h>
4840 +
4841 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
4842 +MODULE_LICENSE("GPL");
4843 +
4844 +static int
4845 +match(const struct sk_buff *skb,
4846 +      const struct net_device *in,
4847 +      const struct net_device *out,
4848 +      const void *matchinfo,
4849 +      int offset,
4850 +      const void *hdr,
4851 +      u_int16_t datalen,
4852 +      int *hotdrop)
4853 +{
4854 +       const struct ipt_realm_info *info = matchinfo;
4855 +       struct dst_entry *dst = skb->dst;
4856 +       u32 id;
4857 +    
4858 +       if(dst == NULL)
4859 +               return 0;
4860 +       id = dst->tclassid;
4861 +
4862 +       return (info->id == (id & info->mask)) ^ info->invert;
4863 +}
4864 +
4865 +static int check(const char *tablename,
4866 +                 const struct ipt_ip *ip,
4867 +                 void *matchinfo,
4868 +                 unsigned int matchsize,
4869 +                 unsigned int hook_mask)
4870 +{
4871 +       if (hook_mask
4872 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
4873 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
4874 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
4875 +                      "LOCAL_IN or FORWARD.\n");
4876 +               return 0;
4877 +       }
4878 +
4879 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
4880 +               return 0;
4881 +
4882 +       return 1;
4883 +}
4884 +
4885 +static struct ipt_match realm_match
4886 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
4887 +
4888 +static int __init init(void)
4889 +{
4890 +       return ipt_register_match(&realm_match);
4891 +}
4892 +
4893 +static void __exit fini(void)
4894 +{
4895 +       ipt_unregister_match(&realm_match);
4896 +}
4897 +
4898 +module_init(init);
4899 +module_exit(fini);
4900 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_time.c
4901 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_time.c   1970-01-01 01:00:00.000000000 +0100
4902 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_time.c       2004-02-16 11:07:27.150454383 +0100
4903 @@ -0,0 +1,185 @@
4904 +/*
4905 +  This is a module which is used for time matching
4906 +  It is using some modified code from dietlibc (localtime() function)
4907 +  that you can find at http://www.fefe.de/dietlibc/
4908 +  This file is distributed under the terms of the GNU General Public
4909 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
4910 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
4911 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
4912 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
4913 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
4914 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
4915 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
4916 +*/
4917 +
4918 +#include <linux/module.h>
4919 +#include <linux/skbuff.h>
4920 +#include <linux/netfilter_ipv4/ip_tables.h>
4921 +#include <linux/netfilter_ipv4/ipt_time.h>
4922 +#include <linux/time.h>
4923 +
4924 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
4925 +MODULE_DESCRIPTION("Match arrival timestamp");
4926 +MODULE_LICENSE("GPL");
4927 +
4928 +struct tm
4929 +{
4930 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
4931 +       int tm_min;                   /* Minutes.     [0-59] */
4932 +       int tm_hour;                  /* Hours.       [0-23] */
4933 +       int tm_mday;                  /* Day.         [1-31] */
4934 +       int tm_mon;                   /* Month.       [0-11] */
4935 +       int tm_year;                  /* Year - 1900.  */
4936 +       int tm_wday;                  /* Day of week. [0-6] */
4937 +       int tm_yday;                  /* Days in year.[0-365] */
4938 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
4939 +
4940 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
4941 +       const char *tm_zone;          /* we don't care, we count from GMT */
4942 +};
4943 +
4944 +void
4945 +localtime(const time_t *timepr, struct tm *r);
4946 +
4947 +static int
4948 +match(const struct sk_buff *skb,
4949 +      const struct net_device *in,
4950 +      const struct net_device *out,
4951 +      const void *matchinfo,
4952 +      int offset,
4953 +      const void *hdr,
4954 +      u_int16_t datalen,
4955 +      int *hotdrop)
4956 +{
4957 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
4958 +       struct tm currenttime;                          /* time human readable */
4959 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
4960 +       u_int16_t packet_time;
4961 +       struct timeval kerneltimeval;
4962 +       time_t packet_local_time;
4963 +
4964 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
4965 +       if (info->kerneltime)
4966 +       {
4967 +               do_gettimeofday(&kerneltimeval);
4968 +               packet_local_time = kerneltimeval.tv_sec;
4969 +       }
4970 +       else
4971 +               packet_local_time = skb->stamp.tv_sec;
4972 +
4973 +       /* Transform the timestamp of the packet, in a human readable form */
4974 +       localtime(&packet_local_time, &currenttime);
4975 +
4976 +       /* check if we match this timestamp, we start by the days... */
4977 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
4978 +               return 0; /* the day doesn't match */
4979 +
4980 +       /* ... check the time now */
4981 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
4982 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
4983 +               return 0;
4984 +
4985 +       /* here we match ! */
4986 +       return 1;
4987 +}
4988 +
4989 +static int
4990 +checkentry(const char *tablename,
4991 +           const struct ipt_ip *ip,
4992 +           void *matchinfo,
4993 +           unsigned int matchsize,
4994 +           unsigned int hook_mask)
4995 +{
4996 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
4997 +
4998 +       /* First, check that we are in the correct hook */
4999 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
5000 +       if (hook_mask
5001 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
5002 +       {
5003 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
5004 +               return 0;
5005 +       }
5006 +       /* we use the kerneltime if we are in forward or output */
5007 +       info->kerneltime = 1;
5008 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
5009 +               /* if not, we use the skb time */
5010 +               info->kerneltime = 0;
5011 +
5012 +       /* Check the size */
5013 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
5014 +               return 0;
5015 +       /* Now check the coherence of the data ... */
5016 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
5017 +           (info->time_stop  > 1439))
5018 +       {
5019 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
5020 +               return 0;
5021 +       }
5022 +
5023 +       return 1;
5024 +}
5025 +
5026 +static struct ipt_match time_match
5027 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
5028 +
5029 +static int __init init(void)
5030 +{
5031 +       printk("ipt_time loading\n");
5032 +       return ipt_register_match(&time_match);
5033 +}
5034 +
5035 +static void __exit fini(void)
5036 +{
5037 +       ipt_unregister_match(&time_match);
5038 +       printk("ipt_time unloaded\n");
5039 +}
5040 +
5041 +module_init(init);
5042 +module_exit(fini);
5043 +
5044 +
5045 +/* The part below is borowed and modified from dietlibc */
5046 +
5047 +/* seconds per day */
5048 +#define SPD 24*60*60
5049 +
5050 +void
5051 +localtime(const time_t *timepr, struct tm *r) {
5052 +       time_t i;
5053 +       time_t timep;
5054 +       extern struct timezone sys_tz;
5055 +       const unsigned int __spm[12] =
5056 +               { 0,
5057 +                 (31),
5058 +                 (31+28),
5059 +                 (31+28+31),
5060 +                 (31+28+31+30),
5061 +                 (31+28+31+30+31),
5062 +                 (31+28+31+30+31+30),
5063 +                 (31+28+31+30+31+30+31),
5064 +                 (31+28+31+30+31+30+31+31),
5065 +                 (31+28+31+30+31+30+31+31+30),
5066 +                 (31+28+31+30+31+30+31+31+30+31),
5067 +                 (31+28+31+30+31+30+31+31+30+31+30),
5068 +               };
5069 +       register time_t work;
5070 +
5071 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
5072 +       work=timep%(SPD);
5073 +       r->tm_sec=work%60; work/=60;
5074 +       r->tm_min=work%60; r->tm_hour=work/60;
5075 +       work=timep/(SPD);
5076 +       r->tm_wday=(4+work)%7;
5077 +       for (i=1970; ; ++i) {
5078 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
5079 +               if (work>k)
5080 +                       work-=k;
5081 +               else
5082 +                       break;
5083 +       }
5084 +       r->tm_year=i-1900;
5085 +       for (i=11; i && __spm[i]>work; --i) ;
5086 +       r->tm_mon=i;
5087 +       r->tm_mday=work-__spm[i]+1;
5088 +}
5089 diff -Nur linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.3-rc3/net/ipv4/netfilter/ipt_u32.c
5090 --- linux-2.6.3-rc3.org/net/ipv4/netfilter/ipt_u32.c    1970-01-01 01:00:00.000000000 +0100
5091 +++ linux-2.6.3-rc3/net/ipv4/netfilter/ipt_u32.c        2004-02-16 11:07:28.175208970 +0100
5092 @@ -0,0 +1,211 @@
5093 +/* Kernel module to match u32 packet content. */
5094 +
5095 +/* 
5096 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
5097 +have specified values.  The specification of what to extract is general 
5098 +enough to find data at given offsets from tcp headers or payloads.
5099 +
5100 + --u32 tests
5101 + The argument amounts to a program in a small language described below.
5102 + tests := location = value |  tests && location = value
5103 + value := range | value , range
5104 + range := number | number : number
5105 +  a single number, n, is interpreted the same as n:n
5106 +  n:m is interpreted as the range of numbers >=n and <=m
5107 + location := number | location operator number
5108 + operator := & | << | >> | @
5109 +
5110 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
5111 + membership operator and the value syntax describes a set.  The @ operator
5112 + is what allows moving to the next header and is described further below.
5113 +
5114 + *** Until I can find out how to avoid it, there are some artificial limits
5115 + on the size of the tests:
5116 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
5117 + - no more than 10 ranges (and 9 commas) per value
5118 + - no more than 10 numbers (and 9 operators) per location
5119 +
5120 + To describe the meaning of location, imagine the following machine that
5121 + interprets it.  There are three registers:
5122 +  A is of type char*, initially the address of the IP header
5123 +  B and C are unsigned 32 bit integers, initially zero
5124 +
5125 +  The instructions are:
5126 +   number      B = number;
5127 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
5128 +   &number     C = C&number
5129 +   <<number    C = C<<number
5130 +   >>number    C = C>>number
5131 +   @number     A = A+C; then do the instruction number
5132 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
5133 +  Otherwise the result of the computation is the final value of C.
5134 +
5135 + Whitespace is allowed but not required in the tests.
5136 + However the characters that do occur there are likely to require
5137 + shell quoting, so it's a good idea to enclose the arguments in quotes.
5138 +
5139 +Example:
5140 + match IP packets with total length >= 256
5141 + The IP header contains a total length field in bytes 2-3.
5142 + --u32 "0&0xFFFF=0x100:0xFFFF" 
5143 + read bytes 0-3
5144 + AND that with FFFF (giving bytes 2-3),
5145 + and test whether that's in the range [0x100:0xFFFF]
5146 +
5147 +Example: (more realistic, hence more complicated)
5148 + match icmp packets with icmp type 0
5149 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
5150 + --u32 "6&0xFF=1 && ...
5151 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
5152 + Next test that it's not a fragment.
5153 +  (If so it might be part of such a packet but we can't always tell.)
5154 +  n.b. This test is generally needed if you want to match anything
5155 +  beyond the IP header.
5156 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
5157 + packet (not a fragment).  Alternatively, you can allow first fragments
5158 + by only testing the last 5 bits of byte 6.
5159 + ... 4&0x3FFF=0 && ...
5160 + Last test: the first byte past the IP header (the type) is 0
5161 + This is where we have to use the @syntax.  The length of the IP header
5162 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
5163 + IP header itself.
5164 + ... 0>>22&0x3C@0>>24=0"
5165 + The first 0 means read bytes 0-3,
5166 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
5167 +   the first byte, so only 22 bits is four times that plus a few more bits.
5168 + &3C then eliminates the two extra bits on the right and the first four 
5169 + bits of the first byte.
5170 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
5171 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
5172 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
5173 + @ means to use this number as a new offset into the packet, and read
5174 + four bytes starting from there.  This is the first 4 bytes of the icmp
5175 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
5176 + the value 24 to the right to throw out all but the first byte and compare
5177 + the result with 0.
5178 +
5179 +Example: 
5180 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
5181 + First we test that the packet is a tcp packet (similar to icmp).
5182 + --u32 "6&0xFF=6 && ...
5183 + Next, test that it's not a fragment (same as above).
5184 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
5185 + 0>>22&3C as above computes the number of bytes in the IP header.
5186 + @ makes this the new offset into the packet, which is the start of the
5187 + tcp header.  The length of the tcp header (again in 32 bit words) is
5188 + the left half of byte 12 of the tcp header.  The 12>>26&3C
5189 + computes this length in bytes (similar to the IP header before).
5190 + @ makes this the new offset, which is the start of the tcp payload.
5191 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
5192 + result is any of 1, 2, 5 or 8
5193 +*/
5194 +
5195 +#include <linux/module.h>
5196 +#include <linux/skbuff.h>
5197 +
5198 +#include <linux/netfilter_ipv4/ipt_u32.h>
5199 +#include <linux/netfilter_ipv4/ip_tables.h>
5200 +
5201 +/* #include <asm-i386/timex.h> for timing */
5202 +
5203 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
5204 +MODULE_DESCRIPTION("IP tables u32 matching module");
5205 +MODULE_LICENSE("GPL");
5206 +
5207 +static int
5208 +match(const struct sk_buff *skb,
5209 +      const struct net_device *in,
5210 +      const struct net_device *out,
5211 +      const void *matchinfo,
5212 +      int offset,
5213 +      const void *hdr,
5214 +      u_int16_t datalen,
5215 +      int *hotdrop)
5216 +{
5217 +       const struct ipt_u32 *data = matchinfo;
5218 +       int testind, i;
5219 +       unsigned char* origbase = (char*)skb->nh.iph;
5220 +       unsigned char* base = origbase;
5221 +       unsigned char* head = skb->head;
5222 +       unsigned char* end = skb->end;
5223 +       int nnums, nvals;
5224 +       u_int32_t pos, val;
5225 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
5226 +          cycles1 = get_cycles(); */
5227 +
5228 +       for (testind=0; testind < data->ntests; testind++) {
5229 +               base = origbase; /* reset for each test */
5230 +               pos = data->tests[testind].location[0].number;
5231 +               if (base+pos+3 > end || base+pos < head) 
5232 +                       return 0;
5233 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
5234 +                       (base[pos+2]<<8) + base[pos+3];
5235 +               nnums = data->tests[testind].nnums;
5236 +               for (i=1; i < nnums; i++) {
5237 +                       u_int32_t number = data->tests[testind].location[i].number;
5238 +                       switch (data->tests[testind].location[i].nextop) {
5239 +                       case IPT_U32_AND: 
5240 +                               val = val & number; 
5241 +                               break;
5242 +                       case IPT_U32_LEFTSH: 
5243 +                               val = val << number;
5244 +                               break;
5245 +                       case IPT_U32_RIGHTSH: 
5246 +                               val = val >> number; 
5247 +                               break;
5248 +                       case IPT_U32_AT:
5249 +                               base = base + val;
5250 +                               pos = number;
5251 +                               if (base+pos+3 > end || base+pos < head) 
5252 +                                       return 0;
5253 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
5254 +                                       (base[pos+2]<<8) + base[pos+3];
5255 +                               break;
5256 +                       }
5257 +               }
5258 +               nvals = data->tests[testind].nvalues;
5259 +               for (i=0; i < nvals; i++) {
5260 +                       if ((data->tests[testind].value[i].min <= val) &&
5261 +                           (val <= data->tests[testind].value[i].max)) {
5262 +                               break;
5263 +                       }
5264 +               }
5265 +               if (i >= data->tests[testind].nvalues) {
5266 +                       /* cycles2 = get_cycles(); 
5267 +                          printk("failed %d in %d cycles\n", testind, 
5268 +                                 cycles2-cycles1); */
5269 +                       return 0;
5270 +               }
5271 +       }
5272 +       /* cycles2 = get_cycles();
5273 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
5274 +       return 1;
5275 +}
5276 +
5277 +static int
5278 +checkentry(const char *tablename,
5279 +           const struct ipt_ip *ip,
5280 +           void *matchinfo,
5281 +           unsigned int matchsize,
5282 +           unsigned int hook_mask)
5283 +{
5284 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
5285 +               return 0;
5286 +       return 1;
5287 +}
5288 +
5289 +static struct ipt_match u32_match
5290 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
5291 +
5292 +static int __init init(void)
5293 +{
5294 +       return ipt_register_match(&u32_match);
5295 +}
5296 +
5297 +static void __exit fini(void)
5298 +{
5299 +       ipt_unregister_match(&u32_match);
5300 +}
5301 +
5302 +module_init(init);
5303 +module_exit(fini);
5304 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/Kconfig linux-2.6.3-rc3/net/ipv6/netfilter/Kconfig
5305 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/Kconfig      2004-02-15 03:45:16.000000000 +0100
5306 +++ linux-2.6.3-rc3/net/ipv6/netfilter/Kconfig  2004-02-16 11:07:24.383117116 +0100
5307 @@ -218,5 +218,85 @@
5308           To compile it as a module, choose M here.  If unsure, say N.
5309  
5310  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
5311 +config IP6_NF_TARGET_HL
5312 +       tristate  'HL target support'
5313 +       depends on IP6_NF_MANGLE
5314 +         help
5315 +         This allows the user to set the IPv6 Hop Limit value on a packet or
5316 +         to increment or decrement it by a given value.
5317 +         
5318 +         Example:
5319 +         # ip6tables -t mangle -A OUTPUT -j HL --hl-inc 1
5320 +         # ip6tables -t mangle -A INPUT -j HL --hl-eq 64
5321 +         # ip6tables -t mangle -A OUTPUT -j HL --hl-dec 2
5322 +
5323 +config IP6_NF_TARGET_REJECT
5324 +       tristate  'REJECT target support'
5325 +       depends on IP6_NF_FILTER
5326 +         help
5327 +         This CONFIG_IP6_NF_TARGET_REJECT option adds a REJECT target to ip6tables.
5328 +         Please keep in mind that the icmp-types are different from the icmpv6 types
5329 +         (see ip6tables -j REJECT -h for more info)
5330 +
5331 +config IP6_NF_MATCH_FUZZY
5332 +       tristate  'Fuzzy match support'
5333 +       depends on IP6_NF_FILTER
5334 +         help
5335 +         This option adds a `fuzzy' match which allows you to match packets according to
5336 +         a dynamic profile implemented by means of a simple Fuzzy Logic Controller (FLC)
5337 +
5338 +config IP6_NF_MATCH_NTH
5339 +       tristate  'Nth match support'
5340 +       depends on IP6_NF_IPTABLES
5341 +         help
5342 +         This option adds an iptables `Nth' match, which allows you to match every Nth
5343 +         packet encountered.  By default there are 16 different counters that can be
5344 +         used.
5345 +         
5346 +         This match functions in one of two ways
5347 +         1) Match ever Nth packet, and only the Nth packet.
5348 +            example:
5349 +             iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
5350 +            This rule will drop every 10th packet.
5351 +         2) Unique rule for every packet.  This is an easy and quick
5352 +            method to produce load-balancing for both inbound and outbound.
5353 +            example:
5354 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
5355 +                      --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
5356 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
5357 +                      --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
5358 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
5359 +                      --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
5360 +            This example evenly splits connections between the three SNAT
5361 +            addresses.
5362 +         
5363 +            By using the mangle table and iproute2, you can setup complex
5364 +            load-balanced routing.  There's lot of other uses.  Be creative!
5365 +         
5366 +         Suppported options are:
5367 +            --every     Nth         Match every Nth packet
5368 +           [--counter]  num         Use counter 0-15 (default:0)
5369 +           [--start]    num         Initialize the counter at the number 'num'
5370 +                                    instead of 0. Must be between 0 and Nth-1
5371 +           [--packet]   num         Match on 'num' packet. Must be between 0
5372 +                                    and Nth-1.
5373 +                                    If --packet is used for a counter than
5374 +                                    there must be Nth number of --packet
5375 +                                    rules, covering all values between 0 and
5376 +                                    Nth-1 inclusively.
5377 +
5378 +config IP6_NF_MATCH_RANDOM
5379 +       tristate  'Random match support'
5380 +       depends on IP6_NF_IPTABLES
5381 +         help
5382 +         This option adds a `random' match,
5383 +         which allow you to match packets randomly
5384 +         following a given probability. 
5385 +         
5386 +         Suppported options are:
5387 +         
5388 +         [--average]   percent will match randomly packets with a probability of
5389 +                       'percent'. default is 50%
5390 +
5391  endmenu
5392  
5393 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/Makefile linux-2.6.3-rc3/net/ipv6/netfilter/Makefile
5394 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/Makefile     2004-02-15 03:44:25.000000000 +0100
5395 +++ linux-2.6.3-rc3/net/ipv6/netfilter/Makefile 2004-02-16 11:07:24.383117116 +0100
5396 @@ -8,6 +8,7 @@
5397  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
5398  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
5399  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
5400 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
5401  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
5402  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
5403  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
5404 @@ -19,6 +20,12 @@
5405  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
5406  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
5407  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
5408 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
5409  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
5410  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
5411 +
5412 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
5413 +
5414 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
5415 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
5416  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
5417 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_HL.c
5418 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_HL.c    1970-01-01 01:00:00.000000000 +0100
5419 +++ linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_HL.c        2004-02-16 11:06:53.521507853 +0100
5420 @@ -0,0 +1,105 @@
5421 +/* 
5422 + * Hop Limit modification target for ip6tables
5423 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
5424 + * Based on HW's TTL module
5425 + *
5426 + * This software is distributed under the terms of GNU GPL
5427 + */
5428 +
5429 +#include <linux/module.h>
5430 +#include <linux/skbuff.h>
5431 +#include <linux/ip.h>
5432 +
5433 +#include <linux/netfilter_ipv6/ip6_tables.h>
5434 +#include <linux/netfilter_ipv6/ip6t_HL.h>
5435 +
5436 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
5437 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
5438 +MODULE_LICENSE("GPL");
5439 +
5440 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
5441 +               const struct net_device *in, const struct net_device *out,
5442 +               const void *targinfo, void *userinfo)
5443 +{
5444 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
5445 +       const struct ip6t_HL_info *info = targinfo;
5446 +       u_int16_t diffs[2];
5447 +       int new_hl;
5448 +                        
5449 +       switch (info->mode) {
5450 +               case IP6T_HL_SET:
5451 +                       new_hl = info->hop_limit;
5452 +                       break;
5453 +               case IP6T_HL_INC:
5454 +                       new_hl = ip6h->hop_limit + info->hop_limit;
5455 +                       if (new_hl > 255)
5456 +                               new_hl = 255;
5457 +                       break;
5458 +               case IP6T_HL_DEC:
5459 +                       new_hl = ip6h->hop_limit + info->hop_limit;
5460 +                       if (new_hl < 0)
5461 +                               new_hl = 0;
5462 +                       break;
5463 +               default:
5464 +                       new_hl = ip6h->hop_limit;
5465 +                       break;
5466 +       }
5467 +
5468 +       if (new_hl != ip6h->hop_limit) {
5469 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
5470 +               ip6h->hop_limit = new_hl;
5471 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
5472 +       }
5473 +
5474 +       return IP6T_CONTINUE;
5475 +}
5476 +
5477 +static int ip6t_hl_checkentry(const char *tablename,
5478 +               const struct ip6t_entry *e,
5479 +               void *targinfo,
5480 +               unsigned int targinfosize,
5481 +               unsigned int hook_mask)
5482 +{
5483 +       struct ip6t_HL_info *info = targinfo;
5484 +
5485 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
5486 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
5487 +                               targinfosize,
5488 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
5489 +               return 0;       
5490 +       }       
5491 +
5492 +       if (strcmp(tablename, "mangle")) {
5493 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5494 +               return 0;
5495 +       }
5496 +
5497 +       if (info->mode > IP6T_HL_MAXMODE) {
5498 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
5499 +                       info->mode);
5500 +               return 0;
5501 +       }
5502 +
5503 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
5504 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
5505 +               return 0;
5506 +       }
5507 +       
5508 +       return 1;
5509 +}
5510 +
5511 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
5512 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
5513 +
5514 +static int __init init(void)
5515 +{
5516 +       return ip6t_register_target(&ip6t_HL);
5517 +}
5518 +
5519 +static void __exit fini(void)
5520 +{
5521 +       ip6t_unregister_target(&ip6t_HL);
5522 +}
5523 +
5524 +module_init(init);
5525 +module_exit(fini);
5526 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_REJECT.c
5527 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_REJECT.c        1970-01-01 01:00:00.000000000 +0100
5528 +++ linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_REJECT.c    2004-02-16 11:07:07.805087251 +0100
5529 @@ -0,0 +1,274 @@
5530 +/*
5531 + * This is a module which is used for rejecting packets.
5532 + *     Added support for customized reject packets (Jozsef Kadlecsik).
5533 + * Sun 12 Nov 2000
5534 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
5535 + */
5536 +#include <linux/config.h>
5537 +#include <linux/module.h>
5538 +#include <linux/skbuff.h>
5539 +#include <linux/icmpv6.h>
5540 +#include <net/tcp.h>
5541 +#include <linux/netfilter_ipv6/ip6_tables.h>
5542 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
5543 +
5544 +#if 1
5545 +#define DEBUGP printk
5546 +#else
5547 +#define DEBUGP(format, args...)
5548 +#endif
5549 +
5550 +#if 0
5551 +/* Send RST reply */
5552 +static void send_reset(struct sk_buff *oldskb)
5553 +{
5554 +       struct sk_buff *nskb;
5555 +       struct tcphdr *otcph, *tcph;
5556 +       struct rtable *rt;
5557 +       unsigned int otcplen;
5558 +       int needs_ack;
5559 +
5560 +       /* IP header checks: fragment, too short. */
5561 +       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
5562 +           || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
5563 +               return;
5564 +
5565 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
5566 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
5567 +
5568 +       /* No RST for RST. */
5569 +       if (otcph->rst)
5570 +               return;
5571 +
5572 +       /* Check checksum. */
5573 +       if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
5574 +                        oldskb->nh.iph->daddr,
5575 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
5576 +               return;
5577 +
5578 +       /* Copy skb (even if skb is about to be dropped, we can't just
5579 +           clone it because there may be other things, such as tcpdump,
5580 +           interested in it) */
5581 +       nskb = skb_copy(oldskb, GFP_ATOMIC);
5582 +       if (!nskb)
5583 +               return;
5584 +
5585 +       /* This packet will not be the same as the other: clear nf fields */
5586 +       nf_conntrack_put(nskb->nfct);
5587 +       nskb->nfct = NULL;
5588 +       nskb->nfcache = 0;
5589 +#ifdef CONFIG_NETFILTER_DEBUG
5590 +       nskb->nf_debug = 0;
5591 +#endif
5592 +
5593 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
5594 +
5595 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
5596 +       tcph->source = xchg(&tcph->dest, tcph->source);
5597 +
5598 +       /* Truncate to length (no data) */
5599 +       tcph->doff = sizeof(struct tcphdr)/4;
5600 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
5601 +       nskb->nh.iph->tot_len = htons(nskb->len);
5602 +
5603 +       if (tcph->ack) {
5604 +               needs_ack = 0;
5605 +               tcph->seq = otcph->ack_seq;
5606 +               tcph->ack_seq = 0;
5607 +       } else {
5608 +               needs_ack = 1;
5609 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
5610 +                                     + otcplen - (otcph->doff<<2));
5611 +               tcph->seq = 0;
5612 +       }
5613 +
5614 +       /* Reset flags */
5615 +       ((u_int8_t *)tcph)[13] = 0;
5616 +       tcph->rst = 1;
5617 +       tcph->ack = needs_ack;
5618 +
5619 +       tcph->window = 0;
5620 +       tcph->urg_ptr = 0;
5621 +
5622 +       /* Adjust TCP checksum */
5623 +       tcph->check = 0;
5624 +       tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
5625 +                                  nskb->nh.iph->saddr,
5626 +                                  nskb->nh.iph->daddr,
5627 +                                  csum_partial((char *)tcph,
5628 +                                               sizeof(struct tcphdr), 0));
5629 +
5630 +       /* Adjust IP TTL, DF */
5631 +       nskb->nh.iph->ttl = MAXTTL;
5632 +       /* Set DF, id = 0 */
5633 +       nskb->nh.iph->frag_off = htons(IP_DF);
5634 +       nskb->nh.iph->id = 0;
5635 +
5636 +       /* Adjust IP checksum */
5637 +       nskb->nh.iph->check = 0;
5638 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
5639 +                                          nskb->nh.iph->ihl);
5640 +
5641 +       /* Routing */
5642 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
5643 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
5644 +                           0) != 0)
5645 +               goto free_nskb;
5646 +
5647 +       dst_release(nskb->dst);
5648 +       nskb->dst = &rt->u.dst;
5649 +
5650 +       /* "Never happens" */
5651 +       if (nskb->len > nskb->dst->pmtu)
5652 +               goto free_nskb;
5653 +
5654 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
5655 +               ip_finish_output);
5656 +       return;
5657 +
5658 + free_nskb:
5659 +       kfree_skb(nskb);
5660 +}
5661 +#endif
5662 +
5663 +static unsigned int reject6_target(struct sk_buff **pskb,
5664 +                          unsigned int hooknum,
5665 +                          const struct net_device *in,
5666 +                          const struct net_device *out,
5667 +                          const void *targinfo,
5668 +                          void *userinfo)
5669 +{
5670 +       const struct ip6t_reject_info *reject = targinfo;
5671 +
5672 +       /* WARNING: This code causes reentry within ip6tables.
5673 +          This means that the ip6tables jump stack is now crap.  We
5674 +          must return an absolute verdict. --RR */
5675 +       DEBUGP("REJECTv6: calling icmpv6_send\n");
5676 +       switch (reject->with) {
5677 +       case IP6T_ICMP6_NO_ROUTE:
5678 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
5679 +               break;
5680 +       case IP6T_ICMP6_ADM_PROHIBITED:
5681 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
5682 +               break;
5683 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
5684 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
5685 +               break;
5686 +       case IP6T_ICMP6_ADDR_UNREACH:
5687 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
5688 +               break;
5689 +       case IP6T_ICMP6_PORT_UNREACH:
5690 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
5691 +               break;
5692 +#if 0
5693 +       case IPT_ICMP_ECHOREPLY: {
5694 +               struct icmp6hdr *icmph  = (struct icmphdr *)
5695 +                       ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
5696 +               unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
5697 +
5698 +               /* Not non-head frags, or truncated */
5699 +               if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
5700 +                   && datalen >= 4) {
5701 +                       /* Usually I don't like cut & pasting code,
5702 +                           but dammit, my party is starting in 45
5703 +                           mins! --RR */
5704 +                       struct icmp_bxm icmp_param;
5705 +
5706 +                       icmp_param.icmph=*icmph;
5707 +                       icmp_param.icmph.type=ICMP_ECHOREPLY;
5708 +                       icmp_param.data_ptr=(icmph+1);
5709 +                       icmp_param.data_len=datalen;
5710 +                       icmp_reply(&icmp_param, *pskb);
5711 +               }
5712 +       }
5713 +       break;
5714 +       case IPT_TCP_RESET:
5715 +               send_reset(*pskb);
5716 +               break;
5717 +#endif
5718 +       default:
5719 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
5720 +               break;
5721 +       }
5722 +
5723 +       return NF_DROP;
5724 +}
5725 +
5726 +static inline int find_ping_match(const struct ip6t_entry_match *m)
5727 +{
5728 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
5729 +
5730 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
5731 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
5732 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
5733 +               return 1;
5734 +
5735 +       return 0;
5736 +}
5737 +
5738 +static int check(const char *tablename,
5739 +                const struct ip6t_entry *e,
5740 +                void *targinfo,
5741 +                unsigned int targinfosize,
5742 +                unsigned int hook_mask)
5743 +{
5744 +       const struct ip6t_reject_info *rejinfo = targinfo;
5745 +
5746 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
5747 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
5748 +               return 0;
5749 +       }
5750 +
5751 +       /* Only allow these for packet filtering. */
5752 +       if (strcmp(tablename, "filter") != 0) {
5753 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
5754 +               return 0;
5755 +       }
5756 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
5757 +                          | (1 << NF_IP6_FORWARD)
5758 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
5759 +               DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
5760 +               return 0;
5761 +       }
5762 +
5763 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
5764 +               /* Must specify that it's an ICMP ping packet. */
5765 +               if (e->ipv6.proto != IPPROTO_ICMPV6
5766 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
5767 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
5768 +                       return 0;
5769 +               }
5770 +               /* Must contain ICMP match. */
5771 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
5772 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
5773 +                       return 0;
5774 +               }
5775 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
5776 +               /* Must specify that it's a TCP packet */
5777 +               if (e->ipv6.proto != IPPROTO_TCP
5778 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
5779 +                       DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
5780 +                       return 0;
5781 +               }
5782 +       }
5783 +
5784 +       return 1;
5785 +}
5786 +
5787 +static struct ip6t_target ip6t_reject_reg
5788 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
5789 +
5790 +static int __init init(void)
5791 +{
5792 +       if (ip6t_register_target(&ip6t_reject_reg))
5793 +               return -EINVAL;
5794 +       return 0;
5795 +}
5796 +
5797 +static void __exit fini(void)
5798 +{
5799 +       ip6t_unregister_target(&ip6t_reject_reg);
5800 +}
5801 +
5802 +module_init(init);
5803 +module_exit(fini);
5804 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_fuzzy.c
5805 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
5806 +++ linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_fuzzy.c     2004-02-16 11:07:14.926381841 +0100
5807 @@ -0,0 +1,189 @@
5808 +/*
5809 + * This module implements a simple TSK FLC
5810 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
5811 + * to limit , in an adaptive and flexible way , the packet rate crossing
5812 + * a given stream . It serves as an initial and very simple (but effective)
5813 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
5814 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
5815 + * into our code in a precise , adaptive and efficient manner.
5816 + *  The goal is very similar to that of "limit" match , but using techniques of
5817 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
5818 + * avoiding over and undershoots - and stuff like that .
5819 + *
5820 + *
5821 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
5822 + * 2002-08-17  : Changed to eliminate floating point operations .
5823 + * 2002-08-23  : Coding style changes .
5824 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
5825 + */
5826 +
5827 +#include <linux/module.h>
5828 +#include <linux/skbuff.h>
5829 +#include <linux/ipv6.h>
5830 +#include <linux/random.h>
5831 +#include <net/tcp.h>
5832 +#include <linux/spinlock.h>
5833 +#include <linux/netfilter_ipv6/ip6_tables.h>
5834 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
5835 +
5836 +/*
5837 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
5838 + Expressed in percentage
5839 +*/
5840 +
5841 +#define PAR_LOW                1/100
5842 +#define PAR_HIGH       1
5843 +
5844 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
5845 +
5846 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
5847 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
5848 +MODULE_LICENSE("GPL");
5849 +
5850 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
5851 +{
5852 +       if (tx >= maxi) return 100;
5853 +
5854 +       if (tx <= mini) return 0;
5855 +
5856 +       return ((100 * (tx-mini)) / (maxi-mini));
5857 +}
5858 +
5859 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
5860 +{
5861 +       if (tx <= mini) return 100;
5862 +
5863 +       if (tx >= maxi) return 0;
5864 +
5865 +       return ((100 * (maxi - tx)) / (maxi - mini));
5866 +
5867 +}
5868 +
5869 +static int
5870 +ip6t_fuzzy_match(const struct sk_buff *pskb,
5871 +              const struct net_device *in,
5872 +              const struct net_device *out,
5873 +              const void *matchinfo,
5874 +              int offset,
5875 +              const void *hdr,
5876 +              u_int16_t datalen,
5877 +              int *hotdrop)
5878 +{
5879 +       /* From userspace */
5880 +
5881 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
5882 +
5883 +       u_int8_t random_number;
5884 +       unsigned long amount;
5885 +       u_int8_t howhigh, howlow;
5886 +
5887 +
5888 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
5889 +
5890 +       info->bytes_total += pskb->len;
5891 +       info->packets_total++;
5892 +
5893 +       info->present_time = jiffies;
5894 +
5895 +       if (info->present_time >= info->previous_time)
5896 +               amount = info->present_time - info->previous_time;
5897 +       else {
5898 +               /* There was a transition : I choose to re-sample
5899 +                  and keep the old acceptance rate...
5900 +               */
5901 +
5902 +               amount = 0;
5903 +               info->previous_time = info->present_time;
5904 +               info->bytes_total = info->packets_total = 0;
5905 +            };
5906 +
5907 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
5908 +
5909 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
5910 +                                       / amount);
5911 +
5912 +               info->previous_time = info->present_time;
5913 +               info->bytes_total = info->packets_total = 0;
5914 +
5915 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
5916 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
5917 +
5918 +               info->acceptance_rate = (u_int8_t) \
5919 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
5920 +
5921 +       /* In fact, the above defuzzification would require a denominator
5922 +        * proportional to (howhigh+howlow) but, in this particular case,
5923 +        * that expression is constant.
5924 +        * An imediate consequence is that it is not necessary to call
5925 +        * both mf_high and mf_low - but to keep things understandable,
5926 +        * I did so.
5927 +        */
5928 +
5929 +       }
5930 +
5931 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
5932 +
5933 +
5934 +       if (info->acceptance_rate < 100)
5935 +       {
5936 +               get_random_bytes((void *)(&random_number), 1);
5937 +
5938 +               /*  If within the acceptance , it can pass => don't match */
5939 +               if (random_number <= (255 * info->acceptance_rate) / 100)
5940 +                       return 0;
5941 +               else
5942 +                       return 1; /* It can't pass (It matches) */
5943 +       };
5944 +
5945 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
5946 +
5947 +}
5948 +
5949 +static int
5950 +ip6t_fuzzy_checkentry(const char *tablename,
5951 +                  const struct ip6t_ip6 *ip,
5952 +                  void *matchinfo,
5953 +                  unsigned int matchsize,
5954 +                  unsigned int hook_mask)
5955 +{
5956 +
5957 +       const struct ip6t_fuzzy_info *info = matchinfo;
5958 +
5959 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
5960 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
5961 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
5962 +               return 0;
5963 +       }
5964 +
5965 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
5966 +        || (info->minimum_rate >= info->maximum_rate)) {
5967 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
5968 +               return 0;
5969 +       }
5970 +
5971 +       return 1;
5972 +}
5973 +
5974 +static struct ip6t_match ip6t_fuzzy_reg = {
5975 +       {NULL, NULL},
5976 +       "fuzzy",
5977 +       ip6t_fuzzy_match,
5978 +       ip6t_fuzzy_checkentry,
5979 +       NULL,
5980 +       THIS_MODULE };
5981 +
5982 +static int __init init(void)
5983 +{
5984 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
5985 +               return -EINVAL;
5986 +
5987 +       return 0;
5988 +}
5989 +
5990 +static void __exit fini(void)
5991 +{
5992 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
5993 +}
5994 +
5995 +module_init(init);
5996 +module_exit(fini);
5997 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_nth.c
5998 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_nth.c   1970-01-01 01:00:00.000000000 +0100
5999 +++ linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_nth.c       2004-02-16 11:07:18.803453352 +0100
6000 @@ -0,0 +1,173 @@
6001 +/*
6002 +  This is a module which is used for match support for every Nth packet
6003 +  This file is distributed under the terms of the GNU General Public
6004 +  License (GPL). Copies of the GPL can be obtained from:
6005 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
6006 +
6007 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
6008 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
6009 +        * added support for multiple counters
6010 +        * added support for matching on individual packets
6011 +          in the counter cycle
6012 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
6013 +
6014 +*/
6015 +
6016 +#include <linux/module.h>
6017 +#include <linux/skbuff.h>
6018 +#include <linux/ip.h>
6019 +#include <net/tcp.h>
6020 +#include <linux/spinlock.h>
6021 +#include <linux/netfilter_ipv6/ip6_tables.h>
6022 +#include <linux/netfilter_ipv6/ip6t_nth.h>
6023 +
6024 +MODULE_LICENSE("GPL");
6025 +
6026 +/*
6027 + * State information.
6028 + */
6029 +struct state {
6030 +       spinlock_t lock;
6031 +       u_int16_t number;
6032 +};
6033 +
6034 +static struct state states[IP6T_NTH_NUM_COUNTERS];
6035 +
6036 +static int
6037 +ip6t_nth_match(const struct sk_buff *pskb,
6038 +             const struct net_device *in,
6039 +             const struct net_device *out,
6040 +             const void *matchinfo,
6041 +             int offset,
6042 +             const void *hdr,
6043 +             u_int16_t datalen,
6044 +             int *hotdrop)
6045 +{
6046 +       /* Parameters from userspace */
6047 +       const struct ip6t_nth_info *info = matchinfo;
6048 +        unsigned counter = info->counter;
6049 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
6050 +       {
6051 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
6052 +               return 0;
6053 +        };
6054 +
6055 +        spin_lock(&states[counter].lock);
6056 +
6057 +        /* Are we matching every nth packet?*/
6058 +        if (info->packet == 0xFF)
6059 +        {
6060 +               /* We're matching every nth packet and only every nth packet*/
6061 +               /* Do we match or invert match? */
6062 +               if (info->not == 0)
6063 +               {
6064 +                       if (states[counter].number == 0)
6065 +                       {
6066 +                               ++states[counter].number;
6067 +                               goto match;
6068 +                       }
6069 +                       if (states[counter].number >= info->every)
6070 +                               states[counter].number = 0; /* reset the counter */
6071 +                       else
6072 +                               ++states[counter].number;
6073 +                       goto dontmatch;
6074 +               }
6075 +               else
6076 +               {
6077 +                       if (states[counter].number == 0)
6078 +                       {
6079 +                               ++states[counter].number;
6080 +                               goto dontmatch;
6081 +                       }
6082 +                       if (states[counter].number >= info->every)
6083 +                               states[counter].number = 0;
6084 +                       else
6085 +                               ++states[counter].number;
6086 +                       goto match;
6087 +               }
6088 +        }
6089 +        else
6090 +        {
6091 +               /* We're using the --packet, so there must be a rule for every value */
6092 +               if (states[counter].number == info->packet)
6093 +               {
6094 +                       /* only increment the counter when a match happens */
6095 +                       if (states[counter].number >= info->every)
6096 +                               states[counter].number = 0; /* reset the counter */
6097 +                       else
6098 +                               ++states[counter].number;
6099 +                       goto match;
6100 +               }
6101 +               else
6102 +                       goto dontmatch;
6103 +       }
6104 +
6105 + dontmatch:
6106 +       /* don't match */
6107 +       spin_unlock(&states[counter].lock);
6108 +       return 0;
6109 +
6110 + match:
6111 +       spin_unlock(&states[counter].lock);
6112 +       return 1;
6113 +}
6114 +
6115 +static int
6116 +ip6t_nth_checkentry(const char *tablename,
6117 +                  const struct ip6t_ip6 *e,
6118 +                  void *matchinfo,
6119 +                  unsigned int matchsize,
6120 +                  unsigned int hook_mask)
6121 +{
6122 +       /* Parameters from userspace */
6123 +       const struct ip6t_nth_info *info = matchinfo;
6124 +        unsigned counter = info->counter;
6125 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
6126 +       {
6127 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
6128 +                       return 0;
6129 +               };
6130 +
6131 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
6132 +               printk("nth: matchsize %u != %u\n", matchsize,
6133 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
6134 +               return 0;
6135 +       }
6136 +
6137 +       states[counter].number = info->startat;
6138 +
6139 +       return 1;
6140 +}
6141 +
6142 +static struct ip6t_match ip6t_nth_reg = { 
6143 +       {NULL, NULL},
6144 +       "nth",
6145 +       ip6t_nth_match,
6146 +       ip6t_nth_checkentry,
6147 +       NULL,
6148 +       THIS_MODULE };
6149 +
6150 +static int __init init(void)
6151 +{
6152 +       unsigned counter;
6153 +        memset(&states, 0, sizeof(states));
6154 +       if (ip6t_register_match(&ip6t_nth_reg))
6155 +               return -EINVAL;
6156 +
6157 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
6158 +       {
6159 +               spin_lock_init(&(states[counter].lock));
6160 +        };
6161 +
6162 +       printk("ip6t_nth match loaded\n");
6163 +       return 0;
6164 +}
6165 +
6166 +static void __exit fini(void)
6167 +{
6168 +       ip6t_unregister_match(&ip6t_nth_reg);
6169 +       printk("ip6t_nth match unloaded\n");
6170 +}
6171 +
6172 +module_init(init);
6173 +module_exit(fini);
6174 diff -Nur linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_random.c
6175 --- linux-2.6.3-rc3.org/net/ipv6/netfilter/ip6t_random.c        1970-01-01 01:00:00.000000000 +0100
6176 +++ linux-2.6.3-rc3/net/ipv6/netfilter/ip6t_random.c    2004-02-16 11:07:24.379118074 +0100
6177 @@ -0,0 +1,97 @@
6178 +/*
6179 +  This is a module which is used for a "random" match support.
6180 +  This file is distributed under the terms of the GNU General Public
6181 +  License (GPL). Copies of the GPL can be obtained from:
6182 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
6183 +
6184 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
6185 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
6186 +*/
6187 +
6188 +#include <linux/module.h>
6189 +#include <linux/skbuff.h>
6190 +#include <linux/ip.h>
6191 +#include <linux/random.h>
6192 +#include <net/tcp.h>
6193 +#include <linux/spinlock.h>
6194 +#include <linux/netfilter_ipv6/ip6_tables.h>
6195 +#include <linux/netfilter_ipv6/ip6t_random.h>
6196 +
6197 +MODULE_LICENSE("GPL");
6198 +
6199 +static int
6200 +ip6t_rand_match(const struct sk_buff *pskb,
6201 +              const struct net_device *in,
6202 +              const struct net_device *out,
6203 +              const void *matchinfo,
6204 +              int offset,
6205 +              const void *hdr,
6206 +              u_int16_t datalen,
6207 +              int *hotdrop)
6208 +{
6209 +       /* Parameters from userspace */
6210 +       const struct ip6t_rand_info *info = matchinfo;
6211 +       u_int8_t random_number;
6212 +
6213 +       /* get 1 random number from the kernel random number generation routine */
6214 +       get_random_bytes((void *)(&random_number), 1);
6215 +
6216 +       /* Do we match ? */
6217 +       if (random_number <= info->average)
6218 +               return 1;
6219 +       else
6220 +               return 0;
6221 +}
6222 +
6223 +static int
6224 +ip6t_rand_checkentry(const char *tablename,
6225 +                  const struct ip6t_ip6 *e,
6226 +                  void *matchinfo,
6227 +                  unsigned int matchsize,
6228 +                  unsigned int hook_mask)
6229 +{
6230 +       /* Parameters from userspace */
6231 +       const struct ip6t_rand_info *info = matchinfo;
6232 +
6233 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
6234 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
6235 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
6236 +               return 0;
6237 +       }
6238 +
6239 +       /* must be  1 <= average % <= 99 */
6240 +       /* 1  x 2.55 = 2   */
6241 +       /* 99 x 2.55 = 252 */
6242 +       if ((info->average < 2) || (info->average > 252)) {
6243 +               printk("ip6t_random:  invalid average %u\n", info->average);
6244 +               return 0;
6245 +       }
6246 +
6247 +       return 1;
6248 +}
6249 +
6250 +static struct ip6t_match ip6t_rand_reg = { 
6251 +       {NULL, NULL},
6252 +       "random",
6253 +       ip6t_rand_match,
6254 +       ip6t_rand_checkentry,
6255 +       NULL,
6256 +       THIS_MODULE };
6257 +
6258 +static int __init init(void)
6259 +{
6260 +       if (ip6t_register_match(&ip6t_rand_reg))
6261 +               return -EINVAL;
6262 +
6263 +       printk("ip6t_random match loaded\n");
6264 +       return 0;
6265 +}
6266 +
6267 +static void __exit fini(void)
6268 +{
6269 +       ip6t_unregister_match(&ip6t_rand_reg);
6270 +       printk("ip6t_random match unloaded\n");
6271 +}
6272 +
6273 +module_init(init);
6274 +module_exit(fini);
This page took 0.492683 seconds and 3 git commands to generate.