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
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. */
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. */
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 +/***************************************************************************/
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!
29 + * Comes with its own certificate of authenticity, valid anywhere in the
34 +#define SO_IP_POOL 81
36 +typedef int ip_pool_t; /* pool index */
37 +#define IP_POOL_NONE ((ip_pool_t)-1)
39 +struct ip_pool_request {
46 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
48 +#define IP_POOL_BAD001 0x00000010
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 */
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);
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
76 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
77 + * Patrick Schaaf (bof@bof.de)
78 + * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
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.
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.
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
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!
101 + * Comes with its own certificate of authenticity, valid anywhere in the
106 +#define SO_IP_SET 83
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
119 +/*FIXME: remove this */
120 +/* #define CONFIG_IP_NF_SET_DEBUG */
123 + * Heavily modify by Joakim Axelsson 08.03.2002
124 + * - Made it more modulebased
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
131 +/* Used so that the kernel module and ipset-binary can match thier versions
133 +#define IP_SET_PROTOCOL_VERSION 1
135 +#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
137 +/* The max level of the sets.
138 + * Do not increase lightheartedly before eliminating
139 + * the recursive functions from ip_set.c.
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)
146 +/* Lets work with our own typedef for representing an IP address.
147 + * We hope to make the code more portable, possibly to IPv6...
149 + * The representation works in HOST byte order, because most set types
150 + * will perform arithmetic operations and compare operations.
152 + * For now the type is an uint32_t.
154 + * We do not enforce, but assume that a set may not store more than
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:
161 + * parse_ipandmask()
163 + * (Joakim: where are they???)
166 +typedef uint32_t ip_set_ip_t;
168 +/* SO_IP_SET operation constants, and their request struct types.
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.
174 +#define IP_SET_REQ_BASE \
178 +struct ip_set_req_base {
182 +struct ip_set_req_std {
184 + ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
188 +#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
189 +struct ip_set_req_create {
191 + char name[IP_SET_MAXNAMELEN];
192 + char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN];
196 +#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
197 +/* Uses ip_set_req_std */
199 +#define IP_SET_OP_CREATE_CHILD 0x00000003 /* Create a new child set */
200 +struct ip_set_req_sub {
202 + ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
204 + u_int8_t childsets;
207 +#define IP_SET_OP_FLUSH 0x00000004 /* Remove all IPs in a set */
208 +/* Uses ip_set_req_sub */
210 +#define IP_SET_OP_RENAME 0x00000005 /* Rename a set */
211 +struct ip_set_req_rename {
213 + char newname[IP_SET_MAXNAMELEN];
216 +#define IP_SET_OP_SWAP 0x00000006 /* Swap two sets */
217 +struct ip_set_req_swap {
222 +#define IP_SET_OP_ADD_IP 0x00000007 /* Add an IP to a set */
223 +/* Uses ip_set_req_std, with type specific addage */
225 +#define IP_SET_OP_DEL_IP 0x00000008 /* Remove an IP from a set */
226 +/* Uses ip_set_req_std, with type specific addage */
228 +/* Test if an IP is in the set
230 +#define IP_SET_OP_TEST_IP 0x00000009 /* Test an IP in a set */
231 +struct ip_set_req_test {
233 + ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
235 + int reply; /* Test result */
238 +#define IP_SET_OP_VERSION 0x00000010
239 +struct ip_set_req_version {
245 + * Size requests are sent by ip_set_req_list
246 + * except for LISTING.
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 {
256 + ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
261 +#define IP_SET_OP_LISTING_SIZE 0x00000107
262 +#define IP_SET_OP_LISTING 0x00000108
264 +struct ip_set_req_listing_size {
269 +struct ip_set_req_listing {
270 + char name[IP_SET_MAXNAMELEN];
271 + char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN];
277 +/* Between the iptables(8) set extension modules and the kernel we
278 + * identify a set by its id.
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.
285 +#define IP_SET_OP_GETSET_BYNAME 0x00000011
286 +struct ip_set_req_get {
289 + char name[IP_SET_MAXNAMELEN];
292 +#define IP_SET_OP_GETSET_BYID 0x00000012
293 +/* Uses ip_set_req_get */
295 +static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
297 + return 4 * ((((b - a + 8) / 8) + 3) / 4);
302 +#define ip_set_printk(format, args...) \
304 + printk("%s: %s: ", __FILE__, __FUNCTION__); \
305 + printk(format "\n" , ## args); \
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
312 +#define DP(format, args...) \
314 + printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
315 + printk(format "\n" , ## args); \
318 +#define DP(format, args...)
321 +/* Generic set type: */
322 +struct ip_set_private {
323 + struct ip_set_private **childsets; /* child sets */
325 + /* type speficic members */
329 + * The ip_set_type_t definition - one per set type, e.g. "ipmap".
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.
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.
339 +struct ip_set_type {
340 + struct list_head list; /* next in list of set types */
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
346 + int (*matchip) (struct ip_set_private *private,
350 + /* test for IP in set (kernel: iptables -m set --entry x)
351 + * return 0 if not in set, 1 if in set.
353 + int (*testip_kernel) (struct ip_set_private *private,
354 + const struct sk_buff * skb,
358 + /* test for IP in set (userspace: ipset -T set --entry x)
359 + * return 0 if not in set, 1 if in set.
361 + int (*testip) (struct ip_set_private *private,
362 + const void *data, size_t size,
366 + * Size of the data structure passed by when
367 + * adding/deletin/testing an entry.
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.
376 + int (*addip) (struct ip_set_private *private,
377 + const void *data, size_t size,
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.
385 + int (*addip_kernel) (struct ip_set_private *private,
386 + const struct sk_buff * skb,
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.
395 + int (*delip) (struct ip_set_private *private,
396 + const void *data, size_t size,
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.
404 + int (*delip_kernel) (struct ip_set_private *private,
405 + const struct sk_buff * skb,
409 + /* new set creation - allocated type specific items
411 + int (*create) (struct ip_set_private **private,
412 + const void *data, size_t size);
414 + /* set destruction - free type specific items
415 + * There is no return value.
416 + * Can be called only when child sets are destroyed.
418 + void (*destroy) (struct ip_set_private **private);
420 + /* set flushing - reset all bits in the set, or something similar.
421 + * There is no return value.
423 + void (*flush) (struct ip_set_private *private);
425 + /* Listing: Get size needed for header
427 + int (*list_header_size) (const struct ip_set_private *private);
429 + /* Listing: Get the header
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
436 + void (*list_header) (const struct ip_set_private *private,
439 + /* Listing: Get the size for the set members
441 + int (*list_members_size) (const struct ip_set_private *private);
443 + /* Listing: Get the set members
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
450 + void (*list_members) (const struct ip_set_private *private,
453 + /* Listing: set size in ids (first id is 0. Cannot change for a set).
455 + ip_set_ip_t (*sizeid) (const struct ip_set_private *private);
457 + /* Listing: Get the bitmap for the valid childsets
459 + void (*list_childsets) (const struct ip_set_private *private,
462 + char typename[IP_SET_MAXNAMELEN];
464 + int protocol_version;
466 + /* Set this to THIS_MODULE if you are a module, otherwise NULL */
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);
473 +/* A generic ipset */
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 */
485 +extern struct ip_set **ip_set_list;
487 +/* register and unregister set pointer references */
488 +extern struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
490 +extern struct ip_set *ip_set_get_byid(int id);
491 +extern void ip_set_put(struct ip_set *set);
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);
510 +#endif /* __KERNEL__ */
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
517 +#ifndef __IP_SET_IPHASH_H
518 +#define __IP_SET_IPHASH_H
520 +#include <linux/netfilter_ipv4/ip_set.h>
522 +#define SETTYPE_NAME "iphash"
523 +#define MAX_RANGE 0x0000FFFF
525 +struct ip_set_iphash {
526 + struct ip_set_private **childsets; /* child sets */
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 */
535 +struct ip_set_req_iphash_create {
537 + ip_set_ip_t hashsize;
538 + ip_set_ip_t netmask;
541 +struct ip_set_req_iphash {
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
551 +#ifndef __IP_SET_IPMAP_H
552 +#define __IP_SET_IPMAP_H
554 +#include <linux/netfilter_ipv4/ip_set.h>
556 +#define SETTYPE_NAME "ipmap"
557 +#define MAX_RANGE 0x0000FFFF
559 +struct ip_set_ipmap {
560 + struct ip_set_private **childsets; /* child sets */
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 */
571 +struct ip_set_req_ipmap_create {
574 + ip_set_ip_t netmask;
577 +struct ip_set_req_ipmap {
582 +mask_to_bits(ip_set_ip_t mask)
584 + unsigned int bits = 32;
585 + ip_set_ip_t maskaddr;
587 + if (mask == 0xFFFFFFFF)
590 + maskaddr = 0xFFFFFFFE;
591 + while (--bits >= 0 && maskaddr != mask)
598 +range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
600 + ip_set_ip_t mask = 0xFFFFFFFE;
603 + while (--(*bits) >= 0 && mask && (to & mask) != from)
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
614 +#ifndef _LINUX_IPSET_JHASH_H
615 +#define _LINUX_IPSET_JHASH_H
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)
622 +/* jhash.h: Jenkins hash support.
624 + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
626 + * http://burtleburtle.net/bob/hash/
628 + * These are the credits from Bob's sources:
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.
635 + * Copyright (C) 2003 David S. Miller (davem@redhat.com)
637 + * I've modified Bob's hash to be useful in the Linux kernel, and
638 + * any bugs present are surely my fault. -DaveM
641 +/* NOTE: Arguments are modified. */
642 +#define __jhash_mix(a, b, c) \
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); \
655 +/* The golden ration: an arbitrary value */
656 +#define JHASH_GOLDEN_RATIO 0x9e3779b9
658 +/* The most generic version, hashes an arbitrary sequence
659 + * of bytes. No alignment or length assumptions are made about
662 +static inline __u32 jhash(void *key, __u32 length, __u32 initval)
664 + __u32 a, b, c, len;
668 + a = b = JHASH_GOLDEN_RATIO;
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));
676 + __jhash_mix(a,b,c);
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];
697 + __jhash_mix(a,b,c);
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.
705 +static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
707 + __u32 a, b, c, len;
709 + a = b = JHASH_GOLDEN_RATIO;
717 + __jhash_mix(a, b, c);
724 + case 2 : b += k[1];
725 + case 1 : a += k[0];
728 + __jhash_mix(a,b,c);
734 +/* A special ultra-optimized versions that knows they are hashing exactly
735 + * 3, 2 or 1 word(s).
737 + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
738 + * done at the end is not done here.
740 +static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
742 + a += JHASH_GOLDEN_RATIO;
743 + b += JHASH_GOLDEN_RATIO;
746 + __jhash_mix(a, b, c);
751 +static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
753 + return jhash_3words(a, b, 0, initval);
756 +static inline __u32 jhash_1word(__u32 a, __u32 initval)
758 + return jhash_3words(a, 0, 0, initval);
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
766 +#ifndef __IP_SET_MACIPMAP_H
767 +#define __IP_SET_MACIPMAP_H
769 +#include <linux/netfilter_ipv4/ip_set.h>
771 +#define SETTYPE_NAME "macipmap"
772 +#define MAX_RANGE 0x0000FFFF
775 +#define IPSET_MACIP_MATCHUNSET 1
778 +#define IPSET_MACIP_ISSET 1
780 +struct ip_set_macipmap {
781 + struct ip_set_private **childsets; /* child sets */
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 */
790 +struct ip_set_req_macipmap_create {
796 +struct ip_set_req_macipmap {
798 + unsigned char ethernet[ETH_ALEN];
801 +struct ip_set_macip {
802 + unsigned short flags;
803 + unsigned char ethernet[ETH_ALEN];
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
811 +#ifndef __IP_SET_PORTMAP_H
812 +#define __IP_SET_PORTMAP_H
814 +#include <linux/netfilter_ipv4/ip_set.h>
816 +#define SETTYPE_NAME "portmap"
817 +#define MAX_RANGE 0x0000FFFF
818 +#define INVALID_PORT (MAX_RANGE + 1)
820 +struct ip_set_portmap {
821 + struct ip_set_private **childsets; /* child sets */
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 */
829 +struct ip_set_req_portmap_create {
834 +struct ip_set_req_portmap {
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
843 +#ifndef _IPT_FWMON_H
844 +#define _IPT_FWMON_H
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
851 +#define USE_MARK 0x00000001
852 +#define USE_DROP 0x00000002
853 +#define USE_SIZE 0x00000004
857 + unsigned int flags;
866 + char iface[IFNAMSIZ];
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
874 +/* TTL modification module for IP tables
875 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
886 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
888 +struct ipt_TTL_info {
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
899 +#ifndef _IPT_CONNLIMIT_H
900 +#define _IPT_CONNLIMIT_H
902 +struct ipt_connlimit_data;
904 +struct ipt_connlimit_info {
908 + struct ipt_connlimit_data *data;
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
915 +#ifndef _IPT_DSTLIMIT_H
916 +#define _IPT_DSTLIMIT_H
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. */
923 +/* details of this structure hidden by the implementation */
924 +struct ipt_dstlimit_htable;
926 +#define IPT_DSTLIMIT_HASH_DIP 0x0001
927 +#define IPT_DSTLIMIT_HASH_DPT 0x0002
928 +#define IPT_DSTLIMIT_HASH_SIP 0x0004
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. */
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? */
942 +struct ipt_dstlimit_info {
943 + char name [IFNAMSIZ]; /* name */
944 + struct dstlimit_cfg cfg;
945 + struct ipt_dstlimit_htable *hinfo;
947 + /* Used internally by the kernel */
950 + struct ipt_dstlimit_info *master;
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
958 +#ifndef _IPT_FUZZY_H
959 +#define _IPT_FUZZY_H
961 +#include <linux/param.h>
962 +#include <linux/types.h>
964 +#define MAXFUZZYRATE 10000000
965 +#define MINFUZZYRATE 3
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;
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
983 +#ifndef __ipt_ipv4options_h_included__
984 +#define __ipt_ipv4options_h_included__
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 */
998 +struct ipt_ipv4options_info {
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
1008 +#ifndef _IPT_MPORT_H
1009 +#define _IPT_MPORT_H
1010 +#include <linux/netfilter_ipv4/ip_tables.h>
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)
1016 +#define IPT_MULTI_PORTS 15
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[] */
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 */
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
1039 +#include <linux/param.h>
1040 +#include <linux/types.h>
1042 +#ifndef IPT_NTH_NUM_COUNTERS
1043 +#define IPT_NTH_NUM_COUNTERS 16
1046 +struct ipt_nth_info {
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
1062 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
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.
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.
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
1083 +#define MAXGENRELEN 32
1084 +#define MAXDETLEN 64
1086 +#define IPT_OSF_GENRE 1
1087 +#define IPT_OSF_SMART 2
1088 +#define IPT_OSF_LOG 4
1090 +#define IPT_OSF_LOGLEVEL_ALL 0
1091 +#define IPT_OSF_LOGLEVEL_FIRST 1
1093 +#include <linux/list.h>
1095 +struct ipt_osf_info
1097 + char genre[MAXGENRELEN];
1099 + unsigned long flags;
1101 + int invert; /* UNSUPPORTED */
1107 + unsigned long val;
1110 +/* This struct represents IANA options
1111 + * http://www.iana.org/assignments/tcp-parameters
1115 + unsigned char kind;
1116 + unsigned char length;
1124 + struct list_head flist;
1125 + struct osf_wc wss;
1126 + unsigned char ttl;
1129 + char genre[MAXGENRELEN];
1130 + char version[MAXGENRELEN], subtype[MAXGENRELEN];
1132 + /* Not needed, but for consistency with original table from Michal Zalewski */
1133 + char details[MAXDETLEN];
1136 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1140 +/* Defines for IANA option kinds */
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 */
1155 +static struct osf_opt IANA_opts[] =
1162 + {5, 1 ,}, /* SACK length is not defined */
1168 + {11, 1,}, /* CC: Suppose 1 */
1169 + {12, 1,}, /* the same */
1170 + {13, 1,}, /* and here too */
1172 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1186 +#endif /* __KERNEL__ */
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
1193 +#ifndef _IPT_POOL_H
1194 +#define _IPT_POOL_H
1196 +#include <linux/netfilter_ipv4/ip_pool.h>
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
1210 +struct ipt_pool_info
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
1225 +#include <linux/param.h>
1226 +#include <linux/types.h>
1229 + * High port numbers have a lower weight to reduce the frequency of false
1230 + * positives, such as from passive mode FTP transfers.
1232 +#define PORT_WEIGHT_PRIV 3
1233 +#define PORT_WEIGHT_HIGH 1
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.
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)
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.
1249 +#define LIST_SIZE 0x100
1251 +#define HASH_SIZE (1 << HASH_LOG)
1252 +#define HASH_MAX 0x10
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;
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
1266 +#ifndef _IPT_QUOTA_H
1267 +#define _IPT_QUOTA_H
1269 +/* print debug info in both kernel/netfilter module & iptable library */
1270 +//#define DEBUG_IPT_QUOTA
1272 +struct ipt_quota_info {
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
1281 +#ifndef _IPT_RAND_H
1282 +#define _IPT_RAND_H
1284 +#include <linux/param.h>
1285 +#include <linux/types.h>
1287 +struct ipt_rand_info {
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
1296 +#ifndef _IPT_REALM_H
1297 +#define _IPT_REALM_H
1299 +struct ipt_realm_info {
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
1312 +#include <linux/netfilter_ipv4/ip_set.h>
1314 +struct ipt_set_info {
1316 + u_int8_t set_level, ip_level;
1317 + u_int32_t flags[IP_SET_LEVELS];
1321 +struct ipt_set_info_match {
1322 + struct ipt_set_info match;
1325 +struct ipt_set_info_target {
1326 + struct ipt_set_info add_set;
1327 + struct ipt_set_info del_set;
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
1335 +#ifndef __ipt_time_h_included__
1336 +#define __ipt_time_h_included__
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. */
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
1354 +#include <linux/netfilter_ipv4/ip_tables.h>
1364 +struct ipt_u32_location_element
1369 +struct ipt_u32_value_element
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
1380 + struct ipt_u32_location_element location[U32MAXSIZE+1];
1382 + struct ipt_u32_value_element value[U32MAXSIZE+1];
1388 + struct ipt_u32_test tests[U32MAXSIZE+1];
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
1396 +/* Hop Limit modification module for ip6tables
1397 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1398 + * Based on HW's TTL module */
1409 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
1411 +struct ip6t_HL_info {
1413 + u_int8_t hop_limit;
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
1422 #define _IP6T_REJECT_H
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,
1439 struct ip6t_reject_info {
1440 enum ip6t_reject_with with; /* reject type */
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
1449 +#ifndef _IP6T_FUZZY_H
1450 +#define _IP6T_FUZZY_H
1452 +#include <linux/param.h>
1453 +#include <linux/types.h>
1455 +#define MAXFUZZYRATE 10000000
1456 +#define MINFUZZYRATE 3
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;
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
1474 +#ifndef _IP6T_NTH_H
1475 +#define _IP6T_NTH_H
1477 +#include <linux/param.h>
1478 +#include <linux/types.h>
1480 +#ifndef IP6T_NTH_NUM_COUNTERS
1481 +#define IP6T_NTH_NUM_COUNTERS 16
1484 +struct ip6t_nth_info {
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
1497 +#ifndef _IP6T_RAND_H
1498 +#define _IP6T_RAND_H
1500 +#include <linux/param.h>
1501 +#include <linux/types.h>
1503 +struct ip6t_rand_info {
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 @@
1513 To compile it as a module, choose M here. If unsure, say N.
1515 +config IP_NF_TARGET_IPV4OPTSSTRIP
1516 + tristate 'IPV4OPTSSTRIP target support'
1517 + depends on IP_NF_MANGLE
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.
1522 + The target doesn't take any option, and therefore is extremly easy to use :
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
1530 + Chain OUTPUT (policy ACCEPT)
1531 + target prot opt source destination
1533 +config IP_NF_TARGET_NETLINK
1534 + tristate 'NETLINK target support'
1535 + depends on IP_NF_FILTER
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.
1542 +config IP_NF_TARGET_TTL
1543 + tristate 'TTL target support'
1544 + depends on IP_NF_MANGLE
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
1550 +config IP_NF_MATCH_CONNLIMIT
1551 + tristate 'Connections/IP limit match support'
1552 + depends on IP_NF_IPTABLES
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).
1560 + # allow 2 telnet connections per client host
1561 + iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
1563 + # you can also match the other way around:
1564 + iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
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
1571 +config IP_NF_MATCH_DSTLIMIT
1572 + tristate 'dstlimit match support'
1573 + depends on IP_NF_IPTABLES
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.
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'
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
1603 +config IP_NF_MATCH_FUZZY
1604 + tristate 'fuzzy match support'
1605 + depends on IP_NF_IPTABLES
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)
1610 +config IP_NF_MATCH_IPV4OPTIONS
1611 + tristate 'IPV4OPTIONS match support'
1612 + depends on IP_NF_IPTABLES
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
1618 + Suppported options are:
1620 + To match packets with the flag strict source routing.
1622 + To match packets with the flag loose source routing.
1624 + To match packets with no flag for source routing.
1626 + To match packets with the RR flag.
1628 + To match packets with the TS flag.
1630 + To match packets with the router-alert option.
1632 + To match a packet with at least one IP option, or no IP option
1633 + at all if ! is chosen.
1636 + $ iptables -A input -m ipv4options --rr -j DROP
1637 + will drop packets with the record-route flag.
1639 + $ iptables -A input -m ipv4options --ts -j DROP
1640 + will drop packets with the timestamp flag.
1642 +config IP_NF_MATCH_MPORT
1643 + tristate 'Multiple port with ranges match support'
1644 + depends on IP_NF_IPTABLES
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.
1651 + # iptables -A FORWARD -p tcp -m mport --ports 23:42,65
1653 +config IP_NF_MATCH_NTH
1654 + tristate 'Nth match support'
1655 + depends on IP_NF_IPTABLES
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
1661 + This match functions in one of two ways
1662 + 1) Match ever Nth packet, and only the Nth packet.
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.
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
1678 + By using the mangle table and iproute2, you can setup complex
1679 + load-balanced routing. There's lot of other uses. Be creative!
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
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.
1693 +config IP_NF_MATCH_OSF
1694 + tristate 'OSF match support'
1695 + depends on IP_NF_IPTABLES
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.
1702 + Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
1703 + his excellent p0f and than changed a bit for more convenience.
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.
1709 + Example: (Of course this only an example, do not get inspired by this)
1711 + # iptables -N LINUX
1712 + # iptables -A LINUX -j LOG --log-prefix "Linux"
1714 + # iptables -A INPUT -p tcp -m osf --genre Linux -j LINUX
1715 + # iptables -A INPUT -p tcp -m osf --genre FreeBSD -j REJECT
1717 + NOTE: -p tcp is obviously required as it is a TCP match.
1721 + If present, OSF will log determined genres even if they don't match
1723 + 0 - log all determined entries,
1724 + 1 - only first one.
1727 + #iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
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
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).
1737 + Fingerprints can be loaded through /proc/sys/net/ipv4/osf file.
1738 + Only one fingerprint per open/close.
1740 + Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
1742 +config IP_POOL_STATISTICS
1743 + bool 'enable statistics on pool usage'
1744 + depends on IP_NF_POOL!=n
1747 + tristate 'IP address pool support'
1748 + depends on IP_NF_IPTABLES
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
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.
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/.
1764 +config IP_NF_MATCH_PSD
1765 + tristate 'psd match support'
1766 + depends on IP_NF_IPTABLES
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.
1772 + Suppported options are:
1774 + --psd-weight-threshold <threshold>
1776 + Total weight of the latest TCP/UDP packets with different
1777 + destination ports coming from the same host to be treated as port
1780 + --psd-delay-threshold <delay>
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.
1786 + --psd-lo-ports-weight <weight>
1788 + Weight of the packet with privileged (<=1024) destination port.
1790 + --psd-hi-ports-weight <weight>
1792 + Weight of the packet with non-priviliged destination port.
1794 +config IP_NF_MATCH_QUOTA
1795 + tristate 'quota match support'
1796 + depends on IP_NF_IPTABLES
1798 + This option adds CONFIG_IP_NF_MATCH_QUOTA, which implements network
1799 + quotas by decrementing a byte counter with each packet.
1801 + Supported options are:
1803 + The quota in bytes.
1805 + KNOWN BUGS: this does not work on SMP systems.
1808 +config IP_NF_MATCH_RANDOM
1809 + tristate 'random match support'
1810 + depends on IP_NF_IPTABLES
1812 + This option adds a `random' match,
1813 + which allow you to match packets randomly
1814 + following a given probability.
1816 + Suppported options are:
1818 + [--average] percent will match randomly packets with a probability of
1819 + 'percent'. default is 50%
1821 +config IP_NF_MATCH_REALM
1822 + tristate 'realm match support'
1823 + depends on IP_NF_IPTABLES
1825 + realm match: uses realm key from routing as match criteria similiar to
1826 + one in packet classifier
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.
1838 + /sbin/ip route add 194.29.194.0/24 via 194.29.192.1 realm 10
1840 + # source realm is in realm with mask 0xFFFF0000,
1841 + # destination is in realm with mask 0x0000FFFF
1843 + # match destination realm
1844 + /usr/local/sbin/iptables -A OUTPUT -m realm --realm 10 -j LOG
1846 + # match realm of source, this is also determinated by routing,
1847 + /usr/local/sbin/iptables -A INPUT -m realm --realm 655360 -j LOG
1849 + THIS PATCH REQUIRES CONFIG_NET_CLS_ROUTE TO BE SET
1851 +config IP_NF_MATCH_TIME
1852 + tristate 'TIME match support'
1853 + depends on IP_NF_IPTABLES
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).
1861 + Supported options are:
1863 + The starting point of the time match frame.
1866 + The stopping point of the time match frame
1869 + Days of the week to match separated by a coma, no space
1870 + (one of Sun,Mon,Tue,Wed,Thu,Fri,Sat)
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
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.
1881 +config IP_NF_MATCH_U32
1882 + tristate 'U32 match support'
1883 + depends on IP_NF_IPTABLES
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
1892 + Details and examples are in the kernel module source.
1895 + tristate 'IP address/port sets support'
1896 + depends on IP_NF_IPTABLES
1899 +config IP_NF_SET_MAX
1900 + int ' Maximum number of sets'
1901 + depends on IP_NF_SET
1904 +config IP_NF_SET_IPMAP
1905 + tristate ' ipmap set type support'
1906 + depends on IP_NF_SET
1909 +config IP_NF_SET_PORTMAP
1910 + tristate ' portmap set type support'
1911 + depends on IP_NF_SET
1914 +config IP_NF_SET_MACIPMAP
1915 + tristate ' macipmap set type support'
1916 + depends on IP_NF_SET
1919 +config IP_NF_SET_IPHASH
1920 + tristate ' iphash set type support'
1921 + depends on IP_NF_SET
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
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
1940 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1941 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1943 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1945 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1946 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1948 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1951 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
1953 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1955 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1958 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1960 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1963 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1965 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1967 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1970 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1972 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
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
1982 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
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
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
1998 +/* Kernel module for IP pool management */
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>
2014 +#define DP(format, args...)
2017 +MODULE_LICENSE("GPL");
2020 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
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 */
2031 +static struct ip_pool *POOL;
2033 +static inline struct ip_pool *lookup(ip_pool_t index)
2035 + if (index < 0 || index >= nr_pool) {
2036 + DP("ip_pool:lookup: bad index %d\n", index);
2039 + return POOL+index;
2042 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
2044 + struct ip_pool *pool = lookup(index);
2047 + if (!pool || !pool->members)
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)) {
2055 +#ifdef CONFIG_IP_POOL_STATISTICS
2060 +#ifdef CONFIG_IP_POOL_STATISTICS
2064 + read_unlock_bh(&pool->lock);
2067 +EXPORT_SYMBOL(ip_pool_match);
2069 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
2071 + struct ip_pool *pool;
2074 + pool = lookup(index);
2075 + if ( !pool || !pool->members
2076 + || addr < pool->first_ip || addr > pool->last_ip)
2078 + read_lock_bh(&pool->lock);
2079 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
2080 + addr -= pool->first_ip;
2082 + ? (0 != test_and_clear_bit(addr, pool->members))
2083 + : (0 != test_and_set_bit(addr, pool->members));
2085 + read_unlock_bh(&pool->lock);
2089 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
2091 + int res = pool_change(index,addr,isdel);
2093 + if (!isdel) res = !res;
2096 +EXPORT_SYMBOL(ip_pool_mod);
2098 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
2100 + return 4*((((b-a+8)/8)+3)/4);
2103 +static inline int poolbytes(ip_pool_t index)
2105 + struct ip_pool *pool = lookup(index);
2107 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
2110 +static int setpool(
2116 + struct ip_pool_request req;
2118 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
2119 + if (!capable(CAP_NET_ADMIN))
2121 + if (optval != SO_IP_POOL)
2123 + if (len != sizeof(req))
2125 + if (copy_from_user(&req, user, sizeof(req)) != 0)
2127 + printk("obsolete op - upgrade your ippool(8) utility.\n");
2131 +static int getpool(
2137 + struct ip_pool_request req;
2138 + struct ip_pool *pool;
2144 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
2145 + if (!capable(CAP_NET_ADMIN))
2147 + if (optval != SO_IP_POOL)
2149 + if (*len != sizeof(req)) {
2152 + if (copy_from_user(&req, user, sizeof(req)) != 0)
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");
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)
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);
2172 + if (!pool->members)
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);
2182 + if (!pool->members)
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);
2193 + read_lock_bh(&pool->lock);
2194 + if (!pool->members) {
2195 + DP("ip_pool TEST_ADDR no members in pool\n");
2197 + goto unlock_and_return_res;
2199 + req.addr = ntohl(req.addr);
2200 + if (req.addr < pool->first_ip) {
2201 + DP("ip_pool TEST_ADDR address < pool bounds\n");
2203 + goto unlock_and_return_res;
2205 + if (req.addr > pool->last_ip) {
2206 + DP("ip_pool TEST_ADDR address > pool bounds\n");
2208 + goto unlock_and_return_res;
2210 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
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");
2217 + case IP_POOL_DESTROY:
2218 + DP("ip_pool DESTROY not yet implemented.\n");
2220 + case IP_POOL_INIT:
2221 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
2222 + pool = lookup(req.index);
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");
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);
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);
2243 + goto unlock_and_return_res;
2245 + pool->first_ip = req.addr;
2246 + pool->last_ip = req.addr2;
2248 + pool->nr_match = 0;
2249 + pool->members = newmembers;
2250 + write_unlock_bh(&pool->lock);
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));
2261 + DP("ip_pool:getpool bad op %d\n", req.op);
2266 +unlock_and_return_res:
2268 + read_unlock_bh(&pool->lock);
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,
2278 +MODULE_PARM(nr_pool, "i");
2280 +static int __init init(void)
2285 + if (nr_pool < 1) {
2286 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
2289 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
2291 + printk("ip_pool module init: out of memory for nr_pool %d\n",
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;
2303 + res = nf_register_sockopt(&so_pool);
2304 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
2312 +static void __exit fini(void)
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;
2326 + DP("ip_pool:fini these are the famous last words\n");
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
2336 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
2337 + * Patrick Schaaf (bof@bof.de)
2338 + * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
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.
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.
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
2355 +/* Kernel module for IP set management */
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>
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>
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, */
2381 +#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
2382 +#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
2384 +#define __MOD_INC(foo) do { } while (0)
2385 +#define __MOD_DEC(foo) do { } while (0)
2388 +#define NOT_IN_CHILD_SET(fn,args...) \
2390 + || !(*private)->childsets \
2391 + || (set->type[i]->fn(*private,##args) < 0)
2393 +static struct ip_set_private **
2394 +ip_set_find_private(struct ip_set *set,
2395 + struct ip_set_private **private,
2402 + for (i = 0; i < level; i++) {
2403 + if (NOT_IN_CHILD_SET(matchip, ip[i], &id))
2405 + private = &(*private)->childsets[id];
2407 + DP("id: %i private: %p %p", id, private, *private);
2411 +/* Destroy function for the private part of the (child)sets.
2412 + * Must be called without holding any locks.
2415 +ip_set_destroy_private(struct ip_set *set,
2416 + struct ip_set_private **private,
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],
2430 + vfree((*private)->childsets);
2433 + set->type[level]->destroy(private);
2434 + DP("%p %p", private, *private);
2437 +static void ip_set_flush_private(struct ip_set *set,
2438 + struct ip_set_private *private,
2440 + u_int8_t childsets)
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],
2452 + set->type[level]->flush(private);
2456 +/* ip_set_flush() - flush data in a set
2458 +static int ip_set_flush(struct ip_set *set,
2461 + u_int8_t childsets)
2464 + struct ip_set_private **private;
2466 + write_lock_bh(&set->lock);
2467 + if (set->subref) {
2472 + private = ip_set_find_private(set, &set->private, ip, level);
2475 + ip_set_flush_private(set, *private, level, childsets);
2478 + write_unlock_bh(&set->lock);
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)
2489 + struct ip_set_private **private = &set->private;
2493 + read_lock_bh(&set->lock);
2494 + if (set->levels < ip_level || set->subref)
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))
2501 + DP("id: %i private: %p", id, *private);
2502 + private = &(*private)->childsets[id];
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)
2508 + private = (*private)->childsets
2509 + ? &(*private)->childsets[id] : NULL;
2513 + read_unlock_bh(&set->lock);
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)
2524 + struct ip_set_private **private = &set->private;
2528 + write_lock_bh(&set->lock);
2529 + if (set->levels < ip_level || set->subref) {
2530 + write_unlock_bh(&set->lock);
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);
2539 + private = &(*private)->childsets[id];
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);
2548 + private = (*private)->childsets
2549 + ? &(*private)->childsets[id] : NULL;
2551 + write_unlock_bh(&set->lock);
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)
2561 + struct ip_set_private **private = &set->private;
2565 + write_lock_bh(&set->lock);
2566 + if (set->levels < ip_level || set->subref) {
2567 + write_unlock_bh(&set->lock);
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);
2576 + private = &(*private)->childsets[id];
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);
2585 + private = (*private)->childsets
2586 + ? &(*private)->childsets[id] : NULL;
2588 + write_unlock_bh(&set->lock);
2592 +ip_set_addip(struct ip_set *set,
2598 + struct ip_set_private **private;
2602 + DP("%s %i %d", set->name, level, size);
2603 + write_lock_bh(&set->lock);
2604 + if (set->subref) {
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)) {
2616 + if (size < set->type[level]->reqsize) {
2620 + res = set->type[level]->addip(*private, data,
2621 + set->type[level]->reqsize, &id);
2622 + if (!(res == 0 || res == -EEXIST))
2624 + private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2625 + data += set->type[level]->reqsize;
2626 + size -= set->type[level++]->reqsize;
2631 + write_unlock_bh(&set->lock);
2636 +ip_set_delip(struct ip_set *set,
2642 + struct ip_set_private **private;
2646 + write_lock_bh(&set->lock);
2647 + if (set->subref) {
2651 + private = ip_set_find_private(set, &set->private, ip, level);
2652 + while (level <= set->levels && size) {
2653 + if (!(private && *private)) {
2657 + if (size < set->type[level]->reqsize) {
2661 + res = set->type[level]->delip(*private, data,
2662 + set->type[level]->reqsize, &id);
2663 + if (!(res == 0 || res == -EEXIST))
2665 + private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2666 + data += set->type[level]->reqsize;
2667 + size -= set->type[level++]->reqsize;
2672 + write_unlock_bh(&set->lock);
2677 +ip_set_testip(struct ip_set *set,
2683 + struct ip_set_private **private;
2687 + write_lock_bh(&set->lock);
2688 + if (set->subref) {
2692 + private = ip_set_find_private(set, &set->private, ip, level);
2693 + while (level <= set->levels && size) {
2694 + if (!(private && *private)) {
2698 + if (size < set->type[level]->reqsize) {
2702 + res = set->type[level]->testip(*private, data,
2703 + set->type[level]->reqsize, &id);
2704 + DP("level: %i res: %i", level, res);
2707 + private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2708 + data += set->type[level]->reqsize;
2709 + size -= set->type[level++]->reqsize;
2714 + write_unlock_bh(&set->lock);
2719 +set_type_equal(const struct ip_set_type *set_type, const char *str2)
2721 + DP("'%s' vs. '%s'", set_type->typename, str2);
2722 + return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
2726 + * Always use find_setfoo() under the &list_lock.
2728 +static inline struct ip_set_type *find_set_type(const char name[IP_SET_MAXNAMELEN])
2730 + return LIST_FIND(&set_type_list,
2732 + struct ip_set_type *,
2736 +int ip_set_register_set_type(struct ip_set_type *set_type)
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);
2746 + write_lock_bh(&list_lock);
2747 + if (find_set_type(set_type->typename)) {
2749 + write_unlock_bh(&list_lock);
2750 + ip_set_printk("'%s' already registered!",
2751 + set_type->typename);
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);
2761 +void ip_set_unregister_set_type(struct ip_set_type *set_type)
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);
2770 + LIST_DELETE(&set_type_list, set_type);
2771 + write_unlock_bh(&list_lock);
2772 + MOD_DEC_USE_COUNT;
2774 + DP("'%s' unregistered.", set_type->typename);
2777 +/* Create the private part of a (child)set.
2778 + * Must be called without holding any locks.
2781 +ip_set_create_private(struct ip_set_type *set_type,
2782 + struct ip_set_private **private,
2785 + u_int8_t childsets)
2790 + DP("%s %p %p %i", set_type->typename, private, *private, childsets);
2793 + printk("%p: %p as private already occupied", private, *private);
2795 + /* Call the set_type initializer. */
2796 + res = set_type->create(private, data, size);
2801 + (*private)->childsets = NULL;
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);
2813 + DP("%s %p %p %p", set_type->typename, private, *private, (*private)->childsets);
2814 + memset((*private)->childsets, 0, newbytes);
2819 +ip_set_create_childset(struct ip_set *set,
2822 + u_int8_t childsets,
2826 + struct ip_set_private **private = &set->private;
2830 + DP("%s (%i %i)", set->name, level, childsets);
2831 + write_lock_bh(&set->lock);
2832 + if (set->subref) {
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)) {
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);
2850 + if ((*private)->childsets[id]) {
2855 + write_unlock_bh(&set->lock);
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);
2862 + write_lock_bh(&set->lock);
2865 + DP("%s (%p %p) res=%i", set->name, private, *private, res);
2866 + write_unlock_bh(&set->lock);
2871 +ip_set_create(const char name[IP_SET_MAXNAMELEN],
2872 + char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN],
2877 + int i, id, res = 0;
2878 + struct ip_set *set;
2880 + DP("%s (%i): %s", typename[0], level, name);
2882 + * First, and without any locks, allocate and initialize
2883 + * a normal base set structure.
2885 + set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
2888 + set->lock = RW_LOCK_UNLOCKED;
2889 + strncpy(set->name, name, IP_SET_MAXNAMELEN);
2890 + set->name[IP_SET_MAXNAMELEN - 1] = '\0';
2893 + set->levels = level;
2894 + set->private = NULL;
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.
2901 + * After referencing the type, we drop the &list_lock,
2902 + * and let the new set construction run without locks.
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);
2916 + for (i = 0; i < level; i++)
2917 + __MOD_INC(set->type[i]->me);
2918 + write_unlock_bh(&list_lock);
2921 + * Without holding any locks, create private part.
2923 + res = ip_set_create_private(set->type[0],
2925 + data, size, level - 1);
2927 + for (i = 0; i <= level; i++)
2928 + __MOD_DEC(set->type[i]->me);
2933 + /* BTW, res==0 here. */
2936 + * Here, we have a valid, constructed set. &list_lock again,
2937 + * and check that it is not already in ip_set_list.
2939 + write_lock_bh(&list_lock);
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) {
2947 + } else if (id < 0 && ip_set_list[i] == NULL)
2951 + /* No free slot remained */
2956 + * Finally! Append our shiny new set into the list, and be done.
2958 + DP("create: '%s' created with id %i!", set->name, id);
2959 + ip_set_list[id] = set;
2960 + write_unlock_bh(&list_lock);
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);
2972 +static int ip_set_destroy(struct ip_set *set,
2976 + struct ip_set_private **private;
2979 + write_lock_bh(&list_lock);
2980 + /* there is no race, here. ->ref modification always happens
2981 + * under &list_lock. Fine.
2984 + /* one ref from caller */
2985 + if (set->ref > 1 || set->subref) {
2990 + for (i = 0; i < max_sets; i++)
2991 + if (ip_set_list[i] == set) {
2992 + ip_set_list[i] = NULL;
2995 + write_unlock_bh(&list_lock);
2997 + ip_set_destroy_private(set, &set->private, 0);
2998 + for (i = 0; i < set->levels; i++)
2999 + __MOD_DEC(set->type[i]->me);
3004 + private = ip_set_find_private(set, &set->private,
3007 + if (private && *private) {
3008 + if (set->subref) {
3013 + write_unlock_bh(&list_lock);
3015 + DP("%p %p", private, *private);
3016 + ip_set_destroy_private(set, private, level);
3017 + DP("%p %p", private, *private);
3019 + write_lock_bh(&list_lock);
3025 + write_unlock_bh(&list_lock);
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().
3034 +struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
3037 + struct ip_set *set = NULL;
3040 + read_lock_bh(&list_lock);
3041 + for (i = 0; i < max_sets; i++) {
3042 + set = ip_set_list[i];
3044 + && strncmp(set->name, name, IP_SET_MAXNAMELEN - 1) == 0) {
3050 + read_unlock_bh(&list_lock);
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().
3059 +struct ip_set *ip_set_get_byid(int id)
3061 + struct ip_set *set;
3063 + if (id < 0 || id >= max_sets)
3066 + write_lock_bh(&list_lock);
3067 + set = ip_set_list[id];;
3070 + write_unlock_bh(&list_lock);
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.
3079 +void ip_set_put(struct ip_set *set)
3081 + write_lock_bh(&list_lock);
3084 + write_unlock_bh(&list_lock);
3087 +static int ip_set_rename(struct ip_set *set, const char *name)
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,
3096 + IP_SET_MAXNAMELEN - 1) == 0) {
3101 + strncpy(set->name, name, IP_SET_MAXNAMELEN);
3102 + set->name[IP_SET_MAXNAMELEN - 1] = '\0';
3104 + write_unlock_bh(&list_lock);
3108 +static int ip_set_swap(struct ip_set *from, struct ip_set *to)
3110 + char from_name[IP_SET_MAXNAMELEN];
3111 + unsigned from_ref;
3113 + int from_id = -1, to_id = -1;
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)
3119 + if (ip_set_list[i] == to)
3122 + /* We must have got both sets: we hold refcounts against them! */
3123 + if (from_id < 0 || to_id < 0) {
3128 + strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
3129 + from_ref = from->ref;
3131 + ip_set_list[from_id] = to;
3132 + ip_set_list[to_id] = from;
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;
3139 + write_unlock_bh(&list_lock);
3143 +size_t ip_set_listing_size(void)
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);
3153 + read_unlock_bh(&list_lock);
3158 +int ip_set_listing(void *data, int *len)
3161 + int res = 0; /* All OK */
3163 + struct ip_set *set;
3164 + struct ip_set_req_listing *header = data;
3166 + read_lock_bh(&list_lock);
3167 + for (id = 0; id < max_sets; id++) {
3168 + if (ip_set_list[id] == NULL)
3171 + /* Pointer to our header */
3172 + header = (struct ip_set_req_listing *) (data + used);
3174 + DP("used before= %d %p %p %p", used, header, data,
3177 + /* Get and ensure header size */
3178 + if (used + sizeof(struct ip_set_req_listing) > *len)
3179 + goto not_enough_mem;
3181 + set = ip_set_list[id];
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;
3192 + used += sizeof(struct ip_set_req_listing);
3193 + DP("used after= %d", used);
3195 + *len = used; /* How much did we use? */
3196 + goto unlock_and_return;
3199 + DP("not enough mem, try again");
3202 + unlock_and_return:
3203 + read_unlock_bh(&list_lock);
3207 +int ip_set_list_size(struct ip_set * set,
3213 + int res = 0; /* OK */
3214 + struct ip_set_private **private;
3216 + DP("%d %s %d", op, set->name, level);
3217 + read_lock_bh(&set->lock);
3218 + if (set->subref) {
3222 + private = ip_set_find_private(set, &set->private, ip, level);
3223 + if (!(private && *private)) {
3228 + case IP_SET_OP_LIST_HEADER_SIZE:
3229 + *size = set->type[level]->list_header_size(*private);
3231 + case IP_SET_OP_LIST_MEMBERS_SIZE:
3232 + *size = set->type[level]->list_members_size(*private);
3234 + case IP_SET_OP_LIST_CHILDSETS_SIZE:
3235 + *size = (*private)->childsets == NULL ? 0
3236 + : bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3242 + read_unlock_bh(&set->lock);
3243 + DP("%d %s %d: %u", op, set->name, level, *size);
3248 +static void list_childsets(const struct ip_set_private *private,
3250 + ip_set_ip_t sizeid)
3254 + memset(data, 0, bitmap_bytes(0, sizeid - 1));
3256 + if (private->childsets == NULL)
3259 + for (id = 0; id < sizeid; id++)
3260 + if (private->childsets[id] != NULL)
3261 + set_bit(id, data);
3264 +int ip_set_list_data(struct ip_set *set,
3271 + int res = 0; /* All OK */
3273 + struct ip_set_private **private;
3274 + void (*datafn)(const struct ip_set_private *, void *);
3276 + read_lock_bh(&set->lock);
3277 + if (set->subref) {
3281 + private = ip_set_find_private(set, &set->private, ip, level);
3282 + if (!(private && *private)) {
3287 + case IP_SET_OP_LIST_HEADER:
3288 + need = set->type[level]->list_header_size(*private);
3289 + datafn = set->type[level]->list_header;
3291 + case IP_SET_OP_LIST_MEMBERS:
3292 + need = set->type[level]->list_members_size(*private);
3293 + datafn = set->type[level]->list_members;
3295 + case IP_SET_OP_LIST_CHILDSETS:
3296 + if ((*private)->childsets == NULL) {
3300 + need = bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3307 + if (need > *len) {
3313 + datafn(*private, data);
3315 + list_childsets(*private, data, set->type[level]->sizeid(*private));
3318 + read_unlock_bh(&set->lock);
3323 +ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
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;
3331 + DP("optval=%d, user=%p, len=%d", optval, user, len);
3332 + if (!capable(CAP_NET_ADMIN))
3334 + if (optval != SO_IP_SET)
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);
3341 + data = vmalloc(len);
3343 + DP("out of mem for %d bytes", len);
3346 + if (copy_from_user(data, user, len) != 0) {
3351 + req_base = (struct ip_set_req_base *) data;
3353 + DP("op=%x id='%x'", req_base->op, req_base->id);
3355 + /* Handle set creation first - no incoming set specified */
3357 + if (req_base->op == IP_SET_OP_CREATE) {
3358 + struct ip_set_req_create *req_create
3359 + = (struct ip_set_req_create *) data;
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);
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);
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));
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'.
3390 + set = ip_set_get_byid(req_base->id);
3391 + if (set == NULL) {
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;
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);
3410 + res = ip_set_rename(set, req_rename->newname);
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;
3419 + if (len != sizeof(struct ip_set_req_swap)) {
3421 + ip_set_printk("short SWAP data (want >%d, got %d)",
3422 + sizeof(struct ip_set_req_swap), len);
3427 + to = ip_set_get_byid(req_swap->to);
3432 + res = ip_set_swap(set, to);
3437 + ; /* Requests with possible subsets: fall trough. */
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);
3446 + } else if (req_std->level >= set->levels) {
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));
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));
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 */
3472 + case IP_SET_OP_FLUSH:{
3473 + struct ip_set_req_sub *req_sub =
3474 + (struct ip_set_req_sub *) data;
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);
3482 + res = ip_set_flush(set, req_sub->ip, req_sub->level, req_sub->childsets);
3485 + case IP_SET_OP_CREATE_CHILD:{
3486 + struct ip_set_req_sub *req_sub
3487 + = (struct ip_set_req_sub *) data;
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);
3495 + if (req_sub->level < 1) {
3496 + /* No entry supplied? */
3500 + if (((req_sub->level >= set->levels - 1) && req_sub->childsets)) {
3501 + /* No room for subsets to be created. */
3505 + res = ip_set_create_childset(set,
3508 + req_sub->childsets,
3509 + data + sizeof(struct ip_set_req_sub),
3510 + len - sizeof(struct ip_set_req_sub));
3514 + DP("unknown op %d", req_base->op);
3515 + ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3518 + } /* end of switch(op) */
3531 +ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
3534 + struct ip_set_req_base *req_base;
3535 + struct ip_set_req_std *req_std;
3536 + struct ip_set *set = NULL;
3538 + int copylen = *len;
3540 + DP("optval=%d, user=%p, len=%d", optval, user, *len);
3541 + if (!capable(CAP_NET_ADMIN))
3543 + if (optval != SO_IP_SET)
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);
3550 + data = vmalloc(*len);
3552 + DP("out of mem for %d bytes", *len);
3555 + if (copy_from_user(data, user, *len) != 0) {
3560 + req_base = (struct ip_set_req_base *) data;
3562 + DP("op=%x id='%x'", req_base->op, req_base->id);
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;
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),
3578 + req_version->version = IP_SET_PROTOCOL_VERSION;
3579 + res = copy_to_user(user, req_version,
3580 + sizeof(struct ip_set_req_version));
3583 + case IP_SET_OP_LISTING_SIZE:{
3584 + struct ip_set_req_listing_size *req_list =
3585 + (struct ip_set_req_listing_size *) data;
3587 + DP("IP_SET_OP_LISTING_SIZE");
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),
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));
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);
3608 + goto done; /* Error */
3610 + res = copy_to_user(user, data, *len); /* Only copy the mem used */
3614 + ; /* Requests with named set: fall trought */
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;
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);
3629 + req_get->name[IP_SET_MAXNAMELEN - 1] = '\0';
3631 + set = ip_set_get_byname(req_get->name, &req_get->id);
3633 + req_get->ref = set->ref - 1;
3636 + res = copy_to_user(user, data, copylen);
3639 + case IP_SET_OP_GETSET_BYID: {
3640 + struct ip_set_req_get *req_get
3641 + = (struct ip_set_req_get *) data;
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);
3649 + set = ip_set_get_byid(req_get->id);
3651 + req_get->ref = set->ref - 1;
3652 + strncpy(req_get->name, set->name, IP_SET_MAXNAMELEN);
3656 + res = copy_to_user(user, data, copylen);
3660 + ; /* Requests with set id: fall trought */
3663 + /* Requests with set id: */
3664 + if (req_base->id < 0 || req_base->id >= max_sets) {
3668 + set = ip_set_get_byid(req_base->id); /* Reference lock */
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);
3680 + } else if (req_std->level >= set->levels) {
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;
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);
3696 + req_test->reply = ip_set_testip(set,
3699 + data + sizeof(struct ip_set_req_test),
3700 + *len - sizeof(struct ip_set_req_test));
3702 + DP("test result: %i", req_test->reply);
3703 + *len = copylen = sizeof(struct ip_set_req_test);
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;
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),
3718 + res = ip_set_list_size(set,
3723 + DP("SIZEfoo size=%d", req_list->size);
3725 + goto put_set; /* Error */
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,
3738 + DP("LISTfoo done len=%d", *len);
3741 + goto put_set; /* Error */
3743 + copylen = *len; /* Only copy the mem used */
3747 + DP("unknown op %d", req_base->op);
3748 + ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3751 + } /* end of switch(op) */
3755 + DP("set %s (%u)", set->name, set->ref);
3756 + res = copy_to_user(user, data, copylen);
3762 + DP("set %s (%u)", set->name, set->ref);
3767 + DP("final result %d", res);
3771 +static struct nf_sockopt_ops so_set = {
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,
3782 +MODULE_PARM(max_sets, "i");
3783 +MODULE_PARM_DESC(max_sets, "maximal number of sets");
3785 +static int __init init(void)
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");
3796 + memset(ip_set_list, 0, sizeof(struct ip_set *) * max_sets);
3797 + INIT_LIST_HEAD(&set_type_list);
3799 + res = nf_register_sockopt(&so_set);
3801 + ip_set_printk("SO_SET registry failed: %d", res);
3802 + vfree(ip_set_list);
3808 +static void __exit fini(void)
3810 + nf_unregister_sockopt(&so_set);
3811 + vfree(ip_set_list);
3812 + DP("these are the famous last words");
3815 +EXPORT_SYMBOL(ip_set_register_set_type);
3816 +EXPORT_SYMBOL(ip_set_unregister_set_type);
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);
3823 +EXPORT_SYMBOL(ip_set_addip_kernel);
3824 +EXPORT_SYMBOL(ip_set_delip_kernel);
3825 +EXPORT_SYMBOL(ip_set_testip_kernel);
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
3834 +/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
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.
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.
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
3851 +/* Kernel module implementing an ip hash set */
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>
3865 +#include <net/ip.h>
3867 +#include <linux/netfilter_ipv4/ip_set_iphash.h>
3868 +#include <linux/netfilter_ipv4/ip_set_jhash.h>
3870 +static inline ip_set_ip_t
3871 +hash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
3873 + return (jhash_1word(ip & map->netmask, map->initval) % map->hashsize);
3877 +__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3879 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3881 + *id = hash_ip(map, ip);
3882 + return (map->members[*id] == ip);
3886 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3888 + return __testip(private, ip, id);
3892 +testip(struct ip_set_private *private, const void *data, size_t size,
3895 + struct ip_set_req_iphash *req =
3896 + (struct ip_set_req_iphash *) data;
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),
3904 + return __testip(private, req->ip, id);
3908 +testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3909 + u_int32_t flags, ip_set_ip_t *id)
3911 + if (!(flags & IPSET_TYPE_IP))
3914 + return __testip(private,
3915 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
3916 + : skb->nh.iph->daddr),
3921 +__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id,
3924 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3926 + *id = hash_ip(map, ip);
3928 + if (map->members[*id] == ip)
3931 + if (map->members[*id] != 0 && !(flags & IPSET_ADD_OVERWRITE))
3932 + return -EADDRINUSE;
3934 + map->members[*id] = ip;
3939 +addip(struct ip_set_private *private, const void *data, size_t size,
3942 + struct ip_set_req_iphash *req =
3943 + (struct ip_set_req_iphash *) data;
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),
3951 + return __addip(private, req->ip, id, req->flags);
3955 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3956 + u_int32_t flags, ip_set_ip_t *id)
3958 + if (!(flags & IPSET_TYPE_IP))
3961 + return __addip(private,
3962 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
3963 + : skb->nh.iph->daddr),
3969 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3971 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3973 + *id = hash_ip(map, ip);
3975 + if (map->members[*id] == 0)
3978 + if (map->members[*id] != ip)
3979 + return -EADDRINUSE;
3981 + map->members[*id] = 0;
3986 +delip(struct ip_set_private *private, const void *data, size_t size,
3989 + struct ip_set_req_iphash *req =
3990 + (struct ip_set_req_iphash *) data;
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),
3998 + return __delip(private, req->ip, id);
4002 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4003 + u_int32_t flags, ip_set_ip_t *id)
4005 + if (!(flags & IPSET_TYPE_IP))
4008 + return __delip(private,
4009 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4010 + : skb->nh.iph->daddr),
4014 +static int create(struct ip_set_private **private, const void *data, size_t size)
4017 + struct ip_set_req_iphash_create *req =
4018 + (struct ip_set_req_iphash_create *) data;
4019 + struct ip_set_iphash *map;
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),
4028 + if (req->hashsize > MAX_RANGE) {
4029 + ip_set_printk("hashsize too big (max %d)",
4034 + if (req->hashsize < 1) {
4035 + ip_set_printk("hashsize too small");
4039 + map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
4041 + DP("out of memory for %d bytes",
4042 + sizeof(struct ip_set_iphash));
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);
4055 + memset(map->members, 0, newbytes);
4057 + *private = (struct ip_set_private *) map;
4061 +static void destroy(struct ip_set_private **private)
4063 + struct ip_set_iphash *map = (struct ip_set_iphash *) *private;
4065 + vfree(map->members);
4071 +static void flush(struct ip_set_private *private)
4073 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4074 + memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
4077 +static int list_header_size(const struct ip_set_private *private)
4079 + return sizeof(struct ip_set_req_iphash_create);
4082 +static void list_header(const struct ip_set_private *private, void *data)
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;
4088 + header->initval = map->initval;
4089 + header->hashsize = map->hashsize;
4090 + header->netmask = map->netmask;
4093 +static int list_members_size(const struct ip_set_private *private)
4095 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4097 + return (map->hashsize * sizeof(ip_set_ip_t));
4100 +static void list_members(const struct ip_set_private *private, void *data)
4102 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4104 + int bytes = map->hashsize * sizeof(ip_set_ip_t);
4106 + memcpy(data, map->members, bytes);
4109 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4111 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4113 + return (map->hashsize);
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,
4123 + .reqsize = sizeof(struct ip_set_req_iphash),
4125 + .addip_kernel = &addip_kernel,
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,
4139 +static int __init init(void)
4141 + return ip_set_register_set_type(&ip_set_iphash);
4144 +static void __exit fini(void)
4146 + /* FIXME: possible race with ip_set_create() */
4147 + ip_set_unregister_set_type(&ip_set_iphash);
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
4157 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4158 + * Patrick Schaaf (bof@bof.de)
4159 + * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
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.
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.
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
4176 +/* Kernel module implementing an IP set type: the single bitmap type */
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>
4189 +#include <linux/netfilter_ipv4/ip_set_ipmap.h>
4191 +static inline ip_set_ip_t
4192 +ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
4194 + return ((ip & map->netmask) - map->first_ip)/map->hosts;
4198 +__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4200 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4202 + if (ip < map->first_ip || ip > map->last_ip)
4205 + *id = ip_to_id(map, ip);
4206 + return !!test_bit(*id, map->members);
4210 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4212 + return __testip(private, ip, id);
4216 +testip(struct ip_set_private *private, const void *data, size_t size,
4219 + struct ip_set_req_ipmap *req =
4220 + (struct ip_set_req_ipmap *) data;
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),
4228 + return __testip(private, req->ip, id);
4232 +testip_kernel(struct ip_set_private *private,
4233 + const struct sk_buff *skb,
4237 + if (!(flags & IPSET_TYPE_IP))
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));
4247 + return __testip(private,
4248 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4249 + : skb->nh.iph->daddr),
4254 +__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4256 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4258 + if (ip < map->first_ip || ip > map->last_ip)
4261 + *id = ip_to_id(map, ip);
4262 + if (test_and_set_bit(*id, map->members))
4269 +addip(struct ip_set_private *private, const void *data, size_t size,
4272 + struct ip_set_req_ipmap *req =
4273 + (struct ip_set_req_ipmap *) data;
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),
4281 + DP("%u.%u.%u.%u", NIPQUAD(req->ip));
4282 + return __addip(private, req->ip, id);
4286 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4287 + u_int32_t flags, ip_set_ip_t *id)
4289 + if (!(flags & IPSET_TYPE_IP))
4292 + return __addip(private,
4293 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4294 + : skb->nh.iph->daddr),
4299 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4301 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4303 + if (ip < map->first_ip || ip > map->last_ip)
4306 + *id = ip_to_id(map, ip);
4307 + if (!test_and_clear_bit(*id, map->members))
4314 +delip(struct ip_set_private *private, const void *data, size_t size,
4317 + struct ip_set_req_ipmap *req =
4318 + (struct ip_set_req_ipmap *) data;
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),
4326 + return __delip(private, req->ip, id);
4330 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4331 + u_int32_t flags, ip_set_ip_t *id)
4333 + if (!(flags & IPSET_TYPE_IP))
4336 + return __delip(private,
4337 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4338 + : skb->nh.iph->daddr),
4342 +static int create(struct ip_set_private **private, const void *data, size_t size)
4345 + struct ip_set_req_ipmap_create *req =
4346 + (struct ip_set_req_ipmap_create *) data;
4347 + struct ip_set_ipmap *map;
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),
4356 + DP("from 0x%08x to 0x%08x", req->from, req->to);
4358 + if (req->from > req->to) {
4359 + DP("bad ip range");
4363 + if (req->to - req->from > MAX_RANGE) {
4364 + ip_set_printk("range too big (max %d addresses)",
4369 + map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
4371 + DP("out of memory for %d bytes",
4372 + sizeof(struct ip_set_ipmap));
4375 + map->first_ip = req->from;
4376 + map->last_ip = req->to;
4377 + map->netmask = req->netmask;
4379 + if (req->netmask == 0xFFFFFFFF) {
4381 + map->sizeid = map->last_ip - map->first_ip + 1;
4383 + unsigned int mask_bits, netmask_bits;
4386 + map->first_ip &= map->netmask; /* Should we better bark? */
4388 + mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
4389 + netmask_bits = mask_to_bits(map->netmask);
4391 + if (!mask || netmask_bits <= mask_bits)
4394 + map->hosts = 2 << (32 - netmask_bits - 1);
4395 + map->sizeid = 2 << (netmask_bits - mask_bits - 1);
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);
4405 + memset(map->members, 0, newbytes);
4407 + *private = (struct ip_set_private *) map;
4411 +static void destroy(struct ip_set_private **private)
4413 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) *private;
4415 + kfree(map->members);
4421 +static void flush(struct ip_set_private *private)
4423 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4424 + memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
4427 +static int list_header_size(const struct ip_set_private *private)
4429 + return sizeof(struct ip_set_req_ipmap_create);
4432 +static void list_header(const struct ip_set_private *private, void *data)
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;
4438 + DP("list_header %x %x", map->first_ip, map->last_ip);
4440 + header->from = map->first_ip;
4441 + header->to = map->last_ip;
4442 + header->netmask = map->netmask;
4445 +static int list_members_size(const struct ip_set_private *private)
4447 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4449 + return bitmap_bytes(0, map->sizeid - 1);
4452 +static void list_members(const struct ip_set_private *private, void *data)
4454 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4456 + int bytes = bitmap_bytes(0, map->sizeid - 1);
4458 + memcpy(data, map->members, bytes);
4461 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4463 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4465 + return (map->sizeid);
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,
4475 + .reqsize = sizeof(struct ip_set_req_ipmap),
4477 + .addip_kernel = &addip_kernel,
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,
4491 +static int __init init(void)
4493 + return ip_set_register_set_type(&ip_set_ipmap);
4496 +static void __exit fini(void)
4498 + /* FIXME: possible race with ip_set_create() */
4499 + ip_set_unregister_set_type(&ip_set_ipmap);
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
4509 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4510 + * Patrick Schaaf (bof@bof.de)
4511 + * Martin Josefsson (gandalf@wlug.westbo.se)
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.
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.
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
4528 +/* Kernel module implementing an IP set type: the macipmap type */
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>
4543 +#include <linux/netfilter_ipv4/ip_set_macipmap.h>
4546 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4548 + struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4549 + struct ip_set_macip *table =
4550 + (struct ip_set_macip *) map->members;
4552 + if (ip < map->first_ip || ip > map->last_ip)
4555 + *id = ip - map->first_ip;
4556 + return !!test_bit(IPSET_MACIP_ISSET, &table[*id].flags);
4560 +testip(struct ip_set_private *private, const void *data, size_t size,
4563 + struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4564 + struct ip_set_macip *table =
4565 + (struct ip_set_macip *) map->members;
4567 + struct ip_set_req_macipmap *req =
4568 + (struct ip_set_req_macipmap *) data;
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),
4577 + if (req->ip < map->first_ip || req->ip > map->last_ip)
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,
4588 + return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4593 +testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4594 + u_int32_t flags, ip_set_ip_t *id)
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;
4602 + if (!(flags & IPSET_TYPE_IP))
4605 + ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4606 + : skb->nh.iph->daddr);
4608 + if (ip < map->first_ip || ip > map->last_ip)
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,
4621 + return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4625 +/* returns 0 on success */
4627 +__addip(struct ip_set_private *private,
4628 + ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *id)
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;
4635 + if (ip < map->first_ip || ip > map->last_ip)
4637 + if (test_and_set_bit(IPSET_MACIP_ISSET,
4638 + &table[ip - map->first_ip].flags))
4641 + *id = ip - map->first_ip;
4642 + memcpy(&table[*id].ethernet, ethernet, ETH_ALEN);
4647 +addip(struct ip_set_private *private, const void *data, size_t size,
4650 + struct ip_set_req_macipmap *req =
4651 + (struct ip_set_req_macipmap *) data;
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),
4659 + return __addip(private, req->ip, req->ethernet, id);
4663 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4664 + u_int32_t flags, ip_set_ip_t *id)
4668 + if (!(flags & IPSET_TYPE_IP))
4671 + ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4672 + : skb->nh.iph->daddr);
4674 + if (!(skb->mac.raw >= skb->head
4675 + && (skb->mac.raw + ETH_HLEN) <= skb->data))
4678 + return __addip(private, ip, skb->mac.ethernet->h_source, id);
4682 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
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;
4689 + if (ip < map->first_ip || ip > map->last_ip)
4691 + if (!test_and_clear_bit(IPSET_MACIP_ISSET,
4692 + &table[ip - map->first_ip].flags))
4695 + *id = ip - map->first_ip;
4700 +delip(struct ip_set_private *private, const void *data, size_t size,
4703 + struct ip_set_req_macipmap *req =
4704 + (struct ip_set_req_macipmap *) data;
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),
4712 + return __delip(private, req->ip, id);
4716 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4717 + u_int32_t flags, ip_set_ip_t *id)
4719 + if (!(flags & IPSET_TYPE_IP))
4722 + return __delip(private,
4723 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4724 + : skb->nh.iph->daddr),
4728 +static int create(struct ip_set_private **private, const void *data, size_t size)
4731 + struct ip_set_req_macipmap_create *req =
4732 + (struct ip_set_req_macipmap_create *) data;
4733 + struct ip_set_macipmap *map;
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),
4742 + DP("from 0x%08x to 0x%08x", req->from, req->to);
4744 + if (req->from > req->to) {
4745 + DP("bad ip range");
4749 + if (req->to - req->from > MAX_RANGE) {
4750 + ip_set_printk("range too big (max %d addresses)",
4755 + map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
4757 + DP("out of memory for %d bytes",
4758 + sizeof(struct ip_set_macipmap));
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);
4771 + memset(map->members, 0, newbytes);
4773 + *private = (struct ip_set_private *) map;
4777 +static void destroy(struct ip_set_private **private)
4779 + struct ip_set_macipmap *map =
4780 + (struct ip_set_macipmap *) *private;
4782 + vfree(map->members);
4788 +static void flush(struct ip_set_private *private)
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));
4796 +static int list_header_size(const struct ip_set_private *private)
4798 + return sizeof(struct ip_set_req_macipmap_create);
4801 +static void list_header(const struct ip_set_private *private, void *data)
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;
4808 + DP("list_header %x %x %u", map->first_ip, map->last_ip,
4811 + header->from = map->first_ip;
4812 + header->to = map->last_ip;
4813 + header->flags = map->flags;
4816 +static int list_members_size(const struct ip_set_private *private)
4818 + struct ip_set_macipmap *map =
4819 + (struct ip_set_macipmap *) private;
4821 + return (map->last_ip
4822 + - map->first_ip + 1) * sizeof(struct ip_set_macip);
4825 +static void list_members(const struct ip_set_private *private, void *data)
4827 + struct ip_set_macipmap *map =
4828 + (struct ip_set_macipmap *) private;
4830 + int bytes = (map->last_ip -
4831 + - map->first_ip + 1) * sizeof(struct ip_set_macip);
4833 + memcpy(data, map->members, bytes);
4836 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4838 + struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4840 + return (map->last_ip - map->first_ip + 1);
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,
4850 + .reqsize = sizeof(struct ip_set_req_macipmap),
4852 + .addip_kernel = &addip_kernel,
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,
4866 +static int __init init(void)
4868 + return ip_set_register_set_type(&ip_set_macipmap);
4871 +static void __exit fini(void)
4873 + /* FIXME: possible race with ip_set_create() */
4874 + ip_set_unregister_set_type(&ip_set_macipmap);
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
4884 +/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4886 + * Based on ip_set_ipmap.c
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.
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.
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
4903 +/* Kernel module implementing a port set type as a bitmap */
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>
4918 +#include <net/ip.h>
4920 +#include <linux/netfilter_ipv4/ip_set_portmap.h>
4922 +static inline ip_set_ip_t
4923 +get_port(const struct sk_buff *skb, u_int32_t flags)
4925 + struct iphdr *iph = skb->nh.iph;
4926 + u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
4928 + switch (iph->protocol) {
4929 + case IPPROTO_TCP: {
4930 + struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
4932 + /* See comments at tcp_match in ip_tables.c */
4935 + && (skb->len - iph->ihl * 4) < sizeof(struct tcphdr)))
4936 + return INVALID_PORT;
4938 + return ntohs(flags & IPSET_SRC ?
4939 + tcph->source : tcph->dest);
4941 + case IPPROTO_UDP: {
4942 + struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
4946 + && (skb->len - iph->ihl * 4) < sizeof(struct udphdr)))
4947 + return INVALID_PORT;
4949 + return ntohs(flags & IPSET_SRC ?
4950 + udph->source : udph->dest);
4953 + return INVALID_PORT;
4958 +__testport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4960 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
4962 + if (port < map->first_port || port > map->last_port)
4965 + *id = port - map->first_port;
4966 + return !!test_bit(*id, map->members);
4970 +matchport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4972 + return __testport(private, port, id);
4976 +testport(struct ip_set_private *private, const void *data, size_t size,
4979 + struct ip_set_req_portmap *req =
4980 + (struct ip_set_req_portmap *) data;
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),
4988 + return __testport(private, req->port, id);
4992 +testport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4993 + u_int32_t flags, ip_set_ip_t *id)
4997 + if (!(flags & IPSET_TYPE_PORT))
5000 + port = get_port(skb, flags);
5001 + DP("flags %u %s port %u",
5003 + flags & IPSET_SRC ? "SRC" : "DST",
5006 + if (port == INVALID_PORT)
5009 + return __testport(private, port, id);
5013 +__addport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5015 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5017 + if (port < map->first_port || port > map->last_port)
5019 + if (test_and_set_bit(port - map->first_port, map->members))
5022 + *id = port - map->first_port;
5027 +addport(struct ip_set_private *private, const void *data, size_t size,
5030 + struct ip_set_req_portmap *req =
5031 + (struct ip_set_req_portmap *) data;
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),
5039 + return __addport(private, req->port, id);
5043 +addport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5044 + u_int32_t flags, ip_set_ip_t *id)
5048 + if (!(flags & IPSET_TYPE_PORT))
5051 + port = get_port(skb, flags);
5053 + if (port == INVALID_PORT)
5056 + return __addport(private, port, id);
5060 +__delport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5062 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5064 + if (port < map->first_port || port > map->last_port)
5066 + if (!test_and_clear_bit(port - map->first_port, map->members))
5069 + *id = port - map->first_port;
5074 +delport(struct ip_set_private *private, const void *data, size_t size,
5077 + struct ip_set_req_portmap *req =
5078 + (struct ip_set_req_portmap *) data;
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),
5086 + return __delport(private, req->port, id);
5090 +delport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5091 + u_int32_t flags, ip_set_ip_t *id)
5095 + if (!(flags & IPSET_TYPE_PORT))
5098 + port = get_port(skb, flags);
5100 + if (port == INVALID_PORT)
5103 + return __delport(private, port, id);
5106 +static int create(struct ip_set_private **private, const void *data, size_t size)
5109 + struct ip_set_req_portmap_create *req =
5110 + (struct ip_set_req_portmap_create *) data;
5111 + struct ip_set_portmap *map;
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),
5120 + DP("from 0x%08x to 0x%08x", req->from, req->to);
5122 + if (req->from > req->to) {
5123 + DP("bad port range");
5127 + if (req->to - req->from > MAX_RANGE) {
5128 + ip_set_printk("range too big (max %d ports)",
5133 + map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
5135 + DP("out of memory for %d bytes",
5136 + sizeof(struct ip_set_portmap));
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);
5148 + memset(map->members, 0, newbytes);
5150 + *private = (struct ip_set_private *) map;
5154 +static void destroy(struct ip_set_private **private)
5156 + struct ip_set_portmap *map = (struct ip_set_portmap *) *private;
5158 + kfree(map->members);
5164 +static void flush(struct ip_set_private *private)
5166 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5167 + memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
5170 +static int list_header_size(const struct ip_set_private *private)
5172 + return sizeof(struct ip_set_req_portmap_create);
5175 +static void list_header(const struct ip_set_private *private, void *data)
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;
5181 + DP("list_header %x %x", map->first_port, map->last_port);
5183 + header->from = map->first_port;
5184 + header->to = map->last_port;
5187 +static int list_members_size(const struct ip_set_private *private)
5189 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5191 + return bitmap_bytes(map->first_port, map->last_port);
5194 +static void list_members(const struct ip_set_private *private, void *data)
5196 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5198 + int bytes = bitmap_bytes(map->first_port, map->last_port);
5200 + memcpy(data, map->members, bytes);
5203 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
5205 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5207 + return (map->last_port - map->first_port + 1);
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,
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,
5233 +static int __init init(void)
5235 + return ip_set_register_set_type(&ip_set_portmap);
5238 +static void __exit fini(void)
5240 + /* FIXME: possible race with ip_set_create() */
5241 + ip_set_unregister_set_type(&ip_set_portmap);
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
5252 + * Strip all IP options in the IP packet header.
5254 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
5255 + * This software is distributed under GNU GPL v2, 1991
5258 +#include <linux/module.h>
5259 +#include <linux/skbuff.h>
5260 +#include <linux/ip.h>
5261 +#include <net/checksum.h>
5263 +#include <linux/netfilter_ipv4/ip_tables.h>
5265 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5266 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
5267 +MODULE_LICENSE("GPL");
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,
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;
5284 + /* if no options in packet then nothing to clear. */
5285 + if (iph->ihl * 4 == sizeof(struct iphdr))
5286 + return IPT_CONTINUE;
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);
5295 + skb->nfcache |= NFC_ALTERED;
5297 + return IPT_CONTINUE;
5301 +checkentry(const char *tablename,
5302 + const struct ipt_entry *e,
5304 + unsigned int targinfosize,
5305 + unsigned int hook_mask)
5307 + if (strcmp(tablename, "mangle")) {
5308 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5311 + /* nothing else to check because no parameters */
5315 +static struct ipt_target ipt_ipv4optsstrip_reg
5316 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
5318 +static int __init init(void)
5320 + if (ipt_register_target(&ipt_ipv4optsstrip_reg))
5322 + printk("ipt_IPV4OPTSSTRIP loaded\n");
5327 +static void __exit fini(void)
5329 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
5330 + printk("ipt_IPV4OPTSSTRIP unloaded\n");
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
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>
5353 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
5354 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
5355 +MODULE_LICENSE("GPL");
5358 +#define DEBUGP printk
5360 +#define DEBUGP(format, args...)
5363 +static struct sock *ipfwsk;
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)
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;
5377 + /* Allocate a socket buffer */
5378 + if ( MASK(nld->flags, USE_SIZE) )
5379 + len = nld->size+sizeof(nlhdr);
5381 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
5383 + outskb=alloc_skb(len, GFP_ATOMIC);
5388 + if ( MASK(nld->flags, USE_MARK) )
5389 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
5391 + nlhdr.mark=(*pskb)->nfmark;
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);
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);
5404 + if (net_ratelimit())
5405 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
5408 + if ( MASK(nld->flags, USE_DROP) )
5411 + return IPT_CONTINUE;
5414 +static int ipt_netlink_checkentry(const char *tablename,
5415 + const struct ipt_entry *e,
5417 + unsigned int targinfosize,
5418 + unsigned int hookmask)
5420 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5425 +static struct ipt_target ipt_netlink_reg = {
5428 + ipt_netlink_target,
5429 + ipt_netlink_checkentry,
5434 +static int __init init(void)
5436 + DEBUGP("ipt_NETLINK: init module\n");
5438 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
5442 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
5449 +static void __exit fini(void)
5451 + DEBUGP("ipt_NETLINK: cleanup_module\n");
5452 + ipt_unregister_target(&ipt_netlink_reg);
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
5461 +/* ipt_POOL.c - netfilter target to manipulate IP pools
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.
5468 + * The target normally returns IPT_CONTINUE.
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>
5486 +#define DEBUGP printk
5488 +#define DEBUGP(format, args...)
5491 +/*** NOTE NOTE NOTE NOTE ***
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.
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.
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.)
5509 +do_check(const char *tablename,
5510 + const struct ipt_entry *e,
5512 + unsigned int targinfosize,
5513 + unsigned int hook_mask)
5515 + const struct ipt_pool_info *ipi = targinfo;
5517 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
5518 + DEBUGP("POOL_check: size %u.\n", targinfosize);
5521 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
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,
5533 + const struct ipt_pool_info *ipi = targinfo;
5535 + unsigned int verdict = IPT_CONTINUE;
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;
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;
5560 +static struct ipt_target pool_reg
5561 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
5563 +static int __init init(void)
5565 + DEBUGP("init ipt_POOL\n");
5566 + return ipt_register_target(&pool_reg);
5569 +static void __exit fini(void)
5571 + DEBUGP("fini ipt_POOL\n");
5572 + ipt_unregister_target(&pool_reg);
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
5581 +/* ipt_SET.c - netfilter target to manipulate IP sets
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.
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>
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,
5612 + const struct ipt_set_info_target *info = targinfo;
5614 + if (info->add_set.id >= 0)
5615 + ip_set_addip_kernel(ip_set_list[info->add_set.id],
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],
5623 + info->del_set.flags,
5624 + info->del_set.set_level,
5625 + info->del_set.ip_level);
5627 + return IPT_CONTINUE;
5631 +checkentry(const char *tablename,
5632 + const struct ipt_entry *e,
5634 + unsigned int targinfosize, unsigned int hook_mask)
5636 + struct ipt_set_info_target *info = targinfo;
5638 + if (targinfosize != IPT_ALIGN(sizeof(*info))) {
5639 + DP("bad target info size %u", targinfosize);
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 */
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 */
5655 + DP("checkentry OK");
5660 +static void destroy(void *targetinfo, unsigned int targetsize)
5662 + struct ipt_set_info_target *info = targetinfo;
5664 + if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
5665 + ip_set_printk("invalid targetsize %d", targetsize);
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]);
5675 +static struct ipt_target SET_target = {
5678 + .checkentry = checkentry,
5679 + .destroy = destroy,
5683 +static int __init init(void)
5685 + return ipt_register_target(&SET_target);
5688 +static void __exit fini(void)
5690 + ipt_unregister_target(&SET_target);
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
5700 +/* TTL modification target for IP tables
5701 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
5705 + * This software is distributed under the terms of GNU GPL
5708 +#include <linux/module.h>
5709 +#include <linux/skbuff.h>
5710 +#include <linux/ip.h>
5711 +#include <net/checksum.h>
5713 +#include <linux/netfilter_ipv4/ip_tables.h>
5714 +#include <linux/netfilter_ipv4/ipt_TTL.h>
5716 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
5717 +MODULE_DESCRIPTION("IP tables TTL modification module");
5718 +MODULE_LICENSE("GPL");
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)
5724 + struct iphdr *iph = (*pskb)->nh.iph;
5725 + const struct ipt_TTL_info *info = targinfo;
5726 + u_int16_t diffs[2];
5729 + switch (info->mode) {
5731 + new_ttl = info->ttl;
5734 + new_ttl = iph->ttl + info->ttl;
5735 + if (new_ttl > 255)
5739 + new_ttl = iph->ttl + info->ttl;
5744 + new_ttl = iph->ttl;
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,
5754 + iph->check^0xFFFF));
5755 + (*pskb)->nfcache |= NFC_ALTERED;
5758 + return IPT_CONTINUE;
5761 +static int ipt_ttl_checkentry(const char *tablename,
5762 + const struct ipt_entry *e,
5764 + unsigned int targinfosize,
5765 + unsigned int hook_mask)
5767 + struct ipt_TTL_info *info = targinfo;
5769 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
5770 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
5772 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
5776 + if (strcmp(tablename, "mangle")) {
5777 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5781 + if (info->mode > IPT_TTL_MAXMODE) {
5782 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
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");
5795 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
5796 + ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
5798 +static int __init init(void)
5800 + return ipt_register_target(&ipt_TTL);
5803 +static void __exit fini(void)
5805 + ipt_unregister_target(&ipt_TTL);
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
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
5823 + * Kernel module to match connection tracking information.
5824 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
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>
5837 +MODULE_LICENSE("GPL");
5839 +/* we'll save the tuples of all connections we care about */
5840 +struct ipt_connlimit_conn
5842 + struct list_head list;
5843 + struct ip_conntrack_tuple tuple;
5846 +struct ipt_connlimit_data {
5848 + struct list_head iphash[256];
5851 +static int ipt_iphash(u_int32_t addr)
5855 + hash = addr & 0xff;
5856 + hash ^= (addr >> 8) & 0xff;
5857 + hash ^= (addr >> 16) & 0xff;
5858 + hash ^= (addr >> 24) & 0xff;
5862 +static int count_them(struct ipt_connlimit_data *data,
5863 + u_int32_t addr, u_int32_t mask,
5864 + struct ip_conntrack *ct)
5867 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
5868 + "fin_wait", "time_wait", "close", "close_wait",
5869 + "last_ack", "listen" };
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;
5877 + spin_lock(&data->lock);
5878 + tuple = ct->tuplehash[0].tuple;
5879 + hash = &data->iphash[ipt_iphash(addr & mask)];
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)) &&
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" */
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");
5900 + if (NULL == found) {
5901 + /* this one is gone */
5903 + list_del(lh->next);
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 */
5911 + list_del(lh->next);
5913 + nf_conntrack_put(&found->ctrack->infos[0]);
5916 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
5917 + /* same source IP address -> be counted! */
5920 + nf_conntrack_put(&found->ctrack->infos[0]);
5923 + /* save the new connection in our list */
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));
5930 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
5933 + memset(conn,0,sizeof(*conn));
5934 + INIT_LIST_HEAD(&conn->list);
5935 + conn->tuple = tuple;
5936 + list_add(&conn->list,hash);
5939 + spin_unlock(&data->lock);
5944 +match(const struct sk_buff *skb,
5945 + const struct net_device *in,
5946 + const struct net_device *out,
5947 + const void *matchinfo,
5950 + u_int16_t datalen,
5953 + const struct ipt_connlimit_info *info = matchinfo;
5954 + int connections, match;
5955 + struct ip_conntrack *ct;
5956 + enum ip_conntrack_info ctinfo;
5958 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
5960 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
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 :-) */
5970 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
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");
5981 +static int check(const char *tablename,
5982 + const struct ipt_ip *ip,
5984 + unsigned int matchsize,
5985 + unsigned int hook_mask)
5987 + struct ipt_connlimit_info *info = matchinfo;
5991 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
5994 + /* refuse anything but tcp */
5995 + if (ip->proto != IPPROTO_TCP)
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]));
6007 +static void destroy(void *matchinfo, unsigned int matchinfosize)
6009 + struct ipt_connlimit_info *info = matchinfo;
6010 + struct ipt_connlimit_conn *conn;
6011 + struct list_head *hash;
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);
6023 + kfree(info->data);
6026 +static struct ipt_match connlimit_match
6027 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
6029 +static int __init init(void)
6031 + return ipt_register_match(&connlimit_match);
6034 +static void __exit fini(void)
6036 + ipt_unregister_match(&connlimit_match);
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
6045 +/* iptables match extension to limit the number of packets per second
6046 + * seperately for each destination.
6048 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
6052 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
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>
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.
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 ;)
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>
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>
6085 +#include <linux/netfilter_ipv4/ip_tables.h>
6086 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
6088 +/* FIXME: this is just for IP_NF_ASSERRT */
6089 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6091 +#define MS2JIFFIES(x) ((x*HZ)/1000)
6093 +MODULE_LICENSE("GPL");
6094 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
6095 +MODULE_DESCRIPTION("iptables match for limiting per destination");
6097 +/* need to declare this at the top */
6098 +static struct proc_dir_entry *dstlimit_procdir;
6099 +static struct file_operations dl_file_ops;
6101 +/* hash table crap */
6103 +struct dsthash_dst {
6109 +struct dsthash_ent {
6110 + /* static / read-only parts in the beginning */
6111 + struct list_head list;
6112 + struct dsthash_dst dst;
6114 + /* modified structure members in the end */
6115 + unsigned long expires; /* precalculated expiry time */
6117 + unsigned long prev; /* last modification */
6119 + u_int32_t credit_cap, cost;
6123 +struct ipt_dstlimit_htable {
6124 + struct list_head list; /* global list of all htables */
6127 + struct dstlimit_cfg cfg; /* config */
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 */
6135 + /* seq_file stuff */
6136 + struct proc_dir_entry *pde;
6138 + struct list_head hash[0]; /* hashtable itself */
6141 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
6142 +static LIST_HEAD(dstlimit_htables);
6143 +static kmem_cache_t *dstlimit_cachep;
6145 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
6147 + return (ent->dst.dst_ip == b->dst_ip
6148 + && ent->dst.port == b->port
6149 + && ent->dst.src_ip == b->src_ip);
6152 +static inline u_int32_t
6153 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
6155 + return (jhash_3words(dst->dst_ip, dst->port,
6156 + dst->src_ip, ht->rnd) % ht->cfg.size);
6159 +static inline struct dsthash_ent *
6160 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
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);
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)
6173 + struct dsthash_ent *ent;
6175 + /* initialize hash with random val at the time we allocate
6176 + * the first hashtable entry */
6178 + get_random_bytes(&ht->rnd, 4);
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",
6190 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
6192 + if (net_ratelimit())
6194 + "ipt_dstlimit: can't allocate dsthash_ent\n");
6198 + atomic_inc(&ht->count);
6200 + ent->dst.dst_ip = dst->dst_ip;
6201 + ent->dst.port = dst->port;
6202 + ent->dst.src_ip = dst->src_ip;
6204 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
6210 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
6212 + MUST_BE_LOCKED(&ht->lock);
6214 + list_del(&ent->list);
6215 + kmem_cache_free(dstlimit_cachep, ent);
6216 + atomic_dec(&ht->count);
6218 +static void htable_gc(unsigned long htlong);
6220 +static int htable_create(struct ipt_dstlimit_info *minfo)
6223 + unsigned int size;
6224 + struct ipt_dstlimit_htable *hinfo;
6226 + if (minfo->cfg.size)
6227 + size = minfo->cfg.size;
6229 + size = (((num_physpages << PAGE_SHIFT) / 16384)
6230 + / sizeof(struct list_head));
6231 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
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));
6240 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
6243 + minfo->hinfo = hinfo;
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;
6253 + for (i = 0; i < hinfo->cfg.size; i++)
6254 + INIT_LIST_HEAD(&hinfo->hash[i]);
6256 + atomic_set(&hinfo->count, 0);
6257 + atomic_set(&hinfo->use, 1);
6259 + hinfo->lock = SPIN_LOCK_UNLOCKED;
6260 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
6261 + if (!hinfo->pde) {
6265 + hinfo->pde->proc_fops = &dl_file_ops;
6266 + hinfo->pde->data = hinfo;
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);
6274 + WRITE_LOCK(&dstlimit_lock);
6275 + list_add(&hinfo->list, &dstlimit_htables);
6276 + WRITE_UNLOCK(&dstlimit_lock);
6281 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
6286 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
6288 + return (jiffies >= he->expires);
6291 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
6292 + int (*select)(struct ipt_dstlimit_htable *ht,
6293 + struct dsthash_ent *he))
6297 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
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);
6308 + UNLOCK_BH(&ht->lock);
6311 +/* hash table garbage collector, run by timer */
6312 +static void htable_gc(unsigned long htlong)
6314 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
6316 + htable_selective_cleanup(ht, select_gc);
6318 + /* re-add the timer accordingly */
6319 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
6320 + add_timer(&ht->timer);
6323 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
6325 + /* remove timer, if it is pending */
6326 + if (timer_pending(&hinfo->timer))
6327 + del_timer(&hinfo->timer);
6329 + /* remove proc entry */
6330 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
6332 + htable_selective_cleanup(hinfo, select_all);
6336 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
6338 + struct ipt_dstlimit_htable *hinfo;
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);
6348 + READ_UNLOCK(&dstlimit_lock);
6353 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
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);
6364 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
6365 + * see net/sched/sch_tbf.c in the linux source tree
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
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.
6379 + See Alexey's formal explanation in net/sched/sch_tbf.c.
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.
6386 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
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
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)
6398 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
6400 +/* Precision saver. */
6401 +static inline u_int32_t
6402 +user2credits(u_int32_t user)
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;
6409 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
6412 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
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;
6421 +dstlimit_match(const struct sk_buff *skb,
6422 + const struct net_device *in,
6423 + const struct net_device *out,
6424 + const void *matchinfo,
6427 + u_int16_t datalen,
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;
6437 + memset(&dst, 0, sizeof(dst));
6439 + /* dest ip is always in hash */
6440 + dst.dst_ip = skb->nh.iph->daddr;
6442 + /* source ip only if respective hashmode, otherwise set to
6444 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
6445 + dst.src_ip = skb->nh.iph->saddr;
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;
6453 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
6454 + dst.port = th->dest;
6457 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
6458 + dst.port = uh->dest;
6465 + LOCK_BH(&hinfo->lock);
6466 + dh = __dsthash_find(hinfo, &dst);
6468 + dh = __dsthash_alloc_init(hinfo, &dst);
6471 + /* enomem... don't match == DROP */
6472 + if (net_ratelimit())
6473 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
6474 + UNLOCK_BH(&hinfo->lock);
6478 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
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);
6487 + UNLOCK_BH(&hinfo->lock);
6491 + /* update expiration timeout */
6492 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
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);
6502 + UNLOCK_BH(&hinfo->lock);
6504 + /* default case: we're overlimit, thus don't match */
6509 +dstlimit_checkentry(const char *tablename,
6510 + const struct ipt_ip *ip,
6512 + unsigned int matchsize,
6513 + unsigned int hook_mask)
6515 + struct ipt_dstlimit_info *r = matchinfo;
6517 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
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);
6529 + if (r->cfg.mode == 0
6530 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
6531 + |IPT_DSTLIMIT_HASH_DIP
6532 + |IPT_DSTLIMIT_HASH_SIP))
6535 + if (!r->cfg.gc_interval)
6538 + if (!r->cfg.expire)
6541 + r->hinfo = htable_find_get(r->name);
6542 + if (!r->hinfo && (htable_create(r) != 0)) {
6546 + /* Ugly hack: For SMP, we only want to use one set */
6553 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
6555 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
6557 + htable_put(r->hinfo);
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,
6571 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
6573 + struct proc_dir_entry *pde = s->private;
6574 + struct ipt_dstlimit_htable *htable = pde->data;
6575 + unsigned int *bucket;
6577 + LOCK_BH(&htable->lock);
6578 + if (*pos >= htable->cfg.size)
6581 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
6583 + return ERR_PTR(-ENOMEM);
6589 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
6591 + struct proc_dir_entry *pde = s->private;
6592 + struct ipt_dstlimit_htable *htable = pde->data;
6593 + unsigned int *bucket = (unsigned int *)v;
6595 + *pos = ++(*bucket);
6596 + if (*pos >= htable->cfg.size) {
6603 +static void dl_seq_stop(struct seq_file *s, void *v)
6605 + struct proc_dir_entry *pde = s->private;
6606 + struct ipt_dstlimit_htable *htable = pde->data;
6607 + unsigned int *bucket = (unsigned int *)v;
6611 + UNLOCK_BH(&htable->lock);
6614 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
6616 + /* recalculate to show accurate numbers */
6617 + rateinfo_recalc(ent, jiffies);
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);
6627 +static int dl_seq_show(struct seq_file *s, void *v)
6629 + struct proc_dir_entry *pde = s->private;
6630 + struct ipt_dstlimit_htable *htable = pde->data;
6631 + unsigned int *bucket = (unsigned int *)v;
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 */
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
6648 +static int dl_proc_open(struct inode *inode, struct file *file)
6650 + int ret = seq_open(file, &dl_seq_ops);
6653 + struct seq_file *sf = file->private_data;
6654 + sf->private = PDE(inode);
6659 +static struct file_operations dl_file_ops = {
6660 + .owner = THIS_MODULE,
6661 + .open = dl_proc_open,
6663 + .llseek = seq_lseek,
6664 + .release = seq_release
6667 +static int init_or_fini(int fini)
6674 + if (ipt_register_match(&ipt_dstlimit)) {
6676 + goto cleanup_nothing;
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");
6687 + goto cleanup_unreg_match;
6690 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
6691 + if (!dstlimit_procdir) {
6692 + printk(KERN_ERR "Unable to create proc dir entry\n");
6694 + goto cleanup_free_slab;
6700 + remove_proc_entry("ipt_dstlimit", proc_net);
6702 + kmem_cache_destroy(dstlimit_cachep);
6703 +cleanup_unreg_match:
6704 + ipt_unregister_match(&ipt_dstlimit);
6710 +static int __init init(void)
6712 + return init_or_fini(0);
6715 +static void __exit fini(void)
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
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 .
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 .
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>
6754 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6755 + Expressed in percentage
6758 +#define PAR_LOW 1/100
6761 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
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");
6767 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6769 + if (tx >= maxi) return 100;
6771 + if (tx <= mini) return 0;
6773 + return ( (100*(tx-mini)) / (maxi-mini) ) ;
6776 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6778 + if (tx <= mini) return 100;
6780 + if (tx >= maxi) return 0;
6782 + return ( (100*( maxi - tx )) / ( maxi - mini ) ) ;
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,
6793 + u_int16_t datalen,
6796 + /* From userspace */
6798 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
6800 + u_int8_t random_number;
6801 + unsigned long amount ;
6802 + u_int8_t howhigh , howlow ;
6805 + spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
6807 + info->bytes_total += pskb->len ;
6808 + info->packets_total++ ;
6810 + info->present_time = jiffies ;
6812 + if ( info->present_time >= info->previous_time )
6813 + amount = info->present_time - info->previous_time ;
6815 + /* There was a transition : I choose to re-sample
6816 + and keep the old acceptance rate...
6820 + info->previous_time = info->present_time ;
6821 + info->bytes_total = info->packets_total = 0;
6824 + if ( amount > HZ/10 ) /* More than 100 ms elapsed ... */
6827 + info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total ) \
6830 + info->previous_time = info->present_time ;
6831 + info->bytes_total = info->packets_total = 0 ;
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);
6836 + info->acceptance_rate = (u_int8_t) \
6837 + ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
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 ,
6849 + spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
6852 + if ( info->acceptance_rate < 100 )
6854 + get_random_bytes((void *)(&random_number), 1);
6856 + /* If within the acceptance , it can pass => don't match */
6857 + if ( random_number <= (255 * info->acceptance_rate) / 100 )
6860 + return 1; /* It can't pass ( It matches ) */
6863 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
6868 +ipt_fuzzy_checkentry(const char *tablename,
6869 + const struct ipt_ip *e,
6871 + unsigned int matchsize,
6872 + unsigned int hook_mask)
6875 + const struct ipt_fuzzy_info *info = matchinfo;
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)));
6883 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
6884 + || (info->minimum_rate >= info->maximum_rate ))
6886 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
6893 +static struct ipt_match ipt_fuzzy_reg = {
6897 + ipt_fuzzy_checkentry,
6901 +static int __init init(void)
6903 + if (ipt_register_match(&ipt_fuzzy_reg))
6909 +static void __exit fini(void)
6911 + ipt_unregister_match(&ipt_fuzzy_reg);
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
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
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.
6932 +#include <linux/module.h>
6933 +#include <linux/skbuff.h>
6934 +#include <net/ip.h>
6936 +#include <linux/netfilter_ipv4/ip_tables.h>
6937 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
6939 +MODULE_LICENSE("GPL");
6942 +match(const struct sk_buff *skb,
6943 + const struct net_device *in,
6944 + const struct net_device *out,
6945 + const void *matchinfo,
6948 + u_int16_t datalen,
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;
6955 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
6956 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
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))
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 */
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 ! */
6978 + opt = &(IPCB(skb)->opt);
6980 + /* source routing */
6981 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
6982 + if (!((opt->srr) & (opt->is_strictroute)))
6985 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
6986 + if (!((opt->srr) & (!opt->is_strictroute)))
6989 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
6993 + /* record route */
6994 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
6998 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
7003 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
7007 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
7011 + /* router-alert option */
7012 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
7013 + if (!opt->router_alert)
7016 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
7017 + if (opt->router_alert)
7026 +checkentry(const char *tablename,
7027 + const struct ipt_ip *ip,
7029 + unsigned int matchsize,
7030 + unsigned int hook_mask)
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)))
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 */
7069 + /* everything looks ok. */
7073 +static struct ipt_match ipv4options_match
7074 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
7076 +static int __init init(void)
7078 + printk("ipt_ipv4options loading\n");
7079 + return ipt_register_match(&ipv4options_match);
7082 +static void __exit fini(void)
7084 + ipt_unregister_match(&ipv4options_match);
7085 + printk("ipt_ipv4options unloaded\n");
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
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>
7101 +#include <linux/netfilter_ipv4/ipt_mport.h>
7102 +#include <linux/netfilter_ipv4/ip_tables.h>
7104 +MODULE_LICENSE("GPL");
7107 +#define duprintf(format, args...) printk(format , ## args)
7109 +#define duprintf(format, args...)
7112 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
7114 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
7118 + u_int16_t pflags = minfo->pflags;
7119 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
7123 + && minfo->ports[i] == 65535)
7126 + s = minfo->ports[i];
7129 + e = minfo->ports[++i];
7134 + if (minfo->flags & IPT_MPORT_SOURCE
7135 + && src >= s && src <= e)
7138 + if (minfo->flags & IPT_MPORT_DESTINATION
7139 + && dst >= s && dst <= e)
7147 +match(const struct sk_buff *skb,
7148 + const struct net_device *in,
7149 + const struct net_device *out,
7150 + const void *matchinfo,
7153 + u_int16_t datalen,
7156 + const struct udphdr *udp = hdr;
7157 + const struct ipt_mport *minfo = matchinfo;
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");
7169 + /* Must not be a fragment. */
7171 + && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
7174 +/* Called when user tries to insert an entry of this type. */
7176 +checkentry(const char *tablename,
7177 + const struct ipt_ip *ip,
7179 + unsigned int matchsize,
7180 + unsigned int hook_mask)
7182 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
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));
7191 +static struct ipt_match mport_match
7192 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
7194 +static int __init init(void)
7196 + return ipt_register_match(&mport_match);
7199 +static void __exit fini(void)
7201 + ipt_unregister_match(&mport_match);
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
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
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
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>
7232 +MODULE_LICENSE("GPL");
7235 + * State information.
7242 +static struct state states[IPT_NTH_NUM_COUNTERS];
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,
7251 + u_int16_t datalen,
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))
7259 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
7263 + spin_lock(&states[counter].lock);
7265 + /* Are we matching every nth packet?*/
7266 + if (info->packet == 0xFF)
7268 + /* We're matching every nth packet and only every nth packet*/
7269 + /* Do we match or invert match? */
7270 + if (info->not == 0)
7272 + if (states[counter].number == 0)
7274 + ++states[counter].number;
7277 + if (states[counter].number >= info->every)
7278 + states[counter].number = 0; /* reset the counter */
7280 + ++states[counter].number;
7285 + if (states[counter].number == 0)
7287 + ++states[counter].number;
7290 + if (states[counter].number >= info->every)
7291 + states[counter].number = 0;
7293 + ++states[counter].number;
7299 + /* We're using the --packet, so there must be a rule for every value */
7300 + if (states[counter].number == info->packet)
7302 + /* only increment the counter when a match happens */
7303 + if (states[counter].number >= info->every)
7304 + states[counter].number = 0; /* reset the counter */
7306 + ++states[counter].number;
7315 + spin_unlock(&states[counter].lock);
7319 + spin_unlock(&states[counter].lock);
7324 +ipt_nth_checkentry(const char *tablename,
7325 + const struct ipt_ip *e,
7327 + unsigned int matchsize,
7328 + unsigned int hook_mask)
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))
7335 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
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)));
7345 + states[counter].number = info->startat;
7350 +static struct ipt_match ipt_nth_reg = {
7354 + ipt_nth_checkentry,
7358 +static int __init init(void)
7361 + memset(&states, 0, sizeof(states));
7362 + if (ipt_register_match(&ipt_nth_reg))
7365 + for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
7367 + spin_lock_init(&(states[counter].lock));
7370 + printk("ipt_nth match loaded\n");
7374 +static void __exit fini(void)
7376 + ipt_unregister_match(&ipt_nth_reg);
7377 + printk("ipt_nth match unloaded\n");
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
7389 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
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.
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.
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
7408 + * OS fingerprint matching module.
7409 + * It simply compares various parameters from SYN packet with
7410 + * some hardcoded ones.
7412 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
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>
7430 +#include <net/sock.h>
7431 +#include <net/ip.h>
7433 +#include <linux/netfilter_ipv4/ip_tables.h>
7435 +#include <linux/netfilter_ipv4/ipt_osf.h>
7440 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
7441 +#define loga(x...) printk(x)
7443 +#define log(x...) do {} while(0)
7444 +#define loga(x...) do {} while(0)
7447 +#define FMATCH_WRONG 0
7448 +#define FMATCH_OK 1
7449 +#define FMATCH_OPT_WRONG 2
7452 +#define OSFPDEL ':'
7453 +#define MAXOPTSTRLEN 128
7454 +#define OSFFLUSH "FLUSH"
7456 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
7457 +static struct list_head finger_list;
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);
7464 +static struct ipt_match osf_match =
7474 +static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
7476 + if (flags & IPT_OSF_SMART)
7479 + return (ip_ttl == f_ttl);
7483 +match(const struct sk_buff *skb,
7484 + const struct net_device *in,
7485 + const struct net_device *out,
7486 + const void *matchinfo,
7489 + u_int16_t datalen,
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;
7505 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
7509 + else if (tcp->ack)
7512 + totlen = ntohs(ip->tot_len);
7513 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
7514 + window = ntohs(tcp->window);
7516 + if (tcp->doff*4 > sizeof(struct tcphdr))
7518 + _optp = optp = (char *)(tcp+1);
7519 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
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.
7527 + read_lock(&osf_lock);
7528 + list_for_each(ent, &finger_list)
7530 + f = list_entry(ent, struct osf_finger, flist);
7532 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
7536 + fmatch = FMATCH_WRONG;
7538 + if (totlen == f->ss && df == f->df &&
7539 + smart_dec(info->flags, ip->ttl, f->ttl))
7541 + unsigned long foptsize;
7543 + unsigned short mss = 0;
7547 + switch (f->wss.wc)
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);
7558 + if (check_WSS == 4)
7561 + /* Check options */
7564 + for (optnum=0; optnum<f->opt_num; ++optnum)
7565 + foptsize += f->opt[optnum].length;
7568 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
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)
7583 + for (optnum=0; optnum<f->opt_num; ++optnum)
7585 + if (f->opt[optnum].kind == (*optp))
7587 + unsigned char len = f->opt[optnum].length;
7588 + unsigned char *optend = optp + len;
7590 + fmatch = FMATCH_OK;
7592 + if (*optp == OSFOPT_MSS) /* MSS */
7593 + mss = ntohs(*(unsigned short *)(optp+2));
7597 + /* Skip kind and length fields*/
7600 + if (f->opt[optnum].wc.wc != 0)
7602 + unsigned long tmp = 0;
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));
7610 + if (tmp != f->opt[optnum].wc.val)
7611 + fmatch = FMATCH_OPT_WRONG;
7618 + fmatch = FMATCH_OPT_WRONG;
7620 + if (fmatch != FMATCH_OK)
7624 + if (fmatch != FMATCH_OPT_WRONG)
7626 + fmatch = FMATCH_WRONG;
7628 + switch (check_WSS)
7631 + if (window == f->wss.val)
7632 + fmatch = FMATCH_OK;
7635 + if (window == f->wss.val*mss)
7636 + fmatch = FMATCH_OK;
7639 + if (window == f->wss.val*(mss+40))
7640 + fmatch = FMATCH_OK;
7643 + if (window % f->wss.val == 0)
7644 + fmatch = FMATCH_OK;
7650 + if (fmatch == FMATCH_OK)
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)
7663 + if (!fcount && (info->flags & IPT_OSF_LOG))
7665 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
7668 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
7669 + unsigned int i, optsize;
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");
7676 + for (i = 0; i < optsize; i++)
7677 + loga("%02X", opt[i]);
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));
7684 + read_unlock(&osf_lock);
7686 + return (fmatch == FMATCH_OK)?1:0;
7690 +checkentry(const char *tablename,
7691 + const struct ipt_ip *ip,
7693 + unsigned int matchsize,
7694 + unsigned int hook_mask)
7696 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
7698 + if (ip->proto != IPPROTO_TCP)
7704 +static char * osf_strchr(char *ptr, char c)
7708 + tmp = strchr(ptr, c);
7710 + while (tmp && tmp+1 && isspace(*(tmp+1)))
7716 +static struct osf_finger * finger_alloc(void)
7718 + struct osf_finger *f;
7720 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
7722 + memset(f, 0, sizeof(struct osf_finger));
7727 +static void finger_free(struct osf_finger *f)
7729 + memset(f, 0, sizeof(struct osf_finger));
7734 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
7738 + unsigned long val;
7742 + while (ptr != NULL && i < olen)
7751 + ptr = osf_strchr(&obuf[i], OPTDEL);
7756 + i += (int)(ptr-&obuf[i]);
7763 + op = OSFOPT_SACKP;
7764 + ptr = osf_strchr(&obuf[i], OPTDEL);
7769 + i += (int)(ptr-&obuf[i]);
7777 + ptr = osf_strchr(&obuf[i], OPTDEL);
7782 + i += (int)(ptr-&obuf[i]);
7790 + ptr = osf_strchr(&obuf[i], OPTDEL);
7793 + switch (obuf[i+1])
7795 + case '%': wc = '%'; break;
7796 + case 'S': wc = 'S'; break;
7797 + case 'T': wc = 'T'; break;
7798 + default: wc = 0; break;
7804 + val = simple_strtoul(&obuf[i+2], NULL, 10);
7806 + val = simple_strtoul(&obuf[i+1], NULL, 10);
7807 + i += (int)(ptr-&obuf[i]);
7815 + ptr = osf_strchr(&obuf[i], OPTDEL);
7818 + if (obuf[i+1] == '%')
7823 + val = simple_strtoul(&obuf[i+2], NULL, 10);
7825 + val = simple_strtoul(&obuf[i+1], NULL, 10);
7826 + i += (int)(ptr-&obuf[i]);
7834 + ptr = osf_strchr(&obuf[i], OPTDEL);
7839 + i += (int)(ptr-&obuf[i]);
7846 + ptr = osf_strchr(&obuf[i], OPTDEL);
7850 + i += (int)(ptr-&obuf[i]);
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;
7867 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
7869 + struct list_head *ent;
7870 + struct osf_finger *f = NULL;
7876 + read_lock_bh(&osf_lock);
7877 + list_for_each(ent, &finger_list)
7879 + f = list_entry(ent, struct osf_finger, flist);
7881 + log("%s [%s]", f->genre, f->details);
7883 + count += sprintf(buf+count, "%s - %s[%s] : %s",
7884 + f->genre, f->version,
7885 + f->subtype, f->details);
7890 + //count += sprintf(buf+count, " OPT: ");
7891 + for (i=0; i<f->opt_num; ++i)
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);
7900 + count += sprintf(buf+count, "\n");
7902 + read_unlock_bh(&osf_lock);
7907 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
7911 + char obuf[MAXOPTSTRLEN];
7912 + struct osf_finger *finger;
7913 + struct list_head *ent, *n;
7915 + char *pbeg, *pend;
7917 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
7920 + write_lock_bh(&osf_lock);
7921 + list_for_each_safe(ent, n, &finger_list)
7924 + finger = list_entry(ent, struct osf_finger, flist);
7925 + list_del(&finger->flist);
7926 + finger_free(finger);
7928 + write_unlock_bh(&osf_lock);
7930 + log("Flushed %d entries.\n", i);
7937 + for (i=0; i<count && buffer[i] != '\0'; ++i)
7938 + if (buffer[i] == ':')
7941 + if (cnt != 8 || i != count)
7943 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
7948 + memset(obuf, 0, sizeof(obuf));
7950 + finger = finger_alloc();
7953 + log("Failed to allocate new fingerprint entry.\n");
7957 + pbeg = (char *)buffer;
7958 + pend = osf_strchr(pbeg, OSFPDEL);
7962 + if (pbeg[0] == 'S')
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;
7970 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
7972 + else if (pbeg[0] == 'T')
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;
7980 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
7982 + if (isdigit(pbeg[0]))
7984 + finger->wss.wc = 0;
7985 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
7990 + pend = osf_strchr(pbeg, OSFPDEL);
7994 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
7997 + pend = osf_strchr(pbeg, OSFPDEL);
8001 + finger->df = simple_strtoul(pbeg, NULL, 10);
8004 + pend = osf_strchr(pbeg, OSFPDEL);
8008 + finger->ss = simple_strtoul(pbeg, NULL, 10);
8012 + pend = osf_strchr(pbeg, OSFPDEL);
8016 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
8020 + pend = osf_strchr(pbeg, OSFPDEL);
8024 + if (pbeg[0] == '@' || pbeg[0] == '*')
8025 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
8027 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
8031 + pend = osf_strchr(pbeg, OSFPDEL);
8035 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
8039 + pend = osf_strchr(pbeg, OSFPDEL);
8043 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
8047 + cnt = snprintf(finger->details,
8048 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
8051 + log("%s - %s[%s] : %s\n",
8052 + finger->genre, finger->version,
8053 + finger->subtype, finger->details);
8055 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
8058 + write_lock_bh(&osf_lock);
8059 + list_add_tail(&finger->flist, &finger_list);
8060 + write_unlock_bh(&osf_lock);
8065 +static int __init osf_init(void)
8068 + struct proc_dir_entry *p;
8070 + log("Startng OS fingerprint matching module.\n");
8072 + INIT_LIST_HEAD(&finger_list);
8074 + err = ipt_register_match(&osf_match);
8077 + log("Failed to register OS fingerprint matching module.\n");
8081 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
8084 + ipt_unregister_match(&osf_match);
8088 + p->write_proc = osf_proc_write;
8089 + p->read_proc = osf_proc_read;
8094 +static void __exit osf_fini(void)
8096 + struct list_head *ent, *n;
8097 + struct osf_finger *f;
8099 + remove_proc_entry("sys/net/ipv4/osf", NULL);
8100 + ipt_unregister_match(&osf_match);
8102 + list_for_each_safe(ent, n, &finger_list)
8104 + f = list_entry(ent, struct osf_finger, flist);
8105 + list_del(&f->flist);
8109 + log("OS fingerprint matching module finished.\n");
8112 +module_init(osf_init);
8113 +module_exit(osf_fini);
8115 +MODULE_LICENSE("GPL");
8116 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
8117 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
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
8123 +/* Kernel module to match an IP address pool. */
8125 +#include <linux/module.h>
8126 +#include <linux/ip.h>
8127 +#include <linux/skbuff.h>
8129 +#include <linux/netfilter_ipv4/ip_tables.h>
8130 +#include <linux/netfilter_ipv4/ip_pool.h>
8131 +#include <linux/netfilter_ipv4/ipt_pool.h>
8133 +static inline int match_pool(
8138 + if (ip_pool_match(index, ntohl(addr)))
8144 + const struct sk_buff *skb,
8145 + const struct net_device *in,
8146 + const struct net_device *out,
8147 + const void *matchinfo,
8150 + u_int16_t datalen,
8153 + const struct ipt_pool_info *info = matchinfo;
8154 + const struct iphdr *iph = skb->nh.iph;
8156 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
8157 + info->flags&IPT_POOL_INV_SRC))
8160 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
8161 + info->flags&IPT_POOL_INV_DST))
8167 +static int checkentry(
8168 + const char *tablename,
8169 + const struct ipt_ip *ip,
8171 + unsigned int matchsize,
8172 + unsigned int hook_mask
8174 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
8179 +static struct ipt_match pool_match
8180 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
8182 +static int __init init(void)
8184 + return ipt_register_match(&pool_match);
8187 +static void __exit fini(void)
8189 + ipt_unregister_match(&pool_match);
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
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.
8203 + Copyright (C) 2000,2001 astaro AG
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
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
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>
8225 +#define DEBUGP printk
8227 +#define DEBUGP(format, args...)
8230 +MODULE_LICENSE("GPL");
8231 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
8233 +#define HF_DADDR_CHANGING 0x01
8234 +#define HF_SPORT_CHANGING 0x02
8235 +#define HF_TOS_CHANGING 0x04
8236 +#define HF_TTL_CHANGING 0x08
8239 + * Information we keep per each target 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 */
8249 + * Information we keep per each source address.
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 */
8266 + * State information.
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 */
8276 + * Convert an IP address into a hash table index.
8278 +static inline int hashfunc(struct in_addr addr)
8280 + unsigned int value;
8283 + value = addr.s_addr;
8287 + } while ((value >>= HASH_LOG));
8289 + return hash & (HASH_SIZE - 1);
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,
8299 + u_int16_t datalen,
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;
8308 + struct host *curr, *last, **head;
8309 + int hash, index, count;
8311 + /* Parameters from userspace */
8312 + const struct ipt_psd_info *psdinfo = matchinfo;
8315 + ip_hdr = pskb->nh.iph;
8317 + /* Sanity check */
8318 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
8319 + DEBUGP("PSD: sanity check failed\n");
8323 + /* TCP or UDP ? */
8324 + proto = ip_hdr->protocol;
8326 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
8327 + DEBUGP("PSD: protocol not supported\n");
8331 + /* Get the source address, source & destination ports, and TCP flags */
8333 + addr.s_addr = ip_hdr->saddr;
8335 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
8337 + /* Yep, it´s dirty */
8338 + src_port = tcp_hdr->source;
8339 + dest_port = tcp_hdr->dest;
8341 + if (proto == IPPROTO_TCP) {
8342 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
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");
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. */
8359 + spin_lock(&state.lock);
8361 + /* Do we know this source address already? */
8364 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
8366 + if (curr->src_addr.s_addr == addr.s_addr) break;
8368 + if (curr->next) last = curr;
8369 + } while ((curr = curr->next));
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)) {
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;
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;
8391 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
8392 + curr->timestamp = now;
8394 + /* Logged this scan already? Then drop the packet. */
8395 + if (curr->weight >= psdinfo->weight_threshold)
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;
8408 + /* Update the total weight */
8409 + curr->weight += (ntohs(dest_port) < 1024) ?
8410 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
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)
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;
8426 + goto out_no_match;
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;
8434 + last->next = last->next->next;
8436 + *head = (*head)->next;
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;
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;
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). */
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)];
8459 + if ((curr = *head))
8461 + if (curr == &state.list[state.index]) break;
8463 + } while ((curr = curr->next));
8465 + /* Then, remove it */
8468 + last->next = last->next->next;
8470 + *head = (*head)->next;
8473 + /* Get our list entry */
8474 + curr = &state.list[state.index++];
8475 + if (state.index >= LIST_SIZE) state.index = 0;
8477 + /* Link it into the hash table */
8478 + head = &state.hash[hash];
8479 + curr->next = *head;
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;
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;
8498 + spin_unlock(&state.lock);
8502 + spin_unlock(&state.lock);
8506 +static int ipt_psd_checkentry(const char *tablename,
8507 + const struct ipt_ip *e,
8509 + unsigned int matchsize,
8510 + unsigned int hook_mask)
8512 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
8514 + /* we accept TCP only */
8515 +/* if (e->ip.proto != IPPROTO_TCP) { */
8516 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
8520 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
8521 + DEBUGP("PSD: matchsize %u != %u\n",
8523 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
8530 +static struct ipt_match ipt_psd_reg = {
8534 + ipt_psd_checkentry,
8538 +static int __init init(void)
8540 + if (ipt_register_match(&ipt_psd_reg))
8543 + memset(&state, 0, sizeof(state));
8545 + spin_lock_init(&(state.lock));
8547 + printk("netfilter PSD loaded - (c) astaro AG\n");
8551 +static void __exit fini(void)
8553 + ipt_unregister_match(&ipt_psd_reg);
8554 + printk("netfilter PSD unloaded - (c) astaro AG\n");
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
8564 + * netfilter module to enforce network quotas
8566 + * Sam Johnston <samj@samj.net>
8568 +#include <linux/module.h>
8569 +#include <linux/skbuff.h>
8570 +#include <linux/spinlock.h>
8571 +#include <linux/interrupt.h>
8573 +#include <linux/netfilter_ipv4/ip_tables.h>
8574 +#include <linux/netfilter_ipv4/ipt_quota.h>
8576 +MODULE_LICENSE("GPL");
8578 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
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)
8588 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
8590 + spin_lock_bh("a_lock);
8592 + if (q->quota >= datalen) {
8593 + /* we can afford this one */
8594 + q->quota -= datalen;
8595 + spin_unlock_bh("a_lock);
8597 +#ifdef DEBUG_IPT_QUOTA
8598 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
8603 + /* so we do not allow even small packets from now on */
8606 +#ifdef DEBUG_IPT_QUOTA
8607 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
8610 + spin_unlock_bh("a_lock);
8615 +checkentry(const char *tablename,
8616 + const struct ipt_ip *ip,
8617 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
8619 + /* TODO: spinlocks? sanity checks? */
8620 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
8626 +static struct ipt_match quota_match
8627 + = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
8632 + return ipt_register_match("a_match);
8638 + ipt_unregister_match("a_match);
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
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
8654 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
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>
8666 +MODULE_LICENSE("GPL");
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,
8675 + u_int16_t datalen,
8678 + /* Parameters from userspace */
8679 + const struct ipt_rand_info *info = matchinfo;
8680 + u_int8_t random_number;
8682 + /* get 1 random number from the kernel random number generation routine */
8683 + get_random_bytes((void *)(&random_number), 1);
8685 + /* Do we match ? */
8686 + if (random_number <= info->average)
8693 +ipt_rand_checkentry(const char *tablename,
8694 + const struct ipt_ip *e,
8696 + unsigned int matchsize,
8697 + unsigned int hook_mask)
8699 + /* Parameters from userspace */
8700 + const struct ipt_rand_info *info = matchinfo;
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)));
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);
8719 +static struct ipt_match ipt_rand_reg = {
8723 + ipt_rand_checkentry,
8727 +static int __init init(void)
8729 + if (ipt_register_match(&ipt_rand_reg))
8732 + printk("ipt_random match loaded\n");
8736 +static void __exit fini(void)
8738 + ipt_unregister_match(&ipt_rand_reg);
8739 + printk("ipt_random match unloaded\n");
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
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>
8754 +#include <linux/netfilter_ipv4/ipt_realm.h>
8755 +#include <linux/netfilter_ipv4/ip_tables.h>
8757 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
8758 +MODULE_LICENSE("GPL");
8761 +match(const struct sk_buff *skb,
8762 + const struct net_device *in,
8763 + const struct net_device *out,
8764 + const void *matchinfo,
8767 + u_int16_t datalen,
8770 + const struct ipt_realm_info *info = matchinfo;
8771 + struct dst_entry *dst = skb->dst;
8776 + id = dst->tclassid;
8778 + return (info->id == (id & info->mask)) ^ info->invert;
8781 +static int check(const char *tablename,
8782 + const struct ipt_ip *ip,
8784 + unsigned int matchsize,
8785 + unsigned int 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");
8795 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
8801 +static struct ipt_match realm_match
8802 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
8804 +static int __init init(void)
8806 + return ipt_register_match(&realm_match);
8809 +static void __exit fini(void)
8811 + ipt_unregister_match(&realm_match);
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
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.
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>
8840 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
8841 +MODULE_DESCRIPTION("Match arrival timestamp");
8842 +MODULE_LICENSE("GPL");
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]*/
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 */
8861 +localtime(const time_t *timepr, struct tm *r);
8864 +match(const struct sk_buff *skb,
8865 + const struct net_device *in,
8866 + const struct net_device *out,
8867 + const void *matchinfo,
8870 + u_int16_t datalen,
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;
8880 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
8881 + if (info->kerneltime)
8883 + do_gettimeofday(&kerneltimeval);
8884 + packet_local_time = kerneltimeval.tv_sec;
8887 + packet_local_time = skb->stamp.tv_sec;
8889 + /* Transform the timestamp of the packet, in a human readable form */
8890 + localtime(&packet_local_time, ¤ttime);
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 */
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))
8901 + /* here we match ! */
8906 +checkentry(const char *tablename,
8907 + const struct ipt_ip *ip,
8909 + unsigned int matchsize,
8910 + unsigned int hook_mask)
8912 + struct ipt_time_info *info = matchinfo; /* match info for rule */
8914 + /* First, check that we are in the correct hook */
8915 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
8917 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
8919 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
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;
8928 + /* Check the size */
8929 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
8931 + /* Now check the coherence of the data ... */
8932 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
8933 + (info->time_stop > 1439))
8935 + printk(KERN_WARNING "ipt_time: invalid argument\n");
8942 +static struct ipt_match time_match
8943 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
8945 +static int __init init(void)
8947 + printk("ipt_time loading\n");
8948 + return ipt_register_match(&time_match);
8951 +static void __exit fini(void)
8953 + ipt_unregister_match(&time_match);
8954 + printk("ipt_time unloaded\n");
8961 +/* The part below is borowed and modified from dietlibc */
8963 +/* seconds per day */
8964 +#define SPD 24*60*60
8967 +localtime(const time_t *timepr, struct tm *r) {
8970 + extern struct timezone sys_tz;
8971 + const unsigned int __spm[12] =
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),
8985 + register time_t work;
8987 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
8989 + r->tm_sec=work%60; work/=60;
8990 + r->tm_min=work%60; r->tm_hour=work/60;
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;
9000 + r->tm_year=i-1900;
9001 + for (i=11; i && __spm[i]>work; --i) ;
9003 + r->tm_mday=work-__spm[i]+1;
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
9009 +/* Kernel module to match u32 packet content. */
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.
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 := & | << | >> | @
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.
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
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
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.
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.
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"
9060 + AND that with FFFF (giving bytes 2-3),
9061 + and test whether that's in the range [0x100:0xFFFF]
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
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.
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
9111 +#include <linux/module.h>
9112 +#include <linux/skbuff.h>
9114 +#include <linux/netfilter_ipv4/ipt_u32.h>
9115 +#include <linux/netfilter_ipv4/ip_tables.h>
9117 +/* #include <asm-i386/timex.h> for timing */
9119 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
9120 +MODULE_DESCRIPTION("IP tables u32 matching module");
9121 +MODULE_LICENSE("GPL");
9124 +match(const struct sk_buff *skb,
9125 + const struct net_device *in,
9126 + const struct net_device *out,
9127 + const void *matchinfo,
9130 + u_int16_t datalen,
9133 + const struct ipt_u32 *data = matchinfo;
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;
9140 + u_int32_t pos, val;
9141 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
9142 + cycles1 = get_cycles(); */
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)
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) {
9156 + val = val & number;
9158 + case IPT_U32_LEFTSH:
9159 + val = val << number;
9161 + case IPT_U32_RIGHTSH:
9162 + val = val >> number;
9165 + base = base + val;
9167 + if (base+pos+3 > end || base+pos < head)
9169 + val = (base[pos]<<24) + (base[pos+1]<<16) +
9170 + (base[pos+2]<<8) + base[pos+3];
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)) {
9181 + if (i >= data->tests[testind].nvalues) {
9182 + /* cycles2 = get_cycles();
9183 + printk("failed %d in %d cycles\n", testind,
9184 + cycles2-cycles1); */
9188 + /* cycles2 = get_cycles();
9189 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
9194 +checkentry(const char *tablename,
9195 + const struct ipt_ip *ip,
9197 + unsigned int matchsize,
9198 + unsigned int hook_mask)
9200 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
9205 +static struct ipt_match u32_match
9206 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
9208 +static int __init init(void)
9210 + return ipt_register_match(&u32_match);
9213 +static void __exit fini(void)
9215 + ipt_unregister_match(&u32_match);
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.
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
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.
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
9239 +config IP6_NF_TARGET_REJECT
9240 + tristate 'REJECT target support'
9241 + depends on IP6_NF_FILTER
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)
9247 +config IP6_NF_MATCH_FUZZY
9248 + tristate 'Fuzzy match support'
9249 + depends on IP6_NF_FILTER
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)
9254 +config IP6_NF_MATCH_NTH
9255 + tristate 'Nth match support'
9256 + depends on IP6_NF_IPTABLES
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
9262 + This match functions in one of two ways
9263 + 1) Match ever Nth packet, and only the Nth packet.
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.
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
9279 + By using the mangle table and iproute2, you can setup complex
9280 + load-balanced routing. There's lot of other uses. Be creative!
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
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.
9294 +config IP6_NF_MATCH_RANDOM
9295 + tristate 'Random match support'
9296 + depends on IP6_NF_IPTABLES
9298 + This option adds a `random' match,
9299 + which allow you to match packets randomly
9300 + following a given probability.
9302 + Suppported options are:
9304 + [--average] percent will match randomly packets with a probability of
9305 + 'percent'. default is 50%
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
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
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
9328 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
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
9338 + * Hop Limit modification target for ip6tables
9339 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
9340 + * Based on HW's TTL module
9342 + * This software is distributed under the terms of GNU GPL
9345 +#include <linux/module.h>
9346 +#include <linux/skbuff.h>
9347 +#include <linux/ip.h>
9349 +#include <linux/netfilter_ipv6/ip6_tables.h>
9350 +#include <linux/netfilter_ipv6/ip6t_HL.h>
9352 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
9353 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
9354 +MODULE_LICENSE("GPL");
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)
9360 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
9361 + const struct ip6t_HL_info *info = targinfo;
9362 + u_int16_t diffs[2];
9365 + switch (info->mode) {
9367 + new_hl = info->hop_limit;
9370 + new_hl = ip6h->hop_limit + info->hop_limit;
9375 + new_hl = ip6h->hop_limit + info->hop_limit;
9380 + new_hl = ip6h->hop_limit;
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);
9390 + return IP6T_CONTINUE;
9393 +static int ip6t_hl_checkentry(const char *tablename,
9394 + const struct ip6t_entry *e,
9396 + unsigned int targinfosize,
9397 + unsigned int hook_mask)
9399 + struct ip6t_HL_info *info = targinfo;
9401 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
9402 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
9404 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
9408 + if (strcmp(tablename, "mangle")) {
9409 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9413 + if (info->mode > IP6T_HL_MAXMODE) {
9414 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
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");
9427 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
9428 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
9430 +static int __init init(void)
9432 + return ip6t_register_target(&ip6t_HL);
9435 +static void __exit fini(void)
9437 + ip6t_unregister_target(&ip6t_HL);
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
9447 + * This is a module which is used for rejecting packets.
9448 + * Added support for customized reject packets (Jozsef Kadlecsik).
9450 + * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
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>
9461 +#define DEBUGP printk
9463 +#define DEBUGP(format, args...)
9467 +/* Send RST reply */
9468 +static void send_reset(struct sk_buff *oldskb)
9470 + struct sk_buff *nskb;
9471 + struct tcphdr *otcph, *tcph;
9472 + struct rtable *rt;
9473 + unsigned int otcplen;
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))
9481 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
9482 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
9484 + /* No RST for RST. */
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)
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);
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;
9509 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
9511 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
9512 + tcph->source = xchg(&tcph->dest, tcph->source);
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);
9521 + tcph->seq = otcph->ack_seq;
9522 + tcph->ack_seq = 0;
9525 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
9526 + + otcplen - (otcph->doff<<2));
9531 + ((u_int8_t *)tcph)[13] = 0;
9533 + tcph->ack = needs_ack;
9536 + tcph->urg_ptr = 0;
9538 + /* Adjust TCP checksum */
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));
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;
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);
9558 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
9559 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
9563 + dst_release(nskb->dst);
9564 + nskb->dst = &rt->u.dst;
9566 + /* "Never happens" */
9567 + if (nskb->len > nskb->dst->pmtu)
9570 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
9571 + ip_finish_output);
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,
9586 + const struct ip6t_reject_info *reject = targinfo;
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);
9596 + case IP6T_ICMP6_ADM_PROHIBITED:
9597 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
9599 + case IP6T_ICMP6_NOT_NEIGHBOUR:
9600 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
9602 + case IP6T_ICMP6_ADDR_UNREACH:
9603 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
9605 + case IP6T_ICMP6_PORT_UNREACH:
9606 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
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;
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
9620 + struct icmp_bxm icmp_param;
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);
9630 + case IPT_TCP_RESET:
9631 + send_reset(*pskb);
9635 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
9642 +static inline int find_ping_match(const struct ip6t_entry_match *m)
9644 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
9646 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
9647 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
9648 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
9654 +static int check(const char *tablename,
9655 + const struct ip6t_entry *e,
9657 + unsigned int targinfosize,
9658 + unsigned int hook_mask)
9660 + const struct ip6t_reject_info *rejinfo = targinfo;
9662 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
9663 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
9667 + /* Only allow these for packet filtering. */
9668 + if (strcmp(tablename, "filter") != 0) {
9669 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
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);
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");
9686 + /* Must contain ICMP match. */
9687 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
9688 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
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");
9703 +static struct ip6t_target ip6t_reject_reg
9704 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
9706 +static int __init init(void)
9708 + if (ip6t_register_target(&ip6t_reject_reg))
9713 +static void __exit fini(void)
9715 + ip6t_unregister_target(&ip6t_reject_reg);
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
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 .
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
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>
9753 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
9754 + Expressed in percentage
9757 +#define PAR_LOW 1/100
9760 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
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");
9766 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
9768 + if (tx >= maxi) return 100;
9770 + if (tx <= mini) return 0;
9772 + return ((100 * (tx-mini)) / (maxi-mini));
9775 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
9777 + if (tx <= mini) return 100;
9779 + if (tx >= maxi) return 0;
9781 + return ((100 * (maxi - tx)) / (maxi - mini));
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,
9792 + u_int16_t datalen,
9795 + /* From userspace */
9797 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
9799 + u_int8_t random_number;
9800 + unsigned long amount;
9801 + u_int8_t howhigh, howlow;
9804 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
9806 + info->bytes_total += pskb->len;
9807 + info->packets_total++;
9809 + info->present_time = jiffies;
9811 + if (info->present_time >= info->previous_time)
9812 + amount = info->present_time - info->previous_time;
9814 + /* There was a transition : I choose to re-sample
9815 + and keep the old acceptance rate...
9819 + info->previous_time = info->present_time;
9820 + info->bytes_total = info->packets_total = 0;
9823 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
9825 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
9828 + info->previous_time = info->present_time;
9829 + info->bytes_total = info->packets_total = 0;
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);
9834 + info->acceptance_rate = (u_int8_t) \
9835 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
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,
9847 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
9850 + if (info->acceptance_rate < 100)
9852 + get_random_bytes((void *)(&random_number), 1);
9854 + /* If within the acceptance , it can pass => don't match */
9855 + if (random_number <= (255 * info->acceptance_rate) / 100)
9858 + return 1; /* It can't pass (It matches) */
9861 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
9866 +ip6t_fuzzy_checkentry(const char *tablename,
9867 + const struct ip6t_ip6 *ip,
9869 + unsigned int matchsize,
9870 + unsigned int hook_mask)
9873 + const struct ip6t_fuzzy_info *info = matchinfo;
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)));
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");
9890 +static struct ip6t_match ip6t_fuzzy_reg = {
9894 + ip6t_fuzzy_checkentry,
9898 +static int __init init(void)
9900 + if (ip6t_register_match(&ip6t_fuzzy_reg))
9906 +static void __exit fini(void)
9908 + ip6t_unregister_match(&ip6t_fuzzy_reg);
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
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
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
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>
9940 +MODULE_LICENSE("GPL");
9943 + * State information.
9950 +static struct state states[IP6T_NTH_NUM_COUNTERS];
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,
9959 + u_int16_t datalen,
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))
9967 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
9971 + spin_lock(&states[counter].lock);
9973 + /* Are we matching every nth packet?*/
9974 + if (info->packet == 0xFF)
9976 + /* We're matching every nth packet and only every nth packet*/
9977 + /* Do we match or invert match? */
9978 + if (info->not == 0)
9980 + if (states[counter].number == 0)
9982 + ++states[counter].number;
9985 + if (states[counter].number >= info->every)
9986 + states[counter].number = 0; /* reset the counter */
9988 + ++states[counter].number;
9993 + if (states[counter].number == 0)
9995 + ++states[counter].number;
9998 + if (states[counter].number >= info->every)
9999 + states[counter].number = 0;
10001 + ++states[counter].number;
10007 + /* We're using the --packet, so there must be a rule for every value */
10008 + if (states[counter].number == info->packet)
10010 + /* only increment the counter when a match happens */
10011 + if (states[counter].number >= info->every)
10012 + states[counter].number = 0; /* reset the counter */
10014 + ++states[counter].number;
10022 + /* don't match */
10023 + spin_unlock(&states[counter].lock);
10027 + spin_unlock(&states[counter].lock);
10032 +ip6t_nth_checkentry(const char *tablename,
10033 + const struct ip6t_ip6 *e,
10035 + unsigned int matchsize,
10036 + unsigned int hook_mask)
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))
10043 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
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)));
10053 + states[counter].number = info->startat;
10058 +static struct ip6t_match ip6t_nth_reg = {
10062 + ip6t_nth_checkentry,
10066 +static int __init init(void)
10068 + unsigned counter;
10069 + memset(&states, 0, sizeof(states));
10070 + if (ip6t_register_match(&ip6t_nth_reg))
10073 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
10075 + spin_lock_init(&(states[counter].lock));
10078 + printk("ip6t_nth match loaded\n");
10082 +static void __exit fini(void)
10084 + ip6t_unregister_match(&ip6t_nth_reg);
10085 + printk("ip6t_nth match unloaded\n");
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
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
10100 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
10101 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
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>
10113 +MODULE_LICENSE("GPL");
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,
10122 + u_int16_t datalen,
10125 + /* Parameters from userspace */
10126 + const struct ip6t_rand_info *info = matchinfo;
10127 + u_int8_t random_number;
10129 + /* get 1 random number from the kernel random number generation routine */
10130 + get_random_bytes((void *)(&random_number), 1);
10132 + /* Do we match ? */
10133 + if (random_number <= info->average)
10140 +ip6t_rand_checkentry(const char *tablename,
10141 + const struct ip6t_ip6 *e,
10143 + unsigned int matchsize,
10144 + unsigned int hook_mask)
10146 + /* Parameters from userspace */
10147 + const struct ip6t_rand_info *info = matchinfo;
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)));
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);
10166 +static struct ip6t_match ip6t_rand_reg = {
10170 + ip6t_rand_checkentry,
10174 +static int __init init(void)
10176 + if (ip6t_register_match(&ip6t_rand_reg))
10179 + printk("ip6t_random match loaded\n");
10183 +static void __exit fini(void)
10185 + ip6t_unregister_match(&ip6t_rand_reg);
10186 + printk("ip6t_random match unloaded\n");
10189 +module_init(init);
10190 +module_exit(fini);