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
1995 obj-$(CONFIG_IP_NF_COMPAT_IPFWADM) += ipfwadm.o
1997 obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
1999 +obj-$(CONFIG_IP_NF_SET) += ipt_set.o ipt_SET.o ip_set.o
2000 +obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o
2001 +obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
2002 +obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
2003 +obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
2005 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.3/net/ipv4/netfilter/ip_pool.c
2006 --- linux-2.6.3.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
2007 +++ linux-2.6.3/net/ipv4/netfilter/ip_pool.c 2004-02-19 09:08:42.247779733 +0100
2009 +/* Kernel module for IP pool management */
2011 +#include <linux/module.h>
2012 +#include <linux/ip.h>
2013 +#include <linux/skbuff.h>
2014 +#include <linux/netfilter_ipv4/ip_tables.h>
2015 +#include <linux/netfilter_ipv4/ip_pool.h>
2016 +#include <linux/errno.h>
2017 +#include <asm/uaccess.h>
2018 +#include <asm/bitops.h>
2019 +#include <linux/interrupt.h>
2020 +#include <linux/spinlock.h>
2025 +#define DP(format, args...)
2028 +MODULE_LICENSE("GPL");
2031 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
2034 + u_int32_t first_ip; /* host byte order, included in range */
2035 + u_int32_t last_ip; /* host byte order, included in range */
2036 + void *members; /* the bitmap proper */
2037 + int nr_use; /* total nr. of tests through this */
2038 + int nr_match; /* total nr. of matches through this */
2042 +static struct ip_pool *POOL;
2044 +static inline struct ip_pool *lookup(ip_pool_t index)
2046 + if (index < 0 || index >= nr_pool) {
2047 + DP("ip_pool:lookup: bad index %d\n", index);
2050 + return POOL+index;
2053 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
2055 + struct ip_pool *pool = lookup(index);
2058 + if (!pool || !pool->members)
2060 + read_lock_bh(&pool->lock);
2061 + if (pool->members) {
2062 + if (addr >= pool->first_ip && addr <= pool->last_ip) {
2063 + addr -= pool->first_ip;
2064 + if (test_bit(addr, pool->members)) {
2066 +#ifdef CONFIG_IP_POOL_STATISTICS
2071 +#ifdef CONFIG_IP_POOL_STATISTICS
2075 + read_unlock_bh(&pool->lock);
2078 +EXPORT_SYMBOL(ip_pool_match);
2080 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
2082 + struct ip_pool *pool;
2085 + pool = lookup(index);
2086 + if ( !pool || !pool->members
2087 + || addr < pool->first_ip || addr > pool->last_ip)
2089 + read_lock_bh(&pool->lock);
2090 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
2091 + addr -= pool->first_ip;
2093 + ? (0 != test_and_clear_bit(addr, pool->members))
2094 + : (0 != test_and_set_bit(addr, pool->members));
2096 + read_unlock_bh(&pool->lock);
2100 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
2102 + int res = pool_change(index,addr,isdel);
2104 + if (!isdel) res = !res;
2107 +EXPORT_SYMBOL(ip_pool_mod);
2109 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
2111 + return 4*((((b-a+8)/8)+3)/4);
2114 +static inline int poolbytes(ip_pool_t index)
2116 + struct ip_pool *pool = lookup(index);
2118 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
2121 +static int setpool(
2127 + struct ip_pool_request req;
2129 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
2130 + if (!capable(CAP_NET_ADMIN))
2132 + if (optval != SO_IP_POOL)
2134 + if (len != sizeof(req))
2136 + if (copy_from_user(&req, user, sizeof(req)) != 0)
2138 + printk("obsolete op - upgrade your ippool(8) utility.\n");
2142 +static int getpool(
2148 + struct ip_pool_request req;
2149 + struct ip_pool *pool;
2155 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
2156 + if (!capable(CAP_NET_ADMIN))
2158 + if (optval != SO_IP_POOL)
2160 + if (*len != sizeof(req)) {
2163 + if (copy_from_user(&req, user, sizeof(req)) != 0)
2165 + DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
2166 + if (req.op < IP_POOL_BAD001) {
2167 + printk("obsolete op - upgrade your ippool(8) utility.\n");
2171 + case IP_POOL_HIGH_NR:
2172 + DP("ip_pool HIGH_NR\n");
2173 + req.index = IP_POOL_NONE;
2174 + for (i=0; i<nr_pool; i++)
2175 + if (POOL[i].members)
2177 + return copy_to_user(user, &req, sizeof(req));
2178 + case IP_POOL_LOOKUP:
2179 + DP("ip_pool LOOKUP\n");
2180 + pool = lookup(req.index);
2183 + if (!pool->members)
2185 + req.addr = htonl(pool->first_ip);
2186 + req.addr2 = htonl(pool->last_ip);
2187 + return copy_to_user(user, &req, sizeof(req));
2188 + case IP_POOL_USAGE:
2189 + DP("ip_pool USE\n");
2190 + pool = lookup(req.index);
2193 + if (!pool->members)
2195 + req.addr = pool->nr_use;
2196 + req.addr2 = pool->nr_match;
2197 + return copy_to_user(user, &req, sizeof(req));
2198 + case IP_POOL_TEST_ADDR:
2199 + DP("ip_pool TEST 0x%08x\n", req.addr);
2200 + pool = lookup(req.index);
2204 + read_lock_bh(&pool->lock);
2205 + if (!pool->members) {
2206 + DP("ip_pool TEST_ADDR no members in pool\n");
2208 + goto unlock_and_return_res;
2210 + req.addr = ntohl(req.addr);
2211 + if (req.addr < pool->first_ip) {
2212 + DP("ip_pool TEST_ADDR address < pool bounds\n");
2214 + goto unlock_and_return_res;
2216 + if (req.addr > pool->last_ip) {
2217 + DP("ip_pool TEST_ADDR address > pool bounds\n");
2219 + goto unlock_and_return_res;
2221 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
2223 + read_unlock_bh(&pool->lock);
2224 + return copy_to_user(user, &req, sizeof(req));
2225 + case IP_POOL_FLUSH:
2226 + DP("ip_pool FLUSH not yet implemented.\n");
2228 + case IP_POOL_DESTROY:
2229 + DP("ip_pool DESTROY not yet implemented.\n");
2231 + case IP_POOL_INIT:
2232 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
2233 + pool = lookup(req.index);
2236 + req.addr = ntohl(req.addr);
2237 + req.addr2 = ntohl(req.addr2);
2238 + if (req.addr > req.addr2) {
2239 + DP("ip_pool INIT bad ip range\n");
2242 + newbytes = bitmap_bytes(req.addr, req.addr2);
2243 + newmembers = kmalloc(newbytes, GFP_KERNEL);
2244 + if (!newmembers) {
2245 + DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
2248 + memset(newmembers, 0, newbytes);
2249 + write_lock_bh(&pool->lock);
2250 + if (pool->members) {
2251 + DP("ip_pool INIT pool %d exists\n", req.index);
2252 + kfree(newmembers);
2254 + goto unlock_and_return_res;
2256 + pool->first_ip = req.addr;
2257 + pool->last_ip = req.addr2;
2259 + pool->nr_match = 0;
2260 + pool->members = newmembers;
2261 + write_unlock_bh(&pool->lock);
2263 + case IP_POOL_ADD_ADDR:
2264 + DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
2265 + req.addr = pool_change(req.index, ntohl(req.addr), 0);
2266 + return copy_to_user(user, &req, sizeof(req));
2267 + case IP_POOL_DEL_ADDR:
2268 + DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
2269 + req.addr = pool_change(req.index, ntohl(req.addr), 1);
2270 + return copy_to_user(user, &req, sizeof(req));
2272 + DP("ip_pool:getpool bad op %d\n", req.op);
2277 +unlock_and_return_res:
2279 + read_unlock_bh(&pool->lock);
2283 +static struct nf_sockopt_ops so_pool
2284 += { { NULL, NULL }, PF_INET,
2285 + SO_IP_POOL, SO_IP_POOL+1, &setpool,
2286 + SO_IP_POOL, SO_IP_POOL+1, &getpool,
2289 +MODULE_PARM(nr_pool, "i");
2291 +static int __init init(void)
2296 + if (nr_pool < 1) {
2297 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
2300 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
2302 + printk("ip_pool module init: out of memory for nr_pool %d\n",
2306 + for (i=0; i<nr_pool; i++) {
2307 + POOL[i].first_ip = 0;
2308 + POOL[i].last_ip = 0;
2309 + POOL[i].members = 0;
2310 + POOL[i].nr_use = 0;
2311 + POOL[i].nr_match = 0;
2312 + POOL[i].lock = RW_LOCK_UNLOCKED;
2314 + res = nf_register_sockopt(&so_pool);
2315 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
2323 +static void __exit fini(void)
2327 + DP("ip_pool:fini BYEBYE\n");
2328 + nf_unregister_sockopt(&so_pool);
2329 + for (i=0; i<nr_pool; i++) {
2330 + if (POOL[i].members) {
2331 + kfree(POOL[i].members);
2332 + POOL[i].members = 0;
2337 + DP("ip_pool:fini these are the famous last words\n");
2343 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set.c linux-2.6.3/net/ipv4/netfilter/ip_set.c
2344 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
2345 +++ linux-2.6.3/net/ipv4/netfilter/ip_set.c 2004-02-09 15:02:00.000000000 +0100
2347 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
2348 + * Patrick Schaaf (bof@bof.de)
2349 + * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2351 + * This program is free software; you can redistribute it and/or modify
2352 + * it under the terms of the GNU General Public License as published by
2353 + * the Free Software Foundation; either version 2 of the License, or
2354 + * (at your option) any later version.
2356 + * This program is distributed in the hope that it will be useful,
2357 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2358 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2359 + * GNU General Public License for more details.
2361 + * You should have received a copy of the GNU General Public License
2362 + * along with this program; if not, write to the Free Software
2363 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2366 +/* Kernel module for IP set management */
2368 +#include <linux/config.h>
2369 +#include <linux/module.h>
2370 +#include <linux/ip.h>
2371 +#include <linux/skbuff.h>
2372 +#include <linux/netfilter_ipv4/ip_tables.h>
2373 +#include <linux/errno.h>
2374 +#include <asm/uaccess.h>
2375 +#include <asm/bitops.h>
2376 +#include <asm/softirq.h>
2377 +#include <linux/spinlock.h>
2378 +#include <linux/vmalloc.h>
2380 +#define ASSERT_READ_LOCK(x) /* dont use that */
2381 +#define ASSERT_WRITE_LOCK(x)
2382 +#include <linux/netfilter_ipv4/listhelp.h>
2383 +#include <linux/netfilter_ipv4/ip_set.h>
2385 +static struct list_head set_type_list; /* all registred set types */
2386 +struct ip_set **ip_set_list; /* all individual sets */
2387 +static rwlock_t list_lock = RW_LOCK_UNLOCKED; /* protects both set_type_list and ip_set_list */
2388 +static unsigned int max_sets = 0; /* max number of sets, */
2392 +#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
2393 +#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
2395 +#define __MOD_INC(foo) do { } while (0)
2396 +#define __MOD_DEC(foo) do { } while (0)
2399 +#define NOT_IN_CHILD_SET(fn,args...) \
2401 + || !(*private)->childsets \
2402 + || (set->type[i]->fn(*private,##args) < 0)
2404 +static struct ip_set_private **
2405 +ip_set_find_private(struct ip_set *set,
2406 + struct ip_set_private **private,
2413 + for (i = 0; i < level; i++) {
2414 + if (NOT_IN_CHILD_SET(matchip, ip[i], &id))
2416 + private = &(*private)->childsets[id];
2418 + DP("id: %i private: %p %p", id, private, *private);
2422 +/* Destroy function for the private part of the (child)sets.
2423 + * Must be called without holding any locks.
2426 +ip_set_destroy_private(struct ip_set *set,
2427 + struct ip_set_private **private,
2432 + DP("set %p private %p %p %p", set, private, *private, (*private)->childsets);
2433 + if ((*private)->childsets) {
2434 + for (i = 0; i < set->type[level]->sizeid(*private); i++)
2435 + if ((*private)->childsets[i]) {
2436 + DP("%i -> %p", i, (*private)->childsets[i]);
2437 + ip_set_destroy_private(set,
2438 + &(*private)->childsets[i],
2441 + vfree((*private)->childsets);
2444 + set->type[level]->destroy(private);
2445 + DP("%p %p", private, *private);
2448 +static void ip_set_flush_private(struct ip_set *set,
2449 + struct ip_set_private *private,
2451 + u_int8_t childsets)
2455 + if (childsets && private->childsets)
2456 + for (i = 0; i < set->type[level]->sizeid(private); i++)
2457 + if (private->childsets[i])
2458 + ip_set_flush_private(set,
2459 + private->childsets[i],
2463 + set->type[level]->flush(private);
2467 +/* ip_set_flush() - flush data in a set
2469 +static int ip_set_flush(struct ip_set *set,
2472 + u_int8_t childsets)
2475 + struct ip_set_private **private;
2477 + write_lock_bh(&set->lock);
2478 + if (set->subref) {
2483 + private = ip_set_find_private(set, &set->private, ip, level);
2486 + ip_set_flush_private(set, *private, level, childsets);
2489 + write_unlock_bh(&set->lock);
2494 +ip_set_testip_kernel(struct ip_set *set,
2495 + const struct sk_buff *skb,
2496 + const u_int32_t *flags,
2497 + u_int8_t set_level,
2498 + u_int8_t ip_level)
2500 + struct ip_set_private **private = &set->private;
2504 + read_lock_bh(&set->lock);
2505 + if (set->levels < ip_level || set->subref)
2508 + for (i = 0; i < set_level; i++) {
2509 + if (NOT_IN_CHILD_SET(testip_kernel, skb,
2510 + flags[i] | set->type[i]->typecode, &id))
2512 + DP("id: %i private: %p", id, *private);
2513 + private = &(*private)->childsets[id];
2515 + for (i = set_level; private && *private && i < ip_level; i++) {
2516 + if (set->type[i]->testip_kernel(*private, skb,
2517 + flags[i] | set->type[i]->typecode, &id) <= 0)
2519 + private = (*private)->childsets
2520 + ? &(*private)->childsets[id] : NULL;
2524 + read_unlock_bh(&set->lock);
2529 +ip_set_addip_kernel(struct ip_set *set,
2530 + const struct sk_buff *skb,
2531 + const u_int32_t *flags,
2532 + u_int8_t set_level,
2533 + u_int8_t ip_level)
2535 + struct ip_set_private **private = &set->private;
2539 + write_lock_bh(&set->lock);
2540 + if (set->levels < ip_level || set->subref) {
2541 + write_unlock_bh(&set->lock);
2544 + for (i = 0; i < set_level; i++) {
2545 + if (NOT_IN_CHILD_SET(testip_kernel, skb,
2546 + flags[i] | set->type[i]->typecode, &id)) {
2547 + write_unlock_bh(&set->lock);
2550 + private = &(*private)->childsets[id];
2552 + for (i = set_level; private && *private && i < ip_level; i++) {
2553 + res = set->type[i]->addip_kernel(*private, skb,
2554 + flags[i] | set->type[i]->typecode, &id);
2555 + if (!(res == 0 || res == -EEXIST)) {
2556 + write_unlock_bh(&set->lock);
2559 + private = (*private)->childsets
2560 + ? &(*private)->childsets[id] : NULL;
2562 + write_unlock_bh(&set->lock);
2566 +ip_set_delip_kernel(struct ip_set *set,
2567 + const struct sk_buff *skb,
2568 + const u_int32_t *flags,
2569 + u_int8_t set_level,
2570 + u_int8_t ip_level)
2572 + struct ip_set_private **private = &set->private;
2576 + write_lock_bh(&set->lock);
2577 + if (set->levels < ip_level || set->subref) {
2578 + write_unlock_bh(&set->lock);
2581 + for (i = 0; i < set_level; i++) {
2582 + if (NOT_IN_CHILD_SET(testip_kernel, skb,
2583 + flags[i] | set->type[i]->typecode, &id)) {
2584 + write_unlock_bh(&set->lock);
2587 + private = &(*private)->childsets[id];
2589 + for (i = set_level; private && *private && i < ip_level; i++) {
2590 + res = set->type[i]->delip_kernel(*private, skb,
2591 + flags[i] | set->type[i]->typecode, &id);
2592 + if (!(res == 0 || res == -EEXIST)) {
2593 + write_unlock_bh(&set->lock);
2596 + private = (*private)->childsets
2597 + ? &(*private)->childsets[id] : NULL;
2599 + write_unlock_bh(&set->lock);
2603 +ip_set_addip(struct ip_set *set,
2609 + struct ip_set_private **private;
2613 + DP("%s %i %d", set->name, level, size);
2614 + write_lock_bh(&set->lock);
2615 + if (set->subref) {
2619 + private = ip_set_find_private(set, &set->private, ip, level);
2620 + DP("%s %i %d", set->name, level, size);
2621 + while (level <= set->levels && size) {
2622 + DP("%s %i %d", set->name, level, size);
2623 + if (!(private && *private)) {
2627 + if (size < set->type[level]->reqsize) {
2631 + res = set->type[level]->addip(*private, data,
2632 + set->type[level]->reqsize, &id);
2633 + if (!(res == 0 || res == -EEXIST))
2635 + private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2636 + data += set->type[level]->reqsize;
2637 + size -= set->type[level++]->reqsize;
2642 + write_unlock_bh(&set->lock);
2647 +ip_set_delip(struct ip_set *set,
2653 + struct ip_set_private **private;
2657 + write_lock_bh(&set->lock);
2658 + if (set->subref) {
2662 + private = ip_set_find_private(set, &set->private, ip, level);
2663 + while (level <= set->levels && size) {
2664 + if (!(private && *private)) {
2668 + if (size < set->type[level]->reqsize) {
2672 + res = set->type[level]->delip(*private, data,
2673 + set->type[level]->reqsize, &id);
2674 + if (!(res == 0 || res == -EEXIST))
2676 + private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2677 + data += set->type[level]->reqsize;
2678 + size -= set->type[level++]->reqsize;
2683 + write_unlock_bh(&set->lock);
2688 +ip_set_testip(struct ip_set *set,
2694 + struct ip_set_private **private;
2698 + write_lock_bh(&set->lock);
2699 + if (set->subref) {
2703 + private = ip_set_find_private(set, &set->private, ip, level);
2704 + while (level <= set->levels && size) {
2705 + if (!(private && *private)) {
2709 + if (size < set->type[level]->reqsize) {
2713 + res = set->type[level]->testip(*private, data,
2714 + set->type[level]->reqsize, &id);
2715 + DP("level: %i res: %i", level, res);
2718 + private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2719 + data += set->type[level]->reqsize;
2720 + size -= set->type[level++]->reqsize;
2725 + write_unlock_bh(&set->lock);
2730 +set_type_equal(const struct ip_set_type *set_type, const char *str2)
2732 + DP("'%s' vs. '%s'", set_type->typename, str2);
2733 + return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
2737 + * Always use find_setfoo() under the &list_lock.
2739 +static inline struct ip_set_type *find_set_type(const char name[IP_SET_MAXNAMELEN])
2741 + return LIST_FIND(&set_type_list,
2743 + struct ip_set_type *,
2747 +int ip_set_register_set_type(struct ip_set_type *set_type)
2749 + if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
2750 + ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
2751 + set_type->typename,
2752 + set_type->protocol_version,
2753 + IP_SET_PROTOCOL_VERSION);
2757 + write_lock_bh(&list_lock);
2758 + if (find_set_type(set_type->typename)) {
2760 + write_unlock_bh(&list_lock);
2761 + ip_set_printk("'%s' already registered!",
2762 + set_type->typename);
2765 + MOD_INC_USE_COUNT;
2766 + list_append(&set_type_list, set_type);
2767 + write_unlock_bh(&list_lock);
2768 + DP("'%s' registered.", set_type->typename);
2772 +void ip_set_unregister_set_type(struct ip_set_type *set_type)
2774 + write_lock_bh(&list_lock);
2775 + if (!find_set_type(set_type->typename)) {
2776 + ip_set_printk("'%s' not registered?",
2777 + set_type->typename);
2778 + write_unlock_bh(&list_lock);
2781 + LIST_DELETE(&set_type_list, set_type);
2782 + write_unlock_bh(&list_lock);
2783 + MOD_DEC_USE_COUNT;
2785 + DP("'%s' unregistered.", set_type->typename);
2788 +/* Create the private part of a (child)set.
2789 + * Must be called without holding any locks.
2792 +ip_set_create_private(struct ip_set_type *set_type,
2793 + struct ip_set_private **private,
2796 + u_int8_t childsets)
2801 + DP("%s %p %p %i", set_type->typename, private, *private, childsets);
2804 + printk("%p: %p as private already occupied", private, *private);
2806 + /* Call the set_type initializer. */
2807 + res = set_type->create(private, data, size);
2812 + (*private)->childsets = NULL;
2816 + /* Create room for subsets */
2817 + newbytes = set_type->sizeid(*private) * sizeof(struct ip_set_private *);
2818 + DP("%s (%p) %i", set_type->typename, *private, newbytes);
2819 + (*private)->childsets = vmalloc(newbytes); \
2820 + if (!(*private)->childsets) {
2821 + set_type->destroy(private);
2824 + DP("%s %p %p %p", set_type->typename, private, *private, (*private)->childsets);
2825 + memset((*private)->childsets, 0, newbytes);
2830 +ip_set_create_childset(struct ip_set *set,
2833 + u_int8_t childsets,
2837 + struct ip_set_private **private = &set->private;
2841 + DP("%s (%i %i)", set->name, level, childsets);
2842 + write_lock_bh(&set->lock);
2843 + if (set->subref) {
2848 + private = ip_set_find_private(set, private, ip, level - 1);
2849 + DP("%s (%i %i) %p %p", set->name, level, childsets, private, *private);
2850 + if (!(private && *private && (*private)->childsets)) {
2854 + DP("%s (%i %i) %p %p", set->name, level, childsets, private, *private);
2855 + set->type[level - 1]->matchip(*private, ip[level - 1], &id);
2856 + DP("%s (%i %i) %p %p %i", set->name, level, childsets, private, *private, id);
2861 + if ((*private)->childsets[id]) {
2866 + write_unlock_bh(&set->lock);
2868 + /* Without holding any locks, create private part. */
2869 + res = ip_set_create_private(set->type[level],
2870 + &(*private)->childsets[id],
2871 + data, size, childsets);
2873 + write_lock_bh(&set->lock);
2876 + DP("%s (%p %p) res=%i", set->name, private, *private, res);
2877 + write_unlock_bh(&set->lock);
2882 +ip_set_create(const char name[IP_SET_MAXNAMELEN],
2883 + char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN],
2888 + int i, id, res = 0;
2889 + struct ip_set *set;
2891 + DP("%s (%i): %s", typename[0], level, name);
2893 + * First, and without any locks, allocate and initialize
2894 + * a normal base set structure.
2896 + set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
2899 + set->lock = RW_LOCK_UNLOCKED;
2900 + strncpy(set->name, name, IP_SET_MAXNAMELEN);
2901 + set->name[IP_SET_MAXNAMELEN - 1] = '\0';
2904 + set->levels = level;
2905 + set->private = NULL;
2908 + * Next, take the &list_lock, check that we know the type,
2909 + * and take a reference on the type, to make sure it
2910 + * stays available while constructing our new set.
2912 + * After referencing the type, we drop the &list_lock,
2913 + * and let the new set construction run without locks.
2915 + write_lock_bh(&list_lock);
2916 + for (i = 0; i < level; i++) {
2917 + set->type[i] = find_set_type(typename[i]);
2918 + if (set->type[i] == NULL) {
2919 + /* FIXME: try loading the module */
2920 + write_unlock_bh(&list_lock);
2921 + ip_set_printk("no set type '%s', set '%s' not created",
2922 + typename[i], name);
2927 + for (i = 0; i < level; i++)
2928 + __MOD_INC(set->type[i]->me);
2929 + write_unlock_bh(&list_lock);
2932 + * Without holding any locks, create private part.
2934 + res = ip_set_create_private(set->type[0],
2936 + data, size, level - 1);
2938 + for (i = 0; i <= level; i++)
2939 + __MOD_DEC(set->type[i]->me);
2944 + /* BTW, res==0 here. */
2947 + * Here, we have a valid, constructed set. &list_lock again,
2948 + * and check that it is not already in ip_set_list.
2950 + write_lock_bh(&list_lock);
2952 + for (i = 0; i < max_sets; i++) {
2953 + if (ip_set_list[i] != NULL
2954 + && strncmp(ip_set_list[i]->name, set->name,
2955 + IP_SET_MAXNAMELEN - 1) == 0) {
2958 + } else if (id < 0 && ip_set_list[i] == NULL)
2962 + /* No free slot remained */
2967 + * Finally! Append our shiny new set into the list, and be done.
2969 + DP("create: '%s' created with id %i!", set->name, id);
2970 + ip_set_list[id] = set;
2971 + write_unlock_bh(&list_lock);
2975 + write_unlock_bh(&list_lock);
2976 + ip_set_destroy_private(set, &set->private, 0);
2977 + for (i = 0; i < level; i++)
2978 + __MOD_DEC(set->type[i]->me);
2983 +static int ip_set_destroy(struct ip_set *set,
2987 + struct ip_set_private **private;
2990 + write_lock_bh(&list_lock);
2991 + /* there is no race, here. ->ref modification always happens
2992 + * under &list_lock. Fine.
2995 + /* one ref from caller */
2996 + if (set->ref > 1 || set->subref) {
3001 + for (i = 0; i < max_sets; i++)
3002 + if (ip_set_list[i] == set) {
3003 + ip_set_list[i] = NULL;
3006 + write_unlock_bh(&list_lock);
3008 + ip_set_destroy_private(set, &set->private, 0);
3009 + for (i = 0; i < set->levels; i++)
3010 + __MOD_DEC(set->type[i]->me);
3015 + private = ip_set_find_private(set, &set->private,
3018 + if (private && *private) {
3019 + if (set->subref) {
3024 + write_unlock_bh(&list_lock);
3026 + DP("%p %p", private, *private);
3027 + ip_set_destroy_private(set, private, level);
3028 + DP("%p %p", private, *private);
3030 + write_lock_bh(&list_lock);
3036 + write_unlock_bh(&list_lock);
3041 + * Find set by name, reference it once. The reference makes sure the
3042 + * thing pointed to, does not go away under our feet. Drop the reference
3043 + * later, using ip_set_put().
3045 +struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
3048 + struct ip_set *set = NULL;
3051 + read_lock_bh(&list_lock);
3052 + for (i = 0; i < max_sets; i++) {
3053 + set = ip_set_list[i];
3055 + && strncmp(set->name, name, IP_SET_MAXNAMELEN - 1) == 0) {
3061 + read_unlock_bh(&list_lock);
3066 + * Find set by id, reference it once. The reference makes sure the
3067 + * thing pointed to, does not go away under our feet. Drop the reference
3068 + * later, using ip_set_put().
3070 +struct ip_set *ip_set_get_byid(int id)
3072 + struct ip_set *set;
3074 + if (id < 0 || id >= max_sets)
3077 + write_lock_bh(&list_lock);
3078 + set = ip_set_list[id];;
3081 + write_unlock_bh(&list_lock);
3086 + * If the given set pointer points to a valid set, decrement
3087 + * reference count by 1. The caller shall not assume the pointer
3088 + * to be valid, after calling this function.
3090 +void ip_set_put(struct ip_set *set)
3092 + write_lock_bh(&list_lock);
3095 + write_unlock_bh(&list_lock);
3098 +static int ip_set_rename(struct ip_set *set, const char *name)
3102 + write_lock_bh(&list_lock);
3103 + for (i = 0; i < max_sets; i++) {
3104 + if (ip_set_list[i] != NULL
3105 + && strncmp(ip_set_list[i]->name,
3107 + IP_SET_MAXNAMELEN - 1) == 0) {
3112 + strncpy(set->name, name, IP_SET_MAXNAMELEN);
3113 + set->name[IP_SET_MAXNAMELEN - 1] = '\0';
3115 + write_unlock_bh(&list_lock);
3119 +static int ip_set_swap(struct ip_set *from, struct ip_set *to)
3121 + char from_name[IP_SET_MAXNAMELEN];
3122 + unsigned from_ref;
3124 + int from_id = -1, to_id = -1;
3126 + write_lock_bh(&list_lock);
3127 + for (i = 0; i < max_sets && (from_id < 0 || to_id < 0); i++) {
3128 + if (ip_set_list[i] == from)
3130 + if (ip_set_list[i] == to)
3133 + /* We must have got both sets: we hold refcounts against them! */
3134 + if (from_id < 0 || to_id < 0) {
3139 + strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
3140 + from_ref = from->ref;
3142 + ip_set_list[from_id] = to;
3143 + ip_set_list[to_id] = from;
3145 + strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
3146 + from->ref = to->ref;
3147 + strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
3148 + to->ref = from_ref;
3150 + write_unlock_bh(&list_lock);
3154 +size_t ip_set_listing_size(void)
3159 + read_lock_bh(&list_lock);
3160 + for (id = 0; id < max_sets; id++) {
3161 + if (ip_set_list[id] != NULL)
3162 + size += sizeof(struct ip_set_req_listing);
3164 + read_unlock_bh(&list_lock);
3169 +int ip_set_listing(void *data, int *len)
3172 + int res = 0; /* All OK */
3174 + struct ip_set *set;
3175 + struct ip_set_req_listing *header = data;
3177 + read_lock_bh(&list_lock);
3178 + for (id = 0; id < max_sets; id++) {
3179 + if (ip_set_list[id] == NULL)
3182 + /* Pointer to our header */
3183 + header = (struct ip_set_req_listing *) (data + used);
3185 + DP("used before= %d %p %p %p", used, header, data,
3188 + /* Get and ensure header size */
3189 + if (used + sizeof(struct ip_set_req_listing) > *len)
3190 + goto not_enough_mem;
3192 + set = ip_set_list[id];
3194 + /* Fill with data */
3195 + strncpy(header->name, set->name, IP_SET_MAXNAMELEN - 1);
3196 + for (i = 0; i < set->levels; i++)
3197 + strncpy(header->typename[i], set->type[i]->typename,
3198 + IP_SET_MAXNAMELEN - 1);
3199 + header->levels = set->levels;
3200 + header->ref = set->ref;
3203 + used += sizeof(struct ip_set_req_listing);
3204 + DP("used after= %d", used);
3206 + *len = used; /* How much did we use? */
3207 + goto unlock_and_return;
3210 + DP("not enough mem, try again");
3213 + unlock_and_return:
3214 + read_unlock_bh(&list_lock);
3218 +int ip_set_list_size(struct ip_set * set,
3224 + int res = 0; /* OK */
3225 + struct ip_set_private **private;
3227 + DP("%d %s %d", op, set->name, level);
3228 + read_lock_bh(&set->lock);
3229 + if (set->subref) {
3233 + private = ip_set_find_private(set, &set->private, ip, level);
3234 + if (!(private && *private)) {
3239 + case IP_SET_OP_LIST_HEADER_SIZE:
3240 + *size = set->type[level]->list_header_size(*private);
3242 + case IP_SET_OP_LIST_MEMBERS_SIZE:
3243 + *size = set->type[level]->list_members_size(*private);
3245 + case IP_SET_OP_LIST_CHILDSETS_SIZE:
3246 + *size = (*private)->childsets == NULL ? 0
3247 + : bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3253 + read_unlock_bh(&set->lock);
3254 + DP("%d %s %d: %u", op, set->name, level, *size);
3259 +static void list_childsets(const struct ip_set_private *private,
3261 + ip_set_ip_t sizeid)
3265 + memset(data, 0, bitmap_bytes(0, sizeid - 1));
3267 + if (private->childsets == NULL)
3270 + for (id = 0; id < sizeid; id++)
3271 + if (private->childsets[id] != NULL)
3272 + set_bit(id, data);
3275 +int ip_set_list_data(struct ip_set *set,
3282 + int res = 0; /* All OK */
3284 + struct ip_set_private **private;
3285 + void (*datafn)(const struct ip_set_private *, void *);
3287 + read_lock_bh(&set->lock);
3288 + if (set->subref) {
3292 + private = ip_set_find_private(set, &set->private, ip, level);
3293 + if (!(private && *private)) {
3298 + case IP_SET_OP_LIST_HEADER:
3299 + need = set->type[level]->list_header_size(*private);
3300 + datafn = set->type[level]->list_header;
3302 + case IP_SET_OP_LIST_MEMBERS:
3303 + need = set->type[level]->list_members_size(*private);
3304 + datafn = set->type[level]->list_members;
3306 + case IP_SET_OP_LIST_CHILDSETS:
3307 + if ((*private)->childsets == NULL) {
3311 + need = bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3318 + if (need > *len) {
3324 + datafn(*private, data);
3326 + list_childsets(*private, data, set->type[level]->sizeid(*private));
3329 + read_unlock_bh(&set->lock);
3334 +ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
3337 + int res = 0; /* Assume OK */
3338 + struct ip_set_req_base *req_base;
3339 + struct ip_set_req_std *req_std;
3340 + struct ip_set *set = NULL;
3342 + DP("optval=%d, user=%p, len=%d", optval, user, len);
3343 + if (!capable(CAP_NET_ADMIN))
3345 + if (optval != SO_IP_SET)
3347 + if (len < sizeof(struct ip_set_req_base)) {
3348 + ip_set_printk("short userdata (want >=%d, got %d)",
3349 + sizeof(struct ip_set_req_base), len);
3352 + data = vmalloc(len);
3354 + DP("out of mem for %d bytes", len);
3357 + if (copy_from_user(data, user, len) != 0) {
3362 + req_base = (struct ip_set_req_base *) data;
3364 + DP("op=%x id='%x'", req_base->op, req_base->id);
3366 + /* Handle set creation first - no incoming set specified */
3368 + if (req_base->op == IP_SET_OP_CREATE) {
3369 + struct ip_set_req_create *req_create
3370 + = (struct ip_set_req_create *) data;
3373 + if (len < sizeof(struct ip_set_req_create)) {
3374 + ip_set_printk("short CREATE data (want >%d, got %d)",
3375 + sizeof(struct ip_set_req_create), len);
3379 + if (req_create->levels > IP_SET_LEVELS) {
3380 + ip_set_printk("set level %d too deep (max %d)",
3381 + req_create->levels, IP_SET_LEVELS);
3385 + req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
3386 + for (i = 0; i < req_create->levels; i++)
3387 + req_create->typename[i][IP_SET_MAXNAMELEN - 1] = '\0';
3388 + res = ip_set_create(req_create->name,
3389 + req_create->typename,
3390 + req_create->levels,
3391 + data + sizeof(struct ip_set_req_create),
3392 + len - sizeof(struct ip_set_req_create));
3396 + /* All remaining requests want a set by id.
3397 + * We take a proper reference here, and drop it after processing.
3398 + * From hereon, code goes to '*put_set', not to 'done'.
3401 + set = ip_set_get_byid(req_base->id);
3402 + if (set == NULL) {
3407 + DP("set %s (%d) (%u)", set->name, req_base->id, set->ref);
3408 + /* Simple requests: no subsets */
3409 + switch (req_base->op) {
3410 + case IP_SET_OP_RENAME:{
3411 + struct ip_set_req_rename *req_rename
3412 + = (struct ip_set_req_rename *) data;
3414 + if (len != sizeof(struct ip_set_req_rename)) {
3415 + ip_set_printk("short RENAME data (want >%d, got %d)",
3416 + sizeof(struct ip_set_req_rename), len);
3421 + res = ip_set_rename(set, req_rename->newname);
3425 + case IP_SET_OP_SWAP:{
3426 + struct ip_set_req_swap *req_swap
3427 + = (struct ip_set_req_swap *) data;
3428 + struct ip_set *to;
3430 + if (len != sizeof(struct ip_set_req_swap)) {
3432 + ip_set_printk("short SWAP data (want >%d, got %d)",
3433 + sizeof(struct ip_set_req_swap), len);
3438 + to = ip_set_get_byid(req_swap->to);
3443 + res = ip_set_swap(set, to);
3448 + ; /* Requests with possible subsets: fall trough. */
3451 + req_std = (struct ip_set_req_std *) data;
3452 + if (len < sizeof(struct ip_set_req_std)) {
3453 + ip_set_printk("short data in std request (want >%d, got %d)",
3454 + sizeof(struct ip_set_req_std), len);
3457 + } else if (req_std->level >= set->levels) {
3462 + switch (req_base->op) {
3463 + case IP_SET_OP_ADD_IP:{
3464 + res = ip_set_addip(set,
3465 + req_std->ip, req_std->level,
3466 + data + sizeof(struct ip_set_req_std),
3467 + len - sizeof(struct ip_set_req_std));
3470 + case IP_SET_OP_DEL_IP:{
3471 + res = ip_set_delip(set,
3472 + req_std->ip, req_std->level,
3473 + data + sizeof(struct ip_set_req_std),
3474 + len - sizeof(struct ip_set_req_std));
3477 + case IP_SET_OP_DESTROY:{
3478 + res = ip_set_destroy(set, req_std->ip, req_std->level);
3479 + if (req_std->level == 0 && res == 0)
3480 + goto done; /* destroyed: no ip_set_put */
3483 + case IP_SET_OP_FLUSH:{
3484 + struct ip_set_req_sub *req_sub =
3485 + (struct ip_set_req_sub *) data;
3487 + if (len < sizeof(struct ip_set_req_sub)) {
3488 + ip_set_printk("short data in flush request (want >%d, got %d)",
3489 + sizeof(struct ip_set_req_sub), len);
3493 + res = ip_set_flush(set, req_sub->ip, req_sub->level, req_sub->childsets);
3496 + case IP_SET_OP_CREATE_CHILD:{
3497 + struct ip_set_req_sub *req_sub
3498 + = (struct ip_set_req_sub *) data;
3500 + if (len < sizeof(struct ip_set_req_sub)) {
3501 + ip_set_printk("short CREATE_CHILD data (want >%d, got %d)",
3502 + sizeof(struct ip_set_req_sub), len);
3506 + if (req_sub->level < 1) {
3507 + /* No entry supplied? */
3511 + if (((req_sub->level >= set->levels - 1) && req_sub->childsets)) {
3512 + /* No room for subsets to be created. */
3516 + res = ip_set_create_childset(set,
3519 + req_sub->childsets,
3520 + data + sizeof(struct ip_set_req_sub),
3521 + len - sizeof(struct ip_set_req_sub));
3525 + DP("unknown op %d", req_base->op);
3526 + ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3529 + } /* end of switch(op) */
3542 +ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
3545 + struct ip_set_req_base *req_base;
3546 + struct ip_set_req_std *req_std;
3547 + struct ip_set *set = NULL;
3549 + int copylen = *len;
3551 + DP("optval=%d, user=%p, len=%d", optval, user, *len);
3552 + if (!capable(CAP_NET_ADMIN))
3554 + if (optval != SO_IP_SET)
3556 + if (*len < sizeof(struct ip_set_req_base)) {
3557 + ip_set_printk("short userdata (want >=%d, got %d)",
3558 + sizeof(struct ip_set_req_base), *len);
3561 + data = vmalloc(*len);
3563 + DP("out of mem for %d bytes", *len);
3566 + if (copy_from_user(data, user, *len) != 0) {
3571 + req_base = (struct ip_set_req_base *) data;
3573 + DP("op=%x id='%x'", req_base->op, req_base->id);
3575 + /* Requests without a named set. */
3576 + switch (req_base->op) {
3577 + case IP_SET_OP_VERSION:{
3578 + struct ip_set_req_version *req_version =
3579 + (struct ip_set_req_version *) data;
3581 + if (*len != sizeof(struct ip_set_req_version)) {
3582 + ip_set_printk("short VERSION (want >=%d, got %d)",
3583 + sizeof(struct ip_set_req_version),
3589 + req_version->version = IP_SET_PROTOCOL_VERSION;
3590 + res = copy_to_user(user, req_version,
3591 + sizeof(struct ip_set_req_version));
3594 + case IP_SET_OP_LISTING_SIZE:{
3595 + struct ip_set_req_listing_size *req_list =
3596 + (struct ip_set_req_listing_size *) data;
3598 + DP("IP_SET_OP_LISTING_SIZE");
3600 + if (*len != sizeof(struct ip_set_req_listing_size)) {
3601 + ip_set_printk("short LISTING_SIZE (want >=%d, got %d)",
3602 + sizeof(struct ip_set_req_listing_size),
3608 + req_list->size = ip_set_listing_size();
3609 + DP("req_list->size = %d", req_list->size);
3610 + res = copy_to_user(user, req_list,
3611 + sizeof(struct ip_set_req_listing_size));
3614 + case IP_SET_OP_LISTING:{
3615 + DP("LISTING before len=%d", *len);
3616 + res = ip_set_listing(data, len);
3617 + DP("LISTING done len=%d", *len);
3619 + goto done; /* Error */
3621 + res = copy_to_user(user, data, *len); /* Only copy the mem used */
3625 + ; /* Requests with named set: fall trought */
3628 + /* Special cases: GETSET_BYNAME/BYID */
3629 + switch (req_base->op) {
3630 + case IP_SET_OP_GETSET_BYNAME: {
3631 + struct ip_set_req_get *req_get
3632 + = (struct ip_set_req_get *) data;
3634 + if (*len != sizeof(struct ip_set_req_get)) {
3635 + ip_set_printk("short _BYNAME (want >=%d, got %d)",
3636 + sizeof(struct ip_set_req_get), *len);
3640 + req_get->name[IP_SET_MAXNAMELEN - 1] = '\0';
3642 + set = ip_set_get_byname(req_get->name, &req_get->id);
3644 + req_get->ref = set->ref - 1;
3647 + res = copy_to_user(user, data, copylen);
3650 + case IP_SET_OP_GETSET_BYID: {
3651 + struct ip_set_req_get *req_get
3652 + = (struct ip_set_req_get *) data;
3654 + if (*len != sizeof(struct ip_set_req_get)) {
3655 + ip_set_printk("short _BYID (want >=%d, got %d)",
3656 + sizeof(struct ip_set_req_get), *len);
3660 + set = ip_set_get_byid(req_get->id);
3662 + req_get->ref = set->ref - 1;
3663 + strncpy(req_get->name, set->name, IP_SET_MAXNAMELEN);
3667 + res = copy_to_user(user, data, copylen);
3671 + ; /* Requests with set id: fall trought */
3674 + /* Requests with set id: */
3675 + if (req_base->id < 0 || req_base->id >= max_sets) {
3679 + set = ip_set_get_byid(req_base->id); /* Reference lock */
3685 + DP("set %s (%d) (%u)", set->name, req_base->id, set->ref);
3686 + req_std = (struct ip_set_req_std *) data;
3687 + if (*len < sizeof(struct ip_set_req_std)) {
3688 + ip_set_printk("short data in std request (want >%d, got %d)",
3689 + sizeof(struct ip_set_req_std), *len);
3691 + } else if (req_std->level >= set->levels) {
3696 + switch (req_base->op) {
3697 + case IP_SET_OP_TEST_IP:{
3698 + struct ip_set_req_test *req_test =
3699 + (struct ip_set_req_test *) data;
3701 + if (*len < sizeof(struct ip_set_req_test)) {
3702 + ip_set_printk("short data in testip request (want >%d, got %d)",
3703 + sizeof(struct ip_set_req_test), *len);
3707 + req_test->reply = ip_set_testip(set,
3710 + data + sizeof(struct ip_set_req_test),
3711 + *len - sizeof(struct ip_set_req_test));
3713 + DP("test result: %i", req_test->reply);
3714 + *len = copylen = sizeof(struct ip_set_req_test);
3717 + case IP_SET_OP_LIST_HEADER_SIZE:
3718 + case IP_SET_OP_LIST_MEMBERS_SIZE:
3719 + case IP_SET_OP_LIST_CHILDSETS_SIZE: {
3720 + struct ip_set_req_list *req_list =
3721 + (struct ip_set_req_list *) data;
3723 + if (*len != sizeof(struct ip_set_req_list)) {
3724 + ip_set_printk("short LIST (want >=%d, got %d)",
3725 + sizeof(struct ip_set_req_list),
3729 + res = ip_set_list_size(set,
3734 + DP("SIZEfoo size=%d", req_list->size);
3736 + goto put_set; /* Error */
3739 + case IP_SET_OP_LIST_HEADER:
3740 + case IP_SET_OP_LIST_MEMBERS:
3741 + case IP_SET_OP_LIST_CHILDSETS:{
3742 + DP("LISTfoo before len=%d", *len);
3743 + res = ip_set_list_data(set,
3749 + DP("LISTfoo done len=%d", *len);
3752 + goto put_set; /* Error */
3754 + copylen = *len; /* Only copy the mem used */
3758 + DP("unknown op %d", req_base->op);
3759 + ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3762 + } /* end of switch(op) */
3766 + DP("set %s (%u)", set->name, set->ref);
3767 + res = copy_to_user(user, data, copylen);
3773 + DP("set %s (%u)", set->name, set->ref);
3778 + DP("final result %d", res);
3782 +static struct nf_sockopt_ops so_set = {
3784 + .set_optmin = SO_IP_SET,
3785 + .set_optmax = SO_IP_SET + 1,
3786 + .set = &ip_set_sockfn_set,
3787 + .get_optmin = SO_IP_SET,
3788 + .get_optmax = SO_IP_SET + 1,
3789 + .get = &ip_set_sockfn_get,
3793 +MODULE_PARM(max_sets, "i");
3794 +MODULE_PARM_DESC(max_sets, "maximal number of sets");
3796 +static int __init init(void)
3800 + if (max_sets <= 0)
3801 + max_sets = CONFIG_IP_NF_SET_MAX;
3802 + ip_set_list = vmalloc(sizeof(struct ip_set *) * max_sets);
3803 + if (!ip_set_list) {
3804 + printk(KERN_ERR "Unable to create ip_set_list\n");
3807 + memset(ip_set_list, 0, sizeof(struct ip_set *) * max_sets);
3808 + INIT_LIST_HEAD(&set_type_list);
3810 + res = nf_register_sockopt(&so_set);
3812 + ip_set_printk("SO_SET registry failed: %d", res);
3813 + vfree(ip_set_list);
3819 +static void __exit fini(void)
3821 + nf_unregister_sockopt(&so_set);
3822 + vfree(ip_set_list);
3823 + DP("these are the famous last words");
3826 +EXPORT_SYMBOL(ip_set_register_set_type);
3827 +EXPORT_SYMBOL(ip_set_unregister_set_type);
3829 +EXPORT_SYMBOL(ip_set_list);
3830 +EXPORT_SYMBOL(ip_set_get_byname);
3831 +EXPORT_SYMBOL(ip_set_get_byid);
3832 +EXPORT_SYMBOL(ip_set_put);
3834 +EXPORT_SYMBOL(ip_set_addip_kernel);
3835 +EXPORT_SYMBOL(ip_set_delip_kernel);
3836 +EXPORT_SYMBOL(ip_set_testip_kernel);
3840 +MODULE_LICENSE("GPL");
3841 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.3/net/ipv4/netfilter/ip_set_iphash.c
3842 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
3843 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_iphash.c 2004-02-09 15:02:00.000000000 +0100
3845 +/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
3847 + * This program is free software; you can redistribute it and/or modify
3848 + * it under the terms of the GNU General Public License as published by
3849 + * the Free Software Foundation; either version 2 of the License, or
3850 + * (at your option) any later version.
3852 + * This program is distributed in the hope that it will be useful,
3853 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3854 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3855 + * GNU General Public License for more details.
3857 + * You should have received a copy of the GNU General Public License
3858 + * along with this program; if not, write to the Free Software
3859 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3862 +/* Kernel module implementing an ip hash set */
3864 +#include <linux/module.h>
3865 +#include <linux/ip.h>
3866 +#include <linux/skbuff.h>
3867 +#include <linux/netfilter_ipv4/ip_tables.h>
3868 +#include <linux/netfilter_ipv4/ip_set.h>
3869 +#include <linux/errno.h>
3870 +#include <asm/uaccess.h>
3871 +#include <asm/bitops.h>
3872 +#include <asm/softirq.h>
3873 +#include <linux/spinlock.h>
3874 +#include <linux/vmalloc.h>
3876 +#include <net/ip.h>
3878 +#include <linux/netfilter_ipv4/ip_set_iphash.h>
3879 +#include <linux/netfilter_ipv4/ip_set_jhash.h>
3881 +static inline ip_set_ip_t
3882 +hash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
3884 + return (jhash_1word(ip & map->netmask, map->initval) % map->hashsize);
3888 +__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3890 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3892 + *id = hash_ip(map, ip);
3893 + return (map->members[*id] == ip);
3897 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3899 + return __testip(private, ip, id);
3903 +testip(struct ip_set_private *private, const void *data, size_t size,
3906 + struct ip_set_req_iphash *req =
3907 + (struct ip_set_req_iphash *) data;
3909 + if (size != sizeof(struct ip_set_req_iphash)) {
3910 + ip_set_printk("data length wrong (want %d, have %d)",
3911 + sizeof(struct ip_set_req_iphash),
3915 + return __testip(private, req->ip, id);
3919 +testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3920 + u_int32_t flags, ip_set_ip_t *id)
3922 + if (!(flags & IPSET_TYPE_IP))
3925 + return __testip(private,
3926 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
3927 + : skb->nh.iph->daddr),
3932 +__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id,
3935 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3937 + *id = hash_ip(map, ip);
3939 + if (map->members[*id] == ip)
3942 + if (map->members[*id] != 0 && !(flags & IPSET_ADD_OVERWRITE))
3943 + return -EADDRINUSE;
3945 + map->members[*id] = ip;
3950 +addip(struct ip_set_private *private, const void *data, size_t size,
3953 + struct ip_set_req_iphash *req =
3954 + (struct ip_set_req_iphash *) data;
3956 + if (size != sizeof(struct ip_set_req_iphash)) {
3957 + ip_set_printk("data length wrong (want %d, have %d)",
3958 + sizeof(struct ip_set_req_iphash),
3962 + return __addip(private, req->ip, id, req->flags);
3966 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3967 + u_int32_t flags, ip_set_ip_t *id)
3969 + if (!(flags & IPSET_TYPE_IP))
3972 + return __addip(private,
3973 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
3974 + : skb->nh.iph->daddr),
3980 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3982 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3984 + *id = hash_ip(map, ip);
3986 + if (map->members[*id] == 0)
3989 + if (map->members[*id] != ip)
3990 + return -EADDRINUSE;
3992 + map->members[*id] = 0;
3997 +delip(struct ip_set_private *private, const void *data, size_t size,
4000 + struct ip_set_req_iphash *req =
4001 + (struct ip_set_req_iphash *) data;
4003 + if (size != sizeof(struct ip_set_req_iphash)) {
4004 + ip_set_printk("data length wrong (want %d, have %d)",
4005 + sizeof(struct ip_set_req_iphash),
4009 + return __delip(private, req->ip, id);
4013 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4014 + u_int32_t flags, ip_set_ip_t *id)
4016 + if (!(flags & IPSET_TYPE_IP))
4019 + return __delip(private,
4020 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4021 + : skb->nh.iph->daddr),
4025 +static int create(struct ip_set_private **private, const void *data, size_t size)
4028 + struct ip_set_req_iphash_create *req =
4029 + (struct ip_set_req_iphash_create *) data;
4030 + struct ip_set_iphash *map;
4032 + if (size != sizeof(struct ip_set_req_iphash_create)) {
4033 + ip_set_printk("data length wrong (want %d, have %d)",
4034 + sizeof(struct ip_set_req_iphash_create),
4039 + if (req->hashsize > MAX_RANGE) {
4040 + ip_set_printk("hashsize too big (max %d)",
4045 + if (req->hashsize < 1) {
4046 + ip_set_printk("hashsize too small");
4050 + map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
4052 + DP("out of memory for %d bytes",
4053 + sizeof(struct ip_set_iphash));
4056 + map->initval = req->initval;
4057 + map->hashsize = req->hashsize;
4058 + map->netmask = req->netmask;
4059 + newbytes = map->hashsize * sizeof(ip_set_ip_t);
4060 + map->members = vmalloc(newbytes);
4061 + if (!map->members) {
4062 + DP("out of memory for %d bytes", newbytes);
4066 + memset(map->members, 0, newbytes);
4068 + *private = (struct ip_set_private *) map;
4072 +static void destroy(struct ip_set_private **private)
4074 + struct ip_set_iphash *map = (struct ip_set_iphash *) *private;
4076 + vfree(map->members);
4082 +static void flush(struct ip_set_private *private)
4084 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4085 + memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
4088 +static int list_header_size(const struct ip_set_private *private)
4090 + return sizeof(struct ip_set_req_iphash_create);
4093 +static void list_header(const struct ip_set_private *private, void *data)
4095 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4096 + struct ip_set_req_iphash_create *header =
4097 + (struct ip_set_req_iphash_create *) data;
4099 + header->initval = map->initval;
4100 + header->hashsize = map->hashsize;
4101 + header->netmask = map->netmask;
4104 +static int list_members_size(const struct ip_set_private *private)
4106 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4108 + return (map->hashsize * sizeof(ip_set_ip_t));
4111 +static void list_members(const struct ip_set_private *private, void *data)
4113 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4115 + int bytes = map->hashsize * sizeof(ip_set_ip_t);
4117 + memcpy(data, map->members, bytes);
4120 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4122 + struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4124 + return (map->hashsize);
4127 +static struct ip_set_type ip_set_iphash = {
4128 + .typename = SETTYPE_NAME,
4129 + .typecode = IPSET_TYPE_IP,
4130 + .protocol_version = IP_SET_PROTOCOL_VERSION,
4131 + .create = &create,
4132 + .destroy = &destroy,
4134 + .reqsize = sizeof(struct ip_set_req_iphash),
4136 + .addip_kernel = &addip_kernel,
4138 + .delip_kernel = &delip_kernel,
4139 + .matchip = &matchip,
4140 + .testip = &testip,
4141 + .testip_kernel = &testip_kernel,
4142 + .list_header_size = &list_header_size,
4143 + .list_header = &list_header,
4144 + .list_members_size = &list_members_size,
4145 + .list_members = &list_members,
4146 + .sizeid = &sizeid,
4147 + .me = THIS_MODULE,
4150 +static int __init init(void)
4152 + return ip_set_register_set_type(&ip_set_iphash);
4155 +static void __exit fini(void)
4157 + /* FIXME: possible race with ip_set_create() */
4158 + ip_set_unregister_set_type(&ip_set_iphash);
4163 +MODULE_LICENSE("GPL");
4164 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_ipmap.c
4165 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
4166 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_ipmap.c 2004-02-09 15:02:00.000000000 +0100
4168 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4169 + * Patrick Schaaf (bof@bof.de)
4170 + * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4172 + * This program is free software; you can redistribute it and/or modify
4173 + * it under the terms of the GNU General Public License as published by
4174 + * the Free Software Foundation; either version 2 of the License, or
4175 + * (at your option) any later version.
4177 + * This program is distributed in the hope that it will be useful,
4178 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4179 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4180 + * GNU General Public License for more details.
4182 + * You should have received a copy of the GNU General Public License
4183 + * along with this program; if not, write to the Free Software
4184 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4187 +/* Kernel module implementing an IP set type: the single bitmap type */
4189 +#include <linux/module.h>
4190 +#include <linux/ip.h>
4191 +#include <linux/skbuff.h>
4192 +#include <linux/netfilter_ipv4/ip_tables.h>
4193 +#include <linux/netfilter_ipv4/ip_set.h>
4194 +#include <linux/errno.h>
4195 +#include <asm/uaccess.h>
4196 +#include <asm/bitops.h>
4197 +#include <asm/softirq.h>
4198 +#include <linux/spinlock.h>
4200 +#include <linux/netfilter_ipv4/ip_set_ipmap.h>
4202 +static inline ip_set_ip_t
4203 +ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
4205 + return ((ip & map->netmask) - map->first_ip)/map->hosts;
4209 +__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4211 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4213 + if (ip < map->first_ip || ip > map->last_ip)
4216 + *id = ip_to_id(map, ip);
4217 + return !!test_bit(*id, map->members);
4221 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4223 + return __testip(private, ip, id);
4227 +testip(struct ip_set_private *private, const void *data, size_t size,
4230 + struct ip_set_req_ipmap *req =
4231 + (struct ip_set_req_ipmap *) data;
4233 + if (size != sizeof(struct ip_set_req_ipmap)) {
4234 + ip_set_printk("data length wrong (want %d, have %d)",
4235 + sizeof(struct ip_set_req_ipmap),
4239 + return __testip(private, req->ip, id);
4243 +testip_kernel(struct ip_set_private *private,
4244 + const struct sk_buff *skb,
4248 + if (!(flags & IPSET_TYPE_IP))
4251 + DP("flags: %u (%s) ip %u.%u.%u.%u", flags,
4252 + flags & IPSET_SRC ? "SRC" : "DST",
4253 + NIPQUAD(skb->nh.iph->saddr));
4254 + DP("flags: %u (%s) ip %u.%u.%u.%u", flags,
4255 + flags & IPSET_SRC ? "SRC" : "DST",
4256 + NIPQUAD(skb->nh.iph->daddr));
4258 + return __testip(private,
4259 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4260 + : skb->nh.iph->daddr),
4265 +__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4267 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4269 + if (ip < map->first_ip || ip > map->last_ip)
4272 + *id = ip_to_id(map, ip);
4273 + if (test_and_set_bit(*id, map->members))
4280 +addip(struct ip_set_private *private, const void *data, size_t size,
4283 + struct ip_set_req_ipmap *req =
4284 + (struct ip_set_req_ipmap *) data;
4286 + if (size != sizeof(struct ip_set_req_ipmap)) {
4287 + ip_set_printk("data length wrong (want %d, have %d)",
4288 + sizeof(struct ip_set_req_ipmap),
4292 + DP("%u.%u.%u.%u", NIPQUAD(req->ip));
4293 + return __addip(private, req->ip, id);
4297 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4298 + u_int32_t flags, ip_set_ip_t *id)
4300 + if (!(flags & IPSET_TYPE_IP))
4303 + return __addip(private,
4304 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4305 + : skb->nh.iph->daddr),
4310 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4312 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4314 + if (ip < map->first_ip || ip > map->last_ip)
4317 + *id = ip_to_id(map, ip);
4318 + if (!test_and_clear_bit(*id, map->members))
4325 +delip(struct ip_set_private *private, const void *data, size_t size,
4328 + struct ip_set_req_ipmap *req =
4329 + (struct ip_set_req_ipmap *) data;
4331 + if (size != sizeof(struct ip_set_req_ipmap)) {
4332 + ip_set_printk("data length wrong (want %d, have %d)",
4333 + sizeof(struct ip_set_req_ipmap),
4337 + return __delip(private, req->ip, id);
4341 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4342 + u_int32_t flags, ip_set_ip_t *id)
4344 + if (!(flags & IPSET_TYPE_IP))
4347 + return __delip(private,
4348 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4349 + : skb->nh.iph->daddr),
4353 +static int create(struct ip_set_private **private, const void *data, size_t size)
4356 + struct ip_set_req_ipmap_create *req =
4357 + (struct ip_set_req_ipmap_create *) data;
4358 + struct ip_set_ipmap *map;
4360 + if (size != sizeof(struct ip_set_req_ipmap_create)) {
4361 + ip_set_printk("data length wrong (want %d, have %d)",
4362 + sizeof(struct ip_set_req_ipmap_create),
4367 + DP("from 0x%08x to 0x%08x", req->from, req->to);
4369 + if (req->from > req->to) {
4370 + DP("bad ip range");
4374 + if (req->to - req->from > MAX_RANGE) {
4375 + ip_set_printk("range too big (max %d addresses)",
4380 + map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
4382 + DP("out of memory for %d bytes",
4383 + sizeof(struct ip_set_ipmap));
4386 + map->first_ip = req->from;
4387 + map->last_ip = req->to;
4388 + map->netmask = req->netmask;
4390 + if (req->netmask == 0xFFFFFFFF) {
4392 + map->sizeid = map->last_ip - map->first_ip + 1;
4394 + unsigned int mask_bits, netmask_bits;
4397 + map->first_ip &= map->netmask; /* Should we better bark? */
4399 + mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
4400 + netmask_bits = mask_to_bits(map->netmask);
4402 + if (!mask || netmask_bits <= mask_bits)
4405 + map->hosts = 2 << (32 - netmask_bits - 1);
4406 + map->sizeid = 2 << (netmask_bits - mask_bits - 1);
4408 + newbytes = bitmap_bytes(0, map->sizeid - 1);
4409 + DP("%x %x %i", map->first_ip, map->last_ip, newbytes);
4410 + map->members = kmalloc(newbytes, GFP_KERNEL);
4411 + if (!map->members) {
4412 + DP("out of memory for %d bytes", newbytes);
4416 + memset(map->members, 0, newbytes);
4418 + *private = (struct ip_set_private *) map;
4422 +static void destroy(struct ip_set_private **private)
4424 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) *private;
4426 + kfree(map->members);
4432 +static void flush(struct ip_set_private *private)
4434 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4435 + memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
4438 +static int list_header_size(const struct ip_set_private *private)
4440 + return sizeof(struct ip_set_req_ipmap_create);
4443 +static void list_header(const struct ip_set_private *private, void *data)
4445 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4446 + struct ip_set_req_ipmap_create *header =
4447 + (struct ip_set_req_ipmap_create *) data;
4449 + DP("list_header %x %x", map->first_ip, map->last_ip);
4451 + header->from = map->first_ip;
4452 + header->to = map->last_ip;
4453 + header->netmask = map->netmask;
4456 +static int list_members_size(const struct ip_set_private *private)
4458 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4460 + return bitmap_bytes(0, map->sizeid - 1);
4463 +static void list_members(const struct ip_set_private *private, void *data)
4465 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4467 + int bytes = bitmap_bytes(0, map->sizeid - 1);
4469 + memcpy(data, map->members, bytes);
4472 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4474 + struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4476 + return (map->sizeid);
4479 +static struct ip_set_type ip_set_ipmap = {
4480 + .typename = SETTYPE_NAME,
4481 + .typecode = IPSET_TYPE_IP,
4482 + .protocol_version = IP_SET_PROTOCOL_VERSION,
4483 + .create = &create,
4484 + .destroy = &destroy,
4486 + .reqsize = sizeof(struct ip_set_req_ipmap),
4488 + .addip_kernel = &addip_kernel,
4490 + .delip_kernel = &delip_kernel,
4491 + .matchip = &matchip,
4492 + .testip = &testip,
4493 + .testip_kernel = &testip_kernel,
4494 + .list_header_size = &list_header_size,
4495 + .list_header = &list_header,
4496 + .list_members_size = &list_members_size,
4497 + .list_members = &list_members,
4498 + .sizeid = &sizeid,
4499 + .me = THIS_MODULE,
4502 +static int __init init(void)
4504 + return ip_set_register_set_type(&ip_set_ipmap);
4507 +static void __exit fini(void)
4509 + /* FIXME: possible race with ip_set_create() */
4510 + ip_set_unregister_set_type(&ip_set_ipmap);
4515 +MODULE_LICENSE("GPL");
4516 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_macipmap.c
4517 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
4518 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_macipmap.c 2004-02-09 15:02:00.000000000 +0100
4520 +/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4521 + * Patrick Schaaf (bof@bof.de)
4522 + * Martin Josefsson (gandalf@wlug.westbo.se)
4524 + * This program is free software; you can redistribute it and/or modify
4525 + * it under the terms of the GNU General Public License as published by
4526 + * the Free Software Foundation; either version 2 of the License, or
4527 + * (at your option) any later version.
4529 + * This program is distributed in the hope that it will be useful,
4530 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4531 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4532 + * GNU General Public License for more details.
4534 + * You should have received a copy of the GNU General Public License
4535 + * along with this program; if not, write to the Free Software
4536 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4539 +/* Kernel module implementing an IP set type: the macipmap type */
4541 +#include <linux/module.h>
4542 +#include <linux/ip.h>
4543 +#include <linux/skbuff.h>
4544 +#include <linux/netfilter_ipv4/ip_tables.h>
4545 +#include <linux/netfilter_ipv4/ip_set.h>
4546 +#include <linux/errno.h>
4547 +#include <asm/uaccess.h>
4548 +#include <asm/bitops.h>
4549 +#include <asm/softirq.h>
4550 +#include <linux/spinlock.h>
4551 +#include <linux/if_ether.h>
4552 +#include <linux/vmalloc.h>
4554 +#include <linux/netfilter_ipv4/ip_set_macipmap.h>
4557 +matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4559 + struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4560 + struct ip_set_macip *table =
4561 + (struct ip_set_macip *) map->members;
4563 + if (ip < map->first_ip || ip > map->last_ip)
4566 + *id = ip - map->first_ip;
4567 + return !!test_bit(IPSET_MACIP_ISSET, &table[*id].flags);
4571 +testip(struct ip_set_private *private, const void *data, size_t size,
4574 + struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4575 + struct ip_set_macip *table =
4576 + (struct ip_set_macip *) map->members;
4578 + struct ip_set_req_macipmap *req =
4579 + (struct ip_set_req_macipmap *) data;
4581 + if (size != sizeof(struct ip_set_req_macipmap)) {
4582 + ip_set_printk("data length wrong (want %d, have %d)",
4583 + sizeof(struct ip_set_req_macipmap),
4588 + if (req->ip < map->first_ip || req->ip > map->last_ip)
4591 + *id = req->ip - map->first_ip;
4592 + if (test_bit(IPSET_MACIP_ISSET, &table[*id].flags)) {
4593 + /* Is mac pointer valid?
4594 + * If so, compare... */
4595 + return (memcmp(req->ethernet,
4596 + &table[*id].ethernet,
4599 + return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4604 +testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4605 + u_int32_t flags, ip_set_ip_t *id)
4607 + struct ip_set_macipmap *map =
4608 + (struct ip_set_macipmap *) private;
4609 + struct ip_set_macip *table =
4610 + (struct ip_set_macip *) map->members;
4613 + if (!(flags & IPSET_TYPE_IP))
4616 + ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4617 + : skb->nh.iph->daddr);
4619 + if (ip < map->first_ip || ip > map->last_ip)
4622 + *id = ip - map->first_ip;
4623 + if (test_bit(IPSET_MACIP_ISSET, &table[*id].flags)) {
4624 + /* Is mac pointer valid?
4625 + * If so, compare... */
4626 + return (skb->mac.raw >= skb->head
4627 + && (skb->mac.raw + ETH_HLEN) <= skb->data
4628 + && (memcmp(skb->mac.ethernet->h_source,
4629 + &table[*id].ethernet,
4632 + return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4636 +/* returns 0 on success */
4638 +__addip(struct ip_set_private *private,
4639 + ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *id)
4641 + struct ip_set_macipmap *map =
4642 + (struct ip_set_macipmap *) private;
4643 + struct ip_set_macip *table =
4644 + (struct ip_set_macip *) map->members;
4646 + if (ip < map->first_ip || ip > map->last_ip)
4648 + if (test_and_set_bit(IPSET_MACIP_ISSET,
4649 + &table[ip - map->first_ip].flags))
4652 + *id = ip - map->first_ip;
4653 + memcpy(&table[*id].ethernet, ethernet, ETH_ALEN);
4658 +addip(struct ip_set_private *private, const void *data, size_t size,
4661 + struct ip_set_req_macipmap *req =
4662 + (struct ip_set_req_macipmap *) data;
4664 + if (size != sizeof(struct ip_set_req_macipmap)) {
4665 + ip_set_printk("data length wrong (want %d, have %d)",
4666 + sizeof(struct ip_set_req_macipmap),
4670 + return __addip(private, req->ip, req->ethernet, id);
4674 +addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4675 + u_int32_t flags, ip_set_ip_t *id)
4679 + if (!(flags & IPSET_TYPE_IP))
4682 + ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4683 + : skb->nh.iph->daddr);
4685 + if (!(skb->mac.raw >= skb->head
4686 + && (skb->mac.raw + ETH_HLEN) <= skb->data))
4689 + return __addip(private, ip, skb->mac.ethernet->h_source, id);
4693 +__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4695 + struct ip_set_macipmap *map =
4696 + (struct ip_set_macipmap *) private;
4697 + struct ip_set_macip *table =
4698 + (struct ip_set_macip *) map->members;
4700 + if (ip < map->first_ip || ip > map->last_ip)
4702 + if (!test_and_clear_bit(IPSET_MACIP_ISSET,
4703 + &table[ip - map->first_ip].flags))
4706 + *id = ip - map->first_ip;
4711 +delip(struct ip_set_private *private, const void *data, size_t size,
4714 + struct ip_set_req_macipmap *req =
4715 + (struct ip_set_req_macipmap *) data;
4717 + if (size != sizeof(struct ip_set_req_macipmap)) {
4718 + ip_set_printk("data length wrong (want %d, have %d)",
4719 + sizeof(struct ip_set_req_macipmap),
4723 + return __delip(private, req->ip, id);
4727 +delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4728 + u_int32_t flags, ip_set_ip_t *id)
4730 + if (!(flags & IPSET_TYPE_IP))
4733 + return __delip(private,
4734 + ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4735 + : skb->nh.iph->daddr),
4739 +static int create(struct ip_set_private **private, const void *data, size_t size)
4742 + struct ip_set_req_macipmap_create *req =
4743 + (struct ip_set_req_macipmap_create *) data;
4744 + struct ip_set_macipmap *map;
4746 + if (size != sizeof(struct ip_set_req_macipmap_create)) {
4747 + ip_set_printk("data length wrong (want %d, have %d)",
4748 + sizeof(struct ip_set_req_macipmap_create),
4753 + DP("from 0x%08x to 0x%08x", req->from, req->to);
4755 + if (req->from > req->to) {
4756 + DP("bad ip range");
4760 + if (req->to - req->from > MAX_RANGE) {
4761 + ip_set_printk("range too big (max %d addresses)",
4766 + map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
4768 + DP("out of memory for %d bytes",
4769 + sizeof(struct ip_set_macipmap));
4772 + map->flags = req->flags;
4773 + map->first_ip = req->from;
4774 + map->last_ip = req->to;
4775 + newbytes = (req->to - req->from + 1) * sizeof(struct ip_set_macip);
4776 + map->members = vmalloc(newbytes);
4777 + if (!map->members) {
4778 + DP("out of memory for %d bytes", newbytes);
4782 + memset(map->members, 0, newbytes);
4784 + *private = (struct ip_set_private *) map;
4788 +static void destroy(struct ip_set_private **private)
4790 + struct ip_set_macipmap *map =
4791 + (struct ip_set_macipmap *) *private;
4793 + vfree(map->members);
4799 +static void flush(struct ip_set_private *private)
4801 + struct ip_set_macipmap *map =
4802 + (struct ip_set_macipmap *) private;
4803 + memset(map->members, 0, (map->last_ip - map->first_ip)
4804 + * sizeof(struct ip_set_macip));
4807 +static int list_header_size(const struct ip_set_private *private)
4809 + return sizeof(struct ip_set_req_macipmap_create);
4812 +static void list_header(const struct ip_set_private *private, void *data)
4814 + struct ip_set_macipmap *map =
4815 + (struct ip_set_macipmap *) private;
4816 + struct ip_set_req_macipmap_create *header =
4817 + (struct ip_set_req_macipmap_create *) data;
4819 + DP("list_header %x %x %u", map->first_ip, map->last_ip,
4822 + header->from = map->first_ip;
4823 + header->to = map->last_ip;
4824 + header->flags = map->flags;
4827 +static int list_members_size(const struct ip_set_private *private)
4829 + struct ip_set_macipmap *map =
4830 + (struct ip_set_macipmap *) private;
4832 + return (map->last_ip
4833 + - map->first_ip + 1) * sizeof(struct ip_set_macip);
4836 +static void list_members(const struct ip_set_private *private, void *data)
4838 + struct ip_set_macipmap *map =
4839 + (struct ip_set_macipmap *) private;
4841 + int bytes = (map->last_ip -
4842 + - map->first_ip + 1) * sizeof(struct ip_set_macip);
4844 + memcpy(data, map->members, bytes);
4847 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
4849 + struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4851 + return (map->last_ip - map->first_ip + 1);
4854 +static struct ip_set_type ip_set_macipmap = {
4855 + .typename = SETTYPE_NAME,
4856 + .typecode = IPSET_TYPE_IP,
4857 + .protocol_version = IP_SET_PROTOCOL_VERSION,
4858 + .create = &create,
4859 + .destroy = &destroy,
4861 + .reqsize = sizeof(struct ip_set_req_macipmap),
4863 + .addip_kernel = &addip_kernel,
4865 + .delip_kernel = &delip_kernel,
4866 + .matchip = &matchip,
4867 + .testip = &testip,
4868 + .testip_kernel = &testip_kernel,
4869 + .list_header_size = &list_header_size,
4870 + .list_header = &list_header,
4871 + .list_members_size = &list_members_size,
4872 + .list_members = &list_members,
4873 + .sizeid = &sizeid,
4874 + .me = THIS_MODULE,
4877 +static int __init init(void)
4879 + return ip_set_register_set_type(&ip_set_macipmap);
4882 +static void __exit fini(void)
4884 + /* FIXME: possible race with ip_set_create() */
4885 + ip_set_unregister_set_type(&ip_set_macipmap);
4890 +MODULE_LICENSE("GPL");
4891 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_portmap.c
4892 --- linux-2.6.3.org/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
4893 +++ linux-2.6.3/net/ipv4/netfilter/ip_set_portmap.c 2004-02-09 15:02:00.000000000 +0100
4895 +/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4897 + * Based on ip_set_ipmap.c
4899 + * This program is free software; you can redistribute it and/or modify
4900 + * it under the terms of the GNU General Public License as published by
4901 + * the Free Software Foundation; either version 2 of the License, or
4902 + * (at your option) any later version.
4904 + * This program is distributed in the hope that it will be useful,
4905 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4906 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4907 + * GNU General Public License for more details.
4909 + * You should have received a copy of the GNU General Public License
4910 + * along with this program; if not, write to the Free Software
4911 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4914 +/* Kernel module implementing a port set type as a bitmap */
4916 +#include <linux/module.h>
4917 +#include <linux/ip.h>
4918 +#include <linux/tcp.h>
4919 +#include <linux/udp.h>
4920 +#include <linux/skbuff.h>
4921 +#include <linux/netfilter_ipv4/ip_tables.h>
4922 +#include <linux/netfilter_ipv4/ip_set.h>
4923 +#include <linux/errno.h>
4924 +#include <asm/uaccess.h>
4925 +#include <asm/bitops.h>
4926 +#include <asm/softirq.h>
4927 +#include <linux/spinlock.h>
4929 +#include <net/ip.h>
4931 +#include <linux/netfilter_ipv4/ip_set_portmap.h>
4933 +static inline ip_set_ip_t
4934 +get_port(const struct sk_buff *skb, u_int32_t flags)
4936 + struct iphdr *iph = skb->nh.iph;
4937 + u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
4939 + switch (iph->protocol) {
4940 + case IPPROTO_TCP: {
4941 + struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
4943 + /* See comments at tcp_match in ip_tables.c */
4946 + && (skb->len - iph->ihl * 4) < sizeof(struct tcphdr)))
4947 + return INVALID_PORT;
4949 + return ntohs(flags & IPSET_SRC ?
4950 + tcph->source : tcph->dest);
4952 + case IPPROTO_UDP: {
4953 + struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
4957 + && (skb->len - iph->ihl * 4) < sizeof(struct udphdr)))
4958 + return INVALID_PORT;
4960 + return ntohs(flags & IPSET_SRC ?
4961 + udph->source : udph->dest);
4964 + return INVALID_PORT;
4969 +__testport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4971 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
4973 + if (port < map->first_port || port > map->last_port)
4976 + *id = port - map->first_port;
4977 + return !!test_bit(*id, map->members);
4981 +matchport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4983 + return __testport(private, port, id);
4987 +testport(struct ip_set_private *private, const void *data, size_t size,
4990 + struct ip_set_req_portmap *req =
4991 + (struct ip_set_req_portmap *) data;
4993 + if (size != sizeof(struct ip_set_req_portmap)) {
4994 + ip_set_printk("data length wrong (want %d, have %d)",
4995 + sizeof(struct ip_set_req_portmap),
4999 + return __testport(private, req->port, id);
5003 +testport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5004 + u_int32_t flags, ip_set_ip_t *id)
5008 + if (!(flags & IPSET_TYPE_PORT))
5011 + port = get_port(skb, flags);
5012 + DP("flags %u %s port %u",
5014 + flags & IPSET_SRC ? "SRC" : "DST",
5017 + if (port == INVALID_PORT)
5020 + return __testport(private, port, id);
5024 +__addport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5026 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5028 + if (port < map->first_port || port > map->last_port)
5030 + if (test_and_set_bit(port - map->first_port, map->members))
5033 + *id = port - map->first_port;
5038 +addport(struct ip_set_private *private, const void *data, size_t size,
5041 + struct ip_set_req_portmap *req =
5042 + (struct ip_set_req_portmap *) data;
5044 + if (size != sizeof(struct ip_set_req_portmap)) {
5045 + ip_set_printk("data length wrong (want %d, have %d)",
5046 + sizeof(struct ip_set_req_portmap),
5050 + return __addport(private, req->port, id);
5054 +addport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5055 + u_int32_t flags, ip_set_ip_t *id)
5059 + if (!(flags & IPSET_TYPE_PORT))
5062 + port = get_port(skb, flags);
5064 + if (port == INVALID_PORT)
5067 + return __addport(private, port, id);
5071 +__delport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5073 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5075 + if (port < map->first_port || port > map->last_port)
5077 + if (!test_and_clear_bit(port - map->first_port, map->members))
5080 + *id = port - map->first_port;
5085 +delport(struct ip_set_private *private, const void *data, size_t size,
5088 + struct ip_set_req_portmap *req =
5089 + (struct ip_set_req_portmap *) data;
5091 + if (size != sizeof(struct ip_set_req_portmap)) {
5092 + ip_set_printk("data length wrong (want %d, have %d)",
5093 + sizeof(struct ip_set_req_portmap),
5097 + return __delport(private, req->port, id);
5101 +delport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5102 + u_int32_t flags, ip_set_ip_t *id)
5106 + if (!(flags & IPSET_TYPE_PORT))
5109 + port = get_port(skb, flags);
5111 + if (port == INVALID_PORT)
5114 + return __delport(private, port, id);
5117 +static int create(struct ip_set_private **private, const void *data, size_t size)
5120 + struct ip_set_req_portmap_create *req =
5121 + (struct ip_set_req_portmap_create *) data;
5122 + struct ip_set_portmap *map;
5124 + if (size != sizeof(struct ip_set_req_portmap_create)) {
5125 + ip_set_printk("data length wrong (want %d, have %d)",
5126 + sizeof(struct ip_set_req_portmap_create),
5131 + DP("from 0x%08x to 0x%08x", req->from, req->to);
5133 + if (req->from > req->to) {
5134 + DP("bad port range");
5138 + if (req->to - req->from > MAX_RANGE) {
5139 + ip_set_printk("range too big (max %d ports)",
5144 + map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
5146 + DP("out of memory for %d bytes",
5147 + sizeof(struct ip_set_portmap));
5150 + map->first_port = req->from;
5151 + map->last_port = req->to;
5152 + newbytes = bitmap_bytes(req->from, req->to);
5153 + map->members = kmalloc(newbytes, GFP_KERNEL);
5154 + if (!map->members) {
5155 + DP("out of memory for %d bytes", newbytes);
5159 + memset(map->members, 0, newbytes);
5161 + *private = (struct ip_set_private *) map;
5165 +static void destroy(struct ip_set_private **private)
5167 + struct ip_set_portmap *map = (struct ip_set_portmap *) *private;
5169 + kfree(map->members);
5175 +static void flush(struct ip_set_private *private)
5177 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5178 + memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
5181 +static int list_header_size(const struct ip_set_private *private)
5183 + return sizeof(struct ip_set_req_portmap_create);
5186 +static void list_header(const struct ip_set_private *private, void *data)
5188 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5189 + struct ip_set_req_portmap_create *header =
5190 + (struct ip_set_req_portmap_create *) data;
5192 + DP("list_header %x %x", map->first_port, map->last_port);
5194 + header->from = map->first_port;
5195 + header->to = map->last_port;
5198 +static int list_members_size(const struct ip_set_private *private)
5200 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5202 + return bitmap_bytes(map->first_port, map->last_port);
5205 +static void list_members(const struct ip_set_private *private, void *data)
5207 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5209 + int bytes = bitmap_bytes(map->first_port, map->last_port);
5211 + memcpy(data, map->members, bytes);
5214 +static ip_set_ip_t sizeid(const struct ip_set_private *private)
5216 + struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5218 + return (map->last_port - map->first_port + 1);
5221 +static struct ip_set_type ip_set_portmap = {
5222 + .typename = SETTYPE_NAME,
5223 + .typecode = IPSET_TYPE_PORT,
5224 + .protocol_version = IP_SET_PROTOCOL_VERSION,
5225 + .create = &create,
5226 + .destroy = &destroy,
5228 + .reqsize = sizeof(struct ip_set_req_portmap),
5229 + .addip = &addport,
5230 + .addip_kernel = &addport_kernel,
5231 + .delip = &delport,
5232 + .delip_kernel = &delport_kernel,
5233 + .matchip = &matchport,
5234 + .testip = &testport,
5235 + .testip_kernel = &testport_kernel,
5236 + .list_header_size = &list_header_size,
5237 + .list_header = &list_header,
5238 + .list_members_size = &list_members_size,
5239 + .list_members = &list_members,
5240 + .sizeid = &sizeid,
5241 + .me = THIS_MODULE,
5244 +static int __init init(void)
5246 + return ip_set_register_set_type(&ip_set_portmap);
5249 +static void __exit fini(void)
5251 + /* FIXME: possible race with ip_set_create() */
5252 + ip_set_unregister_set_type(&ip_set_portmap);
5257 +MODULE_LICENSE("GPL");
5258 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
5259 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
5260 +++ linux-2.6.3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-02-19 08:47:22.288007614 +0100
5263 + * Strip all IP options in the IP packet header.
5265 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
5266 + * This software is distributed under GNU GPL v2, 1991
5269 +#include <linux/module.h>
5270 +#include <linux/skbuff.h>
5271 +#include <linux/ip.h>
5272 +#include <net/checksum.h>
5274 +#include <linux/netfilter_ipv4/ip_tables.h>
5276 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5277 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
5278 +MODULE_LICENSE("GPL");
5280 +static unsigned int
5281 +target(struct sk_buff **pskb,
5282 + unsigned int hooknum,
5283 + const struct net_device *in,
5284 + const struct net_device *out,
5285 + const void *targinfo,
5288 + struct iphdr *iph = (*pskb)->nh.iph;
5289 + struct sk_buff *skb = (*pskb);
5290 + struct ip_options * opt;
5291 + unsigned char * optiph = skb->nh.raw;
5292 + int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
5295 + /* if no options in packet then nothing to clear. */
5296 + if (iph->ihl * 4 == sizeof(struct iphdr))
5297 + return IPT_CONTINUE;
5299 + /* else clear all options */
5300 + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
5301 + memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
5302 + opt = &(IPCB(skb)->opt);
5306 + skb->nfcache |= NFC_ALTERED;
5308 + return IPT_CONTINUE;
5312 +checkentry(const char *tablename,
5313 + const struct ipt_entry *e,
5315 + unsigned int targinfosize,
5316 + unsigned int hook_mask)
5318 + if (strcmp(tablename, "mangle")) {
5319 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5322 + /* nothing else to check because no parameters */
5326 +static struct ipt_target ipt_ipv4optsstrip_reg
5327 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
5329 +static int __init init(void)
5331 + if (ipt_register_target(&ipt_ipv4optsstrip_reg))
5333 + printk("ipt_IPV4OPTSSTRIP loaded\n");
5338 +static void __exit fini(void)
5340 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
5341 + printk("ipt_IPV4OPTSSTRIP unloaded\n");
5346 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.3/net/ipv4/netfilter/ipt_NETLINK.c
5347 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
5348 +++ linux-2.6.3/net/ipv4/netfilter/ipt_NETLINK.c 2004-02-19 08:47:24.269530314 +0100
5350 +#include <linux/module.h>
5351 +#include <linux/version.h>
5352 +#include <linux/config.h>
5353 +#include <linux/socket.h>
5354 +#include <linux/skbuff.h>
5355 +#include <linux/kernel.h>
5356 +#include <linux/netlink.h>
5357 +#include <linux/netdevice.h>
5358 +#include <linux/mm.h>
5359 +#include <linux/socket.h>
5360 +#include <linux/netfilter_ipv4/ip_tables.h>
5361 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
5362 +#include <net/sock.h>
5364 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
5365 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
5366 +MODULE_LICENSE("GPL");
5369 +#define DEBUGP printk
5371 +#define DEBUGP(format, args...)
5374 +static struct sock *ipfwsk;
5376 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
5377 + unsigned int hooknum,
5378 + const struct net_device *in,
5379 + const struct net_device *out,
5380 + const void *targinfo, void *userinfo)
5382 + struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5383 + struct iphdr *ip = (*pskb)->nh.iph;
5384 + struct sk_buff *outskb;
5385 + struct netlink_t nlhdr;
5388 + /* Allocate a socket buffer */
5389 + if ( MASK(nld->flags, USE_SIZE) )
5390 + len = nld->size+sizeof(nlhdr);
5392 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
5394 + outskb=alloc_skb(len, GFP_ATOMIC);
5399 + if ( MASK(nld->flags, USE_MARK) )
5400 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
5402 + nlhdr.mark=(*pskb)->nfmark;
5404 + if ( in && in->name ) {
5405 + strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
5406 + }else if ( out && out->name ){
5407 + strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
5410 + skb_put(outskb, len);
5411 + memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
5412 + memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
5413 + netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
5415 + if (net_ratelimit())
5416 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
5419 + if ( MASK(nld->flags, USE_DROP) )
5422 + return IPT_CONTINUE;
5425 +static int ipt_netlink_checkentry(const char *tablename,
5426 + const struct ipt_entry *e,
5428 + unsigned int targinfosize,
5429 + unsigned int hookmask)
5431 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5436 +static struct ipt_target ipt_netlink_reg = {
5439 + ipt_netlink_target,
5440 + ipt_netlink_checkentry,
5445 +static int __init init(void)
5447 + DEBUGP("ipt_NETLINK: init module\n");
5449 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
5453 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
5460 +static void __exit fini(void)
5462 + DEBUGP("ipt_NETLINK: cleanup_module\n");
5463 + ipt_unregister_target(&ipt_netlink_reg);
5464 + if(ipfwsk->socket) sock_release(ipfwsk->socket);
5469 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.3/net/ipv4/netfilter/ipt_POOL.c
5470 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
5471 +++ linux-2.6.3/net/ipv4/netfilter/ipt_POOL.c 2004-02-19 08:47:30.712978249 +0100
5473 +/* ipt_POOL.c - netfilter target to manipulate IP pools
5475 + * This target can be used almost everywhere. It acts on some specified
5476 + * IP pool, adding or deleting some IP address in the pool. The address
5477 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
5478 + * of the packet under inspection.
5480 + * The target normally returns IPT_CONTINUE.
5483 +#include <linux/types.h>
5484 +#include <linux/ip.h>
5485 +#include <linux/timer.h>
5486 +#include <linux/module.h>
5487 +#include <linux/netfilter.h>
5488 +#include <linux/netdevice.h>
5489 +#include <linux/if.h>
5490 +#include <linux/inetdevice.h>
5491 +#include <net/protocol.h>
5492 +#include <net/checksum.h>
5493 +#include <linux/netfilter_ipv4.h>
5494 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5495 +#include <linux/netfilter_ipv4/ipt_pool.h>
5498 +#define DEBUGP printk
5500 +#define DEBUGP(format, args...)
5503 +/*** NOTE NOTE NOTE NOTE ***
5505 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
5506 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
5507 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
5508 +** is modified for the source IP address of the packet under inspection.
5509 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
5511 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
5512 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
5514 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
5515 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
5516 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
5517 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
5521 +do_check(const char *tablename,
5522 + const struct ipt_entry *e,
5524 + unsigned int targinfosize,
5525 + unsigned int hook_mask)
5527 + const struct ipt_pool_info *ipi = targinfo;
5529 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
5530 + DEBUGP("POOL_check: size %u.\n", targinfosize);
5533 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
5537 +static unsigned int
5538 +do_target(struct sk_buff **pskb,
5539 + unsigned int hooknum,
5540 + const struct net_device *in,
5541 + const struct net_device *out,
5542 + const void *targinfo,
5545 + const struct ipt_pool_info *ipi = targinfo;
5547 + unsigned int verdict = IPT_CONTINUE;
5549 + if (ipi->src != IP_POOL_NONE) {
5550 + modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
5551 + ipi->flags & IPT_POOL_DEL_SRC);
5552 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
5553 + if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
5554 + verdict = NF_ACCEPT;
5555 + else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
5556 + verdict = NF_DROP;
5559 + if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
5560 + modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
5561 + ipi->flags & IPT_POOL_DEL_DST);
5562 + if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
5563 + if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
5564 + verdict = NF_ACCEPT;
5565 + else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
5566 + verdict = NF_DROP;
5572 +static struct ipt_target pool_reg
5573 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
5575 +static int __init init(void)
5577 + DEBUGP("init ipt_POOL\n");
5578 + return ipt_register_target(&pool_reg);
5581 +static void __exit fini(void)
5583 + DEBUGP("fini ipt_POOL\n");
5584 + ipt_unregister_target(&pool_reg);
5589 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_SET.c linux-2.6.3/net/ipv4/netfilter/ipt_SET.c
5590 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
5591 +++ linux-2.6.3/net/ipv4/netfilter/ipt_SET.c 2004-02-09 15:02:00.000000000 +0100
5593 +/* ipt_SET.c - netfilter target to manipulate IP sets
5595 + * This target can be used almost everywhere. It acts on some specified
5596 + * IP set, adding or deleting some IP addresses/ports in the set.
5597 + * The addresses/ports can be either the source, or destination
5598 + * of the packet under inspection.
5602 +#include <linux/types.h>
5603 +#include <linux/ip.h>
5604 +#include <linux/timer.h>
5605 +#include <linux/module.h>
5606 +#include <linux/netfilter.h>
5607 +#include <linux/netdevice.h>
5608 +#include <linux/if.h>
5609 +#include <linux/inetdevice.h>
5610 +#include <net/protocol.h>
5611 +#include <net/checksum.h>
5612 +#include <linux/netfilter_ipv4.h>
5613 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
5614 +#include <linux/netfilter_ipv4/ipt_set.h>
5616 +static unsigned int
5617 +target(struct sk_buff **pskb,
5618 + unsigned int hooknum,
5619 + const struct net_device *in,
5620 + const struct net_device *out,
5621 + const void *targinfo,
5624 + const struct ipt_set_info_target *info = targinfo;
5626 + if (info->add_set.id >= 0)
5627 + ip_set_addip_kernel(ip_set_list[info->add_set.id],
5629 + info->add_set.flags,
5630 + info->add_set.set_level,
5631 + info->add_set.ip_level);
5632 + if (info->del_set.id >= 0)
5633 + ip_set_delip_kernel(ip_set_list[info->del_set.id],
5635 + info->del_set.flags,
5636 + info->del_set.set_level,
5637 + info->del_set.ip_level);
5639 + return IPT_CONTINUE;
5643 +checkentry(const char *tablename,
5644 + const struct ipt_entry *e,
5646 + unsigned int targinfosize, unsigned int hook_mask)
5648 + struct ipt_set_info_target *info = targinfo;
5650 + if (targinfosize != IPT_ALIGN(sizeof(*info))) {
5651 + DP("bad target info size %u", targinfosize);
5655 + if (info->add_set.id >= 0
5656 + && !ip_set_get_byid(info->add_set.id)) {
5657 + ip_set_printk("cannot verify add_set id %i as target",
5658 + info->add_set.id);
5659 + return 0; /* error */
5661 + if (info->del_set.id >= 0
5662 + && !ip_set_get_byid(info->del_set.id)) {
5663 + ip_set_printk("cannot verify del_set id %i as target",
5664 + info->del_set.id);
5665 + return 0; /* error */
5667 + DP("checkentry OK");
5672 +static void destroy(void *targetinfo, unsigned int targetsize)
5674 + struct ipt_set_info_target *info = targetinfo;
5676 + if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
5677 + ip_set_printk("invalid targetsize %d", targetsize);
5681 + if (info->add_set.id >= 0)
5682 + ip_set_put(ip_set_list[info->add_set.id]);
5683 + if (info->del_set.id >= 0)
5684 + ip_set_put(ip_set_list[info->del_set.id]);
5687 +static struct ipt_target SET_target = {
5690 + .checkentry = checkentry,
5691 + .destroy = destroy,
5695 +static int __init init(void)
5697 + return ipt_register_target(&SET_target);
5700 +static void __exit fini(void)
5702 + ipt_unregister_target(&SET_target);
5707 +MODULE_LICENSE("GPL");
5708 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.3/net/ipv4/netfilter/ipt_TTL.c
5709 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
5710 +++ linux-2.6.3/net/ipv4/netfilter/ipt_TTL.c 2004-02-19 08:47:25.605208582 +0100
5712 +/* TTL modification target for IP tables
5713 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
5717 + * This software is distributed under the terms of GNU GPL
5720 +#include <linux/module.h>
5721 +#include <linux/skbuff.h>
5722 +#include <linux/ip.h>
5723 +#include <net/checksum.h>
5725 +#include <linux/netfilter_ipv4/ip_tables.h>
5726 +#include <linux/netfilter_ipv4/ipt_TTL.h>
5728 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
5729 +MODULE_DESCRIPTION("IP tables TTL modification module");
5730 +MODULE_LICENSE("GPL");
5732 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
5733 + const struct net_device *in, const struct net_device *out,
5734 + const void *targinfo, void *userinfo)
5736 + struct iphdr *iph = (*pskb)->nh.iph;
5737 + const struct ipt_TTL_info *info = targinfo;
5738 + u_int16_t diffs[2];
5741 + switch (info->mode) {
5743 + new_ttl = info->ttl;
5746 + new_ttl = iph->ttl + info->ttl;
5747 + if (new_ttl > 255)
5751 + new_ttl = iph->ttl + info->ttl;
5756 + new_ttl = iph->ttl;
5760 + if (new_ttl != iph->ttl) {
5761 + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
5762 + iph->ttl = new_ttl;
5763 + diffs[1] = htons(((unsigned)iph->ttl) << 8);
5764 + iph->check = csum_fold(csum_partial((char *)diffs,
5766 + iph->check^0xFFFF));
5767 + (*pskb)->nfcache |= NFC_ALTERED;
5770 + return IPT_CONTINUE;
5773 +static int ipt_ttl_checkentry(const char *tablename,
5774 + const struct ipt_entry *e,
5776 + unsigned int targinfosize,
5777 + unsigned int hook_mask)
5779 + struct ipt_TTL_info *info = targinfo;
5781 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
5782 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
5784 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
5788 + if (strcmp(tablename, "mangle")) {
5789 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5793 + if (info->mode > IPT_TTL_MAXMODE) {
5794 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
5799 + if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
5800 + printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
5807 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
5808 + ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
5810 +static int __init init(void)
5812 + return ipt_register_target(&ipt_TTL);
5815 +static void __exit fini(void)
5817 + ipt_unregister_target(&ipt_TTL);
5822 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.3/net/ipv4/netfilter/ipt_connlimit.c
5823 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
5824 +++ linux-2.6.3/net/ipv4/netfilter/ipt_connlimit.c 2004-02-19 08:47:26.593970414 +0100
5827 + * netfilter module to limit the number of parallel tcp
5828 + * connections per IP address.
5829 + * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
5830 + * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
5831 + * only ignore TIME_WAIT or gone connections
5835 + * Kernel module to match connection tracking information.
5836 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
5838 +#include <linux/module.h>
5839 +#include <linux/skbuff.h>
5840 +#include <linux/list.h>
5841 +#include <linux/netfilter_ipv4/ip_conntrack.h>
5842 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5843 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
5844 +#include <linux/netfilter_ipv4/ip_tables.h>
5845 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
5849 +MODULE_LICENSE("GPL");
5851 +/* we'll save the tuples of all connections we care about */
5852 +struct ipt_connlimit_conn
5854 + struct list_head list;
5855 + struct ip_conntrack_tuple tuple;
5858 +struct ipt_connlimit_data {
5860 + struct list_head iphash[256];
5863 +static int ipt_iphash(u_int32_t addr)
5867 + hash = addr & 0xff;
5868 + hash ^= (addr >> 8) & 0xff;
5869 + hash ^= (addr >> 16) & 0xff;
5870 + hash ^= (addr >> 24) & 0xff;
5874 +static int count_them(struct ipt_connlimit_data *data,
5875 + u_int32_t addr, u_int32_t mask,
5876 + struct ip_conntrack *ct)
5879 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
5880 + "fin_wait", "time_wait", "close", "close_wait",
5881 + "last_ack", "listen" };
5883 + int addit = 1, matches = 0;
5884 + struct ip_conntrack_tuple tuple;
5885 + struct ip_conntrack_tuple_hash *found;
5886 + struct ipt_connlimit_conn *conn;
5887 + struct list_head *hash,*lh;
5889 + spin_lock(&data->lock);
5890 + tuple = ct->tuplehash[0].tuple;
5891 + hash = &data->iphash[ipt_iphash(addr & mask)];
5893 + /* check the saved connections */
5894 + for (lh = hash->next; lh != hash; lh = lh->next) {
5895 + conn = list_entry(lh,struct ipt_connlimit_conn,list);
5896 + found = ip_conntrack_find_get(&conn->tuple,ct);
5897 + if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
5899 + found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
5900 + /* Just to be sure we have it only once in the list.
5901 + We should'nt see tuples twice unless someone hooks this
5902 + into a table without "-p tcp --syn" */
5906 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
5907 + ipt_iphash(addr & mask),
5908 + NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
5909 + NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
5910 + (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
5912 + if (NULL == found) {
5913 + /* this one is gone */
5915 + list_del(lh->next);
5919 + if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
5920 + /* we don't care about connections which are
5921 + closed already -> ditch it */
5923 + list_del(lh->next);
5925 + nf_conntrack_put(&found->ctrack->infos[0]);
5928 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
5929 + /* same source IP address -> be counted! */
5932 + nf_conntrack_put(&found->ctrack->infos[0]);
5935 + /* save the new connection in our list */
5937 + printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
5938 + ipt_iphash(addr & mask),
5939 + NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
5940 + NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
5942 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
5945 + memset(conn,0,sizeof(*conn));
5946 + INIT_LIST_HEAD(&conn->list);
5947 + conn->tuple = tuple;
5948 + list_add(&conn->list,hash);
5951 + spin_unlock(&data->lock);
5956 +match(const struct sk_buff *skb,
5957 + const struct net_device *in,
5958 + const struct net_device *out,
5959 + const void *matchinfo,
5962 + u_int16_t datalen,
5965 + const struct ipt_connlimit_info *info = matchinfo;
5966 + int connections, match;
5967 + struct ip_conntrack *ct;
5968 + enum ip_conntrack_info ctinfo;
5970 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
5972 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
5976 + connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
5977 + if (-1 == connections) {
5978 + printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
5979 + *hotdrop = 1; /* let's free some memory :-) */
5982 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
5984 + printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
5985 + "connections=%d limit=%d match=%s\n",
5986 + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
5987 + connections, info->limit, match ? "yes" : "no");
5993 +static int check(const char *tablename,
5994 + const struct ipt_ip *ip,
5996 + unsigned int matchsize,
5997 + unsigned int hook_mask)
5999 + struct ipt_connlimit_info *info = matchinfo;
6003 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
6006 + /* refuse anything but tcp */
6007 + if (ip->proto != IPPROTO_TCP)
6010 + /* init private data */
6011 + info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
6012 + spin_lock_init(&(info->data->lock));
6013 + for (i = 0; i < 256; i++)
6014 + INIT_LIST_HEAD(&(info->data->iphash[i]));
6019 +static void destroy(void *matchinfo, unsigned int matchinfosize)
6021 + struct ipt_connlimit_info *info = matchinfo;
6022 + struct ipt_connlimit_conn *conn;
6023 + struct list_head *hash;
6027 + for (i = 0; i < 256; i++) {
6028 + hash = &(info->data->iphash[i]);
6029 + while (hash != hash->next) {
6030 + conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
6031 + list_del(hash->next);
6035 + kfree(info->data);
6038 +static struct ipt_match connlimit_match
6039 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
6041 +static int __init init(void)
6043 + /* NULL if ip_conntrack not a module */
6044 + if (ip_conntrack_module)
6045 + __MOD_INC_USE_COUNT(ip_conntrack_module);
6046 + return ipt_register_match(&connlimit_match);
6049 +static void __exit fini(void)
6051 + ipt_unregister_match(&connlimit_match);
6052 + if (ip_conntrack_module)
6053 + __MOD_DEC_USE_COUNT(ip_conntrack_module);
6058 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.3/net/ipv4/netfilter/ipt_dstlimit.c
6059 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
6060 +++ linux-2.6.3/net/ipv4/netfilter/ipt_dstlimit.c 2004-02-19 08:47:27.235815809 +0100
6062 +/* iptables match extension to limit the number of packets per second
6063 + * seperately for each destination.
6065 + * (C) 2003 by Harald Welte <laforge@netfilter.org>
6069 + * Development of this code was funded by Astaro AG, http://www.astaro.com/
6071 + * based on ipt_limit.c by:
6072 + * Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
6073 + * Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr>
6074 + * Rusty Russell <rusty@rustcorp.com.au>
6076 + * The general idea is to create a hash table for every dstip and have a
6077 + * seperate limit counter per tuple. This way you can do something like 'limit
6078 + * the number of syn packets for each of my internal addresses.
6080 + * Ideally this would just be implemented as a general 'hash' match, which would
6081 + * allow us to attach any iptables target to it's hash buckets. But this is
6082 + * not possible in the current iptables architecture. As always, pkttables for
6083 + * 2.7.x will help ;)
6085 +#include <linux/module.h>
6086 +#include <linux/skbuff.h>
6087 +#include <linux/spinlock.h>
6088 +#include <linux/random.h>
6089 +#include <linux/jhash.h>
6090 +#include <linux/slab.h>
6091 +#include <linux/vmalloc.h>
6092 +#include <linux/tcp.h>
6093 +#include <linux/udp.h>
6094 +#include <linux/proc_fs.h>
6095 +#include <linux/seq_file.h>
6097 +#define ASSERT_READ_LOCK(x)
6098 +#define ASSERT_WRITE_LOCK(x)
6099 +#include <linux/netfilter_ipv4/lockhelp.h>
6100 +#include <linux/netfilter_ipv4/listhelp.h>
6102 +#include <linux/netfilter_ipv4/ip_tables.h>
6103 +#include <linux/netfilter_ipv4/ipt_dstlimit.h>
6105 +/* FIXME: this is just for IP_NF_ASSERRT */
6106 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6108 +#define MS2JIFFIES(x) ((x*HZ)/1000)
6110 +MODULE_LICENSE("GPL");
6111 +MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
6112 +MODULE_DESCRIPTION("iptables match for limiting per destination");
6114 +/* need to declare this at the top */
6115 +static struct proc_dir_entry *dstlimit_procdir;
6116 +static struct file_operations dl_file_ops;
6118 +/* hash table crap */
6120 +struct dsthash_dst {
6126 +struct dsthash_ent {
6127 + /* static / read-only parts in the beginning */
6128 + struct list_head list;
6129 + struct dsthash_dst dst;
6131 + /* modified structure members in the end */
6132 + unsigned long expires; /* precalculated expiry time */
6134 + unsigned long prev; /* last modification */
6136 + u_int32_t credit_cap, cost;
6140 +struct ipt_dstlimit_htable {
6141 + struct list_head list; /* global list of all htables */
6144 + struct dstlimit_cfg cfg; /* config */
6146 + /* used internally */
6147 + spinlock_t lock; /* lock for list_head */
6148 + u_int32_t rnd; /* random seed for hash */
6149 + struct timer_list timer; /* timer for gc */
6150 + atomic_t count; /* number entries in table */
6152 + /* seq_file stuff */
6153 + struct proc_dir_entry *pde;
6155 + struct list_head hash[0]; /* hashtable itself */
6158 +DECLARE_RWLOCK(dstlimit_lock); /* protects htables list */
6159 +static LIST_HEAD(dstlimit_htables);
6160 +static kmem_cache_t *dstlimit_cachep;
6162 +static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
6164 + return (ent->dst.dst_ip == b->dst_ip
6165 + && ent->dst.port == b->port
6166 + && ent->dst.src_ip == b->src_ip);
6169 +static inline u_int32_t
6170 +hash_dst(const struct ipt_dstlimit_htable *ht, const struct dsthash_dst *dst)
6172 + return (jhash_3words(dst->dst_ip, dst->port,
6173 + dst->src_ip, ht->rnd) % ht->cfg.size);
6176 +static inline struct dsthash_ent *
6177 +__dsthash_find(const struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
6179 + struct dsthash_ent *ent;
6180 + u_int32_t hash = hash_dst(ht, dst);
6181 + MUST_BE_LOCKED(&ht->lock);
6182 + ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
6186 +/* allocate dsthash_ent, initialize dst, put in htable and lock it */
6187 +static struct dsthash_ent *
6188 +__dsthash_alloc_init(struct ipt_dstlimit_htable *ht, struct dsthash_dst *dst)
6190 + struct dsthash_ent *ent;
6192 + /* initialize hash with random val at the time we allocate
6193 + * the first hashtable entry */
6195 + get_random_bytes(&ht->rnd, 4);
6197 + if (ht->cfg.max &&
6198 + atomic_read(&ht->count) >= ht->cfg.max) {
6199 + /* FIXME: do something. question is what.. */
6200 + if (net_ratelimit())
6201 + printk(KERN_WARNING
6202 + "ipt_dstlimit: max count of %u reached\n",
6207 + ent = kmem_cache_alloc(dstlimit_cachep, GFP_ATOMIC);
6209 + if (net_ratelimit())
6211 + "ipt_dstlimit: can't allocate dsthash_ent\n");
6215 + atomic_inc(&ht->count);
6217 + ent->dst.dst_ip = dst->dst_ip;
6218 + ent->dst.port = dst->port;
6219 + ent->dst.src_ip = dst->src_ip;
6221 + list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
6227 +__dsthash_free(struct ipt_dstlimit_htable *ht, struct dsthash_ent *ent)
6229 + MUST_BE_LOCKED(&ht->lock);
6231 + list_del(&ent->list);
6232 + kmem_cache_free(dstlimit_cachep, ent);
6233 + atomic_dec(&ht->count);
6235 +static void htable_gc(unsigned long htlong);
6237 +static int htable_create(struct ipt_dstlimit_info *minfo)
6240 + unsigned int size;
6241 + struct ipt_dstlimit_htable *hinfo;
6243 + if (minfo->cfg.size)
6244 + size = minfo->cfg.size;
6246 + size = (((num_physpages << PAGE_SHIFT) / 16384)
6247 + / sizeof(struct list_head));
6248 + if (num_physpages > (1024 * 1024 * 1024 / PAGE_SIZE))
6253 + /* FIXME: don't use vmalloc() here or anywhere else -HW */
6254 + hinfo = vmalloc(sizeof(struct ipt_dstlimit_htable)
6255 + + (sizeof(struct list_head) * size));
6257 + printk(KERN_ERR "ipt_dstlimit: Unable to create hashtable\n");
6260 + minfo->hinfo = hinfo;
6262 + /* copy match config into hashtable config */
6263 + memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
6264 + hinfo->cfg.size = size;
6265 + if (!hinfo->cfg.max)
6266 + hinfo->cfg.max = 8 * hinfo->cfg.size;
6267 + else if (hinfo->cfg.max < hinfo->cfg.size)
6268 + hinfo->cfg.max = hinfo->cfg.size;
6270 + for (i = 0; i < hinfo->cfg.size; i++)
6271 + INIT_LIST_HEAD(&hinfo->hash[i]);
6273 + atomic_set(&hinfo->count, 0);
6274 + atomic_set(&hinfo->use, 1);
6276 + hinfo->lock = SPIN_LOCK_UNLOCKED;
6277 + hinfo->pde = create_proc_entry(minfo->name, 0, dstlimit_procdir);
6278 + if (!hinfo->pde) {
6282 + hinfo->pde->proc_fops = &dl_file_ops;
6283 + hinfo->pde->data = hinfo;
6285 + init_timer(&hinfo->timer);
6286 + hinfo->timer.expires = jiffies + MS2JIFFIES(hinfo->cfg.gc_interval);
6287 + hinfo->timer.data = (unsigned long )hinfo;
6288 + hinfo->timer.function = htable_gc;
6289 + add_timer(&hinfo->timer);
6291 + WRITE_LOCK(&dstlimit_lock);
6292 + list_add(&hinfo->list, &dstlimit_htables);
6293 + WRITE_UNLOCK(&dstlimit_lock);
6298 +static int select_all(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
6303 +static int select_gc(struct ipt_dstlimit_htable *ht, struct dsthash_ent *he)
6305 + return (jiffies >= he->expires);
6308 +static void htable_selective_cleanup(struct ipt_dstlimit_htable *ht,
6309 + int (*select)(struct ipt_dstlimit_htable *ht,
6310 + struct dsthash_ent *he))
6314 + IP_NF_ASSERT(ht->cfg.size && ht->cfg.max);
6316 + /* lock hash table and iterate over it */
6317 + LOCK_BH(&ht->lock);
6318 + for (i = 0; i < ht->cfg.size; i++) {
6319 + struct dsthash_ent *dh, *n;
6320 + list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
6321 + if ((*select)(ht, dh))
6322 + __dsthash_free(ht, dh);
6325 + UNLOCK_BH(&ht->lock);
6328 +/* hash table garbage collector, run by timer */
6329 +static void htable_gc(unsigned long htlong)
6331 + struct ipt_dstlimit_htable *ht = (struct ipt_dstlimit_htable *)htlong;
6333 + htable_selective_cleanup(ht, select_gc);
6335 + /* re-add the timer accordingly */
6336 + ht->timer.expires = jiffies + MS2JIFFIES(ht->cfg.gc_interval);
6337 + add_timer(&ht->timer);
6340 +static void htable_destroy(struct ipt_dstlimit_htable *hinfo)
6342 + /* remove timer, if it is pending */
6343 + if (timer_pending(&hinfo->timer))
6344 + del_timer(&hinfo->timer);
6346 + /* remove proc entry */
6347 + remove_proc_entry(hinfo->pde->name, dstlimit_procdir);
6349 + htable_selective_cleanup(hinfo, select_all);
6353 +static struct ipt_dstlimit_htable *htable_find_get(char *name)
6355 + struct ipt_dstlimit_htable *hinfo;
6357 + READ_LOCK(&dstlimit_lock);
6358 + list_for_each_entry(hinfo, &dstlimit_htables, list) {
6359 + if (!strcmp(name, hinfo->pde->name)) {
6360 + atomic_inc(&hinfo->use);
6361 + READ_UNLOCK(&dstlimit_lock);
6365 + READ_UNLOCK(&dstlimit_lock);
6370 +static void htable_put(struct ipt_dstlimit_htable *hinfo)
6372 + if (atomic_dec_and_test(&hinfo->use)) {
6373 + WRITE_LOCK(&dstlimit_lock);
6374 + list_del(&hinfo->list);
6375 + WRITE_UNLOCK(&dstlimit_lock);
6376 + htable_destroy(hinfo);
6381 +/* The algorithm used is the Simple Token Bucket Filter (TBF)
6382 + * see net/sched/sch_tbf.c in the linux source tree
6385 +/* Rusty: This is my (non-mathematically-inclined) understanding of
6386 + this algorithm. The `average rate' in jiffies becomes your initial
6387 + amount of credit `credit' and the most credit you can ever have
6388 + `credit_cap'. The `peak rate' becomes the cost of passing the
6391 + `prev' tracks the last packet hit: you gain one credit per jiffy.
6392 + If you get credit balance more than this, the extra credit is
6393 + discarded. Every time the match passes, you lose `cost' credits;
6394 + if you don't have that many, the test fails.
6396 + See Alexey's formal explanation in net/sched/sch_tbf.c.
6398 + To get the maximum range, we multiply by this factor (ie. you get N
6399 + credits per jiffy). We want to allow a rate as low as 1 per day
6400 + (slowest userspace tool allows), which means
6401 + CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
6403 +#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
6405 +/* Repeated shift and or gives us all 1s, final shift and add 1 gives
6406 + * us the power of 2 below the theoretical max, so GCC simply does a
6408 +#define _POW2_BELOW2(x) ((x)|((x)>>1))
6409 +#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
6410 +#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
6411 +#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
6412 +#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
6413 +#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
6415 +#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
6417 +/* Precision saver. */
6418 +static inline u_int32_t
6419 +user2credits(u_int32_t user)
6421 + /* If multiplying would overflow... */
6422 + if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
6423 + /* Divide first. */
6424 + return (user / IPT_DSTLIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
6426 + return (user * HZ * CREDITS_PER_JIFFY) / IPT_DSTLIMIT_SCALE;
6429 +static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
6431 + dh->rateinfo.credit += (now - xchg(&dh->rateinfo.prev, now))
6432 + * CREDITS_PER_JIFFY;
6433 + if (dh->rateinfo.credit > dh->rateinfo.credit_cap)
6434 + dh->rateinfo.credit = dh->rateinfo.credit_cap;
6438 +dstlimit_match(const struct sk_buff *skb,
6439 + const struct net_device *in,
6440 + const struct net_device *out,
6441 + const void *matchinfo,
6444 + u_int16_t datalen,
6447 + struct ipt_dstlimit_info *r =
6448 + ((struct ipt_dstlimit_info *)matchinfo)->u.master;
6449 + struct ipt_dstlimit_htable *hinfo = r->hinfo;
6450 + unsigned long now = jiffies;
6451 + struct dsthash_ent *dh;
6452 + struct dsthash_dst dst;
6454 + memset(&dst, 0, sizeof(dst));
6456 + /* dest ip is always in hash */
6457 + dst.dst_ip = skb->nh.iph->daddr;
6459 + /* source ip only if respective hashmode, otherwise set to
6461 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_SIP)
6462 + dst.src_ip = skb->nh.iph->saddr;
6464 + /* dest port only if respective mode */
6465 + if (hinfo->cfg.mode & IPT_DSTLIMIT_HASH_DPT) {
6466 + switch (skb->nh.iph->protocol) {
6467 + struct tcphdr *th;
6468 + struct udphdr *uh;
6470 + th = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
6471 + dst.port = th->dest;
6474 + uh = (void *)skb->nh.iph+skb->nh.iph->ihl*4;
6475 + dst.port = uh->dest;
6482 + LOCK_BH(&hinfo->lock);
6483 + dh = __dsthash_find(hinfo, &dst);
6485 + dh = __dsthash_alloc_init(hinfo, &dst);
6488 + /* enomem... don't match == DROP */
6489 + if (net_ratelimit())
6490 + printk(KERN_ERR "%s: ENOMEM\n", __FUNCTION__);
6491 + UNLOCK_BH(&hinfo->lock);
6495 + dh->expires = jiffies + MS2JIFFIES(hinfo->cfg.expire);
6497 + dh->rateinfo.prev = jiffies;
6498 + dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
6499 + hinfo->cfg.burst);
6500 + dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
6501 + hinfo->cfg.burst);
6502 + dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
6504 + UNLOCK_BH(&hinfo->lock);
6508 + /* update expiration timeout */
6509 + dh->expires = now + MS2JIFFIES(hinfo->cfg.expire);
6511 + rateinfo_recalc(dh, now);
6512 + if (dh->rateinfo.credit >= dh->rateinfo.cost) {
6513 + /* We're underlimit. */
6514 + dh->rateinfo.credit -= dh->rateinfo.cost;
6515 + UNLOCK_BH(&hinfo->lock);
6519 + UNLOCK_BH(&hinfo->lock);
6521 + /* default case: we're overlimit, thus don't match */
6526 +dstlimit_checkentry(const char *tablename,
6527 + const struct ipt_ip *ip,
6529 + unsigned int matchsize,
6530 + unsigned int hook_mask)
6532 + struct ipt_dstlimit_info *r = matchinfo;
6534 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_dstlimit_info)))
6537 + /* Check for overflow. */
6538 + if (r->cfg.burst == 0
6539 + || user2credits(r->cfg.avg * r->cfg.burst) <
6540 + user2credits(r->cfg.avg)) {
6541 + printk(KERN_ERR "ipt_dstlimit: Overflow, try lower: %u/%u\n",
6542 + r->cfg.avg, r->cfg.burst);
6546 + if (r->cfg.mode == 0
6547 + || r->cfg.mode > (IPT_DSTLIMIT_HASH_DPT
6548 + |IPT_DSTLIMIT_HASH_DIP
6549 + |IPT_DSTLIMIT_HASH_SIP))
6552 + if (!r->cfg.gc_interval)
6555 + if (!r->cfg.expire)
6558 + r->hinfo = htable_find_get(r->name);
6559 + if (!r->hinfo && (htable_create(r) != 0)) {
6563 + /* Ugly hack: For SMP, we only want to use one set */
6570 +dstlimit_destroy(void *matchinfo, unsigned int matchsize)
6572 + struct ipt_dstlimit_info *r = (struct ipt_dstlimit_info *) matchinfo;
6574 + htable_put(r->hinfo);
6577 +static struct ipt_match ipt_dstlimit = {
6578 + .list = { .prev = NULL, .next = NULL },
6579 + .name = "dstlimit",
6580 + .match = dstlimit_match,
6581 + .checkentry = dstlimit_checkentry,
6582 + .destroy = dstlimit_destroy,
6588 +static void *dl_seq_start(struct seq_file *s, loff_t *pos)
6590 + struct proc_dir_entry *pde = s->private;
6591 + struct ipt_dstlimit_htable *htable = pde->data;
6592 + unsigned int *bucket;
6594 + LOCK_BH(&htable->lock);
6595 + if (*pos >= htable->cfg.size)
6598 + bucket = kmalloc(sizeof(unsigned int), GFP_KERNEL);
6600 + return ERR_PTR(-ENOMEM);
6606 +static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
6608 + struct proc_dir_entry *pde = s->private;
6609 + struct ipt_dstlimit_htable *htable = pde->data;
6610 + unsigned int *bucket = (unsigned int *)v;
6612 + *pos = ++(*bucket);
6613 + if (*pos >= htable->cfg.size) {
6620 +static void dl_seq_stop(struct seq_file *s, void *v)
6622 + struct proc_dir_entry *pde = s->private;
6623 + struct ipt_dstlimit_htable *htable = pde->data;
6624 + unsigned int *bucket = (unsigned int *)v;
6628 + UNLOCK_BH(&htable->lock);
6631 +static inline int dl_seq_real_show(struct dsthash_ent *ent, struct seq_file *s)
6633 + /* recalculate to show accurate numbers */
6634 + rateinfo_recalc(ent, jiffies);
6636 + return seq_printf(s, "%ld %u.%u.%u.%u->%u.%u.%u.%u:%u %u %u %u\n",
6637 + (ent->expires - jiffies)/HZ,
6638 + NIPQUAD(ent->dst.src_ip),
6639 + NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.port),
6640 + ent->rateinfo.credit, ent->rateinfo.credit_cap,
6641 + ent->rateinfo.cost);
6644 +static int dl_seq_show(struct seq_file *s, void *v)
6646 + struct proc_dir_entry *pde = s->private;
6647 + struct ipt_dstlimit_htable *htable = pde->data;
6648 + unsigned int *bucket = (unsigned int *)v;
6650 + if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
6651 + struct dsthash_ent *, s)) {
6652 + /* buffer was filled and unable to print that tuple */
6658 +static struct seq_operations dl_seq_ops = {
6659 + .start = dl_seq_start,
6660 + .next = dl_seq_next,
6661 + .stop = dl_seq_stop,
6662 + .show = dl_seq_show
6665 +static int dl_proc_open(struct inode *inode, struct file *file)
6667 + int ret = seq_open(file, &dl_seq_ops);
6670 + struct seq_file *sf = file->private_data;
6671 + sf->private = PDE(inode);
6676 +static struct file_operations dl_file_ops = {
6677 + .owner = THIS_MODULE,
6678 + .open = dl_proc_open,
6680 + .llseek = seq_lseek,
6681 + .release = seq_release
6684 +static int init_or_fini(int fini)
6691 + if (ipt_register_match(&ipt_dstlimit)) {
6693 + goto cleanup_nothing;
6696 + /* FIXME: do we really want HWCACHE_ALIGN since our objects are
6697 + * quite small ? */
6698 + dstlimit_cachep = kmem_cache_create("ipt_dstlimit",
6699 + sizeof(struct dsthash_ent), 0,
6700 + SLAB_HWCACHE_ALIGN, NULL, NULL);
6701 + if (!dstlimit_cachep) {
6702 + printk(KERN_ERR "Unable to create ipt_dstlimit slab cache\n");
6704 + goto cleanup_unreg_match;
6707 + dstlimit_procdir = proc_mkdir("ipt_dstlimit", proc_net);
6708 + if (!dstlimit_procdir) {
6709 + printk(KERN_ERR "Unable to create proc dir entry\n");
6711 + goto cleanup_free_slab;
6717 + remove_proc_entry("ipt_dstlimit", proc_net);
6719 + kmem_cache_destroy(dstlimit_cachep);
6720 +cleanup_unreg_match:
6721 + ipt_unregister_match(&ipt_dstlimit);
6727 +static int __init init(void)
6729 + return init_or_fini(0);
6732 +static void __exit fini(void)
6739 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.6.3/net/ipv4/netfilter/ipt_fuzzy.c
6740 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
6741 +++ linux-2.6.3/net/ipv4/netfilter/ipt_fuzzy.c 2004-02-19 08:47:27.855666503 +0100
6744 + * This module implements a simple TSK FLC
6745 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
6746 + * to limit , in an adaptive and flexible way , the packet rate crossing
6747 + * a given stream . It serves as an initial and very simple (but effective)
6748 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
6749 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
6750 + * into our code in a precise , adaptive and efficient manner.
6751 + * The goal is very similar to that of "limit" match , but using techniques of
6752 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
6753 + * avoiding over and undershoots - and stuff like that .
6756 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
6757 + * 2002-08-17 : Changed to eliminate floating point operations .
6758 + * 2002-08-23 : Coding style changes .
6761 +#include <linux/module.h>
6762 +#include <linux/skbuff.h>
6763 +#include <linux/ip.h>
6764 +#include <linux/random.h>
6765 +#include <net/tcp.h>
6766 +#include <linux/spinlock.h>
6767 +#include <linux/netfilter_ipv4/ip_tables.h>
6768 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
6771 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
6772 + Expressed in percentage
6775 +#define PAR_LOW 1/100
6778 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
6780 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
6781 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
6782 +MODULE_LICENSE("GPL");
6784 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6786 + if (tx >= maxi) return 100;
6788 + if (tx <= mini) return 0;
6790 + return ( (100*(tx-mini)) / (maxi-mini) ) ;
6793 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
6795 + if (tx <= mini) return 100;
6797 + if (tx >= maxi) return 0;
6799 + return ( (100*( maxi - tx )) / ( maxi - mini ) ) ;
6804 +ipt_fuzzy_match(const struct sk_buff *pskb,
6805 + const struct net_device *in,
6806 + const struct net_device *out,
6807 + const void *matchinfo,
6810 + u_int16_t datalen,
6813 + /* From userspace */
6815 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
6817 + u_int8_t random_number;
6818 + unsigned long amount ;
6819 + u_int8_t howhigh , howlow ;
6822 + spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
6824 + info->bytes_total += pskb->len ;
6825 + info->packets_total++ ;
6827 + info->present_time = jiffies ;
6829 + if ( info->present_time >= info->previous_time )
6830 + amount = info->present_time - info->previous_time ;
6832 + /* There was a transition : I choose to re-sample
6833 + and keep the old acceptance rate...
6837 + info->previous_time = info->present_time ;
6838 + info->bytes_total = info->packets_total = 0;
6841 + if ( amount > HZ/10 ) /* More than 100 ms elapsed ... */
6844 + info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total ) \
6847 + info->previous_time = info->present_time ;
6848 + info->bytes_total = info->packets_total = 0 ;
6850 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
6851 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
6853 + info->acceptance_rate = (u_int8_t) \
6854 + ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
6856 + /* In fact , the above defuzzification would require a denominator
6857 + proportional to (howhigh+howlow) but , in this particular case ,
6858 + that expression is constant .
6859 + An imediate consequence is that it isn't necessary to call
6860 + both mf_high and mf_low - but to keep things understandable ,
6866 + spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
6869 + if ( info->acceptance_rate < 100 )
6871 + get_random_bytes((void *)(&random_number), 1);
6873 + /* If within the acceptance , it can pass => don't match */
6874 + if ( random_number <= (255 * info->acceptance_rate) / 100 )
6877 + return 1; /* It can't pass ( It matches ) */
6880 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
6885 +ipt_fuzzy_checkentry(const char *tablename,
6886 + const struct ipt_ip *e,
6888 + unsigned int matchsize,
6889 + unsigned int hook_mask)
6892 + const struct ipt_fuzzy_info *info = matchinfo;
6894 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
6895 + printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
6896 + IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
6900 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
6901 + || (info->minimum_rate >= info->maximum_rate ))
6903 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
6910 +static struct ipt_match ipt_fuzzy_reg = {
6914 + ipt_fuzzy_checkentry,
6918 +static int __init init(void)
6920 + if (ipt_register_match(&ipt_fuzzy_reg))
6926 +static void __exit fini(void)
6928 + ipt_unregister_match(&ipt_fuzzy_reg);
6933 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.6.3/net/ipv4/netfilter/ipt_ipv4options.c
6934 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_ipv4options.c 1970-01-01 01:00:00.000000000 +0100
6935 +++ linux-2.6.3/net/ipv4/netfilter/ipt_ipv4options.c 2004-02-19 08:47:28.441525384 +0100
6938 + This is a module which is used to match ipv4 options.
6939 + This file is distributed under the terms of the GNU General Public
6940 + License (GPL). Copies of the GPL can be obtained from:
6941 + ftp://prep.ai.mit.edu/pub/gnu/GPL
6943 + 11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
6944 + 12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
6945 + 12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
6946 + 18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
6949 +#include <linux/module.h>
6950 +#include <linux/skbuff.h>
6951 +#include <net/ip.h>
6953 +#include <linux/netfilter_ipv4/ip_tables.h>
6954 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
6956 +MODULE_LICENSE("GPL");
6959 +match(const struct sk_buff *skb,
6960 + const struct net_device *in,
6961 + const struct net_device *out,
6962 + const void *matchinfo,
6965 + u_int16_t datalen,
6968 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
6969 + const struct iphdr *iph = skb->nh.iph;
6970 + const struct ip_options *opt;
6972 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
6973 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
6975 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
6976 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
6977 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
6978 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
6979 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
6980 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
6985 + if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
6986 + /* there are options, and we don't need to care which one */
6989 + if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
6990 + /* there are options but we don't want any ! */
6995 + opt = &(IPCB(skb)->opt);
6997 + /* source routing */
6998 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
6999 + if (!((opt->srr) & (opt->is_strictroute)))
7002 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
7003 + if (!((opt->srr) & (!opt->is_strictroute)))
7006 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
7010 + /* record route */
7011 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
7015 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
7020 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
7024 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
7028 + /* router-alert option */
7029 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
7030 + if (!opt->router_alert)
7033 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
7034 + if (opt->router_alert)
7043 +checkentry(const char *tablename,
7044 + const struct ipt_ip *ip,
7046 + unsigned int matchsize,
7047 + unsigned int hook_mask)
7049 + const struct ipt_ipv4options_info *info = matchinfo; /* match info for rule */
7050 + /* Check the size */
7051 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
7053 + /* Now check the coherence of the data ... */
7054 + if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
7055 + (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
7056 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
7057 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
7058 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
7059 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
7060 + return 0; /* opposites */
7061 + if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
7062 + (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
7063 + ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
7064 + ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
7065 + ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
7066 + ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
7067 + ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
7068 + return 0; /* opposites */
7069 + if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
7070 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
7071 + return 0; /* cannot match in the same time loose and strict source routing */
7072 + if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
7073 + ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
7074 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
7075 + return 0; /* opposites */
7076 + if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
7077 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
7078 + return 0; /* opposites */
7079 + if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
7080 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
7081 + return 0; /* opposites */
7082 + if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
7083 + ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
7084 + return 0; /* opposites */
7086 + /* everything looks ok. */
7090 +static struct ipt_match ipv4options_match
7091 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
7093 +static int __init init(void)
7095 + printk("ipt_ipv4options loading\n");
7096 + return ipt_register_match(&ipv4options_match);
7099 +static void __exit fini(void)
7101 + ipt_unregister_match(&ipv4options_match);
7102 + printk("ipt_ipv4options unloaded\n");
7107 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_mport.c linux-2.6.3/net/ipv4/netfilter/ipt_mport.c
7108 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_mport.c 1970-01-01 01:00:00.000000000 +0100
7109 +++ linux-2.6.3/net/ipv4/netfilter/ipt_mport.c 2004-02-19 08:47:29.018386433 +0100
7111 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
7112 + the same place so we can treat them as equal. */
7113 +#include <linux/module.h>
7114 +#include <linux/types.h>
7115 +#include <linux/udp.h>
7116 +#include <linux/skbuff.h>
7118 +#include <linux/netfilter_ipv4/ipt_mport.h>
7119 +#include <linux/netfilter_ipv4/ip_tables.h>
7121 +MODULE_LICENSE("GPL");
7124 +#define duprintf(format, args...) printk(format , ## args)
7126 +#define duprintf(format, args...)
7129 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
7131 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
7135 + u_int16_t pflags = minfo->pflags;
7136 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
7140 + && minfo->ports[i] == 65535)
7143 + s = minfo->ports[i];
7146 + e = minfo->ports[++i];
7151 + if (minfo->flags & IPT_MPORT_SOURCE
7152 + && src >= s && src <= e)
7155 + if (minfo->flags & IPT_MPORT_DESTINATION
7156 + && dst >= s && dst <= e)
7164 +match(const struct sk_buff *skb,
7165 + const struct net_device *in,
7166 + const struct net_device *out,
7167 + const void *matchinfo,
7170 + u_int16_t datalen,
7173 + const struct udphdr *udp = hdr;
7174 + const struct ipt_mport *minfo = matchinfo;
7176 + /* Must be big enough to read ports. */
7177 + if (offset == 0 && datalen < sizeof(struct udphdr)) {
7178 + /* We've been asked to examine this packet, and we
7179 + can't. Hence, no choice but to drop. */
7180 + duprintf("ipt_mport:"
7181 + " Dropping evil offset=0 tinygram.\n");
7186 + /* Must not be a fragment. */
7188 + && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
7191 +/* Called when user tries to insert an entry of this type. */
7193 +checkentry(const char *tablename,
7194 + const struct ipt_ip *ip,
7196 + unsigned int matchsize,
7197 + unsigned int hook_mask)
7199 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
7202 + /* Must specify proto == TCP/UDP, no unknown flags or bad count */
7203 + return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
7204 + && !(ip->invflags & IPT_INV_PROTO)
7205 + && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
7208 +static struct ipt_match mport_match
7209 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
7211 +static int __init init(void)
7213 + return ipt_register_match(&mport_match);
7216 +static void __exit fini(void)
7218 + ipt_unregister_match(&mport_match);
7223 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_nth.c linux-2.6.3/net/ipv4/netfilter/ipt_nth.c
7224 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_nth.c 1970-01-01 01:00:00.000000000 +0100
7225 +++ linux-2.6.3/net/ipv4/netfilter/ipt_nth.c 2004-02-19 08:47:29.579251335 +0100
7228 + This is a module which is used for match support for every Nth packet
7229 + This file is distributed under the terms of the GNU General Public
7230 + License (GPL). Copies of the GPL can be obtained from:
7231 + ftp://prep.ai.mit.edu/pub/gnu/GPL
7233 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
7234 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
7235 + * added support for multiple counters
7236 + * added support for matching on individual packets
7237 + in the counter cycle
7241 +#include <linux/module.h>
7242 +#include <linux/skbuff.h>
7243 +#include <linux/ip.h>
7244 +#include <net/tcp.h>
7245 +#include <linux/spinlock.h>
7246 +#include <linux/netfilter_ipv4/ip_tables.h>
7247 +#include <linux/netfilter_ipv4/ipt_nth.h>
7249 +MODULE_LICENSE("GPL");
7252 + * State information.
7259 +static struct state states[IPT_NTH_NUM_COUNTERS];
7262 +ipt_nth_match(const struct sk_buff *pskb,
7263 + const struct net_device *in,
7264 + const struct net_device *out,
7265 + const void *matchinfo,
7268 + u_int16_t datalen,
7271 + /* Parameters from userspace */
7272 + const struct ipt_nth_info *info = matchinfo;
7273 + unsigned counter = info->counter;
7274 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
7276 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
7280 + spin_lock(&states[counter].lock);
7282 + /* Are we matching every nth packet?*/
7283 + if (info->packet == 0xFF)
7285 + /* We're matching every nth packet and only every nth packet*/
7286 + /* Do we match or invert match? */
7287 + if (info->not == 0)
7289 + if (states[counter].number == 0)
7291 + ++states[counter].number;
7294 + if (states[counter].number >= info->every)
7295 + states[counter].number = 0; /* reset the counter */
7297 + ++states[counter].number;
7302 + if (states[counter].number == 0)
7304 + ++states[counter].number;
7307 + if (states[counter].number >= info->every)
7308 + states[counter].number = 0;
7310 + ++states[counter].number;
7316 + /* We're using the --packet, so there must be a rule for every value */
7317 + if (states[counter].number == info->packet)
7319 + /* only increment the counter when a match happens */
7320 + if (states[counter].number >= info->every)
7321 + states[counter].number = 0; /* reset the counter */
7323 + ++states[counter].number;
7332 + spin_unlock(&states[counter].lock);
7336 + spin_unlock(&states[counter].lock);
7341 +ipt_nth_checkentry(const char *tablename,
7342 + const struct ipt_ip *e,
7344 + unsigned int matchsize,
7345 + unsigned int hook_mask)
7347 + /* Parameters from userspace */
7348 + const struct ipt_nth_info *info = matchinfo;
7349 + unsigned counter = info->counter;
7350 + if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS))
7352 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
7356 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
7357 + printk("nth: matchsize %u != %u\n", matchsize,
7358 + IPT_ALIGN(sizeof(struct ipt_nth_info)));
7362 + states[counter].number = info->startat;
7367 +static struct ipt_match ipt_nth_reg = {
7371 + ipt_nth_checkentry,
7375 +static int __init init(void)
7378 + memset(&states, 0, sizeof(states));
7379 + if (ipt_register_match(&ipt_nth_reg))
7382 + for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
7384 + spin_lock_init(&(states[counter].lock));
7387 + printk("ipt_nth match loaded\n");
7391 +static void __exit fini(void)
7393 + ipt_unregister_match(&ipt_nth_reg);
7394 + printk("ipt_nth match unloaded\n");
7399 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_osf.c linux-2.6.3/net/ipv4/netfilter/ipt_osf.c
7400 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_osf.c 1970-01-01 01:00:00.000000000 +0100
7401 +++ linux-2.6.3/net/ipv4/netfilter/ipt_osf.c 2004-02-19 08:47:30.115122257 +0100
7406 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
7409 + * This program is free software; you can redistribute it and/or modify
7410 + * it under the terms of the GNU General Public License as published by
7411 + * the Free Software Foundation; either version 2 of the License, or
7412 + * (at your option) any later version.
7414 + * This program is distributed in the hope that it will be useful,
7415 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7416 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7417 + * GNU General Public License for more details.
7419 + * You should have received a copy of the GNU General Public License
7420 + * along with this program; if not, write to the Free Software
7421 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7425 + * OS fingerprint matching module.
7426 + * It simply compares various parameters from SYN packet with
7427 + * some hardcoded ones.
7429 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
7433 +#include <linux/config.h>
7434 +#include <linux/kernel.h>
7435 +#include <linux/smp.h>
7436 +#include <linux/module.h>
7437 +#include <linux/skbuff.h>
7438 +#include <linux/file.h>
7439 +#include <linux/ip.h>
7440 +#include <linux/proc_fs.h>
7441 +#include <linux/fs.h>
7442 +#include <linux/slab.h>
7443 +#include <linux/spinlock.h>
7444 +#include <linux/ctype.h>
7445 +#include <linux/list.h>
7447 +#include <net/sock.h>
7448 +#include <net/ip.h>
7450 +#include <linux/netfilter_ipv4/ip_tables.h>
7452 +#include <linux/netfilter_ipv4/ipt_osf.h>
7457 +#define log(x...) printk(KERN_INFO "ipt_osf: " x)
7458 +#define loga(x...) printk(x)
7460 +#define log(x...) do {} while(0)
7461 +#define loga(x...) do {} while(0)
7464 +#define FMATCH_WRONG 0
7465 +#define FMATCH_OK 1
7466 +#define FMATCH_OPT_WRONG 2
7469 +#define OSFPDEL ':'
7470 +#define MAXOPTSTRLEN 128
7471 +#define OSFFLUSH "FLUSH"
7473 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
7474 +static struct list_head finger_list;
7476 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
7477 + const void *, int, const void *, u_int16_t, int *);
7478 +static int checkentry(const char *, const struct ipt_ip *, void *,
7479 + unsigned int, unsigned int);
7481 +static struct ipt_match osf_match =
7491 +static inline int smart_dec(unsigned long flags, unsigned char ip_ttl, unsigned char f_ttl)
7493 + if (flags & IPT_OSF_SMART)
7496 + return (ip_ttl == f_ttl);
7500 +match(const struct sk_buff *skb,
7501 + const struct net_device *in,
7502 + const struct net_device *out,
7503 + const void *matchinfo,
7506 + u_int16_t datalen,
7509 + struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
7510 + struct iphdr *ip = skb->nh.iph;
7511 + struct tcphdr *tcp;
7512 + int fmatch = FMATCH_WRONG, fcount = 0;
7513 + unsigned long totlen, optsize = 0, window;
7514 + unsigned char df, *optp = NULL, *_optp = NULL;
7515 + char check_WSS = 0;
7516 + struct list_head *ent;
7517 + struct osf_finger *f;
7522 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
7526 + else if (tcp->ack)
7529 + totlen = ntohs(ip->tot_len);
7530 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
7531 + window = ntohs(tcp->window);
7533 + if (tcp->doff*4 > sizeof(struct tcphdr))
7535 + _optp = optp = (char *)(tcp+1);
7536 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
7540 + /* Actually we can create hash/table of all genres and search
7541 + * only in appropriate part, but here is initial variant,
7542 + * so will use slow path.
7544 + read_lock(&osf_lock);
7545 + list_for_each(ent, &finger_list)
7547 + f = list_entry(ent, struct osf_finger, flist);
7549 + if (!(info->flags & IPT_OSF_LOG) && strcmp(info->genre, f->genre))
7553 + fmatch = FMATCH_WRONG;
7555 + if (totlen == f->ss && df == f->df &&
7556 + smart_dec(info->flags, ip->ttl, f->ttl))
7558 + unsigned long foptsize;
7560 + unsigned short mss = 0;
7564 + switch (f->wss.wc)
7566 + case 0: check_WSS = 0; break;
7567 + case 'S': check_WSS = 1; break;
7568 + case 'T': check_WSS = 2; break;
7569 + case '%': check_WSS = 3; break;
7570 + default: log("Wrong fingerprint wss.wc=%d, %s - %s\n",
7571 + f->wss.wc, f->genre, f->details);
7575 + if (check_WSS == 4)
7578 + /* Check options */
7581 + for (optnum=0; optnum<f->opt_num; ++optnum)
7582 + foptsize += f->opt[optnum].length;
7585 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
7590 + fmatch = FMATCH_OK;
7591 + loga("\tYEP : matching without options.\n");
7592 + if ((info->flags & IPT_OSF_LOG) &&
7593 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
7600 + for (optnum=0; optnum<f->opt_num; ++optnum)
7602 + if (f->opt[optnum].kind == (*optp))
7604 + unsigned char len = f->opt[optnum].length;
7605 + unsigned char *optend = optp + len;
7607 + fmatch = FMATCH_OK;
7609 + if (*optp == OSFOPT_MSS) /* MSS */
7610 + mss = ntohs(*(unsigned short *)(optp+2));
7614 + /* Skip kind and length fields*/
7617 + if (f->opt[optnum].wc.wc != 0)
7619 + unsigned long tmp = 0;
7621 + /* Hmmm... It looks a bit ugly. :) */
7622 + memcpy(&tmp, &f->opt[optnum].wc.val,
7623 + (len > sizeof(unsigned long)?
7624 + sizeof(unsigned long):len));
7627 + if (tmp != f->opt[optnum].wc.val)
7628 + fmatch = FMATCH_OPT_WRONG;
7635 + fmatch = FMATCH_OPT_WRONG;
7637 + if (fmatch != FMATCH_OK)
7641 + if (fmatch != FMATCH_OPT_WRONG)
7643 + fmatch = FMATCH_WRONG;
7645 + switch (check_WSS)
7648 + if (window == f->wss.val)
7649 + fmatch = FMATCH_OK;
7652 + if (window == f->wss.val*mss)
7653 + fmatch = FMATCH_OK;
7656 + if (window == f->wss.val*(mss+40))
7657 + fmatch = FMATCH_OK;
7660 + if (window % f->wss.val == 0)
7661 + fmatch = FMATCH_OK;
7667 + if (fmatch == FMATCH_OK)
7670 + log("%s [%s]: %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
7671 + f->genre, f->details,
7672 + NIPQUAD(ip->saddr), ntohs(tcp->source),
7673 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
7674 + if ((info->flags & IPT_OSF_LOG) &&
7675 + info->loglevel == IPT_OSF_LOGLEVEL_FIRST)
7680 + if (!fcount && (info->flags & IPT_OSF_LOG))
7682 + log("Unknown: %lu:%d:%d:%lu:", window, ip->ttl, df, totlen);
7685 + unsigned char opt[4 * 15 - sizeof(struct tcphdr)];
7686 + unsigned int i, optsize;
7688 + optsize = tcp->doff * 4 - sizeof(struct tcphdr);
7689 + if (skb_copy_bits(skb, ip->ihl*4 + sizeof(struct tcphdr),
7690 + opt, optsize) < 0)
7691 + loga("TRUNCATED");
7693 + for (i = 0; i < optsize; i++)
7694 + loga("%02X", opt[i]);
7697 + loga(" %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",
7698 + NIPQUAD(ip->saddr), ntohs(tcp->source),
7699 + NIPQUAD(ip->daddr), ntohs(tcp->dest));
7701 + read_unlock(&osf_lock);
7703 + return (fmatch == FMATCH_OK)?1:0;
7707 +checkentry(const char *tablename,
7708 + const struct ipt_ip *ip,
7710 + unsigned int matchsize,
7711 + unsigned int hook_mask)
7713 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
7715 + if (ip->proto != IPPROTO_TCP)
7721 +static char * osf_strchr(char *ptr, char c)
7725 + tmp = strchr(ptr, c);
7727 + while (tmp && tmp+1 && isspace(*(tmp+1)))
7733 +static struct osf_finger * finger_alloc(void)
7735 + struct osf_finger *f;
7737 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
7739 + memset(f, 0, sizeof(struct osf_finger));
7744 +static void finger_free(struct osf_finger *f)
7746 + memset(f, 0, sizeof(struct osf_finger));
7751 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
7755 + unsigned long val;
7759 + while (ptr != NULL && i < olen)
7768 + ptr = osf_strchr(&obuf[i], OPTDEL);
7773 + i += (int)(ptr-&obuf[i]);
7780 + op = OSFOPT_SACKP;
7781 + ptr = osf_strchr(&obuf[i], OPTDEL);
7786 + i += (int)(ptr-&obuf[i]);
7794 + ptr = osf_strchr(&obuf[i], OPTDEL);
7799 + i += (int)(ptr-&obuf[i]);
7807 + ptr = osf_strchr(&obuf[i], OPTDEL);
7810 + switch (obuf[i+1])
7812 + case '%': wc = '%'; break;
7813 + case 'S': wc = 'S'; break;
7814 + case 'T': wc = 'T'; break;
7815 + default: wc = 0; break;
7821 + val = simple_strtoul(&obuf[i+2], NULL, 10);
7823 + val = simple_strtoul(&obuf[i+1], NULL, 10);
7824 + i += (int)(ptr-&obuf[i]);
7832 + ptr = osf_strchr(&obuf[i], OPTDEL);
7835 + if (obuf[i+1] == '%')
7840 + val = simple_strtoul(&obuf[i+2], NULL, 10);
7842 + val = simple_strtoul(&obuf[i+1], NULL, 10);
7843 + i += (int)(ptr-&obuf[i]);
7851 + ptr = osf_strchr(&obuf[i], OPTDEL);
7856 + i += (int)(ptr-&obuf[i]);
7863 + ptr = osf_strchr(&obuf[i], OPTDEL);
7867 + i += (int)(ptr-&obuf[i]);
7875 + opt[*optnum].kind = IANA_opts[op].kind;
7876 + opt[*optnum].length = IANA_opts[op].length;
7877 + opt[*optnum].wc.wc = wc;
7878 + opt[*optnum].wc.val = val;
7884 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
7886 + struct list_head *ent;
7887 + struct osf_finger *f = NULL;
7893 + read_lock_bh(&osf_lock);
7894 + list_for_each(ent, &finger_list)
7896 + f = list_entry(ent, struct osf_finger, flist);
7898 + log("%s [%s]", f->genre, f->details);
7900 + count += sprintf(buf+count, "%s - %s[%s] : %s",
7901 + f->genre, f->version,
7902 + f->subtype, f->details);
7907 + //count += sprintf(buf+count, " OPT: ");
7908 + for (i=0; i<f->opt_num; ++i)
7910 + //count += sprintf(buf+count, "%d.%c%lu; ",
7911 + // f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
7912 + loga("%d.%c%lu; ",
7913 + f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
7917 + count += sprintf(buf+count, "\n");
7919 + read_unlock_bh(&osf_lock);
7924 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
7928 + char obuf[MAXOPTSTRLEN];
7929 + struct osf_finger *finger;
7930 + struct list_head *ent, *n;
7932 + char *pbeg, *pend;
7934 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
7937 + write_lock_bh(&osf_lock);
7938 + list_for_each_safe(ent, n, &finger_list)
7941 + finger = list_entry(ent, struct osf_finger, flist);
7942 + list_del(&finger->flist);
7943 + finger_free(finger);
7945 + write_unlock_bh(&osf_lock);
7947 + log("Flushed %d entries.\n", i);
7954 + for (i=0; i<count && buffer[i] != '\0'; ++i)
7955 + if (buffer[i] == ':')
7958 + if (cnt != 8 || i != count)
7960 + log("Wrong input line cnt=%d[8], len=%lu[%lu]\n",
7965 + memset(obuf, 0, sizeof(obuf));
7967 + finger = finger_alloc();
7970 + log("Failed to allocate new fingerprint entry.\n");
7974 + pbeg = (char *)buffer;
7975 + pend = osf_strchr(pbeg, OSFPDEL);
7979 + if (pbeg[0] == 'S')
7981 + finger->wss.wc = 'S';
7982 + if (pbeg[1] == '%')
7983 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
7984 + else if (pbeg[1] == '*')
7985 + finger->wss.val = 0;
7987 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
7989 + else if (pbeg[0] == 'T')
7991 + finger->wss.wc = 'T';
7992 + if (pbeg[1] == '%')
7993 + finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
7994 + else if (pbeg[1] == '*')
7995 + finger->wss.val = 0;
7997 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
7999 + if (isdigit(pbeg[0]))
8001 + finger->wss.wc = 0;
8002 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
8007 + pend = osf_strchr(pbeg, OSFPDEL);
8011 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
8014 + pend = osf_strchr(pbeg, OSFPDEL);
8018 + finger->df = simple_strtoul(pbeg, NULL, 10);
8021 + pend = osf_strchr(pbeg, OSFPDEL);
8025 + finger->ss = simple_strtoul(pbeg, NULL, 10);
8029 + pend = osf_strchr(pbeg, OSFPDEL);
8033 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
8037 + pend = osf_strchr(pbeg, OSFPDEL);
8041 + if (pbeg[0] == '@' || pbeg[0] == '*')
8042 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg+1);
8044 + cnt = snprintf(finger->genre, sizeof(finger->genre), "%s", pbeg);
8048 + pend = osf_strchr(pbeg, OSFPDEL);
8052 + cnt = snprintf(finger->version, sizeof(finger->version), "%s", pbeg);
8056 + pend = osf_strchr(pbeg, OSFPDEL);
8060 + cnt = snprintf(finger->subtype, sizeof(finger->subtype), "%s", pbeg);
8064 + cnt = snprintf(finger->details,
8065 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
8068 + log("%s - %s[%s] : %s\n",
8069 + finger->genre, finger->version,
8070 + finger->subtype, finger->details);
8072 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
8075 + write_lock_bh(&osf_lock);
8076 + list_add_tail(&finger->flist, &finger_list);
8077 + write_unlock_bh(&osf_lock);
8082 +static int __init osf_init(void)
8085 + struct proc_dir_entry *p;
8087 + log("Startng OS fingerprint matching module.\n");
8089 + INIT_LIST_HEAD(&finger_list);
8091 + err = ipt_register_match(&osf_match);
8094 + log("Failed to register OS fingerprint matching module.\n");
8098 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
8101 + ipt_unregister_match(&osf_match);
8105 + p->write_proc = osf_proc_write;
8106 + p->read_proc = osf_proc_read;
8111 +static void __exit osf_fini(void)
8113 + struct list_head *ent, *n;
8114 + struct osf_finger *f;
8116 + remove_proc_entry("sys/net/ipv4/osf", NULL);
8117 + ipt_unregister_match(&osf_match);
8119 + list_for_each_safe(ent, n, &finger_list)
8121 + f = list_entry(ent, struct osf_finger, flist);
8122 + list_del(&f->flist);
8126 + log("OS fingerprint matching module finished.\n");
8129 +module_init(osf_init);
8130 +module_exit(osf_fini);
8132 +MODULE_LICENSE("GPL");
8133 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
8134 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
8136 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_pool.c linux-2.6.3/net/ipv4/netfilter/ipt_pool.c
8137 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_pool.c 1970-01-01 01:00:00.000000000 +0100
8138 +++ linux-2.6.3/net/ipv4/netfilter/ipt_pool.c 2004-02-19 08:47:30.713978008 +0100
8140 +/* Kernel module to match an IP address pool. */
8142 +#include <linux/module.h>
8143 +#include <linux/ip.h>
8144 +#include <linux/skbuff.h>
8146 +#include <linux/netfilter_ipv4/ip_tables.h>
8147 +#include <linux/netfilter_ipv4/ip_pool.h>
8148 +#include <linux/netfilter_ipv4/ipt_pool.h>
8150 +static inline int match_pool(
8155 + if (ip_pool_match(index, ntohl(addr)))
8161 + const struct sk_buff *skb,
8162 + const struct net_device *in,
8163 + const struct net_device *out,
8164 + const void *matchinfo,
8167 + u_int16_t datalen,
8170 + const struct ipt_pool_info *info = matchinfo;
8171 + const struct iphdr *iph = skb->nh.iph;
8173 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
8174 + info->flags&IPT_POOL_INV_SRC))
8177 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
8178 + info->flags&IPT_POOL_INV_DST))
8184 +static int checkentry(
8185 + const char *tablename,
8186 + const struct ipt_ip *ip,
8188 + unsigned int matchsize,
8189 + unsigned int hook_mask
8191 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
8196 +static struct ipt_match pool_match
8197 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
8199 +static int __init init(void)
8201 + return ipt_register_match(&pool_match);
8204 +static void __exit fini(void)
8206 + ipt_unregister_match(&pool_match);
8211 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_psd.c linux-2.6.3/net/ipv4/netfilter/ipt_psd.c
8212 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_psd.c 1970-01-01 01:00:00.000000000 +0100
8213 +++ linux-2.6.3/net/ipv4/netfilter/ipt_psd.c 2004-02-19 08:47:31.249848931 +0100
8216 + This is a module which is used for PSD (portscan detection)
8217 + Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
8218 + and LOG target module.
8220 + Copyright (C) 2000,2001 astaro AG
8222 + This file is distributed under the terms of the GNU General Public
8223 + License (GPL). Copies of the GPL can be obtained from:
8224 + ftp://prep.ai.mit.edu/pub/gnu/GPL
8226 + 2000-05-04 Markus Hennig <hennig@astaro.de> : initial
8227 + 2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
8228 + 2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
8229 + 2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
8230 + 2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
8233 +#include <linux/module.h>
8234 +#include <linux/skbuff.h>
8235 +#include <linux/ip.h>
8236 +#include <net/tcp.h>
8237 +#include <linux/spinlock.h>
8238 +#include <linux/netfilter_ipv4/ip_tables.h>
8239 +#include <linux/netfilter_ipv4/ipt_psd.h>
8242 +#define DEBUGP printk
8244 +#define DEBUGP(format, args...)
8247 +MODULE_LICENSE("GPL");
8248 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
8250 +#define HF_DADDR_CHANGING 0x01
8251 +#define HF_SPORT_CHANGING 0x02
8252 +#define HF_TOS_CHANGING 0x04
8253 +#define HF_TTL_CHANGING 0x08
8256 + * Information we keep per each target port
8259 + u_int16_t number; /* port number */
8260 + u_int8_t proto; /* protocol number */
8261 + u_int8_t and_flags; /* tcp ANDed flags */
8262 + u_int8_t or_flags; /* tcp ORed flags */
8266 + * Information we keep per each source address.
8269 + struct host *next; /* Next entry with the same hash */
8270 + clock_t timestamp; /* Last update time */
8271 + struct in_addr src_addr; /* Source address */
8272 + struct in_addr dest_addr; /* Destination address */
8273 + unsigned short src_port; /* Source port */
8274 + int count; /* Number of ports in the list */
8275 + int weight; /* Total weight of ports in the list */
8276 + struct port ports[SCAN_MAX_COUNT - 1]; /* List of ports */
8277 + unsigned char tos; /* TOS */
8278 + unsigned char ttl; /* TTL */
8279 + unsigned char flags; /* HF_ flags bitmask */
8283 + * State information.
8287 + struct host list[LIST_SIZE]; /* List of source addresses */
8288 + struct host *hash[HASH_SIZE]; /* Hash: pointers into the list */
8289 + int index; /* Oldest entry to be replaced */
8293 + * Convert an IP address into a hash table index.
8295 +static inline int hashfunc(struct in_addr addr)
8297 + unsigned int value;
8300 + value = addr.s_addr;
8304 + } while ((value >>= HASH_LOG));
8306 + return hash & (HASH_SIZE - 1);
8310 +ipt_psd_match(const struct sk_buff *pskb,
8311 + const struct net_device *in,
8312 + const struct net_device *out,
8313 + const void *matchinfo,
8316 + u_int16_t datalen,
8319 + struct iphdr *ip_hdr;
8320 + struct tcphdr *tcp_hdr;
8321 + struct in_addr addr;
8322 + u_int16_t src_port,dest_port;
8323 + u_int8_t tcp_flags, proto;
8325 + struct host *curr, *last, **head;
8326 + int hash, index, count;
8328 + /* Parameters from userspace */
8329 + const struct ipt_psd_info *psdinfo = matchinfo;
8332 + ip_hdr = pskb->nh.iph;
8334 + /* Sanity check */
8335 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
8336 + DEBUGP("PSD: sanity check failed\n");
8340 + /* TCP or UDP ? */
8341 + proto = ip_hdr->protocol;
8343 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
8344 + DEBUGP("PSD: protocol not supported\n");
8348 + /* Get the source address, source & destination ports, and TCP flags */
8350 + addr.s_addr = ip_hdr->saddr;
8352 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
8354 + /* Yep, it´s dirty */
8355 + src_port = tcp_hdr->source;
8356 + dest_port = tcp_hdr->dest;
8358 + if (proto == IPPROTO_TCP) {
8359 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
8365 + /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
8366 + * them spoof us. [DHCP needs this feature - HW] */
8367 + if (!addr.s_addr) {
8368 + DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
8372 + /* Use jiffies here not to depend on someone setting the time while we're
8373 + * running; we need to be careful with possible return value overflows. */
8376 + spin_lock(&state.lock);
8378 + /* Do we know this source address already? */
8381 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
8383 + if (curr->src_addr.s_addr == addr.s_addr) break;
8385 + if (curr->next) last = curr;
8386 + } while ((curr = curr->next));
8390 + /* We know this address, and the entry isn't too old. Update it. */
8391 + if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
8392 + time_after_eq(now, curr->timestamp)) {
8394 + /* Just update the appropriate list entry if we've seen this port already */
8395 + for (index = 0; index < curr->count; index++) {
8396 + if (curr->ports[index].number == dest_port) {
8397 + curr->ports[index].proto = proto;
8398 + curr->ports[index].and_flags &= tcp_flags;
8399 + curr->ports[index].or_flags |= tcp_flags;
8400 + goto out_no_match;
8404 + /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
8405 + if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
8406 + goto out_no_match;
8408 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
8409 + curr->timestamp = now;
8411 + /* Logged this scan already? Then drop the packet. */
8412 + if (curr->weight >= psdinfo->weight_threshold)
8415 + /* Specify if destination address, source port, TOS or TTL are not fixed */
8416 + if (curr->dest_addr.s_addr != ip_hdr->daddr)
8417 + curr->flags |= HF_DADDR_CHANGING;
8418 + if (curr->src_port != src_port)
8419 + curr->flags |= HF_SPORT_CHANGING;
8420 + if (curr->tos != ip_hdr->tos)
8421 + curr->flags |= HF_TOS_CHANGING;
8422 + if (curr->ttl != ip_hdr->ttl)
8423 + curr->flags |= HF_TTL_CHANGING;
8425 + /* Update the total weight */
8426 + curr->weight += (ntohs(dest_port) < 1024) ?
8427 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
8429 + /* Got enough destination ports to decide that this is a scan? */
8430 + /* Then log it and drop the packet. */
8431 + if (curr->weight >= psdinfo->weight_threshold)
8434 + /* Remember the new port */
8435 + if (curr->count < SCAN_MAX_COUNT) {
8436 + curr->ports[curr->count].number = dest_port;
8437 + curr->ports[curr->count].proto = proto;
8438 + curr->ports[curr->count].and_flags = tcp_flags;
8439 + curr->ports[curr->count].or_flags = tcp_flags;
8443 + goto out_no_match;
8446 + /* We know this address, but the entry is outdated. Mark it unused, and
8447 + * remove from the hash table. We'll allocate a new entry instead since
8448 + * this one might get re-used too soon. */
8449 + curr->src_addr.s_addr = 0;
8451 + last->next = last->next->next;
8453 + *head = (*head)->next;
8457 + /* We don't need an ACK from a new source address */
8458 + if (proto == IPPROTO_TCP && tcp_hdr->ack)
8459 + goto out_no_match;
8461 + /* Got too many source addresses with the same hash value? Then remove the
8462 + * oldest one from the hash table, so that they can't take too much of our
8463 + * CPU time even with carefully chosen spoofed IP addresses. */
8464 + if (count >= HASH_MAX && last) last->next = NULL;
8466 + /* We're going to re-use the oldest list entry, so remove it from the hash
8467 + * table first (if it is really already in use, and isn't removed from the
8468 + * hash table already because of the HASH_MAX check above). */
8470 + /* First, find it */
8471 + if (state.list[state.index].src_addr.s_addr)
8472 + head = &state.hash[hashfunc(state.list[state.index].src_addr)];
8476 + if ((curr = *head))
8478 + if (curr == &state.list[state.index]) break;
8480 + } while ((curr = curr->next));
8482 + /* Then, remove it */
8485 + last->next = last->next->next;
8487 + *head = (*head)->next;
8490 + /* Get our list entry */
8491 + curr = &state.list[state.index++];
8492 + if (state.index >= LIST_SIZE) state.index = 0;
8494 + /* Link it into the hash table */
8495 + head = &state.hash[hash];
8496 + curr->next = *head;
8499 + /* And fill in the fields */
8500 + curr->timestamp = now;
8501 + curr->src_addr = addr;
8502 + curr->dest_addr.s_addr = ip_hdr->daddr;
8503 + curr->src_port = src_port;
8505 + curr->weight = (ntohs(dest_port) < 1024) ?
8506 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
8507 + curr->ports[0].number = dest_port;
8508 + curr->ports[0].proto = proto;
8509 + curr->ports[0].and_flags = tcp_flags;
8510 + curr->ports[0].or_flags = tcp_flags;
8511 + curr->tos = ip_hdr->tos;
8512 + curr->ttl = ip_hdr->ttl;
8515 + spin_unlock(&state.lock);
8519 + spin_unlock(&state.lock);
8523 +static int ipt_psd_checkentry(const char *tablename,
8524 + const struct ipt_ip *e,
8526 + unsigned int matchsize,
8527 + unsigned int hook_mask)
8529 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
8531 + /* we accept TCP only */
8532 +/* if (e->ip.proto != IPPROTO_TCP) { */
8533 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
8537 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
8538 + DEBUGP("PSD: matchsize %u != %u\n",
8540 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
8547 +static struct ipt_match ipt_psd_reg = {
8551 + ipt_psd_checkentry,
8555 +static int __init init(void)
8557 + if (ipt_register_match(&ipt_psd_reg))
8560 + memset(&state, 0, sizeof(state));
8562 + spin_lock_init(&(state.lock));
8564 + printk("netfilter PSD loaded - (c) astaro AG\n");
8568 +static void __exit fini(void)
8570 + ipt_unregister_match(&ipt_psd_reg);
8571 + printk("netfilter PSD unloaded - (c) astaro AG\n");
8576 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_quota.c linux-2.6.3/net/ipv4/netfilter/ipt_quota.c
8577 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_quota.c 1970-01-01 01:00:00.000000000 +0100
8578 +++ linux-2.6.3/net/ipv4/netfilter/ipt_quota.c 2004-02-19 08:47:31.780721057 +0100
8581 + * netfilter module to enforce network quotas
8583 + * Sam Johnston <samj@samj.net>
8585 +#include <linux/module.h>
8586 +#include <linux/skbuff.h>
8587 +#include <linux/spinlock.h>
8588 +#include <linux/interrupt.h>
8590 +#include <linux/netfilter_ipv4/ip_tables.h>
8591 +#include <linux/netfilter_ipv4/ipt_quota.h>
8593 +MODULE_LICENSE("GPL");
8595 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
8598 +match(const struct sk_buff *skb,
8599 + const struct net_device *in,
8600 + const struct net_device *out,
8601 + const void *matchinfo,
8602 + int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
8605 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
8607 + spin_lock_bh("a_lock);
8609 + if (q->quota >= datalen) {
8610 + /* we can afford this one */
8611 + q->quota -= datalen;
8612 + spin_unlock_bh("a_lock);
8614 +#ifdef DEBUG_IPT_QUOTA
8615 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
8620 + /* so we do not allow even small packets from now on */
8623 +#ifdef DEBUG_IPT_QUOTA
8624 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
8627 + spin_unlock_bh("a_lock);
8632 +checkentry(const char *tablename,
8633 + const struct ipt_ip *ip,
8634 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
8636 + /* TODO: spinlocks? sanity checks? */
8637 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
8643 +static struct ipt_match quota_match
8644 + = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
8649 + return ipt_register_match("a_match);
8655 + ipt_unregister_match("a_match);
8661 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_random.c linux-2.6.3/net/ipv4/netfilter/ipt_random.c
8662 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_random.c 1970-01-01 01:00:00.000000000 +0100
8663 +++ linux-2.6.3/net/ipv4/netfilter/ipt_random.c 2004-02-19 08:47:32.336587163 +0100
8666 + This is a module which is used for a "random" match support.
8667 + This file is distributed under the terms of the GNU General Public
8668 + License (GPL). Copies of the GPL can be obtained from:
8669 + ftp://prep.ai.mit.edu/pub/gnu/GPL
8671 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
8674 +#include <linux/module.h>
8675 +#include <linux/skbuff.h>
8676 +#include <linux/ip.h>
8677 +#include <linux/random.h>
8678 +#include <net/tcp.h>
8679 +#include <linux/spinlock.h>
8680 +#include <linux/netfilter_ipv4/ip_tables.h>
8681 +#include <linux/netfilter_ipv4/ipt_random.h>
8683 +MODULE_LICENSE("GPL");
8686 +ipt_rand_match(const struct sk_buff *pskb,
8687 + const struct net_device *in,
8688 + const struct net_device *out,
8689 + const void *matchinfo,
8692 + u_int16_t datalen,
8695 + /* Parameters from userspace */
8696 + const struct ipt_rand_info *info = matchinfo;
8697 + u_int8_t random_number;
8699 + /* get 1 random number from the kernel random number generation routine */
8700 + get_random_bytes((void *)(&random_number), 1);
8702 + /* Do we match ? */
8703 + if (random_number <= info->average)
8710 +ipt_rand_checkentry(const char *tablename,
8711 + const struct ipt_ip *e,
8713 + unsigned int matchsize,
8714 + unsigned int hook_mask)
8716 + /* Parameters from userspace */
8717 + const struct ipt_rand_info *info = matchinfo;
8719 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
8720 + printk("ipt_random: matchsize %u != %u\n", matchsize,
8721 + IPT_ALIGN(sizeof(struct ipt_rand_info)));
8725 + /* must be 1 <= average % <= 99 */
8726 + /* 1 x 2.55 = 2 */
8727 + /* 99 x 2.55 = 252 */
8728 + if ((info->average < 2) || (info->average > 252)) {
8729 + printk("ipt_random: invalid average %u\n", info->average);
8736 +static struct ipt_match ipt_rand_reg = {
8740 + ipt_rand_checkentry,
8744 +static int __init init(void)
8746 + if (ipt_register_match(&ipt_rand_reg))
8749 + printk("ipt_random match loaded\n");
8753 +static void __exit fini(void)
8755 + ipt_unregister_match(&ipt_rand_reg);
8756 + printk("ipt_random match unloaded\n");
8761 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_realm.c linux-2.6.3/net/ipv4/netfilter/ipt_realm.c
8762 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_realm.c 1970-01-01 01:00:00.000000000 +0100
8763 +++ linux-2.6.3/net/ipv4/netfilter/ipt_realm.c 2004-02-19 08:47:33.450318894 +0100
8765 +/* Kernel module to match realm from routing. */
8766 +#include <linux/module.h>
8767 +#include <linux/skbuff.h>
8768 +#include <linux/netdevice.h>
8769 +#include <net/route.h>
8771 +#include <linux/netfilter_ipv4/ipt_realm.h>
8772 +#include <linux/netfilter_ipv4/ip_tables.h>
8774 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
8775 +MODULE_LICENSE("GPL");
8778 +match(const struct sk_buff *skb,
8779 + const struct net_device *in,
8780 + const struct net_device *out,
8781 + const void *matchinfo,
8784 + u_int16_t datalen,
8787 + const struct ipt_realm_info *info = matchinfo;
8788 + struct dst_entry *dst = skb->dst;
8793 + id = dst->tclassid;
8795 + return (info->id == (id & info->mask)) ^ info->invert;
8798 +static int check(const char *tablename,
8799 + const struct ipt_ip *ip,
8801 + unsigned int matchsize,
8802 + unsigned int hook_mask)
8805 + & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
8806 + (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
8807 + printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
8808 + "LOCAL_IN or FORWARD.\n");
8812 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
8818 +static struct ipt_match realm_match
8819 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
8821 +static int __init init(void)
8823 + return ipt_register_match(&realm_match);
8826 +static void __exit fini(void)
8828 + ipt_unregister_match(&realm_match);
8833 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_time.c linux-2.6.3/net/ipv4/netfilter/ipt_time.c
8834 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_time.c 1970-01-01 01:00:00.000000000 +0100
8835 +++ linux-2.6.3/net/ipv4/netfilter/ipt_time.c 2004-02-19 08:47:33.998186927 +0100
8838 + This is a module which is used for time matching
8839 + It is using some modified code from dietlibc (localtime() function)
8840 + that you can find at http://www.fefe.de/dietlibc/
8841 + This file is distributed under the terms of the GNU General Public
8842 + License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
8843 + 2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
8844 + 2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
8845 + thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
8846 + 2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
8847 + 2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
8848 + added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
8851 +#include <linux/module.h>
8852 +#include <linux/skbuff.h>
8853 +#include <linux/netfilter_ipv4/ip_tables.h>
8854 +#include <linux/netfilter_ipv4/ipt_time.h>
8855 +#include <linux/time.h>
8857 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
8858 +MODULE_DESCRIPTION("Match arrival timestamp");
8859 +MODULE_LICENSE("GPL");
8863 + int tm_sec; /* Seconds. [0-60] (1 leap second) */
8864 + int tm_min; /* Minutes. [0-59] */
8865 + int tm_hour; /* Hours. [0-23] */
8866 + int tm_mday; /* Day. [1-31] */
8867 + int tm_mon; /* Month. [0-11] */
8868 + int tm_year; /* Year - 1900. */
8869 + int tm_wday; /* Day of week. [0-6] */
8870 + int tm_yday; /* Days in year.[0-365] */
8871 + int tm_isdst; /* DST. [-1/0/1]*/
8873 + long int tm_gmtoff; /* we don't care, we count from GMT */
8874 + const char *tm_zone; /* we don't care, we count from GMT */
8878 +localtime(const time_t *timepr, struct tm *r);
8881 +match(const struct sk_buff *skb,
8882 + const struct net_device *in,
8883 + const struct net_device *out,
8884 + const void *matchinfo,
8887 + u_int16_t datalen,
8890 + const struct ipt_time_info *info = matchinfo; /* match info for rule */
8891 + struct tm currenttime; /* time human readable */
8892 + u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
8893 + u_int16_t packet_time;
8894 + struct timeval kerneltimeval;
8895 + time_t packet_local_time;
8897 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
8898 + if (info->kerneltime)
8900 + do_gettimeofday(&kerneltimeval);
8901 + packet_local_time = kerneltimeval.tv_sec;
8904 + packet_local_time = skb->stamp.tv_sec;
8906 + /* Transform the timestamp of the packet, in a human readable form */
8907 + localtime(&packet_local_time, ¤ttime);
8909 + /* check if we match this timestamp, we start by the days... */
8910 + if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
8911 + return 0; /* the day doesn't match */
8913 + /* ... check the time now */
8914 + packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
8915 + if ((packet_time < info->time_start) || (packet_time > info->time_stop))
8918 + /* here we match ! */
8923 +checkentry(const char *tablename,
8924 + const struct ipt_ip *ip,
8926 + unsigned int matchsize,
8927 + unsigned int hook_mask)
8929 + struct ipt_time_info *info = matchinfo; /* match info for rule */
8931 + /* First, check that we are in the correct hook */
8932 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
8934 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
8936 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
8939 + /* we use the kerneltime if we are in forward or output */
8940 + info->kerneltime = 1;
8941 + if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
8942 + /* if not, we use the skb time */
8943 + info->kerneltime = 0;
8945 + /* Check the size */
8946 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
8948 + /* Now check the coherence of the data ... */
8949 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
8950 + (info->time_stop > 1439))
8952 + printk(KERN_WARNING "ipt_time: invalid argument\n");
8959 +static struct ipt_match time_match
8960 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
8962 +static int __init init(void)
8964 + printk("ipt_time loading\n");
8965 + return ipt_register_match(&time_match);
8968 +static void __exit fini(void)
8970 + ipt_unregister_match(&time_match);
8971 + printk("ipt_time unloaded\n");
8978 +/* The part below is borowed and modified from dietlibc */
8980 +/* seconds per day */
8981 +#define SPD 24*60*60
8984 +localtime(const time_t *timepr, struct tm *r) {
8987 + extern struct timezone sys_tz;
8988 + const unsigned int __spm[12] =
8995 + (31+28+31+30+31+30),
8996 + (31+28+31+30+31+30+31),
8997 + (31+28+31+30+31+30+31+31),
8998 + (31+28+31+30+31+30+31+31+30),
8999 + (31+28+31+30+31+30+31+31+30+31),
9000 + (31+28+31+30+31+30+31+31+30+31+30),
9002 + register time_t work;
9004 + timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
9006 + r->tm_sec=work%60; work/=60;
9007 + r->tm_min=work%60; r->tm_hour=work/60;
9009 + r->tm_wday=(4+work)%7;
9010 + for (i=1970; ; ++i) {
9011 + register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
9017 + r->tm_year=i-1900;
9018 + for (i=11; i && __spm[i]>work; --i) ;
9020 + r->tm_mday=work-__spm[i]+1;
9022 diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_u32.c linux-2.6.3/net/ipv4/netfilter/ipt_u32.c
9023 --- linux-2.6.3.org/net/ipv4/netfilter/ipt_u32.c 1970-01-01 01:00:00.000000000 +0100
9024 +++ linux-2.6.3/net/ipv4/netfilter/ipt_u32.c 2004-02-19 08:47:34.549054238 +0100
9026 +/* Kernel module to match u32 packet content. */
9029 +U32 tests whether quantities of up to 4 bytes extracted from a packet
9030 +have specified values. The specification of what to extract is general
9031 +enough to find data at given offsets from tcp headers or payloads.
9034 + The argument amounts to a program in a small language described below.
9035 + tests := location = value | tests && location = value
9036 + value := range | value , range
9037 + range := number | number : number
9038 + a single number, n, is interpreted the same as n:n
9039 + n:m is interpreted as the range of numbers >=n and <=m
9040 + location := number | location operator number
9041 + operator := & | << | >> | @
9043 + The operators &, <<, >>, && mean the same as in c. The = is really a set
9044 + membership operator and the value syntax describes a set. The @ operator
9045 + is what allows moving to the next header and is described further below.
9047 + *** Until I can find out how to avoid it, there are some artificial limits
9048 + on the size of the tests:
9049 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
9050 + - no more than 10 ranges (and 9 commas) per value
9051 + - no more than 10 numbers (and 9 operators) per location
9053 + To describe the meaning of location, imagine the following machine that
9054 + interprets it. There are three registers:
9055 + A is of type char*, initially the address of the IP header
9056 + B and C are unsigned 32 bit integers, initially zero
9058 + The instructions are:
9059 + number B = number;
9060 + C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
9061 + &number C = C&number
9062 + <<number C = C<<number
9063 + >>number C = C>>number
9064 + @number A = A+C; then do the instruction number
9065 + Any access of memory outside [skb->head,skb->end] causes the match to fail.
9066 + Otherwise the result of the computation is the final value of C.
9068 + Whitespace is allowed but not required in the tests.
9069 + However the characters that do occur there are likely to require
9070 + shell quoting, so it's a good idea to enclose the arguments in quotes.
9073 + match IP packets with total length >= 256
9074 + The IP header contains a total length field in bytes 2-3.
9075 + --u32 "0&0xFFFF=0x100:0xFFFF"
9077 + AND that with FFFF (giving bytes 2-3),
9078 + and test whether that's in the range [0x100:0xFFFF]
9080 +Example: (more realistic, hence more complicated)
9081 + match icmp packets with icmp type 0
9082 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
9083 + --u32 "6&0xFF=1 && ...
9084 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
9085 + Next test that it's not a fragment.
9086 + (If so it might be part of such a packet but we can't always tell.)
9087 + n.b. This test is generally needed if you want to match anything
9088 + beyond the IP header.
9089 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
9090 + packet (not a fragment). Alternatively, you can allow first fragments
9091 + by only testing the last 5 bits of byte 6.
9092 + ... 4&0x3FFF=0 && ...
9093 + Last test: the first byte past the IP header (the type) is 0
9094 + This is where we have to use the @syntax. The length of the IP header
9095 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
9097 + ... 0>>22&0x3C@0>>24=0"
9098 + The first 0 means read bytes 0-3,
9099 + >>22 means shift that 22 bits to the right. Shifting 24 bits would give
9100 + the first byte, so only 22 bits is four times that plus a few more bits.
9101 + &3C then eliminates the two extra bits on the right and the first four
9102 + bits of the first byte.
9103 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
9104 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz,
9105 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
9106 + @ means to use this number as a new offset into the packet, and read
9107 + four bytes starting from there. This is the first 4 bytes of the icmp
9108 + payload, of which byte 0 is the icmp type. Therefore we simply shift
9109 + the value 24 to the right to throw out all but the first byte and compare
9110 + the result with 0.
9113 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
9114 + First we test that the packet is a tcp packet (similar to icmp).
9115 + --u32 "6&0xFF=6 && ...
9116 + Next, test that it's not a fragment (same as above).
9117 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
9118 + 0>>22&3C as above computes the number of bytes in the IP header.
9119 + @ makes this the new offset into the packet, which is the start of the
9120 + tcp header. The length of the tcp header (again in 32 bit words) is
9121 + the left half of byte 12 of the tcp header. The 12>>26&3C
9122 + computes this length in bytes (similar to the IP header before).
9123 + @ makes this the new offset, which is the start of the tcp payload.
9124 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
9125 + result is any of 1, 2, 5 or 8
9128 +#include <linux/module.h>
9129 +#include <linux/skbuff.h>
9131 +#include <linux/netfilter_ipv4/ipt_u32.h>
9132 +#include <linux/netfilter_ipv4/ip_tables.h>
9134 +/* #include <asm-i386/timex.h> for timing */
9136 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
9137 +MODULE_DESCRIPTION("IP tables u32 matching module");
9138 +MODULE_LICENSE("GPL");
9141 +match(const struct sk_buff *skb,
9142 + const struct net_device *in,
9143 + const struct net_device *out,
9144 + const void *matchinfo,
9147 + u_int16_t datalen,
9150 + const struct ipt_u32 *data = matchinfo;
9152 + unsigned char* origbase = (char*)skb->nh.iph;
9153 + unsigned char* base = origbase;
9154 + unsigned char* head = skb->head;
9155 + unsigned char* end = skb->end;
9157 + u_int32_t pos, val;
9158 + /* unsigned long long cycles1, cycles2, cycles3, cycles4;
9159 + cycles1 = get_cycles(); */
9161 + for (testind=0; testind < data->ntests; testind++) {
9162 + base = origbase; /* reset for each test */
9163 + pos = data->tests[testind].location[0].number;
9164 + if (base+pos+3 > end || base+pos < head)
9166 + val = (base[pos]<<24) + (base[pos+1]<<16) +
9167 + (base[pos+2]<<8) + base[pos+3];
9168 + nnums = data->tests[testind].nnums;
9169 + for (i=1; i < nnums; i++) {
9170 + u_int32_t number = data->tests[testind].location[i].number;
9171 + switch (data->tests[testind].location[i].nextop) {
9173 + val = val & number;
9175 + case IPT_U32_LEFTSH:
9176 + val = val << number;
9178 + case IPT_U32_RIGHTSH:
9179 + val = val >> number;
9182 + base = base + val;
9184 + if (base+pos+3 > end || base+pos < head)
9186 + val = (base[pos]<<24) + (base[pos+1]<<16) +
9187 + (base[pos+2]<<8) + base[pos+3];
9191 + nvals = data->tests[testind].nvalues;
9192 + for (i=0; i < nvals; i++) {
9193 + if ((data->tests[testind].value[i].min <= val) &&
9194 + (val <= data->tests[testind].value[i].max)) {
9198 + if (i >= data->tests[testind].nvalues) {
9199 + /* cycles2 = get_cycles();
9200 + printk("failed %d in %d cycles\n", testind,
9201 + cycles2-cycles1); */
9205 + /* cycles2 = get_cycles();
9206 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
9211 +checkentry(const char *tablename,
9212 + const struct ipt_ip *ip,
9214 + unsigned int matchsize,
9215 + unsigned int hook_mask)
9217 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
9222 +static struct ipt_match u32_match
9223 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
9225 +static int __init init(void)
9227 + return ipt_register_match(&u32_match);
9230 +static void __exit fini(void)
9232 + ipt_unregister_match(&u32_match);
9237 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/Kconfig linux-2.6.3/net/ipv6/netfilter/Kconfig
9238 --- linux-2.6.3.org/net/ipv6/netfilter/Kconfig 2004-02-18 04:59:20.000000000 +0100
9239 +++ linux-2.6.3/net/ipv6/netfilter/Kconfig 2004-02-19 08:47:32.341585959 +0100
9240 @@ -218,5 +218,85 @@
9241 To compile it as a module, choose M here. If unsure, say N.
9243 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
9244 +config IP6_NF_TARGET_HL
9245 + tristate 'HL target support'
9246 + depends on IP6_NF_MANGLE
9248 + This allows the user to set the IPv6 Hop Limit value on a packet or
9249 + to increment or decrement it by a given value.
9252 + # ip6tables -t mangle -A OUTPUT -j HL --hl-inc 1
9253 + # ip6tables -t mangle -A INPUT -j HL --hl-eq 64
9254 + # ip6tables -t mangle -A OUTPUT -j HL --hl-dec 2
9256 +config IP6_NF_TARGET_REJECT
9257 + tristate 'REJECT target support'
9258 + depends on IP6_NF_FILTER
9260 + This CONFIG_IP6_NF_TARGET_REJECT option adds a REJECT target to ip6tables.
9261 + Please keep in mind that the icmp-types are different from the icmpv6 types
9262 + (see ip6tables -j REJECT -h for more info)
9264 +config IP6_NF_MATCH_FUZZY
9265 + tristate 'Fuzzy match support'
9266 + depends on IP6_NF_FILTER
9268 + This option adds a `fuzzy' match which allows you to match packets according to
9269 + a dynamic profile implemented by means of a simple Fuzzy Logic Controller (FLC)
9271 +config IP6_NF_MATCH_NTH
9272 + tristate 'Nth match support'
9273 + depends on IP6_NF_IPTABLES
9275 + This option adds an iptables `Nth' match, which allows you to match every Nth
9276 + packet encountered. By default there are 16 different counters that can be
9279 + This match functions in one of two ways
9280 + 1) Match ever Nth packet, and only the Nth packet.
9282 + iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
9283 + This rule will drop every 10th packet.
9284 + 2) Unique rule for every packet. This is an easy and quick
9285 + method to produce load-balancing for both inbound and outbound.
9287 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
9288 + --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
9289 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
9290 + --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
9291 + iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
9292 + --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
9293 + This example evenly splits connections between the three SNAT
9296 + By using the mangle table and iproute2, you can setup complex
9297 + load-balanced routing. There's lot of other uses. Be creative!
9299 + Suppported options are:
9300 + --every Nth Match every Nth packet
9301 + [--counter] num Use counter 0-15 (default:0)
9302 + [--start] num Initialize the counter at the number 'num'
9303 + instead of 0. Must be between 0 and Nth-1
9304 + [--packet] num Match on 'num' packet. Must be between 0
9306 + If --packet is used for a counter than
9307 + there must be Nth number of --packet
9308 + rules, covering all values between 0 and
9309 + Nth-1 inclusively.
9311 +config IP6_NF_MATCH_RANDOM
9312 + tristate 'Random match support'
9313 + depends on IP6_NF_IPTABLES
9315 + This option adds a `random' match,
9316 + which allow you to match packets randomly
9317 + following a given probability.
9319 + Suppported options are:
9321 + [--average] percent will match randomly packets with a probability of
9322 + 'percent'. default is 50%
9326 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/Makefile linux-2.6.3/net/ipv6/netfilter/Makefile
9327 --- linux-2.6.3.org/net/ipv6/netfilter/Makefile 2004-02-18 04:58:26.000000000 +0100
9328 +++ linux-2.6.3/net/ipv6/netfilter/Makefile 2004-02-19 08:47:32.341585959 +0100
9330 obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
9331 obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
9332 obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
9333 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
9334 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
9335 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
9336 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
9338 obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
9339 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
9340 obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
9341 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
9342 obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
9343 obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
9345 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
9347 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
9348 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
9349 obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
9350 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_HL.c linux-2.6.3/net/ipv6/netfilter/ip6t_HL.c
9351 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_HL.c 1970-01-01 01:00:00.000000000 +0100
9352 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_HL.c 2004-02-19 09:07:45.267493759 +0100
9355 + * Hop Limit modification target for ip6tables
9356 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
9357 + * Based on HW's TTL module
9359 + * This software is distributed under the terms of GNU GPL
9362 +#include <linux/module.h>
9363 +#include <linux/skbuff.h>
9364 +#include <linux/ip.h>
9366 +#include <linux/netfilter_ipv6/ip6_tables.h>
9367 +#include <linux/netfilter_ipv6/ip6t_HL.h>
9369 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
9370 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
9371 +MODULE_LICENSE("GPL");
9373 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
9374 + const struct net_device *in, const struct net_device *out,
9375 + const void *targinfo, void *userinfo)
9377 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
9378 + const struct ip6t_HL_info *info = targinfo;
9379 + u_int16_t diffs[2];
9382 + switch (info->mode) {
9384 + new_hl = info->hop_limit;
9387 + new_hl = ip6h->hop_limit + info->hop_limit;
9392 + new_hl = ip6h->hop_limit + info->hop_limit;
9397 + new_hl = ip6h->hop_limit;
9401 + if (new_hl != ip6h->hop_limit) {
9402 + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
9403 + ip6h->hop_limit = new_hl;
9404 + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
9407 + return IP6T_CONTINUE;
9410 +static int ip6t_hl_checkentry(const char *tablename,
9411 + const struct ip6t_entry *e,
9413 + unsigned int targinfosize,
9414 + unsigned int hook_mask)
9416 + struct ip6t_HL_info *info = targinfo;
9418 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
9419 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
9421 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
9425 + if (strcmp(tablename, "mangle")) {
9426 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
9430 + if (info->mode > IP6T_HL_MAXMODE) {
9431 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
9436 + if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
9437 + printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
9444 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
9445 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
9447 +static int __init init(void)
9449 + return ip6t_register_target(&ip6t_HL);
9452 +static void __exit fini(void)
9454 + ip6t_unregister_target(&ip6t_HL);
9459 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.6.3/net/ipv6/netfilter/ip6t_REJECT.c
9460 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_REJECT.c 1970-01-01 01:00:00.000000000 +0100
9461 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_REJECT.c 2004-02-19 08:47:25.025348256 +0100
9464 + * This is a module which is used for rejecting packets.
9465 + * Added support for customized reject packets (Jozsef Kadlecsik).
9467 + * Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
9469 +#include <linux/config.h>
9470 +#include <linux/module.h>
9471 +#include <linux/skbuff.h>
9472 +#include <linux/icmpv6.h>
9473 +#include <net/tcp.h>
9474 +#include <linux/netfilter_ipv6/ip6_tables.h>
9475 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
9478 +#define DEBUGP printk
9480 +#define DEBUGP(format, args...)
9484 +/* Send RST reply */
9485 +static void send_reset(struct sk_buff *oldskb)
9487 + struct sk_buff *nskb;
9488 + struct tcphdr *otcph, *tcph;
9489 + struct rtable *rt;
9490 + unsigned int otcplen;
9493 + /* IP header checks: fragment, too short. */
9494 + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
9495 + || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
9498 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
9499 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
9501 + /* No RST for RST. */
9505 + /* Check checksum. */
9506 + if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
9507 + oldskb->nh.iph->daddr,
9508 + csum_partial((char *)otcph, otcplen, 0)) != 0)
9511 + /* Copy skb (even if skb is about to be dropped, we can't just
9512 + clone it because there may be other things, such as tcpdump,
9513 + interested in it) */
9514 + nskb = skb_copy(oldskb, GFP_ATOMIC);
9518 + /* This packet will not be the same as the other: clear nf fields */
9519 + nf_conntrack_put(nskb->nfct);
9520 + nskb->nfct = NULL;
9521 + nskb->nfcache = 0;
9522 +#ifdef CONFIG_NETFILTER_DEBUG
9523 + nskb->nf_debug = 0;
9526 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
9528 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
9529 + tcph->source = xchg(&tcph->dest, tcph->source);
9531 + /* Truncate to length (no data) */
9532 + tcph->doff = sizeof(struct tcphdr)/4;
9533 + skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
9534 + nskb->nh.iph->tot_len = htons(nskb->len);
9538 + tcph->seq = otcph->ack_seq;
9539 + tcph->ack_seq = 0;
9542 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
9543 + + otcplen - (otcph->doff<<2));
9548 + ((u_int8_t *)tcph)[13] = 0;
9550 + tcph->ack = needs_ack;
9553 + tcph->urg_ptr = 0;
9555 + /* Adjust TCP checksum */
9557 + tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
9558 + nskb->nh.iph->saddr,
9559 + nskb->nh.iph->daddr,
9560 + csum_partial((char *)tcph,
9561 + sizeof(struct tcphdr), 0));
9563 + /* Adjust IP TTL, DF */
9564 + nskb->nh.iph->ttl = MAXTTL;
9565 + /* Set DF, id = 0 */
9566 + nskb->nh.iph->frag_off = htons(IP_DF);
9567 + nskb->nh.iph->id = 0;
9569 + /* Adjust IP checksum */
9570 + nskb->nh.iph->check = 0;
9571 + nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
9572 + nskb->nh.iph->ihl);
9575 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
9576 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
9580 + dst_release(nskb->dst);
9581 + nskb->dst = &rt->u.dst;
9583 + /* "Never happens" */
9584 + if (nskb->len > nskb->dst->pmtu)
9587 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
9588 + ip_finish_output);
9596 +static unsigned int reject6_target(struct sk_buff **pskb,
9597 + unsigned int hooknum,
9598 + const struct net_device *in,
9599 + const struct net_device *out,
9600 + const void *targinfo,
9603 + const struct ip6t_reject_info *reject = targinfo;
9605 + /* WARNING: This code causes reentry within ip6tables.
9606 + This means that the ip6tables jump stack is now crap. We
9607 + must return an absolute verdict. --RR */
9608 + DEBUGP("REJECTv6: calling icmpv6_send\n");
9609 + switch (reject->with) {
9610 + case IP6T_ICMP6_NO_ROUTE:
9611 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
9613 + case IP6T_ICMP6_ADM_PROHIBITED:
9614 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
9616 + case IP6T_ICMP6_NOT_NEIGHBOUR:
9617 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
9619 + case IP6T_ICMP6_ADDR_UNREACH:
9620 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
9622 + case IP6T_ICMP6_PORT_UNREACH:
9623 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
9626 + case IPT_ICMP_ECHOREPLY: {
9627 + struct icmp6hdr *icmph = (struct icmphdr *)
9628 + ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
9629 + unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
9631 + /* Not non-head frags, or truncated */
9632 + if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
9633 + && datalen >= 4) {
9634 + /* Usually I don't like cut & pasting code,
9635 + but dammit, my party is starting in 45
9637 + struct icmp_bxm icmp_param;
9639 + icmp_param.icmph=*icmph;
9640 + icmp_param.icmph.type=ICMP_ECHOREPLY;
9641 + icmp_param.data_ptr=(icmph+1);
9642 + icmp_param.data_len=datalen;
9643 + icmp_reply(&icmp_param, *pskb);
9647 + case IPT_TCP_RESET:
9648 + send_reset(*pskb);
9652 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
9659 +static inline int find_ping_match(const struct ip6t_entry_match *m)
9661 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
9663 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
9664 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
9665 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
9671 +static int check(const char *tablename,
9672 + const struct ip6t_entry *e,
9674 + unsigned int targinfosize,
9675 + unsigned int hook_mask)
9677 + const struct ip6t_reject_info *rejinfo = targinfo;
9679 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
9680 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
9684 + /* Only allow these for packet filtering. */
9685 + if (strcmp(tablename, "filter") != 0) {
9686 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
9689 + if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
9690 + | (1 << NF_IP6_FORWARD)
9691 + | (1 << NF_IP6_LOCAL_OUT))) != 0) {
9692 + DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
9696 + if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
9697 + /* Must specify that it's an ICMP ping packet. */
9698 + if (e->ipv6.proto != IPPROTO_ICMPV6
9699 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
9700 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
9703 + /* Must contain ICMP match. */
9704 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
9705 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
9708 + } else if (rejinfo->with == IP6T_TCP_RESET) {
9709 + /* Must specify that it's a TCP packet */
9710 + if (e->ipv6.proto != IPPROTO_TCP
9711 + || (e->ipv6.invflags & IP6T_INV_PROTO)) {
9712 + DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
9720 +static struct ip6t_target ip6t_reject_reg
9721 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
9723 +static int __init init(void)
9725 + if (ip6t_register_target(&ip6t_reject_reg))
9730 +static void __exit fini(void)
9732 + ip6t_unregister_target(&ip6t_reject_reg);
9737 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.6.3/net/ipv6/netfilter/ip6t_fuzzy.c
9738 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_fuzzy.c 1970-01-01 01:00:00.000000000 +0100
9739 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_fuzzy.c 2004-02-19 08:47:27.856666262 +0100
9742 + * This module implements a simple TSK FLC
9743 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
9744 + * to limit , in an adaptive and flexible way , the packet rate crossing
9745 + * a given stream . It serves as an initial and very simple (but effective)
9746 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
9747 + * As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
9748 + * into our code in a precise , adaptive and efficient manner.
9749 + * The goal is very similar to that of "limit" match , but using techniques of
9750 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
9751 + * avoiding over and undershoots - and stuff like that .
9754 + * 2002-08-10 Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
9755 + * 2002-08-17 : Changed to eliminate floating point operations .
9756 + * 2002-08-23 : Coding style changes .
9757 + * 2003-04-08 Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
9760 +#include <linux/module.h>
9761 +#include <linux/skbuff.h>
9762 +#include <linux/ipv6.h>
9763 +#include <linux/random.h>
9764 +#include <net/tcp.h>
9765 +#include <linux/spinlock.h>
9766 +#include <linux/netfilter_ipv6/ip6_tables.h>
9767 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
9770 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
9771 + Expressed in percentage
9774 +#define PAR_LOW 1/100
9777 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
9779 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
9780 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
9781 +MODULE_LICENSE("GPL");
9783 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
9785 + if (tx >= maxi) return 100;
9787 + if (tx <= mini) return 0;
9789 + return ((100 * (tx-mini)) / (maxi-mini));
9792 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
9794 + if (tx <= mini) return 100;
9796 + if (tx >= maxi) return 0;
9798 + return ((100 * (maxi - tx)) / (maxi - mini));
9803 +ip6t_fuzzy_match(const struct sk_buff *pskb,
9804 + const struct net_device *in,
9805 + const struct net_device *out,
9806 + const void *matchinfo,
9809 + u_int16_t datalen,
9812 + /* From userspace */
9814 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
9816 + u_int8_t random_number;
9817 + unsigned long amount;
9818 + u_int8_t howhigh, howlow;
9821 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
9823 + info->bytes_total += pskb->len;
9824 + info->packets_total++;
9826 + info->present_time = jiffies;
9828 + if (info->present_time >= info->previous_time)
9829 + amount = info->present_time - info->previous_time;
9831 + /* There was a transition : I choose to re-sample
9832 + and keep the old acceptance rate...
9836 + info->previous_time = info->present_time;
9837 + info->bytes_total = info->packets_total = 0;
9840 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
9842 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
9845 + info->previous_time = info->present_time;
9846 + info->bytes_total = info->packets_total = 0;
9848 + howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
9849 + howlow = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
9851 + info->acceptance_rate = (u_int8_t) \
9852 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
9854 + /* In fact, the above defuzzification would require a denominator
9855 + * proportional to (howhigh+howlow) but, in this particular case,
9856 + * that expression is constant.
9857 + * An imediate consequence is that it is not necessary to call
9858 + * both mf_high and mf_low - but to keep things understandable,
9864 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
9867 + if (info->acceptance_rate < 100)
9869 + get_random_bytes((void *)(&random_number), 1);
9871 + /* If within the acceptance , it can pass => don't match */
9872 + if (random_number <= (255 * info->acceptance_rate) / 100)
9875 + return 1; /* It can't pass (It matches) */
9878 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
9883 +ip6t_fuzzy_checkentry(const char *tablename,
9884 + const struct ip6t_ip6 *ip,
9886 + unsigned int matchsize,
9887 + unsigned int hook_mask)
9890 + const struct ip6t_fuzzy_info *info = matchinfo;
9892 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
9893 + printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
9894 + IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
9898 + if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
9899 + || (info->minimum_rate >= info->maximum_rate)) {
9900 + printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
9907 +static struct ip6t_match ip6t_fuzzy_reg = {
9911 + ip6t_fuzzy_checkentry,
9915 +static int __init init(void)
9917 + if (ip6t_register_match(&ip6t_fuzzy_reg))
9923 +static void __exit fini(void)
9925 + ip6t_unregister_match(&ip6t_fuzzy_reg);
9930 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_nth.c linux-2.6.3/net/ipv6/netfilter/ip6t_nth.c
9931 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_nth.c 1970-01-01 01:00:00.000000000 +0100
9932 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_nth.c 2004-02-19 08:47:29.580251094 +0100
9935 + This is a module which is used for match support for every Nth packet
9936 + This file is distributed under the terms of the GNU General Public
9937 + License (GPL). Copies of the GPL can be obtained from:
9938 + ftp://prep.ai.mit.edu/pub/gnu/GPL
9940 + 2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
9941 + 2001-09-20 Richard Wagner (rwagner@cloudnet.com)
9942 + * added support for multiple counters
9943 + * added support for matching on individual packets
9944 + in the counter cycle
9945 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
9949 +#include <linux/module.h>
9950 +#include <linux/skbuff.h>
9951 +#include <linux/ip.h>
9952 +#include <net/tcp.h>
9953 +#include <linux/spinlock.h>
9954 +#include <linux/netfilter_ipv6/ip6_tables.h>
9955 +#include <linux/netfilter_ipv6/ip6t_nth.h>
9957 +MODULE_LICENSE("GPL");
9960 + * State information.
9967 +static struct state states[IP6T_NTH_NUM_COUNTERS];
9970 +ip6t_nth_match(const struct sk_buff *pskb,
9971 + const struct net_device *in,
9972 + const struct net_device *out,
9973 + const void *matchinfo,
9976 + u_int16_t datalen,
9979 + /* Parameters from userspace */
9980 + const struct ip6t_nth_info *info = matchinfo;
9981 + unsigned counter = info->counter;
9982 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
9984 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
9988 + spin_lock(&states[counter].lock);
9990 + /* Are we matching every nth packet?*/
9991 + if (info->packet == 0xFF)
9993 + /* We're matching every nth packet and only every nth packet*/
9994 + /* Do we match or invert match? */
9995 + if (info->not == 0)
9997 + if (states[counter].number == 0)
9999 + ++states[counter].number;
10002 + if (states[counter].number >= info->every)
10003 + states[counter].number = 0; /* reset the counter */
10005 + ++states[counter].number;
10010 + if (states[counter].number == 0)
10012 + ++states[counter].number;
10015 + if (states[counter].number >= info->every)
10016 + states[counter].number = 0;
10018 + ++states[counter].number;
10024 + /* We're using the --packet, so there must be a rule for every value */
10025 + if (states[counter].number == info->packet)
10027 + /* only increment the counter when a match happens */
10028 + if (states[counter].number >= info->every)
10029 + states[counter].number = 0; /* reset the counter */
10031 + ++states[counter].number;
10039 + /* don't match */
10040 + spin_unlock(&states[counter].lock);
10044 + spin_unlock(&states[counter].lock);
10049 +ip6t_nth_checkentry(const char *tablename,
10050 + const struct ip6t_ip6 *e,
10052 + unsigned int matchsize,
10053 + unsigned int hook_mask)
10055 + /* Parameters from userspace */
10056 + const struct ip6t_nth_info *info = matchinfo;
10057 + unsigned counter = info->counter;
10058 + if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS))
10060 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
10064 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
10065 + printk("nth: matchsize %u != %u\n", matchsize,
10066 + IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
10070 + states[counter].number = info->startat;
10075 +static struct ip6t_match ip6t_nth_reg = {
10079 + ip6t_nth_checkentry,
10083 +static int __init init(void)
10085 + unsigned counter;
10086 + memset(&states, 0, sizeof(states));
10087 + if (ip6t_register_match(&ip6t_nth_reg))
10090 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
10092 + spin_lock_init(&(states[counter].lock));
10095 + printk("ip6t_nth match loaded\n");
10099 +static void __exit fini(void)
10101 + ip6t_unregister_match(&ip6t_nth_reg);
10102 + printk("ip6t_nth match unloaded\n");
10105 +module_init(init);
10106 +module_exit(fini);
10107 diff -Nur linux-2.6.3.org/net/ipv6/netfilter/ip6t_random.c linux-2.6.3/net/ipv6/netfilter/ip6t_random.c
10108 --- linux-2.6.3.org/net/ipv6/netfilter/ip6t_random.c 1970-01-01 01:00:00.000000000 +0100
10109 +++ linux-2.6.3/net/ipv6/netfilter/ip6t_random.c 2004-02-19 08:47:32.336587163 +0100
10112 + This is a module which is used for a "random" match support.
10113 + This file is distributed under the terms of the GNU General Public
10114 + License (GPL). Copies of the GPL can be obtained from:
10115 + ftp://prep.ai.mit.edu/pub/gnu/GPL
10117 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
10118 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
10121 +#include <linux/module.h>
10122 +#include <linux/skbuff.h>
10123 +#include <linux/ip.h>
10124 +#include <linux/random.h>
10125 +#include <net/tcp.h>
10126 +#include <linux/spinlock.h>
10127 +#include <linux/netfilter_ipv6/ip6_tables.h>
10128 +#include <linux/netfilter_ipv6/ip6t_random.h>
10130 +MODULE_LICENSE("GPL");
10133 +ip6t_rand_match(const struct sk_buff *pskb,
10134 + const struct net_device *in,
10135 + const struct net_device *out,
10136 + const void *matchinfo,
10139 + u_int16_t datalen,
10142 + /* Parameters from userspace */
10143 + const struct ip6t_rand_info *info = matchinfo;
10144 + u_int8_t random_number;
10146 + /* get 1 random number from the kernel random number generation routine */
10147 + get_random_bytes((void *)(&random_number), 1);
10149 + /* Do we match ? */
10150 + if (random_number <= info->average)
10157 +ip6t_rand_checkentry(const char *tablename,
10158 + const struct ip6t_ip6 *e,
10160 + unsigned int matchsize,
10161 + unsigned int hook_mask)
10163 + /* Parameters from userspace */
10164 + const struct ip6t_rand_info *info = matchinfo;
10166 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
10167 + printk("ip6t_random: matchsize %u != %u\n", matchsize,
10168 + IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
10172 + /* must be 1 <= average % <= 99 */
10173 + /* 1 x 2.55 = 2 */
10174 + /* 99 x 2.55 = 252 */
10175 + if ((info->average < 2) || (info->average > 252)) {
10176 + printk("ip6t_random: invalid average %u\n", info->average);
10183 +static struct ip6t_match ip6t_rand_reg = {
10187 + ip6t_rand_checkentry,
10191 +static int __init init(void)
10193 + if (ip6t_register_match(&ip6t_rand_reg))
10196 + printk("ip6t_random match loaded\n");
10200 +static void __exit fini(void)
10202 + ip6t_unregister_match(&ip6t_rand_reg);
10203 + printk("ip6t_random match unloaded\n");
10206 +module_init(init);
10207 +module_exit(fini);