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