]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.x-patch-o-matic-ng-base-20040219.patch
- IT82XX seriec RAID support
[packages/kernel.git] / 2.6.x-patch-o-matic-ng-base-20040219.patch
1 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.3/include/linux/netfilter_ipv4/ip_pool.h
2 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_pool.h      1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_pool.h  2004-02-19 08:47:30.712978249 +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.org/include/linux/netfilter_ipv4/ip_set.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set.h
70 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set.h       1970-01-01 01:00:00.000000000 +0100
71 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set.h   2004-02-09 15:02:00.000000000 +0100
72 @@ -0,0 +1,440 @@
73 +#ifndef _IP_SET_H
74 +#define _IP_SET_H
75 +
76 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
77 + *                     Patrick Schaaf (bof@bof.de)
78 + *                     Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
79 + *
80 + * This program is free software; you can redistribute it and/or modify   
81 + * it under the terms of the GNU General Public License as published by   
82 + * the Free Software Foundation; either version 2 of the License, or      
83 + * (at your option) any later version.                                    
84 + *                                                                         
85 + * This program is distributed in the hope that it will be useful,        
86 + * but WITHOUT ANY WARRANTY; without even the implied warranty of         
87 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
88 + * GNU General Public License for more details.                           
89 + *                                                                         
90 + * You should have received a copy of the GNU General Public License      
91 + * along with this program; if not, write to the Free Software            
92 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
93 + */
94 +
95 +/*
96 + * A sockopt of such quality has hardly ever been seen before on the open
97 + * market!  This little beauty, hardly ever used: above 64, so it's
98 + * traditionally used for firewalling, not touched (even once!) by the
99 + * 2.0, 2.2 and 2.4 kernels!
100 + *
101 + * Comes with its own certificate of authenticity, valid anywhere in the
102 + * Free world!
103 + *
104 + * Rusty, 19.4.2000
105 + */
106 +#define SO_IP_SET              83
107 +
108 +/* Directions: */
109 +#define IPSET_SRC              0x01
110 +#define IPSET_DST              0x02
111 +/* Inverse flag for matching: */
112 +#define IPSET_MATCH_INV                0x04
113 +/* Overwrite at adding a new entry: */
114 +#define IPSET_ADD_OVERWRITE    0x08
115 +/* Set typecodes: */
116 +#define IPSET_TYPE_IP          0x10
117 +#define IPSET_TYPE_PORT                0x20
118 +
119 +/*FIXME: remove this */
120 +/* #define CONFIG_IP_NF_SET_DEBUG */
121 +
122 +/*
123 + * Heavily modify by Joakim Axelsson 08.03.2002
124 + * - Made it more modulebased
125 + *
126 + * Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
127 + * - multilevel pools (sets)
128 + * - in order to "deal with" backward compatibility, renamed to ipset
129 + */
130 +
131 +/* Used so that the kernel module and ipset-binary can match thier versions 
132 + */
133 +#define IP_SET_PROTOCOL_VERSION 1
134 +
135 +#define IP_SET_MAXNAMELEN 32   /* set names and set typenames */
136 +
137 +/* The max level of the sets. 
138 + * Do not increase lightheartedly before eliminating
139 + * the recursive functions from ip_set.c.
140 + */
141 +/* So many IPs can identify a set: */
142 +#define IP_SET_SETIP_LEVELS    4
143 +/* Max level of a set: */
144 +#define IP_SET_LEVELS          (IP_SET_SETIP_LEVELS+1)
145 +
146 +/* Lets work with our own typedef for representing an IP address.
147 + * We hope to make the code more portable, possibly to IPv6...
148 + *
149 + * The representation works in HOST byte order, because most set types
150 + * will perform arithmetic operations and compare operations.
151 + * 
152 + * For now the type is an uint32_t.
153 + *
154 + * We do not enforce, but assume that a set may not store more than 
155 + * 65536 entries.
156 + *
157 + * Make sure to ONLY use the functions when translating and parsing
158 + * in order to keep the host byte order and make it more portable:
159 + *  parse_ip()
160 + *  parse_mask()
161 + *  parse_ipandmask()
162 + *  ip_tostring()
163 + * (Joakim: where are they???)
164 + */
165 +
166 +typedef uint32_t ip_set_ip_t;
167 +
168 +/* SO_IP_SET operation constants, and their request struct types.
169 + */
170 +
171 +/* IP_SET_REQ_BASE defines the first components of ANY request structure.
172 + * It is used for all SO_IP_SET calls, set or get.
173 + */
174 +#define IP_SET_REQ_BASE \
175 +       unsigned op; \
176 +       int id \
177 +       
178 +struct ip_set_req_base {
179 +       IP_SET_REQ_BASE;
180 +};
181 +
182 +struct ip_set_req_std {
183 +       IP_SET_REQ_BASE;
184 +       ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
185 +       u_int8_t level;
186 +};
187 +
188 +#define IP_SET_OP_CREATE       0x00000001      /* Create a new (empty) set */
189 +struct ip_set_req_create {
190 +       IP_SET_REQ_BASE;
191 +       char name[IP_SET_MAXNAMELEN];
192 +       char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN];
193 +       u_int8_t levels;
194 +};
195 +
196 +#define IP_SET_OP_DESTROY      0x00000002      /* Remove a (empty) set */
197 +/* Uses ip_set_req_std */
198 +
199 +#define IP_SET_OP_CREATE_CHILD         0x00000003      /* Create a new child set */
200 +struct ip_set_req_sub {
201 +       IP_SET_REQ_BASE;
202 +       ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
203 +       u_int8_t level;
204 +       u_int8_t childsets;
205 +};
206 +
207 +#define IP_SET_OP_FLUSH                0x00000004      /* Remove all IPs in a set */
208 +/* Uses ip_set_req_sub */
209 +
210 +#define IP_SET_OP_RENAME       0x00000005      /* Rename a set */
211 +struct ip_set_req_rename {
212 +       IP_SET_REQ_BASE;
213 +       char newname[IP_SET_MAXNAMELEN];
214 +};
215 +
216 +#define IP_SET_OP_SWAP         0x00000006      /* Swap two sets */
217 +struct ip_set_req_swap {
218 +       IP_SET_REQ_BASE;
219 +       int to;
220 +};
221 +
222 +#define IP_SET_OP_ADD_IP       0x00000007      /* Add an IP to a set */
223 +/* Uses ip_set_req_std, with type specific addage */
224 +
225 +#define IP_SET_OP_DEL_IP       0x00000008      /* Remove an IP from a set */
226 +/* Uses ip_set_req_std, with type specific addage */
227 +
228 +/* Test if an IP is in the set
229 + */
230 +#define IP_SET_OP_TEST_IP      0x00000009      /* Test an IP in a set */
231 +struct ip_set_req_test {
232 +       IP_SET_REQ_BASE;
233 +       ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
234 +       u_int8_t level;
235 +       int reply;              /* Test result */
236 +};
237 +
238 +#define IP_SET_OP_VERSION      0x00000010
239 +struct ip_set_req_version {
240 +       IP_SET_REQ_BASE;
241 +       unsigned version;
242 +};
243 +
244 +/* List operations:
245 + * Size requests are sent by ip_set_req_list
246 + * except for LISTING.
247 + */
248 +#define IP_SET_OP_LIST_HEADER_SIZE     0x00000101
249 +#define IP_SET_OP_LIST_HEADER          0x00000102
250 +#define IP_SET_OP_LIST_MEMBERS_SIZE    0x00000103
251 +#define IP_SET_OP_LIST_MEMBERS         0x00000104
252 +#define IP_SET_OP_LIST_CHILDSETS_SIZE  0x00000105
253 +#define IP_SET_OP_LIST_CHILDSETS       0x00000106
254 +struct ip_set_req_list {
255 +       IP_SET_REQ_BASE;
256 +       ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
257 +       u_int8_t level;
258 +       size_t size;
259 +};
260 +
261 +#define IP_SET_OP_LISTING_SIZE         0x00000107
262 +#define IP_SET_OP_LISTING              0x00000108
263 +
264 +struct ip_set_req_listing_size {
265 +       IP_SET_REQ_BASE;
266 +       size_t size;
267 +};
268 +
269 +struct ip_set_req_listing {
270 +       char name[IP_SET_MAXNAMELEN];
271 +       char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN];
272 +       u_int8_t levels;
273 +       unsigned ref;
274 +       int id;
275 +};
276 +
277 +/* Between the iptables(8) set extension modules and the kernel we
278 + * identify a set by its id.
279 + *
280 + * The GETSET_BYNAME call passes the name of a set to the kernel, and
281 + * the a valid set id is returned if the set is still exist.
282 + * The GETSET_BYID call passes the id a set to the kernel, and
283 + * the set name is returned if the set is still exist.
284 + */
285 +#define IP_SET_OP_GETSET_BYNAME                0x00000011
286 +struct ip_set_req_get {
287 +       IP_SET_REQ_BASE;
288 +       unsigned ref;
289 +       char name[IP_SET_MAXNAMELEN];
290 +};
291 +
292 +#define IP_SET_OP_GETSET_BYID          0x00000012
293 +/* Uses ip_set_req_get */
294 +
295 +static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
296 +{
297 +       return 4 * ((((b - a + 8) / 8) + 3) / 4);
298 +}
299 +
300 +#ifdef __KERNEL__
301 +
302 +#define ip_set_printk(format, args...)                         \
303 +       do {                                                    \
304 +               printk("%s: %s: ", __FILE__, __FUNCTION__);     \
305 +               printk(format "\n" , ## args);                  \
306 +       } while (0)
307 +
308 +#if defined(CONFIG_IP_NF_SET_DEBUG) || defined(CONFIG_IP_NF_SET_DEBUG_MODULE)
309 +#define CONFIG_IP_NF_SET_DEBUG
310 +#define CONFIG_IP_NF_SET_DEBUG_MODULE
311 +
312 +#define DP(format, args...)                                    \
313 +       do {                                                    \
314 +               printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
315 +               printk(format "\n" , ## args);                  \
316 +       } while (0)
317 +#else
318 +#define DP(format, args...)
319 +#endif
320 +
321 +/* Generic set type: */
322 +struct ip_set_private {
323 +       struct ip_set_private **childsets;      /* child sets */
324 +
325 +       /* type speficic members */
326 +};
327 +
328 +/*
329 + * The ip_set_type_t definition - one per set type, e.g. "ipmap".
330 + *
331 + * Each individual set has a pointer, set->type, going to one
332 + * of these structures. Function pointers inside the structure implement
333 + * the real behaviour of the sets.
334 + *
335 + * If not mentioned differently, the implementation behind the function
336 + * pointers of a set_type, is expected to return 0 if ok, and a negative
337 + * errno (e.g. -EINVAL) on error.
338 + */
339 +struct ip_set_type {
340 +       struct list_head list;  /* next in list of set types */
341 +
342 +       /* match IP in set - internally required
343 +        * return 0 if not in set, 1 if in set or
344 +        * negative errno if input was invalid
345 +        */
346 +       int (*matchip) (struct ip_set_private *private,
347 +                       ip_set_ip_t ip,
348 +                       ip_set_ip_t *id);
349 +
350 +       /* test for IP in set (kernel: iptables -m set --entry x)
351 +        * return 0 if not in set, 1 if in set.
352 +        */
353 +       int (*testip_kernel) (struct ip_set_private *private,
354 +                             const struct sk_buff * skb, 
355 +                             u_int32_t flags,
356 +                             ip_set_ip_t *id);
357 +
358 +       /* test for IP in set (userspace: ipset -T set --entry x)
359 +        * return 0 if not in set, 1 if in set.
360 +        */
361 +       int (*testip) (struct ip_set_private *private,
362 +                      const void *data, size_t size,
363 +                      ip_set_ip_t *id);
364 +
365 +       /*
366 +        * Size of the data structure passed by when
367 +        * adding/deletin/testing an entry.
368 +        */
369 +       size_t reqsize;
370 +
371 +       /* Add IP into set (userspace: ipset -A set --entry x)
372 +        * Return -EEXIST if the address is already in the set,
373 +        * and -ERANGE if the address lies outside the set bounds.
374 +        * If the address was not already in the set, 0 is returned.
375 +        */
376 +       int (*addip) (struct ip_set_private *private, 
377 +                     const void *data, size_t size,
378 +                     ip_set_ip_t *id);
379 +
380 +       /* Add IP into set (kernel: iptables ... -j SET --entry x)
381 +        * Return -EEXIST if the address is already in the set,
382 +        * and -ERANGE if the address lies outside the set bounds.
383 +        * If the address was not already in the set, 0 is returned.
384 +        */
385 +       int (*addip_kernel) (struct ip_set_private *private,
386 +                            const struct sk_buff * skb, 
387 +                            u_int32_t flags,
388 +                            ip_set_ip_t *id);
389 +
390 +       /* remove IP from set (userspace: ipset -D set --entry x)
391 +        * Return -EEXIST if the address is NOT in the set,
392 +        * and -ERANGE if the address lies outside the set bounds.
393 +        * If the address really was in the set, 0 is returned.
394 +        */
395 +       int (*delip) (struct ip_set_private *private, 
396 +                     const void *data, size_t size,
397 +                     ip_set_ip_t *id);
398 +
399 +       /* remove IP from set (kernel: iptables ... -j SET --entry x)
400 +        * Return -EEXIST if the address is NOT in the set,
401 +        * and -ERANGE if the address lies outside the set bounds.
402 +        * If the address really was in the set, 0 is returned.
403 +        */
404 +       int (*delip_kernel) (struct ip_set_private *private,
405 +                            const struct sk_buff * skb, 
406 +                            u_int32_t flags,
407 +                            ip_set_ip_t *id);
408 +
409 +       /* new set creation - allocated type specific items
410 +        */
411 +       int (*create) (struct ip_set_private **private,
412 +                      const void *data, size_t size);
413 +
414 +       /* set destruction - free type specific items
415 +        * There is no return value.
416 +        * Can be called only when child sets are destroyed.
417 +        */
418 +       void (*destroy) (struct ip_set_private **private);
419 +
420 +       /* set flushing - reset all bits in the set, or something similar.
421 +        * There is no return value.
422 +        */
423 +       void (*flush) (struct ip_set_private *private);
424 +
425 +       /* Listing: Get size needed for header
426 +        */
427 +       int (*list_header_size) (const struct ip_set_private *private);
428 +
429 +       /* Listing: Get the header
430 +        *
431 +        * Fill in the information in "data".
432 +        * This function is always run after list_header_size() under a 
433 +        * writelock on the set. Therefor is the length of "data" always 
434 +        * correct. 
435 +        */
436 +       void (*list_header) (const struct ip_set_private *private, 
437 +                            void *data);
438 +
439 +       /* Listing: Get the size for the set members
440 +        */
441 +       int (*list_members_size) (const struct ip_set_private *private);
442 +
443 +       /* Listing: Get the set members
444 +        *
445 +        * Fill in the information in "data".
446 +        * This function is always run after list_member_size() under a 
447 +        * writelock on the set. Therefor is the length of "data" always 
448 +        * correct. 
449 +        */
450 +       void (*list_members) (const struct ip_set_private *private,
451 +                             void *data);
452 +
453 +       /* Listing: set size in ids (first id is 0. Cannot change for a set).
454 +        */
455 +       ip_set_ip_t (*sizeid) (const struct ip_set_private *private);
456 +
457 +       /* Listing: Get the bitmap for the valid childsets
458 +        */
459 +       void (*list_childsets) (const struct ip_set_private *private,
460 +                               void *data);
461 +
462 +       char typename[IP_SET_MAXNAMELEN];
463 +       char typecode;
464 +       int protocol_version;
465 +
466 +       /* Set this to THIS_MODULE if you are a module, otherwise NULL */
467 +       struct module *me;
468 +};
469 +
470 +extern int ip_set_register_set_type(struct ip_set_type *set_type);
471 +extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
472 +
473 +/* A generic ipset */
474 +struct ip_set {
475 +       struct list_head list;          /* next in list of all sets */
476 +       rwlock_t lock;                  /* a lock for concurrency control */
477 +       unsigned ref;                   /* reference counter */
478 +       unsigned subref;                /* reference counter at creating/destroying childsets */
479 +       u_int8_t levels;                /* max levels of subsets */
480 +       struct ip_set_type *type[IP_SET_LEVELS]; /* the set types */
481 +       struct ip_set_private *private; /* type specific data */
482 +       char name[IP_SET_MAXNAMELEN];   /* the proper name of the set */
483 +};
484 +
485 +extern struct ip_set **ip_set_list;
486 +
487 +/* register and unregister set pointer references */
488 +extern struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
489 +                                       int *id);
490 +extern struct ip_set *ip_set_get_byid(int id);
491 +extern void ip_set_put(struct ip_set *set);
492 +
493 +/* API for iptables set match, and SET target */
494 +extern void ip_set_addip_kernel(struct ip_set *set,
495 +                               const struct sk_buff *skb,
496 +                               const u_int32_t *flags,
497 +                               u_int8_t set_level,
498 +                               u_int8_t ip_level);
499 +extern void ip_set_delip_kernel(struct ip_set *set,
500 +                               const struct sk_buff *skb,
501 +                               const u_int32_t *flags,
502 +                               u_int8_t set_level,
503 +                               u_int8_t ip_level);
504 +extern int ip_set_testip_kernel(struct ip_set *set,
505 +                               const struct sk_buff *skb,
506 +                               const u_int32_t *flags,
507 +                               u_int8_t set_level,
508 +                               u_int8_t ip_level);
509 +
510 +#endif                         /* __KERNEL__ */
511 +
512 +#endif /*_IP_SET_H*/
513 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_iphash.h
514 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_iphash.h        1970-01-01 01:00:00.000000000 +0100
515 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_iphash.h    2004-02-09 15:02:00.000000000 +0100
516 @@ -0,0 +1,30 @@
517 +#ifndef __IP_SET_IPHASH_H
518 +#define __IP_SET_IPHASH_H
519 +
520 +#include <linux/netfilter_ipv4/ip_set.h>
521 +
522 +#define SETTYPE_NAME "iphash"
523 +#define MAX_RANGE 0x0000FFFF
524 +
525 +struct ip_set_iphash {
526 +       struct ip_set_private **childsets;      /* child sets */
527 +
528 +       /* Type speficic members: */
529 +       uint32_t initval;               /* initval for jhash_1word */
530 +       ip_set_ip_t hashsize;           /* hash size */
531 +       ip_set_ip_t netmask;            /* netmask */
532 +       ip_set_ip_t *members;           /* the iphash proper */
533 +};
534 +
535 +struct ip_set_req_iphash_create {
536 +       uint32_t initval;
537 +       ip_set_ip_t hashsize;
538 +       ip_set_ip_t netmask;
539 +};
540 +
541 +struct ip_set_req_iphash {
542 +       ip_set_ip_t ip;
543 +       u_int32_t flags;
544 +};
545 +
546 +#endif /* __IP_SET_IPHASH_H */
547 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_ipmap.h
548 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
549 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_ipmap.h     2004-02-09 15:02:00.000000000 +0100
550 @@ -0,0 +1,59 @@
551 +#ifndef __IP_SET_IPMAP_H
552 +#define __IP_SET_IPMAP_H
553 +
554 +#include <linux/netfilter_ipv4/ip_set.h>
555 +
556 +#define SETTYPE_NAME "ipmap"
557 +#define MAX_RANGE 0x0000FFFF
558 +
559 +struct ip_set_ipmap {
560 +       struct ip_set_private **childsets;      /* child sets */
561 +
562 +       /* Type speficic members: */
563 +       ip_set_ip_t first_ip;           /* host byte order, included in range */
564 +       ip_set_ip_t last_ip;            /* host byte order, included in range */
565 +       ip_set_ip_t netmask;            /* subnet netmask */
566 +       ip_set_ip_t sizeid;             /* size of set in ids */
567 +       u_int16_t hosts;                /* hosts per subnet */
568 +       void *members;                  /* the ipmap proper */
569 +};
570 +
571 +struct ip_set_req_ipmap_create {
572 +       ip_set_ip_t from;
573 +       ip_set_ip_t to;
574 +       ip_set_ip_t netmask;
575 +};
576 +
577 +struct ip_set_req_ipmap {
578 +       ip_set_ip_t ip;
579 +};
580 +
581 +unsigned int
582 +mask_to_bits(ip_set_ip_t mask)
583 +{
584 +       unsigned int bits = 32;
585 +       ip_set_ip_t maskaddr;
586 +       
587 +       if (mask == 0xFFFFFFFF)
588 +               return bits;
589 +       
590 +       maskaddr = 0xFFFFFFFE;
591 +       while (--bits >= 0 && maskaddr != mask)
592 +               maskaddr <<= 1;
593 +       
594 +       return bits;
595 +}
596 +
597 +ip_set_ip_t
598 +range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
599 +{
600 +       ip_set_ip_t mask = 0xFFFFFFFE;
601 +       
602 +       *bits = 32;
603 +       while (--(*bits) >= 0 && mask && (to & mask) != from)
604 +               mask <<= 1;
605 +               
606 +       return mask;
607 +}
608 +       
609 +#endif /* __IP_SET_IPMAP_H */
610 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_jhash.h
611 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
612 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_jhash.h     2004-02-09 15:02:00.000000000 +0100
613 @@ -0,0 +1,148 @@
614 +#ifndef _LINUX_IPSET_JHASH_H
615 +#define _LINUX_IPSET_JHASH_H
616 +
617 +/* This is a copy of linux/jhash.h but the types u32/u8 are changed
618 + * to __u32/__u8 so that the header file can be included into
619 + * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
620 + */
621 +
622 +/* jhash.h: Jenkins hash support.
623 + *
624 + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
625 + *
626 + * http://burtleburtle.net/bob/hash/
627 + *
628 + * These are the credits from Bob's sources:
629 + *
630 + * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
631 + * hash(), hash2(), hash3, and mix() are externally useful functions.
632 + * Routines to test the hash are included if SELF_TEST is defined.
633 + * You can use this free for any purpose.  It has no warranty.
634 + *
635 + * Copyright (C) 2003 David S. Miller (davem@redhat.com)
636 + *
637 + * I've modified Bob's hash to be useful in the Linux kernel, and
638 + * any bugs present are surely my fault.  -DaveM
639 + */
640 +
641 +/* NOTE: Arguments are modified. */
642 +#define __jhash_mix(a, b, c) \
643 +{ \
644 +  a -= b; a -= c; a ^= (c>>13); \
645 +  b -= c; b -= a; b ^= (a<<8); \
646 +  c -= a; c -= b; c ^= (b>>13); \
647 +  a -= b; a -= c; a ^= (c>>12);  \
648 +  b -= c; b -= a; b ^= (a<<16); \
649 +  c -= a; c -= b; c ^= (b>>5); \
650 +  a -= b; a -= c; a ^= (c>>3);  \
651 +  b -= c; b -= a; b ^= (a<<10); \
652 +  c -= a; c -= b; c ^= (b>>15); \
653 +}
654 +
655 +/* The golden ration: an arbitrary value */
656 +#define JHASH_GOLDEN_RATIO     0x9e3779b9
657 +
658 +/* The most generic version, hashes an arbitrary sequence
659 + * of bytes.  No alignment or length assumptions are made about
660 + * the input key.
661 + */
662 +static inline __u32 jhash(void *key, __u32 length, __u32 initval)
663 +{
664 +       __u32 a, b, c, len;
665 +       __u8 *k = key;
666 +
667 +       len = length;
668 +       a = b = JHASH_GOLDEN_RATIO;
669 +       c = initval;
670 +
671 +       while (len >= 12) {
672 +               a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
673 +               b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
674 +               c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
675 +
676 +               __jhash_mix(a,b,c);
677 +
678 +               k += 12;
679 +               len -= 12;
680 +       }
681 +
682 +       c += length;
683 +       switch (len) {
684 +       case 11: c += ((__u32)k[10]<<24);
685 +       case 10: c += ((__u32)k[9]<<16);
686 +       case 9 : c += ((__u32)k[8]<<8);
687 +       case 8 : b += ((__u32)k[7]<<24);
688 +       case 7 : b += ((__u32)k[6]<<16);
689 +       case 6 : b += ((__u32)k[5]<<8);
690 +       case 5 : b += k[4];
691 +       case 4 : a += ((__u32)k[3]<<24);
692 +       case 3 : a += ((__u32)k[2]<<16);
693 +       case 2 : a += ((__u32)k[1]<<8);
694 +       case 1 : a += k[0];
695 +       };
696 +
697 +       __jhash_mix(a,b,c);
698 +
699 +       return c;
700 +}
701 +
702 +/* A special optimized version that handles 1 or more of __u32s.
703 + * The length parameter here is the number of __u32s in the key.
704 + */
705 +static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
706 +{
707 +       __u32 a, b, c, len;
708 +
709 +       a = b = JHASH_GOLDEN_RATIO;
710 +       c = initval;
711 +       len = length;
712 +
713 +       while (len >= 3) {
714 +               a += k[0];
715 +               b += k[1];
716 +               c += k[2];
717 +               __jhash_mix(a, b, c);
718 +               k += 3; len -= 3;
719 +       }
720 +
721 +       c += length * 4;
722 +
723 +       switch (len) {
724 +       case 2 : b += k[1];
725 +       case 1 : a += k[0];
726 +       };
727 +
728 +       __jhash_mix(a,b,c);
729 +
730 +       return c;
731 +}
732 +
733 +
734 +/* A special ultra-optimized versions that knows they are hashing exactly
735 + * 3, 2 or 1 word(s).
736 + *
737 + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
738 + *       done at the end is not done here.
739 + */
740 +static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
741 +{
742 +       a += JHASH_GOLDEN_RATIO;
743 +       b += JHASH_GOLDEN_RATIO;
744 +       c += initval;
745 +
746 +       __jhash_mix(a, b, c);
747 +
748 +       return c;
749 +}
750 +
751 +static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
752 +{
753 +       return jhash_3words(a, b, 0, initval);
754 +}
755 +
756 +static inline __u32 jhash_1word(__u32 a, __u32 initval)
757 +{
758 +       return jhash_3words(a, 0, 0, initval);
759 +}
760 +
761 +#endif /* _LINUX_IPSET_JHASH_H */
762 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_macipmap.h
763 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_macipmap.h      1970-01-01 01:00:00.000000000 +0100
764 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_macipmap.h  2004-02-09 15:02:00.000000000 +0100
765 @@ -0,0 +1,41 @@
766 +#ifndef __IP_SET_MACIPMAP_H
767 +#define __IP_SET_MACIPMAP_H
768 +
769 +#include <linux/netfilter_ipv4/ip_set.h>
770 +
771 +#define SETTYPE_NAME "macipmap"
772 +#define MAX_RANGE 0x0000FFFF
773 +
774 +/* general flags */
775 +#define IPSET_MACIP_MATCHUNSET 1
776 +
777 +/* per ip flags */
778 +#define IPSET_MACIP_ISSET      1
779 +
780 +struct ip_set_macipmap {
781 +       struct ip_set_private **childsets;      /* child sets */
782 +
783 +       /* Type speficic members: */
784 +       ip_set_ip_t first_ip;           /* host byte order, included in range */
785 +       ip_set_ip_t last_ip;            /* host byte order, included in range */
786 +       void *members;                  /* the macipmap proper */
787 +       u_int32_t flags;
788 +};
789 +
790 +struct ip_set_req_macipmap_create {
791 +       ip_set_ip_t from;
792 +       ip_set_ip_t to;
793 +       u_int32_t flags;
794 +};
795 +
796 +struct ip_set_req_macipmap {
797 +       ip_set_ip_t ip;
798 +       unsigned char ethernet[ETH_ALEN];
799 +};
800 +
801 +struct ip_set_macip {
802 +       unsigned short flags;
803 +       unsigned char ethernet[ETH_ALEN];
804 +};
805 +
806 +#endif /* __IP_SET_MACIPMAP_H */
807 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_portmap.h
808 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_portmap.h       1970-01-01 01:00:00.000000000 +0100
809 +++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_portmap.h   2004-02-09 15:02:00.000000000 +0100
810 @@ -0,0 +1,28 @@
811 +#ifndef __IP_SET_PORTMAP_H
812 +#define __IP_SET_PORTMAP_H
813 +
814 +#include <linux/netfilter_ipv4/ip_set.h>
815 +
816 +#define SETTYPE_NAME   "portmap"
817 +#define MAX_RANGE      0x0000FFFF
818 +#define INVALID_PORT   (MAX_RANGE + 1)
819 +
820 +struct ip_set_portmap {
821 +       struct ip_set_private **childsets;      /* child sets */
822 +
823 +       /* Type speficic members: */
824 +       ip_set_ip_t first_port;         /* host byte order, included in range */
825 +       ip_set_ip_t last_port;          /* host byte order, included in range */
826 +       void *members;                  /* the portmap proper */
827 +};
828 +
829 +struct ip_set_req_portmap_create {
830 +       ip_set_ip_t from;
831 +       ip_set_ip_t to;
832 +};
833 +
834 +struct ip_set_req_portmap {
835 +       ip_set_ip_t port;
836 +};
837 +
838 +#endif /* __IP_SET_PORTMAP_H */
839 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_NETLINK.h
840 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h  1970-01-01 01:00:00.000000000 +0100
841 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_NETLINK.h      2004-02-19 08:47:24.269530314 +0100
842 @@ -0,0 +1,27 @@
843 +#ifndef _IPT_FWMON_H
844 +#define _IPT_FWMON_H
845 +
846 +/* Bitmask macros */
847 +#define MASK(x,y) (x & y)
848 +#define MASK_SET(x,y) x |= y
849 +#define MASK_UNSET(x,y) x &= ~y
850 +
851 +#define USE_MARK       0x00000001
852 +#define USE_DROP       0x00000002
853 +#define USE_SIZE       0x00000004
854 +
855 +struct ipt_nldata
856 +{      
857 +       unsigned int flags;
858 +       unsigned int mark;
859 +       unsigned int size;
860 +};
861 +
862 +/* Old header */
863 +struct netlink_t {
864 +       unsigned int len;
865 +       unsigned int mark;
866 +       char iface[IFNAMSIZ];
867 +};
868 +
869 +#endif /*_IPT_FWMON_H*/
870 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_TTL.h
871 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_TTL.h      1970-01-01 01:00:00.000000000 +0100
872 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_TTL.h  2004-02-19 08:47:25.605208582 +0100
873 @@ -0,0 +1,21 @@
874 +/* TTL modification module for IP tables
875 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
876 +
877 +#ifndef _IPT_TTL_H
878 +#define _IPT_TTL_H
879 +
880 +enum {
881 +       IPT_TTL_SET = 0,
882 +       IPT_TTL_INC,
883 +       IPT_TTL_DEC
884 +};
885 +
886 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
887 +
888 +struct ipt_TTL_info {
889 +       u_int8_t        mode;
890 +       u_int8_t        ttl;
891 +};
892 +
893 +
894 +#endif
895 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_connlimit.h
896 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_connlimit.h        1970-01-01 01:00:00.000000000 +0100
897 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_connlimit.h    2004-02-19 08:47:26.593970414 +0100
898 @@ -0,0 +1,12 @@
899 +#ifndef _IPT_CONNLIMIT_H
900 +#define _IPT_CONNLIMIT_H
901 +
902 +struct ipt_connlimit_data;
903 +
904 +struct ipt_connlimit_info {
905 +       int limit;
906 +       int inverse;
907 +       u_int32_t mask;
908 +       struct ipt_connlimit_data *data;
909 +};
910 +#endif /* _IPT_CONNLIMIT_H */
911 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_dstlimit.h
912 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
913 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_dstlimit.h     2004-02-19 08:47:27.235815809 +0100
914 @@ -0,0 +1,39 @@
915 +#ifndef _IPT_DSTLIMIT_H
916 +#define _IPT_DSTLIMIT_H
917 +
918 +/* timings are in milliseconds. */
919 +#define IPT_DSTLIMIT_SCALE 10000
920 +/* 1/10,000 sec period => max of 10,000/sec.  Min rate is then 429490
921 +   seconds, or one every 59 hours. */
922 +
923 +/* details of this structure hidden by the implementation */
924 +struct ipt_dstlimit_htable;
925 +
926 +#define IPT_DSTLIMIT_HASH_DIP  0x0001
927 +#define IPT_DSTLIMIT_HASH_DPT  0x0002
928 +#define IPT_DSTLIMIT_HASH_SIP  0x0004
929 +
930 +struct dstlimit_cfg {
931 +       u_int32_t mode;   /* bitmask of IPT_DSTLIMIT_HASH_* */
932 +       u_int32_t avg;    /* Average secs between packets * scale */
933 +       u_int32_t burst;  /* Period multiplier for upper limit. */
934 +
935 +       /* user specified */
936 +       u_int32_t size;         /* how many buckets */
937 +       u_int32_t max;          /* max number of entries */
938 +       u_int32_t gc_interval;  /* gc interval */
939 +       u_int32_t expire;       /* when do entries expire? */
940 +};
941 +
942 +struct ipt_dstlimit_info {
943 +       char name [IFNAMSIZ];           /* name */
944 +       struct dstlimit_cfg cfg;
945 +       struct ipt_dstlimit_htable *hinfo;
946 +
947 +       /* Used internally by the kernel */
948 +       union {
949 +               void *ptr;
950 +               struct ipt_dstlimit_info *master;
951 +       } u;
952 +};
953 +#endif /*_IPT_DSTLIMIT_H*/
954 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_fuzzy.h
955 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h    1970-01-01 01:00:00.000000000 +0100
956 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_fuzzy.h        2004-02-19 08:47:27.855666503 +0100
957 @@ -0,0 +1,21 @@
958 +#ifndef _IPT_FUZZY_H
959 +#define _IPT_FUZZY_H
960 +
961 +#include <linux/param.h>
962 +#include <linux/types.h>
963 +
964 +#define MAXFUZZYRATE 10000000
965 +#define MINFUZZYRATE 3
966 +
967 +struct ipt_fuzzy_info {
968 +       u_int32_t minimum_rate;
969 +       u_int32_t maximum_rate;
970 +       u_int32_t packets_total;
971 +       u_int32_t bytes_total;
972 +       u_int32_t previous_time;
973 +       u_int32_t present_time;
974 +       u_int32_t mean_rate;
975 +       u_int8_t acceptance_rate;
976 +};
977 +
978 +#endif /*_IPT_FUZZY_H*/
979 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_ipv4options.h
980 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h      1970-01-01 01:00:00.000000000 +0100
981 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_ipv4options.h  2004-02-19 08:47:28.441525384 +0100
982 @@ -0,0 +1,21 @@
983 +#ifndef __ipt_ipv4options_h_included__
984 +#define __ipt_ipv4options_h_included__
985 +
986 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
987 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
988 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
989 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
990 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
991 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
992 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
993 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
994 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
995 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
996 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
997 +
998 +struct ipt_ipv4options_info {
999 +       u_int16_t options;
1000 +};
1001 +
1002 +
1003 +#endif /* __ipt_ipv4options_h_included__ */
1004 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_mport.h
1005 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_mport.h    1970-01-01 01:00:00.000000000 +0100
1006 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_mport.h        2004-02-19 08:47:29.017386674 +0100
1007 @@ -0,0 +1,24 @@
1008 +#ifndef _IPT_MPORT_H
1009 +#define _IPT_MPORT_H
1010 +#include <linux/netfilter_ipv4/ip_tables.h>
1011 +
1012 +#define IPT_MPORT_SOURCE (1<<0)
1013 +#define IPT_MPORT_DESTINATION (1<<1)
1014 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1015 +
1016 +#define IPT_MULTI_PORTS        15
1017 +
1018 +/* Must fit inside union ipt_matchinfo: 32 bytes */
1019 +/* every entry in ports[] except for the last one has one bit in pflags
1020 + * associated with it. If this bit is set, the port is the first port of
1021 + * a portrange, with the next entry being the last.
1022 + * End of list is marked with pflags bit set and port=65535.
1023 + * If 14 ports are used (last one does not have a pflag), the last port
1024 + * is repeated to fill the last entry in ports[] */
1025 +struct ipt_mport
1026 +{
1027 +       u_int8_t flags:2;                       /* Type of comparison */
1028 +       u_int16_t pflags:14;                    /* Port flags */
1029 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
1030 +};
1031 +#endif /*_IPT_MPORT_H*/
1032 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_nth.h
1033 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_nth.h      1970-01-01 01:00:00.000000000 +0100
1034 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_nth.h  2004-02-19 08:47:29.579251335 +0100
1035 @@ -0,0 +1,19 @@
1036 +#ifndef _IPT_NTH_H
1037 +#define _IPT_NTH_H
1038 +
1039 +#include <linux/param.h>
1040 +#include <linux/types.h>
1041 +
1042 +#ifndef IPT_NTH_NUM_COUNTERS
1043 +#define IPT_NTH_NUM_COUNTERS 16
1044 +#endif
1045 +
1046 +struct ipt_nth_info {
1047 +       u_int8_t every;
1048 +       u_int8_t not;
1049 +       u_int8_t startat;
1050 +       u_int8_t counter;
1051 +       u_int8_t packet;
1052 +};
1053 +
1054 +#endif /*_IPT_NTH_H*/
1055 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_osf.h
1056 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_osf.h      1970-01-01 01:00:00.000000000 +0100
1057 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_osf.h  2004-02-19 08:47:30.115122257 +0100
1058 @@ -0,0 +1,130 @@
1059 +/*
1060 + * ipt_osf.h
1061 + *
1062 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1063 + *
1064 + *
1065 + * This program is free software; you can redistribute it and/or modify
1066 + * it under the terms of the GNU General Public License as published by
1067 + * the Free Software Foundation; either version 2 of the License, or
1068 + * (at your option) any later version.
1069 + *
1070 + * This program is distributed in the hope that it will be useful,
1071 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1072 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1073 + * GNU General Public License for more details.
1074 + *
1075 + * You should have received a copy of the GNU General Public License
1076 + * along with this program; if not, write to the Free Software
1077 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1078 + */
1079 +
1080 +#ifndef _IPT_OSF_H
1081 +#define _IPT_OSF_H
1082 +
1083 +#define MAXGENRELEN            32
1084 +#define MAXDETLEN              64
1085 +
1086 +#define IPT_OSF_GENRE          1
1087 +#define IPT_OSF_SMART          2
1088 +#define IPT_OSF_LOG            4
1089 +
1090 +#define IPT_OSF_LOGLEVEL_ALL           0
1091 +#define IPT_OSF_LOGLEVEL_FIRST 1
1092 +
1093 +#include <linux/list.h>
1094 +
1095 +struct ipt_osf_info
1096 +{
1097 +       char                    genre[MAXGENRELEN];
1098 +       int                     len;
1099 +       unsigned long           flags;
1100 +       int                     loglevel;
1101 +       int                     invert; /* UNSUPPORTED */
1102 +};
1103 +
1104 +struct osf_wc
1105 +{
1106 +       char                    wc;
1107 +       unsigned long           val;
1108 +};
1109 +
1110 +/* This struct represents IANA options
1111 + * http://www.iana.org/assignments/tcp-parameters
1112 + */
1113 +struct osf_opt
1114 +{
1115 +       unsigned char           kind;
1116 +       unsigned char           length;
1117 +       struct osf_wc           wc;
1118 +};
1119 +
1120 +#ifdef __KERNEL__
1121 +
1122 +struct osf_finger
1123 +{
1124 +       struct list_head        flist;
1125 +       struct osf_wc           wss;
1126 +       unsigned char           ttl;
1127 +       unsigned char           df;
1128 +       unsigned long           ss;
1129 +       char                    genre[MAXGENRELEN];
1130 +       char                    version[MAXGENRELEN], subtype[MAXGENRELEN];
1131 +       
1132 +       /* Not needed, but for consistency with original table from Michal Zalewski */
1133 +       char                    details[MAXDETLEN]; 
1134 +
1135 +       int                     opt_num;
1136 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1137 +
1138 +};
1139 +
1140 +/* Defines for IANA option kinds */
1141 +
1142 +#define OSFOPT_EOL             0       /* End of options */
1143 +#define OSFOPT_NOP             1       /* NOP */
1144 +#define OSFOPT_MSS             2       /* Maximum segment size */
1145 +#define OSFOPT_WSO             3       /* Window scale option */
1146 +#define OSFOPT_SACKP           4       /* SACK permitted */
1147 +#define OSFOPT_SACK            5       /* SACK */
1148 +#define OSFOPT_ECHO            6       
1149 +#define OSFOPT_ECHOREPLY       7
1150 +#define OSFOPT_TS              8       /* Timestamp option */
1151 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
1152 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
1153 +/* Others are not used in current OSF */
1154 +
1155 +static struct osf_opt IANA_opts[] = 
1156 +{
1157 +       {0, 1,},
1158 +       {1, 1,},
1159 +       {2, 4,},
1160 +       {3, 3,},
1161 +       {4, 2,},
1162 +       {5, 1 ,}, /* SACK length is not defined */
1163 +       {6, 6,},
1164 +       {7, 6,},
1165 +       {8, 10,},
1166 +       {9, 2,},
1167 +       {10, 3,},
1168 +       {11, 1,}, /* CC: Suppose 1 */
1169 +       {12, 1,}, /* the same */
1170 +       {13, 1,}, /* and here too */
1171 +       {14, 3,},
1172 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1173 +       {16, 1,},
1174 +       {17, 1,},
1175 +       {18, 3,},
1176 +       {19, 18,},
1177 +       {20, 1,},
1178 +       {21, 1,},
1179 +       {22, 1,},
1180 +       {23, 1,},
1181 +       {24, 1,},
1182 +       {25, 1,},
1183 +       {26, 1,},
1184 +};
1185 +
1186 +#endif /* __KERNEL__ */
1187 +
1188 +#endif /* _IPT_OSF_H */
1189 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_pool.h
1190 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_pool.h     1970-01-01 01:00:00.000000000 +0100
1191 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_pool.h 2004-02-19 08:47:30.712978249 +0100
1192 @@ -0,0 +1,25 @@
1193 +#ifndef _IPT_POOL_H
1194 +#define _IPT_POOL_H
1195 +
1196 +#include <linux/netfilter_ipv4/ip_pool.h>
1197 +
1198 +#define IPT_POOL_INV_SRC       0x00000001
1199 +#define IPT_POOL_INV_DST       0x00000002
1200 +#define IPT_POOL_DEL_SRC       0x00000004
1201 +#define IPT_POOL_DEL_DST       0x00000008
1202 +#define IPT_POOL_INV_MOD_SRC   0x00000010
1203 +#define IPT_POOL_INV_MOD_DST   0x00000020
1204 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
1205 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
1206 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
1207 +#define IPT_POOL_MOD_DST_DROP  0x00000200
1208 +
1209 +/* match info */
1210 +struct ipt_pool_info
1211 +{
1212 +       ip_pool_t src;
1213 +       ip_pool_t dst;
1214 +       unsigned flags;
1215 +};
1216 +
1217 +#endif /*_IPT_POOL_H*/
1218 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_psd.h
1219 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_psd.h      1970-01-01 01:00:00.000000000 +0100
1220 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_psd.h  2004-02-19 08:47:31.249848931 +0100
1221 @@ -0,0 +1,40 @@
1222 +#ifndef _IPT_PSD_H
1223 +#define _IPT_PSD_H
1224 +
1225 +#include <linux/param.h>
1226 +#include <linux/types.h>
1227 +
1228 +/*
1229 + * High port numbers have a lower weight to reduce the frequency of false
1230 + * positives, such as from passive mode FTP transfers.
1231 + */
1232 +#define PORT_WEIGHT_PRIV               3
1233 +#define PORT_WEIGHT_HIGH               1
1234 +
1235 +/*
1236 + * Port scan detection thresholds: at least COUNT ports need to be scanned
1237 + * from the same source, with no longer than DELAY ticks between ports.
1238 + */
1239 +#define SCAN_MIN_COUNT                 7
1240 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1241 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
1242 +#define SCAN_DELAY_THRESHOLD           (HZ * 3)
1243 +
1244 +/*
1245 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
1246 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1247 + * HASH_MAX source addresses per the same hash value.
1248 + */
1249 +#define LIST_SIZE                      0x100
1250 +#define HASH_LOG                       9
1251 +#define HASH_SIZE                      (1 << HASH_LOG)
1252 +#define HASH_MAX                       0x10
1253 +
1254 +struct ipt_psd_info {
1255 +       unsigned int weight_threshold;
1256 +       unsigned int delay_threshold;
1257 +       unsigned short lo_ports_weight;
1258 +       unsigned short hi_ports_weight;
1259 +};
1260 +
1261 +#endif /*_IPT_PSD_H*/
1262 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_quota.h
1263 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_quota.h    1970-01-01 01:00:00.000000000 +0100
1264 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_quota.h        2004-02-19 08:47:31.780721057 +0100
1265 @@ -0,0 +1,11 @@
1266 +#ifndef _IPT_QUOTA_H
1267 +#define _IPT_QUOTA_H
1268 +
1269 +/* print debug info in both kernel/netfilter module & iptable library */
1270 +//#define DEBUG_IPT_QUOTA
1271 +
1272 +struct ipt_quota_info {
1273 +        u_int64_t quota;
1274 +};
1275 +
1276 +#endif /*_IPT_QUOTA_H*/
1277 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_random.h
1278 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_random.h   1970-01-01 01:00:00.000000000 +0100
1279 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_random.h       2004-02-19 08:47:32.335587404 +0100
1280 @@ -0,0 +1,11 @@
1281 +#ifndef _IPT_RAND_H
1282 +#define _IPT_RAND_H
1283 +
1284 +#include <linux/param.h>
1285 +#include <linux/types.h>
1286 +
1287 +struct ipt_rand_info {
1288 +       u_int8_t average;
1289 +};
1290 +
1291 +#endif /*_IPT_RAND_H*/
1292 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_realm.h
1293 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_realm.h    1970-01-01 01:00:00.000000000 +0100
1294 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_realm.h        2004-02-19 08:47:33.450318894 +0100
1295 @@ -0,0 +1,9 @@
1296 +#ifndef _IPT_REALM_H
1297 +#define _IPT_REALM_H
1298 +
1299 +struct ipt_realm_info {
1300 +       u_int32_t id;
1301 +       u_int32_t mask;
1302 +       u_int8_t invert;
1303 +};
1304 +#endif /*_IPT_REALM_H*/
1305 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_set.h
1306 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_set.h      1970-01-01 01:00:00.000000000 +0100
1307 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_set.h  2004-02-09 15:02:00.000000000 +0100
1308 @@ -0,0 +1,22 @@
1309 +#ifndef _IPT_SET_H
1310 +#define _IPT_SET_H
1311 +
1312 +#include <linux/netfilter_ipv4/ip_set.h>
1313 +
1314 +struct ipt_set_info {
1315 +       int16_t id;
1316 +       u_int8_t set_level, ip_level;
1317 +       u_int32_t flags[IP_SET_LEVELS];
1318 +};
1319 +
1320 +/* match info */
1321 +struct ipt_set_info_match {
1322 +       struct ipt_set_info match;
1323 +};
1324 +
1325 +struct ipt_set_info_target {
1326 +       struct ipt_set_info add_set;
1327 +       struct ipt_set_info del_set;
1328 +};
1329 +
1330 +#endif /*_IPT_SET_H*/
1331 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_time.h
1332 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_time.h     1970-01-01 01:00:00.000000000 +0100
1333 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_time.h 2004-02-19 08:47:33.998186927 +0100
1334 @@ -0,0 +1,13 @@
1335 +#ifndef __ipt_time_h_included__
1336 +#define __ipt_time_h_included__
1337 +
1338 +
1339 +struct ipt_time_info {
1340 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
1341 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
1342 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
1343 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
1344 +};
1345 +
1346 +
1347 +#endif /* __ipt_time_h_included__ */
1348 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_u32.h
1349 --- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_u32.h      1970-01-01 01:00:00.000000000 +0100
1350 +++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_u32.h  2004-02-19 08:47:34.549054238 +0100
1351 @@ -0,0 +1,40 @@
1352 +#ifndef _IPT_U32_H
1353 +#define _IPT_U32_H
1354 +#include <linux/netfilter_ipv4/ip_tables.h>
1355 +
1356 +enum ipt_u32_ops
1357 +{
1358 +       IPT_U32_AND,
1359 +       IPT_U32_LEFTSH,
1360 +       IPT_U32_RIGHTSH,
1361 +       IPT_U32_AT
1362 +};
1363 +
1364 +struct ipt_u32_location_element
1365 +{
1366 +       u_int32_t number;
1367 +       u_int8_t nextop;
1368 +};
1369 +struct ipt_u32_value_element
1370 +{
1371 +       u_int32_t min;
1372 +       u_int32_t max;
1373 +};
1374 +/* *** any way to allow for an arbitrary number of elements?
1375 +   for now I settle for a limit of 10 of each */
1376 +#define U32MAXSIZE 10
1377 +struct ipt_u32_test
1378 +{
1379 +       u_int8_t nnums;
1380 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
1381 +       u_int8_t nvalues;
1382 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
1383 +};
1384 +
1385 +struct ipt_u32
1386 +{
1387 +       u_int8_t ntests;
1388 +       struct ipt_u32_test tests[U32MAXSIZE+1];
1389 +};
1390 +
1391 +#endif /*_IPT_U32_H*/
1392 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_HL.h
1393 --- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_HL.h      1970-01-01 01:00:00.000000000 +0100
1394 +++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_HL.h  2004-02-19 09:09:04.595401585 +0100
1395 @@ -0,0 +1,22 @@
1396 +/* Hop Limit modification module for ip6tables
1397 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1398 + * Based on HW's TTL module */
1399 +
1400 +#ifndef _IP6T_HL_H
1401 +#define _IP6T_HL_H
1402 +
1403 +enum {
1404 +       IP6T_HL_SET = 0,
1405 +       IP6T_HL_INC,
1406 +       IP6T_HL_DEC
1407 +};
1408 +
1409 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
1410 +
1411 +struct ip6t_HL_info {
1412 +       u_int8_t        mode;
1413 +       u_int8_t        hop_limit;
1414 +};
1415 +
1416 +
1417 +#endif
1418 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1419 --- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h  2004-02-18 04:57:12.000000000 +0100
1420 +++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_REJECT.h      2004-02-19 08:47:25.031346811 +0100
1421 @@ -2,15 +2,17 @@
1422  #define _IP6T_REJECT_H
1423  
1424  enum ip6t_reject_with {
1425 -       IP6T_ICMP_NET_UNREACHABLE,
1426 -       IP6T_ICMP_HOST_UNREACHABLE,
1427 -       IP6T_ICMP_PROT_UNREACHABLE,
1428 -       IP6T_ICMP_PORT_UNREACHABLE,
1429 -       IP6T_ICMP_ECHOREPLY
1430 +       IP6T_ICMP6_NO_ROUTE,
1431 +       IP6T_ICMP6_ADM_PROHIBITED,
1432 +       IP6T_ICMP6_NOT_NEIGHBOUR,
1433 +       IP6T_ICMP6_ADDR_UNREACH,
1434 +       IP6T_ICMP6_PORT_UNREACH,
1435 +       IP6T_ICMP6_ECHOREPLY,
1436 +       IP6T_TCP_RESET
1437  };
1438  
1439  struct ip6t_reject_info {
1440         enum ip6t_reject_with with;      /* reject type */
1441  };
1442  
1443 -#endif /*_IPT_REJECT_H*/
1444 +#endif /*_IP6T_REJECT_H*/
1445 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1446 --- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h   1970-01-01 01:00:00.000000000 +0100
1447 +++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_fuzzy.h       2004-02-19 08:47:27.855666503 +0100
1448 @@ -0,0 +1,21 @@
1449 +#ifndef _IP6T_FUZZY_H
1450 +#define _IP6T_FUZZY_H
1451 +
1452 +#include <linux/param.h>
1453 +#include <linux/types.h>
1454 +
1455 +#define MAXFUZZYRATE 10000000
1456 +#define MINFUZZYRATE 3
1457 +
1458 +struct ip6t_fuzzy_info {
1459 +       u_int32_t minimum_rate;
1460 +       u_int32_t maximum_rate;
1461 +       u_int32_t packets_total;
1462 +       u_int32_t bytes_total;
1463 +       u_int32_t previous_time;
1464 +       u_int32_t present_time;
1465 +       u_int32_t mean_rate;
1466 +       u_int8_t acceptance_rate;
1467 +};
1468 +
1469 +#endif /*_IP6T_FUZZY_H*/
1470 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_nth.h
1471 --- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_nth.h     1970-01-01 01:00:00.000000000 +0100
1472 +++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_nth.h 2004-02-19 08:47:29.579251335 +0100
1473 @@ -0,0 +1,19 @@
1474 +#ifndef _IP6T_NTH_H
1475 +#define _IP6T_NTH_H
1476 +
1477 +#include <linux/param.h>
1478 +#include <linux/types.h>
1479 +
1480 +#ifndef IP6T_NTH_NUM_COUNTERS
1481 +#define IP6T_NTH_NUM_COUNTERS 16
1482 +#endif
1483 +
1484 +struct ip6t_nth_info {
1485 +       u_int8_t every;
1486 +       u_int8_t not;
1487 +       u_int8_t startat;
1488 +       u_int8_t counter;
1489 +       u_int8_t packet;
1490 +};
1491 +
1492 +#endif /*_IP6T_NTH_H*/
1493 diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_random.h
1494 --- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_random.h  1970-01-01 01:00:00.000000000 +0100
1495 +++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_random.h      2004-02-19 08:47:32.336587163 +0100
1496 @@ -0,0 +1,11 @@
1497 +#ifndef _IP6T_RAND_H
1498 +#define _IP6T_RAND_H
1499 +
1500 +#include <linux/param.h>
1501 +#include <linux/types.h>
1502 +
1503 +struct ip6t_rand_info {
1504 +       u_int8_t average;
1505 +};
1506 +
1507 +#endif /*_IP6T_RAND_H*/
1508 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/Kconfig linux-2.6.3/net/ipv4/netfilter/Kconfig
1509 --- linux-2.6.3.org/net/ipv4/netfilter/Kconfig  2004-02-18 04:59:13.000000000 +0100
1510 +++ linux-2.6.3/net/ipv4/netfilter/Kconfig      2004-02-19 09:06:18.111476624 +0100
1511 @@ -579,5 +579,414 @@
1512  
1513           To compile it as a module, choose M here.  If unsure, say N.
1514  
1515 +config IP_NF_TARGET_IPV4OPTSSTRIP
1516 +       tristate  'IPV4OPTSSTRIP target support'
1517 +       depends on IP_NF_MANGLE
1518 +         help
1519 +         This option adds CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP, which supplies a target
1520 +         module that will allow you to strip all the IP options from a packet.
1521 +         
1522 +         The target doesn't take any option, and therefore is extremly easy to use :
1523 +         
1524 +         # iptables -t mangle -A PREROUTING -j IPV4OPTSSTRIP
1525 +         # iptables -t mangle --list -n
1526 +         Chain PREROUTING (policy ACCEPT)
1527 +         target     prot opt source               destination
1528 +         IPV4OPTSSTRIP  all  --  0.0.0.0/0            0.0.0.0/0
1529 +         
1530 +         Chain OUTPUT (policy ACCEPT)
1531 +         target     prot opt source               destination
1532 +
1533 +config IP_NF_TARGET_NETLINK
1534 +       tristate  'NETLINK target support'
1535 +       depends on IP_NF_FILTER
1536 +         help
1537 +         CONFIG_IP_NF_TARGET_NETLINK adds a NETLINK target that sends dropped packets to
1538 +         userspace via a netlink socket.  Apps such as fwmon
1539 +         (http://firestorm.geek-ware.co.uk) can then recieve and dislpay these packets.
1540 +         This option is basically a re-implementation of the ipchains -o option.
1541 +
1542 +config IP_NF_TARGET_TTL
1543 +       tristate  'TTL target support'
1544 +       depends on IP_NF_MANGLE
1545 +         help
1546 +         This adds an iptables TTL manipulation target, which enables the user
1547 +         to set the TTL value of an IP packet or to increment / decrement it 
1548 +         by a given value.
1549 +
1550 +config IP_NF_MATCH_CONNLIMIT
1551 +       tristate  'Connections/IP limit match support'
1552 +       depends on IP_NF_IPTABLES
1553 +         help
1554 +         This adds an iptables match which allows you to restrict the
1555 +         number of parallel TCP connections to a server per client IP address
1556 +         (or address block).
1557 +         
1558 +         Examples:
1559 +         
1560 +         # allow 2 telnet connections per client host
1561 +         iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
1562 +         
1563 +         # you can also match the other way around:
1564 +         iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
1565 +         
1566 +         # limit the nr of parallel http requests to 16 per class C sized
1567 +         # network (24 bit netmask)
1568 +         iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 \
1569 +               --connlimit-mask 24 -j REJECT
1570 +
1571 +config IP_NF_MATCH_DSTLIMIT
1572 +       tristate  'dstlimit match support'
1573 +       depends on IP_NF_IPTABLES
1574 +         help
1575 +         
1576 +         This patch adds a new match called 'dstlimit'.  
1577 +         The idea is to have something like 'limit', but either per 
1578 +         destination-ip or per (destip,destport) tuple.
1579 +         
1580 +         It gives you the ability to say 
1581 +               '1000 packets per second for every host in 192.168.0.0/16'
1582 +               '100 packets per second for every service of 192.168.1.1'
1583 +         
1584 +         Parameters are:
1585 +               --dstlimit <rate>
1586 +                       A rate just like the limit match
1587 +               --dstlimit-burst <num>
1588 +                       Burst value, just like limit match
1589 +               --dstlimit-mode destip | destip-destport
1590 +                       Limit per IP or per port
1591 +               --dstlimit-name foo
1592 +                       The name for the /proc/net/ipt_dstlimit/foo entry
1593 +               --dstlimit-htable-size <num>
1594 +                       The number of buckets of the hash table
1595 +               --dstlimit-htable-max <num>
1596 +                       Maximum entries in the hash
1597 +               --dstlimit-htable-expire <num>
1598 +                       After how many miliseconds do hash entries expire
1599 +               --dstlimit-htable-gcinterval <num>
1600 +                       How many miliseconds between garbage collection intervals
1601 +         
1602 +
1603 +config IP_NF_MATCH_FUZZY
1604 +       tristate  'fuzzy match support'
1605 +       depends on IP_NF_IPTABLES
1606 +         help
1607 +         This option adds a `fuzzy' match which allows you to match packets according to
1608 +         a dynamic profile implemented by means of a simple Fuzzy Logic Controller (FLC)
1609 +
1610 +config IP_NF_MATCH_IPV4OPTIONS
1611 +       tristate  'IPV4OPTIONS match support'
1612 +       depends on IP_NF_IPTABLES
1613 +         help
1614 +         This option adds an iptables 'ipv4options' match, which allows you to
1615 +         match on IPv4 header options like source routing, record route, timestamp and
1616 +         router-alert.
1617 +         
1618 +         Suppported options are:
1619 +         --ssrr
1620 +           To match packets with the flag strict source routing.
1621 +         --lsrr
1622 +           To match packets with the flag loose source routing.
1623 +         --no-srr
1624 +           To match packets with no flag for source routing.
1625 +         [!] --rr
1626 +           To match packets with the RR flag.
1627 +         [!] --ts
1628 +           To match packets with the TS flag.
1629 +         [!] --ra
1630 +           To match packets with the router-alert option.
1631 +         [!] --any-opt
1632 +           To match a packet with at least one IP option, or no IP option
1633 +           at all if ! is chosen.
1634 +         
1635 +         Example:
1636 +           $ iptables -A input -m ipv4options --rr -j DROP
1637 +           will drop packets with the record-route flag.
1638 +         
1639 +           $ iptables -A input -m ipv4options --ts -j DROP
1640 +           will drop packets with the timestamp flag.
1641 +
1642 +config IP_NF_MATCH_MPORT
1643 +       tristate  'Multiple port with ranges match support'
1644 +       depends on IP_NF_IPTABLES
1645 +         help
1646 +         This module is an enhanced multiport match. It has support for byte
1647 +         ranges as well as for single ports.
1648 +         Up to 15 ports are allowed. Note that a portrange uses up 2 port values.
1649 +         
1650 +         Examples:
1651 +         # iptables -A FORWARD -p tcp -m mport --ports 23:42,65
1652 +
1653 +config IP_NF_MATCH_NTH
1654 +       tristate  'Nth match support'
1655 +       depends on IP_NF_IPTABLES
1656 +         help
1657 +         This option adds an iptables `Nth' match, which allows you to match every Nth
1658 +         packet encountered.  By default there are 16 different counters that can be
1659 +         used.
1660 +         
1661 +         This match functions in one of two ways
1662 +         1) Match ever Nth packet, and only the Nth packet.
1663 +            example:
1664 +             iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
1665 +            This rule will drop every 10th packet.
1666 +         2) Unique rule for every packet.  This is an easy and quick
1667 +            method to produce load-balancing for both inbound and outbound.
1668 +            example:
1669 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1670 +                      --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
1671 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1672 +                      --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
1673 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1674 +                      --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
1675 +            This example evenly splits connections between the three SNAT
1676 +            addresses.
1677 +         
1678 +            By using the mangle table and iproute2, you can setup complex
1679 +            load-balanced routing.  There's lot of other uses.  Be creative!
1680 +         
1681 +         Suppported options are:
1682 +            --every     Nth         Match every Nth packet
1683 +           [--counter]  num         Use counter 0-15 (default:0)
1684 +           [--start]    num         Initialize the counter at the number 'num'
1685 +                                    instead of 0. Must be between 0 and Nth-1
1686 +           [--packet]   num         Match on 'num' packet. Must be between 0
1687 +                                    and Nth-1.
1688 +                                    If --packet is used for a counter than
1689 +                                    there must be Nth number of --packet
1690 +                                    rules, covering all values between 0 and
1691 +                                    Nth-1 inclusively.
1692 +
1693 +config IP_NF_MATCH_OSF
1694 +       tristate  'OSF match support'
1695 +       depends on IP_NF_IPTABLES
1696 +         help
1697 +         The idea of passive OS fingerprint matching exists for quite a long time,
1698 +         but was created as extension fo OpenBSD pf only some weeks ago.
1699 +         Original idea was lurked in some OpenBSD mailing list (thanks
1700 +         grange@open...) and than adopted for Linux netfilter in form of this code.
1701 +         
1702 +         Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
1703 +         his excellent p0f and than changed a bit for more convenience.
1704 +         
1705 +         This module compares some data(WS, MSS, options and it's order, ttl,
1706 +         df and others) from first SYN packet (actually from packets with SYN
1707 +         bit set) with hardcoded in fingers[] table ones.
1708 +         
1709 +         Example: (Of course this only an example, do not get inspired by this)
1710 +         
1711 +         # iptables -N LINUX
1712 +         # iptables -A LINUX -j LOG --log-prefix "Linux"
1713 +         
1714 +         # iptables -A INPUT -p tcp -m osf --genre Linux -j LINUX
1715 +         # iptables -A INPUT -p tcp -m osf --genre FreeBSD -j REJECT
1716 +         
1717 +         NOTE: -p tcp is obviously required as it is a TCP match.
1718 +         
1719 +         OSF also has:
1720 +         --log 1/0. 
1721 +               If present, OSF will log determined genres even if they don't match
1722 +               desired one.    
1723 +               0 - log all determined entries, 
1724 +               1 - only first one.
1725 +               
1726 +               Example:
1727 +               #iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
1728 +         
1729 +               In syslog you find something like this:
1730 +               ipt_osf: Windows [Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
1731 +               ipt_osf: Unknown: 16384:106:1:48:020405B401010402 44.33.22.11:1239 -> 11.22.33.44:80
1732 +         
1733 +           --smart
1734 +               if present, OSF will use some smartness to determine remote OS.
1735 +               Now only not use TTL( with it far remote machines can be determined).
1736 +         
1737 +         Fingerprints can be loaded through /proc/sys/net/ipv4/osf file.
1738 +         Only one fingerprint per open/close.
1739 +         
1740 +         Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
1741 +
1742 +config IP_POOL_STATISTICS
1743 +       bool  'enable statistics on pool usage'
1744 +       depends on IP_NF_POOL!=n
1745 +
1746 +config IP_NF_POOL
1747 +       tristate  'IP address pool support'
1748 +       depends on IP_NF_IPTABLES
1749 +         help
1750 +         CONFIG_IP_NF_POOL provides a match which lets you use bitmaps with one bit per
1751 +         address from some range of IP addresses; the match depends on whether a checked
1752 +         source or destination address has its bit set in the pool.  It also provides a
1753 +         POOL target, which can be used to add or remove the addresses of a packet
1754 +         to/from a pool.
1755 +         
1756 +         There is also a POOL netfilter target, which can be used to set or remove the
1757 +         addresses of a packet from a pool.
1758 +         
1759 +         To define and use pools, you need userlevel utilities: a patched iptables, and
1760 +         the program ippool(8), which defines the pools and their bounds.  The current
1761 +         release of pool matching is ippool-0.0.2, and can be found in the archives of
1762 +         the netfilter mailing list at http://lists.netfilter.org/.
1763 +
1764 +config IP_NF_MATCH_PSD
1765 +       tristate  'psd match support'
1766 +       depends on IP_NF_IPTABLES
1767 +         help
1768 +         This option adds a `psd' match, which supplies portscan
1769 +         detection match (psd). This match will attempt to detect TCP and UDP
1770 +         port scans. This match was derived from Solar Designer's scanlogd.
1771 +         
1772 +         Suppported options are:
1773 +         
1774 +         --psd-weight-threshold <threshold>
1775 +         
1776 +           Total weight of the latest TCP/UDP packets with different
1777 +           destination ports coming from the same host to be treated as port
1778 +           scan sequence.
1779 +         
1780 +         --psd-delay-threshold <delay>
1781 +         
1782 +           Delay (in hundredths of second) for the packets with different
1783 +           destination ports coming from the same host to be treated as
1784 +           possible port scan subsequence.
1785 +         
1786 +         --psd-lo-ports-weight <weight>
1787 +         
1788 +           Weight of the packet with privileged (<=1024) destination port.
1789 +         
1790 +         --psd-hi-ports-weight <weight>
1791 +         
1792 +           Weight of the packet with non-priviliged destination port.
1793 +
1794 +config IP_NF_MATCH_QUOTA
1795 +       tristate  'quota match support'
1796 +       depends on IP_NF_IPTABLES
1797 +         help
1798 +         This option adds CONFIG_IP_NF_MATCH_QUOTA, which implements network
1799 +         quotas by decrementing a byte counter with each packet.
1800 +         
1801 +         Supported options are:
1802 +         --quota <bytes>
1803 +           The quota in bytes.
1804 +         
1805 +         KNOWN BUGS: this does not work on SMP systems.
1806 +         
1807 +
1808 +config IP_NF_MATCH_RANDOM
1809 +       tristate  'random match support'
1810 +       depends on IP_NF_IPTABLES
1811 +         help
1812 +         This option adds a `random' match,
1813 +         which allow you to match packets randomly
1814 +         following a given probability. 
1815 +         
1816 +         Suppported options are:
1817 +         
1818 +         [--average]   percent will match randomly packets with a probability of
1819 +                       'percent'. default is 50%
1820 +
1821 +config IP_NF_MATCH_REALM
1822 +       tristate  'realm match support'
1823 +       depends on IP_NF_IPTABLES
1824 +         help
1825 +         realm match: uses realm key from routing as match criteria similiar to
1826 +                      one in packet classifier
1827 +         
1828 +         /** snip from packet classifier documentation */
1829 +         Routing tables based classifier
1830 +         CONFIG_NET_CLS_ROUTE4
1831 +           If you say Y here, you will be able to classify outgoing packets
1832 +           according to the route table entry they matched. If unsure, say Y.
1833 +         /** end snip **/
1834 +         
1835 +         
1836 +         # Example
1837 +         # add route
1838 +         /sbin/ip route add 194.29.194.0/24 via 194.29.192.1 realm 10
1839 +         
1840 +         # source realm is in realm with mask 0xFFFF0000,
1841 +         # destination is in realm with mask 0x0000FFFF
1842 +         
1843 +         # match destination realm
1844 +         /usr/local/sbin/iptables -A OUTPUT -m realm --realm 10 -j LOG
1845 +         
1846 +         # match realm of source, this is also determinated by routing,
1847 +         /usr/local/sbin/iptables -A INPUT -m realm --realm 655360 -j LOG
1848 +         
1849 +         THIS PATCH REQUIRES CONFIG_NET_CLS_ROUTE TO BE SET
1850 +
1851 +config IP_NF_MATCH_TIME
1852 +       tristate  'TIME match support'
1853 +       depends on IP_NF_IPTABLES
1854 +         help
1855 +         
1856 +         This option adds CONFIG_IP_NF_MATCH_TIME, which supplies a time match module.
1857 +         This match allows you to filter based on the packet arrival time
1858 +         (arrival time at the machine which the netfilter is running on) or
1859 +         departure time (for locally generated packets).
1860 +         
1861 +         Supported options are:
1862 +         --timestart HH:MM
1863 +           The starting point of the time match frame.
1864 +         
1865 +         --timestop HH:MM
1866 +           The stopping point of the time match frame
1867 +         
1868 +         --days Tue,Mon...
1869 +           Days of the week to match separated by a coma, no space
1870 +           (one of Sun,Mon,Tue,Wed,Thu,Fri,Sat)
1871 +         
1872 +         Example:
1873 +           -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon,Tue,Wed,Thu,Fri
1874 +           will match packets that have an arrival timestamp in the range 8:00->18:00 from Monday
1875 +           to Friday.
1876 +         
1877 +           -A OUTPUT -m time --timestart 8:00 --timestop 18:00 --Days Mon
1878 +           will match the packets (locally generated) that have a departure timestamp
1879 +           in the range 8:00->18:00 on Monday only.
1880 +
1881 +config IP_NF_MATCH_U32
1882 +       tristate  'U32 match support'
1883 +       depends on IP_NF_IPTABLES
1884 +         help
1885 +         
1886 +         U32 allows you to extract quantities of up to 4 bytes from a packet,
1887 +         AND them with specified masks, shift them by specified amounts and
1888 +         test whether the results are in any of a set of specified ranges.
1889 +         The specification of what to extract is general enough to skip over
1890 +         headers with lengths stored in the packet, as in IP or TCP header
1891 +         lengths.
1892 +         Details and examples are in the kernel module source.
1893 +
1894 +config IP_NF_SET
1895 +       tristate  'IP address/port sets support'
1896 +       depends on IP_NF_IPTABLES
1897 +         help
1898 +         
1899 +config IP_NF_SET_MAX
1900 +       int  '  Maximum number of sets'
1901 +       depends on IP_NF_SET
1902 +       default 256
1903 +       
1904 +config IP_NF_SET_IPMAP
1905 +       tristate  '  ipmap set type support'
1906 +       depends on IP_NF_SET
1907 +         help
1908 +
1909 +config IP_NF_SET_PORTMAP
1910 +       tristate  '  portmap set type support'
1911 +       depends on IP_NF_SET
1912 +         help
1913 +
1914 +config IP_NF_SET_MACIPMAP
1915 +       tristate  '  macipmap set type support'
1916 +       depends on IP_NF_SET
1917 +         help
1918 +
1919 +config IP_NF_SET_IPHASH
1920 +       tristate  '  iphash set type support'
1921 +       depends on IP_NF_SET
1922 +         help
1923 +
1924  endmenu
1925  
1926 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/Makefile linux-2.6.3/net/ipv4/netfilter/Makefile
1927 --- linux-2.6.3.org/net/ipv4/netfilter/Makefile 2004-02-18 04:57:20.000000000 +0100
1928 +++ linux-2.6.3/net/ipv4/netfilter/Makefile     2004-02-19 08:55:20.544815689 +0100
1929 @@ -42,15 +42,38 @@
1930  # matches
1931  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1932  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1933 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
1934 +obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
1935  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
1936 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
1937  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
1938  obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
1939  
1940  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1941  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1942 +
1943 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1944 +
1945  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1946  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1947  
1948 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1949 +
1950 +
1951 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
1952 +
1953 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1954 +
1955 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1956 +
1957 +
1958 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1959 +
1960 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1961 +
1962 +
1963 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1964 +
1965  obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1966  
1967  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1968 @@ -59,10 +82,15 @@
1969  
1970  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1971  
1972 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1973 +
1974 +
1975  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1976  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1977 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1978  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1979  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1980 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1981  
1982  obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1983  
1984 @@ -79,6 +107,9 @@
1985  obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1986  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1987  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1988 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1989 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1990 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1991  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1992  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1993  
1994 @@ -94,3 +125,10 @@
1995  obj-$(CONFIG_IP_NF_COMPAT_IPFWADM) += ipfwadm.o
1996  
1997  obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
1998 +
1999 +obj-$(CONFIG_IP_NF_SET) += ipt_set.o ipt_SET.o ip_set.o
2000 +obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o
2001 +obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
2002 +obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
2003 +obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
2004 +
2005 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.3/net/ipv4/netfilter/ip_pool.c
2006 --- linux-2.6.3.org/net/ipv4/netfilter/ip_pool.c        1970-01-01 01:00:00.000000000 +0100
2007 +++ linux-2.6.3/net/ipv4/netfilter/ip_pool.c    2004-02-19 09:08:42.247779733 +0100
2008 @@ -0,0 +1,334 @@
2009 +/* Kernel module for IP pool management */
2010 +
2011 +#include <linux/module.h>
2012 +#include <linux/ip.h>
2013 +#include <linux/skbuff.h>
2014 +#include <linux/netfilter_ipv4/ip_tables.h>
2015 +#include <linux/netfilter_ipv4/ip_pool.h>
2016 +#include <linux/errno.h>
2017 +#include <asm/uaccess.h>
2018 +#include <asm/bitops.h>
2019 +#include <linux/interrupt.h>
2020 +#include <linux/spinlock.h>
2021 +
2022 +#if 0
2023 +#define DP printk
2024 +#else
2025 +#define DP(format, args...)
2026 +#endif
2027 +
2028 +MODULE_LICENSE("GPL");
2029 +
2030 +#define NR_POOL 16
2031 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
2032 +
2033 +struct ip_pool {
2034 +       u_int32_t first_ip;     /* host byte order, included in range */
2035 +       u_int32_t last_ip;      /* host byte order, included in range */
2036 +       void *members;          /* the bitmap proper */
2037 +       int nr_use;             /* total nr. of tests through this */
2038 +       int nr_match;           /* total nr. of matches through this */
2039 +       rwlock_t lock;
2040 +};
2041 +
2042 +static struct ip_pool *POOL;
2043 +
2044 +static inline struct ip_pool *lookup(ip_pool_t index)
2045 +{
2046 +       if (index < 0 || index >= nr_pool) {
2047 +               DP("ip_pool:lookup: bad index %d\n", index);
2048 +               return 0;
2049 +       }
2050 +       return POOL+index;
2051 +}
2052 +
2053 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
2054 +{
2055 +        struct ip_pool *pool = lookup(index);
2056 +       int res = 0;
2057 +
2058 +       if (!pool || !pool->members)
2059 +               return 0;
2060 +       read_lock_bh(&pool->lock);
2061 +       if (pool->members) {
2062 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
2063 +                       addr -= pool->first_ip;
2064 +                       if (test_bit(addr, pool->members)) {
2065 +                               res = 1;
2066 +#ifdef CONFIG_IP_POOL_STATISTICS
2067 +                               pool->nr_match++;
2068 +#endif
2069 +                       }
2070 +               }
2071 +#ifdef CONFIG_IP_POOL_STATISTICS
2072 +               pool->nr_use++;
2073 +#endif
2074 +       }
2075 +       read_unlock_bh(&pool->lock);
2076 +       return res;
2077 +}
2078 +EXPORT_SYMBOL(ip_pool_match);
2079 +
2080 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
2081 +{
2082 +       struct ip_pool *pool;
2083 +       int res = -1;
2084 +
2085 +       pool = lookup(index);
2086 +       if (    !pool || !pool->members
2087 +            || addr < pool->first_ip || addr > pool->last_ip)
2088 +               return -1;
2089 +       read_lock_bh(&pool->lock);
2090 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
2091 +               addr -= pool->first_ip;
2092 +               res = isdel
2093 +                       ? (0 != test_and_clear_bit(addr, pool->members))
2094 +                       : (0 != test_and_set_bit(addr, pool->members));
2095 +       }
2096 +       read_unlock_bh(&pool->lock);
2097 +       return res;
2098 +}
2099 +
2100 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
2101 +{
2102 +       int res = pool_change(index,addr,isdel);
2103 +
2104 +       if (!isdel) res = !res;
2105 +       return res;
2106 +}
2107 +EXPORT_SYMBOL(ip_pool_mod);
2108 +
2109 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
2110 +{
2111 +       return 4*((((b-a+8)/8)+3)/4);
2112 +}
2113 +
2114 +static inline int poolbytes(ip_pool_t index)
2115 +{
2116 +       struct ip_pool *pool = lookup(index);
2117 +
2118 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
2119 +}
2120 +
2121 +static int setpool(
2122 +       struct sock *sk,
2123 +       int optval,
2124 +       void *user,
2125 +       unsigned int len
2126 +) {
2127 +       struct ip_pool_request req;
2128 +
2129 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
2130 +       if (!capable(CAP_NET_ADMIN))
2131 +               return -EPERM;
2132 +       if (optval != SO_IP_POOL)
2133 +               return -EBADF;
2134 +       if (len != sizeof(req))
2135 +               return -EINVAL;
2136 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
2137 +               return -EFAULT;
2138 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
2139 +       return -EINVAL;
2140 +}
2141 +
2142 +static int getpool(
2143 +       struct sock *sk,
2144 +       int optval,
2145 +       void *user,
2146 +       int *len
2147 +) {
2148 +       struct ip_pool_request req;
2149 +       struct ip_pool *pool;
2150 +       ip_pool_t i;
2151 +       int newbytes;
2152 +       void *newmembers;
2153 +       int res;
2154 +
2155 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
2156 +       if (!capable(CAP_NET_ADMIN))
2157 +               return -EINVAL;
2158 +       if (optval != SO_IP_POOL)
2159 +               return -EINVAL;
2160 +       if (*len != sizeof(req)) {
2161 +               return -EFAULT;
2162 +       }
2163 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
2164 +               return -EFAULT;
2165 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
2166 +       if (req.op < IP_POOL_BAD001) {
2167 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
2168 +               return -EFAULT;
2169 +       }
2170 +       switch(req.op) {
2171 +       case IP_POOL_HIGH_NR:
2172 +               DP("ip_pool HIGH_NR\n");
2173 +               req.index = IP_POOL_NONE;
2174 +               for (i=0; i<nr_pool; i++)
2175 +                       if (POOL[i].members)
2176 +                               req.index = i;
2177 +               return copy_to_user(user, &req, sizeof(req));
2178 +       case IP_POOL_LOOKUP:
2179 +               DP("ip_pool LOOKUP\n");
2180 +               pool = lookup(req.index);
2181 +               if (!pool)
2182 +                       return -EINVAL;
2183 +               if (!pool->members)
2184 +                       return -EBADF;
2185 +               req.addr = htonl(pool->first_ip);
2186 +               req.addr2 = htonl(pool->last_ip);
2187 +               return copy_to_user(user, &req, sizeof(req));
2188 +       case IP_POOL_USAGE:
2189 +               DP("ip_pool USE\n");
2190 +               pool = lookup(req.index);
2191 +               if (!pool)
2192 +                       return -EINVAL;
2193 +               if (!pool->members)
2194 +                       return -EBADF;
2195 +               req.addr = pool->nr_use;
2196 +               req.addr2 = pool->nr_match;
2197 +               return copy_to_user(user, &req, sizeof(req));
2198 +       case IP_POOL_TEST_ADDR:
2199 +               DP("ip_pool TEST 0x%08x\n", req.addr);
2200 +               pool = lookup(req.index);
2201 +               if (!pool)
2202 +                       return -EINVAL;
2203 +               res = 0;
2204 +               read_lock_bh(&pool->lock);
2205 +               if (!pool->members) {
2206 +                       DP("ip_pool TEST_ADDR no members in pool\n");
2207 +                       res = -EBADF;
2208 +                       goto unlock_and_return_res;
2209 +               }
2210 +               req.addr = ntohl(req.addr);
2211 +               if (req.addr < pool->first_ip) {
2212 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
2213 +                       res = -ERANGE;
2214 +                       goto unlock_and_return_res;
2215 +               }
2216 +               if (req.addr > pool->last_ip) {
2217 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
2218 +                       res = -ERANGE;
2219 +                       goto unlock_and_return_res;
2220 +               }
2221 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
2222 +                                       pool->members));
2223 +               read_unlock_bh(&pool->lock);
2224 +               return copy_to_user(user, &req, sizeof(req));
2225 +       case IP_POOL_FLUSH:
2226 +               DP("ip_pool FLUSH not yet implemented.\n");
2227 +               return -EBUSY;
2228 +       case IP_POOL_DESTROY:
2229 +               DP("ip_pool DESTROY not yet implemented.\n");
2230 +               return -EBUSY;
2231 +       case IP_POOL_INIT:
2232 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
2233 +               pool = lookup(req.index);
2234 +               if (!pool)
2235 +                       return -EINVAL;
2236 +               req.addr = ntohl(req.addr);
2237 +               req.addr2 = ntohl(req.addr2);
2238 +               if (req.addr > req.addr2) {
2239 +                       DP("ip_pool INIT bad ip range\n");
2240 +                       return -EINVAL;
2241 +               }
2242 +               newbytes = bitmap_bytes(req.addr, req.addr2);
2243 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
2244 +               if (!newmembers) {
2245 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
2246 +                       return -ENOMEM;
2247 +               }
2248 +               memset(newmembers, 0, newbytes);
2249 +               write_lock_bh(&pool->lock);
2250 +               if (pool->members) {
2251 +                       DP("ip_pool INIT pool %d exists\n", req.index);
2252 +                       kfree(newmembers);
2253 +                       res = -EBUSY;
2254 +                       goto unlock_and_return_res;
2255 +               }
2256 +               pool->first_ip = req.addr;
2257 +               pool->last_ip = req.addr2;
2258 +               pool->nr_use = 0;
2259 +               pool->nr_match = 0;
2260 +               pool->members = newmembers;
2261 +               write_unlock_bh(&pool->lock);
2262 +               return 0;
2263 +       case IP_POOL_ADD_ADDR:
2264 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
2265 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
2266 +               return copy_to_user(user, &req, sizeof(req));
2267 +       case IP_POOL_DEL_ADDR:
2268 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
2269 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
2270 +               return copy_to_user(user, &req, sizeof(req));
2271 +       default:
2272 +               DP("ip_pool:getpool bad op %d\n", req.op);
2273 +               return -EINVAL;
2274 +       }
2275 +       return -EINVAL;
2276 +
2277 +unlock_and_return_res:
2278 +       if (pool)
2279 +               read_unlock_bh(&pool->lock);
2280 +       return res;
2281 +}
2282 +
2283 +static struct nf_sockopt_ops so_pool
2284 += { { NULL, NULL }, PF_INET,
2285 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
2286 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
2287 +    0, NULL };
2288 +
2289 +MODULE_PARM(nr_pool, "i");
2290 +
2291 +static int __init init(void)
2292 +{
2293 +       ip_pool_t i;
2294 +       int res;
2295 +
2296 +       if (nr_pool < 1) {
2297 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
2298 +               return -EINVAL;
2299 +       }
2300 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
2301 +       if (!POOL) {
2302 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
2303 +                       nr_pool);
2304 +               return -ENOMEM;
2305 +       }
2306 +       for (i=0; i<nr_pool; i++) {
2307 +               POOL[i].first_ip = 0;
2308 +               POOL[i].last_ip = 0;
2309 +               POOL[i].members = 0;
2310 +               POOL[i].nr_use = 0;
2311 +               POOL[i].nr_match = 0;
2312 +               POOL[i].lock = RW_LOCK_UNLOCKED;
2313 +       }
2314 +       res = nf_register_sockopt(&so_pool);
2315 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
2316 +       if (res != 0) {
2317 +               kfree(POOL);
2318 +               POOL = 0;
2319 +       }
2320 +       return res;
2321 +}
2322 +
2323 +static void __exit fini(void)
2324 +{
2325 +       ip_pool_t i;
2326 +
2327 +       DP("ip_pool:fini BYEBYE\n");
2328 +       nf_unregister_sockopt(&so_pool);
2329 +       for (i=0; i<nr_pool; i++) {
2330 +               if (POOL[i].members) {
2331 +                       kfree(POOL[i].members);
2332 +                       POOL[i].members = 0;
2333 +               }
2334 +       }
2335 +       kfree(POOL);
2336 +       POOL = 0;
2337 +       DP("ip_pool:fini these are the famous last words\n");
2338 +       return;
2339 +}
2340 +
2341 +module_init(init);
2342 +module_exit(fini);
2343 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set.c linux-2.6.3/net/ipv4/netfilter/ip_set.c
2344 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
2345 +++ linux-2.6.3/net/ipv4/netfilter/ip_set.c     2004-02-09 15:02:00.000000000 +0100
2346 @@ -0,0 +1,1494 @@
2347 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
2348 + *                     Patrick Schaaf (bof@bof.de)
2349 + *                     Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2350 + *
2351 + * This program is free software; you can redistribute it and/or modify   
2352 + * it under the terms of the GNU General Public License as published by   
2353 + * the Free Software Foundation; either version 2 of the License, or      
2354 + * (at your option) any later version.                                    
2355 + *                                                                         
2356 + * This program is distributed in the hope that it will be useful,        
2357 + * but WITHOUT ANY WARRANTY; without even the implied warranty of         
2358 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
2359 + * GNU General Public License for more details.                           
2360 + *                                                                         
2361 + * You should have received a copy of the GNU General Public License      
2362 + * along with this program; if not, write to the Free Software            
2363 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2364 + */
2365 +
2366 +/* Kernel module for IP set management */
2367 +
2368 +#include <linux/config.h>
2369 +#include <linux/module.h>
2370 +#include <linux/ip.h>
2371 +#include <linux/skbuff.h>
2372 +#include <linux/netfilter_ipv4/ip_tables.h>
2373 +#include <linux/errno.h>
2374 +#include <asm/uaccess.h>
2375 +#include <asm/bitops.h>
2376 +#include <asm/softirq.h>
2377 +#include <linux/spinlock.h>
2378 +#include <linux/vmalloc.h>
2379 +
2380 +#define ASSERT_READ_LOCK(x)    /* dont use that */
2381 +#define ASSERT_WRITE_LOCK(x)
2382 +#include <linux/netfilter_ipv4/listhelp.h>
2383 +#include <linux/netfilter_ipv4/ip_set.h>
2384 +
2385 +static struct list_head set_type_list;         /* all registred set types */
2386 +struct ip_set **ip_set_list;                   /* all individual sets */
2387 +static rwlock_t list_lock = RW_LOCK_UNLOCKED;  /* protects both set_type_list and ip_set_list */
2388 +static unsigned int max_sets = 0;              /* max number of sets, */
2389 +
2390 +/* Arrgh */
2391 +#ifdef MODULE
2392 +#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
2393 +#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
2394 +#else
2395 +#define __MOD_INC(foo) do { } while (0)
2396 +#define __MOD_DEC(foo) do { } while (0)
2397 +#endif
2398 +
2399 +#define NOT_IN_CHILD_SET(fn,args...) \
2400 +       !*private \
2401 +       || !(*private)->childsets \
2402 +       || (set->type[i]->fn(*private,##args) < 0)
2403 +
2404 +static struct ip_set_private **
2405 +ip_set_find_private(struct ip_set *set,
2406 +                   struct ip_set_private **private,
2407 +                   ip_set_ip_t *ip,
2408 +                   u_int8_t level)
2409 +{
2410 +       int i;
2411 +       ip_set_ip_t id;
2412 +
2413 +       for (i = 0; i < level; i++) {
2414 +               if (NOT_IN_CHILD_SET(matchip, ip[i], &id))
2415 +                       return NULL;
2416 +               private = &(*private)->childsets[id];
2417 +       }
2418 +       DP("id: %i private: %p %p", id, private, *private);
2419 +       return private;
2420 +}
2421 +
2422 +/* Destroy function for the private part of the (child)sets.
2423 + * Must be called without holding any locks.
2424 + */
2425 +static void
2426 +ip_set_destroy_private(struct ip_set *set,
2427 +                      struct ip_set_private **private,
2428 +                      u_int8_t level)
2429 +{
2430 +       int i;
2431 +       
2432 +       DP("set %p private %p %p %p", set, private, *private, (*private)->childsets);
2433 +       if ((*private)->childsets) {
2434 +               for (i = 0; i < set->type[level]->sizeid(*private); i++)
2435 +                       if ((*private)->childsets[i]) {
2436 +                               DP("%i -> %p", i, (*private)->childsets[i]);
2437 +                               ip_set_destroy_private(set,
2438 +                                                      &(*private)->childsets[i],
2439 +                                                      level + 1);
2440 +                       }
2441 +               vfree((*private)->childsets);
2442 +       }
2443 +
2444 +       set->type[level]->destroy(private);
2445 +       DP("%p %p", private, *private);
2446 +}
2447 +
2448 +static void ip_set_flush_private(struct ip_set *set,
2449 +                                struct ip_set_private *private,
2450 +                                u_int8_t level,
2451 +                                u_int8_t childsets)
2452 +{
2453 +       int i;
2454 +       
2455 +       if (childsets && private->childsets)
2456 +               for (i = 0; i < set->type[level]->sizeid(private); i++)
2457 +                       if (private->childsets[i])
2458 +                               ip_set_flush_private(set,
2459 +                                                    private->childsets[i],
2460 +                                                    level + 1,
2461 +                                                    childsets);
2462 +
2463 +       set->type[level]->flush(private);
2464 +       
2465 +}
2466 +
2467 +/* ip_set_flush() - flush data in a set
2468 + */
2469 +static int ip_set_flush(struct ip_set *set,
2470 +                       ip_set_ip_t *ip, 
2471 +                       u_int8_t level,
2472 +                       u_int8_t childsets)
2473 +{
2474 +       int res = 0;
2475 +       struct ip_set_private **private;
2476 +       
2477 +       write_lock_bh(&set->lock);
2478 +       if (set->subref) {
2479 +               res = -EBUSY;
2480 +               goto unlock;
2481 +       }
2482 +       
2483 +       private = ip_set_find_private(set, &set->private, ip, level);
2484 +               
2485 +       if (private)
2486 +               ip_set_flush_private(set, *private, level, childsets);
2487 +
2488 +    unlock:
2489 +       write_unlock_bh(&set->lock);
2490 +       return res;
2491 +}
2492 +
2493 +int
2494 +ip_set_testip_kernel(struct ip_set *set,
2495 +                    const struct sk_buff *skb,
2496 +                    const u_int32_t *flags,
2497 +                    u_int8_t set_level,
2498 +                    u_int8_t ip_level)
2499 +{
2500 +       struct ip_set_private **private = &set->private;
2501 +       ip_set_ip_t id;
2502 +       int i, res = 0;
2503 +       
2504 +       read_lock_bh(&set->lock);
2505 +       if (set->levels < ip_level || set->subref)
2506 +               goto unlock;
2507 +       
2508 +       for (i = 0; i < set_level; i++) {
2509 +               if (NOT_IN_CHILD_SET(testip_kernel, skb,
2510 +                                    flags[i] | set->type[i]->typecode, &id))
2511 +                       goto unlock;
2512 +               DP("id: %i private: %p", id, *private);
2513 +               private = &(*private)->childsets[id];
2514 +       }
2515 +       for (i = set_level; private && *private && i < ip_level; i++) {
2516 +               if (set->type[i]->testip_kernel(*private, skb,
2517 +                               flags[i] | set->type[i]->typecode, &id) <= 0)
2518 +                       goto unlock;
2519 +               private = (*private)->childsets 
2520 +                               ? &(*private)->childsets[id] : NULL;
2521 +       }
2522 +       res = 1;
2523 +    unlock:
2524 +       read_unlock_bh(&set->lock);
2525 +       return res;
2526 +}
2527 +
2528 +void
2529 +ip_set_addip_kernel(struct ip_set *set, 
2530 +                   const struct sk_buff *skb,
2531 +                   const u_int32_t *flags,
2532 +                   u_int8_t set_level,
2533 +                   u_int8_t ip_level)
2534 +{
2535 +       struct ip_set_private **private = &set->private;
2536 +       ip_set_ip_t id;
2537 +       int i, res;
2538 +
2539 +       write_lock_bh(&set->lock);
2540 +       if (set->levels < ip_level || set->subref) {
2541 +               write_unlock_bh(&set->lock);
2542 +               return;
2543 +       }
2544 +       for (i = 0; i < set_level; i++) {
2545 +               if (NOT_IN_CHILD_SET(testip_kernel, skb,
2546 +                                    flags[i] | set->type[i]->typecode, &id)) {
2547 +                       write_unlock_bh(&set->lock);
2548 +                       return;
2549 +               }
2550 +               private = &(*private)->childsets[id];
2551 +       }
2552 +       for (i = set_level; private && *private && i < ip_level; i++) {
2553 +               res = set->type[i]->addip_kernel(*private, skb,
2554 +                       flags[i] | set->type[i]->typecode, &id);
2555 +               if (!(res == 0 || res == -EEXIST)) {
2556 +                       write_unlock_bh(&set->lock);
2557 +                       return;
2558 +               }
2559 +               private = (*private)->childsets 
2560 +                               ? &(*private)->childsets[id] : NULL;
2561 +       }
2562 +       write_unlock_bh(&set->lock);
2563 +}
2564 +
2565 +void
2566 +ip_set_delip_kernel(struct ip_set *set,
2567 +                   const struct sk_buff *skb,
2568 +                   const u_int32_t *flags,
2569 +                   u_int8_t set_level,
2570 +                   u_int8_t ip_level)
2571 +{
2572 +       struct ip_set_private **private = &set->private;
2573 +       ip_set_ip_t id;
2574 +       int i, res;
2575 +
2576 +       write_lock_bh(&set->lock);
2577 +       if (set->levels < ip_level || set->subref) {
2578 +               write_unlock_bh(&set->lock);
2579 +               return;
2580 +       }
2581 +       for (i = 0; i < set_level; i++) {
2582 +               if (NOT_IN_CHILD_SET(testip_kernel, skb,
2583 +                                    flags[i] | set->type[i]->typecode, &id)) {
2584 +                       write_unlock_bh(&set->lock);
2585 +                       return;
2586 +               }
2587 +               private = &(*private)->childsets[id];
2588 +       }
2589 +       for (i = set_level; private && *private && i < ip_level; i++) {
2590 +               res = set->type[i]->delip_kernel(*private, skb,
2591 +                       flags[i] | set->type[i]->typecode, &id);
2592 +               if (!(res == 0 || res == -EEXIST)) {
2593 +                       write_unlock_bh(&set->lock);
2594 +                       return;
2595 +               }
2596 +               private = (*private)->childsets 
2597 +                               ? &(*private)->childsets[id] : NULL;
2598 +       }
2599 +       write_unlock_bh(&set->lock);
2600 +}
2601 +
2602 +static int
2603 +ip_set_addip(struct ip_set *set,
2604 +            ip_set_ip_t *ip,
2605 +            u_int8_t level,
2606 +            const void *data,
2607 +            size_t size)
2608 +{
2609 +       struct ip_set_private **private;
2610 +       ip_set_ip_t id;
2611 +       int res = 0;
2612 +
2613 +       DP("%s %i %d", set->name, level, size);
2614 +       write_lock_bh(&set->lock);
2615 +       if (set->subref) {
2616 +               res = -EBUSY;
2617 +               goto unlock;
2618 +       }
2619 +       private = ip_set_find_private(set, &set->private, ip, level);
2620 +       DP("%s %i %d", set->name, level, size);
2621 +       while (level <= set->levels && size) {
2622 +               DP("%s %i %d", set->name, level, size);
2623 +               if (!(private && *private)) {
2624 +                       res = -ENOENT;
2625 +                       goto unlock;
2626 +               }
2627 +               if (size < set->type[level]->reqsize) {
2628 +                       res = -EINVAL;
2629 +                       goto unlock;
2630 +               }
2631 +               res = set->type[level]->addip(*private, data, 
2632 +                                       set->type[level]->reqsize, &id);
2633 +               if (!(res == 0 || res == -EEXIST))
2634 +                       goto unlock;
2635 +               private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2636 +               data += set->type[level]->reqsize;
2637 +               size -= set->type[level++]->reqsize;
2638 +       }
2639 +       if (size)
2640 +               res = -EINVAL;
2641 +    unlock:
2642 +       write_unlock_bh(&set->lock);
2643 +       return res;
2644 +}
2645 +
2646 +static int
2647 +ip_set_delip(struct ip_set *set,
2648 +            ip_set_ip_t *ip,
2649 +            u_int8_t level,
2650 +            const void *data,
2651 +            size_t size)
2652 +{
2653 +       struct ip_set_private **private;
2654 +       ip_set_ip_t id;
2655 +       int res = 0;
2656 +
2657 +       write_lock_bh(&set->lock);
2658 +       if (set->subref) {
2659 +               res = -EBUSY;
2660 +               goto unlock;
2661 +       }
2662 +       private = ip_set_find_private(set, &set->private, ip, level);
2663 +       while (level <= set->levels && size) {
2664 +               if (!(private && *private)) {
2665 +                       res = -ENOENT;
2666 +                       goto unlock;
2667 +               }
2668 +               if (size < set->type[level]->reqsize) {
2669 +                       res = -EINVAL;
2670 +                       goto unlock;
2671 +               }
2672 +               res = set->type[level]->delip(*private, data, 
2673 +                                       set->type[level]->reqsize, &id);
2674 +               if (!(res == 0 || res == -EEXIST))
2675 +                       goto unlock;
2676 +               private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2677 +               data += set->type[level]->reqsize;
2678 +               size -= set->type[level++]->reqsize;
2679 +       }
2680 +       if (size)
2681 +               res = -EINVAL;
2682 +    unlock:
2683 +       write_unlock_bh(&set->lock);
2684 +       return res;
2685 +}
2686 +
2687 +static int
2688 +ip_set_testip(struct ip_set *set,
2689 +             ip_set_ip_t *ip,
2690 +             u_int8_t level,
2691 +             const void *data,
2692 +             size_t size)
2693 +{
2694 +       struct ip_set_private **private;
2695 +       ip_set_ip_t id;
2696 +       int res = 0;
2697 +
2698 +       write_lock_bh(&set->lock);
2699 +       if (set->subref) {
2700 +               res = -EBUSY;
2701 +               goto unlock;
2702 +       }
2703 +       private = ip_set_find_private(set, &set->private, ip, level);
2704 +       while (level <= set->levels && size) {
2705 +               if (!(private && *private)) {
2706 +                       res = -ENOENT;
2707 +                       goto unlock;
2708 +               }
2709 +               if (size < set->type[level]->reqsize) {
2710 +                       res = -EINVAL;
2711 +                       goto unlock;
2712 +               }
2713 +               res = set->type[level]->testip(*private, data, 
2714 +                                       set->type[level]->reqsize, &id);
2715 +               DP("level: %i res: %i", level, res);
2716 +               if (res <= 0)
2717 +                       goto unlock;
2718 +               private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2719 +               data += set->type[level]->reqsize;
2720 +               size -= set->type[level++]->reqsize;
2721 +       }
2722 +       if (size)
2723 +               res = -EINVAL;
2724 +    unlock:
2725 +       write_unlock_bh(&set->lock);
2726 +       return (res > 0);
2727 +}
2728 +
2729 +static inline int
2730 +set_type_equal(const struct ip_set_type *set_type, const char *str2)
2731 +{
2732 +       DP("'%s' vs. '%s'", set_type->typename, str2);
2733 +       return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
2734 +}
2735 +
2736 +/*
2737 + * Always use find_setfoo() under the &list_lock.
2738 + */
2739 +static inline struct ip_set_type *find_set_type(const char name[IP_SET_MAXNAMELEN])
2740 +{
2741 +       return LIST_FIND(&set_type_list,
2742 +                        set_type_equal,
2743 +                        struct ip_set_type *,
2744 +                        name);
2745 +}
2746 +
2747 +int ip_set_register_set_type(struct ip_set_type *set_type)
2748 +{
2749 +       if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
2750 +               ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
2751 +                             set_type->typename,
2752 +                             set_type->protocol_version,
2753 +                             IP_SET_PROTOCOL_VERSION);
2754 +               return -EINVAL;
2755 +       }
2756 +
2757 +       write_lock_bh(&list_lock);
2758 +       if (find_set_type(set_type->typename)) {
2759 +               /* Duplicate! */
2760 +               write_unlock_bh(&list_lock);
2761 +               ip_set_printk("'%s' already registered!", 
2762 +                             set_type->typename);
2763 +               return -EINVAL;
2764 +       }
2765 +       MOD_INC_USE_COUNT;
2766 +       list_append(&set_type_list, set_type);
2767 +       write_unlock_bh(&list_lock);
2768 +       DP("'%s' registered.", set_type->typename);
2769 +       return 0;
2770 +}
2771 +
2772 +void ip_set_unregister_set_type(struct ip_set_type *set_type)
2773 +{
2774 +       write_lock_bh(&list_lock);
2775 +       if (!find_set_type(set_type->typename)) {
2776 +               ip_set_printk("'%s' not registered?",
2777 +                             set_type->typename);
2778 +               write_unlock_bh(&list_lock);
2779 +               return;
2780 +       }
2781 +       LIST_DELETE(&set_type_list, set_type);
2782 +       write_unlock_bh(&list_lock);
2783 +       MOD_DEC_USE_COUNT;
2784 +
2785 +       DP("'%s' unregistered.", set_type->typename);
2786 +}
2787 +
2788 +/* Create the private part of a (child)set.
2789 + * Must be called without holding any locks.
2790 + */
2791 +static int
2792 +ip_set_create_private(struct ip_set_type *set_type,
2793 +                     struct ip_set_private **private,
2794 +                     const void *data,
2795 +                     size_t size,
2796 +                     u_int8_t childsets)
2797 +{
2798 +       int res = 0;
2799 +       int newbytes;
2800 +
2801 +       DP("%s %p %p %i", set_type->typename, private, *private, childsets);
2802 +
2803 +       if (*private)
2804 +               printk("%p: %p as private already occupied", private, *private);
2805 +
2806 +       /* Call the set_type initializer. */
2807 +       res = set_type->create(private, data, size);
2808 +       if (res != 0)
2809 +               return res;
2810 +
2811 +       if (!childsets) {
2812 +               (*private)->childsets = NULL;
2813 +               return res;
2814 +       }
2815 +                               
2816 +       /* Create room for subsets */
2817 +       newbytes = set_type->sizeid(*private) * sizeof(struct ip_set_private *);
2818 +       DP("%s (%p) %i", set_type->typename, *private, newbytes);
2819 +       (*private)->childsets = vmalloc(newbytes);      \
2820 +       if (!(*private)->childsets) {
2821 +               set_type->destroy(private);
2822 +               return -ENOMEM;
2823 +       }
2824 +       DP("%s %p %p %p", set_type->typename, private, *private, (*private)->childsets);
2825 +       memset((*private)->childsets, 0, newbytes);
2826 +       return res;
2827 +}
2828 +
2829 +static int
2830 +ip_set_create_childset(struct ip_set *set, 
2831 +                      ip_set_ip_t *ip,
2832 +                      u_int8_t level,
2833 +                      u_int8_t childsets,
2834 +                      const void *data,
2835 +                      size_t size)
2836 +{
2837 +       struct ip_set_private **private = &set->private;
2838 +       ip_set_ip_t id;
2839 +       int res;
2840 +
2841 +       DP("%s (%i %i)", set->name, level, childsets);
2842 +       write_lock_bh(&set->lock);
2843 +       if (set->subref) {
2844 +               res = -EBUSY;
2845 +               goto unlock;
2846 +       }
2847 +       if (level > 1)
2848 +               private = ip_set_find_private(set, private, ip, level - 1);
2849 +       DP("%s (%i %i) %p %p", set->name, level, childsets, private, *private);
2850 +       if (!(private && *private && (*private)->childsets)) {
2851 +               res = -ENOENT;
2852 +               goto unlock;
2853 +       }
2854 +       DP("%s (%i %i) %p %p", set->name, level, childsets, private, *private);
2855 +       set->type[level - 1]->matchip(*private, ip[level - 1], &id);
2856 +       DP("%s (%i %i) %p %p %i", set->name, level, childsets, private, *private, id);
2857 +       if (id < 0) {
2858 +               res = -ENOENT;
2859 +               goto unlock;
2860 +       }
2861 +       if ((*private)->childsets[id]) {
2862 +               res = -EEXIST;
2863 +               goto unlock;
2864 +       }
2865 +       set->subref++;
2866 +       write_unlock_bh(&set->lock);
2867 +       
2868 +       /* Without holding any locks, create private part.  */
2869 +       res = ip_set_create_private(set->type[level],
2870 +                                   &(*private)->childsets[id],
2871 +                                   data, size, childsets);
2872 +
2873 +       write_lock_bh(&set->lock);
2874 +       set->subref--;
2875 +    unlock:
2876 +       DP("%s (%p %p) res=%i", set->name, private, *private, res);
2877 +       write_unlock_bh(&set->lock);
2878 +       return res;
2879 +}
2880 +
2881 +static int
2882 +ip_set_create(const char name[IP_SET_MAXNAMELEN],
2883 +             char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN],
2884 +             u_int8_t level,
2885 +             const void *data,
2886 +             size_t size)
2887 +{
2888 +       int i, id, res = 0;
2889 +       struct ip_set *set;
2890 +
2891 +       DP("%s (%i): %s", typename[0], level, name);
2892 +       /*
2893 +        * First, and without any locks, allocate and initialize
2894 +        * a normal base set structure.
2895 +        */
2896 +       set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
2897 +       if (!set)
2898 +               return -ENOMEM;
2899 +       set->lock = RW_LOCK_UNLOCKED;
2900 +       strncpy(set->name, name, IP_SET_MAXNAMELEN);
2901 +       set->name[IP_SET_MAXNAMELEN - 1] = '\0';
2902 +       set->ref = 0;
2903 +       set->subref = 0;
2904 +       set->levels = level;
2905 +       set->private = NULL;
2906 +
2907 +       /*
2908 +        * Next, take the &list_lock, check that we know the type,
2909 +        * and take a reference on the type, to make sure it
2910 +        * stays available while constructing our new set.
2911 +        *
2912 +        * After referencing the type, we drop the &list_lock,
2913 +        * and let the new set construction run without locks.
2914 +        */
2915 +       write_lock_bh(&list_lock);
2916 +       for (i = 0; i < level; i++) {
2917 +               set->type[i] = find_set_type(typename[i]);
2918 +               if (set->type[i] == NULL) {
2919 +                       /* FIXME: try loading the module */
2920 +                       write_unlock_bh(&list_lock);
2921 +                       ip_set_printk("no set type '%s', set '%s' not created",
2922 +                                     typename[i], name);
2923 +                       kfree(set);
2924 +                       return -EINVAL;
2925 +               }
2926 +       }
2927 +       for (i = 0; i < level; i++)
2928 +               __MOD_INC(set->type[i]->me);
2929 +       write_unlock_bh(&list_lock);
2930 +
2931 +       /*
2932 +        * Without holding any locks, create private part.
2933 +        */
2934 +       res = ip_set_create_private(set->type[0],
2935 +                                   &set->private,
2936 +                                   data, size, level - 1);                             
2937 +       if (res != 0) {
2938 +               for (i = 0; i <= level; i++)
2939 +                       __MOD_DEC(set->type[i]->me);
2940 +               kfree(set);
2941 +               return res;
2942 +       }
2943 +
2944 +       /* BTW, res==0 here. */
2945 +
2946 +       /*
2947 +        * Here, we have a valid, constructed set. &list_lock again,
2948 +        * and check that it is not already in ip_set_list.
2949 +        */
2950 +       write_lock_bh(&list_lock);
2951 +       id = -1;
2952 +       for (i = 0; i < max_sets; i++) {
2953 +               if (ip_set_list[i] != NULL 
2954 +                   && strncmp(ip_set_list[i]->name, set->name, 
2955 +                              IP_SET_MAXNAMELEN - 1) == 0) {
2956 +                       res = -EEXIST;
2957 +                       goto cleanup;
2958 +               } else if (id < 0 && ip_set_list[i] == NULL)
2959 +                       id = i;
2960 +       }
2961 +       if (id < 0) {
2962 +               /* No free slot remained */
2963 +               res = -ERANGE;
2964 +               goto cleanup;
2965 +       }
2966 +       /*
2967 +        * Finally! Append our shiny new set into the list, and be done.
2968 +        */
2969 +       DP("create: '%s' created with id %i!", set->name, id);
2970 +       ip_set_list[id] = set;
2971 +       write_unlock_bh(&list_lock);
2972 +       return res;
2973 +       
2974 +    cleanup:
2975 +       write_unlock_bh(&list_lock);
2976 +       ip_set_destroy_private(set, &set->private, 0);
2977 +       for (i = 0; i < level; i++)
2978 +               __MOD_DEC(set->type[i]->me);
2979 +       kfree(set);
2980 +       return res;
2981 +}
2982 +
2983 +static int ip_set_destroy(struct ip_set *set,
2984 +                         ip_set_ip_t *ip,
2985 +                         u_int8_t level)
2986 +{
2987 +       struct ip_set_private **private;
2988 +       int i, res = 0;
2989 +
2990 +       write_lock_bh(&list_lock);
2991 +       /* there is no race, here. ->ref modification always happens
2992 +        * under &list_lock. Fine.
2993 +        */
2994 +       if (level == 0) {
2995 +               /* one ref from caller */
2996 +               if (set->ref > 1 || set->subref) {
2997 +                       res = -EBUSY;
2998 +                       goto unlock;
2999 +               }
3000 +
3001 +               for (i = 0; i < max_sets; i++)
3002 +                       if (ip_set_list[i] == set) {
3003 +                               ip_set_list[i] = NULL;
3004 +                               break;
3005 +                       }
3006 +               write_unlock_bh(&list_lock);
3007 +
3008 +               ip_set_destroy_private(set, &set->private, 0);
3009 +               for (i = 0; i < set->levels; i++)
3010 +                       __MOD_DEC(set->type[i]->me);
3011 +               kfree(set);
3012 +               return res;
3013 +       }
3014 +
3015 +       private = ip_set_find_private(set, &set->private, 
3016 +                                     ip, level);
3017 +               
3018 +       if (private && *private) {
3019 +               if (set->subref) {
3020 +                       res = -EBUSY;
3021 +                       goto unlock;
3022 +               }
3023 +               set->subref++;
3024 +               write_unlock_bh(&list_lock);
3025 +               
3026 +               DP("%p %p", private, *private);
3027 +               ip_set_destroy_private(set, private, level);
3028 +               DP("%p %p", private, *private);
3029 +
3030 +               write_lock_bh(&list_lock);
3031 +               set->subref--;
3032 +       } else
3033 +               res = -ENOENT;
3034 +               
3035 +    unlock:
3036 +       write_unlock_bh(&list_lock);
3037 +       return res;
3038 +}
3039 +
3040 +/*
3041 + * Find set by name, reference it once.  The reference makes sure the
3042 + * thing pointed to, does not go away under our feet.  Drop the reference
3043 + * later, using ip_set_put().
3044 + */
3045 +struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
3046 +                                int *id)
3047 +{
3048 +       struct ip_set *set = NULL;
3049 +       int i;
3050 +
3051 +       read_lock_bh(&list_lock);
3052 +       for (i = 0; i < max_sets; i++) {
3053 +               set = ip_set_list[i];
3054 +               if (set != NULL
3055 +                   && strncmp(set->name, name, IP_SET_MAXNAMELEN - 1) == 0) {
3056 +                       set->ref++;
3057 +                       *id = i;
3058 +                       break;
3059 +               }
3060 +       }
3061 +       read_unlock_bh(&list_lock);
3062 +       return set;
3063 +}
3064 +
3065 +/*
3066 + * Find set by id, reference it once.  The reference makes sure the
3067 + * thing pointed to, does not go away under our feet.  Drop the reference
3068 + * later, using ip_set_put().
3069 + */
3070 +struct ip_set *ip_set_get_byid(int id)
3071 +{
3072 +       struct ip_set *set;
3073 +
3074 +       if (id < 0 || id >= max_sets)
3075 +               return NULL;
3076 +               
3077 +       write_lock_bh(&list_lock);
3078 +       set = ip_set_list[id];;
3079 +       if (set)
3080 +               set->ref++;
3081 +       write_unlock_bh(&list_lock);
3082 +       return set;
3083 +}
3084 +
3085 +/*
3086 + * If the given set pointer points to a valid set, decrement
3087 + * reference count by 1.  The caller shall not assume the pointer
3088 + * to be valid, after calling this function.
3089 + */
3090 +void ip_set_put(struct ip_set *set)
3091 +{
3092 +       write_lock_bh(&list_lock);
3093 +       if (set)
3094 +               set->ref--;
3095 +       write_unlock_bh(&list_lock);
3096 +}
3097 +
3098 +static int ip_set_rename(struct ip_set *set, const char *name)
3099 +{
3100 +       int i, res = 0;
3101 +
3102 +       write_lock_bh(&list_lock);
3103 +       for (i = 0; i < max_sets; i++) {
3104 +               if (ip_set_list[i] != NULL 
3105 +                   && strncmp(ip_set_list[i]->name, 
3106 +                              name,
3107 +                              IP_SET_MAXNAMELEN - 1) == 0) {
3108 +                       res = -EEXIST;
3109 +                       goto unlock;
3110 +               }
3111 +       }
3112 +       strncpy(set->name, name, IP_SET_MAXNAMELEN);
3113 +       set->name[IP_SET_MAXNAMELEN - 1] = '\0';
3114 +    unlock:
3115 +       write_unlock_bh(&list_lock);
3116 +       return res;
3117 +}
3118 +
3119 +static int ip_set_swap(struct ip_set *from, struct ip_set *to)
3120 +{
3121 +       char from_name[IP_SET_MAXNAMELEN];
3122 +       unsigned from_ref;
3123 +       int i, res = 0;
3124 +       int from_id = -1, to_id = -1;
3125 +
3126 +       write_lock_bh(&list_lock);
3127 +       for (i = 0; i < max_sets && (from_id < 0 || to_id < 0); i++) {
3128 +               if (ip_set_list[i] == from)
3129 +                       from_id = i;
3130 +               if (ip_set_list[i] == to)
3131 +                       to_id = i;
3132 +       }
3133 +       /* We must have got both sets: we hold refcounts against them! */
3134 +       if (from_id < 0 || to_id < 0) {
3135 +               res = -EINVAL;
3136 +               goto unlock;
3137 +       }
3138 +       
3139 +       strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
3140 +       from_ref = from->ref;
3141 +       
3142 +       ip_set_list[from_id] = to;
3143 +       ip_set_list[to_id] = from;
3144 +       
3145 +       strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
3146 +       from->ref = to->ref;
3147 +       strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
3148 +       to->ref = from_ref;
3149 +    unlock:
3150 +       write_unlock_bh(&list_lock);
3151 +       return res;
3152 +}
3153 +
3154 +size_t ip_set_listing_size(void)
3155 +{
3156 +       size_t size = 0;
3157 +       int id;
3158 +
3159 +       read_lock_bh(&list_lock);
3160 +       for (id = 0; id < max_sets; id++) {
3161 +               if (ip_set_list[id] != NULL)
3162 +                       size += sizeof(struct ip_set_req_listing);
3163 +       }
3164 +       read_unlock_bh(&list_lock);
3165 +
3166 +       return size;
3167 +}
3168 +
3169 +int ip_set_listing(void *data, int *len)
3170 +{
3171 +       int used = 0;
3172 +       int res = 0;            /* All OK */
3173 +       int i, id;
3174 +       struct ip_set *set;
3175 +       struct ip_set_req_listing *header = data;
3176 +
3177 +       read_lock_bh(&list_lock);
3178 +       for (id = 0; id < max_sets; id++) {
3179 +               if (ip_set_list[id] == NULL)
3180 +                       continue;
3181 +       
3182 +               /* Pointer to our header */
3183 +               header = (struct ip_set_req_listing *) (data + used);
3184 +
3185 +               DP("used before= %d %p %p %p", used, header, data,
3186 +                  data + used);
3187 +
3188 +               /* Get and ensure header size */
3189 +               if (used + sizeof(struct ip_set_req_listing) > *len)
3190 +                       goto not_enough_mem;
3191 +
3192 +               set = ip_set_list[id];
3193 +
3194 +               /* Fill with data */
3195 +               strncpy(header->name, set->name, IP_SET_MAXNAMELEN - 1);
3196 +               for (i = 0; i < set->levels; i++)
3197 +                       strncpy(header->typename[i], set->type[i]->typename,
3198 +                               IP_SET_MAXNAMELEN - 1);
3199 +               header->levels = set->levels;
3200 +               header->ref = set->ref;
3201 +               header->id = id;
3202 +
3203 +               used += sizeof(struct ip_set_req_listing);
3204 +               DP("used after= %d", used);
3205 +       }
3206 +       *len = used;            /* How much did we use? */
3207 +       goto unlock_and_return;
3208 +
3209 +    not_enough_mem:
3210 +       DP("not enough mem, try again");
3211 +       res = -ENOMEM;
3212 +
3213 +    unlock_and_return:
3214 +       read_unlock_bh(&list_lock);
3215 +       return res;
3216 +}
3217 +
3218 +int ip_set_list_size(struct ip_set * set,
3219 +                    ip_set_ip_t *ip,
3220 +                    unsigned level,
3221 +                    size_t *size,
3222 +                    unsigned op)
3223 +{
3224 +       int res = 0;    /* OK */
3225 +       struct ip_set_private **private;
3226 +
3227 +       DP("%d %s %d", op, set->name, level);
3228 +       read_lock_bh(&set->lock);
3229 +       if (set->subref) {
3230 +               res = -EBUSY;
3231 +               goto unlock;
3232 +       }
3233 +       private = ip_set_find_private(set, &set->private, ip, level);
3234 +       if (!(private && *private)) {
3235 +               res = -ENOENT;
3236 +               goto unlock;
3237 +       }
3238 +       switch (op) {
3239 +       case IP_SET_OP_LIST_HEADER_SIZE:
3240 +               *size = set->type[level]->list_header_size(*private);
3241 +               break;
3242 +       case IP_SET_OP_LIST_MEMBERS_SIZE:
3243 +               *size = set->type[level]->list_members_size(*private);
3244 +               break;
3245 +       case IP_SET_OP_LIST_CHILDSETS_SIZE:
3246 +               *size = (*private)->childsets == NULL ? 0
3247 +                       : bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3248 +               break;
3249 +       default:
3250 +               res = -EINVAL;
3251 +       }
3252 +   unlock:
3253 +       read_unlock_bh(&set->lock);
3254 +       DP("%d %s %d: %u", op, set->name, level, *size);
3255 +
3256 +       return res;
3257 +}
3258 +
3259 +static void list_childsets(const struct ip_set_private *private, 
3260 +                          void *data,
3261 +                          ip_set_ip_t sizeid)
3262 +{
3263 +       ip_set_ip_t id;
3264 +       
3265 +       memset(data, 0, bitmap_bytes(0, sizeid - 1));
3266 +
3267 +       if (private->childsets == NULL)
3268 +               return;
3269 +       
3270 +       for (id = 0; id < sizeid; id++)
3271 +               if (private->childsets[id] != NULL)
3272 +                       set_bit(id, data);
3273 +}
3274 +
3275 +int ip_set_list_data(struct ip_set *set,
3276 +                    ip_set_ip_t *ip,
3277 +                    unsigned level,
3278 +                    void *data,
3279 +                    int *len,
3280 +                    unsigned op)
3281 +{
3282 +       int res = 0;            /* All OK */
3283 +       size_t need;
3284 +       struct ip_set_private **private;
3285 +       void (*datafn)(const struct ip_set_private *, void *);
3286 +
3287 +       read_lock_bh(&set->lock);
3288 +       if (set->subref) {
3289 +               res = -EBUSY;
3290 +               goto unlock;
3291 +       }
3292 +       private = ip_set_find_private(set, &set->private, ip, level);
3293 +       if (!(private && *private)) {
3294 +               res = -ENOENT;
3295 +               goto unlock;
3296 +       }
3297 +       switch (op) {
3298 +       case IP_SET_OP_LIST_HEADER:
3299 +               need = set->type[level]->list_header_size(*private);
3300 +               datafn = set->type[level]->list_header;
3301 +               break;
3302 +       case IP_SET_OP_LIST_MEMBERS:
3303 +               need = set->type[level]->list_members_size(*private);
3304 +               datafn = set->type[level]->list_members;
3305 +               break;
3306 +       case IP_SET_OP_LIST_CHILDSETS:
3307 +               if ((*private)->childsets == NULL) {
3308 +                       res = -ENOENT;
3309 +                       goto unlock;
3310 +               }
3311 +               need = bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3312 +               datafn = NULL;
3313 +               break;
3314 +       default:
3315 +               res = -EINVAL;
3316 +               goto unlock;
3317 +       }
3318 +       if (need > *len) {
3319 +               res = -ENOMEM;
3320 +               goto unlock;
3321 +       }
3322 +       *len = need;
3323 +       if (datafn)
3324 +               datafn(*private, data);
3325 +       else
3326 +               list_childsets(*private, data, set->type[level]->sizeid(*private));
3327 +
3328 +    unlock:
3329 +       read_unlock_bh(&set->lock);
3330 +       return res;
3331 +}
3332 +
3333 +static int
3334 +ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
3335 +{
3336 +       void *data;
3337 +       int res = 0;            /* Assume OK */
3338 +       struct ip_set_req_base *req_base;
3339 +       struct ip_set_req_std *req_std;
3340 +       struct ip_set *set = NULL;
3341 +
3342 +       DP("optval=%d, user=%p, len=%d", optval, user, len);
3343 +       if (!capable(CAP_NET_ADMIN))
3344 +               return -EPERM;
3345 +       if (optval != SO_IP_SET)
3346 +               return -EBADF;
3347 +       if (len < sizeof(struct ip_set_req_base)) {
3348 +               ip_set_printk("short userdata (want >=%d, got %d)",
3349 +                             sizeof(struct ip_set_req_base), len);
3350 +               return -EINVAL;
3351 +       }
3352 +       data = vmalloc(len);
3353 +       if (!data) {
3354 +               DP("out of mem for %d bytes", len);
3355 +               return -ENOMEM;
3356 +       }
3357 +       if (copy_from_user(data, user, len) != 0) {
3358 +               res = -EFAULT;
3359 +               goto done;
3360 +       }
3361 +
3362 +       req_base = (struct ip_set_req_base *) data;
3363 +
3364 +       DP("op=%x id='%x'", req_base->op, req_base->id);
3365 +       
3366 +       /* Handle set creation first - no incoming set specified */
3367 +
3368 +       if (req_base->op == IP_SET_OP_CREATE) {
3369 +               struct ip_set_req_create *req_create
3370 +                       = (struct ip_set_req_create *) data;
3371 +               int i;
3372 +               
3373 +               if (len < sizeof(struct ip_set_req_create)) {
3374 +                       ip_set_printk("short CREATE data (want >%d, got %d)",
3375 +                                     sizeof(struct ip_set_req_create), len);
3376 +                       res = -EINVAL;
3377 +                       goto done;
3378 +               }
3379 +               if (req_create->levels > IP_SET_LEVELS) {
3380 +                       ip_set_printk("set level %d too deep (max %d)",
3381 +                                     req_create->levels, IP_SET_LEVELS);
3382 +                       res = -EINVAL;
3383 +                       goto done;
3384 +               }
3385 +               req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
3386 +               for (i = 0; i < req_create->levels; i++)
3387 +                       req_create->typename[i][IP_SET_MAXNAMELEN - 1] = '\0';
3388 +               res = ip_set_create(req_create->name,
3389 +                                   req_create->typename,
3390 +                                   req_create->levels,
3391 +                                   data + sizeof(struct ip_set_req_create),
3392 +                                   len - sizeof(struct ip_set_req_create));
3393 +               goto done;
3394 +       }
3395 +
3396 +       /* All remaining requests want a set by id.
3397 +        * We take a proper reference here, and drop it after processing.
3398 +        * From hereon, code goes to '*put_set', not to 'done'.
3399 +        */
3400 +
3401 +       set = ip_set_get_byid(req_base->id);
3402 +       if (set == NULL) {
3403 +               res = -ESRCH;
3404 +               goto done;
3405 +       } 
3406 +       
3407 +       DP("set %s (%d) (%u)", set->name, req_base->id, set->ref);
3408 +       /* Simple requests: no subsets */
3409 +       switch (req_base->op) {
3410 +       case IP_SET_OP_RENAME:{
3411 +                       struct ip_set_req_rename *req_rename
3412 +                               = (struct ip_set_req_rename *) data;
3413 +
3414 +                       if (len != sizeof(struct ip_set_req_rename)) {
3415 +                               ip_set_printk("short RENAME data (want >%d, got %d)",
3416 +                                             sizeof(struct ip_set_req_rename), len);
3417 +                               res = -EINVAL;
3418 +                               goto put_set;
3419 +                       }
3420 +
3421 +                       res = ip_set_rename(set, req_rename->newname);
3422 +                       goto put_set;
3423 +               }
3424 +
3425 +       case IP_SET_OP_SWAP:{
3426 +                       struct ip_set_req_swap *req_swap
3427 +                               = (struct ip_set_req_swap *) data;
3428 +                       struct ip_set *to;
3429 +
3430 +                       if (len != sizeof(struct ip_set_req_swap)) {
3431 +
3432 +                               ip_set_printk("short SWAP data (want >%d, got %d)",
3433 +                                             sizeof(struct ip_set_req_swap), len);
3434 +                               res = -EINVAL;
3435 +                               goto put_set;
3436 +                       }
3437 +
3438 +                       to = ip_set_get_byid(req_swap->to);
3439 +                       if (to == NULL) {
3440 +                               res = -ESRCH;
3441 +                               goto put_set;
3442 +                       }
3443 +                       res = ip_set_swap(set, to);
3444 +                       ip_set_put(to);
3445 +                       goto put_set;
3446 +               }
3447 +       default: 
3448 +               ; /* Requests with possible subsets: fall trough. */
3449 +       }
3450 +       
3451 +       req_std = (struct ip_set_req_std *) data;
3452 +       if (len < sizeof(struct ip_set_req_std)) {
3453 +               ip_set_printk("short data in std request (want >%d, got %d)",
3454 +                             sizeof(struct ip_set_req_std), len);
3455 +               res = -EINVAL;
3456 +               goto put_set;
3457 +       } else if (req_std->level >= set->levels) {
3458 +               res = -EINVAL;
3459 +               goto put_set;
3460 +       }
3461 +
3462 +       switch (req_base->op) {
3463 +       case IP_SET_OP_ADD_IP:{
3464 +                       res = ip_set_addip(set,
3465 +                                          req_std->ip, req_std->level,
3466 +                                          data + sizeof(struct ip_set_req_std),
3467 +                                          len - sizeof(struct ip_set_req_std));
3468 +                       goto put_set;
3469 +               }
3470 +       case IP_SET_OP_DEL_IP:{
3471 +                       res = ip_set_delip(set,
3472 +                                          req_std->ip, req_std->level,
3473 +                                          data + sizeof(struct ip_set_req_std),
3474 +                                          len - sizeof(struct ip_set_req_std));
3475 +                       goto put_set;
3476 +               }
3477 +       case IP_SET_OP_DESTROY:{
3478 +                       res = ip_set_destroy(set, req_std->ip, req_std->level);
3479 +                       if (req_std->level == 0 && res == 0)
3480 +                               goto done;      /* destroyed: no ip_set_put */
3481 +                       goto put_set;
3482 +               }
3483 +       case IP_SET_OP_FLUSH:{
3484 +                       struct ip_set_req_sub *req_sub =
3485 +                               (struct ip_set_req_sub *) data;
3486 +
3487 +                       if (len < sizeof(struct ip_set_req_sub)) {
3488 +                               ip_set_printk("short data in flush request (want >%d, got %d)",
3489 +                                             sizeof(struct ip_set_req_sub), len);
3490 +                               res = -EINVAL;
3491 +                               goto put_set;
3492 +                       }
3493 +                       res = ip_set_flush(set, req_sub->ip, req_sub->level, req_sub->childsets);
3494 +                       goto put_set;
3495 +               }
3496 +       case IP_SET_OP_CREATE_CHILD:{
3497 +                       struct ip_set_req_sub *req_sub
3498 +                               = (struct ip_set_req_sub *) data;
3499 +               
3500 +                       if (len < sizeof(struct ip_set_req_sub)) {
3501 +                               ip_set_printk("short CREATE_CHILD data (want >%d, got %d)",
3502 +                                             sizeof(struct ip_set_req_sub), len);
3503 +                               res = -EINVAL;
3504 +                               goto put_set;
3505 +                       }
3506 +                       if (req_sub->level < 1) {
3507 +                               /* No entry supplied? */
3508 +                               res = -EINVAL;
3509 +                               goto put_set;
3510 +                       }
3511 +                       if (((req_sub->level >= set->levels  - 1) && req_sub->childsets)) {
3512 +                               /* No room for subsets to be created. */
3513 +                               res = -ERANGE;
3514 +                               goto put_set;
3515 +                       }
3516 +                       res = ip_set_create_childset(set,
3517 +                                           req_sub->ip, 
3518 +                                           req_sub->level, 
3519 +                                           req_sub->childsets,
3520 +                                           data + sizeof(struct ip_set_req_sub),
3521 +                                           len - sizeof(struct ip_set_req_sub));
3522 +                       goto put_set;
3523 +               }
3524 +       default:{
3525 +               DP("unknown op %d", req_base->op);
3526 +               ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3527 +               res = -EINVAL;
3528 +               }
3529 +       } /* end of switch(op) */
3530 +
3531 +    put_set:
3532 +       if (set)
3533 +               ip_set_put(set);
3534 +    done:
3535 +       vfree(data);
3536 +       if (res > 0)
3537 +               res = 0;
3538 +       return res;
3539 +}
3540 +
3541 +static int 
3542 +ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
3543 +{
3544 +       int res = 0;
3545 +       struct ip_set_req_base *req_base;
3546 +       struct ip_set_req_std *req_std;
3547 +       struct ip_set *set = NULL;
3548 +       void *data;
3549 +       int copylen = *len;
3550 +
3551 +       DP("optval=%d, user=%p, len=%d", optval, user, *len);
3552 +       if (!capable(CAP_NET_ADMIN))
3553 +               return -EPERM;
3554 +       if (optval != SO_IP_SET)
3555 +               return -EBADF;
3556 +       if (*len < sizeof(struct ip_set_req_base)) {
3557 +               ip_set_printk("short userdata (want >=%d, got %d)",
3558 +                             sizeof(struct ip_set_req_base), *len);
3559 +               return -EINVAL;
3560 +       }
3561 +       data = vmalloc(*len);
3562 +       if (!data) {
3563 +               DP("out of mem for %d bytes", *len);
3564 +               return -ENOMEM;
3565 +       }
3566 +       if (copy_from_user(data, user, *len) != 0) {
3567 +               res = -EFAULT;
3568 +               goto done;
3569 +       }
3570 +
3571 +       req_base = (struct ip_set_req_base *) data;
3572 +
3573 +       DP("op=%x id='%x'", req_base->op, req_base->id);
3574 +
3575 +       /* Requests without a named set. */
3576 +       switch (req_base->op) {
3577 +       case IP_SET_OP_VERSION:{
3578 +                       struct ip_set_req_version *req_version =
3579 +                           (struct ip_set_req_version *) data;
3580 +
3581 +                       if (*len != sizeof(struct ip_set_req_version)) {
3582 +                               ip_set_printk("short VERSION (want >=%d, got %d)",
3583 +                                             sizeof(struct ip_set_req_version),
3584 +                                             *len);
3585 +                               res = -EINVAL;
3586 +                               goto done;
3587 +                       }
3588 +
3589 +                       req_version->version = IP_SET_PROTOCOL_VERSION;
3590 +                       res = copy_to_user(user, req_version,
3591 +                                          sizeof(struct ip_set_req_version));
3592 +                       goto done;
3593 +               }
3594 +       case IP_SET_OP_LISTING_SIZE:{
3595 +                       struct ip_set_req_listing_size *req_list =
3596 +                           (struct ip_set_req_listing_size *) data;
3597 +
3598 +                       DP("IP_SET_OP_LISTING_SIZE");
3599 +
3600 +                       if (*len != sizeof(struct ip_set_req_listing_size)) {
3601 +                               ip_set_printk("short LISTING_SIZE (want >=%d, got %d)",
3602 +                                             sizeof(struct ip_set_req_listing_size),
3603 +                                             *len);
3604 +                               res = -EINVAL;
3605 +                               goto done;
3606 +                       }
3607 +
3608 +                       req_list->size = ip_set_listing_size();
3609 +                       DP("req_list->size = %d", req_list->size);
3610 +                       res = copy_to_user(user, req_list,
3611 +                                          sizeof(struct ip_set_req_listing_size));
3612 +                       goto done;
3613 +               }
3614 +       case IP_SET_OP_LISTING:{
3615 +                       DP("LISTING before len=%d", *len);
3616 +                       res = ip_set_listing(data, len);
3617 +                       DP("LISTING done len=%d", *len);
3618 +                       if (res < 0)
3619 +                               goto done;      /* Error */
3620 +
3621 +                       res = copy_to_user(user, data, *len);   /* Only copy the mem used */
3622 +                       goto done;
3623 +               }
3624 +       default: 
3625 +               ; /* Requests with named set: fall trought */
3626 +       }
3627 +
3628 +       /* Special cases: GETSET_BYNAME/BYID */
3629 +       switch (req_base->op) {
3630 +       case IP_SET_OP_GETSET_BYNAME: {
3631 +                       struct ip_set_req_get *req_get
3632 +                               = (struct ip_set_req_get *) data;
3633 +
3634 +                       if (*len != sizeof(struct ip_set_req_get)) {
3635 +                               ip_set_printk("short _BYNAME (want >=%d, got %d)",
3636 +                                             sizeof(struct ip_set_req_get), *len);
3637 +                               res = -EINVAL;
3638 +                               goto done;
3639 +                       }
3640 +                       req_get->name[IP_SET_MAXNAMELEN - 1] = '\0';
3641 +                       req_get->id = -1;
3642 +                       set = ip_set_get_byname(req_get->name, &req_get->id);
3643 +                       if (set) {
3644 +                               req_get->ref = set->ref - 1;
3645 +                               ip_set_put(set);
3646 +                       }
3647 +                       res = copy_to_user(user, data, copylen);
3648 +                       goto done;
3649 +               }
3650 +       case IP_SET_OP_GETSET_BYID: {
3651 +                       struct ip_set_req_get *req_get
3652 +                               = (struct ip_set_req_get *) data;
3653 +
3654 +                       if (*len != sizeof(struct ip_set_req_get)) {
3655 +                               ip_set_printk("short _BYID (want >=%d, got %d)",
3656 +                                              sizeof(struct ip_set_req_get), *len);
3657 +                               res = -EINVAL;
3658 +                               goto done;
3659 +                       }
3660 +                       set = ip_set_get_byid(req_get->id);
3661 +                       if (set) {
3662 +                               req_get->ref = set->ref - 1;
3663 +                               strncpy(req_get->name, set->name, IP_SET_MAXNAMELEN);
3664 +                               ip_set_put(set);
3665 +                       } else 
3666 +                               req_get->id = -1;
3667 +                       res = copy_to_user(user, data, copylen);
3668 +                       goto done;
3669 +               }
3670 +       default: 
3671 +               ; /* Requests with set id: fall trought */
3672 +       }
3673 +
3674 +       /* Requests with set id: */
3675 +       if (req_base->id < 0 || req_base->id >= max_sets) {
3676 +               res = -EINVAL;
3677 +               goto done;
3678 +       }
3679 +       set = ip_set_get_byid(req_base->id);    /* Reference lock */
3680 +       if (!set) {
3681 +               res = -ENOENT;
3682 +               goto done;
3683 +       }
3684 +
3685 +       DP("set %s (%d) (%u)", set->name, req_base->id, set->ref);
3686 +       req_std = (struct ip_set_req_std *) data;
3687 +       if (*len < sizeof(struct ip_set_req_std)) {
3688 +               ip_set_printk("short data in std request (want >%d, got %d)",
3689 +                             sizeof(struct ip_set_req_std), *len);
3690 +               goto put_inval;
3691 +       } else if (req_std->level >= set->levels) {
3692 +               res = -ERANGE;
3693 +               goto put_set;
3694 +       }
3695 +       
3696 +       switch (req_base->op) {
3697 +       case IP_SET_OP_TEST_IP:{
3698 +                       struct ip_set_req_test *req_test =
3699 +                               (struct ip_set_req_test *) data;
3700 +
3701 +                       if (*len < sizeof(struct ip_set_req_test)) {
3702 +                               ip_set_printk("short data in testip request (want >%d, got %d)",
3703 +                                             sizeof(struct ip_set_req_test), *len);
3704 +                               res = -EINVAL;
3705 +                               goto put_set;
3706 +                       }
3707 +                       req_test->reply = ip_set_testip(set,
3708 +                                           req_test->ip,
3709 +                                           req_test->level,
3710 +                                           data + sizeof(struct ip_set_req_test),
3711 +                                           *len - sizeof(struct  ip_set_req_test));
3712 +
3713 +                       DP("test result: %i", req_test->reply);
3714 +                       *len = copylen = sizeof(struct ip_set_req_test);
3715 +                       goto put_copy;
3716 +               }
3717 +       case IP_SET_OP_LIST_HEADER_SIZE:
3718 +       case IP_SET_OP_LIST_MEMBERS_SIZE:
3719 +       case IP_SET_OP_LIST_CHILDSETS_SIZE: {
3720 +                       struct ip_set_req_list *req_list =
3721 +                           (struct ip_set_req_list *) data;
3722 +
3723 +                       if (*len != sizeof(struct ip_set_req_list)) {
3724 +                               ip_set_printk("short LIST (want >=%d, got %d)",
3725 +                                             sizeof(struct ip_set_req_list),
3726 +                                             *len);
3727 +                               goto put_inval;
3728 +                       }
3729 +                       res =  ip_set_list_size(set,
3730 +                                               req_list->ip,
3731 +                                               req_list->level,
3732 +                                               &req_list->size,
3733 +                                               req_base->op);
3734 +                       DP("SIZEfoo size=%d", req_list->size);
3735 +                       if (res < 0)
3736 +                               goto put_set;   /* Error */
3737 +                       goto put_copy;
3738 +               }
3739 +       case IP_SET_OP_LIST_HEADER:
3740 +       case IP_SET_OP_LIST_MEMBERS:
3741 +       case IP_SET_OP_LIST_CHILDSETS:{
3742 +                       DP("LISTfoo before len=%d", *len);
3743 +                       res = ip_set_list_data(set,
3744 +                                              req_std->ip,
3745 +                                              req_std->level,
3746 +                                              data,
3747 +                                              len,
3748 +                                              req_base->op);
3749 +                       DP("LISTfoo done len=%d", *len);
3750 +
3751 +                       if (res < 0)
3752 +                               goto put_set;   /* Error */
3753 +
3754 +                       copylen = *len;         /* Only copy the mem used */
3755 +                       goto put_copy;
3756 +               }
3757 +       default:{
3758 +                       DP("unknown op %d", req_base->op);
3759 +                       ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3760 +                       goto put_inval;
3761 +               }
3762 +       }       /* end of switch(op) */
3763 +
3764 +    put_copy:
3765 +       ip_set_put(set);
3766 +       DP("set %s (%u)", set->name, set->ref);
3767 +       res = copy_to_user(user, data, copylen);
3768 +       goto done;
3769 +    put_inval:
3770 +       res = -EINVAL;
3771 +    put_set:
3772 +       ip_set_put(set);
3773 +       DP("set %s (%u)", set->name, set->ref);
3774 +    done:
3775 +       vfree(data);
3776 +       if (res > 0)
3777 +               res = 0;
3778 +       DP("final result %d", res);
3779 +       return res;
3780 +}
3781 +
3782 +static struct nf_sockopt_ops so_set = {
3783 +       .pf             = PF_INET,
3784 +       .set_optmin     = SO_IP_SET,
3785 +       .set_optmax     = SO_IP_SET + 1,
3786 +       .set            = &ip_set_sockfn_set,
3787 +       .get_optmin     = SO_IP_SET,
3788 +       .get_optmax     = SO_IP_SET + 1,
3789 +       .get            = &ip_set_sockfn_get,
3790 +       .use            = 0
3791 +};
3792 +
3793 +MODULE_PARM(max_sets, "i");
3794 +MODULE_PARM_DESC(max_sets, "maximal number of sets");
3795 +
3796 +static int __init init(void)
3797 +{
3798 +       int res;
3799 +
3800 +       if (max_sets <= 0)
3801 +               max_sets = CONFIG_IP_NF_SET_MAX;
3802 +       ip_set_list = vmalloc(sizeof(struct ip_set *) * max_sets);
3803 +       if (!ip_set_list) {
3804 +               printk(KERN_ERR "Unable to create ip_set_list\n");
3805 +               return -ENOMEM;
3806 +       }
3807 +       memset(ip_set_list, 0, sizeof(struct ip_set *) * max_sets);
3808 +       INIT_LIST_HEAD(&set_type_list);
3809 +
3810 +       res = nf_register_sockopt(&so_set);
3811 +       if (res != 0) {
3812 +               ip_set_printk("SO_SET registry failed: %d", res);
3813 +               vfree(ip_set_list);
3814 +               return res;
3815 +       }
3816 +       return 0;
3817 +}
3818 +
3819 +static void __exit fini(void)
3820 +{
3821 +       nf_unregister_sockopt(&so_set);
3822 +       vfree(ip_set_list);
3823 +       DP("these are the famous last words");
3824 +}
3825 +
3826 +EXPORT_SYMBOL(ip_set_register_set_type);
3827 +EXPORT_SYMBOL(ip_set_unregister_set_type);
3828 +
3829 +EXPORT_SYMBOL(ip_set_list);
3830 +EXPORT_SYMBOL(ip_set_get_byname);
3831 +EXPORT_SYMBOL(ip_set_get_byid);
3832 +EXPORT_SYMBOL(ip_set_put);
3833 +
3834 +EXPORT_SYMBOL(ip_set_addip_kernel);
3835 +EXPORT_SYMBOL(ip_set_delip_kernel);
3836 +EXPORT_SYMBOL(ip_set_testip_kernel);
3837 +
3838 +module_init(init);
3839 +module_exit(fini);
3840 +MODULE_LICENSE("GPL");
3841 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.3/net/ipv4/netfilter/ip_set_iphash.c
3842 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_iphash.c  1970-01-01 01:00:00.000000000 +0100
3843 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_iphash.c      2004-02-09 15:02:00.000000000 +0100
3844 @@ -0,0 +1,319 @@
3845 +/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
3846 + *
3847 + * This program is free software; you can redistribute it and/or modify   
3848 + * it under the terms of the GNU General Public License as published by   
3849 + * the Free Software Foundation; either version 2 of the License, or      
3850 + * (at your option) any later version.                                    
3851 + *                                                                         
3852 + * This program is distributed in the hope that it will be useful,        
3853 + * but WITHOUT ANY WARRANTY; without even the implied warranty of         
3854 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
3855 + * GNU General Public License for more details.                           
3856 + *                                                                         
3857 + * You should have received a copy of the GNU General Public License      
3858 + * along with this program; if not, write to the Free Software            
3859 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3860 + */
3861 +
3862 +/* Kernel module implementing an ip hash set */
3863 +
3864 +#include <linux/module.h>
3865 +#include <linux/ip.h>
3866 +#include <linux/skbuff.h>
3867 +#include <linux/netfilter_ipv4/ip_tables.h>
3868 +#include <linux/netfilter_ipv4/ip_set.h>
3869 +#include <linux/errno.h>
3870 +#include <asm/uaccess.h>
3871 +#include <asm/bitops.h>
3872 +#include <asm/softirq.h>
3873 +#include <linux/spinlock.h>
3874 +#include <linux/vmalloc.h>
3875 +
3876 +#include <net/ip.h>
3877 +
3878 +#include <linux/netfilter_ipv4/ip_set_iphash.h>
3879 +#include <linux/netfilter_ipv4/ip_set_jhash.h>
3880 +
3881 +static inline ip_set_ip_t
3882 +hash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
3883 +{
3884 +       return (jhash_1word(ip & map->netmask, map->initval) % map->hashsize);
3885 +}
3886 +
3887 +static inline int
3888 +__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3889 +{
3890 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3891 +
3892 +       *id = hash_ip(map, ip);
3893 +       return (map->members[*id] == ip);
3894 +}
3895 +
3896 +static int
3897 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3898 +{
3899 +       return __testip(private, ip, id);
3900 +}
3901 +
3902 +static int
3903 +testip(struct ip_set_private *private, const void *data, size_t size,
3904 +       ip_set_ip_t *id)
3905 +{
3906 +       struct ip_set_req_iphash *req = 
3907 +           (struct ip_set_req_iphash *) data;
3908 +
3909 +       if (size != sizeof(struct ip_set_req_iphash)) {
3910 +               ip_set_printk("data length wrong (want %d, have %d)",
3911 +                             sizeof(struct ip_set_req_iphash),
3912 +                             size);
3913 +               return -EINVAL;
3914 +       }
3915 +       return __testip(private, req->ip, id);
3916 +}
3917 +
3918 +static int
3919 +testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3920 +               u_int32_t flags, ip_set_ip_t *id)
3921 +{
3922 +       if (!(flags & IPSET_TYPE_IP))
3923 +               return -EINVAL;
3924 +                 
3925 +       return __testip(private,
3926 +                       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
3927 +                                               : skb->nh.iph->daddr),
3928 +                       id);
3929 +}
3930 +
3931 +static inline int
3932 +__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id,
3933 +        u_int32_t flags)
3934 +{
3935 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3936 +
3937 +       *id = hash_ip(map, ip);
3938 +
3939 +       if (map->members[*id] == ip)
3940 +               return -EEXIST;
3941 +
3942 +       if (map->members[*id] != 0 && !(flags & IPSET_ADD_OVERWRITE))
3943 +               return -EADDRINUSE;
3944 +
3945 +       map->members[*id] = ip;
3946 +       return 0;
3947 +}
3948 +
3949 +static int
3950 +addip(struct ip_set_private *private, const void *data, size_t size,
3951 +        ip_set_ip_t *id)
3952 +{
3953 +       struct ip_set_req_iphash *req = 
3954 +           (struct ip_set_req_iphash *) data;
3955 +
3956 +       if (size != sizeof(struct ip_set_req_iphash)) {
3957 +               ip_set_printk("data length wrong (want %d, have %d)",
3958 +                             sizeof(struct ip_set_req_iphash),
3959 +                             size);
3960 +               return -EINVAL;
3961 +       }
3962 +       return __addip(private, req->ip, id, req->flags);
3963 +}
3964 +
3965 +static int
3966 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3967 +            u_int32_t flags, ip_set_ip_t *id)
3968 +{
3969 +       if (!(flags & IPSET_TYPE_IP))
3970 +               return -EINVAL;
3971 +                 
3972 +       return __addip(private,
3973 +                      ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
3974 +                                              : skb->nh.iph->daddr),
3975 +                      id,
3976 +                      flags);
3977 +}
3978 +
3979 +static inline int
3980 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3981 +{
3982 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3983 +
3984 +       *id = hash_ip(map, ip);
3985 +
3986 +       if (map->members[*id] == 0)
3987 +               return -EEXIST;
3988 +
3989 +       if (map->members[*id] != ip)
3990 +               return -EADDRINUSE;
3991 +
3992 +       map->members[*id] = 0;
3993 +       return 0;
3994 +}
3995 +
3996 +static int
3997 +delip(struct ip_set_private *private, const void *data, size_t size,
3998 +        ip_set_ip_t *id)
3999 +{
4000 +       struct ip_set_req_iphash *req =
4001 +           (struct ip_set_req_iphash *) data;
4002 +
4003 +       if (size != sizeof(struct ip_set_req_iphash)) {
4004 +               ip_set_printk("data length wrong (want %d, have %d)",
4005 +                             sizeof(struct ip_set_req_iphash),
4006 +                             size);
4007 +               return -EINVAL;
4008 +       }
4009 +       return __delip(private, req->ip, id);
4010 +}
4011 +
4012 +static int
4013 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4014 +              u_int32_t flags, ip_set_ip_t *id)
4015 +{
4016 +       if (!(flags & IPSET_TYPE_IP))
4017 +               return -EINVAL;
4018 +                 
4019 +       return __delip(private,
4020 +                      ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
4021 +                                              : skb->nh.iph->daddr),
4022 +                      id);
4023 +}
4024 +
4025 +static int create(struct ip_set_private **private, const void *data, size_t size)
4026 +{
4027 +       int newbytes;
4028 +       struct ip_set_req_iphash_create *req =
4029 +           (struct ip_set_req_iphash_create *) data;
4030 +       struct ip_set_iphash *map;
4031 +
4032 +       if (size != sizeof(struct ip_set_req_iphash_create)) {
4033 +               ip_set_printk("data length wrong (want %d, have %d)",
4034 +                              sizeof(struct ip_set_req_iphash_create),
4035 +                              size);
4036 +               return -EINVAL;
4037 +       }
4038 +
4039 +       if (req->hashsize > MAX_RANGE) {
4040 +               ip_set_printk("hashsize too big (max %d)",
4041 +                              MAX_RANGE);
4042 +               return -ERANGE;
4043 +       }
4044 +
4045 +       if (req->hashsize < 1) {
4046 +               ip_set_printk("hashsize too small");
4047 +               return -ERANGE;
4048 +       }
4049 +
4050 +       map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
4051 +       if (!map) {
4052 +               DP("out of memory for %d bytes",
4053 +                  sizeof(struct ip_set_iphash));
4054 +               return -ENOMEM;
4055 +       }
4056 +       map->initval = req->initval;
4057 +       map->hashsize = req->hashsize;
4058 +       map->netmask = req->netmask;
4059 +       newbytes = map->hashsize * sizeof(ip_set_ip_t);
4060 +       map->members = vmalloc(newbytes);
4061 +       if (!map->members) {
4062 +               DP("out of memory for %d bytes", newbytes);
4063 +               kfree(map);
4064 +               return -ENOMEM;
4065 +       }
4066 +       memset(map->members, 0, newbytes);
4067 +
4068 +       *private = (struct ip_set_private *) map;
4069 +       return 0;
4070 +}
4071 +
4072 +static void destroy(struct ip_set_private **private)
4073 +{
4074 +       struct ip_set_iphash *map = (struct ip_set_iphash *) *private;
4075 +
4076 +       vfree(map->members);
4077 +       kfree(map);
4078 +
4079 +       *private = NULL;
4080 +}
4081 +
4082 +static void flush(struct ip_set_private *private)
4083 +{
4084 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4085 +       memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
4086 +}
4087 +
4088 +static int list_header_size(const struct ip_set_private *private)
4089 +{
4090 +       return sizeof(struct ip_set_req_iphash_create);
4091 +}
4092 +
4093 +static void list_header(const struct ip_set_private *private, void *data)
4094 +{
4095 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4096 +       struct ip_set_req_iphash_create *header =
4097 +           (struct ip_set_req_iphash_create *) data;
4098 +
4099 +       header->initval = map->initval;
4100 +       header->hashsize = map->hashsize;
4101 +       header->netmask = map->netmask;
4102 +}
4103 +
4104 +static int list_members_size(const struct ip_set_private *private)
4105 +{
4106 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4107 +
4108 +       return (map->hashsize * sizeof(ip_set_ip_t));
4109 +}
4110 +
4111 +static void list_members(const struct ip_set_private *private, void *data)
4112 +{
4113 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4114 +
4115 +       int bytes = map->hashsize * sizeof(ip_set_ip_t);
4116 +
4117 +       memcpy(data, map->members, bytes);
4118 +}
4119 +
4120 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4121 +{
4122 +       struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4123 +
4124 +       return (map->hashsize);
4125 +}
4126 +
4127 +static struct ip_set_type ip_set_iphash = {
4128 +       .typename               = SETTYPE_NAME,
4129 +       .typecode               = IPSET_TYPE_IP,
4130 +       .protocol_version       = IP_SET_PROTOCOL_VERSION,
4131 +       .create                 = &create,
4132 +       .destroy                = &destroy,
4133 +       .flush                  = &flush,
4134 +       .reqsize                = sizeof(struct ip_set_req_iphash),
4135 +       .addip                  = &addip,
4136 +       .addip_kernel           = &addip_kernel,
4137 +       .delip                  = &delip,
4138 +       .delip_kernel           = &delip_kernel,
4139 +       .matchip                = &matchip,
4140 +       .testip                 = &testip,
4141 +       .testip_kernel          = &testip_kernel,
4142 +       .list_header_size       = &list_header_size,
4143 +       .list_header            = &list_header,
4144 +       .list_members_size      = &list_members_size,
4145 +       .list_members           = &list_members,
4146 +       .sizeid                 = &sizeid,
4147 +       .me                     = THIS_MODULE,
4148 +};
4149 +
4150 +static int __init init(void)
4151 +{
4152 +       return ip_set_register_set_type(&ip_set_iphash);
4153 +}
4154 +
4155 +static void __exit fini(void)
4156 +{
4157 +       /* FIXME: possible race with ip_set_create() */
4158 +       ip_set_unregister_set_type(&ip_set_iphash);
4159 +}
4160 +
4161 +module_init(init);
4162 +module_exit(fini);
4163 +MODULE_LICENSE("GPL");
4164 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_ipmap.c
4165 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_ipmap.c   1970-01-01 01:00:00.000000000 +0100
4166 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_ipmap.c       2004-02-09 15:02:00.000000000 +0100
4167 @@ -0,0 +1,348 @@
4168 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4169 + *                     Patrick Schaaf (bof@bof.de)
4170 + *                     Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4171 + *
4172 + * This program is free software; you can redistribute it and/or modify   
4173 + * it under the terms of the GNU General Public License as published by   
4174 + * the Free Software Foundation; either version 2 of the License, or      
4175 + * (at your option) any later version.                                    
4176 + *                                                                         
4177 + * This program is distributed in the hope that it will be useful,        
4178 + * but WITHOUT ANY WARRANTY; without even the implied warranty of         
4179 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
4180 + * GNU General Public License for more details.                           
4181 + *                                                                         
4182 + * You should have received a copy of the GNU General Public License      
4183 + * along with this program; if not, write to the Free Software            
4184 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4185 + */
4186 +
4187 +/* Kernel module implementing an IP set type: the single bitmap type */
4188 +
4189 +#include <linux/module.h>
4190 +#include <linux/ip.h>
4191 +#include <linux/skbuff.h>
4192 +#include <linux/netfilter_ipv4/ip_tables.h>
4193 +#include <linux/netfilter_ipv4/ip_set.h>
4194 +#include <linux/errno.h>
4195 +#include <asm/uaccess.h>
4196 +#include <asm/bitops.h>
4197 +#include <asm/softirq.h>
4198 +#include <linux/spinlock.h>
4199 +
4200 +#include <linux/netfilter_ipv4/ip_set_ipmap.h>
4201 +
4202 +static inline ip_set_ip_t
4203 +ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
4204 +{
4205 +       return ((ip & map->netmask) - map->first_ip)/map->hosts;
4206 +}
4207 +
4208 +static inline int
4209 +__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4210 +{
4211 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4212 +       
4213 +       if (ip < map->first_ip || ip > map->last_ip)
4214 +               return -ERANGE;
4215 +
4216 +       *id = ip_to_id(map, ip);
4217 +       return !!test_bit(*id, map->members);
4218 +}
4219 +
4220 +static int
4221 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4222 +{
4223 +       return __testip(private, ip, id);
4224 +}
4225 +
4226 +static int
4227 +testip(struct ip_set_private *private, const void *data, size_t size,
4228 +       ip_set_ip_t *id)
4229 +{
4230 +       struct ip_set_req_ipmap *req = 
4231 +           (struct ip_set_req_ipmap *) data;
4232 +
4233 +       if (size != sizeof(struct ip_set_req_ipmap)) {
4234 +               ip_set_printk("data length wrong (want %d, have %d)",
4235 +                             sizeof(struct ip_set_req_ipmap),
4236 +                             size);
4237 +               return -EINVAL;
4238 +       }
4239 +       return __testip(private, req->ip, id);
4240 +}
4241 +
4242 +static int
4243 +testip_kernel(struct ip_set_private *private, 
4244 +             const struct sk_buff *skb,
4245 +             u_int32_t flags,
4246 +             ip_set_ip_t *id)
4247 +{
4248 +       if (!(flags & IPSET_TYPE_IP))
4249 +               return -EINVAL;
4250 +       
4251 +       DP("flags: %u (%s) ip %u.%u.%u.%u", flags,
4252 +          flags & IPSET_SRC ? "SRC" : "DST",
4253 +          NIPQUAD(skb->nh.iph->saddr));
4254 +       DP("flags: %u (%s) ip %u.%u.%u.%u", flags,        
4255 +          flags & IPSET_SRC ? "SRC" : "DST",
4256 +          NIPQUAD(skb->nh.iph->daddr));
4257 +
4258 +       return __testip(private,
4259 +                       ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
4260 +                                               : skb->nh.iph->daddr),
4261 +                       id);
4262 +}
4263 +
4264 +static inline int
4265 +__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4266 +{
4267 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4268 +
4269 +       if (ip < map->first_ip || ip > map->last_ip)
4270 +               return -ERANGE;
4271 +
4272 +       *id = ip_to_id(map, ip);
4273 +       if (test_and_set_bit(*id, map->members))
4274 +               return -EEXIST;
4275 +
4276 +       return 0;
4277 +}
4278 +
4279 +static int
4280 +addip(struct ip_set_private *private, const void *data, size_t size,
4281 +      ip_set_ip_t *id)
4282 +{
4283 +       struct ip_set_req_ipmap *req = 
4284 +           (struct ip_set_req_ipmap *) data;
4285 +
4286 +       if (size != sizeof(struct ip_set_req_ipmap)) {
4287 +               ip_set_printk("data length wrong (want %d, have %d)",
4288 +                             sizeof(struct ip_set_req_ipmap),
4289 +                             size);
4290 +               return -EINVAL;
4291 +       }
4292 +       DP("%u.%u.%u.%u", NIPQUAD(req->ip));
4293 +       return __addip(private, req->ip, id);
4294 +}
4295 +
4296 +static int
4297 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4298 +            u_int32_t flags, ip_set_ip_t *id)
4299 +{
4300 +       if (!(flags & IPSET_TYPE_IP))
4301 +               return -EINVAL;
4302 +                 
4303 +       return __addip(private,
4304 +                      ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
4305 +                                              : skb->nh.iph->daddr),
4306 +                      id);
4307 +}
4308 +
4309 +static inline int 
4310 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4311 +{
4312 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4313 +
4314 +       if (ip < map->first_ip || ip > map->last_ip)
4315 +               return -ERANGE;
4316 +
4317 +       *id = ip_to_id(map, ip);
4318 +       if (!test_and_clear_bit(*id, map->members))
4319 +               return -EEXIST;
4320 +       
4321 +       return 0;
4322 +}
4323 +
4324 +static int
4325 +delip(struct ip_set_private *private, const void *data, size_t size,
4326 +      ip_set_ip_t *id)
4327 +{
4328 +       struct ip_set_req_ipmap *req =
4329 +           (struct ip_set_req_ipmap *) data;
4330 +
4331 +       if (size != sizeof(struct ip_set_req_ipmap)) {
4332 +               ip_set_printk("data length wrong (want %d, have %d)",
4333 +                             sizeof(struct ip_set_req_ipmap),
4334 +                             size);
4335 +               return -EINVAL;
4336 +       }
4337 +       return __delip(private, req->ip, id);
4338 +}
4339 +
4340 +static int
4341 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4342 +            u_int32_t flags, ip_set_ip_t *id)
4343 +{
4344 +       if (!(flags & IPSET_TYPE_IP))
4345 +               return -EINVAL;
4346 +                 
4347 +       return __delip(private,
4348 +                      ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
4349 +                                              : skb->nh.iph->daddr),
4350 +                      id);
4351 +}
4352 +
4353 +static int create(struct ip_set_private **private, const void *data, size_t size)
4354 +{
4355 +       int newbytes;
4356 +       struct ip_set_req_ipmap_create *req =
4357 +           (struct ip_set_req_ipmap_create *) data;
4358 +       struct ip_set_ipmap *map;
4359 +
4360 +       if (size != sizeof(struct ip_set_req_ipmap_create)) {
4361 +               ip_set_printk("data length wrong (want %d, have %d)",
4362 +                             sizeof(struct ip_set_req_ipmap_create),
4363 +                             size);
4364 +               return -EINVAL;
4365 +       }
4366 +
4367 +       DP("from 0x%08x to 0x%08x", req->from, req->to);
4368 +
4369 +       if (req->from > req->to) {
4370 +               DP("bad ip range");
4371 +               return -EINVAL;
4372 +       }
4373 +
4374 +       if (req->to - req->from > MAX_RANGE) {
4375 +               ip_set_printk("range too big (max %d addresses)",
4376 +                              MAX_RANGE);
4377 +               return -ERANGE;
4378 +       }
4379 +
4380 +       map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
4381 +       if (!map) {
4382 +               DP("out of memory for %d bytes",
4383 +                  sizeof(struct ip_set_ipmap));
4384 +               return -ENOMEM;
4385 +       }
4386 +       map->first_ip = req->from;
4387 +       map->last_ip = req->to;
4388 +       map->netmask = req->netmask;
4389 +
4390 +       if (req->netmask == 0xFFFFFFFF) {
4391 +               map->hosts = 1;
4392 +               map->sizeid = map->last_ip - map->first_ip + 1;
4393 +       } else {
4394 +               unsigned int mask_bits, netmask_bits;
4395 +               ip_set_ip_t mask;
4396 +               
4397 +               map->first_ip &= map->netmask;  /* Should we better bark? */
4398 +               
4399 +               mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
4400 +               netmask_bits = mask_to_bits(map->netmask);
4401 +               
4402 +               if (!mask || netmask_bits <= mask_bits)
4403 +                       return -EINVAL;
4404 +
4405 +               map->hosts = 2 << (32 - netmask_bits - 1);
4406 +               map->sizeid = 2 << (netmask_bits - mask_bits - 1);
4407 +       }
4408 +       newbytes = bitmap_bytes(0, map->sizeid - 1);
4409 +       DP("%x %x %i", map->first_ip, map->last_ip, newbytes);
4410 +       map->members = kmalloc(newbytes, GFP_KERNEL);
4411 +       if (!map->members) {
4412 +               DP("out of memory for %d bytes", newbytes);
4413 +               kfree(map);
4414 +               return -ENOMEM;
4415 +       }
4416 +       memset(map->members, 0, newbytes);
4417 +       
4418 +       *private = (struct ip_set_private *) map;
4419 +       return 0;
4420 +}
4421 +
4422 +static void destroy(struct ip_set_private **private)
4423 +{
4424 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) *private;
4425 +       
4426 +       kfree(map->members);
4427 +       kfree(map);
4428 +       
4429 +       *private = NULL;
4430 +}
4431 +
4432 +static void flush(struct ip_set_private *private)
4433 +{
4434 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4435 +       memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
4436 +}
4437 +
4438 +static int list_header_size(const struct ip_set_private *private)
4439 +{
4440 +       return sizeof(struct ip_set_req_ipmap_create);
4441 +}
4442 +
4443 +static void list_header(const struct ip_set_private *private, void *data)
4444 +{
4445 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4446 +       struct ip_set_req_ipmap_create *header =
4447 +           (struct ip_set_req_ipmap_create *) data;
4448 +
4449 +       DP("list_header %x %x", map->first_ip, map->last_ip);
4450 +
4451 +       header->from = map->first_ip;
4452 +       header->to = map->last_ip;
4453 +       header->netmask = map->netmask;
4454 +}
4455 +
4456 +static int list_members_size(const struct ip_set_private *private)
4457 +{
4458 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4459 +
4460 +       return bitmap_bytes(0, map->sizeid - 1);
4461 +}
4462 +
4463 +static void list_members(const struct ip_set_private *private, void *data)
4464 +{
4465 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4466 +
4467 +       int bytes = bitmap_bytes(0, map->sizeid - 1);
4468 +
4469 +       memcpy(data, map->members, bytes);
4470 +}
4471 +
4472 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4473 +{
4474 +       struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4475 +
4476 +       return (map->sizeid);
4477 +}
4478 +
4479 +static struct ip_set_type ip_set_ipmap = {
4480 +       .typename               = SETTYPE_NAME,
4481 +       .typecode               = IPSET_TYPE_IP,
4482 +       .protocol_version       = IP_SET_PROTOCOL_VERSION,
4483 +       .create                 = &create,
4484 +       .destroy                = &destroy,
4485 +       .flush                  = &flush,
4486 +       .reqsize                = sizeof(struct ip_set_req_ipmap),
4487 +       .addip                  = &addip,
4488 +       .addip_kernel           = &addip_kernel,
4489 +       .delip                  = &delip,
4490 +       .delip_kernel           = &delip_kernel,
4491 +       .matchip                = &matchip,
4492 +       .testip                 = &testip,
4493 +       .testip_kernel          = &testip_kernel,
4494 +       .list_header_size       = &list_header_size,
4495 +       .list_header            = &list_header,
4496 +       .list_members_size      = &list_members_size,
4497 +       .list_members           = &list_members,
4498 +       .sizeid                 = &sizeid,
4499 +       .me                     = THIS_MODULE,
4500 +};
4501 +
4502 +static int __init init(void)
4503 +{
4504 +       return ip_set_register_set_type(&ip_set_ipmap);
4505 +}
4506 +
4507 +static void __exit fini(void)
4508 +{
4509 +       /* FIXME: possible race with ip_set_create() */
4510 +       ip_set_unregister_set_type(&ip_set_ipmap);
4511 +}
4512 +
4513 +module_init(init);
4514 +module_exit(fini);
4515 +MODULE_LICENSE("GPL");
4516 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_macipmap.c
4517 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_macipmap.c        1970-01-01 01:00:00.000000000 +0100
4518 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_macipmap.c    2004-02-09 15:02:00.000000000 +0100
4519 @@ -0,0 +1,371 @@
4520 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4521 + *                     Patrick Schaaf (bof@bof.de)
4522 + *                     Martin Josefsson (gandalf@wlug.westbo.se)
4523 + *
4524 + * This program is free software; you can redistribute it and/or modify   
4525 + * it under the terms of the GNU General Public License as published by   
4526 + * the Free Software Foundation; either version 2 of the License, or      
4527 + * (at your option) any later version.                                    
4528 + *                                                                         
4529 + * This program is distributed in the hope that it will be useful,        
4530 + * but WITHOUT ANY WARRANTY; without even the implied warranty of         
4531 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
4532 + * GNU General Public License for more details.                           
4533 + *                                                                         
4534 + * You should have received a copy of the GNU General Public License      
4535 + * along with this program; if not, write to the Free Software            
4536 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4537 + */
4538 +
4539 +/* Kernel module implementing an IP set type: the macipmap type */
4540 +
4541 +#include <linux/module.h>
4542 +#include <linux/ip.h>
4543 +#include <linux/skbuff.h>
4544 +#include <linux/netfilter_ipv4/ip_tables.h>
4545 +#include <linux/netfilter_ipv4/ip_set.h>
4546 +#include <linux/errno.h>
4547 +#include <asm/uaccess.h>
4548 +#include <asm/bitops.h>
4549 +#include <asm/softirq.h>
4550 +#include <linux/spinlock.h>
4551 +#include <linux/if_ether.h>
4552 +#include <linux/vmalloc.h>
4553 +
4554 +#include <linux/netfilter_ipv4/ip_set_macipmap.h>
4555 +
4556 +static int
4557 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4558 +{
4559 +       struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4560 +       struct ip_set_macip *table =
4561 +           (struct ip_set_macip *) map->members;
4562 +       
4563 +       if (ip < map->first_ip || ip > map->last_ip)
4564 +               return -ERANGE;
4565 +
4566 +       *id = ip - map->first_ip;
4567 +       return !!test_bit(IPSET_MACIP_ISSET, &table[*id].flags);
4568 +}
4569 +
4570 +static int
4571 +testip(struct ip_set_private *private, const void *data, size_t size,
4572 +       ip_set_ip_t *id)
4573 +{
4574 +       struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4575 +       struct ip_set_macip *table =
4576 +           (struct ip_set_macip *) map->members;
4577 +       
4578 +       struct ip_set_req_macipmap *req =
4579 +           (struct ip_set_req_macipmap *) data;
4580 +
4581 +       if (size != sizeof(struct ip_set_req_macipmap)) {
4582 +               ip_set_printk("data length wrong (want %d, have %d)",
4583 +                             sizeof(struct ip_set_req_macipmap),
4584 +                             size);
4585 +               return -EINVAL;
4586 +       }
4587 +
4588 +       if (req->ip < map->first_ip || req->ip > map->last_ip)
4589 +               return -ERANGE;
4590 +
4591 +       *id = req->ip - map->first_ip;
4592 +       if (test_bit(IPSET_MACIP_ISSET, &table[*id].flags)) {
4593 +               /* Is mac pointer valid?
4594 +                * If so, compare... */
4595 +               return (memcmp(req->ethernet,
4596 +                              &table[*id].ethernet,
4597 +                              ETH_ALEN) == 0);
4598 +       } else {
4599 +               return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4600 +       }
4601 +}
4602 +
4603 +static int
4604 +testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4605 +             u_int32_t flags, ip_set_ip_t *id)
4606 +{
4607 +       struct ip_set_macipmap *map =
4608 +           (struct ip_set_macipmap *) private;
4609 +       struct ip_set_macip *table =
4610 +           (struct ip_set_macip *) map->members;
4611 +       ip_set_ip_t ip;
4612 +       
4613 +       if (!(flags & IPSET_TYPE_IP))
4614 +               return -EINVAL;
4615 +                 
4616 +       ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4617 +                                    : skb->nh.iph->daddr);
4618 +
4619 +       if (ip < map->first_ip || ip > map->last_ip)
4620 +               return -ERANGE;
4621 +
4622 +       *id = ip - map->first_ip;
4623 +       if (test_bit(IPSET_MACIP_ISSET, &table[*id].flags)) {
4624 +               /* Is mac pointer valid?
4625 +                * If so, compare... */
4626 +               return (skb->mac.raw >= skb->head
4627 +                       && (skb->mac.raw + ETH_HLEN) <= skb->data
4628 +                       && (memcmp(skb->mac.ethernet->h_source,
4629 +                                  &table[*id].ethernet,
4630 +                                  ETH_ALEN) == 0));
4631 +       } else {
4632 +               return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4633 +       }
4634 +}
4635 +
4636 +/* returns 0 on success */
4637 +static inline int
4638 +__addip(struct ip_set_private *private, 
4639 +       ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *id)
4640 +{
4641 +       struct ip_set_macipmap *map =
4642 +           (struct ip_set_macipmap *) private;
4643 +       struct ip_set_macip *table =
4644 +           (struct ip_set_macip *) map->members;
4645 +
4646 +       if (ip < map->first_ip || ip > map->last_ip)
4647 +               return -ERANGE;
4648 +       if (test_and_set_bit(IPSET_MACIP_ISSET, 
4649 +                            &table[ip - map->first_ip].flags))
4650 +               return -EEXIST;
4651 +
4652 +       *id = ip - map->first_ip;
4653 +       memcpy(&table[*id].ethernet, ethernet, ETH_ALEN);
4654 +       return 0;
4655 +}
4656 +
4657 +static int
4658 +addip(struct ip_set_private *private, const void *data, size_t size,
4659 +      ip_set_ip_t *id)
4660 +{
4661 +       struct ip_set_req_macipmap *req =
4662 +           (struct ip_set_req_macipmap *) data;
4663 +
4664 +       if (size != sizeof(struct ip_set_req_macipmap)) {
4665 +               ip_set_printk("data length wrong (want %d, have %d)",
4666 +                             sizeof(struct ip_set_req_macipmap),
4667 +                             size);
4668 +               return -EINVAL;
4669 +       }
4670 +       return __addip(private, req->ip, req->ethernet, id);
4671 +}
4672 +
4673 +static int
4674 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4675 +            u_int32_t flags, ip_set_ip_t *id)
4676 +{
4677 +       ip_set_ip_t ip;
4678 +       
4679 +       if (!(flags & IPSET_TYPE_IP))
4680 +               return -EINVAL;
4681 +                 
4682 +       ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4683 +                                    : skb->nh.iph->daddr);
4684 +
4685 +       if (!(skb->mac.raw >= skb->head
4686 +             && (skb->mac.raw + ETH_HLEN) <= skb->data))
4687 +               return -EINVAL;
4688 +
4689 +       return __addip(private, ip, skb->mac.ethernet->h_source, id);
4690 +}
4691 +
4692 +static inline int
4693 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4694 +{
4695 +       struct ip_set_macipmap *map =
4696 +           (struct ip_set_macipmap *) private;
4697 +       struct ip_set_macip *table =
4698 +           (struct ip_set_macip *) map->members;
4699 +
4700 +       if (ip < map->first_ip || ip > map->last_ip)
4701 +               return -ERANGE;
4702 +       if (!test_and_clear_bit(IPSET_MACIP_ISSET, 
4703 +                               &table[ip - map->first_ip].flags))
4704 +               return -EEXIST;
4705 +
4706 +       *id = ip - map->first_ip;
4707 +       return 0;
4708 +}
4709 +
4710 +static int
4711 +delip(struct ip_set_private *private, const void *data, size_t size,
4712 +     ip_set_ip_t *id)
4713 +{
4714 +       struct ip_set_req_macipmap *req =
4715 +           (struct ip_set_req_macipmap *) data;
4716 +
4717 +       if (size != sizeof(struct ip_set_req_macipmap)) {
4718 +               ip_set_printk("data length wrong (want %d, have %d)",
4719 +                             sizeof(struct ip_set_req_macipmap),
4720 +                             size);
4721 +               return -EINVAL;
4722 +       }
4723 +       return __delip(private, req->ip, id);
4724 +}
4725 +
4726 +static int
4727 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4728 +            u_int32_t flags, ip_set_ip_t *id)
4729 +{
4730 +       if (!(flags & IPSET_TYPE_IP))
4731 +               return -EINVAL;
4732 +                 
4733 +       return __delip(private,
4734 +                      ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr 
4735 +                                              : skb->nh.iph->daddr),
4736 +                      id);
4737 +}
4738 +
4739 +static int create(struct ip_set_private **private, const void *data, size_t size)
4740 +{
4741 +       int newbytes;
4742 +       struct ip_set_req_macipmap_create *req =
4743 +           (struct ip_set_req_macipmap_create *) data;
4744 +       struct ip_set_macipmap *map;
4745 +
4746 +       if (size != sizeof(struct ip_set_req_macipmap_create)) {
4747 +               ip_set_printk("data length wrong (want %d, have %d)",
4748 +                             sizeof(struct ip_set_req_macipmap_create),
4749 +                             size);
4750 +               return -EINVAL;
4751 +       }
4752 +
4753 +       DP("from 0x%08x to 0x%08x", req->from, req->to);
4754 +
4755 +       if (req->from > req->to) {
4756 +               DP("bad ip range");
4757 +               return -EINVAL;
4758 +       }
4759 +
4760 +       if (req->to - req->from > MAX_RANGE) {
4761 +               ip_set_printk("range too big (max %d addresses)",
4762 +                              MAX_RANGE);
4763 +               return -ERANGE;
4764 +       }
4765 +
4766 +       map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
4767 +       if (!map) {
4768 +               DP("out of memory for %d bytes",
4769 +                  sizeof(struct ip_set_macipmap));
4770 +               return -ENOMEM;
4771 +       }
4772 +       map->flags = req->flags;
4773 +       map->first_ip = req->from;
4774 +       map->last_ip = req->to;
4775 +       newbytes = (req->to - req->from + 1) * sizeof(struct ip_set_macip);
4776 +       map->members = vmalloc(newbytes);
4777 +       if (!map->members) {
4778 +               DP("out of memory for %d bytes", newbytes);
4779 +               kfree(map);
4780 +               return -ENOMEM;
4781 +       }
4782 +       memset(map->members, 0, newbytes);
4783 +       
4784 +       *private = (struct ip_set_private *) map;
4785 +       return 0;
4786 +}
4787 +
4788 +static void destroy(struct ip_set_private **private)
4789 +{
4790 +       struct ip_set_macipmap *map =
4791 +           (struct ip_set_macipmap *) *private;
4792 +
4793 +       vfree(map->members);
4794 +       kfree(map);
4795 +
4796 +       *private = NULL;
4797 +}
4798 +
4799 +static void flush(struct ip_set_private *private)
4800 +{
4801 +       struct ip_set_macipmap *map =
4802 +           (struct ip_set_macipmap *) private;
4803 +       memset(map->members, 0, (map->last_ip - map->first_ip)
4804 +              * sizeof(struct ip_set_macip));
4805 +}
4806 +
4807 +static int list_header_size(const struct ip_set_private *private)
4808 +{
4809 +       return sizeof(struct ip_set_req_macipmap_create);
4810 +}
4811 +
4812 +static void list_header(const struct ip_set_private *private, void *data)
4813 +{
4814 +       struct ip_set_macipmap *map =
4815 +           (struct ip_set_macipmap *) private;
4816 +       struct ip_set_req_macipmap_create *header =
4817 +           (struct ip_set_req_macipmap_create *) data;
4818 +
4819 +       DP("list_header %x %x %u", map->first_ip, map->last_ip,
4820 +          map->flags);
4821 +
4822 +       header->from = map->first_ip;
4823 +       header->to = map->last_ip;
4824 +       header->flags = map->flags;
4825 +}
4826 +
4827 +static int list_members_size(const struct ip_set_private *private)
4828 +{
4829 +       struct ip_set_macipmap *map =
4830 +           (struct ip_set_macipmap *) private;
4831 +
4832 +       return (map->last_ip
4833 +               - map->first_ip + 1) * sizeof(struct ip_set_macip);
4834 +}
4835 +
4836 +static void list_members(const struct ip_set_private *private, void *data)
4837 +{
4838 +       struct ip_set_macipmap *map =
4839 +           (struct ip_set_macipmap *) private;
4840 +
4841 +       int bytes = (map->last_ip - 
4842 +                    - map->first_ip + 1) * sizeof(struct ip_set_macip);
4843 +
4844 +       memcpy(data, map->members, bytes);
4845 +}
4846 +
4847 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4848 +{
4849 +       struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4850 +
4851 +       return (map->last_ip - map->first_ip + 1);
4852 +}
4853 +
4854 +static struct ip_set_type ip_set_macipmap = {
4855 +       .typename               = SETTYPE_NAME,
4856 +       .typecode               = IPSET_TYPE_IP,
4857 +       .protocol_version       = IP_SET_PROTOCOL_VERSION,
4858 +       .create                 = &create,
4859 +       .destroy                = &destroy,
4860 +       .flush                  = &flush,
4861 +       .reqsize                = sizeof(struct ip_set_req_macipmap),
4862 +       .addip                  = &addip,
4863 +       .addip_kernel           = &addip_kernel,
4864 +       .delip                  = &delip,
4865 +       .delip_kernel           = &delip_kernel,
4866 +       .matchip                = &matchip,
4867 +       .testip                 = &testip,
4868 +       .testip_kernel          = &testip_kernel,
4869 +       .list_header_size       = &list_header_size,
4870 +       .list_header            = &list_header,
4871 +       .list_members_size      = &list_members_size,
4872 +       .list_members           = &list_members,
4873 +       .sizeid                 = &sizeid,
4874 +       .me                     = THIS_MODULE,
4875 +};
4876 +
4877 +static int __init init(void)
4878 +{
4879 +       return ip_set_register_set_type(&ip_set_macipmap);
4880 +}
4881 +
4882 +static void __exit fini(void)
4883 +{
4884 +       /* FIXME: possible race with ip_set_create() */
4885 +       ip_set_unregister_set_type(&ip_set_macipmap);
4886 +}
4887 +
4888 +module_init(init);
4889 +module_exit(fini);
4890 +MODULE_LICENSE("GPL");
4891 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_portmap.c
4892 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
4893 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_portmap.c     2004-02-09 15:02:00.000000000 +0100
4894 @@ -0,0 +1,363 @@
4895 +/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4896 + *
4897 + * Based on ip_set_ipmap.c
4898 + *
4899 + * This program is free software; you can redistribute it and/or modify   
4900 + * it under the terms of the GNU General Public License as published by   
4901 + * the Free Software Foundation; either version 2 of the License, or      
4902 + * (at your option) any later version.                                    
4903 + *                                                                         
4904 + * This program is distributed in the hope that it will be useful,        
4905 + * but WITHOUT ANY WARRANTY; without even the implied warranty of         
4906 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
4907 + * GNU General Public License for more details.                           
4908 + *                                                                         
4909 + * You should have received a copy of the GNU General Public License      
4910 + * along with this program; if not, write to the Free Software            
4911 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4912 + */
4913 +
4914 +/* Kernel module implementing a port set type as a bitmap */
4915 +
4916 +#include <linux/module.h>
4917 +#include <linux/ip.h>
4918 +#include <linux/tcp.h>
4919 +#include <linux/udp.h>
4920 +#include <linux/skbuff.h>
4921 +#include <linux/netfilter_ipv4/ip_tables.h>
4922 +#include <linux/netfilter_ipv4/ip_set.h>
4923 +#include <linux/errno.h>
4924 +#include <asm/uaccess.h>
4925 +#include <asm/bitops.h>
4926 +#include <asm/softirq.h>
4927 +#include <linux/spinlock.h>
4928 +
4929 +#include <net/ip.h>
4930 +
4931 +#include <linux/netfilter_ipv4/ip_set_portmap.h>
4932 +
4933 +static inline ip_set_ip_t
4934 +get_port(const struct sk_buff *skb, u_int32_t flags)
4935 +{
4936 +       struct iphdr *iph = skb->nh.iph;
4937 +       u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
4938 +
4939 +       switch (iph->protocol) {
4940 +       case IPPROTO_TCP: {
4941 +               struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
4942 +               
4943 +               /* See comments at tcp_match in ip_tables.c */
4944 +               if (offset != 0
4945 +                   || (offset == 0 
4946 +                       && (skb->len - iph->ihl * 4) < sizeof(struct tcphdr)))
4947 +                       return INVALID_PORT;
4948 +               
4949 +               return ntohs(flags & IPSET_SRC ?
4950 +                            tcph->source : tcph->dest);
4951 +           }
4952 +       case IPPROTO_UDP: {
4953 +               struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
4954 +
4955 +               if (offset != 0
4956 +                   || (offset == 0 
4957 +                       && (skb->len - iph->ihl * 4) < sizeof(struct udphdr)))
4958 +                       return INVALID_PORT;
4959 +
4960 +               return ntohs(flags & IPSET_SRC ?
4961 +                            udph->source : udph->dest);
4962 +           }
4963 +       default:
4964 +               return INVALID_PORT;
4965 +       }
4966 +}
4967 +
4968 +static inline int
4969 +__testport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4970 +{
4971 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
4972 +
4973 +       if (port < map->first_port || port > map->last_port)
4974 +               return -ERANGE;
4975 +               
4976 +       *id = port - map->first_port;
4977 +       return !!test_bit(*id, map->members);
4978 +}
4979 +
4980 +static int
4981 +matchport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4982 +{
4983 +       return __testport(private, port, id);
4984 +}
4985 +
4986 +static int
4987 +testport(struct ip_set_private *private, const void *data, size_t size,
4988 +         ip_set_ip_t *id)
4989 +{
4990 +       struct ip_set_req_portmap *req = 
4991 +           (struct ip_set_req_portmap *) data;
4992 +
4993 +       if (size != sizeof(struct ip_set_req_portmap)) {
4994 +               ip_set_printk("data length wrong (want %d, have %d)",
4995 +                             sizeof(struct ip_set_req_portmap),
4996 +                             size);
4997 +               return -EINVAL;
4998 +       }
4999 +       return __testport(private, req->port, id);
5000 +}
5001 +
5002 +static int
5003 +testport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5004 +               u_int32_t flags, ip_set_ip_t *id)
5005 +{
5006 +       ip_set_ip_t port;
5007 +       
5008 +       if (!(flags & IPSET_TYPE_PORT))
5009 +               return -EINVAL;
5010 +
5011 +       port = get_port(skb, flags);
5012 +       DP("flags %u %s port %u",
5013 +               flags, 
5014 +               flags & IPSET_SRC ? "SRC" : "DST",
5015 +               port);
5016 +       
5017 +       if (port == INVALID_PORT)
5018 +               return -EINVAL; 
5019 +
5020 +       return __testport(private, port, id);
5021 +}
5022 +
5023 +static inline int
5024 +__addport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5025 +{
5026 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5027 +
5028 +       if (port < map->first_port || port > map->last_port)
5029 +               return -ERANGE;
5030 +       if (test_and_set_bit(port - map->first_port, map->members))
5031 +               return -EEXIST;
5032 +               
5033 +       *id = port - map->first_port;
5034 +       return 0;
5035 +}
5036 +
5037 +static int
5038 +addport(struct ip_set_private *private, const void *data, size_t size,
5039 +        ip_set_ip_t *id)
5040 +{
5041 +       struct ip_set_req_portmap *req = 
5042 +           (struct ip_set_req_portmap *) data;
5043 +
5044 +       if (size != sizeof(struct ip_set_req_portmap)) {
5045 +               ip_set_printk("data length wrong (want %d, have %d)",
5046 +                             sizeof(struct ip_set_req_portmap),
5047 +                             size);
5048 +               return -EINVAL;
5049 +       }
5050 +       return __addport(private, req->port, id);
5051 +}
5052 +
5053 +static int
5054 +addport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5055 +              u_int32_t flags, ip_set_ip_t *id)
5056 +{
5057 +       ip_set_ip_t port;
5058 +       
5059 +       if (!(flags & IPSET_TYPE_PORT))
5060 +               return -EINVAL;
5061 +                 
5062 +       port = get_port(skb, flags);
5063 +       
5064 +       if (port == INVALID_PORT)
5065 +               return -EINVAL;
5066 +
5067 +       return __addport(private, port, id);
5068 +}
5069 +
5070 +static inline int
5071 +__delport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5072 +{
5073 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5074 +
5075 +       if (port < map->first_port || port > map->last_port)
5076 +               return -ERANGE;
5077 +       if (!test_and_clear_bit(port - map->first_port, map->members))
5078 +               return -EEXIST;
5079 +               
5080 +       *id = port - map->first_port;
5081 +       return 0;
5082 +}
5083 +
5084 +static int
5085 +delport(struct ip_set_private *private, const void *data, size_t size,
5086 +        ip_set_ip_t *id)
5087 +{
5088 +       struct ip_set_req_portmap *req =
5089 +           (struct ip_set_req_portmap *) data;
5090 +
5091 +       if (size != sizeof(struct ip_set_req_portmap)) {
5092 +               ip_set_printk("data length wrong (want %d, have %d)",
5093 +                             sizeof(struct ip_set_req_portmap),
5094 +                             size);
5095 +               return -EINVAL;
5096 +       }
5097 +       return __delport(private, req->port, id);
5098 +}
5099 +
5100 +static int
5101 +delport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5102 +              u_int32_t flags, ip_set_ip_t *id)
5103 +{
5104 +       ip_set_ip_t port;
5105 +       
5106 +       if (!(flags & IPSET_TYPE_PORT))
5107 +               return -EINVAL;
5108 +                 
5109 +       port  = get_port(skb, flags);
5110 +       
5111 +       if (port == INVALID_PORT)
5112 +               return -EINVAL;
5113 +
5114 +       return __delport(private, port, id);
5115 +}
5116 +
5117 +static int create(struct ip_set_private **private, const void *data, size_t size)
5118 +{
5119 +       int newbytes;
5120 +       struct ip_set_req_portmap_create *req =
5121 +           (struct ip_set_req_portmap_create *) data;
5122 +       struct ip_set_portmap *map;
5123 +
5124 +       if (size != sizeof(struct ip_set_req_portmap_create)) {
5125 +               ip_set_printk("data length wrong (want %d, have %d)",
5126 +                              sizeof(struct ip_set_req_portmap_create),
5127 +                              size);
5128 +               return -EINVAL;
5129 +       }
5130 +
5131 +       DP("from 0x%08x to 0x%08x", req->from, req->to);
5132 +
5133 +       if (req->from > req->to) {
5134 +               DP("bad port range");
5135 +               return -EINVAL;
5136 +       }
5137 +
5138 +       if (req->to - req->from > MAX_RANGE) {
5139 +               ip_set_printk("range too big (max %d ports)",
5140 +                              MAX_RANGE);
5141 +               return -ERANGE;
5142 +       }
5143 +
5144 +       map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
5145 +       if (!map) {
5146 +               DP("out of memory for %d bytes",
5147 +                  sizeof(struct ip_set_portmap));
5148 +               return -ENOMEM;
5149 +       }
5150 +       map->first_port = req->from;
5151 +       map->last_port = req->to;
5152 +       newbytes = bitmap_bytes(req->from, req->to);
5153 +       map->members = kmalloc(newbytes, GFP_KERNEL);
5154 +       if (!map->members) {
5155 +               DP("out of memory for %d bytes", newbytes);
5156 +               kfree(map);
5157 +               return -ENOMEM;
5158 +       }
5159 +       memset(map->members, 0, newbytes);
5160 +
5161 +       *private = (struct ip_set_private *) map;
5162 +       return 0;
5163 +}
5164 +
5165 +static void destroy(struct ip_set_private **private)
5166 +{
5167 +       struct ip_set_portmap *map = (struct ip_set_portmap *) *private;
5168 +
5169 +       kfree(map->members);
5170 +       kfree(map);
5171 +
5172 +       *private = NULL;
5173 +}
5174 +
5175 +static void flush(struct ip_set_private *private)
5176 +{
5177 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5178 +       memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
5179 +}
5180 +
5181 +static int list_header_size(const struct ip_set_private *private)
5182 +{
5183 +       return sizeof(struct ip_set_req_portmap_create);
5184 +}
5185 +
5186 +static void list_header(const struct ip_set_private *private, void *data)
5187 +{
5188 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5189 +       struct ip_set_req_portmap_create *header =
5190 +           (struct ip_set_req_portmap_create *) data;
5191 +
5192 +       DP("list_header %x %x", map->first_port, map->last_port);
5193 +
5194 +       header->from = map->first_port;
5195 +       header->to = map->last_port;
5196 +}
5197 +
5198 +static int list_members_size(const struct ip_set_private *private)
5199 +{
5200 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5201 +
5202 +       return bitmap_bytes(map->first_port, map->last_port);
5203 +}
5204 +
5205 +static void list_members(const struct ip_set_private *private, void *data)
5206 +{
5207 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5208 +
5209 +       int bytes = bitmap_bytes(map->first_port, map->last_port);
5210 +
5211 +       memcpy(data, map->members, bytes);
5212 +}
5213 +
5214 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
5215 +{
5216 +       struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5217 +
5218 +       return (map->last_port - map->first_port + 1);
5219 +}
5220 +
5221 +static struct ip_set_type ip_set_portmap = {
5222 +       .typename               = SETTYPE_NAME,
5223 +       .typecode               = IPSET_TYPE_PORT,
5224 +       .protocol_version       = IP_SET_PROTOCOL_VERSION,
5225 +       .create                 = &create,
5226 +       .destroy                = &destroy,
5227 +       .flush                  = &flush,
5228 +       .reqsize                = sizeof(struct ip_set_req_portmap),
5229 +       .addip                  = &addport,
5230 +       .addip_kernel           = &addport_kernel,
5231 +       .delip                  = &delport,
5232 +       .delip_kernel           = &delport_kernel,
5233 +       .matchip                = &matchport,
5234 +       .testip                 = &testport,
5235 +       .testip_kernel          = &testport_kernel,
5236 +       .list_header_size       = &list_header_size,
5237 +       .list_header            = &list_header,
5238 +       .list_members_size      = &list_members_size,
5239 +       .list_members           = &list_members,
5240 +       .sizeid                 = &sizeid,
5241 +       .me                     = THIS_MODULE,
5242 +};
5243 +
5244 +static int __init init(void)
5245 +{
5246 +       return ip_set_register_set_type(&ip_set_portmap);
5247 +}
5248 +
5249 +static void __exit fini(void)
5250 +{
5251 +       /* FIXME: possible race with ip_set_create() */
5252 +       ip_set_unregister_set_type(&ip_set_portmap);
5253 +}
5254 +
5255 +module_init(init);
5256 +module_exit(fini);
5257 +MODULE_LICENSE("GPL");
5258 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
5259 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c      1970-01-01 01:00:00.000000000 +0100
5260 +++ linux-2.6.3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c  2004-02-19 08:47:22.288007614 +0100
5261 @@ -0,0 +1,84 @@
5262 +/**
5263 + * Strip all IP options in the IP packet header.
5264 + *
5265 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
5266 + * This software is distributed under GNU GPL v2, 1991
5267 + */
5268 +
5269 +#include <linux/module.h>
5270 +#include <linux/skbuff.h>
5271 +#include <linux/ip.h>
5272 +#include <net/checksum.h>
5273 +
5274 +#include <linux/netfilter_ipv4/ip_tables.h>
5275 +
5276 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5277 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
5278 +MODULE_LICENSE("GPL");
5279 +
5280 +static unsigned int
5281 +target(struct sk_buff **pskb,
5282 +       unsigned int hooknum,
5283 +       const struct net_device *in,
5284 +       const struct net_device *out,
5285 +       const void *targinfo,
5286 +       void *userinfo)
5287 +{
5288 +       struct iphdr *iph = (*pskb)->nh.iph;
5289 +       struct sk_buff *skb = (*pskb);
5290 +       struct ip_options * opt;
5291 +       unsigned char * optiph = skb->nh.raw;
5292 +       int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
5293 +       
5294 +
5295 +       /* if no options in packet then nothing to clear. */
5296 +       if (iph->ihl * 4 == sizeof(struct iphdr))
5297 +               return IPT_CONTINUE;
5298 +
5299 +       /* else clear all options */
5300 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
5301 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
5302 +       opt = &(IPCB(skb)->opt);
5303 +       opt->is_data = 0;
5304 +       opt->optlen = l;
5305 +
5306 +       skb->nfcache |= NFC_ALTERED;
5307 +
5308 +        return IPT_CONTINUE;
5309 +}
5310 +
5311 +static int
5312 +checkentry(const char *tablename,
5313 +          const struct ipt_entry *e,
5314 +           void *targinfo,
5315 +           unsigned int targinfosize,
5316 +           unsigned int hook_mask)
5317 +{
5318 +       if (strcmp(tablename, "mangle")) {
5319 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5320 +               return 0;
5321 +       }
5322 +       /* nothing else to check because no parameters */
5323 +       return 1;
5324 +}
5325 +
5326 +static struct ipt_target ipt_ipv4optsstrip_reg
5327 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
5328 +
5329 +static int __init init(void)
5330 +{
5331 +       if (ipt_register_target(&ipt_ipv4optsstrip_reg))
5332 +               return -EINVAL;
5333 +       printk("ipt_IPV4OPTSSTRIP loaded\n");
5334 +
5335 +       return 0;
5336 +}
5337 +
5338 +static void __exit fini(void)
5339 +{
5340 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
5341 +       printk("ipt_IPV4OPTSSTRIP unloaded\n");
5342 +}
5343 +
5344 +module_init(init);
5345 +module_exit(fini);
5346 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.3/net/ipv4/netfilter/ipt_NETLINK.c
5347 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_NETLINK.c    1970-01-01 01:00:00.000000000 +0100
5348 +++ linux-2.6.3/net/ipv4/netfilter/ipt_NETLINK.c        2004-02-19 08:47:24.269530314 +0100
5349 @@ -0,0 +1,119 @@
5350 +#include <linux/module.h>
5351 +#include <linux/version.h>
5352 +#include <linux/config.h>
5353 +#include <linux/socket.h>
5354 +#include <linux/skbuff.h>
5355 +#include <linux/kernel.h>
5356 +#include <linux/netlink.h>
5357 +#include <linux/netdevice.h>
5358 +#include <linux/mm.h>
5359 +#include <linux/socket.h>
5360 +#include <linux/netfilter_ipv4/ip_tables.h>
5361 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
5362 +#include <net/sock.h>
5363 +
5364 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
5365 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
5366 +MODULE_LICENSE("GPL");
5367 +
5368 +#if 0
5369 +#define DEBUGP printk
5370 +#else
5371 +#define DEBUGP(format, args...)
5372 +#endif
5373 +
5374 +static struct sock *ipfwsk;
5375 +
5376 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
5377 +                                   unsigned int hooknum,
5378 +                                   const struct net_device *in,
5379 +                                   const struct net_device *out,
5380 +                                   const void *targinfo, void *userinfo)
5381 +{
5382 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5383 +       struct iphdr *ip = (*pskb)->nh.iph;
5384 +       struct sk_buff *outskb;
5385 +       struct netlink_t nlhdr;
5386 +       size_t len=0;
5387 +
5388 +       /* Allocate a socket buffer */
5389 +       if ( MASK(nld->flags, USE_SIZE) )
5390 +               len = nld->size+sizeof(nlhdr);
5391 +       else
5392 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
5393 +
5394 +       outskb=alloc_skb(len, GFP_ATOMIC);
5395 +
5396 +       if (outskb) {
5397 +               nlhdr.len=len;
5398 +               
5399 +               if ( MASK(nld->flags, USE_MARK) )
5400 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
5401 +               else
5402 +                       nlhdr.mark=(*pskb)->nfmark;
5403 +               
5404 +               if ( in && in->name ) {
5405 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
5406 +               }else if ( out && out->name ){
5407 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
5408 +               }
5409 +
5410 +               skb_put(outskb, len);
5411 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
5412 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
5413 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
5414 +       }else{
5415 +               if (net_ratelimit())
5416 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
5417 +       }
5418 +
5419 +       if ( MASK(nld->flags, USE_DROP) )
5420 +               return NF_DROP;
5421 +
5422 +       return IPT_CONTINUE;
5423 +}
5424 +
5425 +static int ipt_netlink_checkentry(const char *tablename,
5426 +                              const struct ipt_entry *e,
5427 +                              void *targinfo,
5428 +                              unsigned int targinfosize,
5429 +                              unsigned int hookmask)
5430 +{
5431 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5432 +
5433 +       return 1;
5434 +}
5435 +
5436 +static struct ipt_target ipt_netlink_reg = { 
5437 +       {NULL, NULL},
5438 +       "NETLINK",
5439 +       ipt_netlink_target,
5440 +       ipt_netlink_checkentry,
5441 +       NULL,
5442 +       THIS_MODULE
5443 +};
5444 +
5445 +static int __init init(void)
5446 +{
5447 +       DEBUGP("ipt_NETLINK: init module\n");   
5448 +
5449 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
5450 +               return -EINVAL;
5451 +       }
5452 +
5453 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
5454 +               return -EINVAL;
5455 +       }
5456 +
5457 +       return 0;
5458 +}
5459 +
5460 +static void __exit fini(void)
5461 +{
5462 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
5463 +       ipt_unregister_target(&ipt_netlink_reg);
5464 +       if(ipfwsk->socket) sock_release(ipfwsk->socket);
5465 +}
5466 +
5467 +module_init(init);
5468 +module_exit(fini);
5469 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.3/net/ipv4/netfilter/ipt_POOL.c
5470 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_POOL.c       1970-01-01 01:00:00.000000000 +0100
5471 +++ linux-2.6.3/net/ipv4/netfilter/ipt_POOL.c   2004-02-19 08:47:30.712978249 +0100
5472 @@ -0,0 +1,116 @@
5473 +/* ipt_POOL.c - netfilter target to manipulate IP pools
5474 + *
5475 + * This target can be used almost everywhere. It acts on some specified
5476 + * IP pool, adding or deleting some IP address in the pool. The address
5477 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
5478 + * of the packet under inspection.
5479 + *
5480 + * The target normally returns IPT_CONTINUE.
5481 + */
5482 +
5483 +#include <linux/types.h>
5484 +#include <linux/ip.h>
5485 +#include <linux/timer.h>
5486 +#include <linux/module.h>
5487 +#include <linux/netfilter.h>
5488 +#include <linux/netdevice.h>
5489 +#include <linux/if.h>
5490 +#include <linux/inetdevice.h>
5491 +#include <net/protocol.h>
5492 +#include <net/checksum.h>
5493 +#include <linux/netfilter_ipv4.h>
5494 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5495 +#include <linux/netfilter_ipv4/ipt_pool.h>
5496 +
5497 +#if 0
5498 +#define DEBUGP printk
5499 +#else
5500 +#define DEBUGP(format, args...)
5501 +#endif
5502 +
5503 +/*** NOTE NOTE NOTE NOTE ***
5504 +**
5505 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
5506 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
5507 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
5508 +** is modified for the source IP address of the packet under inspection.
5509 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
5510 +**
5511 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
5512 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
5513 +**
5514 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
5515 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
5516 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
5517 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
5518 +*/
5519 +
5520 +static int
5521 +do_check(const char *tablename,
5522 +              const struct ipt_entry *e,
5523 +              void *targinfo,
5524 +              unsigned int targinfosize,
5525 +              unsigned int hook_mask)
5526 +{
5527 +       const struct ipt_pool_info *ipi = targinfo;
5528 +
5529 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
5530 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
5531 +               return 0;
5532 +       }
5533 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
5534 +       return 1;
5535 +}
5536 +
5537 +static unsigned int
5538 +do_target(struct sk_buff **pskb,
5539 +               unsigned int hooknum,
5540 +               const struct net_device *in,
5541 +               const struct net_device *out,
5542 +               const void *targinfo,
5543 +               void *userinfo)
5544 +{
5545 +       const struct ipt_pool_info *ipi = targinfo;
5546 +       int modified;
5547 +       unsigned int verdict = IPT_CONTINUE;
5548 +
5549 +       if (ipi->src != IP_POOL_NONE) {
5550 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
5551 +                                       ipi->flags & IPT_POOL_DEL_SRC);
5552 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
5553 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
5554 +                               verdict = NF_ACCEPT;
5555 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
5556 +                               verdict = NF_DROP;
5557 +               }
5558 +       }
5559 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
5560 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
5561 +                                       ipi->flags & IPT_POOL_DEL_DST);
5562 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
5563 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
5564 +                               verdict = NF_ACCEPT;
5565 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
5566 +                               verdict = NF_DROP;
5567 +               }
5568 +       }
5569 +       return verdict;
5570 +}
5571 +
5572 +static struct ipt_target pool_reg
5573 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
5574 +
5575 +static int __init init(void)
5576 +{
5577 +       DEBUGP("init ipt_POOL\n");
5578 +       return ipt_register_target(&pool_reg);
5579 +}
5580 +
5581 +static void __exit fini(void)
5582 +{
5583 +       DEBUGP("fini ipt_POOL\n");
5584 +       ipt_unregister_target(&pool_reg);
5585 +}
5586 +
5587 +module_init(init);
5588 +module_exit(fini);
5589 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_SET.c linux-2.6.3/net/ipv4/netfilter/ipt_SET.c
5590 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_SET.c        1970-01-01 01:00:00.000000000 +0100
5591 +++ linux-2.6.3/net/ipv4/netfilter/ipt_SET.c    2004-02-09 15:02:00.000000000 +0100
5592 @@ -0,0 +1,115 @@
5593 +/* ipt_SET.c - netfilter target to manipulate IP sets
5594 + *
5595 + * This target can be used almost everywhere. It acts on some specified
5596 + * IP set, adding or deleting some IP addresses/ports in the set. 
5597 + * The addresses/ports can be either the source, or destination
5598 + * of the packet under inspection.
5599 + *
5600 + */
5601 +
5602 +#include <linux/types.h>
5603 +#include <linux/ip.h>
5604 +#include <linux/timer.h>
5605 +#include <linux/module.h>
5606 +#include <linux/netfilter.h>
5607 +#include <linux/netdevice.h>
5608 +#include <linux/if.h>
5609 +#include <linux/inetdevice.h>
5610 +#include <net/protocol.h>
5611 +#include <net/checksum.h>
5612 +#include <linux/netfilter_ipv4.h>
5613 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5614 +#include <linux/netfilter_ipv4/ipt_set.h>
5615 +
5616 +static unsigned int
5617 +target(struct sk_buff **pskb,
5618 +       unsigned int hooknum,
5619 +       const struct net_device *in,
5620 +       const struct net_device *out,
5621 +       const void *targinfo,
5622 +       void *userinfo)
5623 +{
5624 +       const struct ipt_set_info_target *info = targinfo;
5625 +       
5626 +       if (info->add_set.id >= 0)
5627 +               ip_set_addip_kernel(ip_set_list[info->add_set.id],
5628 +                                   *pskb,
5629 +                                   info->add_set.flags,
5630 +                                   info->add_set.set_level,
5631 +                                   info->add_set.ip_level);
5632 +       if (info->del_set.id >= 0)
5633 +               ip_set_delip_kernel(ip_set_list[info->del_set.id],
5634 +                                   *pskb,
5635 +                                   info->del_set.flags,
5636 +                                   info->del_set.set_level,
5637 +                                   info->del_set.ip_level);
5638 +
5639 +       return IPT_CONTINUE;
5640 +}
5641 +
5642 +static int
5643 +checkentry(const char *tablename,
5644 +          const struct ipt_entry *e,
5645 +          void *targinfo,
5646 +          unsigned int targinfosize, unsigned int hook_mask)
5647 +{
5648 +       struct ipt_set_info_target *info = targinfo;
5649 +
5650 +       if (targinfosize != IPT_ALIGN(sizeof(*info))) {
5651 +               DP("bad target info size %u", targinfosize);
5652 +               return 0;
5653 +       }
5654 +
5655 +       if (info->add_set.id >= 0
5656 +           && !ip_set_get_byid(info->add_set.id)) {
5657 +               ip_set_printk("cannot verify add_set id %i as target",
5658 +                             info->add_set.id);
5659 +               return 0;       /* error */
5660 +       }
5661 +       if (info->del_set.id >= 0
5662 +           && !ip_set_get_byid(info->del_set.id)) {
5663 +               ip_set_printk("cannot verify del_set id %i as target",
5664 +                             info->del_set.id);
5665 +               return 0;       /* error */
5666 +       }
5667 +       DP("checkentry OK");
5668 +
5669 +       return 1;
5670 +}
5671 +
5672 +static void destroy(void *targetinfo, unsigned int targetsize)
5673 +{
5674 +       struct ipt_set_info_target *info = targetinfo;
5675 +
5676 +       if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
5677 +               ip_set_printk("invalid targetsize %d", targetsize);
5678 +               return;
5679 +       }
5680 +
5681 +       if (info->add_set.id >= 0)
5682 +               ip_set_put(ip_set_list[info->add_set.id]);
5683 +       if (info->del_set.id >= 0)
5684 +               ip_set_put(ip_set_list[info->del_set.id]);
5685 +}
5686 +
5687 +static struct ipt_target SET_target = {
5688 +       .name           = "SET",
5689 +       .target         = target,
5690 +       .checkentry     = checkentry,
5691 +       .destroy        = destroy,
5692 +       .me             = THIS_MODULE
5693 +};
5694 +
5695 +static int __init init(void)
5696 +{
5697 +       return ipt_register_target(&SET_target);
5698 +}
5699 +
5700 +static void __exit fini(void)
5701 +{
5702 +       ipt_unregister_target(&SET_target);
5703 +}
5704 +
5705 +module_init(init);
5706 +module_exit(fini);
5707 +MODULE_LICENSE("GPL");
5708 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.3/net/ipv4/netfilter/ipt_TTL.c
5709 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_TTL.c        1970-01-01 01:00:00.000000000 +0100
5710 +++ linux-2.6.3/net/ipv4/netfilter/ipt_TTL.c    2004-02-19 08:47:25.605208582 +0100
5711 @@ -0,0 +1,110 @@
5712 +/* TTL modification target for IP tables
5713 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
5714 + *
5715 + * Version: 1.8
5716 + *
5717 + * This software is distributed under the terms of GNU GPL
5718 + */
5719 +
5720 +#include <linux/module.h>
5721 +#include <linux/skbuff.h>
5722 +#include <linux/ip.h>
5723 +#include <net/checksum.h>
5724 +
5725 +#include <linux/netfilter_ipv4/ip_tables.h>
5726 +#include <linux/netfilter_ipv4/ipt_TTL.h>
5727 +
5728 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
5729 +MODULE_DESCRIPTION("IP tables TTL modification module");
5730 +MODULE_LICENSE("GPL");
5731 +
5732 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
5733 +               const struct net_device *in, const struct net_device *out,
5734 +               const void *targinfo, void *userinfo)
5735 +{
5736 +       struct iphdr *iph = (*pskb)->nh.iph;
5737 +       const struct ipt_TTL_info *info = targinfo;
5738 +       u_int16_t diffs[2];
5739 +       int new_ttl;
5740 +                        
5741 +       switch (info->mode) {
5742 +               case IPT_TTL_SET:
5743 +                       new_ttl = info->ttl;
5744 +                       break;
5745 +               case IPT_TTL_INC:
5746 +                       new_ttl = iph->ttl + info->ttl;
5747 +                       if (new_ttl > 255)
5748 +                               new_ttl = 255;
5749 +                       break;
5750 +               case IPT_TTL_DEC:
5751 +                       new_ttl = iph->ttl + info->ttl;
5752 +                       if (new_ttl < 0)
5753 +                               new_ttl = 0;
5754 +                       break;
5755 +               default:
5756 +                       new_ttl = iph->ttl;
5757 +                       break;
5758 +       }
5759 +
5760 +       if (new_ttl != iph->ttl) {
5761 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
5762 +               iph->ttl = new_ttl;
5763 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
5764 +               iph->check = csum_fold(csum_partial((char *)diffs,
5765 +                                                   sizeof(diffs),
5766 +                                                   iph->check^0xFFFF));
5767 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
5768 +       }
5769 +
5770 +       return IPT_CONTINUE;
5771 +}
5772 +
5773 +static int ipt_ttl_checkentry(const char *tablename,
5774 +               const struct ipt_entry *e,
5775 +               void *targinfo,
5776 +               unsigned int targinfosize,
5777 +               unsigned int hook_mask)
5778 +{
5779 +       struct ipt_TTL_info *info = targinfo;
5780 +
5781 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
5782 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
5783 +                               targinfosize,
5784 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
5785 +               return 0;       
5786 +       }       
5787 +
5788 +       if (strcmp(tablename, "mangle")) {
5789 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5790 +               return 0;
5791 +       }
5792 +
5793 +       if (info->mode > IPT_TTL_MAXMODE) {
5794 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
5795 +                       info->mode);
5796 +               return 0;
5797 +       }
5798 +
5799 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
5800 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
5801 +               return 0;
5802 +       }
5803 +       
5804 +       return 1;
5805 +}
5806 +
5807 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL", 
5808 +       ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
5809 +
5810 +static int __init init(void)
5811 +{
5812 +       return ipt_register_target(&ipt_TTL);
5813 +}
5814 +
5815 +static void __exit fini(void)
5816 +{
5817 +       ipt_unregister_target(&ipt_TTL);
5818 +}
5819 +
5820 +module_init(init);
5821 +module_exit(fini);
5822 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.3/net/ipv4/netfilter/ipt_connlimit.c
5823 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_connlimit.c  1970-01-01 01:00:00.000000000 +0100
5824 +++ linux-2.6.3/net/ipv4/netfilter/ipt_connlimit.c      2004-02-19 08:47:26.593970414 +0100
5825 @@ -0,0 +1,232 @@
5826 +/*
5827 + * netfilter module to limit the number of parallel tcp
5828 + * connections per IP address.
5829 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
5830 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
5831 + *             only ignore TIME_WAIT or gone connections
5832 + *
5833 + * based on ...
5834 + *
5835 + * Kernel module to match connection tracking information.
5836 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
5837 + */
5838 +#include <linux/module.h>
5839 +#include <linux/skbuff.h>
5840 +#include <linux/list.h>
5841 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5842 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5843 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
5844 +#include <linux/netfilter_ipv4/ip_tables.h>
5845 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
5846 +
5847 +#define DEBUG 0
5848 +
5849 +MODULE_LICENSE("GPL");
5850 +
5851 +/* we'll save the tuples of all connections we care about */
5852 +struct ipt_connlimit_conn
5853 +{
5854 +        struct list_head list;
5855 +       struct ip_conntrack_tuple tuple;
5856 +};
5857 +
5858 +struct ipt_connlimit_data {
5859 +       spinlock_t lock;
5860 +       struct list_head iphash[256];
5861 +};
5862 +
5863 +static int ipt_iphash(u_int32_t addr)
5864 +{
5865 +       int hash;
5866 +
5867 +       hash  =  addr        & 0xff;
5868 +       hash ^= (addr >>  8) & 0xff;
5869 +       hash ^= (addr >> 16) & 0xff;
5870 +       hash ^= (addr >> 24) & 0xff;
5871 +       return hash;
5872 +}
5873 +
5874 +static int count_them(struct ipt_connlimit_data *data,
5875 +                     u_int32_t addr, u_int32_t mask,
5876 +                     struct ip_conntrack *ct)
5877 +{
5878 +#if DEBUG
5879 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
5880 +                                    "fin_wait", "time_wait", "close", "close_wait",
5881 +                                    "last_ack", "listen" };
5882 +#endif
5883 +       int addit = 1, matches = 0;
5884 +       struct ip_conntrack_tuple tuple;
5885 +       struct ip_conntrack_tuple_hash *found;
5886 +       struct ipt_connlimit_conn *conn;
5887 +       struct list_head *hash,*lh;
5888 +
5889 +       spin_lock(&data->lock);
5890 +       tuple = ct->tuplehash[0].tuple;
5891 +       hash = &data->iphash[ipt_iphash(addr & mask)];
5892 +
5893 +       /* check the saved connections */
5894 +       for (lh = hash->next; lh != hash; lh = lh->next) {
5895 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
5896 +               found = ip_conntrack_find_get(&conn->tuple,ct);
5897 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
5898 +                   found != NULL &&
5899 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
5900 +                       /* Just to be sure we have it only once in the list.
5901 +                          We should'nt see tuples twice unless someone hooks this
5902 +                          into a table without "-p tcp --syn" */
5903 +                       addit = 0;
5904 +               }
5905 +#if DEBUG
5906 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
5907 +                      ipt_iphash(addr & mask),
5908 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
5909 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
5910 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
5911 +#endif
5912 +               if (NULL == found) {
5913 +                       /* this one is gone */
5914 +                       lh = lh->prev;
5915 +                       list_del(lh->next);
5916 +                       kfree(conn);
5917 +                       continue;
5918 +               }
5919 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
5920 +                       /* we don't care about connections which are
5921 +                          closed already -> ditch it */
5922 +                       lh = lh->prev;
5923 +                       list_del(lh->next);
5924 +                       kfree(conn);
5925 +                       nf_conntrack_put(&found->ctrack->infos[0]);
5926 +                       continue;
5927 +               }
5928 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
5929 +                       /* same source IP address -> be counted! */
5930 +                       matches++;
5931 +               }
5932 +               nf_conntrack_put(&found->ctrack->infos[0]);
5933 +       }
5934 +       if (addit) {
5935 +               /* save the new connection in our list */
5936 +#if DEBUG
5937 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
5938 +                      ipt_iphash(addr & mask),
5939 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
5940 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
5941 +#endif
5942 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
5943 +               if (NULL == conn)
5944 +                       return -1;
5945 +               memset(conn,0,sizeof(*conn));
5946 +               INIT_LIST_HEAD(&conn->list);
5947 +               conn->tuple = tuple;
5948 +               list_add(&conn->list,hash);
5949 +               matches++;
5950 +       }
5951 +       spin_unlock(&data->lock);
5952 +       return matches;
5953 +}
5954 +
5955 +static int
5956 +match(const struct sk_buff *skb,
5957 +      const struct net_device *in,
5958 +      const struct net_device *out,
5959 +      const void *matchinfo,
5960 +      int offset,
5961 +      const void *hdr,
5962 +      u_int16_t datalen,
5963 +      int *hotdrop)
5964 +{
5965 +       const struct ipt_connlimit_info *info = matchinfo;
5966 +       int connections, match;
5967 +       struct ip_conntrack *ct;
5968 +       enum ip_conntrack_info ctinfo;
5969 +
5970 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
5971 +       if (NULL == ct) {
5972 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
5973 +               *hotdrop = 1;
5974 +               return 0;
5975 +       }
5976 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
5977 +       if (-1 == connections) {
5978 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
5979 +               *hotdrop = 1; /* let's free some memory :-) */
5980 +               return 0;
5981 +       }
5982 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
5983 +#if DEBUG
5984 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
5985 +              "connections=%d limit=%d match=%s\n",
5986 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
5987 +              connections, info->limit, match ? "yes" : "no");
5988 +#endif
5989 +
5990 +       return match;
5991 +}
5992 +
5993 +static int check(const char *tablename,
5994 +                const struct ipt_ip *ip,
5995 +                void *matchinfo,
5996 +                unsigned int matchsize,
5997 +                unsigned int hook_mask)
5998 +{
5999 +       struct ipt_connlimit_info *info = matchinfo;
6000 +       int i;
6001 +
6002 +       /* verify size */
6003 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
6004 +               return 0;
6005 +
6006 +       /* refuse anything but tcp */
6007 +       if (ip->proto != IPPROTO_TCP)
6008 +               return 0;
6009 +
6010 +       /* init private data */
6011 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
6012 +       spin_lock_init(&(info->data->lock));
6013 +       for (i = 0; i < 256; i++)
6014 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
6015 +       
6016 +       return 1;
6017 +}
6018 +
6019 +static void destroy(void *matchinfo, unsigned int matchinfosize)
6020 +{
6021 +       struct ipt_connlimit_info *info = matchinfo;
6022 +       struct ipt_connlimit_conn *conn;
6023 +       struct list_head *hash;
6024 +       int i;
6025 +
6026 +       /* cleanup */
6027 +       for (i = 0; i < 256; i++) {
6028 +               hash = &(info->data->iphash[i]);
6029 +               while (hash != hash->next) {
6030 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
6031 +                       list_del(hash->next);
6032 +                       kfree(conn);
6033 +               }
6034 +       }
6035 +       kfree(info->data);
6036 +}
6037 +
6038 +static struct ipt_match connlimit_match
6039 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
6040 +
6041 +static int __init init(void)
6042 +{
6043 +       /* NULL if ip_conntrack not a module */
6044 +       if (ip_conntrack_module)
6045 +               __MOD_INC_USE_COUNT(ip_conntrack_module);
6046 +       return ipt_register_match(&connlimit_match);
6047 +}
6048 +
6049 +static void __exit fini(void)
6050 +{
6051 +       ipt_unregister_match(&connlimit_match);
6052 +       if (ip_conntrack_module)
6053 +               __MOD_DEC_USE_COUNT(ip_conntrack_module);
6054 +}
6055 +
6056 +module_init(init);
6057 +module_exit(fini);
6058 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.3/net/ipv4/netfilter/ipt_dstlimit.c
6059 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_dstlimit.c   1970-01-01 01:00:00.000000000 +0100
6060 +++ linux-2.6.3/net/ipv4/netfilter/ipt_dstlimit.c       2004-02-19 08:47:27.235815809 +0100
6061 @@ -0,0 +1,677 @@
6062 +/* iptables match extension to limit the number of packets per second
6063 + * seperately for each destination.
6064 + *
6065 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
6066 + *
6067 + * $Id$
6068 + *
6069 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
6070 + *
6071 + * based on ipt_limit.c by:
6072 + * Jérôme de Vivie     <devivie@info.enserb.u-bordeaux.fr>
6073 + * Hervé Eychenne      <eychenne@info.enserb.u-bordeaux.fr>
6074 + * Rusty Russell       <rusty@rustcorp.com.au>
6075 + *
6076 + * The general idea is to create a hash table for every dstip and have a
6077 + * seperate limit counter per tuple.  This way you can do something like 'limit
6078 + * the number of syn packets for each of my internal addresses.
6079 + *
6080 + * Ideally this would just be implemented as a general 'hash' match, which would
6081 + * allow us to attach any iptables target to it's hash buckets.  But this is
6082 + * not possible in the current iptables architecture.  As always, pkttables for
6083 + * 2.7.x will help ;)
6084 + */
6085 +#include <linux/module.h>
6086 +#include <linux/skbuff.h>
6087 +#include <linux/spinlock.h>
6088 +#include <linux/random.h>
6089 +#include <linux/jhash.h>
6090 +#include <linux/slab.h>
6091 +#include <linux/vmalloc.h>
6092 +#include <linux/tcp.h>
6093 +#include <linux/udp.h>
6094 +#include <linux/proc_fs.h>
6095 +#include <linux/seq_file.h>
6096 +
6097 +#define ASSERT_READ_LOCK(x) 
6098 +#define ASSERT_WRITE_LOCK(x) 
6099 +#include <linux/netfilter_ipv4/lockhelp.h>
6100 +#include <linux/netfilter_ipv4/listhelp.h>
6101 +
6102 +#include <linux/netfilter_ipv4/ip_tables.h>
6103 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
6104 +
6105 +/* FIXME: this is just for IP_NF_ASSERRT */
6106 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6107 +
6108 +#define MS2JIFFIES(x) ((x*HZ)/1000)
6109 +
6110 +MODULE_LICENSE("GPL");
6111 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
6112 +MODULE_DESCRIPTION("iptables match for limiting per destination");
6113 +
6114 +/* need to declare this at the top */
6115 +static struct proc_dir_entry *dstlimit_procdir;
6116 +static struct file_operations dl_file_ops;
6117 +
6118 +/* hash table crap */
6119 +
6120 +struct dsthash_dst {
6121 +       u_int32_t src_ip;
6122 +       u_int32_t dst_ip;
6123 +       u_int16_t port;
6124 +};
6125 +
6126 +struct dsthash_ent {
6127 +       /* static / read-only parts in the beginning */
6128 +       struct list_head list;
6129 +       struct dsthash_dst dst;
6130 +
6131 +       /* modified structure members in the end */
6132 +       unsigned long expires;          /* precalculated expiry time */
6133 +       struct {
6134 +               unsigned long prev;     /* last modification */
6135 +               u_int32_t credit;
6136 +               u_int32_t credit_cap, cost;
6137 +       } rateinfo;
6138 +};
6139 +
6140 +struct ipt_dstlimit_htable {
6141 +       struct list_head list;          /* global list of all htables */
6142 +       atomic_t use;
6143 +
6144 +       struct dstlimit_cfg cfg;        /* config */
6145 +
6146 +       /* used internally */
6147 +       spinlock_t lock;                /* lock for list_head */
6148 +       u_int32_t rnd;                  /* random seed for hash */
6149 +       struct timer_list timer;        /* timer for gc */
6150 +       atomic_t count;                 /* number entries in table */
6151 +
6152 +       /* seq_file stuff */
6153 +       struct proc_dir_entry *pde;
6154 +
6155 +       struct list_head hash[0];       /* hashtable itself */
6156 +};
6157 +
6158 +DECLARE_RWLOCK(dstlimit_lock);         /* protects htables list */
6159 +static LIST_HEAD(dstlimit_htables);
6160 +static kmem_cache_t *dstlimit_cachep;
6161 +
6162 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
6163 +{
6164 +       return (ent->dst.dst_ip == b->dst_ip 
6165 +               && ent->dst.port == b->port
6166 +               && ent->dst.src_ip == b->src_ip);
6167 +}
6168 +
6169 +static inline u_int32_t
6170 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
6171 +{
6172 +       return (jhash_3words(dst->dst_ip, dst->port, 
6173 +                            dst->src_ip, ht->rnd) % ht->cfg.size);
6174 +}
6175 +
6176 +static inline struct dsthash_ent *
6177 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
6178 +{
6179 +       struct dsthash_ent *ent;
6180 +       u_int32_t hash = hash_dst(ht, dst);
6181 +       MUST_BE_LOCKED(&ht->lock);
6182 +       ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
6183 +       return ent;
6184 +}
6185 +
6186 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
6187 +static struct dsthash_ent *
6188 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
6189 +{
6190 +       struct dsthash_ent *ent;
6191 +
6192 +       /* initialize hash with random val at the time we allocate
6193 +        * the first hashtable entry */
6194 +       if (!ht->rnd)
6195 +               get_random_bytes(&ht->rnd, 4);
6196 +
6197 +       if (ht->cfg.max &&
6198 +           atomic_read(&ht->count) >= ht->cfg.max) {
6199 +               /* FIXME: do something. question is what.. */
6200 +               if (net_ratelimit())
6201 +                       printk(KERN_WARNING 
6202 +                               "ipt_dstlimit: max count of %u reached\n", 
6203 +                               ht->cfg.max);
6204 +               return NULL;
6205 +       }
6206 +
6207 +       ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
6208 +       if (!ent) {
6209 +               if (net_ratelimit())
6210 +                       printk(KERN_ERR 
6211 +                               "ipt_dstlimit: can't allocate dsthash_ent\n");
6212 +               return NULL;
6213 +       }
6214 +
6215 +       atomic_inc(&ht->count);
6216 +
6217 +       ent->dst.dst_ip = dst->dst_ip;
6218 +       ent->dst.port = dst->port;
6219 +       ent->dst.src_ip = dst->src_ip;
6220 +
6221 +       list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
6222 +
6223 +       return ent;
6224 +}
6225 +
6226 +static inline void 
6227 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
6228 +{
6229 +       MUST_BE_LOCKED(&ht->lock);
6230 +
6231 +       list_del(&ent->list);
6232 +       kmem_cache_free(dstlimit_cachep, ent);
6233 +       atomic_dec(&ht->count);
6234 +}
6235 +static void htable_gc(unsigned long htlong);
6236 +
6237 +static int htable_create(struct ipt_dstlimit_info *minfo)
6238 +{
6239 +       int i;
6240 +       unsigned int size;
6241 +       struct ipt_dstlimit_htable *hinfo;
6242 +
6243 +       if (minfo->cfg.size)
6244 +               size = minfo->cfg.size;
6245 +       else {
6246 +               size = (((num_physpages << PAGE_SHIFT) / 16384)
6247 +                        / sizeof(struct list_head));
6248 +               if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
6249 +                       size = 8192;
6250 +               if (size < 16)
6251 +                       size = 16;
6252 +       }
6253 +       /* FIXME: don't use vmalloc() here or anywhere else -HW */
6254 +       hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
6255 +                       + (sizeof(struct list_head) * size));
6256 +       if (!hinfo) {
6257 +               printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
6258 +               return -1;
6259 +       }
6260 +       minfo->hinfo = hinfo;
6261 +
6262 +       /* copy match config into hashtable config */
6263 +       memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
6264 +       hinfo->cfg.size = size;
6265 +       if (!hinfo->cfg.max)
6266 +               hinfo->cfg.max = 8 * hinfo->cfg.size;
6267 +       else if (hinfo->cfg.max < hinfo->cfg.size)
6268 +               hinfo->cfg.max = hinfo->cfg.size;
6269 +
6270 +       for (i = 0; i < hinfo->cfg.size; i++)
6271 +               INIT_LIST_HEAD(&hinfo->hash[i]);
6272 +
6273 +       atomic_set(&hinfo->count, 0);
6274 +       atomic_set(&hinfo->use, 1);
6275 +       hinfo->rnd = 0;
6276 +       hinfo->lock = SPIN_LOCK_UNLOCKED;
6277 +       hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
6278 +       if (!hinfo->pde) {
6279 +               vfree(hinfo);
6280 +               return -1;
6281 +       }
6282 +       hinfo->pde->proc_fops = &dl_file_ops;
6283 +       hinfo->pde->data = hinfo;
6284 +
6285 +       init_timer(&hinfo->timer);
6286 +       hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
6287 +       hinfo->timer.data = (unsigned long )hinfo;
6288 +       hinfo->timer.function = htable_gc;
6289 +       add_timer(&hinfo->timer);
6290 +
6291 +       WRITE_LOCK(&dstlimit_lock);
6292 +       list_add(&hinfo->list, &dstlimit_htables);
6293 +       WRITE_UNLOCK(&dstlimit_lock);
6294 +
6295 +       return 0;
6296 +}
6297 +
6298 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
6299 +{
6300 +       return 1;
6301 +}
6302 +
6303 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
6304 +{
6305 +       return (jiffies >= he->expires);
6306 +}
6307 +
6308 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
6309 +                               int (*select)(struct ipt_dstlimit_htable *ht, 
6310 +                                             struct dsthash_ent *he))
6311 +{
6312 +       int i;
6313 +
6314 +       IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
6315 +
6316 +       /* lock hash table and iterate over it */
6317 +       LOCK_BH(&ht->lock);
6318 +       for (i = 0; i < ht->cfg.size; i++) {
6319 +               struct dsthash_ent *dh, *n;
6320 +               list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
6321 +                       if ((*select)(ht, dh))
6322 +                               __dsthash_free(ht, dh);
6323 +               }
6324 +       }
6325 +       UNLOCK_BH(&ht->lock);
6326 +}
6327 +
6328 +/* hash table garbage collector, run by timer */
6329 +static void htable_gc(unsigned long htlong)
6330 +{
6331 +       struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
6332 +
6333 +       htable_selective_cleanup(ht, select_gc);
6334 +
6335 +       /* re-add the timer accordingly */
6336 +       ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
6337 +       add_timer(&ht->timer);
6338 +}
6339 +
6340 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
6341 +{
6342 +       /* remove timer, if it is pending */
6343 +       if (timer_pending(&hinfo->timer))
6344 +               del_timer(&hinfo->timer);
6345 +
6346 +       /* remove proc entry */
6347 +       remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
6348 +
6349 +       htable_selective_cleanup(hinfo, select_all);
6350 +       vfree(hinfo);
6351 +}
6352 +
6353 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
6354 +{
6355 +       struct ipt_dstlimit_htable *hinfo;
6356 +
6357 +       READ_LOCK(&dstlimit_lock);
6358 +       list_for_each_entry(hinfo, &dstlimit_htables, list) {
6359 +               if (!strcmp(name, hinfo->pde->name)) {
6360 +                       atomic_inc(&hinfo->use);
6361 +                       READ_UNLOCK(&dstlimit_lock);
6362 +                       return hinfo;
6363 +               }
6364 +       }
6365 +       READ_UNLOCK(&dstlimit_lock);
6366 +
6367 +       return NULL;
6368 +}
6369 +
6370 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
6371 +{
6372 +       if (atomic_dec_and_test(&hinfo->use)) {
6373 +               WRITE_LOCK(&dstlimit_lock);
6374 +               list_del(&hinfo->list);
6375 +               WRITE_UNLOCK(&dstlimit_lock);
6376 +               htable_destroy(hinfo);
6377 +       }
6378 +}
6379 +
6380 +
6381 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
6382 + * see net/sched/sch_tbf.c in the linux source tree
6383 + */
6384 +
6385 +/* Rusty: This is my (non-mathematically-inclined) understanding of
6386 +   this algorithm.  The `average rate' in jiffies becomes your initial
6387 +   amount of credit `credit' and the most credit you can ever have
6388 +   `credit_cap'.  The `peak rate' becomes the cost of passing the
6389 +   test, `cost'.
6390 +
6391 +   `prev' tracks the last packet hit: you gain one credit per jiffy.
6392 +   If you get credit balance more than this, the extra credit is
6393 +   discarded.  Every time the match passes, you lose `cost' credits;
6394 +   if you don't have that many, the test fails.
6395 +
6396 +   See Alexey's formal explanation in net/sched/sch_tbf.c.
6397 +
6398 +   To get the maximum range, we multiply by this factor (ie. you get N
6399 +   credits per jiffy).  We want to allow a rate as low as 1 per day
6400 +   (slowest userspace tool allows), which means
6401 +   CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
6402 +*/
6403 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
6404 +
6405 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
6406 + * us the power of 2 below the theoretical max, so GCC simply does a
6407 + * shift. */
6408 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
6409 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
6410 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
6411 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
6412 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
6413 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
6414 +
6415 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
6416 +
6417 +/* Precision saver. */
6418 +static inline u_int32_t
6419 +user2credits(u_int32_t user)
6420 +{
6421 +       /* If multiplying would overflow... */
6422 +       if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
6423 +               /* Divide first. */
6424 +               return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
6425 +
6426 +       return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
6427 +}
6428 +
6429 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
6430 +{
6431 +       dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now)) 
6432 +                                       * CREDITS_PER_JIFFY;
6433 +       if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
6434 +               dh->rateinfo.credit = dh->rateinfo.credit_cap;
6435 +}
6436 +
6437 +static int
6438 +dstlimit_match(const struct sk_buff *skb,
6439 +               const struct net_device *in,
6440 +               const struct net_device *out,
6441 +               const void *matchinfo,
6442 +               int offset,
6443 +               const void *hdr,
6444 +               u_int16_t datalen,
6445 +               int *hotdrop)
6446 +{
6447 +       struct ipt_dstlimit_info *r = 
6448 +               ((struct ipt_dstlimit_info *)matchinfo)->u.master;
6449 +       struct ipt_dstlimit_htable *hinfo = r->hinfo;
6450 +       unsigned long now = jiffies;
6451 +       struct dsthash_ent *dh;
6452 +       struct dsthash_dst dst;
6453 +
6454 +       memset(&dst, 0, sizeof(dst));
6455 +
6456 +       /* dest ip is always in hash */
6457 +       dst.dst_ip = skb->nh.iph->daddr;
6458 +
6459 +       /* source ip only if respective hashmode, otherwise set to
6460 +        * zero */
6461 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
6462 +               dst.src_ip = skb->nh.iph->saddr;
6463 +
6464 +       /* dest port only if respective mode */
6465 +       if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
6466 +               switch (skb->nh.iph->protocol) {
6467 +                       struct tcphdr *th;
6468 +                       struct udphdr *uh;
6469 +               case IPPROTO_TCP:
6470 +                       th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
6471 +                       dst.port = th->dest;
6472 +                       break;
6473 +               case IPPROTO_UDP:
6474 +                       uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
6475 +                       dst.port = uh->dest;
6476 +                       break;
6477 +               default:
6478 +                       break;
6479 +               }
6480 +       } 
6481 +
6482 +       LOCK_BH(&hinfo->lock);
6483 +       dh = __dsthash_find(hinfo, &dst);
6484 +       if (!dh) {
6485 +               dh = __dsthash_alloc_init(hinfo, &dst);
6486 +
6487 +               if (!dh) {
6488 +                       /* enomem... don't match == DROP */
6489 +                       if (net_ratelimit())
6490 +                               printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
6491 +                       UNLOCK_BH(&hinfo->lock);
6492 +                       return 0;
6493 +               }
6494 +
6495 +               dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
6496 +
6497 +               dh->rateinfo.prev = jiffies;
6498 +               dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 
6499 +                                                       hinfo->cfg.burst);
6500 +               dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * 
6501 +                                                       hinfo->cfg.burst);
6502 +               dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
6503 +
6504 +               UNLOCK_BH(&hinfo->lock);
6505 +               return 0;
6506 +       }
6507 +
6508 +       /* update expiration timeout */
6509 +       dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
6510 +
6511 +       rateinfo_recalc(dh, now);
6512 +       if (dh->rateinfo.credit >= dh->rateinfo.cost) {
6513 +               /* We're underlimit. */
6514 +               dh->rateinfo.credit -= dh->rateinfo.cost;
6515 +               UNLOCK_BH(&hinfo->lock);
6516 +               return 1;
6517 +       }
6518 +
6519 +               UNLOCK_BH(&hinfo->lock);
6520 +
6521 +       /* default case: we're overlimit, thus don't match */
6522 +       return 0;
6523 +}
6524 +
6525 +static int
6526 +dstlimit_checkentry(const char *tablename,
6527 +                    const struct ipt_ip *ip,
6528 +                    void *matchinfo,
6529 +                    unsigned int matchsize,
6530 +                    unsigned int hook_mask)
6531 +{
6532 +       struct ipt_dstlimit_info *r = matchinfo;
6533 +
6534 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
6535 +               return 0;
6536 +
6537 +       /* Check for overflow. */
6538 +       if (r->cfg.burst == 0
6539 +           || user2credits(r->cfg.avg * r->cfg.burst) < 
6540 +                                       user2credits(r->cfg.avg)) {
6541 +               printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
6542 +                      r->cfg.avg, r->cfg.burst);
6543 +               return 0;
6544 +       }
6545 +
6546 +       if (r->cfg.mode == 0 
6547 +           || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
6548 +                         |IPT_DSTLIMIT_HASH_DIP
6549 +                         |IPT_DSTLIMIT_HASH_SIP))
6550 +               return 0;
6551 +
6552 +       if (!r->cfg.gc_interval)
6553 +               return 0;
6554 +       
6555 +       if (!r->cfg.expire)
6556 +               return 0;
6557 +
6558 +       r->hinfo = htable_find_get(r->name);
6559 +       if (!r->hinfo && (htable_create(r) != 0)) {
6560 +               return 0;
6561 +       }
6562 +
6563 +       /* Ugly hack: For SMP, we only want to use one set */
6564 +       r->u.master = r;
6565 +
6566 +       return 1;
6567 +}
6568 +
6569 +static void
6570 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
6571 +{
6572 +       struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
6573 +
6574 +       htable_put(r->hinfo);
6575 +}
6576 +
6577 +static struct ipt_match ipt_dstlimit = { 
6578 +       .list = { .prev = NULL, .next = NULL }, 
6579 +       .name = "dstlimit", 
6580 +       .match = dstlimit_match, 
6581 +       .checkentry = dstlimit_checkentry, 
6582 +       .destroy = dstlimit_destroy,
6583 +       .me = THIS_MODULE 
6584 +};
6585 +
6586 +/* PROC stuff */
6587 +
6588 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
6589 +{
6590 +       struct proc_dir_entry *pde = s->private;
6591 +       struct ipt_dstlimit_htable *htable = pde->data;
6592 +       unsigned int *bucket;
6593 +
6594 +       LOCK_BH(&htable->lock);
6595 +       if (*pos >= htable->cfg.size)
6596 +               return NULL;
6597 +
6598 +       bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
6599 +       if (!bucket)
6600 +               return ERR_PTR(-ENOMEM);
6601 +
6602 +       *bucket = *pos;
6603 +       return bucket;
6604 +}
6605 +
6606 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
6607 +{
6608 +       struct proc_dir_entry *pde = s->private;
6609 +       struct ipt_dstlimit_htable *htable = pde->data;
6610 +       unsigned int *bucket = (unsigned int *)v;
6611 +
6612 +       *pos = ++(*bucket);
6613 +       if (*pos >= htable->cfg.size) {
6614 +               kfree(v);
6615 +               return NULL;
6616 +       }
6617 +       return bucket;
6618 +}
6619 +
6620 +static void dl_seq_stop(struct seq_file *s, void *v)
6621 +{
6622 +       struct proc_dir_entry *pde = s->private;
6623 +       struct ipt_dstlimit_htable *htable = pde->data;
6624 +       unsigned int *bucket = (unsigned int *)v;
6625 +
6626 +       kfree(bucket);
6627 +
6628 +       UNLOCK_BH(&htable->lock);
6629 +}
6630 +
6631 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
6632 +{
6633 +       /* recalculate to show accurate numbers */
6634 +       rateinfo_recalc(ent, jiffies);
6635 +
6636 +       return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
6637 +                       (ent->expires - jiffies)/HZ,
6638 +                       NIPQUAD(ent->dst.src_ip),
6639 +                       NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
6640 +                       ent->rateinfo.credit, ent->rateinfo.credit_cap,
6641 +                       ent->rateinfo.cost);
6642 +}
6643 +
6644 +static int dl_seq_show(struct seq_file *s, void *v)
6645 +{
6646 +       struct proc_dir_entry *pde = s->private;
6647 +       struct ipt_dstlimit_htable *htable = pde->data;
6648 +       unsigned int *bucket = (unsigned int *)v;
6649 +
6650 +       if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
6651 +                     struct dsthash_ent *, s)) {
6652 +               /* buffer was filled and unable to print that tuple */
6653 +               return 1;
6654 +       }
6655 +       return 0;
6656 +}
6657 +
6658 +static struct seq_operations dl_seq_ops = {
6659 +       .start = dl_seq_start,
6660 +       .next  = dl_seq_next,
6661 +       .stop  = dl_seq_stop,
6662 +       .show  = dl_seq_show
6663 +};
6664 +
6665 +static int dl_proc_open(struct inode *inode, struct file *file)
6666 +{
6667 +       int ret = seq_open(file, &dl_seq_ops);
6668 +
6669 +       if (!ret) {
6670 +               struct seq_file *sf = file->private_data;
6671 +               sf->private = PDE(inode);
6672 +       }
6673 +       return ret;
6674 +}
6675 +
6676 +static struct file_operations dl_file_ops = {
6677 +       .owner   = THIS_MODULE,
6678 +       .open    = dl_proc_open,
6679 +       .read    = seq_read,
6680 +       .llseek  = seq_lseek,
6681 +       .release = seq_release
6682 +};
6683 +
6684 +static int init_or_fini(int fini)
6685 +{
6686 +       int ret = 0;
6687 +
6688 +       if (fini)
6689 +               goto cleanup;
6690 +
6691 +       if (ipt_register_match(&ipt_dstlimit)) {
6692 +               ret = -EINVAL;
6693 +               goto cleanup_nothing;
6694 +       }
6695 +
6696 +       /* FIXME: do we really want HWCACHE_ALIGN since our objects are
6697 +        * quite small ? */
6698 +       dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
6699 +                                           sizeof(struct dsthash_ent), 0,
6700 +                                           SLAB_HWCACHE_ALIGN, NULL, NULL);
6701 +       if (!dstlimit_cachep) {
6702 +               printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
6703 +               ret = -ENOMEM;
6704 +               goto cleanup_unreg_match;
6705 +       }
6706 +
6707 +       dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
6708 +       if (!dstlimit_procdir) {
6709 +               printk(KERN_ERR "Unable to create proc dir entry\n");
6710 +               ret = -ENOMEM;
6711 +               goto cleanup_free_slab;
6712 +       }
6713 +
6714 +       return ret;
6715 +
6716 +cleanup:
6717 +       remove_proc_entry("ipt_dstlimit", proc_net);
6718 +cleanup_free_slab:
6719 +       kmem_cache_destroy(dstlimit_cachep);
6720 +cleanup_unreg_match:
6721 +       ipt_unregister_match(&ipt_dstlimit);
6722 +cleanup_nothing:
6723 +       return ret;
6724 +       
6725 +}
6726 +
6727 +static int __init init(void)
6728 +{
6729 +       return init_or_fini(0);
6730 +}
6731 +
6732 +static void __exit fini(void)
6733 +{
6734 +       init_or_fini(1);
6735 +}
6736 +
6737 +module_init(init);
6738 +module_exit(fini);
6739 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.3/net/ipv4/netfilter/ipt_fuzzy.c
6740 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_fuzzy.c      1970-01-01 01:00:00.000000000 +0100
6741 +++ linux-2.6.3/net/ipv4/netfilter/ipt_fuzzy.c  2004-02-19 08:47:27.855666503 +0100
6742 @@ -0,0 +1,190 @@
6743 +/*
6744 + *  This module implements a simple TSK FLC 
6745 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
6746 + * to limit , in an adaptive and flexible way , the packet rate crossing 
6747 + * a given stream . It serves as an initial and very simple (but effective)
6748 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
6749 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
6750 + * into our code in a precise , adaptive and efficient manner. 
6751 + *  The goal is very similar to that of "limit" match , but using techniques of
6752 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
6753 + * avoiding over and undershoots - and stuff like that .
6754 + *
6755 + *
6756 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
6757 + * 2002-08-17  : Changed to eliminate floating point operations .
6758 + * 2002-08-23  : Coding style changes .
6759 +*/
6760 +
6761 +#include <linux/module.h>
6762 +#include <linux/skbuff.h>
6763 +#include <linux/ip.h>
6764 +#include <linux/random.h>
6765 +#include <net/tcp.h>
6766 +#include <linux/spinlock.h>
6767 +#include <linux/netfilter_ipv4/ip_tables.h>
6768 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
6769 +
6770 +/*
6771 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6772 + Expressed in percentage
6773 +*/
6774 +
6775 +#define PAR_LOW                1/100
6776 +#define PAR_HIGH       1
6777 +
6778 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
6779 +
6780 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
6781 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
6782 +MODULE_LICENSE("GPL");
6783 +
6784 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6785 +{
6786 +       if (tx >= maxi) return 100;
6787 +
6788 +       if (tx <= mini) return 0;
6789 +
6790 +       return ( (100*(tx-mini)) / (maxi-mini) ) ;
6791 +}
6792 +
6793 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6794 +{
6795 +       if (tx <= mini) return 100;
6796 +
6797 +       if (tx >= maxi) return 0;
6798 +
6799 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) ) ;
6800 +
6801 +}
6802 +
6803 +static int
6804 +ipt_fuzzy_match(const struct sk_buff *pskb,
6805 +              const struct net_device *in,
6806 +              const struct net_device *out,
6807 +              const void *matchinfo,
6808 +              int offset,
6809 +              const void *hdr,
6810 +              u_int16_t datalen,
6811 +              int *hotdrop)
6812 +{
6813 +       /* From userspace */
6814 +       
6815 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
6816 +
6817 +       u_int8_t random_number;
6818 +       unsigned long amount ;
6819 +       u_int8_t howhigh , howlow ;
6820 +       
6821 +
6822 +       spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
6823 +
6824 +       info->bytes_total += pskb->len ;
6825 +       info->packets_total++ ;
6826 +
6827 +       info->present_time = jiffies ;
6828 +       
6829 +       if ( info->present_time >= info->previous_time )
6830 +               amount = info->present_time - info->previous_time ;
6831 +       else { 
6832 +               /* There was a transition : I choose to re-sample 
6833 +                  and keep the old acceptance rate...
6834 +               */
6835 +
6836 +               amount = 0 ;
6837 +               info->previous_time = info->present_time ;
6838 +               info->bytes_total = info->packets_total = 0;
6839 +            };
6840 +       
6841 +       if (  amount > HZ/10 ) /* More than 100 ms elapsed ... */
6842 +               {
6843 +
6844 +       info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total )  \
6845 +                                       / amount ) ;
6846 +
6847 +               info->previous_time = info->present_time ;
6848 +               info->bytes_total = info->packets_total = 0 ;
6849 +
6850 +       howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
6851 +       howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
6852 +
6853 +    info->acceptance_rate = (u_int8_t) \
6854 +                          ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
6855 +
6856 +    /* In fact , the above defuzzification would require a denominator
6857 +       proportional to (howhigh+howlow) but , in this particular case ,
6858 +       that expression is constant .
6859 +        An imediate consequence is that it isn't necessary to call 
6860 +       both mf_high and mf_low - but to keep things understandable ,
6861 +       I did so .
6862 +     */ 
6863 +
6864 +               }
6865 +       
6866 +       spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
6867 +
6868 +
6869 +       if ( info->acceptance_rate < 100 )
6870 +       {                
6871 +               get_random_bytes((void *)(&random_number), 1);
6872 +
6873 +               /*  If within the acceptance , it can pass => don't match */
6874 +               if ( random_number <= (255 * info->acceptance_rate) / 100 )
6875 +                       return 0 ;
6876 +               else
6877 +                       return 1; /* It can't pass ( It matches ) */
6878 +       } ;
6879 +
6880 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
6881 +       
6882 +}
6883 +
6884 +static int
6885 +ipt_fuzzy_checkentry(const char *tablename,
6886 +                  const struct ipt_ip *e,
6887 +                  void *matchinfo,
6888 +                  unsigned int matchsize,
6889 +                  unsigned int hook_mask)
6890 +{
6891 +       
6892 +       const struct ipt_fuzzy_info *info = matchinfo;
6893 +
6894 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
6895 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
6896 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
6897 +               return 0;
6898 +       }
6899 +
6900 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
6901 +       || (info->minimum_rate >= info->maximum_rate ))
6902 +               {
6903 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
6904 +               return 0;
6905 +               }
6906 +
6907 +       return 1;
6908 +}
6909 +
6910 +static struct ipt_match ipt_fuzzy_reg = { 
6911 +       {NULL, NULL},
6912 +       "fuzzy",
6913 +       ipt_fuzzy_match,
6914 +       ipt_fuzzy_checkentry,
6915 +       NULL,
6916 +       THIS_MODULE };
6917 +
6918 +static int __init init(void)
6919 +{
6920 +       if (ipt_register_match(&ipt_fuzzy_reg))
6921 +               return -EINVAL;
6922 +
6923 +       return 0;
6924 +}
6925 +
6926 +static void __exit fini(void)
6927 +{
6928 +       ipt_unregister_match(&ipt_fuzzy_reg);
6929 +}
6930 +
6931 +module_init(init);
6932 +module_exit(fini);
6933 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.3/net/ipv4/netfilter/ipt_ipv4options.c
6934 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_ipv4options.c        1970-01-01 01:00:00.000000000 +0100
6935 +++ linux-2.6.3/net/ipv4/netfilter/ipt_ipv4options.c    2004-02-19 08:47:28.441525384 +0100
6936 @@ -0,0 +1,170 @@
6937 +/*
6938 +  This is a module which is used to match ipv4 options.
6939 +  This file is distributed under the terms of the GNU General Public
6940 +  License (GPL). Copies of the GPL can be obtained from:
6941 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
6942 +
6943 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
6944 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
6945 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
6946 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
6947 +*/
6948 +
6949 +#include <linux/module.h>
6950 +#include <linux/skbuff.h>
6951 +#include <net/ip.h>
6952 +
6953 +#include <linux/netfilter_ipv4/ip_tables.h>
6954 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
6955 +
6956 +MODULE_LICENSE("GPL");
6957 +
6958 +static int
6959 +match(const struct sk_buff *skb,
6960 +      const struct net_device *in,
6961 +      const struct net_device *out,
6962 +      const void *matchinfo,
6963 +      int offset,
6964 +      const void *hdr,
6965 +      u_int16_t datalen,
6966 +      int *hotdrop)
6967 +{
6968 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
6969 +       const struct iphdr *iph = skb->nh.iph;
6970 +       const struct ip_options *opt;
6971 +
6972 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
6973 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
6974 +
6975 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
6976 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
6977 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
6978 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
6979 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
6980 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
6981 +                       return 0;
6982 +               return 1;
6983 +       }
6984 +       else {
6985 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
6986 +                       /* there are options, and we don't need to care which one */
6987 +                       return 1;
6988 +               else {
6989 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
6990 +                               /* there are options but we don't want any ! */
6991 +                               return 0;
6992 +               }
6993 +       }
6994 +
6995 +       opt = &(IPCB(skb)->opt);
6996 +
6997 +       /* source routing */
6998 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
6999 +               if (!((opt->srr) & (opt->is_strictroute)))
7000 +                       return 0;
7001 +       }
7002 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
7003 +               if (!((opt->srr) & (!opt->is_strictroute)))
7004 +                       return 0;
7005 +       }
7006 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
7007 +               if (opt->srr)
7008 +                       return 0;
7009 +       }
7010 +       /* record route */
7011 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
7012 +               if (!opt->rr)
7013 +                       return 0;
7014 +       }
7015 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
7016 +               if (opt->rr)
7017 +                       return 0;
7018 +       }
7019 +       /* timestamp */
7020 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
7021 +               if (!opt->ts)
7022 +                       return 0;
7023 +       }
7024 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
7025 +               if (opt->ts)
7026 +                       return 0;
7027 +       }
7028 +       /* router-alert option  */
7029 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
7030 +               if (!opt->router_alert)
7031 +                       return 0;
7032 +       }
7033 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
7034 +               if (opt->router_alert)
7035 +                       return 0;
7036 +       }
7037 +
7038 +       /* we match ! */
7039 +       return 1;
7040 +}
7041 +
7042 +static int
7043 +checkentry(const char *tablename,
7044 +          const struct ipt_ip *ip,
7045 +          void *matchinfo,
7046 +          unsigned int matchsize,
7047 +          unsigned int hook_mask)
7048 +{
7049 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
7050 +       /* Check the size */
7051 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
7052 +               return 0;
7053 +       /* Now check the coherence of the data ... */
7054 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
7055 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
7056 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
7057 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
7058 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
7059 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
7060 +               return 0; /* opposites */
7061 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
7062 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
7063 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
7064 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
7065 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
7066 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
7067 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
7068 +               return 0; /* opposites */
7069 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
7070 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
7071 +               return 0; /* cannot match in the same time loose and strict source routing */
7072 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
7073 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
7074 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
7075 +               return 0; /* opposites */
7076 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
7077 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
7078 +               return 0; /* opposites */
7079 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
7080 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
7081 +               return 0; /* opposites */
7082 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
7083 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
7084 +               return 0; /* opposites */
7085 +
7086 +       /* everything looks ok. */
7087 +       return 1;
7088 +}
7089 +
7090 +static struct ipt_match ipv4options_match
7091 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
7092 +
7093 +static int __init init(void)
7094 +{
7095 +       printk("ipt_ipv4options loading\n");
7096 +       return ipt_register_match(&ipv4options_match);
7097 +}
7098 +
7099 +static void __exit fini(void)
7100 +{
7101 +       ipt_unregister_match(&ipv4options_match);
7102 +       printk("ipt_ipv4options unloaded\n");
7103 +}
7104 +
7105 +module_init(init);
7106 +module_exit(fini);
7107 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.3/net/ipv4/netfilter/ipt_mport.c
7108 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_mport.c      1970-01-01 01:00:00.000000000 +0100
7109 +++ linux-2.6.3/net/ipv4/netfilter/ipt_mport.c  2004-02-19 08:47:29.018386433 +0100
7110 @@ -0,0 +1,112 @@
7111 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
7112 +   the same place so we can treat them as equal. */
7113 +#include <linux/module.h>
7114 +#include <linux/types.h>
7115 +#include <linux/udp.h>
7116 +#include <linux/skbuff.h>
7117 +
7118 +#include <linux/netfilter_ipv4/ipt_mport.h>
7119 +#include <linux/netfilter_ipv4/ip_tables.h>
7120 +
7121 +MODULE_LICENSE("GPL");
7122 +
7123 +#if 0
7124 +#define duprintf(format, args...) printk(format , ## args)
7125 +#else
7126 +#define duprintf(format, args...)
7127 +#endif
7128 +
7129 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
7130 +static inline int
7131 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
7132 +{
7133 +       unsigned int i;
7134 +        unsigned int m;
7135 +        u_int16_t pflags = minfo->pflags;
7136 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
7137 +                u_int16_t s, e;
7138 +
7139 +                if (pflags & m
7140 +                    && minfo->ports[i] == 65535)
7141 +                        return 0;
7142 +
7143 +                s = minfo->ports[i];
7144 +
7145 +                if (pflags & m) {
7146 +                        e = minfo->ports[++i];
7147 +                        m <<= 1;
7148 +                } else
7149 +                        e = s;
7150 +
7151 +                if (minfo->flags & IPT_MPORT_SOURCE
7152 +                    && src >= s && src <= e)
7153 +                        return 1;
7154 +
7155 +               if (minfo->flags & IPT_MPORT_DESTINATION
7156 +                   && dst >= s && dst <= e)
7157 +                       return 1;
7158 +       }
7159 +
7160 +       return 0;
7161 +}
7162 +
7163 +static int
7164 +match(const struct sk_buff *skb,
7165 +      const struct net_device *in,
7166 +      const struct net_device *out,
7167 +      const void *matchinfo,
7168 +      int offset,
7169 +      const void *hdr,
7170 +      u_int16_t datalen,
7171 +      int *hotdrop)
7172 +{
7173 +       const struct udphdr *udp = hdr;
7174 +       const struct ipt_mport *minfo = matchinfo;
7175 +
7176 +       /* Must be big enough to read ports. */
7177 +       if (offset == 0 && datalen < sizeof(struct udphdr)) {
7178 +               /* We've been asked to examine this packet, and we
7179 +                  can't.  Hence, no choice but to drop. */
7180 +                       duprintf("ipt_mport:"
7181 +                                " Dropping evil offset=0 tinygram.\n");
7182 +                       *hotdrop = 1;
7183 +                       return 0;
7184 +       }
7185 +
7186 +       /* Must not be a fragment. */
7187 +       return !offset
7188 +               && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
7189 +}
7190 +
7191 +/* Called when user tries to insert an entry of this type. */
7192 +static int
7193 +checkentry(const char *tablename,
7194 +          const struct ipt_ip *ip,
7195 +          void *matchinfo,
7196 +          unsigned int matchsize,
7197 +          unsigned int hook_mask)
7198 +{
7199 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
7200 +               return 0;
7201 +
7202 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
7203 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
7204 +               && !(ip->invflags & IPT_INV_PROTO)
7205 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
7206 +}
7207 +
7208 +static struct ipt_match mport_match
7209 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
7210 +
7211 +static int __init init(void)
7212 +{
7213 +       return ipt_register_match(&mport_match);
7214 +}
7215 +
7216 +static void __exit fini(void)
7217 +{
7218 +       ipt_unregister_match(&mport_match);
7219 +}
7220 +
7221 +module_init(init);
7222 +module_exit(fini);
7223 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.3/net/ipv4/netfilter/ipt_nth.c
7224 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_nth.c        1970-01-01 01:00:00.000000000 +0100
7225 +++ linux-2.6.3/net/ipv4/netfilter/ipt_nth.c    2004-02-19 08:47:29.579251335 +0100
7226 @@ -0,0 +1,172 @@
7227 +/*
7228 +  This is a module which is used for match support for every Nth packet
7229 +  This file is distributed under the terms of the GNU General Public
7230 +  License (GPL). Copies of the GPL can be obtained from:
7231 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
7232 +
7233 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
7234 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
7235 +        * added support for multiple counters
7236 +        * added support for matching on individual packets
7237 +          in the counter cycle
7238 +
7239 +*/
7240 +
7241 +#include <linux/module.h>
7242 +#include <linux/skbuff.h>
7243 +#include <linux/ip.h>
7244 +#include <net/tcp.h>
7245 +#include <linux/spinlock.h>
7246 +#include <linux/netfilter_ipv4/ip_tables.h>
7247 +#include <linux/netfilter_ipv4/ipt_nth.h>
7248 +
7249 +MODULE_LICENSE("GPL");
7250 +
7251 +/*
7252 + * State information.
7253 + */
7254 +struct state {
7255 +       spinlock_t lock;
7256 +       u_int16_t number;
7257 +};
7258 +
7259 +static struct state states[IPT_NTH_NUM_COUNTERS];
7260 +
7261 +static int
7262 +ipt_nth_match(const struct sk_buff *pskb,
7263 +             const struct net_device *in,
7264 +             const struct net_device *out,
7265 +             const void *matchinfo,
7266 +             int offset,
7267 +             const void *hdr,
7268 +             u_int16_t datalen,
7269 +             int *hotdrop)
7270 +{
7271 +       /* Parameters from userspace */
7272 +       const struct ipt_nth_info *info = matchinfo;
7273 +        unsigned counter = info->counter;
7274 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
7275 +       {
7276 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
7277 +               return 0;
7278 +        };
7279 +
7280 +        spin_lock(&states[counter].lock);
7281 +
7282 +        /* Are we matching every nth packet?*/
7283 +        if (info->packet == 0xFF)
7284 +        {
7285 +               /* We're matching every nth packet and only every nth packet*/
7286 +               /* Do we match or invert match? */
7287 +               if (info->not == 0)
7288 +               {
7289 +                       if (states[counter].number == 0)
7290 +                       {
7291 +                               ++states[counter].number;
7292 +                               goto match;
7293 +                       }
7294 +                       if (states[counter].number >= info->every)
7295 +                               states[counter].number = 0; /* reset the counter */
7296 +                       else
7297 +                               ++states[counter].number;
7298 +                       goto dontmatch;
7299 +               }
7300 +               else
7301 +               {
7302 +                       if (states[counter].number == 0)
7303 +                       {
7304 +                               ++states[counter].number;
7305 +                               goto dontmatch;
7306 +                       }
7307 +                       if (states[counter].number >= info->every)
7308 +                               states[counter].number = 0;
7309 +                       else
7310 +                               ++states[counter].number;
7311 +                       goto match;
7312 +               }
7313 +        }
7314 +        else
7315 +        {
7316 +               /* We're using the --packet, so there must be a rule for every value */
7317 +               if (states[counter].number == info->packet)
7318 +               {
7319 +                       /* only increment the counter when a match happens */
7320 +                       if (states[counter].number >= info->every)
7321 +                               states[counter].number = 0; /* reset the counter */
7322 +                       else
7323 +                               ++states[counter].number;
7324 +                       goto match;
7325 +               }
7326 +               else
7327 +                       goto dontmatch;
7328 +       }
7329 +
7330 + dontmatch:
7331 +       /* don't match */
7332 +       spin_unlock(&states[counter].lock);
7333 +       return 0;
7334 +
7335 + match:
7336 +       spin_unlock(&states[counter].lock);
7337 +       return 1;
7338 +}
7339 +
7340 +static int
7341 +ipt_nth_checkentry(const char *tablename,
7342 +                  const struct ipt_ip *e,
7343 +                  void *matchinfo,
7344 +                  unsigned int matchsize,
7345 +                  unsigned int hook_mask)
7346 +{
7347 +       /* Parameters from userspace */
7348 +       const struct ipt_nth_info *info = matchinfo;
7349 +        unsigned counter = info->counter;
7350 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
7351 +       {
7352 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
7353 +                       return 0;
7354 +               };
7355 +
7356 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
7357 +               printk("nth: matchsize %u != %u\n", matchsize,
7358 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
7359 +               return 0;
7360 +       }
7361 +
7362 +       states[counter].number = info->startat;
7363 +
7364 +       return 1;
7365 +}
7366 +
7367 +static struct ipt_match ipt_nth_reg = { 
7368 +       {NULL, NULL},
7369 +       "nth",
7370 +       ipt_nth_match,
7371 +       ipt_nth_checkentry,
7372 +       NULL,
7373 +       THIS_MODULE };
7374 +
7375 +static int __init init(void)
7376 +{
7377 +       unsigned counter;
7378 +        memset(&states, 0, sizeof(states));
7379 +       if (ipt_register_match(&ipt_nth_reg))
7380 +               return -EINVAL;
7381 +
7382 +        for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
7383 +       {
7384 +               spin_lock_init(&(states[counter].lock));
7385 +        };
7386 +
7387 +       printk("ipt_nth match loaded\n");
7388 +       return 0;
7389 +}
7390 +
7391 +static void __exit fini(void)
7392 +{
7393 +       ipt_unregister_match(&ipt_nth_reg);
7394 +       printk("ipt_nth match unloaded\n");
7395 +}
7396 +
7397 +module_init(init);
7398 +module_exit(fini);
7399 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.3/net/ipv4/netfilter/ipt_osf.c
7400 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_osf.c        1970-01-01 01:00:00.000000000 +0100
7401 +++ linux-2.6.3/net/ipv4/netfilter/ipt_osf.c    2004-02-19 08:47:30.115122257 +0100
7402 @@ -0,0 +1,733 @@
7403 +/*
7404 + * ipt_osf.c
7405 + *
7406 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
7407 + *
7408 + *
7409 + * This program is free software; you can redistribute it and/or modify
7410 + * it under the terms of the GNU General Public License as published by
7411 + * the Free Software Foundation; either version 2 of the License, or
7412 + * (at your option) any later version.
7413 + *
7414 + * This program is distributed in the hope that it will be useful,
7415 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7416 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
7417 + * GNU General Public License for more details.
7418 + *
7419 + * You should have received a copy of the GNU General Public License
7420 + * along with this program; if not, write to the Free Software
7421 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7422 + */
7423 +
7424 +/*
7425 + * OS fingerprint matching module.
7426 + * It simply compares various parameters from SYN packet with
7427 + * some hardcoded ones.
7428 + *
7429 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
7430 + * for his p0f.
7431 + */
7432 +
7433 +#include <linux/config.h>
7434 +#include <linux/kernel.h>
7435 +#include <linux/smp.h>
7436 +#include <linux/module.h>
7437 +#include <linux/skbuff.h>
7438 +#include <linux/file.h>
7439 +#include <linux/ip.h>
7440 +#include <linux/proc_fs.h>
7441 +#include <linux/fs.h>
7442 +#include <linux/slab.h>
7443 +#include <linux/spinlock.h>
7444 +#include <linux/ctype.h>
7445 +#include <linux/list.h>
7446 +
7447 +#include <net/sock.h>
7448 +#include <net/ip.h>
7449 +
7450 +#include <linux/netfilter_ipv4/ip_tables.h>
7451 +
7452 +#include <linux/netfilter_ipv4/ipt_osf.h>
7453 +
7454 +#define OSF_DEBUG
7455 +
7456 +#ifdef OSF_DEBUG
7457 +#define log(x...)              printk(KERN_INFO "ipt_osf: " x)
7458 +#define loga(x...)             printk(x)
7459 +#else
7460 +#define log(x...)              do {} while(0)
7461 +#define loga(x...)             do {} while(0)
7462 +#endif
7463 +
7464 +#define FMATCH_WRONG           0
7465 +#define FMATCH_OK              1
7466 +#define FMATCH_OPT_WRONG       2
7467 +
7468 +#define OPTDEL                 ','
7469 +#define OSFPDEL                ':'
7470 +#define MAXOPTSTRLEN           128
7471 +#define OSFFLUSH               "FLUSH"
7472 +
7473 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
7474 +static struct list_head        finger_list;    
7475 +
7476 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
7477 +                     const void *, int, const void *, u_int16_t, int *);
7478 +static int checkentry(const char *, const struct ipt_ip *, void *,
7479 +                          unsigned int, unsigned int);
7480 +
7481 +static struct ipt_match osf_match = 
7482 +{ 
7483 +       { NULL, NULL }, 
7484 +       "osf", 
7485 +       &match, 
7486 +       &checkentry, 
7487 +       NULL, 
7488 +       THIS_MODULE 
7489 +};
7490 +
7491 +static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
7492 +{
7493 +       if (flags & IPT_OSF_SMART)
7494 +               return 1;
7495 +       else
7496 +               return (ip_ttl == f_ttl);
7497 +}
7498 +
7499 +static int
7500 +match(const struct sk_buff *skb,
7501 +      const struct net_device *in,
7502 +      const struct net_device *out,
7503 +      const void *matchinfo,
7504 +      int offset,
7505 +      const void *hdr,
7506 +      u_int16_t datalen,
7507 +      int *hotdrop)
7508 +{
7509 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
7510 +       struct iphdr *ip = skb->nh.iph;
7511 +       struct tcphdr *tcp;
7512 +       int fmatch = FMATCH_WRONG, fcount = 0;
7513 +       unsigned long totlen, optsize = 0, window;
7514 +       unsigned char df, *optp = NULL, *_optp = NULL;
7515 +       char check_WSS = 0;
7516 +       struct list_head *ent;
7517 +       struct osf_finger *f;
7518 +
7519 +       if (!ip || !info)
7520 +               return 0;
7521 +                               
7522 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
7523 +
7524 +       if (!tcp->syn)
7525 +               return 0;
7526 +       else if (tcp->ack)
7527 +               return 0;
7528 +       
7529 +       totlen = ntohs(ip->tot_len);
7530 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
7531 +       window = ntohs(tcp->window);
7532 +       
7533 +       if (tcp->doff*4 > sizeof(struct tcphdr))
7534 +       {
7535 +               _optp = optp = (char *)(tcp+1);
7536 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
7537 +       }
7538 +
7539 +       
7540 +       /* Actually we can create hash/table of all genres and search
7541 +        * only in appropriate part, but here is initial variant,
7542 +        * so will use slow path.
7543 +        */
7544 +       read_lock(&osf_lock);
7545 +       list_for_each(ent, &finger_list)
7546 +       {
7547 +               f = list_entry(ent, struct osf_finger, flist);
7548 +       
7549 +               if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre)) 
7550 +                       continue;
7551 +
7552 +               optp = _optp;
7553 +               fmatch = FMATCH_WRONG;
7554 +
7555 +               if (totlen == f->ss && df == f->df && 
7556 +                       smart_dec(info->flags, ip->ttl, f->ttl))
7557 +               {
7558 +                       unsigned long foptsize;
7559 +                       int optnum;
7560 +                       unsigned short mss = 0;
7561 +
7562 +                       check_WSS = 0;
7563 +
7564 +                       switch (f->wss.wc)
7565 +                       {
7566 +                               case 0:   check_WSS = 0; break;
7567 +                               case 'S': check_WSS = 1; break;
7568 +                               case 'T': check_WSS = 2; break;
7569 +                               case '%': check_WSS = 3; break;
7570 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
7571 +                                                        f->wss.wc, f->genre, f->details);
7572 +                                        check_WSS = 4;
7573 +                                        break;
7574 +                       }
7575 +                       if (check_WSS == 4)
7576 +                               continue;
7577 +
7578 +                       /* Check options */
7579 +
7580 +                       foptsize = 0;
7581 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
7582 +                               foptsize += f->opt[optnum].length;
7583 +
7584 +                               
7585 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
7586 +                               continue;
7587 +
7588 +                       if (!optp)
7589 +                       {
7590 +                               fmatch = FMATCH_OK;
7591 +                               loga("\tYEP : matching without options.\n");
7592 +                               if ((info->flags & IPT_OSF_LOG) && 
7593 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
7594 +                                       break;
7595 +                               else
7596 +                                       continue;
7597 +                       }
7598 +                       
7599 +
7600 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
7601 +                       {
7602 +                               if (f->opt[optnum].kind == (*optp))
7603 +                               {
7604 +                                       unsigned char len = f->opt[optnum].length;
7605 +                                       unsigned char *optend = optp + len;
7606 +
7607 +                                       fmatch = FMATCH_OK;
7608 +
7609 +                                       if (*optp == OSFOPT_MSS) /* MSS */
7610 +                                               mss = ntohs(*(unsigned short *)(optp+2));
7611 +                                       
7612 +                                       if (len != 1)
7613 +                                       {
7614 +                                               /* Skip kind and length fields*/
7615 +                                               optp += 2; 
7616 +
7617 +                                               if (f->opt[optnum].wc.wc != 0)
7618 +                                               {
7619 +                                                       unsigned long tmp = 0;
7620 +                                                       
7621 +                                                       /* Hmmm... It looks a bit ugly. :) */
7622 +                                                       memcpy(&tmp, &f->opt[optnum].wc.val, 
7623 +                                                               (len > sizeof(unsigned long)?
7624 +                                                                       sizeof(unsigned long):len));
7625 +
7626 +                                                       tmp = ntohl(tmp);
7627 +                                                       if (tmp != f->opt[optnum].wc.val)
7628 +                                                               fmatch = FMATCH_OPT_WRONG;
7629 +                                               }
7630 +                                       }
7631 +
7632 +                                       optp = optend;
7633 +                               }
7634 +                               else
7635 +                                       fmatch = FMATCH_OPT_WRONG;
7636 +
7637 +                               if (fmatch != FMATCH_OK)
7638 +                                       break;
7639 +                       }
7640 +
7641 +                       if (fmatch != FMATCH_OPT_WRONG)
7642 +                       {
7643 +                               fmatch = FMATCH_WRONG;
7644 +
7645 +                               switch (check_WSS)
7646 +                               {
7647 +                                       case 0:
7648 +                                               if (window == f->wss.val)
7649 +                                                       fmatch = FMATCH_OK;
7650 +                                               break;
7651 +                                       case 1: /* MSS */
7652 +                                               if (window == f->wss.val*mss)
7653 +                                                       fmatch = FMATCH_OK;
7654 +                                               break;
7655 +                                       case 2: /* MTU */
7656 +                                               if (window == f->wss.val*(mss+40))
7657 +                                                       fmatch = FMATCH_OK;
7658 +                                               break;
7659 +                                       case 3: /* MOD */
7660 +                                               if (window % f->wss.val == 0)
7661 +                                                       fmatch = FMATCH_OK;
7662 +                                               break;
7663 +                               }
7664 +                       }
7665 +                                       
7666 +
7667 +                       if (fmatch == FMATCH_OK)
7668 +                       {
7669 +                               fcount++;
7670 +                               log("%s [%s]: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
7671 +                                       f->genre, f->details,
7672 +                                       NIPQUAD(ip->saddr), ntohs(tcp->source),
7673 +                                       NIPQUAD(ip->daddr), ntohs(tcp->dest));
7674 +                               if ((info->flags & IPT_OSF_LOG) && 
7675 +                                       info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
7676 +                                       break;
7677 +                       }
7678 +               }
7679 +       }
7680 +       if (!fcount && (info->flags & IPT_OSF_LOG))
7681 +       {
7682 +               log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
7683 +               if (optp)
7684 +               {
7685 +                       unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
7686 +                       unsigned int i, optsize;
7687 +
7688 +                       optsize = tcp->doff * 4 - sizeof(struct tcphdr);
7689 +                       if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
7690 +                                         opt, optsize) < 0)
7691 +                               loga("TRUNCATED");
7692 +                       else
7693 +                               for (i = 0; i < optsize; i++)
7694 +                                       loga("%02X", opt[i]);
7695 +                       
7696 +               }  
7697 +               loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n", 
7698 +                       NIPQUAD(ip->saddr), ntohs(tcp->source),
7699 +                       NIPQUAD(ip->daddr), ntohs(tcp->dest));
7700 +       }
7701 +       read_unlock(&osf_lock);
7702 +
7703 +       return (fmatch == FMATCH_OK)?1:0;
7704 +}
7705 +
7706 +static int
7707 +checkentry(const char *tablename,
7708 +           const struct ipt_ip *ip,
7709 +           void *matchinfo,
7710 +           unsigned int matchsize,
7711 +           unsigned int hook_mask)
7712 +{
7713 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
7714 +               return 0;
7715 +       if (ip->proto != IPPROTO_TCP)
7716 +              return 0;
7717 +
7718 +       return 1;
7719 +}
7720 +
7721 +static char * osf_strchr(char *ptr, char c)
7722 +{
7723 +       char *tmp;
7724 +
7725 +       tmp = strchr(ptr, c);
7726 +
7727 +       while (tmp && tmp+1 && isspace(*(tmp+1)))
7728 +               tmp++;
7729 +
7730 +       return tmp;
7731 +}
7732 +
7733 +static struct osf_finger * finger_alloc(void)
7734 +{
7735 +       struct osf_finger *f;
7736 +
7737 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
7738 +       if (f)
7739 +               memset(f, 0, sizeof(struct osf_finger));
7740 +       
7741 +       return f;
7742 +}
7743 +
7744 +static void finger_free(struct osf_finger *f)
7745 +{
7746 +       memset(f, 0, sizeof(struct osf_finger));
7747 +       kfree(f);
7748 +}
7749 +
7750 +
7751 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
7752 +{
7753 +       int i, op;
7754 +       char *ptr, wc;
7755 +       unsigned long val;
7756 +
7757 +       ptr = &obuf[0];
7758 +       i = 0;
7759 +       while (ptr != NULL && i < olen)
7760 +       {
7761 +               val = 0;
7762 +               op = 0;
7763 +               wc = 0;
7764 +               switch (obuf[i])
7765 +               {
7766 +                       case 'N': 
7767 +                               op = OSFOPT_NOP;
7768 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7769 +                               if (ptr)
7770 +                               {
7771 +                                       *ptr = '\0';
7772 +                                       ptr++;
7773 +                                       i += (int)(ptr-&obuf[i]);
7774 +
7775 +                               }
7776 +                               else
7777 +                                       i++;
7778 +                               break;
7779 +                       case 'S': 
7780 +                               op = OSFOPT_SACKP;
7781 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7782 +                               if (ptr)
7783 +                               {
7784 +                                       *ptr = '\0';
7785 +                                       ptr++;
7786 +                                       i += (int)(ptr-&obuf[i]);
7787 +
7788 +                               }
7789 +                               else
7790 +                                       i++;
7791 +                               break;
7792 +                       case 'T': 
7793 +                               op = OSFOPT_TS;
7794 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7795 +                               if (ptr)
7796 +                               {
7797 +                                       *ptr = '\0';
7798 +                                       ptr++;
7799 +                                       i += (int)(ptr-&obuf[i]);
7800 +
7801 +                               }
7802 +                               else
7803 +                                       i++;
7804 +                               break;
7805 +                       case 'W': 
7806 +                               op = OSFOPT_WSO;
7807 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7808 +                               if (ptr)
7809 +                               {
7810 +                                       switch (obuf[i+1])
7811 +                                       {
7812 +                                               case '%':       wc = '%'; break;
7813 +                                               case 'S':       wc = 'S'; break;
7814 +                                               case 'T':       wc = 'T'; break;
7815 +                                               default:        wc = 0; break;
7816 +                                       }
7817 +                                       
7818 +                                       *ptr = '\0';
7819 +                                       ptr++;
7820 +                                       if (wc)
7821 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
7822 +                                       else
7823 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
7824 +                                       i += (int)(ptr-&obuf[i]);
7825 +
7826 +                               }
7827 +                               else
7828 +                                       i++;
7829 +                               break;
7830 +                       case 'M': 
7831 +                               op = OSFOPT_MSS;
7832 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7833 +                               if (ptr)
7834 +                               {
7835 +                                       if (obuf[i+1] == '%')
7836 +                                               wc = '%';
7837 +                                       *ptr = '\0';
7838 +                                       ptr++;
7839 +                                       if (wc)
7840 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
7841 +                                       else
7842 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
7843 +                                       i += (int)(ptr-&obuf[i]);
7844 +
7845 +                               }
7846 +                               else
7847 +                                       i++;
7848 +                               break;
7849 +                       case 'E': 
7850 +                               op = OSFOPT_EOL;
7851 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7852 +                               if (ptr)
7853 +                               {
7854 +                                       *ptr = '\0';
7855 +                                       ptr++;
7856 +                                       i += (int)(ptr-&obuf[i]);
7857 +
7858 +                               }
7859 +                               else
7860 +                                       i++;
7861 +                               break;
7862 +                       default:
7863 +                               ptr = osf_strchr(&obuf[i], OPTDEL);
7864 +                               if (ptr)
7865 +                               {
7866 +                                       ptr++;
7867 +                                       i += (int)(ptr-&obuf[i]);
7868 +
7869 +                               }
7870 +                               else
7871 +                                       i++;
7872 +                               break;
7873 +               }
7874 +
7875 +               opt[*optnum].kind       = IANA_opts[op].kind;
7876 +               opt[*optnum].length     = IANA_opts[op].length;
7877 +               opt[*optnum].wc.wc      = wc;
7878 +               opt[*optnum].wc.val     = val;
7879 +
7880 +               (*optnum)++;
7881 +       }
7882 +}
7883 +
7884 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
7885 +{
7886 +       struct list_head *ent;
7887 +       struct osf_finger *f = NULL;
7888 +       int i;
7889 +       
7890 +       *eof = 1;
7891 +       count = 0;
7892 +
7893 +       read_lock_bh(&osf_lock);
7894 +       list_for_each(ent, &finger_list)
7895 +       {
7896 +               f = list_entry(ent, struct osf_finger, flist);
7897 +
7898 +               log("%s [%s]", f->genre, f->details);
7899 +               
7900 +               count += sprintf(buf+count, "%s - %s[%s] : %s", 
7901 +                                       f->genre, f->version,
7902 +                                       f->subtype, f->details);
7903 +               
7904 +               if (f->opt_num)
7905 +               {
7906 +                       loga(" OPT: ");
7907 +                       //count += sprintf(buf+count, " OPT: ");
7908 +                       for (i=0; i<f->opt_num; ++i)
7909 +                       {
7910 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
7911 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
7912 +                               loga("%d.%c%lu; ", 
7913 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
7914 +                       }
7915 +               }
7916 +               loga("\n");
7917 +               count += sprintf(buf+count, "\n");
7918 +       }
7919 +       read_unlock_bh(&osf_lock);
7920 +
7921 +       return count;
7922 +}
7923 +
7924 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
7925 +{
7926 +       int cnt;
7927 +       unsigned long i;
7928 +       char obuf[MAXOPTSTRLEN];
7929 +       struct osf_finger *finger;
7930 +       struct list_head *ent, *n;
7931 +
7932 +       char *pbeg, *pend;
7933 +
7934 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
7935 +       {
7936 +               int i = 0;
7937 +               write_lock_bh(&osf_lock);
7938 +               list_for_each_safe(ent, n, &finger_list)
7939 +               {
7940 +                       i++;
7941 +                       finger = list_entry(ent, struct osf_finger, flist);
7942 +                       list_del(&finger->flist);
7943 +                       finger_free(finger);
7944 +               }
7945 +               write_unlock_bh(&osf_lock);
7946 +       
7947 +               log("Flushed %d entries.\n", i);
7948 +               
7949 +               return count;
7950 +       }
7951 +
7952 +       
7953 +       cnt = 0;
7954 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
7955 +               if (buffer[i] == ':')
7956 +                       cnt++;
7957 +
7958 +       if (cnt != 8 || i != count)
7959 +       {
7960 +               log("Wrong input line cnt=%d[8], len=%lu[%lu]\n", 
7961 +                       cnt, i, count);
7962 +               return count;
7963 +       }
7964 +
7965 +       memset(obuf, 0, sizeof(obuf));
7966 +       
7967 +       finger = finger_alloc();
7968 +       if (!finger)
7969 +       {
7970 +               log("Failed to allocate new fingerprint entry.\n");
7971 +               return -ENOMEM;
7972 +       }
7973 +
7974 +       pbeg = (char *)buffer;
7975 +       pend = osf_strchr(pbeg, OSFPDEL);
7976 +       if (pend)
7977 +       {
7978 +               *pend = '\0';
7979 +               if (pbeg[0] == 'S')
7980 +               {
7981 +                       finger->wss.wc = 'S';
7982 +                       if (pbeg[1] == '%')
7983 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
7984 +                       else if (pbeg[1] == '*')
7985 +                               finger->wss.val = 0;
7986 +                       else 
7987 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
7988 +               }
7989 +               else if (pbeg[0] == 'T')
7990 +               {
7991 +                       finger->wss.wc = 'T';
7992 +                       if (pbeg[1] == '%')
7993 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
7994 +                       else if (pbeg[1] == '*')
7995 +                               finger->wss.val = 0;
7996 +                       else 
7997 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
7998 +               }
7999 +               if (isdigit(pbeg[0]))
8000 +               {
8001 +                       finger->wss.wc = 0;
8002 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
8003 +               }
8004 +
8005 +               pbeg = pend+1;
8006 +       }
8007 +       pend = osf_strchr(pbeg, OSFPDEL);
8008 +       if (pend)
8009 +       {
8010 +               *pend = '\0';
8011 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
8012 +               pbeg = pend+1;
8013 +       }
8014 +       pend = osf_strchr(pbeg, OSFPDEL);
8015 +       if (pend)
8016 +       {
8017 +               *pend = '\0';
8018 +               finger->df = simple_strtoul(pbeg, NULL, 10);
8019 +               pbeg = pend+1;
8020 +       }
8021 +       pend = osf_strchr(pbeg, OSFPDEL);
8022 +       if (pend)
8023 +       {
8024 +               *pend = '\0';
8025 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
8026 +               pbeg = pend+1;
8027 +       }
8028 +
8029 +       pend = osf_strchr(pbeg, OSFPDEL);
8030 +       if (pend)
8031 +       {
8032 +               *pend = '\0';
8033 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
8034 +               pbeg = pend+1;
8035 +       }
8036 +
8037 +       pend = osf_strchr(pbeg, OSFPDEL);
8038 +       if (pend)
8039 +       {
8040 +               *pend = '\0';
8041 +               if (pbeg[0] == '@' || pbeg[0] == '*')
8042 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
8043 +               else
8044 +                       cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
8045 +               pbeg = pend+1;
8046 +       }
8047 +       
8048 +       pend = osf_strchr(pbeg, OSFPDEL);
8049 +       if (pend)
8050 +       {
8051 +               *pend = '\0';
8052 +               cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
8053 +               pbeg = pend+1;
8054 +       }
8055 +       
8056 +       pend = osf_strchr(pbeg, OSFPDEL);
8057 +       if (pend)
8058 +       {
8059 +               *pend = '\0';
8060 +               cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
8061 +               pbeg = pend+1;
8062 +       }
8063 +
8064 +       cnt = snprintf(finger->details, 
8065 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
8066 +                       "%s", pbeg);
8067 +       
8068 +       log("%s - %s[%s] : %s\n", 
8069 +               finger->genre, finger->version,
8070 +               finger->subtype, finger->details);
8071 +       
8072 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
8073 +       
8074 +
8075 +       write_lock_bh(&osf_lock);
8076 +       list_add_tail(&finger->flist, &finger_list);
8077 +       write_unlock_bh(&osf_lock);
8078 +
8079 +       return count;
8080 +}
8081 +
8082 +static int __init osf_init(void)
8083 +{
8084 +       int err;
8085 +       struct proc_dir_entry *p;
8086 +
8087 +       log("Startng OS fingerprint matching module.\n");
8088 +
8089 +       INIT_LIST_HEAD(&finger_list);
8090 +       
8091 +       err = ipt_register_match(&osf_match);
8092 +       if (err)
8093 +       {
8094 +               log("Failed to register OS fingerprint matching module.\n");
8095 +               return -ENXIO;
8096 +       }
8097 +
8098 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
8099 +       if (!p)
8100 +       {
8101 +               ipt_unregister_match(&osf_match);
8102 +               return -ENXIO;
8103 +       }
8104 +
8105 +       p->write_proc = osf_proc_write;
8106 +       p->read_proc  = osf_proc_read;
8107 +
8108 +       return 0;
8109 +}
8110 +
8111 +static void __exit osf_fini(void)
8112 +{
8113 +       struct list_head *ent, *n;
8114 +       struct osf_finger *f;
8115 +       
8116 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
8117 +       ipt_unregister_match(&osf_match);
8118 +
8119 +       list_for_each_safe(ent, n, &finger_list)
8120 +       {
8121 +               f = list_entry(ent, struct osf_finger, flist);
8122 +               list_del(&f->flist);
8123 +               finger_free(f);
8124 +       }
8125 +       
8126 +       log("OS fingerprint matching module finished.\n");
8127 +}
8128 +
8129 +module_init(osf_init);
8130 +module_exit(osf_fini);
8131 +
8132 +MODULE_LICENSE("GPL");
8133 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
8134 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
8135 +
8136 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.3/net/ipv4/netfilter/ipt_pool.c
8137 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_pool.c       1970-01-01 01:00:00.000000000 +0100
8138 +++ linux-2.6.3/net/ipv4/netfilter/ipt_pool.c   2004-02-19 08:47:30.713978008 +0100
8139 @@ -0,0 +1,71 @@
8140 +/* Kernel module to match an IP address pool. */
8141 +
8142 +#include <linux/module.h>
8143 +#include <linux/ip.h>
8144 +#include <linux/skbuff.h>
8145 +
8146 +#include <linux/netfilter_ipv4/ip_tables.h>
8147 +#include <linux/netfilter_ipv4/ip_pool.h>
8148 +#include <linux/netfilter_ipv4/ipt_pool.h>
8149 +
8150 +static inline int match_pool(
8151 +       ip_pool_t index,
8152 +       __u32 addr,
8153 +       int inv
8154 +) {
8155 +       if (ip_pool_match(index, ntohl(addr)))
8156 +               inv = !inv;
8157 +       return inv;
8158 +}
8159 +
8160 +static int match(
8161 +       const struct sk_buff *skb,
8162 +       const struct net_device *in,
8163 +       const struct net_device *out,
8164 +       const void *matchinfo,
8165 +       int offset,
8166 +       const void *hdr,
8167 +       u_int16_t datalen,
8168 +       int *hotdrop
8169 +) {
8170 +       const struct ipt_pool_info *info = matchinfo;
8171 +       const struct iphdr *iph = skb->nh.iph;
8172 +
8173 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
8174 +                                               info->flags&IPT_POOL_INV_SRC))
8175 +               return 0;
8176 +
8177 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
8178 +                                               info->flags&IPT_POOL_INV_DST))
8179 +               return 0;
8180 +
8181 +       return 1;
8182 +}
8183 +
8184 +static int checkentry(
8185 +       const char *tablename,
8186 +       const struct ipt_ip *ip,
8187 +       void *matchinfo,
8188 +       unsigned int matchsize,
8189 +       unsigned int hook_mask
8190 +) {
8191 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
8192 +               return 0;
8193 +       return 1;
8194 +}
8195 +
8196 +static struct ipt_match pool_match
8197 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
8198 +
8199 +static int __init init(void)
8200 +{
8201 +       return ipt_register_match(&pool_match);
8202 +}
8203 +
8204 +static void __exit fini(void)
8205 +{
8206 +       ipt_unregister_match(&pool_match);
8207 +}
8208 +
8209 +module_init(init);
8210 +module_exit(fini);
8211 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.3/net/ipv4/netfilter/ipt_psd.c
8212 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_psd.c        1970-01-01 01:00:00.000000000 +0100
8213 +++ linux-2.6.3/net/ipv4/netfilter/ipt_psd.c    2004-02-19 08:47:31.249848931 +0100
8214 @@ -0,0 +1,361 @@
8215 +/*
8216 +  This is a module which is used for PSD (portscan detection)
8217 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
8218 +  and LOG target module.
8219 +
8220 +  Copyright (C) 2000,2001 astaro AG
8221 +
8222 +  This file is distributed under the terms of the GNU General Public
8223 +  License (GPL). Copies of the GPL can be obtained from:
8224 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
8225 +
8226 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
8227 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
8228 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
8229 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
8230 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
8231 +*/
8232 +
8233 +#include <linux/module.h>
8234 +#include <linux/skbuff.h>
8235 +#include <linux/ip.h>
8236 +#include <net/tcp.h>
8237 +#include <linux/spinlock.h>
8238 +#include <linux/netfilter_ipv4/ip_tables.h>
8239 +#include <linux/netfilter_ipv4/ipt_psd.h>
8240 +
8241 +#if 0
8242 +#define DEBUGP printk
8243 +#else
8244 +#define DEBUGP(format, args...)
8245 +#endif
8246 +
8247 +MODULE_LICENSE("GPL");
8248 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
8249 +
8250 +#define HF_DADDR_CHANGING   0x01
8251 +#define HF_SPORT_CHANGING   0x02
8252 +#define HF_TOS_CHANGING            0x04
8253 +#define HF_TTL_CHANGING            0x08
8254 +            
8255 +/*
8256 + * Information we keep per each target port
8257 + */
8258 +struct port {
8259 +       u_int16_t number;      /* port number */ 
8260 +       u_int8_t proto;        /* protocol number */
8261 +       u_int8_t and_flags;    /* tcp ANDed flags */
8262 +       u_int8_t or_flags;     /* tcp ORed flags */
8263 +};
8264 +
8265 +/*
8266 + * Information we keep per each source address.
8267 + */
8268 +struct host {
8269 +       struct host *next;              /* Next entry with the same hash */
8270 +       clock_t timestamp;              /* Last update time */
8271 +       struct in_addr src_addr;        /* Source address */
8272 +       struct in_addr dest_addr;       /* Destination address */
8273 +       unsigned short src_port;        /* Source port */
8274 +       int count;                      /* Number of ports in the list */
8275 +       int weight;                     /* Total weight of ports in the list */
8276 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
8277 +       unsigned char tos;              /* TOS */
8278 +       unsigned char ttl;              /* TTL */
8279 +       unsigned char flags;            /* HF_ flags bitmask */
8280 +};
8281 +
8282 +/*
8283 + * State information.
8284 + */
8285 +static struct {
8286 +       spinlock_t lock;
8287 +       struct host list[LIST_SIZE];    /* List of source addresses */
8288 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
8289 +       int index;                      /* Oldest entry to be replaced */
8290 +} state;
8291 +
8292 +/*
8293 + * Convert an IP address into a hash table index.
8294 + */
8295 +static inline int hashfunc(struct in_addr addr)
8296 +{
8297 +       unsigned int value;
8298 +       int hash;
8299 +
8300 +       value = addr.s_addr;
8301 +       hash = 0;
8302 +       do {
8303 +               hash ^= value;
8304 +       } while ((value >>= HASH_LOG));
8305 +
8306 +       return hash & (HASH_SIZE - 1);
8307 +}
8308 +
8309 +static int
8310 +ipt_psd_match(const struct sk_buff *pskb,
8311 +             const struct net_device *in,
8312 +             const struct net_device *out,
8313 +             const void *matchinfo,
8314 +             int offset,
8315 +             const void *hdr,
8316 +             u_int16_t datalen,
8317 +             int *hotdrop)
8318 +{
8319 +       struct iphdr *ip_hdr;
8320 +       struct tcphdr *tcp_hdr;
8321 +       struct in_addr addr;
8322 +       u_int16_t src_port,dest_port;
8323 +       u_int8_t tcp_flags, proto;
8324 +       clock_t now;
8325 +       struct host *curr, *last, **head;
8326 +       int hash, index, count;
8327 +
8328 +       /* Parameters from userspace */
8329 +       const struct ipt_psd_info *psdinfo = matchinfo;
8330 +
8331 +       /* IP header */
8332 +       ip_hdr = pskb->nh.iph;
8333 +
8334 +       /* Sanity check */
8335 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
8336 +               DEBUGP("PSD: sanity check failed\n");
8337 +               return 0;
8338 +       }
8339 +
8340 +       /* TCP or UDP ? */
8341 +       proto = ip_hdr->protocol;
8342 +
8343 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
8344 +               DEBUGP("PSD: protocol not supported\n");
8345 +               return 0;
8346 +       }
8347 +
8348 +       /* Get the source address, source & destination ports, and TCP flags */
8349 +
8350 +       addr.s_addr = ip_hdr->saddr;
8351 +
8352 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
8353 +
8354 +       /* Yep, it´s dirty */
8355 +       src_port = tcp_hdr->source;
8356 +       dest_port = tcp_hdr->dest;
8357 +
8358 +       if (proto == IPPROTO_TCP) {
8359 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
8360 +       }
8361 +       else {
8362 +               tcp_flags = 0x00;
8363 +       }
8364 +
8365 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
8366 +        * them spoof us. [DHCP needs this feature - HW] */
8367 +       if (!addr.s_addr) {
8368 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
8369 +               return 0;
8370 +       }
8371 +
8372 +       /* Use jiffies here not to depend on someone setting the time while we're
8373 +        * running; we need to be careful with possible return value overflows. */
8374 +       now = jiffies;
8375 +
8376 +       spin_lock(&state.lock);
8377 +
8378 +       /* Do we know this source address already? */
8379 +       count = 0;
8380 +       last = NULL;
8381 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
8382 +               do {
8383 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
8384 +                       count++;
8385 +                       if (curr->next) last = curr;
8386 +               } while ((curr = curr->next));
8387 +
8388 +       if (curr) {
8389 +
8390 +               /* We know this address, and the entry isn't too old. Update it. */
8391 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
8392 +                   time_after_eq(now, curr->timestamp)) {
8393 +
8394 +                       /* Just update the appropriate list entry if we've seen this port already */
8395 +                       for (index = 0; index < curr->count; index++) {
8396 +                               if (curr->ports[index].number == dest_port) {
8397 +                                       curr->ports[index].proto = proto;
8398 +                                       curr->ports[index].and_flags &= tcp_flags;
8399 +                                       curr->ports[index].or_flags |= tcp_flags;
8400 +                                       goto out_no_match;
8401 +                               }
8402 +                       }
8403 +
8404 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
8405 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
8406 +                               goto out_no_match;
8407 +
8408 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
8409 +                       curr->timestamp = now;
8410 +
8411 +                       /* Logged this scan already? Then drop the packet. */
8412 +                       if (curr->weight >= psdinfo->weight_threshold)
8413 +                               goto out_match;
8414 +
8415 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
8416 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
8417 +                               curr->flags |= HF_DADDR_CHANGING;
8418 +                       if (curr->src_port != src_port)
8419 +                               curr->flags |= HF_SPORT_CHANGING;
8420 +                       if (curr->tos != ip_hdr->tos)
8421 +                               curr->flags |= HF_TOS_CHANGING;
8422 +                       if (curr->ttl != ip_hdr->ttl)
8423 +                               curr->flags |= HF_TTL_CHANGING;
8424 +
8425 +                       /* Update the total weight */
8426 +                       curr->weight += (ntohs(dest_port) < 1024) ?
8427 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
8428 +
8429 +                       /* Got enough destination ports to decide that this is a scan? */
8430 +                       /* Then log it and drop the packet. */
8431 +                       if (curr->weight >= psdinfo->weight_threshold)
8432 +                               goto out_match;
8433 +
8434 +                       /* Remember the new port */
8435 +                       if (curr->count < SCAN_MAX_COUNT) {
8436 +                               curr->ports[curr->count].number = dest_port;
8437 +                               curr->ports[curr->count].proto = proto;
8438 +                               curr->ports[curr->count].and_flags = tcp_flags;
8439 +                               curr->ports[curr->count].or_flags = tcp_flags;
8440 +                               curr->count++;
8441 +                       }
8442 +
8443 +                       goto out_no_match;
8444 +               }
8445 +
8446 +               /* We know this address, but the entry is outdated. Mark it unused, and
8447 +                * remove from the hash table. We'll allocate a new entry instead since
8448 +                * this one might get re-used too soon. */
8449 +               curr->src_addr.s_addr = 0;
8450 +               if (last)
8451 +                       last->next = last->next->next;
8452 +               else if (*head)
8453 +                       *head = (*head)->next;
8454 +               last = NULL;
8455 +       }
8456 +
8457 +       /* We don't need an ACK from a new source address */
8458 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
8459 +               goto out_no_match;
8460 +
8461 +       /* Got too many source addresses with the same hash value? Then remove the
8462 +        * oldest one from the hash table, so that they can't take too much of our
8463 +        * CPU time even with carefully chosen spoofed IP addresses. */
8464 +       if (count >= HASH_MAX && last) last->next = NULL;
8465 +
8466 +       /* We're going to re-use the oldest list entry, so remove it from the hash
8467 +        * table first (if it is really already in use, and isn't removed from the
8468 +        * hash table already because of the HASH_MAX check above). */
8469 +
8470 +       /* First, find it */
8471 +       if (state.list[state.index].src_addr.s_addr)
8472 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
8473 +       else
8474 +               head = &last;
8475 +       last = NULL;
8476 +       if ((curr = *head))
8477 +       do {
8478 +               if (curr == &state.list[state.index]) break;
8479 +               last = curr;
8480 +       } while ((curr = curr->next));
8481 +
8482 +       /* Then, remove it */
8483 +       if (curr) {
8484 +               if (last)
8485 +                       last->next = last->next->next;
8486 +               else if (*head)
8487 +                       *head = (*head)->next;
8488 +       }
8489 +
8490 +       /* Get our list entry */
8491 +       curr = &state.list[state.index++];
8492 +       if (state.index >= LIST_SIZE) state.index = 0;
8493 +
8494 +       /* Link it into the hash table */
8495 +       head = &state.hash[hash];
8496 +       curr->next = *head;
8497 +       *head = curr;
8498 +
8499 +       /* And fill in the fields */
8500 +       curr->timestamp = now;
8501 +       curr->src_addr = addr;
8502 +       curr->dest_addr.s_addr = ip_hdr->daddr;
8503 +       curr->src_port = src_port;
8504 +       curr->count = 1;
8505 +       curr->weight = (ntohs(dest_port) < 1024) ?
8506 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
8507 +       curr->ports[0].number = dest_port;
8508 +       curr->ports[0].proto = proto;
8509 +       curr->ports[0].and_flags = tcp_flags;
8510 +       curr->ports[0].or_flags = tcp_flags;
8511 +       curr->tos = ip_hdr->tos;
8512 +       curr->ttl = ip_hdr->ttl;
8513 +
8514 +out_no_match:
8515 +       spin_unlock(&state.lock);
8516 +       return 0;
8517 +
8518 +out_match:
8519 +       spin_unlock(&state.lock);
8520 +       return 1;
8521 +}
8522 +
8523 +static int ipt_psd_checkentry(const char *tablename,
8524 +                             const struct ipt_ip *e,
8525 +                             void *matchinfo,
8526 +                             unsigned int matchsize,
8527 +                             unsigned int hook_mask)
8528 +{
8529 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
8530 +
8531 +       /* we accept TCP only */
8532 +/*     if (e->ip.proto != IPPROTO_TCP) { */
8533 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
8534 +/*             return 0; */
8535 +/*     } */
8536 +
8537 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
8538 +               DEBUGP("PSD: matchsize %u != %u\n",
8539 +                      matchsize,
8540 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
8541 +               return 0;
8542 +       }
8543 +
8544 +       return 1;
8545 +}
8546 +
8547 +static struct ipt_match ipt_psd_reg = { 
8548 +       {NULL, NULL},
8549 +       "psd",
8550 +       ipt_psd_match,
8551 +       ipt_psd_checkentry,
8552 +       NULL,
8553 +       THIS_MODULE };
8554 +
8555 +static int __init init(void)
8556 +{
8557 +       if (ipt_register_match(&ipt_psd_reg))
8558 +               return -EINVAL;
8559 +
8560 +       memset(&state, 0, sizeof(state));
8561 +
8562 +       spin_lock_init(&(state.lock));
8563 +
8564 +       printk("netfilter PSD loaded - (c) astaro AG\n");
8565 +       return 0;
8566 +}
8567 +
8568 +static void __exit fini(void)
8569 +{
8570 +       ipt_unregister_match(&ipt_psd_reg);
8571 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
8572 +}
8573 +
8574 +module_init(init);
8575 +module_exit(fini);
8576 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.3/net/ipv4/netfilter/ipt_quota.c
8577 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_quota.c      1970-01-01 01:00:00.000000000 +0100
8578 +++ linux-2.6.3/net/ipv4/netfilter/ipt_quota.c  2004-02-19 08:47:31.780721057 +0100
8579 @@ -0,0 +1,81 @@
8580 +/* 
8581 + * netfilter module to enforce network quotas
8582 + *
8583 + * Sam Johnston <samj@samj.net>
8584 + */
8585 +#include <linux/module.h>
8586 +#include <linux/skbuff.h>
8587 +#include <linux/spinlock.h>
8588 +#include <linux/interrupt.h>
8589 +
8590 +#include <linux/netfilter_ipv4/ip_tables.h>
8591 +#include <linux/netfilter_ipv4/ipt_quota.h>
8592 +
8593 +MODULE_LICENSE("GPL");
8594 +
8595 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
8596 +
8597 +static int
8598 +match(const struct sk_buff *skb,
8599 +      const struct net_device *in,
8600 +      const struct net_device *out,
8601 +      const void *matchinfo,
8602 +      int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
8603 +{
8604 +
8605 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
8606 +
8607 +        spin_lock_bh(&quota_lock);
8608 +
8609 +        if (q->quota >= datalen) {
8610 +                /* we can afford this one */
8611 +                q->quota -= datalen;
8612 +                spin_unlock_bh(&quota_lock);
8613 +
8614 +#ifdef DEBUG_IPT_QUOTA
8615 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
8616 +#endif
8617 +                return 1;
8618 +        }
8619 +
8620 +        /* so we do not allow even small packets from now on */
8621 +        q->quota = 0;
8622 +
8623 +#ifdef DEBUG_IPT_QUOTA
8624 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
8625 +#endif
8626 +
8627 +        spin_unlock_bh(&quota_lock);
8628 +        return 0;
8629 +}
8630 +
8631 +static int
8632 +checkentry(const char *tablename,
8633 +           const struct ipt_ip *ip,
8634 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
8635 +{
8636 +        /* TODO: spinlocks? sanity checks? */
8637 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
8638 +                return 0;
8639 +
8640 +        return 1;
8641 +}
8642 +
8643 +static struct ipt_match quota_match
8644 +    = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
8645 +
8646 +static int __init
8647 +init(void)
8648 +{
8649 +        return ipt_register_match(&quota_match);
8650 +}
8651 +
8652 +static void __exit
8653 +fini(void)
8654 +{
8655 +        ipt_unregister_match(&quota_match);
8656 +}
8657 +
8658 +module_init(init);
8659 +module_exit(fini);
8660 +
8661 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.3/net/ipv4/netfilter/ipt_random.c
8662 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_random.c     1970-01-01 01:00:00.000000000 +0100
8663 +++ linux-2.6.3/net/ipv4/netfilter/ipt_random.c 2004-02-19 08:47:32.336587163 +0100
8664 @@ -0,0 +1,96 @@
8665 +/*
8666 +  This is a module which is used for a "random" match support.
8667 +  This file is distributed under the terms of the GNU General Public
8668 +  License (GPL). Copies of the GPL can be obtained from:
8669 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
8670 +
8671 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
8672 +*/
8673 +
8674 +#include <linux/module.h>
8675 +#include <linux/skbuff.h>
8676 +#include <linux/ip.h>
8677 +#include <linux/random.h>
8678 +#include <net/tcp.h>
8679 +#include <linux/spinlock.h>
8680 +#include <linux/netfilter_ipv4/ip_tables.h>
8681 +#include <linux/netfilter_ipv4/ipt_random.h>
8682 +
8683 +MODULE_LICENSE("GPL");
8684 +
8685 +static int
8686 +ipt_rand_match(const struct sk_buff *pskb,
8687 +              const struct net_device *in,
8688 +              const struct net_device *out,
8689 +              const void *matchinfo,
8690 +              int offset,
8691 +              const void *hdr,
8692 +              u_int16_t datalen,
8693 +              int *hotdrop)
8694 +{
8695 +       /* Parameters from userspace */
8696 +       const struct ipt_rand_info *info = matchinfo;
8697 +       u_int8_t random_number;
8698 +
8699 +       /* get 1 random number from the kernel random number generation routine */
8700 +       get_random_bytes((void *)(&random_number), 1);
8701 +
8702 +       /* Do we match ? */
8703 +       if (random_number <= info->average)
8704 +               return 1;
8705 +       else
8706 +               return 0;
8707 +}
8708 +
8709 +static int
8710 +ipt_rand_checkentry(const char *tablename,
8711 +                  const struct ipt_ip *e,
8712 +                  void *matchinfo,
8713 +                  unsigned int matchsize,
8714 +                  unsigned int hook_mask)
8715 +{
8716 +       /* Parameters from userspace */
8717 +       const struct ipt_rand_info *info = matchinfo;
8718 +
8719 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
8720 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
8721 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
8722 +               return 0;
8723 +       }
8724 +
8725 +       /* must be  1 <= average % <= 99 */
8726 +       /* 1  x 2.55 = 2   */
8727 +       /* 99 x 2.55 = 252 */
8728 +       if ((info->average < 2) || (info->average > 252)) {
8729 +               printk("ipt_random:  invalid average %u\n", info->average);
8730 +               return 0;
8731 +       }
8732 +
8733 +       return 1;
8734 +}
8735 +
8736 +static struct ipt_match ipt_rand_reg = { 
8737 +       {NULL, NULL},
8738 +       "random",
8739 +       ipt_rand_match,
8740 +       ipt_rand_checkentry,
8741 +       NULL,
8742 +       THIS_MODULE };
8743 +
8744 +static int __init init(void)
8745 +{
8746 +       if (ipt_register_match(&ipt_rand_reg))
8747 +               return -EINVAL;
8748 +
8749 +       printk("ipt_random match loaded\n");
8750 +       return 0;
8751 +}
8752 +
8753 +static void __exit fini(void)
8754 +{
8755 +       ipt_unregister_match(&ipt_rand_reg);
8756 +       printk("ipt_random match unloaded\n");
8757 +}
8758 +
8759 +module_init(init);
8760 +module_exit(fini);
8761 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.3/net/ipv4/netfilter/ipt_realm.c
8762 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_realm.c      1970-01-01 01:00:00.000000000 +0100
8763 +++ linux-2.6.3/net/ipv4/netfilter/ipt_realm.c  2004-02-19 08:47:33.450318894 +0100
8764 @@ -0,0 +1,68 @@
8765 +/* Kernel module to match realm from routing. */
8766 +#include <linux/module.h>
8767 +#include <linux/skbuff.h>
8768 +#include <linux/netdevice.h>
8769 +#include <net/route.h>
8770 +
8771 +#include <linux/netfilter_ipv4/ipt_realm.h>
8772 +#include <linux/netfilter_ipv4/ip_tables.h>
8773 +
8774 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
8775 +MODULE_LICENSE("GPL");
8776 +
8777 +static int
8778 +match(const struct sk_buff *skb,
8779 +      const struct net_device *in,
8780 +      const struct net_device *out,
8781 +      const void *matchinfo,
8782 +      int offset,
8783 +      const void *hdr,
8784 +      u_int16_t datalen,
8785 +      int *hotdrop)
8786 +{
8787 +       const struct ipt_realm_info *info = matchinfo;
8788 +       struct dst_entry *dst = skb->dst;
8789 +       u32 id;
8790 +    
8791 +       if(dst == NULL)
8792 +               return 0;
8793 +       id = dst->tclassid;
8794 +
8795 +       return (info->id == (id & info->mask)) ^ info->invert;
8796 +}
8797 +
8798 +static int check(const char *tablename,
8799 +                 const struct ipt_ip *ip,
8800 +                 void *matchinfo,
8801 +                 unsigned int matchsize,
8802 +                 unsigned int hook_mask)
8803 +{
8804 +       if (hook_mask
8805 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
8806 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
8807 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
8808 +                      "LOCAL_IN or FORWARD.\n");
8809 +               return 0;
8810 +       }
8811 +
8812 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
8813 +               return 0;
8814 +
8815 +       return 1;
8816 +}
8817 +
8818 +static struct ipt_match realm_match
8819 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
8820 +
8821 +static int __init init(void)
8822 +{
8823 +       return ipt_register_match(&realm_match);
8824 +}
8825 +
8826 +static void __exit fini(void)
8827 +{
8828 +       ipt_unregister_match(&realm_match);
8829 +}
8830 +
8831 +module_init(init);
8832 +module_exit(fini);
8833 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.3/net/ipv4/netfilter/ipt_time.c
8834 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_time.c       1970-01-01 01:00:00.000000000 +0100
8835 +++ linux-2.6.3/net/ipv4/netfilter/ipt_time.c   2004-02-19 08:47:33.998186927 +0100
8836 @@ -0,0 +1,185 @@
8837 +/*
8838 +  This is a module which is used for time matching
8839 +  It is using some modified code from dietlibc (localtime() function)
8840 +  that you can find at http://www.fefe.de/dietlibc/
8841 +  This file is distributed under the terms of the GNU General Public
8842 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
8843 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
8844 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
8845 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
8846 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
8847 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
8848 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
8849 +*/
8850 +
8851 +#include <linux/module.h>
8852 +#include <linux/skbuff.h>
8853 +#include <linux/netfilter_ipv4/ip_tables.h>
8854 +#include <linux/netfilter_ipv4/ipt_time.h>
8855 +#include <linux/time.h>
8856 +
8857 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
8858 +MODULE_DESCRIPTION("Match arrival timestamp");
8859 +MODULE_LICENSE("GPL");
8860 +
8861 +struct tm
8862 +{
8863 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
8864 +       int tm_min;                   /* Minutes.     [0-59] */
8865 +       int tm_hour;                  /* Hours.       [0-23] */
8866 +       int tm_mday;                  /* Day.         [1-31] */
8867 +       int tm_mon;                   /* Month.       [0-11] */
8868 +       int tm_year;                  /* Year - 1900.  */
8869 +       int tm_wday;                  /* Day of week. [0-6] */
8870 +       int tm_yday;                  /* Days in year.[0-365] */
8871 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
8872 +
8873 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
8874 +       const char *tm_zone;          /* we don't care, we count from GMT */
8875 +};
8876 +
8877 +void
8878 +localtime(const time_t *timepr, struct tm *r);
8879 +
8880 +static int
8881 +match(const struct sk_buff *skb,
8882 +      const struct net_device *in,
8883 +      const struct net_device *out,
8884 +      const void *matchinfo,
8885 +      int offset,
8886 +      const void *hdr,
8887 +      u_int16_t datalen,
8888 +      int *hotdrop)
8889 +{
8890 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
8891 +       struct tm currenttime;                          /* time human readable */
8892 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
8893 +       u_int16_t packet_time;
8894 +       struct timeval kerneltimeval;
8895 +       time_t packet_local_time;
8896 +
8897 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
8898 +       if (info->kerneltime)
8899 +       {
8900 +               do_gettimeofday(&kerneltimeval);
8901 +               packet_local_time = kerneltimeval.tv_sec;
8902 +       }
8903 +       else
8904 +               packet_local_time = skb->stamp.tv_sec;
8905 +
8906 +       /* Transform the timestamp of the packet, in a human readable form */
8907 +       localtime(&packet_local_time, &currenttime);
8908 +
8909 +       /* check if we match this timestamp, we start by the days... */
8910 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
8911 +               return 0; /* the day doesn't match */
8912 +
8913 +       /* ... check the time now */
8914 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
8915 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
8916 +               return 0;
8917 +
8918 +       /* here we match ! */
8919 +       return 1;
8920 +}
8921 +
8922 +static int
8923 +checkentry(const char *tablename,
8924 +           const struct ipt_ip *ip,
8925 +           void *matchinfo,
8926 +           unsigned int matchsize,
8927 +           unsigned int hook_mask)
8928 +{
8929 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
8930 +
8931 +       /* First, check that we are in the correct hook */
8932 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
8933 +       if (hook_mask
8934 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
8935 +       {
8936 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
8937 +               return 0;
8938 +       }
8939 +       /* we use the kerneltime if we are in forward or output */
8940 +       info->kerneltime = 1;
8941 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
8942 +               /* if not, we use the skb time */
8943 +               info->kerneltime = 0;
8944 +
8945 +       /* Check the size */
8946 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
8947 +               return 0;
8948 +       /* Now check the coherence of the data ... */
8949 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
8950 +           (info->time_stop  > 1439))
8951 +       {
8952 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
8953 +               return 0;
8954 +       }
8955 +
8956 +       return 1;
8957 +}
8958 +
8959 +static struct ipt_match time_match
8960 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
8961 +
8962 +static int __init init(void)
8963 +{
8964 +       printk("ipt_time loading\n");
8965 +       return ipt_register_match(&time_match);
8966 +}
8967 +
8968 +static void __exit fini(void)
8969 +{
8970 +       ipt_unregister_match(&time_match);
8971 +       printk("ipt_time unloaded\n");
8972 +}
8973 +
8974 +module_init(init);
8975 +module_exit(fini);
8976 +
8977 +
8978 +/* The part below is borowed and modified from dietlibc */
8979 +
8980 +/* seconds per day */
8981 +#define SPD 24*60*60
8982 +
8983 +void
8984 +localtime(const time_t *timepr, struct tm *r) {
8985 +       time_t i;
8986 +       time_t timep;
8987 +       extern struct timezone sys_tz;
8988 +       const unsigned int __spm[12] =
8989 +               { 0,
8990 +                 (31),
8991 +                 (31+28),
8992 +                 (31+28+31),
8993 +                 (31+28+31+30),
8994 +                 (31+28+31+30+31),
8995 +                 (31+28+31+30+31+30),
8996 +                 (31+28+31+30+31+30+31),
8997 +                 (31+28+31+30+31+30+31+31),
8998 +                 (31+28+31+30+31+30+31+31+30),
8999 +                 (31+28+31+30+31+30+31+31+30+31),
9000 +                 (31+28+31+30+31+30+31+31+30+31+30),
9001 +               };
9002 +       register time_t work;
9003 +
9004 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
9005 +       work=timep%(SPD);
9006 +       r->tm_sec=work%60; work/=60;
9007 +       r->tm_min=work%60; r->tm_hour=work/60;
9008 +       work=timep/(SPD);
9009 +       r->tm_wday=(4+work)%7;
9010 +       for (i=1970; ; ++i) {
9011 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
9012 +               if (work>k)
9013 +                       work-=k;
9014 +               else
9015 +                       break;
9016 +       }
9017 +       r->tm_year=i-1900;
9018 +       for (i=11; i && __spm[i]>work; --i) ;
9019 +       r->tm_mon=i;
9020 +       r->tm_mday=work-__spm[i]+1;
9021 +}
9022 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.3/net/ipv4/netfilter/ipt_u32.c
9023 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_u32.c        1970-01-01 01:00:00.000000000 +0100
9024 +++ linux-2.6.3/net/ipv4/netfilter/ipt_u32.c    2004-02-19 08:47:34.549054238 +0100
9025 @@ -0,0 +1,211 @@
9026 +/* Kernel module to match u32 packet content. */
9027 +
9028 +/* 
9029 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
9030 +have specified values.  The specification of what to extract is general 
9031 +enough to find data at given offsets from tcp headers or payloads.
9032 +
9033 + --u32 tests
9034 + The argument amounts to a program in a small language described below.
9035 + tests := location = value |  tests && location = value
9036 + value := range | value , range
9037 + range := number | number : number
9038 +  a single number, n, is interpreted the same as n:n
9039 +  n:m is interpreted as the range of numbers >=n and <=m
9040 + location := number | location operator number
9041 + operator := & | << | >> | @
9042 +
9043 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
9044 + membership operator and the value syntax describes a set.  The @ operator
9045 + is what allows moving to the next header and is described further below.
9046 +
9047 + *** Until I can find out how to avoid it, there are some artificial limits
9048 + on the size of the tests:
9049 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
9050 + - no more than 10 ranges (and 9 commas) per value
9051 + - no more than 10 numbers (and 9 operators) per location
9052 +
9053 + To describe the meaning of location, imagine the following machine that
9054 + interprets it.  There are three registers:
9055 +  A is of type char*, initially the address of the IP header
9056 +  B and C are unsigned 32 bit integers, initially zero
9057 +
9058 +  The instructions are:
9059 +   number      B = number;
9060 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
9061 +   &number     C = C&number
9062 +   <<number    C = C<<number
9063 +   >>number    C = C>>number
9064 +   @number     A = A+C; then do the instruction number
9065 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
9066 +  Otherwise the result of the computation is the final value of C.
9067 +
9068 + Whitespace is allowed but not required in the tests.
9069 + However the characters that do occur there are likely to require
9070 + shell quoting, so it's a good idea to enclose the arguments in quotes.
9071 +
9072 +Example:
9073 + match IP packets with total length >= 256
9074 + The IP header contains a total length field in bytes 2-3.
9075 + --u32 "0&0xFFFF=0x100:0xFFFF" 
9076 + read bytes 0-3
9077 + AND that with FFFF (giving bytes 2-3),
9078 + and test whether that's in the range [0x100:0xFFFF]
9079 +
9080 +Example: (more realistic, hence more complicated)
9081 + match icmp packets with icmp type 0
9082 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
9083 + --u32 "6&0xFF=1 && ...
9084 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
9085 + Next test that it's not a fragment.
9086 +  (If so it might be part of such a packet but we can't always tell.)
9087 +  n.b. This test is generally needed if you want to match anything
9088 +  beyond the IP header.
9089 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
9090 + packet (not a fragment).  Alternatively, you can allow first fragments
9091 + by only testing the last 5 bits of byte 6.
9092 + ... 4&0x3FFF=0 && ...
9093 + Last test: the first byte past the IP header (the type) is 0
9094 + This is where we have to use the @syntax.  The length of the IP header
9095 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
9096 + IP header itself.
9097 + ... 0>>22&0x3C@0>>24=0"
9098 + The first 0 means read bytes 0-3,
9099 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
9100 +   the first byte, so only 22 bits is four times that plus a few more bits.
9101 + &3C then eliminates the two extra bits on the right and the first four 
9102 + bits of the first byte.
9103 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
9104 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
9105 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
9106 + @ means to use this number as a new offset into the packet, and read
9107 + four bytes starting from there.  This is the first 4 bytes of the icmp
9108 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
9109 + the value 24 to the right to throw out all but the first byte and compare
9110 + the result with 0.
9111 +
9112 +Example: 
9113 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
9114 + First we test that the packet is a tcp packet (similar to icmp).
9115 + --u32 "6&0xFF=6 && ...
9116 + Next, test that it's not a fragment (same as above).
9117 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
9118 + 0>>22&3C as above computes the number of bytes in the IP header.
9119 + @ makes this the new offset into the packet, which is the start of the
9120 + tcp header.  The length of the tcp header (again in 32 bit words) is
9121 + the left half of byte 12 of the tcp header.  The 12>>26&3C
9122 + computes this length in bytes (similar to the IP header before).
9123 + @ makes this the new offset, which is the start of the tcp payload.
9124 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
9125 + result is any of 1, 2, 5 or 8
9126 +*/
9127 +
9128 +#include <linux/module.h>
9129 +#include <linux/skbuff.h>
9130 +
9131 +#include <linux/netfilter_ipv4/ipt_u32.h>
9132 +#include <linux/netfilter_ipv4/ip_tables.h>
9133 +
9134 +/* #include <asm-i386/timex.h> for timing */
9135 +
9136 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
9137 +MODULE_DESCRIPTION("IP tables u32 matching module");
9138 +MODULE_LICENSE("GPL");
9139 +
9140 +static int
9141 +match(const struct sk_buff *skb,
9142 +      const struct net_device *in,
9143 +      const struct net_device *out,
9144 +      const void *matchinfo,
9145 +      int offset,
9146 +      const void *hdr,
9147 +      u_int16_t datalen,
9148 +      int *hotdrop)
9149 +{
9150 +       const struct ipt_u32 *data = matchinfo;
9151 +       int testind, i;
9152 +       unsigned char* origbase = (char*)skb->nh.iph;
9153 +       unsigned char* base = origbase;
9154 +       unsigned char* head = skb->head;
9155 +       unsigned char* end = skb->end;
9156 +       int nnums, nvals;
9157 +       u_int32_t pos, val;
9158 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
9159 +          cycles1 = get_cycles(); */
9160 +
9161 +       for (testind=0; testind < data->ntests; testind++) {
9162 +               base = origbase; /* reset for each test */
9163 +               pos = data->tests[testind].location[0].number;
9164 +               if (base+pos+3 > end || base+pos < head) 
9165 +                       return 0;
9166 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
9167 +                       (base[pos+2]<<8) + base[pos+3];
9168 +               nnums = data->tests[testind].nnums;
9169 +               for (i=1; i < nnums; i++) {
9170 +                       u_int32_t number = data->tests[testind].location[i].number;
9171 +                       switch (data->tests[testind].location[i].nextop) {
9172 +                       case IPT_U32_AND: 
9173 +                               val = val & number; 
9174 +                               break;
9175 +                       case IPT_U32_LEFTSH: 
9176 +                               val = val << number;
9177 +                               break;
9178 +                       case IPT_U32_RIGHTSH: 
9179 +                               val = val >> number; 
9180 +                               break;
9181 +                       case IPT_U32_AT:
9182 +                               base = base + val;
9183 +                               pos = number;
9184 +                               if (base+pos+3 > end || base+pos < head) 
9185 +                                       return 0;
9186 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
9187 +                                       (base[pos+2]<<8) + base[pos+3];
9188 +                               break;
9189 +                       }
9190 +               }
9191 +               nvals = data->tests[testind].nvalues;
9192 +               for (i=0; i < nvals; i++) {
9193 +                       if ((data->tests[testind].value[i].min <= val) &&
9194 +                           (val <= data->tests[testind].value[i].max)) {
9195 +                               break;
9196 +                       }
9197 +               }
9198 +               if (i >= data->tests[testind].nvalues) {
9199 +                       /* cycles2 = get_cycles(); 
9200 +                          printk("failed %d in %d cycles\n", testind, 
9201 +                                 cycles2-cycles1); */
9202 +                       return 0;
9203 +               }
9204 +       }
9205 +       /* cycles2 = get_cycles();
9206 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
9207 +       return 1;
9208 +}
9209 +
9210 +static int
9211 +checkentry(const char *tablename,
9212 +           const struct ipt_ip *ip,
9213 +           void *matchinfo,
9214 +           unsigned int matchsize,
9215 +           unsigned int hook_mask)
9216 +{
9217 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
9218 +               return 0;
9219 +       return 1;
9220 +}
9221 +
9222 +static struct ipt_match u32_match
9223 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
9224 +
9225 +static int __init init(void)
9226 +{
9227 +       return ipt_register_match(&u32_match);
9228 +}
9229 +
9230 +static void __exit fini(void)
9231 +{
9232 +       ipt_unregister_match(&u32_match);
9233 +}
9234 +
9235 +module_init(init);
9236 +module_exit(fini);
9237 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/Kconfig linux-2.6.3/net/ipv6/netfilter/Kconfig
9238 --- linux-2.6.3.org/net/ipv6/netfilter/Kconfig  2004-02-18 04:59:20.000000000 +0100
9239 +++ linux-2.6.3/net/ipv6/netfilter/Kconfig      2004-02-19 08:47:32.341585959 +0100
9240 @@ -218,5 +218,85 @@
9241           To compile it as a module, choose M here.  If unsure, say N.
9242  
9243  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
9244 +config IP6_NF_TARGET_HL
9245 +       tristate  'HL target support'
9246 +       depends on IP6_NF_MANGLE
9247 +         help
9248 +         This allows the user to set the IPv6 Hop Limit value on a packet or
9249 +         to increment or decrement it by a given value.
9250 +         
9251 +         Example:
9252 +         # ip6tables -t mangle -A OUTPUT -j HL --hl-inc 1
9253 +         # ip6tables -t mangle -A INPUT -j HL --hl-eq 64
9254 +         # ip6tables -t mangle -A OUTPUT -j HL --hl-dec 2
9255 +
9256 +config IP6_NF_TARGET_REJECT
9257 +       tristate  'REJECT target support'
9258 +       depends on IP6_NF_FILTER
9259 +         help
9260 +         This CONFIG_IP6_NF_TARGET_REJECT option adds a REJECT target to ip6tables.
9261 +         Please keep in mind that the icmp-types are different from the icmpv6 types
9262 +         (see ip6tables -j REJECT -h for more info)
9263 +
9264 +config IP6_NF_MATCH_FUZZY
9265 +       tristate  'Fuzzy match support'
9266 +       depends on IP6_NF_FILTER
9267 +         help
9268 +         This option adds a `fuzzy' match which allows you to match packets according to
9269 +         a dynamic profile implemented by means of a simple Fuzzy Logic Controller (FLC)
9270 +
9271 +config IP6_NF_MATCH_NTH
9272 +       tristate  'Nth match support'
9273 +       depends on IP6_NF_IPTABLES
9274 +         help
9275 +         This option adds an iptables `Nth' match, which allows you to match every Nth
9276 +         packet encountered.  By default there are 16 different counters that can be
9277 +         used.
9278 +         
9279 +         This match functions in one of two ways
9280 +         1) Match ever Nth packet, and only the Nth packet.
9281 +            example:
9282 +             iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
9283 +            This rule will drop every 10th packet.
9284 +         2) Unique rule for every packet.  This is an easy and quick
9285 +            method to produce load-balancing for both inbound and outbound.
9286 +            example:
9287 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
9288 +                      --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
9289 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
9290 +                      --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
9291 +             iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
9292 +                      --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
9293 +            This example evenly splits connections between the three SNAT
9294 +            addresses.
9295 +         
9296 +            By using the mangle table and iproute2, you can setup complex
9297 +            load-balanced routing.  There's lot of other uses.  Be creative!
9298 +         
9299 +         Suppported options are:
9300 +            --every     Nth         Match every Nth packet
9301 +           [--counter]  num         Use counter 0-15 (default:0)
9302 +           [--start]    num         Initialize the counter at the number 'num'
9303 +                                    instead of 0. Must be between 0 and Nth-1
9304 +           [--packet]   num         Match on 'num' packet. Must be between 0
9305 +                                    and Nth-1.
9306 +                                    If --packet is used for a counter than
9307 +                                    there must be Nth number of --packet
9308 +                                    rules, covering all values between 0 and
9309 +                                    Nth-1 inclusively.
9310 +
9311 +config IP6_NF_MATCH_RANDOM
9312 +       tristate  'Random match support'
9313 +       depends on IP6_NF_IPTABLES
9314 +         help
9315 +         This option adds a `random' match,
9316 +         which allow you to match packets randomly
9317 +         following a given probability. 
9318 +         
9319 +         Suppported options are:
9320 +         
9321 +         [--average]   percent will match randomly packets with a probability of
9322 +                       'percent'. default is 50%
9323 +
9324  endmenu
9325  
9326 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/Makefile linux-2.6.3/net/ipv6/netfilter/Makefile
9327 --- linux-2.6.3.org/net/ipv6/netfilter/Makefile 2004-02-18 04:58:26.000000000 +0100
9328 +++ linux-2.6.3/net/ipv6/netfilter/Makefile     2004-02-19 08:47:32.341585959 +0100
9329 @@ -8,6 +8,7 @@
9330  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
9331  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
9332  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
9333 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
9334  obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
9335  obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
9336  obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
9337 @@ -19,6 +20,12 @@
9338  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
9339  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
9340  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
9341 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
9342  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
9343  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
9344 +
9345 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
9346 +
9347 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
9348 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
9349  obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
9350 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.3/net/ipv6/netfilter/ip6t_HL.c
9351 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_HL.c        1970-01-01 01:00:00.000000000 +0100
9352 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_HL.c    2004-02-19 09:07:45.267493759 +0100
9353 @@ -0,0 +1,105 @@
9354 +/* 
9355 + * Hop Limit modification target for ip6tables
9356 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
9357 + * Based on HW's TTL module
9358 + *
9359 + * This software is distributed under the terms of GNU GPL
9360 + */
9361 +
9362 +#include <linux/module.h>
9363 +#include <linux/skbuff.h>
9364 +#include <linux/ip.h>
9365 +
9366 +#include <linux/netfilter_ipv6/ip6_tables.h>
9367 +#include <linux/netfilter_ipv6/ip6t_HL.h>
9368 +
9369 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
9370 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
9371 +MODULE_LICENSE("GPL");
9372 +
9373 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
9374 +               const struct net_device *in, const struct net_device *out,
9375 +               const void *targinfo, void *userinfo)
9376 +{
9377 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
9378 +       const struct ip6t_HL_info *info = targinfo;
9379 +       u_int16_t diffs[2];
9380 +       int new_hl;
9381 +                        
9382 +       switch (info->mode) {
9383 +               case IP6T_HL_SET:
9384 +                       new_hl = info->hop_limit;
9385 +                       break;
9386 +               case IP6T_HL_INC:
9387 +                       new_hl = ip6h->hop_limit + info->hop_limit;
9388 +                       if (new_hl > 255)
9389 +                               new_hl = 255;
9390 +                       break;
9391 +               case IP6T_HL_DEC:
9392 +                       new_hl = ip6h->hop_limit + info->hop_limit;
9393 +                       if (new_hl < 0)
9394 +                               new_hl = 0;
9395 +                       break;
9396 +               default:
9397 +                       new_hl = ip6h->hop_limit;
9398 +                       break;
9399 +       }
9400 +
9401 +       if (new_hl != ip6h->hop_limit) {
9402 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
9403 +               ip6h->hop_limit = new_hl;
9404 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
9405 +       }
9406 +
9407 +       return IP6T_CONTINUE;
9408 +}
9409 +
9410 +static int ip6t_hl_checkentry(const char *tablename,
9411 +               const struct ip6t_entry *e,
9412 +               void *targinfo,
9413 +               unsigned int targinfosize,
9414 +               unsigned int hook_mask)
9415 +{
9416 +       struct ip6t_HL_info *info = targinfo;
9417 +
9418 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
9419 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
9420 +                               targinfosize,
9421 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
9422 +               return 0;       
9423 +       }       
9424 +
9425 +       if (strcmp(tablename, "mangle")) {
9426 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9427 +               return 0;
9428 +       }
9429 +
9430 +       if (info->mode > IP6T_HL_MAXMODE) {
9431 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
9432 +                       info->mode);
9433 +               return 0;
9434 +       }
9435 +
9436 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
9437 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
9438 +               return 0;
9439 +       }
9440 +       
9441 +       return 1;
9442 +}
9443 +
9444 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
9445 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
9446 +
9447 +static int __init init(void)
9448 +{
9449 +       return ip6t_register_target(&ip6t_HL);
9450 +}
9451 +
9452 +static void __exit fini(void)
9453 +{
9454 +       ip6t_unregister_target(&ip6t_HL);
9455 +}
9456 +
9457 +module_init(init);
9458 +module_exit(fini);
9459 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.3/net/ipv6/netfilter/ip6t_REJECT.c
9460 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_REJECT.c    1970-01-01 01:00:00.000000000 +0100
9461 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_REJECT.c        2004-02-19 08:47:25.025348256 +0100
9462 @@ -0,0 +1,274 @@
9463 +/*
9464 + * This is a module which is used for rejecting packets.
9465 + *     Added support for customized reject packets (Jozsef Kadlecsik).
9466 + * Sun 12 Nov 2000
9467 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
9468 + */
9469 +#include <linux/config.h>
9470 +#include <linux/module.h>
9471 +#include <linux/skbuff.h>
9472 +#include <linux/icmpv6.h>
9473 +#include <net/tcp.h>
9474 +#include <linux/netfilter_ipv6/ip6_tables.h>
9475 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
9476 +
9477 +#if 1
9478 +#define DEBUGP printk
9479 +#else
9480 +#define DEBUGP(format, args...)
9481 +#endif
9482 +
9483 +#if 0
9484 +/* Send RST reply */
9485 +static void send_reset(struct sk_buff *oldskb)
9486 +{
9487 +       struct sk_buff *nskb;
9488 +       struct tcphdr *otcph, *tcph;
9489 +       struct rtable *rt;
9490 +       unsigned int otcplen;
9491 +       int needs_ack;
9492 +
9493 +       /* IP header checks: fragment, too short. */
9494 +       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
9495 +           || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
9496 +               return;
9497 +
9498 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
9499 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
9500 +
9501 +       /* No RST for RST. */
9502 +       if (otcph->rst)
9503 +               return;
9504 +
9505 +       /* Check checksum. */
9506 +       if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
9507 +                        oldskb->nh.iph->daddr,
9508 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
9509 +               return;
9510 +
9511 +       /* Copy skb (even if skb is about to be dropped, we can't just
9512 +           clone it because there may be other things, such as tcpdump,
9513 +           interested in it) */
9514 +       nskb = skb_copy(oldskb, GFP_ATOMIC);
9515 +       if (!nskb)
9516 +               return;
9517 +
9518 +       /* This packet will not be the same as the other: clear nf fields */
9519 +       nf_conntrack_put(nskb->nfct);
9520 +       nskb->nfct = NULL;
9521 +       nskb->nfcache = 0;
9522 +#ifdef CONFIG_NETFILTER_DEBUG
9523 +       nskb->nf_debug = 0;
9524 +#endif
9525 +
9526 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
9527 +
9528 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
9529 +       tcph->source = xchg(&tcph->dest, tcph->source);
9530 +
9531 +       /* Truncate to length (no data) */
9532 +       tcph->doff = sizeof(struct tcphdr)/4;
9533 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
9534 +       nskb->nh.iph->tot_len = htons(nskb->len);
9535 +
9536 +       if (tcph->ack) {
9537 +               needs_ack = 0;
9538 +               tcph->seq = otcph->ack_seq;
9539 +               tcph->ack_seq = 0;
9540 +       } else {
9541 +               needs_ack = 1;
9542 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
9543 +                                     + otcplen - (otcph->doff<<2));
9544 +               tcph->seq = 0;
9545 +       }
9546 +
9547 +       /* Reset flags */
9548 +       ((u_int8_t *)tcph)[13] = 0;
9549 +       tcph->rst = 1;
9550 +       tcph->ack = needs_ack;
9551 +
9552 +       tcph->window = 0;
9553 +       tcph->urg_ptr = 0;
9554 +
9555 +       /* Adjust TCP checksum */
9556 +       tcph->check = 0;
9557 +       tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
9558 +                                  nskb->nh.iph->saddr,
9559 +                                  nskb->nh.iph->daddr,
9560 +                                  csum_partial((char *)tcph,
9561 +                                               sizeof(struct tcphdr), 0));
9562 +
9563 +       /* Adjust IP TTL, DF */
9564 +       nskb->nh.iph->ttl = MAXTTL;
9565 +       /* Set DF, id = 0 */
9566 +       nskb->nh.iph->frag_off = htons(IP_DF);
9567 +       nskb->nh.iph->id = 0;
9568 +
9569 +       /* Adjust IP checksum */
9570 +       nskb->nh.iph->check = 0;
9571 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
9572 +                                          nskb->nh.iph->ihl);
9573 +
9574 +       /* Routing */
9575 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
9576 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
9577 +                           0) != 0)
9578 +               goto free_nskb;
9579 +
9580 +       dst_release(nskb->dst);
9581 +       nskb->dst = &rt->u.dst;
9582 +
9583 +       /* "Never happens" */
9584 +       if (nskb->len > nskb->dst->pmtu)
9585 +               goto free_nskb;
9586 +
9587 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
9588 +               ip_finish_output);
9589 +       return;
9590 +
9591 + free_nskb:
9592 +       kfree_skb(nskb);
9593 +}
9594 +#endif
9595 +
9596 +static unsigned int reject6_target(struct sk_buff **pskb,
9597 +                          unsigned int hooknum,
9598 +                          const struct net_device *in,
9599 +                          const struct net_device *out,
9600 +                          const void *targinfo,
9601 +                          void *userinfo)
9602 +{
9603 +       const struct ip6t_reject_info *reject = targinfo;
9604 +
9605 +       /* WARNING: This code causes reentry within ip6tables.
9606 +          This means that the ip6tables jump stack is now crap.  We
9607 +          must return an absolute verdict. --RR */
9608 +       DEBUGP("REJECTv6: calling icmpv6_send\n");
9609 +       switch (reject->with) {
9610 +       case IP6T_ICMP6_NO_ROUTE:
9611 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
9612 +               break;
9613 +       case IP6T_ICMP6_ADM_PROHIBITED:
9614 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
9615 +               break;
9616 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
9617 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
9618 +               break;
9619 +       case IP6T_ICMP6_ADDR_UNREACH:
9620 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
9621 +               break;
9622 +       case IP6T_ICMP6_PORT_UNREACH:
9623 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
9624 +               break;
9625 +#if 0
9626 +       case IPT_ICMP_ECHOREPLY: {
9627 +               struct icmp6hdr *icmph  = (struct icmphdr *)
9628 +                       ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
9629 +               unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
9630 +
9631 +               /* Not non-head frags, or truncated */
9632 +               if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
9633 +                   && datalen >= 4) {
9634 +                       /* Usually I don't like cut & pasting code,
9635 +                           but dammit, my party is starting in 45
9636 +                           mins! --RR */
9637 +                       struct icmp_bxm icmp_param;
9638 +
9639 +                       icmp_param.icmph=*icmph;
9640 +                       icmp_param.icmph.type=ICMP_ECHOREPLY;
9641 +                       icmp_param.data_ptr=(icmph+1);
9642 +                       icmp_param.data_len=datalen;
9643 +                       icmp_reply(&icmp_param, *pskb);
9644 +               }
9645 +       }
9646 +       break;
9647 +       case IPT_TCP_RESET:
9648 +               send_reset(*pskb);
9649 +               break;
9650 +#endif
9651 +       default:
9652 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
9653 +               break;
9654 +       }
9655 +
9656 +       return NF_DROP;
9657 +}
9658 +
9659 +static inline int find_ping_match(const struct ip6t_entry_match *m)
9660 +{
9661 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
9662 +
9663 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
9664 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
9665 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
9666 +               return 1;
9667 +
9668 +       return 0;
9669 +}
9670 +
9671 +static int check(const char *tablename,
9672 +                const struct ip6t_entry *e,
9673 +                void *targinfo,
9674 +                unsigned int targinfosize,
9675 +                unsigned int hook_mask)
9676 +{
9677 +       const struct ip6t_reject_info *rejinfo = targinfo;
9678 +
9679 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
9680 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
9681 +               return 0;
9682 +       }
9683 +
9684 +       /* Only allow these for packet filtering. */
9685 +       if (strcmp(tablename, "filter") != 0) {
9686 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
9687 +               return 0;
9688 +       }
9689 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
9690 +                          | (1 << NF_IP6_FORWARD)
9691 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
9692 +               DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
9693 +               return 0;
9694 +       }
9695 +
9696 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
9697 +               /* Must specify that it's an ICMP ping packet. */
9698 +               if (e->ipv6.proto != IPPROTO_ICMPV6
9699 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
9700 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
9701 +                       return 0;
9702 +               }
9703 +               /* Must contain ICMP match. */
9704 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
9705 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
9706 +                       return 0;
9707 +               }
9708 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
9709 +               /* Must specify that it's a TCP packet */
9710 +               if (e->ipv6.proto != IPPROTO_TCP
9711 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
9712 +                       DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
9713 +                       return 0;
9714 +               }
9715 +       }
9716 +
9717 +       return 1;
9718 +}
9719 +
9720 +static struct ip6t_target ip6t_reject_reg
9721 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
9722 +
9723 +static int __init init(void)
9724 +{
9725 +       if (ip6t_register_target(&ip6t_reject_reg))
9726 +               return -EINVAL;
9727 +       return 0;
9728 +}
9729 +
9730 +static void __exit fini(void)
9731 +{
9732 +       ip6t_unregister_target(&ip6t_reject_reg);
9733 +}
9734 +
9735 +module_init(init);
9736 +module_exit(fini);
9737 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.3/net/ipv6/netfilter/ip6t_fuzzy.c
9738 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_fuzzy.c     1970-01-01 01:00:00.000000000 +0100
9739 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_fuzzy.c 2004-02-19 08:47:27.856666262 +0100
9740 @@ -0,0 +1,189 @@
9741 +/*
9742 + * This module implements a simple TSK FLC
9743 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
9744 + * to limit , in an adaptive and flexible way , the packet rate crossing
9745 + * a given stream . It serves as an initial and very simple (but effective)
9746 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
9747 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
9748 + * into our code in a precise , adaptive and efficient manner.
9749 + *  The goal is very similar to that of "limit" match , but using techniques of
9750 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
9751 + * avoiding over and undershoots - and stuff like that .
9752 + *
9753 + *
9754 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
9755 + * 2002-08-17  : Changed to eliminate floating point operations .
9756 + * 2002-08-23  : Coding style changes .
9757 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
9758 + */
9759 +
9760 +#include <linux/module.h>
9761 +#include <linux/skbuff.h>
9762 +#include <linux/ipv6.h>
9763 +#include <linux/random.h>
9764 +#include <net/tcp.h>
9765 +#include <linux/spinlock.h>
9766 +#include <linux/netfilter_ipv6/ip6_tables.h>
9767 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
9768 +
9769 +/*
9770 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
9771 + Expressed in percentage
9772 +*/
9773 +
9774 +#define PAR_LOW                1/100
9775 +#define PAR_HIGH       1
9776 +
9777 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
9778 +
9779 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
9780 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
9781 +MODULE_LICENSE("GPL");
9782 +
9783 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
9784 +{
9785 +       if (tx >= maxi) return 100;
9786 +
9787 +       if (tx <= mini) return 0;
9788 +
9789 +       return ((100 * (tx-mini)) / (maxi-mini));
9790 +}
9791 +
9792 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
9793 +{
9794 +       if (tx <= mini) return 100;
9795 +
9796 +       if (tx >= maxi) return 0;
9797 +
9798 +       return ((100 * (maxi - tx)) / (maxi - mini));
9799 +
9800 +}
9801 +
9802 +static int
9803 +ip6t_fuzzy_match(const struct sk_buff *pskb,
9804 +              const struct net_device *in,
9805 +              const struct net_device *out,
9806 +              const void *matchinfo,
9807 +              int offset,
9808 +              const void *hdr,
9809 +              u_int16_t datalen,
9810 +              int *hotdrop)
9811 +{
9812 +       /* From userspace */
9813 +
9814 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
9815 +
9816 +       u_int8_t random_number;
9817 +       unsigned long amount;
9818 +       u_int8_t howhigh, howlow;
9819 +
9820 +
9821 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
9822 +
9823 +       info->bytes_total += pskb->len;
9824 +       info->packets_total++;
9825 +
9826 +       info->present_time = jiffies;
9827 +
9828 +       if (info->present_time >= info->previous_time)
9829 +               amount = info->present_time - info->previous_time;
9830 +       else {
9831 +               /* There was a transition : I choose to re-sample
9832 +                  and keep the old acceptance rate...
9833 +               */
9834 +
9835 +               amount = 0;
9836 +               info->previous_time = info->present_time;
9837 +               info->bytes_total = info->packets_total = 0;
9838 +            };
9839 +
9840 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
9841 +
9842 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
9843 +                                       / amount);
9844 +
9845 +               info->previous_time = info->present_time;
9846 +               info->bytes_total = info->packets_total = 0;
9847 +
9848 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
9849 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
9850 +
9851 +               info->acceptance_rate = (u_int8_t) \
9852 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
9853 +
9854 +       /* In fact, the above defuzzification would require a denominator
9855 +        * proportional to (howhigh+howlow) but, in this particular case,
9856 +        * that expression is constant.
9857 +        * An imediate consequence is that it is not necessary to call
9858 +        * both mf_high and mf_low - but to keep things understandable,
9859 +        * I did so.
9860 +        */
9861 +
9862 +       }
9863 +
9864 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
9865 +
9866 +
9867 +       if (info->acceptance_rate < 100)
9868 +       {
9869 +               get_random_bytes((void *)(&random_number), 1);
9870 +
9871 +               /*  If within the acceptance , it can pass => don't match */
9872 +               if (random_number <= (255 * info->acceptance_rate) / 100)
9873 +                       return 0;
9874 +               else
9875 +                       return 1; /* It can't pass (It matches) */
9876 +       };
9877 +
9878 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
9879 +
9880 +}
9881 +
9882 +static int
9883 +ip6t_fuzzy_checkentry(const char *tablename,
9884 +                  const struct ip6t_ip6 *ip,
9885 +                  void *matchinfo,
9886 +                  unsigned int matchsize,
9887 +                  unsigned int hook_mask)
9888 +{
9889 +
9890 +       const struct ip6t_fuzzy_info *info = matchinfo;
9891 +
9892 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
9893 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
9894 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
9895 +               return 0;
9896 +       }
9897 +
9898 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
9899 +        || (info->minimum_rate >= info->maximum_rate)) {
9900 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
9901 +               return 0;
9902 +       }
9903 +
9904 +       return 1;
9905 +}
9906 +
9907 +static struct ip6t_match ip6t_fuzzy_reg = {
9908 +       {NULL, NULL},
9909 +       "fuzzy",
9910 +       ip6t_fuzzy_match,
9911 +       ip6t_fuzzy_checkentry,
9912 +       NULL,
9913 +       THIS_MODULE };
9914 +
9915 +static int __init init(void)
9916 +{
9917 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
9918 +               return -EINVAL;
9919 +
9920 +       return 0;
9921 +}
9922 +
9923 +static void __exit fini(void)
9924 +{
9925 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
9926 +}
9927 +
9928 +module_init(init);
9929 +module_exit(fini);
9930 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.3/net/ipv6/netfilter/ip6t_nth.c
9931 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_nth.c       1970-01-01 01:00:00.000000000 +0100
9932 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_nth.c   2004-02-19 08:47:29.580251094 +0100
9933 @@ -0,0 +1,173 @@
9934 +/*
9935 +  This is a module which is used for match support for every Nth packet
9936 +  This file is distributed under the terms of the GNU General Public
9937 +  License (GPL). Copies of the GPL can be obtained from:
9938 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
9939 +
9940 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
9941 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
9942 +        * added support for multiple counters
9943 +        * added support for matching on individual packets
9944 +          in the counter cycle
9945 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
9946 +
9947 +*/
9948 +
9949 +#include <linux/module.h>
9950 +#include <linux/skbuff.h>
9951 +#include <linux/ip.h>
9952 +#include <net/tcp.h>
9953 +#include <linux/spinlock.h>
9954 +#include <linux/netfilter_ipv6/ip6_tables.h>
9955 +#include <linux/netfilter_ipv6/ip6t_nth.h>
9956 +
9957 +MODULE_LICENSE("GPL");
9958 +
9959 +/*
9960 + * State information.
9961 + */
9962 +struct state {
9963 +       spinlock_t lock;
9964 +       u_int16_t number;
9965 +};
9966 +
9967 +static struct state states[IP6T_NTH_NUM_COUNTERS];
9968 +
9969 +static int
9970 +ip6t_nth_match(const struct sk_buff *pskb,
9971 +             const struct net_device *in,
9972 +             const struct net_device *out,
9973 +             const void *matchinfo,
9974 +             int offset,
9975 +             const void *hdr,
9976 +             u_int16_t datalen,
9977 +             int *hotdrop)
9978 +{
9979 +       /* Parameters from userspace */
9980 +       const struct ip6t_nth_info *info = matchinfo;
9981 +        unsigned counter = info->counter;
9982 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
9983 +       {
9984 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
9985 +               return 0;
9986 +        };
9987 +
9988 +        spin_lock(&states[counter].lock);
9989 +
9990 +        /* Are we matching every nth packet?*/
9991 +        if (info->packet == 0xFF)
9992 +        {
9993 +               /* We're matching every nth packet and only every nth packet*/
9994 +               /* Do we match or invert match? */
9995 +               if (info->not == 0)
9996 +               {
9997 +                       if (states[counter].number == 0)
9998 +                       {
9999 +                               ++states[counter].number;
10000 +                               goto match;
10001 +                       }
10002 +                       if (states[counter].number >= info->every)
10003 +                               states[counter].number = 0; /* reset the counter */
10004 +                       else
10005 +                               ++states[counter].number;
10006 +                       goto dontmatch;
10007 +               }
10008 +               else
10009 +               {
10010 +                       if (states[counter].number == 0)
10011 +                       {
10012 +                               ++states[counter].number;
10013 +                               goto dontmatch;
10014 +                       }
10015 +                       if (states[counter].number >= info->every)
10016 +                               states[counter].number = 0;
10017 +                       else
10018 +                               ++states[counter].number;
10019 +                       goto match;
10020 +               }
10021 +        }
10022 +        else
10023 +        {
10024 +               /* We're using the --packet, so there must be a rule for every value */
10025 +               if (states[counter].number == info->packet)
10026 +               {
10027 +                       /* only increment the counter when a match happens */
10028 +                       if (states[counter].number >= info->every)
10029 +                               states[counter].number = 0; /* reset the counter */
10030 +                       else
10031 +                               ++states[counter].number;
10032 +                       goto match;
10033 +               }
10034 +               else
10035 +                       goto dontmatch;
10036 +       }
10037 +
10038 + dontmatch:
10039 +       /* don't match */
10040 +       spin_unlock(&states[counter].lock);
10041 +       return 0;
10042 +
10043 + match:
10044 +       spin_unlock(&states[counter].lock);
10045 +       return 1;
10046 +}
10047 +
10048 +static int
10049 +ip6t_nth_checkentry(const char *tablename,
10050 +                  const struct ip6t_ip6 *e,
10051 +                  void *matchinfo,
10052 +                  unsigned int matchsize,
10053 +                  unsigned int hook_mask)
10054 +{
10055 +       /* Parameters from userspace */
10056 +       const struct ip6t_nth_info *info = matchinfo;
10057 +        unsigned counter = info->counter;
10058 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
10059 +       {
10060 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
10061 +                       return 0;
10062 +               };
10063 +
10064 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
10065 +               printk("nth: matchsize %u != %u\n", matchsize,
10066 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
10067 +               return 0;
10068 +       }
10069 +
10070 +       states[counter].number = info->startat;
10071 +
10072 +       return 1;
10073 +}
10074 +
10075 +static struct ip6t_match ip6t_nth_reg = { 
10076 +       {NULL, NULL},
10077 +       "nth",
10078 +       ip6t_nth_match,
10079 +       ip6t_nth_checkentry,
10080 +       NULL,
10081 +       THIS_MODULE };
10082 +
10083 +static int __init init(void)
10084 +{
10085 +       unsigned counter;
10086 +        memset(&states, 0, sizeof(states));
10087 +       if (ip6t_register_match(&ip6t_nth_reg))
10088 +               return -EINVAL;
10089 +
10090 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
10091 +       {
10092 +               spin_lock_init(&(states[counter].lock));
10093 +        };
10094 +
10095 +       printk("ip6t_nth match loaded\n");
10096 +       return 0;
10097 +}
10098 +
10099 +static void __exit fini(void)
10100 +{
10101 +       ip6t_unregister_match(&ip6t_nth_reg);
10102 +       printk("ip6t_nth match unloaded\n");
10103 +}
10104 +
10105 +module_init(init);
10106 +module_exit(fini);
10107 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.3/net/ipv6/netfilter/ip6t_random.c
10108 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_random.c    1970-01-01 01:00:00.000000000 +0100
10109 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_random.c        2004-02-19 08:47:32.336587163 +0100
10110 @@ -0,0 +1,97 @@
10111 +/*
10112 +  This is a module which is used for a "random" match support.
10113 +  This file is distributed under the terms of the GNU General Public
10114 +  License (GPL). Copies of the GPL can be obtained from:
10115 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
10116 +
10117 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
10118 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
10119 +*/
10120 +
10121 +#include <linux/module.h>
10122 +#include <linux/skbuff.h>
10123 +#include <linux/ip.h>
10124 +#include <linux/random.h>
10125 +#include <net/tcp.h>
10126 +#include <linux/spinlock.h>
10127 +#include <linux/netfilter_ipv6/ip6_tables.h>
10128 +#include <linux/netfilter_ipv6/ip6t_random.h>
10129 +
10130 +MODULE_LICENSE("GPL");
10131 +
10132 +static int
10133 +ip6t_rand_match(const struct sk_buff *pskb,
10134 +              const struct net_device *in,
10135 +              const struct net_device *out,
10136 +              const void *matchinfo,
10137 +              int offset,
10138 +              const void *hdr,
10139 +              u_int16_t datalen,
10140 +              int *hotdrop)
10141 +{
10142 +       /* Parameters from userspace */
10143 +       const struct ip6t_rand_info *info = matchinfo;
10144 +       u_int8_t random_number;
10145 +
10146 +       /* get 1 random number from the kernel random number generation routine */
10147 +       get_random_bytes((void *)(&random_number), 1);
10148 +
10149 +       /* Do we match ? */
10150 +       if (random_number <= info->average)
10151 +               return 1;
10152 +       else
10153 +               return 0;
10154 +}
10155 +
10156 +static int
10157 +ip6t_rand_checkentry(const char *tablename,
10158 +                  const struct ip6t_ip6 *e,
10159 +                  void *matchinfo,
10160 +                  unsigned int matchsize,
10161 +                  unsigned int hook_mask)
10162 +{
10163 +       /* Parameters from userspace */
10164 +       const struct ip6t_rand_info *info = matchinfo;
10165 +
10166 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
10167 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
10168 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
10169 +               return 0;
10170 +       }
10171 +
10172 +       /* must be  1 <= average % <= 99 */
10173 +       /* 1  x 2.55 = 2   */
10174 +       /* 99 x 2.55 = 252 */
10175 +       if ((info->average < 2) || (info->average > 252)) {
10176 +               printk("ip6t_random:  invalid average %u\n", info->average);
10177 +               return 0;
10178 +       }
10179 +
10180 +       return 1;
10181 +}
10182 +
10183 +static struct ip6t_match ip6t_rand_reg = { 
10184 +       {NULL, NULL},
10185 +       "random",
10186 +       ip6t_rand_match,
10187 +       ip6t_rand_checkentry,
10188 +       NULL,
10189 +       THIS_MODULE };
10190 +
10191 +static int __init init(void)
10192 +{
10193 +       if (ip6t_register_match(&ip6t_rand_reg))
10194 +               return -EINVAL;
10195 +
10196 +       printk("ip6t_random match loaded\n");
10197 +       return 0;
10198 +}
10199 +
10200 +static void __exit fini(void)
10201 +{
10202 +       ip6t_unregister_match(&ip6t_rand_reg);
10203 +       printk("ip6t_random match unloaded\n");
10204 +}
10205 +
10206 +module_init(init);
10207 +module_exit(fini);
This page took 1.006463 seconds and 3 git commands to generate.