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