]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.x-patch-o-matic-ng-base-20040219.patch
- added description of djurban's branch
[packages/kernel.git] / 2.6.x-patch-o-matic-ng-base-20040219.patch
CommitLineData
2df0d5fe 1diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.6.3/include/linux/netfilter_ipv4/ip_pool.h
2--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_pool.h 1970-01-01 01:00:00.000000000 +0100
3+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_pool.h 2004-02-19 08:47:30.712978249 +0100
4@@ -0,0 +1,64 @@
5+#ifndef _IP_POOL_H
6+#define _IP_POOL_H
7+
8+/***************************************************************************/
9+/* This program is free software; you can redistribute it and/or modify */
10+/* it under the terms of the GNU General Public License as published by */
11+/* the Free Software Foundation; either version 2 of the License, or */
12+/* (at your option) any later version. */
13+/* */
14+/* This program is distributed in the hope that it will be useful, */
15+/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
16+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
17+/* GNU General Public License for more details. */
18+/* */
19+/* You should have received a copy of the GNU General Public License */
20+/* along with this program; if not, write to the Free Software */
21+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
22+/***************************************************************************/
23+
24+/* A sockopt of such quality has hardly ever been seen before on the open
25+ * market! This little beauty, hardly ever used: above 64, so it's
26+ * traditionally used for firewalling, not touched (even once!) by the
27+ * 2.0, 2.2 and 2.4 kernels!
28+ *
29+ * Comes with its own certificate of authenticity, valid anywhere in the
30+ * Free world!
31+ *
32+ * Rusty, 19.4.2000
33+ */
34+#define SO_IP_POOL 81
35+
36+typedef int ip_pool_t; /* pool index */
37+#define IP_POOL_NONE ((ip_pool_t)-1)
38+
39+struct ip_pool_request {
40+ int op;
41+ ip_pool_t index;
42+ u_int32_t addr;
43+ u_int32_t addr2;
44+};
45+
46+/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
47+
48+#define IP_POOL_BAD001 0x00000010
49+
50+#define IP_POOL_FLUSH 0x00000011 /* req.index, no arguments */
51+#define IP_POOL_INIT 0x00000012 /* from addr to addr2 incl. */
52+#define IP_POOL_DESTROY 0x00000013 /* req.index, no arguments */
53+#define IP_POOL_ADD_ADDR 0x00000014 /* add addr to pool */
54+#define IP_POOL_DEL_ADDR 0x00000015 /* del addr from pool */
55+#define IP_POOL_HIGH_NR 0x00000016 /* result in req.index */
56+#define IP_POOL_LOOKUP 0x00000017 /* result in addr and addr2 */
57+#define IP_POOL_USAGE 0x00000018 /* result in addr */
58+#define IP_POOL_TEST_ADDR 0x00000019 /* result (0/1) returned */
59+
60+#ifdef __KERNEL__
61+
62+/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
63+extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
64+extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
65+
66+#endif
67+
68+#endif /*_IP_POOL_H*/
69diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set.h
70--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
71+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set.h 2004-02-09 15:02:00.000000000 +0100
72@@ -0,0 +1,440 @@
73+#ifndef _IP_SET_H
74+#define _IP_SET_H
75+
76+/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
77+ * Patrick Schaaf (bof@bof.de)
78+ * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
79+ *
80+ * This program is free software; you can redistribute it and/or modify
81+ * it under the terms of the GNU General Public License as published by
82+ * the Free Software Foundation; either version 2 of the License, or
83+ * (at your option) any later version.
84+ *
85+ * This program is distributed in the hope that it will be useful,
86+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
87+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88+ * GNU General Public License for more details.
89+ *
90+ * You should have received a copy of the GNU General Public License
91+ * along with this program; if not, write to the Free Software
92+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
93+ */
94+
95+/*
96+ * A sockopt of such quality has hardly ever been seen before on the open
97+ * market! This little beauty, hardly ever used: above 64, so it's
98+ * traditionally used for firewalling, not touched (even once!) by the
99+ * 2.0, 2.2 and 2.4 kernels!
100+ *
101+ * Comes with its own certificate of authenticity, valid anywhere in the
102+ * Free world!
103+ *
104+ * Rusty, 19.4.2000
105+ */
106+#define SO_IP_SET 83
107+
108+/* Directions: */
109+#define IPSET_SRC 0x01
110+#define IPSET_DST 0x02
111+/* Inverse flag for matching: */
112+#define IPSET_MATCH_INV 0x04
113+/* Overwrite at adding a new entry: */
114+#define IPSET_ADD_OVERWRITE 0x08
115+/* Set typecodes: */
116+#define IPSET_TYPE_IP 0x10
117+#define IPSET_TYPE_PORT 0x20
118+
119+/*FIXME: remove this */
120+/* #define CONFIG_IP_NF_SET_DEBUG */
121+
122+/*
123+ * Heavily modify by Joakim Axelsson 08.03.2002
124+ * - Made it more modulebased
125+ *
126+ * Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
127+ * - multilevel pools (sets)
128+ * - in order to "deal with" backward compatibility, renamed to ipset
129+ */
130+
131+/* Used so that the kernel module and ipset-binary can match thier versions
132+ */
133+#define IP_SET_PROTOCOL_VERSION 1
134+
135+#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
136+
137+/* The max level of the sets.
138+ * Do not increase lightheartedly before eliminating
139+ * the recursive functions from ip_set.c.
140+ */
141+/* So many IPs can identify a set: */
142+#define IP_SET_SETIP_LEVELS 4
143+/* Max level of a set: */
144+#define IP_SET_LEVELS (IP_SET_SETIP_LEVELS+1)
145+
146+/* Lets work with our own typedef for representing an IP address.
147+ * We hope to make the code more portable, possibly to IPv6...
148+ *
149+ * The representation works in HOST byte order, because most set types
150+ * will perform arithmetic operations and compare operations.
151+ *
152+ * For now the type is an uint32_t.
153+ *
154+ * We do not enforce, but assume that a set may not store more than
155+ * 65536 entries.
156+ *
157+ * Make sure to ONLY use the functions when translating and parsing
158+ * in order to keep the host byte order and make it more portable:
159+ * parse_ip()
160+ * parse_mask()
161+ * parse_ipandmask()
162+ * ip_tostring()
163+ * (Joakim: where are they???)
164+ */
165+
166+typedef uint32_t ip_set_ip_t;
167+
168+/* SO_IP_SET operation constants, and their request struct types.
169+ */
170+
171+/* IP_SET_REQ_BASE defines the first components of ANY request structure.
172+ * It is used for all SO_IP_SET calls, set or get.
173+ */
174+#define IP_SET_REQ_BASE \
175+ unsigned op; \
176+ int id \
177+
178+struct ip_set_req_base {
179+ IP_SET_REQ_BASE;
180+};
181+
182+struct ip_set_req_std {
183+ IP_SET_REQ_BASE;
184+ ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
185+ u_int8_t level;
186+};
187+
188+#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
189+struct ip_set_req_create {
190+ IP_SET_REQ_BASE;
191+ char name[IP_SET_MAXNAMELEN];
192+ char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN];
193+ u_int8_t levels;
194+};
195+
196+#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
197+/* Uses ip_set_req_std */
198+
199+#define IP_SET_OP_CREATE_CHILD 0x00000003 /* Create a new child set */
200+struct ip_set_req_sub {
201+ IP_SET_REQ_BASE;
202+ ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
203+ u_int8_t level;
204+ u_int8_t childsets;
205+};
206+
207+#define IP_SET_OP_FLUSH 0x00000004 /* Remove all IPs in a set */
208+/* Uses ip_set_req_sub */
209+
210+#define IP_SET_OP_RENAME 0x00000005 /* Rename a set */
211+struct ip_set_req_rename {
212+ IP_SET_REQ_BASE;
213+ char newname[IP_SET_MAXNAMELEN];
214+};
215+
216+#define IP_SET_OP_SWAP 0x00000006 /* Swap two sets */
217+struct ip_set_req_swap {
218+ IP_SET_REQ_BASE;
219+ int to;
220+};
221+
222+#define IP_SET_OP_ADD_IP 0x00000007 /* Add an IP to a set */
223+/* Uses ip_set_req_std, with type specific addage */
224+
225+#define IP_SET_OP_DEL_IP 0x00000008 /* Remove an IP from a set */
226+/* Uses ip_set_req_std, with type specific addage */
227+
228+/* Test if an IP is in the set
229+ */
230+#define IP_SET_OP_TEST_IP 0x00000009 /* Test an IP in a set */
231+struct ip_set_req_test {
232+ IP_SET_REQ_BASE;
233+ ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
234+ u_int8_t level;
235+ int reply; /* Test result */
236+};
237+
238+#define IP_SET_OP_VERSION 0x00000010
239+struct ip_set_req_version {
240+ IP_SET_REQ_BASE;
241+ unsigned version;
242+};
243+
244+/* List operations:
245+ * Size requests are sent by ip_set_req_list
246+ * except for LISTING.
247+ */
248+#define IP_SET_OP_LIST_HEADER_SIZE 0x00000101
249+#define IP_SET_OP_LIST_HEADER 0x00000102
250+#define IP_SET_OP_LIST_MEMBERS_SIZE 0x00000103
251+#define IP_SET_OP_LIST_MEMBERS 0x00000104
252+#define IP_SET_OP_LIST_CHILDSETS_SIZE 0x00000105
253+#define IP_SET_OP_LIST_CHILDSETS 0x00000106
254+struct ip_set_req_list {
255+ IP_SET_REQ_BASE;
256+ ip_set_ip_t ip[IP_SET_SETIP_LEVELS];
257+ u_int8_t level;
258+ size_t size;
259+};
260+
261+#define IP_SET_OP_LISTING_SIZE 0x00000107
262+#define IP_SET_OP_LISTING 0x00000108
263+
264+struct ip_set_req_listing_size {
265+ IP_SET_REQ_BASE;
266+ size_t size;
267+};
268+
269+struct ip_set_req_listing {
270+ char name[IP_SET_MAXNAMELEN];
271+ char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN];
272+ u_int8_t levels;
273+ unsigned ref;
274+ int id;
275+};
276+
277+/* Between the iptables(8) set extension modules and the kernel we
278+ * identify a set by its id.
279+ *
280+ * The GETSET_BYNAME call passes the name of a set to the kernel, and
281+ * the a valid set id is returned if the set is still exist.
282+ * The GETSET_BYID call passes the id a set to the kernel, and
283+ * the set name is returned if the set is still exist.
284+ */
285+#define IP_SET_OP_GETSET_BYNAME 0x00000011
286+struct ip_set_req_get {
287+ IP_SET_REQ_BASE;
288+ unsigned ref;
289+ char name[IP_SET_MAXNAMELEN];
290+};
291+
292+#define IP_SET_OP_GETSET_BYID 0x00000012
293+/* Uses ip_set_req_get */
294+
295+static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
296+{
297+ return 4 * ((((b - a + 8) / 8) + 3) / 4);
298+}
299+
300+#ifdef __KERNEL__
301+
302+#define ip_set_printk(format, args...) \
303+ do { \
304+ printk("%s: %s: ", __FILE__, __FUNCTION__); \
305+ printk(format "\n" , ## args); \
306+ } while (0)
307+
308+#if defined(CONFIG_IP_NF_SET_DEBUG) || defined(CONFIG_IP_NF_SET_DEBUG_MODULE)
309+#define CONFIG_IP_NF_SET_DEBUG
310+#define CONFIG_IP_NF_SET_DEBUG_MODULE
311+
312+#define DP(format, args...) \
313+ do { \
314+ printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
315+ printk(format "\n" , ## args); \
316+ } while (0)
317+#else
318+#define DP(format, args...)
319+#endif
320+
321+/* Generic set type: */
322+struct ip_set_private {
323+ struct ip_set_private **childsets; /* child sets */
324+
325+ /* type speficic members */
326+};
327+
328+/*
329+ * The ip_set_type_t definition - one per set type, e.g. "ipmap".
330+ *
331+ * Each individual set has a pointer, set->type, going to one
332+ * of these structures. Function pointers inside the structure implement
333+ * the real behaviour of the sets.
334+ *
335+ * If not mentioned differently, the implementation behind the function
336+ * pointers of a set_type, is expected to return 0 if ok, and a negative
337+ * errno (e.g. -EINVAL) on error.
338+ */
339+struct ip_set_type {
340+ struct list_head list; /* next in list of set types */
341+
342+ /* match IP in set - internally required
343+ * return 0 if not in set, 1 if in set or
344+ * negative errno if input was invalid
345+ */
346+ int (*matchip) (struct ip_set_private *private,
347+ ip_set_ip_t ip,
348+ ip_set_ip_t *id);
349+
350+ /* test for IP in set (kernel: iptables -m set --entry x)
351+ * return 0 if not in set, 1 if in set.
352+ */
353+ int (*testip_kernel) (struct ip_set_private *private,
354+ const struct sk_buff * skb,
355+ u_int32_t flags,
356+ ip_set_ip_t *id);
357+
358+ /* test for IP in set (userspace: ipset -T set --entry x)
359+ * return 0 if not in set, 1 if in set.
360+ */
361+ int (*testip) (struct ip_set_private *private,
362+ const void *data, size_t size,
363+ ip_set_ip_t *id);
364+
365+ /*
366+ * Size of the data structure passed by when
367+ * adding/deletin/testing an entry.
368+ */
369+ size_t reqsize;
370+
371+ /* Add IP into set (userspace: ipset -A set --entry x)
372+ * Return -EEXIST if the address is already in the set,
373+ * and -ERANGE if the address lies outside the set bounds.
374+ * If the address was not already in the set, 0 is returned.
375+ */
376+ int (*addip) (struct ip_set_private *private,
377+ const void *data, size_t size,
378+ ip_set_ip_t *id);
379+
380+ /* Add IP into set (kernel: iptables ... -j SET --entry x)
381+ * Return -EEXIST if the address is already in the set,
382+ * and -ERANGE if the address lies outside the set bounds.
383+ * If the address was not already in the set, 0 is returned.
384+ */
385+ int (*addip_kernel) (struct ip_set_private *private,
386+ const struct sk_buff * skb,
387+ u_int32_t flags,
388+ ip_set_ip_t *id);
389+
390+ /* remove IP from set (userspace: ipset -D set --entry x)
391+ * Return -EEXIST if the address is NOT in the set,
392+ * and -ERANGE if the address lies outside the set bounds.
393+ * If the address really was in the set, 0 is returned.
394+ */
395+ int (*delip) (struct ip_set_private *private,
396+ const void *data, size_t size,
397+ ip_set_ip_t *id);
398+
399+ /* remove IP from set (kernel: iptables ... -j SET --entry x)
400+ * Return -EEXIST if the address is NOT in the set,
401+ * and -ERANGE if the address lies outside the set bounds.
402+ * If the address really was in the set, 0 is returned.
403+ */
404+ int (*delip_kernel) (struct ip_set_private *private,
405+ const struct sk_buff * skb,
406+ u_int32_t flags,
407+ ip_set_ip_t *id);
408+
409+ /* new set creation - allocated type specific items
410+ */
411+ int (*create) (struct ip_set_private **private,
412+ const void *data, size_t size);
413+
414+ /* set destruction - free type specific items
415+ * There is no return value.
416+ * Can be called only when child sets are destroyed.
417+ */
418+ void (*destroy) (struct ip_set_private **private);
419+
420+ /* set flushing - reset all bits in the set, or something similar.
421+ * There is no return value.
422+ */
423+ void (*flush) (struct ip_set_private *private);
424+
425+ /* Listing: Get size needed for header
426+ */
427+ int (*list_header_size) (const struct ip_set_private *private);
428+
429+ /* Listing: Get the header
430+ *
431+ * Fill in the information in "data".
432+ * This function is always run after list_header_size() under a
433+ * writelock on the set. Therefor is the length of "data" always
434+ * correct.
435+ */
436+ void (*list_header) (const struct ip_set_private *private,
437+ void *data);
438+
439+ /* Listing: Get the size for the set members
440+ */
441+ int (*list_members_size) (const struct ip_set_private *private);
442+
443+ /* Listing: Get the set members
444+ *
445+ * Fill in the information in "data".
446+ * This function is always run after list_member_size() under a
447+ * writelock on the set. Therefor is the length of "data" always
448+ * correct.
449+ */
450+ void (*list_members) (const struct ip_set_private *private,
451+ void *data);
452+
453+ /* Listing: set size in ids (first id is 0. Cannot change for a set).
454+ */
455+ ip_set_ip_t (*sizeid) (const struct ip_set_private *private);
456+
457+ /* Listing: Get the bitmap for the valid childsets
458+ */
459+ void (*list_childsets) (const struct ip_set_private *private,
460+ void *data);
461+
462+ char typename[IP_SET_MAXNAMELEN];
463+ char typecode;
464+ int protocol_version;
465+
466+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
467+ struct module *me;
468+};
469+
470+extern int ip_set_register_set_type(struct ip_set_type *set_type);
471+extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
472+
473+/* A generic ipset */
474+struct ip_set {
475+ struct list_head list; /* next in list of all sets */
476+ rwlock_t lock; /* a lock for concurrency control */
477+ unsigned ref; /* reference counter */
478+ unsigned subref; /* reference counter at creating/destroying childsets */
479+ u_int8_t levels; /* max levels of subsets */
480+ struct ip_set_type *type[IP_SET_LEVELS]; /* the set types */
481+ struct ip_set_private *private; /* type specific data */
482+ char name[IP_SET_MAXNAMELEN]; /* the proper name of the set */
483+};
484+
485+extern struct ip_set **ip_set_list;
486+
487+/* register and unregister set pointer references */
488+extern struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
489+ int *id);
490+extern struct ip_set *ip_set_get_byid(int id);
491+extern void ip_set_put(struct ip_set *set);
492+
493+/* API for iptables set match, and SET target */
494+extern void ip_set_addip_kernel(struct ip_set *set,
495+ const struct sk_buff *skb,
496+ const u_int32_t *flags,
497+ u_int8_t set_level,
498+ u_int8_t ip_level);
499+extern void ip_set_delip_kernel(struct ip_set *set,
500+ const struct sk_buff *skb,
501+ const u_int32_t *flags,
502+ u_int8_t set_level,
503+ u_int8_t ip_level);
504+extern int ip_set_testip_kernel(struct ip_set *set,
505+ const struct sk_buff *skb,
506+ const u_int32_t *flags,
507+ u_int8_t set_level,
508+ u_int8_t ip_level);
509+
510+#endif /* __KERNEL__ */
511+
512+#endif /*_IP_SET_H*/
513diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_iphash.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_iphash.h
514--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
515+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_iphash.h 2004-02-09 15:02:00.000000000 +0100
516@@ -0,0 +1,30 @@
517+#ifndef __IP_SET_IPHASH_H
518+#define __IP_SET_IPHASH_H
519+
520+#include <linux/netfilter_ipv4/ip_set.h>
521+
522+#define SETTYPE_NAME "iphash"
523+#define MAX_RANGE 0x0000FFFF
524+
525+struct ip_set_iphash {
526+ struct ip_set_private **childsets; /* child sets */
527+
528+ /* Type speficic members: */
529+ uint32_t initval; /* initval for jhash_1word */
530+ ip_set_ip_t hashsize; /* hash size */
531+ ip_set_ip_t netmask; /* netmask */
532+ ip_set_ip_t *members; /* the iphash proper */
533+};
534+
535+struct ip_set_req_iphash_create {
536+ uint32_t initval;
537+ ip_set_ip_t hashsize;
538+ ip_set_ip_t netmask;
539+};
540+
541+struct ip_set_req_iphash {
542+ ip_set_ip_t ip;
543+ u_int32_t flags;
544+};
545+
546+#endif /* __IP_SET_IPHASH_H */
547diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_ipmap.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_ipmap.h
548--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
549+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_ipmap.h 2004-02-09 15:02:00.000000000 +0100
550@@ -0,0 +1,59 @@
551+#ifndef __IP_SET_IPMAP_H
552+#define __IP_SET_IPMAP_H
553+
554+#include <linux/netfilter_ipv4/ip_set.h>
555+
556+#define SETTYPE_NAME "ipmap"
557+#define MAX_RANGE 0x0000FFFF
558+
559+struct ip_set_ipmap {
560+ struct ip_set_private **childsets; /* child sets */
561+
562+ /* Type speficic members: */
563+ ip_set_ip_t first_ip; /* host byte order, included in range */
564+ ip_set_ip_t last_ip; /* host byte order, included in range */
565+ ip_set_ip_t netmask; /* subnet netmask */
566+ ip_set_ip_t sizeid; /* size of set in ids */
567+ u_int16_t hosts; /* hosts per subnet */
568+ void *members; /* the ipmap proper */
569+};
570+
571+struct ip_set_req_ipmap_create {
572+ ip_set_ip_t from;
573+ ip_set_ip_t to;
574+ ip_set_ip_t netmask;
575+};
576+
577+struct ip_set_req_ipmap {
578+ ip_set_ip_t ip;
579+};
580+
581+unsigned int
582+mask_to_bits(ip_set_ip_t mask)
583+{
584+ unsigned int bits = 32;
585+ ip_set_ip_t maskaddr;
586+
587+ if (mask == 0xFFFFFFFF)
588+ return bits;
589+
590+ maskaddr = 0xFFFFFFFE;
591+ while (--bits >= 0 && maskaddr != mask)
592+ maskaddr <<= 1;
593+
594+ return bits;
595+}
596+
597+ip_set_ip_t
598+range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
599+{
600+ ip_set_ip_t mask = 0xFFFFFFFE;
601+
602+ *bits = 32;
603+ while (--(*bits) >= 0 && mask && (to & mask) != from)
604+ mask <<= 1;
605+
606+ return mask;
607+}
608+
609+#endif /* __IP_SET_IPMAP_H */
610diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_jhash.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_jhash.h
611--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
612+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_jhash.h 2004-02-09 15:02:00.000000000 +0100
613@@ -0,0 +1,148 @@
614+#ifndef _LINUX_IPSET_JHASH_H
615+#define _LINUX_IPSET_JHASH_H
616+
617+/* This is a copy of linux/jhash.h but the types u32/u8 are changed
618+ * to __u32/__u8 so that the header file can be included into
619+ * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
620+ */
621+
622+/* jhash.h: Jenkins hash support.
623+ *
624+ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
625+ *
626+ * http://burtleburtle.net/bob/hash/
627+ *
628+ * These are the credits from Bob's sources:
629+ *
630+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
631+ * hash(), hash2(), hash3, and mix() are externally useful functions.
632+ * Routines to test the hash are included if SELF_TEST is defined.
633+ * You can use this free for any purpose. It has no warranty.
634+ *
635+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
636+ *
637+ * I've modified Bob's hash to be useful in the Linux kernel, and
638+ * any bugs present are surely my fault. -DaveM
639+ */
640+
641+/* NOTE: Arguments are modified. */
642+#define __jhash_mix(a, b, c) \
643+{ \
644+ a -= b; a -= c; a ^= (c>>13); \
645+ b -= c; b -= a; b ^= (a<<8); \
646+ c -= a; c -= b; c ^= (b>>13); \
647+ a -= b; a -= c; a ^= (c>>12); \
648+ b -= c; b -= a; b ^= (a<<16); \
649+ c -= a; c -= b; c ^= (b>>5); \
650+ a -= b; a -= c; a ^= (c>>3); \
651+ b -= c; b -= a; b ^= (a<<10); \
652+ c -= a; c -= b; c ^= (b>>15); \
653+}
654+
655+/* The golden ration: an arbitrary value */
656+#define JHASH_GOLDEN_RATIO 0x9e3779b9
657+
658+/* The most generic version, hashes an arbitrary sequence
659+ * of bytes. No alignment or length assumptions are made about
660+ * the input key.
661+ */
662+static inline __u32 jhash(void *key, __u32 length, __u32 initval)
663+{
664+ __u32 a, b, c, len;
665+ __u8 *k = key;
666+
667+ len = length;
668+ a = b = JHASH_GOLDEN_RATIO;
669+ c = initval;
670+
671+ while (len >= 12) {
672+ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
673+ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
674+ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
675+
676+ __jhash_mix(a,b,c);
677+
678+ k += 12;
679+ len -= 12;
680+ }
681+
682+ c += length;
683+ switch (len) {
684+ case 11: c += ((__u32)k[10]<<24);
685+ case 10: c += ((__u32)k[9]<<16);
686+ case 9 : c += ((__u32)k[8]<<8);
687+ case 8 : b += ((__u32)k[7]<<24);
688+ case 7 : b += ((__u32)k[6]<<16);
689+ case 6 : b += ((__u32)k[5]<<8);
690+ case 5 : b += k[4];
691+ case 4 : a += ((__u32)k[3]<<24);
692+ case 3 : a += ((__u32)k[2]<<16);
693+ case 2 : a += ((__u32)k[1]<<8);
694+ case 1 : a += k[0];
695+ };
696+
697+ __jhash_mix(a,b,c);
698+
699+ return c;
700+}
701+
702+/* A special optimized version that handles 1 or more of __u32s.
703+ * The length parameter here is the number of __u32s in the key.
704+ */
705+static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
706+{
707+ __u32 a, b, c, len;
708+
709+ a = b = JHASH_GOLDEN_RATIO;
710+ c = initval;
711+ len = length;
712+
713+ while (len >= 3) {
714+ a += k[0];
715+ b += k[1];
716+ c += k[2];
717+ __jhash_mix(a, b, c);
718+ k += 3; len -= 3;
719+ }
720+
721+ c += length * 4;
722+
723+ switch (len) {
724+ case 2 : b += k[1];
725+ case 1 : a += k[0];
726+ };
727+
728+ __jhash_mix(a,b,c);
729+
730+ return c;
731+}
732+
733+
734+/* A special ultra-optimized versions that knows they are hashing exactly
735+ * 3, 2 or 1 word(s).
736+ *
737+ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
738+ * done at the end is not done here.
739+ */
740+static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
741+{
742+ a += JHASH_GOLDEN_RATIO;
743+ b += JHASH_GOLDEN_RATIO;
744+ c += initval;
745+
746+ __jhash_mix(a, b, c);
747+
748+ return c;
749+}
750+
751+static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
752+{
753+ return jhash_3words(a, b, 0, initval);
754+}
755+
756+static inline __u32 jhash_1word(__u32 a, __u32 initval)
757+{
758+ return jhash_3words(a, 0, 0, initval);
759+}
760+
761+#endif /* _LINUX_IPSET_JHASH_H */
762diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_macipmap.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_macipmap.h
763--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
764+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_macipmap.h 2004-02-09 15:02:00.000000000 +0100
765@@ -0,0 +1,41 @@
766+#ifndef __IP_SET_MACIPMAP_H
767+#define __IP_SET_MACIPMAP_H
768+
769+#include <linux/netfilter_ipv4/ip_set.h>
770+
771+#define SETTYPE_NAME "macipmap"
772+#define MAX_RANGE 0x0000FFFF
773+
774+/* general flags */
775+#define IPSET_MACIP_MATCHUNSET 1
776+
777+/* per ip flags */
778+#define IPSET_MACIP_ISSET 1
779+
780+struct ip_set_macipmap {
781+ struct ip_set_private **childsets; /* child sets */
782+
783+ /* Type speficic members: */
784+ ip_set_ip_t first_ip; /* host byte order, included in range */
785+ ip_set_ip_t last_ip; /* host byte order, included in range */
786+ void *members; /* the macipmap proper */
787+ u_int32_t flags;
788+};
789+
790+struct ip_set_req_macipmap_create {
791+ ip_set_ip_t from;
792+ ip_set_ip_t to;
793+ u_int32_t flags;
794+};
795+
796+struct ip_set_req_macipmap {
797+ ip_set_ip_t ip;
798+ unsigned char ethernet[ETH_ALEN];
799+};
800+
801+struct ip_set_macip {
802+ unsigned short flags;
803+ unsigned char ethernet[ETH_ALEN];
804+};
805+
806+#endif /* __IP_SET_MACIPMAP_H */
807diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_portmap.h linux-2.6.3/include/linux/netfilter_ipv4/ip_set_portmap.h
808--- linux-2.6.3.org/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
809+++ linux-2.6.3/include/linux/netfilter_ipv4/ip_set_portmap.h 2004-02-09 15:02:00.000000000 +0100
810@@ -0,0 +1,28 @@
811+#ifndef __IP_SET_PORTMAP_H
812+#define __IP_SET_PORTMAP_H
813+
814+#include <linux/netfilter_ipv4/ip_set.h>
815+
816+#define SETTYPE_NAME "portmap"
817+#define MAX_RANGE 0x0000FFFF
818+#define INVALID_PORT (MAX_RANGE + 1)
819+
820+struct ip_set_portmap {
821+ struct ip_set_private **childsets; /* child sets */
822+
823+ /* Type speficic members: */
824+ ip_set_ip_t first_port; /* host byte order, included in range */
825+ ip_set_ip_t last_port; /* host byte order, included in range */
826+ void *members; /* the portmap proper */
827+};
828+
829+struct ip_set_req_portmap_create {
830+ ip_set_ip_t from;
831+ ip_set_ip_t to;
832+};
833+
834+struct ip_set_req_portmap {
835+ ip_set_ip_t port;
836+};
837+
838+#endif /* __IP_SET_PORTMAP_H */
839diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_NETLINK.h
840--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_NETLINK.h 1970-01-01 01:00:00.000000000 +0100
841+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_NETLINK.h 2004-02-19 08:47:24.269530314 +0100
842@@ -0,0 +1,27 @@
843+#ifndef _IPT_FWMON_H
844+#define _IPT_FWMON_H
845+
846+/* Bitmask macros */
847+#define MASK(x,y) (x & y)
848+#define MASK_SET(x,y) x |= y
849+#define MASK_UNSET(x,y) x &= ~y
850+
851+#define USE_MARK 0x00000001
852+#define USE_DROP 0x00000002
853+#define USE_SIZE 0x00000004
854+
855+struct ipt_nldata
856+{
857+ unsigned int flags;
858+ unsigned int mark;
859+ unsigned int size;
860+};
861+
862+/* Old header */
863+struct netlink_t {
864+ unsigned int len;
865+ unsigned int mark;
866+ char iface[IFNAMSIZ];
867+};
868+
869+#endif /*_IPT_FWMON_H*/
870diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_TTL.h
871--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_TTL.h 1970-01-01 01:00:00.000000000 +0100
872+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_TTL.h 2004-02-19 08:47:25.605208582 +0100
873@@ -0,0 +1,21 @@
874+/* TTL modification module for IP tables
875+ * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
876+
877+#ifndef _IPT_TTL_H
878+#define _IPT_TTL_H
879+
880+enum {
881+ IPT_TTL_SET = 0,
882+ IPT_TTL_INC,
883+ IPT_TTL_DEC
884+};
885+
886+#define IPT_TTL_MAXMODE IPT_TTL_DEC
887+
888+struct ipt_TTL_info {
889+ u_int8_t mode;
890+ u_int8_t ttl;
891+};
892+
893+
894+#endif
895diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_connlimit.h
896--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_connlimit.h 1970-01-01 01:00:00.000000000 +0100
897+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_connlimit.h 2004-02-19 08:47:26.593970414 +0100
898@@ -0,0 +1,12 @@
899+#ifndef _IPT_CONNLIMIT_H
900+#define _IPT_CONNLIMIT_H
901+
902+struct ipt_connlimit_data;
903+
904+struct ipt_connlimit_info {
905+ int limit;
906+ int inverse;
907+ u_int32_t mask;
908+ struct ipt_connlimit_data *data;
909+};
910+#endif /* _IPT_CONNLIMIT_H */
911diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_dstlimit.h
912--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_dstlimit.h 1970-01-01 01:00:00.000000000 +0100
913+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_dstlimit.h 2004-02-19 08:47:27.235815809 +0100
914@@ -0,0 +1,39 @@
915+#ifndef _IPT_DSTLIMIT_H
916+#define _IPT_DSTLIMIT_H
917+
918+/* timings are in milliseconds. */
919+#define IPT_DSTLIMIT_SCALE 10000
920+/* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490
921+ seconds, or one every 59 hours. */
922+
923+/* details of this structure hidden by the implementation */
924+struct ipt_dstlimit_htable;
925+
926+#define IPT_DSTLIMIT_HASH_DIP 0x0001
927+#define IPT_DSTLIMIT_HASH_DPT 0x0002
928+#define IPT_DSTLIMIT_HASH_SIP 0x0004
929+
930+struct dstlimit_cfg {
931+ u_int32_t mode; /* bitmask of IPT_DSTLIMIT_HASH_* */
932+ u_int32_t avg; /* Average secs between packets * scale */
933+ u_int32_t burst; /* Period multiplier for upper limit. */
934+
935+ /* user specified */
936+ u_int32_t size; /* how many buckets */
937+ u_int32_t max; /* max number of entries */
938+ u_int32_t gc_interval; /* gc interval */
939+ u_int32_t expire; /* when do entries expire? */
940+};
941+
942+struct ipt_dstlimit_info {
943+ char name [IFNAMSIZ]; /* name */
944+ struct dstlimit_cfg cfg;
945+ struct ipt_dstlimit_htable *hinfo;
946+
947+ /* Used internally by the kernel */
948+ union {
949+ void *ptr;
950+ struct ipt_dstlimit_info *master;
951+ } u;
952+};
953+#endif /*_IPT_DSTLIMIT_H*/
954diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_fuzzy.h
955--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
956+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_fuzzy.h 2004-02-19 08:47:27.855666503 +0100
957@@ -0,0 +1,21 @@
958+#ifndef _IPT_FUZZY_H
959+#define _IPT_FUZZY_H
960+
961+#include <linux/param.h>
962+#include <linux/types.h>
963+
964+#define MAXFUZZYRATE 10000000
965+#define MINFUZZYRATE 3
966+
967+struct ipt_fuzzy_info {
968+ u_int32_t minimum_rate;
969+ u_int32_t maximum_rate;
970+ u_int32_t packets_total;
971+ u_int32_t bytes_total;
972+ u_int32_t previous_time;
973+ u_int32_t present_time;
974+ u_int32_t mean_rate;
975+ u_int8_t acceptance_rate;
976+};
977+
978+#endif /*_IPT_FUZZY_H*/
979diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_ipv4options.h
980--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_ipv4options.h 1970-01-01 01:00:00.000000000 +0100
981+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_ipv4options.h 2004-02-19 08:47:28.441525384 +0100
982@@ -0,0 +1,21 @@
983+#ifndef __ipt_ipv4options_h_included__
984+#define __ipt_ipv4options_h_included__
985+
986+#define IPT_IPV4OPTION_MATCH_SSRR 0x01 /* For strict source routing */
987+#define IPT_IPV4OPTION_MATCH_LSRR 0x02 /* For loose source routing */
988+#define IPT_IPV4OPTION_DONT_MATCH_SRR 0x04 /* any source routing */
989+#define IPT_IPV4OPTION_MATCH_RR 0x08 /* For Record route */
990+#define IPT_IPV4OPTION_DONT_MATCH_RR 0x10
991+#define IPT_IPV4OPTION_MATCH_TIMESTAMP 0x20 /* For timestamp request */
992+#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP 0x40
993+#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT 0x80 /* For router-alert */
994+#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
995+#define IPT_IPV4OPTION_MATCH_ANY_OPT 0x200 /* match packet with any option */
996+#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT 0x400 /* match packet with no option */
997+
998+struct ipt_ipv4options_info {
999+ u_int16_t options;
1000+};
1001+
1002+
1003+#endif /* __ipt_ipv4options_h_included__ */
1004diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_mport.h
1005--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_mport.h 1970-01-01 01:00:00.000000000 +0100
1006+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_mport.h 2004-02-19 08:47:29.017386674 +0100
1007@@ -0,0 +1,24 @@
1008+#ifndef _IPT_MPORT_H
1009+#define _IPT_MPORT_H
1010+#include <linux/netfilter_ipv4/ip_tables.h>
1011+
1012+#define IPT_MPORT_SOURCE (1<<0)
1013+#define IPT_MPORT_DESTINATION (1<<1)
1014+#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
1015+
1016+#define IPT_MULTI_PORTS 15
1017+
1018+/* Must fit inside union ipt_matchinfo: 32 bytes */
1019+/* every entry in ports[] except for the last one has one bit in pflags
1020+ * associated with it. If this bit is set, the port is the first port of
1021+ * a portrange, with the next entry being the last.
1022+ * End of list is marked with pflags bit set and port=65535.
1023+ * If 14 ports are used (last one does not have a pflag), the last port
1024+ * is repeated to fill the last entry in ports[] */
1025+struct ipt_mport
1026+{
1027+ u_int8_t flags:2; /* Type of comparison */
1028+ u_int16_t pflags:14; /* Port flags */
1029+ u_int16_t ports[IPT_MULTI_PORTS]; /* Ports */
1030+};
1031+#endif /*_IPT_MPORT_H*/
1032diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_nth.h
1033--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_nth.h 1970-01-01 01:00:00.000000000 +0100
1034+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_nth.h 2004-02-19 08:47:29.579251335 +0100
1035@@ -0,0 +1,19 @@
1036+#ifndef _IPT_NTH_H
1037+#define _IPT_NTH_H
1038+
1039+#include <linux/param.h>
1040+#include <linux/types.h>
1041+
1042+#ifndef IPT_NTH_NUM_COUNTERS
1043+#define IPT_NTH_NUM_COUNTERS 16
1044+#endif
1045+
1046+struct ipt_nth_info {
1047+ u_int8_t every;
1048+ u_int8_t not;
1049+ u_int8_t startat;
1050+ u_int8_t counter;
1051+ u_int8_t packet;
1052+};
1053+
1054+#endif /*_IPT_NTH_H*/
1055diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_osf.h
1056--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_osf.h 1970-01-01 01:00:00.000000000 +0100
1057+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_osf.h 2004-02-19 08:47:30.115122257 +0100
1058@@ -0,0 +1,130 @@
1059+/*
1060+ * ipt_osf.h
1061+ *
1062+ * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
1063+ *
1064+ *
1065+ * This program is free software; you can redistribute it and/or modify
1066+ * it under the terms of the GNU General Public License as published by
1067+ * the Free Software Foundation; either version 2 of the License, or
1068+ * (at your option) any later version.
1069+ *
1070+ * This program is distributed in the hope that it will be useful,
1071+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1072+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1073+ * GNU General Public License for more details.
1074+ *
1075+ * You should have received a copy of the GNU General Public License
1076+ * along with this program; if not, write to the Free Software
1077+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1078+ */
1079+
1080+#ifndef _IPT_OSF_H
1081+#define _IPT_OSF_H
1082+
1083+#define MAXGENRELEN 32
1084+#define MAXDETLEN 64
1085+
1086+#define IPT_OSF_GENRE 1
1087+#define IPT_OSF_SMART 2
1088+#define IPT_OSF_LOG 4
1089+
1090+#define IPT_OSF_LOGLEVEL_ALL 0
1091+#define IPT_OSF_LOGLEVEL_FIRST 1
1092+
1093+#include <linux/list.h>
1094+
1095+struct ipt_osf_info
1096+{
1097+ char genre[MAXGENRELEN];
1098+ int len;
1099+ unsigned long flags;
1100+ int loglevel;
1101+ int invert; /* UNSUPPORTED */
1102+};
1103+
1104+struct osf_wc
1105+{
1106+ char wc;
1107+ unsigned long val;
1108+};
1109+
1110+/* This struct represents IANA options
1111+ * http://www.iana.org/assignments/tcp-parameters
1112+ */
1113+struct osf_opt
1114+{
1115+ unsigned char kind;
1116+ unsigned char length;
1117+ struct osf_wc wc;
1118+};
1119+
1120+#ifdef __KERNEL__
1121+
1122+struct osf_finger
1123+{
1124+ struct list_head flist;
1125+ struct osf_wc wss;
1126+ unsigned char ttl;
1127+ unsigned char df;
1128+ unsigned long ss;
1129+ char genre[MAXGENRELEN];
1130+ char version[MAXGENRELEN], subtype[MAXGENRELEN];
1131+
1132+ /* Not needed, but for consistency with original table from Michal Zalewski */
1133+ char details[MAXDETLEN];
1134+
1135+ int opt_num;
1136+ struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
1137+
1138+};
1139+
1140+/* Defines for IANA option kinds */
1141+
1142+#define OSFOPT_EOL 0 /* End of options */
1143+#define OSFOPT_NOP 1 /* NOP */
1144+#define OSFOPT_MSS 2 /* Maximum segment size */
1145+#define OSFOPT_WSO 3 /* Window scale option */
1146+#define OSFOPT_SACKP 4 /* SACK permitted */
1147+#define OSFOPT_SACK 5 /* SACK */
1148+#define OSFOPT_ECHO 6
1149+#define OSFOPT_ECHOREPLY 7
1150+#define OSFOPT_TS 8 /* Timestamp option */
1151+#define OSFOPT_POCP 9 /* Partial Order Connection Permitted */
1152+#define OSFOPT_POSP 10 /* Partial Order Service Profile */
1153+/* Others are not used in current OSF */
1154+
1155+static struct osf_opt IANA_opts[] =
1156+{
1157+ {0, 1,},
1158+ {1, 1,},
1159+ {2, 4,},
1160+ {3, 3,},
1161+ {4, 2,},
1162+ {5, 1 ,}, /* SACK length is not defined */
1163+ {6, 6,},
1164+ {7, 6,},
1165+ {8, 10,},
1166+ {9, 2,},
1167+ {10, 3,},
1168+ {11, 1,}, /* CC: Suppose 1 */
1169+ {12, 1,}, /* the same */
1170+ {13, 1,}, /* and here too */
1171+ {14, 3,},
1172+ {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
1173+ {16, 1,},
1174+ {17, 1,},
1175+ {18, 3,},
1176+ {19, 18,},
1177+ {20, 1,},
1178+ {21, 1,},
1179+ {22, 1,},
1180+ {23, 1,},
1181+ {24, 1,},
1182+ {25, 1,},
1183+ {26, 1,},
1184+};
1185+
1186+#endif /* __KERNEL__ */
1187+
1188+#endif /* _IPT_OSF_H */
1189diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_pool.h
1190--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_pool.h 1970-01-01 01:00:00.000000000 +0100
1191+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_pool.h 2004-02-19 08:47:30.712978249 +0100
1192@@ -0,0 +1,25 @@
1193+#ifndef _IPT_POOL_H
1194+#define _IPT_POOL_H
1195+
1196+#include <linux/netfilter_ipv4/ip_pool.h>
1197+
1198+#define IPT_POOL_INV_SRC 0x00000001
1199+#define IPT_POOL_INV_DST 0x00000002
1200+#define IPT_POOL_DEL_SRC 0x00000004
1201+#define IPT_POOL_DEL_DST 0x00000008
1202+#define IPT_POOL_INV_MOD_SRC 0x00000010
1203+#define IPT_POOL_INV_MOD_DST 0x00000020
1204+#define IPT_POOL_MOD_SRC_ACCEPT 0x00000040
1205+#define IPT_POOL_MOD_DST_ACCEPT 0x00000080
1206+#define IPT_POOL_MOD_SRC_DROP 0x00000100
1207+#define IPT_POOL_MOD_DST_DROP 0x00000200
1208+
1209+/* match info */
1210+struct ipt_pool_info
1211+{
1212+ ip_pool_t src;
1213+ ip_pool_t dst;
1214+ unsigned flags;
1215+};
1216+
1217+#endif /*_IPT_POOL_H*/
1218diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_psd.h
1219--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_psd.h 1970-01-01 01:00:00.000000000 +0100
1220+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_psd.h 2004-02-19 08:47:31.249848931 +0100
1221@@ -0,0 +1,40 @@
1222+#ifndef _IPT_PSD_H
1223+#define _IPT_PSD_H
1224+
1225+#include <linux/param.h>
1226+#include <linux/types.h>
1227+
1228+/*
1229+ * High port numbers have a lower weight to reduce the frequency of false
1230+ * positives, such as from passive mode FTP transfers.
1231+ */
1232+#define PORT_WEIGHT_PRIV 3
1233+#define PORT_WEIGHT_HIGH 1
1234+
1235+/*
1236+ * Port scan detection thresholds: at least COUNT ports need to be scanned
1237+ * from the same source, with no longer than DELAY ticks between ports.
1238+ */
1239+#define SCAN_MIN_COUNT 7
1240+#define SCAN_MAX_COUNT (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
1241+#define SCAN_WEIGHT_THRESHOLD SCAN_MAX_COUNT
1242+#define SCAN_DELAY_THRESHOLD (HZ * 3)
1243+
1244+/*
1245+ * Keep track of up to LIST_SIZE source addresses, using a hash table of
1246+ * HASH_SIZE entries for faster lookups, but limiting hash collisions to
1247+ * HASH_MAX source addresses per the same hash value.
1248+ */
1249+#define LIST_SIZE 0x100
1250+#define HASH_LOG 9
1251+#define HASH_SIZE (1 << HASH_LOG)
1252+#define HASH_MAX 0x10
1253+
1254+struct ipt_psd_info {
1255+ unsigned int weight_threshold;
1256+ unsigned int delay_threshold;
1257+ unsigned short lo_ports_weight;
1258+ unsigned short hi_ports_weight;
1259+};
1260+
1261+#endif /*_IPT_PSD_H*/
1262diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_quota.h
1263--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_quota.h 1970-01-01 01:00:00.000000000 +0100
1264+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_quota.h 2004-02-19 08:47:31.780721057 +0100
1265@@ -0,0 +1,11 @@
1266+#ifndef _IPT_QUOTA_H
1267+#define _IPT_QUOTA_H
1268+
1269+/* print debug info in both kernel/netfilter module & iptable library */
1270+//#define DEBUG_IPT_QUOTA
1271+
1272+struct ipt_quota_info {
1273+ u_int64_t quota;
1274+};
1275+
1276+#endif /*_IPT_QUOTA_H*/
1277diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_random.h
1278--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_random.h 1970-01-01 01:00:00.000000000 +0100
1279+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_random.h 2004-02-19 08:47:32.335587404 +0100
1280@@ -0,0 +1,11 @@
1281+#ifndef _IPT_RAND_H
1282+#define _IPT_RAND_H
1283+
1284+#include <linux/param.h>
1285+#include <linux/types.h>
1286+
1287+struct ipt_rand_info {
1288+ u_int8_t average;
1289+};
1290+
1291+#endif /*_IPT_RAND_H*/
1292diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_realm.h
1293--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_realm.h 1970-01-01 01:00:00.000000000 +0100
1294+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_realm.h 2004-02-19 08:47:33.450318894 +0100
1295@@ -0,0 +1,9 @@
1296+#ifndef _IPT_REALM_H
1297+#define _IPT_REALM_H
1298+
1299+struct ipt_realm_info {
1300+ u_int32_t id;
1301+ u_int32_t mask;
1302+ u_int8_t invert;
1303+};
1304+#endif /*_IPT_REALM_H*/
1305diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_set.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_set.h
1306--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
1307+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_set.h 2004-02-09 15:02:00.000000000 +0100
1308@@ -0,0 +1,22 @@
1309+#ifndef _IPT_SET_H
1310+#define _IPT_SET_H
1311+
1312+#include <linux/netfilter_ipv4/ip_set.h>
1313+
1314+struct ipt_set_info {
1315+ int16_t id;
1316+ u_int8_t set_level, ip_level;
1317+ u_int32_t flags[IP_SET_LEVELS];
1318+};
1319+
1320+/* match info */
1321+struct ipt_set_info_match {
1322+ struct ipt_set_info match;
1323+};
1324+
1325+struct ipt_set_info_target {
1326+ struct ipt_set_info add_set;
1327+ struct ipt_set_info del_set;
1328+};
1329+
1330+#endif /*_IPT_SET_H*/
1331diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_time.h
1332--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_time.h 1970-01-01 01:00:00.000000000 +0100
1333+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_time.h 2004-02-19 08:47:33.998186927 +0100
1334@@ -0,0 +1,13 @@
1335+#ifndef __ipt_time_h_included__
1336+#define __ipt_time_h_included__
1337+
1338+
1339+struct ipt_time_info {
1340+ u_int8_t days_match; /* 1 bit per day. -SMTWTFS */
1341+ u_int16_t time_start; /* 0 < time_start < 23*60+59 = 1439 */
1342+ u_int16_t time_stop; /* 0:0 < time_stat < 23:59 */
1343+ u_int8_t kerneltime; /* ignore skb time (and use kerneltime) or not. */
1344+};
1345+
1346+
1347+#endif /* __ipt_time_h_included__ */
1348diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.6.3/include/linux/netfilter_ipv4/ipt_u32.h
1349--- linux-2.6.3.org/include/linux/netfilter_ipv4/ipt_u32.h 1970-01-01 01:00:00.000000000 +0100
1350+++ linux-2.6.3/include/linux/netfilter_ipv4/ipt_u32.h 2004-02-19 08:47:34.549054238 +0100
1351@@ -0,0 +1,40 @@
1352+#ifndef _IPT_U32_H
1353+#define _IPT_U32_H
1354+#include <linux/netfilter_ipv4/ip_tables.h>
1355+
1356+enum ipt_u32_ops
1357+{
1358+ IPT_U32_AND,
1359+ IPT_U32_LEFTSH,
1360+ IPT_U32_RIGHTSH,
1361+ IPT_U32_AT
1362+};
1363+
1364+struct ipt_u32_location_element
1365+{
1366+ u_int32_t number;
1367+ u_int8_t nextop;
1368+};
1369+struct ipt_u32_value_element
1370+{
1371+ u_int32_t min;
1372+ u_int32_t max;
1373+};
1374+/* *** any way to allow for an arbitrary number of elements?
1375+ for now I settle for a limit of 10 of each */
1376+#define U32MAXSIZE 10
1377+struct ipt_u32_test
1378+{
1379+ u_int8_t nnums;
1380+ struct ipt_u32_location_element location[U32MAXSIZE+1];
1381+ u_int8_t nvalues;
1382+ struct ipt_u32_value_element value[U32MAXSIZE+1];
1383+};
1384+
1385+struct ipt_u32
1386+{
1387+ u_int8_t ntests;
1388+ struct ipt_u32_test tests[U32MAXSIZE+1];
1389+};
1390+
1391+#endif /*_IPT_U32_H*/
1392diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_HL.h
1393--- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_HL.h 1970-01-01 01:00:00.000000000 +0100
1394+++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_HL.h 2004-02-19 09:09:04.595401585 +0100
1395@@ -0,0 +1,22 @@
1396+/* Hop Limit modification module for ip6tables
1397+ * Maciej Soltysiak <solt@dns.toxicfilms.tv>
1398+ * Based on HW's TTL module */
1399+
1400+#ifndef _IP6T_HL_H
1401+#define _IP6T_HL_H
1402+
1403+enum {
1404+ IP6T_HL_SET = 0,
1405+ IP6T_HL_INC,
1406+ IP6T_HL_DEC
1407+};
1408+
1409+#define IP6T_HL_MAXMODE IP6T_HL_DEC
1410+
1411+struct ip6t_HL_info {
1412+ u_int8_t mode;
1413+ u_int8_t hop_limit;
1414+};
1415+
1416+
1417+#endif
1418diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_REJECT.h
1419--- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-02-18 04:57:12.000000000 +0100
1420+++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_REJECT.h 2004-02-19 08:47:25.031346811 +0100
1421@@ -2,15 +2,17 @@
1422 #define _IP6T_REJECT_H
1423
1424 enum ip6t_reject_with {
1425- IP6T_ICMP_NET_UNREACHABLE,
1426- IP6T_ICMP_HOST_UNREACHABLE,
1427- IP6T_ICMP_PROT_UNREACHABLE,
1428- IP6T_ICMP_PORT_UNREACHABLE,
1429- IP6T_ICMP_ECHOREPLY
1430+ IP6T_ICMP6_NO_ROUTE,
1431+ IP6T_ICMP6_ADM_PROHIBITED,
1432+ IP6T_ICMP6_NOT_NEIGHBOUR,
1433+ IP6T_ICMP6_ADDR_UNREACH,
1434+ IP6T_ICMP6_PORT_UNREACH,
1435+ IP6T_ICMP6_ECHOREPLY,
1436+ IP6T_TCP_RESET
1437 };
1438
1439 struct ip6t_reject_info {
1440 enum ip6t_reject_with with; /* reject type */
1441 };
1442
1443-#endif /*_IPT_REJECT_H*/
1444+#endif /*_IP6T_REJECT_H*/
1445diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_fuzzy.h
1446--- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h 1970-01-01 01:00:00.000000000 +0100
1447+++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_fuzzy.h 2004-02-19 08:47:27.855666503 +0100
1448@@ -0,0 +1,21 @@
1449+#ifndef _IP6T_FUZZY_H
1450+#define _IP6T_FUZZY_H
1451+
1452+#include <linux/param.h>
1453+#include <linux/types.h>
1454+
1455+#define MAXFUZZYRATE 10000000
1456+#define MINFUZZYRATE 3
1457+
1458+struct ip6t_fuzzy_info {
1459+ u_int32_t minimum_rate;
1460+ u_int32_t maximum_rate;
1461+ u_int32_t packets_total;
1462+ u_int32_t bytes_total;
1463+ u_int32_t previous_time;
1464+ u_int32_t present_time;
1465+ u_int32_t mean_rate;
1466+ u_int8_t acceptance_rate;
1467+};
1468+
1469+#endif /*_IP6T_FUZZY_H*/
1470diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_nth.h
1471--- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_nth.h 1970-01-01 01:00:00.000000000 +0100
1472+++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_nth.h 2004-02-19 08:47:29.579251335 +0100
1473@@ -0,0 +1,19 @@
1474+#ifndef _IP6T_NTH_H
1475+#define _IP6T_NTH_H
1476+
1477+#include <linux/param.h>
1478+#include <linux/types.h>
1479+
1480+#ifndef IP6T_NTH_NUM_COUNTERS
1481+#define IP6T_NTH_NUM_COUNTERS 16
1482+#endif
1483+
1484+struct ip6t_nth_info {
1485+ u_int8_t every;
1486+ u_int8_t not;
1487+ u_int8_t startat;
1488+ u_int8_t counter;
1489+ u_int8_t packet;
1490+};
1491+
1492+#endif /*_IP6T_NTH_H*/
1493diff -Nur linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.6.3/include/linux/netfilter_ipv6/ip6t_random.h
1494--- linux-2.6.3.org/include/linux/netfilter_ipv6/ip6t_random.h 1970-01-01 01:00:00.000000000 +0100
1495+++ linux-2.6.3/include/linux/netfilter_ipv6/ip6t_random.h 2004-02-19 08:47:32.336587163 +0100
1496@@ -0,0 +1,11 @@
1497+#ifndef _IP6T_RAND_H
1498+#define _IP6T_RAND_H
1499+
1500+#include <linux/param.h>
1501+#include <linux/types.h>
1502+
1503+struct ip6t_rand_info {
1504+ u_int8_t average;
1505+};
1506+
1507+#endif /*_IP6T_RAND_H*/
1508diff -Nur linux-2.6.3.org/net/ipv4/netfilter/Kconfig linux-2.6.3/net/ipv4/netfilter/Kconfig
1509--- linux-2.6.3.org/net/ipv4/netfilter/Kconfig 2004-02-18 04:59:13.000000000 +0100
1510+++ linux-2.6.3/net/ipv4/netfilter/Kconfig 2004-02-19 09:06:18.111476624 +0100
1511@@ -579,5 +579,414 @@
1512
1513 To compile it as a module, choose M here. If unsure, say N.
1514
1515+config IP_NF_TARGET_IPV4OPTSSTRIP
1516+ tristate 'IPV4OPTSSTRIP target support'
1517+ depends on IP_NF_MANGLE
1518+ help
1519+ This option adds CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP, which supplies a target
1520+ module that will allow you to strip all the IP options from a packet.
1521+
1522+ The target doesn't take any option, and therefore is extremly easy to use :
1523+
1524+ # iptables -t mangle -A PREROUTING -j IPV4OPTSSTRIP
1525+ # iptables -t mangle --list -n
1526+ Chain PREROUTING (policy ACCEPT)
1527+ target prot opt source destination
1528+ IPV4OPTSSTRIP all -- 0.0.0.0/0 0.0.0.0/0
1529+
1530+ Chain OUTPUT (policy ACCEPT)
1531+ target prot opt source destination
1532+
1533+config IP_NF_TARGET_NETLINK
1534+ tristate 'NETLINK target support'
1535+ depends on IP_NF_FILTER
1536+ help
1537+ CONFIG_IP_NF_TARGET_NETLINK adds a NETLINK target that sends dropped packets to
1538+ userspace via a netlink socket. Apps such as fwmon
1539+ (http://firestorm.geek-ware.co.uk) can then recieve and dislpay these packets.
1540+ This option is basically a re-implementation of the ipchains -o option.
1541+
1542+config IP_NF_TARGET_TTL
1543+ tristate 'TTL target support'
1544+ depends on IP_NF_MANGLE
1545+ help
1546+ This adds an iptables TTL manipulation target, which enables the user
1547+ to set the TTL value of an IP packet or to increment / decrement it
1548+ by a given value.
1549+
1550+config IP_NF_MATCH_CONNLIMIT
1551+ tristate 'Connections/IP limit match support'
1552+ depends on IP_NF_IPTABLES
1553+ help
1554+ This adds an iptables match which allows you to restrict the
1555+ number of parallel TCP connections to a server per client IP address
1556+ (or address block).
1557+
1558+ Examples:
1559+
1560+ # allow 2 telnet connections per client host
1561+ iptables -p tcp --syn --dport 23 -m connlimit --connlimit-above 2 -j REJECT
1562+
1563+ # you can also match the other way around:
1564+ iptables -p tcp --syn --dport 23 -m connlimit ! --connlimit-above 2 -j ACCEPT
1565+
1566+ # limit the nr of parallel http requests to 16 per class C sized
1567+ # network (24 bit netmask)
1568+ iptables -p tcp --syn --dport 80 -m connlimit --connlimit-above 16 \
1569+ --connlimit-mask 24 -j REJECT
1570+
1571+config IP_NF_MATCH_DSTLIMIT
1572+ tristate 'dstlimit match support'
1573+ depends on IP_NF_IPTABLES
1574+ help
1575+
1576+ This patch adds a new match called 'dstlimit'.
1577+ The idea is to have something like 'limit', but either per
1578+ destination-ip or per (destip,destport) tuple.
1579+
1580+ It gives you the ability to say
1581+ '1000 packets per second for every host in 192.168.0.0/16'
1582+ '100 packets per second for every service of 192.168.1.1'
1583+
1584+ Parameters are:
1585+ --dstlimit <rate>
1586+ A rate just like the limit match
1587+ --dstlimit-burst <num>
1588+ Burst value, just like limit match
1589+ --dstlimit-mode destip | destip-destport
1590+ Limit per IP or per port
1591+ --dstlimit-name foo
1592+ The name for the /proc/net/ipt_dstlimit/foo entry
1593+ --dstlimit-htable-size <num>
1594+ The number of buckets of the hash table
1595+ --dstlimit-htable-max <num>
1596+ Maximum entries in the hash
1597+ --dstlimit-htable-expire <num>
1598+ After how many miliseconds do hash entries expire
1599+ --dstlimit-htable-gcinterval <num>
1600+ How many miliseconds between garbage collection intervals
1601+
1602+
1603+config IP_NF_MATCH_FUZZY
1604+ tristate 'fuzzy match support'
1605+ depends on IP_NF_IPTABLES
1606+ help
1607+ This option adds a `fuzzy' match which allows you to match packets according to
1608+ a dynamic profile implemented by means of a simple Fuzzy Logic Controller (FLC)
1609+
1610+config IP_NF_MATCH_IPV4OPTIONS
1611+ tristate 'IPV4OPTIONS match support'
1612+ depends on IP_NF_IPTABLES
1613+ help
1614+ This option adds an iptables 'ipv4options' match, which allows you to
1615+ match on IPv4 header options like source routing, record route, timestamp and
1616+ router-alert.
1617+
1618+ Suppported options are:
1619+ --ssrr
1620+ To match packets with the flag strict source routing.
1621+ --lsrr
1622+ To match packets with the flag loose source routing.
1623+ --no-srr
1624+ To match packets with no flag for source routing.
1625+ [!] --rr
1626+ To match packets with the RR flag.
1627+ [!] --ts
1628+ To match packets with the TS flag.
1629+ [!] --ra
1630+ To match packets with the router-alert option.
1631+ [!] --any-opt
1632+ To match a packet with at least one IP option, or no IP option
1633+ at all if ! is chosen.
1634+
1635+ Example:
1636+ $ iptables -A input -m ipv4options --rr -j DROP
1637+ will drop packets with the record-route flag.
1638+
1639+ $ iptables -A input -m ipv4options --ts -j DROP
1640+ will drop packets with the timestamp flag.
1641+
1642+config IP_NF_MATCH_MPORT
1643+ tristate 'Multiple port with ranges match support'
1644+ depends on IP_NF_IPTABLES
1645+ help
1646+ This module is an enhanced multiport match. It has support for byte
1647+ ranges as well as for single ports.
1648+ Up to 15 ports are allowed. Note that a portrange uses up 2 port values.
1649+
1650+ Examples:
1651+ # iptables -A FORWARD -p tcp -m mport --ports 23:42,65
1652+
1653+config IP_NF_MATCH_NTH
1654+ tristate 'Nth match support'
1655+ depends on IP_NF_IPTABLES
1656+ help
1657+ This option adds an iptables `Nth' match, which allows you to match every Nth
1658+ packet encountered. By default there are 16 different counters that can be
1659+ used.
1660+
1661+ This match functions in one of two ways
1662+ 1) Match ever Nth packet, and only the Nth packet.
1663+ example:
1664+ iptables -t mangle -A PREROUTING -m nth --every 10 -j DROP
1665+ This rule will drop every 10th packet.
1666+ 2) Unique rule for every packet. This is an easy and quick
1667+ method to produce load-balancing for both inbound and outbound.
1668+ example:
1669+ iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1670+ --every 3 --packet 0 -j SNAT --to-source 10.0.0.5
1671+ iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1672+ --every 3 --packet 1 -j SNAT --to-source 10.0.0.6
1673+ iptables -t nat -A POSTROUTING -o eth0 -m nth --counter 7 \
1674+ --every 3 --packet 2 -j SNAT --to-source 10.0.0.7
1675+ This example evenly splits connections between the three SNAT
1676+ addresses.
1677+
1678+ By using the mangle table and iproute2, you can setup complex
1679+ load-balanced routing. There's lot of other uses. Be creative!
1680+
1681+ Suppported options are:
1682+ --every Nth Match every Nth packet
1683+ [--counter] num Use counter 0-15 (default:0)
1684+ [--start] num Initialize the counter at the number 'num'
1685+ instead of 0. Must be between 0 and Nth-1
1686+ [--packet] num Match on 'num' packet. Must be between 0
1687+ and Nth-1.
1688+ If --packet is used for a counter than
1689+ there must be Nth number of --packet
1690+ rules, covering all values between 0 and
1691+ Nth-1 inclusively.
1692+
1693+config IP_NF_MATCH_OSF
1694+ tristate 'OSF match support'
1695+ depends on IP_NF_IPTABLES
1696+ help
1697+ The idea of passive OS fingerprint matching exists for quite a long time,
1698+ but was created as extension fo OpenBSD pf only some weeks ago.
1699+ Original idea was lurked in some OpenBSD mailing list (thanks
1700+ grange@open...) and than adopted for Linux netfilter in form of this code.
1701+
1702+ Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
1703+ his excellent p0f and than changed a bit for more convenience.
1704+
1705+ This module compares some data(WS, MSS, options and it's order, ttl,
1706+ df and others) from first SYN packet (actually from packets with SYN
1707+ bit set) with hardcoded in fingers[] table ones.
1708+
1709+ Example: (Of course this only an example, do not get inspired by this)
1710+
1711+ # iptables -N LINUX
1712+ # iptables -A LINUX -j LOG --log-prefix "Linux"
1713+
1714+ # iptables -A INPUT -p tcp -m osf --genre Linux -j LINUX
1715+ # iptables -A INPUT -p tcp -m osf --genre FreeBSD -j REJECT
1716+
1717+ NOTE: -p tcp is obviously required as it is a TCP match.
1718+
1719+ OSF also has:
1720+ --log 1/0.
1721+ If present, OSF will log determined genres even if they don't match
1722+ desired one.
1723+ 0 - log all determined entries,
1724+ 1 - only first one.
1725+
1726+ Example:
1727+ #iptables -I INPUT -j ACCEPT -p tcp -m osf --genre Linux --log 1 --smart
1728+
1729+ In syslog you find something like this:
1730+ ipt_osf: Windows [Windows XP Pro SP1, 2000 SP3]: 11.22.33.55:4024 -> 11.22.33.44:139
1731+ ipt_osf: Unknown: 16384:106:1:48:020405B401010402 44.33.22.11:1239 -> 11.22.33.44:80
1732+
1733+ --smart
1734+ if present, OSF will use some smartness to determine remote OS.
1735+ Now only not use TTL( with it far remote machines can be determined).
1736+
1737+ Fingerprints can be loaded through /proc/sys/net/ipv4/osf file.
1738+ Only one fingerprint per open/close.
1739+
1740+ Fingerprints can be downloaded from http://www.openbsd.org/cgi-bin/cvsweb/src/etc/pf.os
1741+
1742+config IP_POOL_STATISTICS
1743+ bool 'enable statistics on pool usage'
1744+ depends on IP_NF_POOL!=n
1745+
1746+config IP_NF_POOL
1747+ tristate 'IP address pool support'
1748+ depends on IP_NF_IPTABLES
1749+ help
1750+ CONFIG_IP_NF_POOL provides a match which lets you use bitmaps with one bit per
1751+ address from some range of IP addresses; the match depends on whether a checked
1752+ source or destination address has its bit set in the pool. It also provides a
1753+ POOL target, which can be used to add or remove the addresses of a packet
1754+ to/from a pool.
1755+
1756+ There is also a POOL netfilter target, which can be used to set or remove the
1757+ addresses of a packet from a pool.
1758+
1759+ To define and use pools, you need userlevel utilities: a patched iptables, and
1760+ the program ippool(8), which defines the pools and their bounds. The current
1761+ release of pool matching is ippool-0.0.2, and can be found in the archives of
1762+ the netfilter mailing list at http://lists.netfilter.org/.
1763+
1764+config IP_NF_MATCH_PSD
1765+ tristate 'psd match support'
1766+ depends on IP_NF_IPTABLES
1767+ help
1768+ This option adds a `psd' match, which supplies portscan
1769+ detection match (psd). This match will attempt to detect TCP and UDP
1770+ port scans. This match was derived from Solar Designer's scanlogd.
1771+
1772+ Suppported options are:
1773+
1774+ --psd-weight-threshold <threshold>
1775+
1776+ Total weight of the latest TCP/UDP packets with different
1777+ destination ports coming from the same host to be treated as port
1778+ scan sequence.
1779+
1780+ --psd-delay-threshold <delay>
1781+
1782+ Delay (in hundredths of second) for the packets with different
1783+ destination ports coming from the same host to be treated as
1784+ possible port scan subsequence.
1785+
1786+ --psd-lo-ports-weight <weight>
1787+
1788+ Weight of the packet with privileged (<=1024) destination port.
1789+
1790+ --psd-hi-ports-weight <weight>
1791+
1792+ Weight of the packet with non-priviliged destination port.
1793+
1794+config IP_NF_MATCH_QUOTA
1795+ tristate 'quota match support'
1796+ depends on IP_NF_IPTABLES
1797+ help
1798+ This option adds CONFIG_IP_NF_MATCH_QUOTA, which implements network
1799+ quotas by decrementing a byte counter with each packet.
1800+
1801+ Supported options are:
1802+ --quota <bytes>
1803+ The quota in bytes.
1804+
1805+ KNOWN BUGS: this does not work on SMP systems.
1806+
1807+
1808+config IP_NF_MATCH_RANDOM
1809+ tristate 'random match support'
1810+ depends on IP_NF_IPTABLES
1811+ help
1812+ This option adds a `random' match,
1813+ which allow you to match packets randomly
1814+ following a given probability.
1815+
1816+ Suppported options are:
1817+
1818+ [--average] percent will match randomly packets with a probability of
1819+ 'percent'. default is 50%
1820+
1821+config IP_NF_MATCH_REALM
1822+ tristate 'realm match support'
1823+ depends on IP_NF_IPTABLES
1824+ help
1825+ realm match: uses realm key from routing as match criteria similiar to
1826+ one in packet classifier
1827+
1828+ /** snip from packet classifier documentation */
1829+ Routing tables based classifier
1830+ CONFIG_NET_CLS_ROUTE4
1831+ If you say Y here, you will be able to classify outgoing packets
1832+ according to the route table entry they matched. If unsure, say Y.
1833+ /** end snip **/
1834+
1835+
1836+ # Example
1837+ # add route
1838+ /sbin/ip route add 194.29.194.0/24 via 194.29.192.1 realm 10
1839+
1840+ # source realm is in realm with mask 0xFFFF0000,
1841+ # destination is in realm with mask 0x0000FFFF
1842+
1843+ # match destination realm
1844+ /usr/local/sbin/iptables -A OUTPUT -m realm --realm 10 -j LOG
1845+
1846+ # match realm of source, this is also determinated by routing,
1847+ /usr/local/sbin/iptables -A INPUT -m realm --realm 655360 -j LOG
1848+
1849+ THIS PATCH REQUIRES CONFIG_NET_CLS_ROUTE TO BE SET
1850+
1851+config IP_NF_MATCH_TIME
1852+ tristate 'TIME match support'
1853+ depends on IP_NF_IPTABLES
1854+ help
1855+
1856+ This option adds CONFIG_IP_NF_MATCH_TIME, which supplies a time match module.
1857+ This match allows you to filter based on the packet arrival time
1858+ (arrival time at the machine which the netfilter is running on) or
1859+ departure time (for locally generated packets).
1860+
1861+ Supported options are:
1862+ --timestart HH:MM
1863+ The starting point of the time match frame.
1864+
1865+ --timestop HH:MM
1866+ The stopping point of the time match frame
1867+
1868+ --days Tue,Mon...
1869+ Days of the week to match separated by a coma, no space
1870+ (one of Sun,Mon,Tue,Wed,Thu,Fri,Sat)
1871+
1872+ Example:
1873+ -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon,Tue,Wed,Thu,Fri
1874+ will match packets that have an arrival timestamp in the range 8:00->18:00 from Monday
1875+ to Friday.
1876+
1877+ -A OUTPUT -m time --timestart 8:00 --timestop 18:00 --Days Mon
1878+ will match the packets (locally generated) that have a departure timestamp
1879+ in the range 8:00->18:00 on Monday only.
1880+
1881+config IP_NF_MATCH_U32
1882+ tristate 'U32 match support'
1883+ depends on IP_NF_IPTABLES
1884+ help
1885+
1886+ U32 allows you to extract quantities of up to 4 bytes from a packet,
1887+ AND them with specified masks, shift them by specified amounts and
1888+ test whether the results are in any of a set of specified ranges.
1889+ The specification of what to extract is general enough to skip over
1890+ headers with lengths stored in the packet, as in IP or TCP header
1891+ lengths.
1892+ Details and examples are in the kernel module source.
1893+
1894+config IP_NF_SET
1895+ tristate 'IP address/port sets support'
1896+ depends on IP_NF_IPTABLES
1897+ help
1898+
1899+config IP_NF_SET_MAX
1900+ int ' Maximum number of sets'
1901+ depends on IP_NF_SET
1902+ default 256
1903+
1904+config IP_NF_SET_IPMAP
1905+ tristate ' ipmap set type support'
1906+ depends on IP_NF_SET
1907+ help
1908+
1909+config IP_NF_SET_PORTMAP
1910+ tristate ' portmap set type support'
1911+ depends on IP_NF_SET
1912+ help
1913+
1914+config IP_NF_SET_MACIPMAP
1915+ tristate ' macipmap set type support'
1916+ depends on IP_NF_SET
1917+ help
1918+
1919+config IP_NF_SET_IPHASH
1920+ tristate ' iphash set type support'
1921+ depends on IP_NF_SET
1922+ help
1923+
1924 endmenu
1925
1926diff -Nur linux-2.6.3.org/net/ipv4/netfilter/Makefile linux-2.6.3/net/ipv4/netfilter/Makefile
1927--- linux-2.6.3.org/net/ipv4/netfilter/Makefile 2004-02-18 04:57:20.000000000 +0100
1928+++ linux-2.6.3/net/ipv4/netfilter/Makefile 2004-02-19 08:55:20.544815689 +0100
1929@@ -42,15 +42,38 @@
1930 # matches
1931 obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
1932 obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
1933+obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
1934+obj-$(CONFIG_IP_NF_MATCH_DSTLIMIT) += ipt_dstlimit.o
1935 obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
1936+obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
1937 obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
1938 obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
1939
1940 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
1941 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
1942+
1943+obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
1944+
1945 obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
1946 obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
1947
1948+obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
1949+
1950+
1951+obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
1952+
1953+obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
1954+
1955+obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
1956+
1957+
1958+obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
1959+
1960+obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
1961+
1962+
1963+obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
1964+
1965 obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
1966
1967 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
1968@@ -59,10 +82,15 @@
1969
1970 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
1971
1972+obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
1973+
1974+
1975 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
1976 obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
1977+obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
1978 obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
1979 obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
1980+obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
1981
1982 obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
1983
1984@@ -79,6 +107,9 @@
1985 obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
1986 obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
1987 obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
1988+obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
1989+obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
1990+obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
1991 obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
1992 obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
1993
1994@@ -94,3 +125,10 @@
1995 obj-$(CONFIG_IP_NF_COMPAT_IPFWADM) += ipfwadm.o
1996
1997 obj-$(CONFIG_IP_NF_QUEUE) += ip_queue.o
1998+
1999+obj-$(CONFIG_IP_NF_SET) += ipt_set.o ipt_SET.o ip_set.o
2000+obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o
2001+obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
2002+obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
2003+obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
2004+
2005diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_pool.c linux-2.6.3/net/ipv4/netfilter/ip_pool.c
2006--- linux-2.6.3.org/net/ipv4/netfilter/ip_pool.c 1970-01-01 01:00:00.000000000 +0100
2007+++ linux-2.6.3/net/ipv4/netfilter/ip_pool.c 2004-02-19 09:08:42.247779733 +0100
2008@@ -0,0 +1,334 @@
2009+/* Kernel module for IP pool management */
2010+
2011+#include <linux/module.h>
2012+#include <linux/ip.h>
2013+#include <linux/skbuff.h>
2014+#include <linux/netfilter_ipv4/ip_tables.h>
2015+#include <linux/netfilter_ipv4/ip_pool.h>
2016+#include <linux/errno.h>
2017+#include <asm/uaccess.h>
2018+#include <asm/bitops.h>
2019+#include <linux/interrupt.h>
2020+#include <linux/spinlock.h>
2021+
2022+#if 0
2023+#define DP printk
2024+#else
2025+#define DP(format, args...)
2026+#endif
2027+
2028+MODULE_LICENSE("GPL");
2029+
2030+#define NR_POOL 16
2031+static int nr_pool = NR_POOL;/* overwrite this when loading module */
2032+
2033+struct ip_pool {
2034+ u_int32_t first_ip; /* host byte order, included in range */
2035+ u_int32_t last_ip; /* host byte order, included in range */
2036+ void *members; /* the bitmap proper */
2037+ int nr_use; /* total nr. of tests through this */
2038+ int nr_match; /* total nr. of matches through this */
2039+ rwlock_t lock;
2040+};
2041+
2042+static struct ip_pool *POOL;
2043+
2044+static inline struct ip_pool *lookup(ip_pool_t index)
2045+{
2046+ if (index < 0 || index >= nr_pool) {
2047+ DP("ip_pool:lookup: bad index %d\n", index);
2048+ return 0;
2049+ }
2050+ return POOL+index;
2051+}
2052+
2053+int ip_pool_match(ip_pool_t index, u_int32_t addr)
2054+{
2055+ struct ip_pool *pool = lookup(index);
2056+ int res = 0;
2057+
2058+ if (!pool || !pool->members)
2059+ return 0;
2060+ read_lock_bh(&pool->lock);
2061+ if (pool->members) {
2062+ if (addr >= pool->first_ip && addr <= pool->last_ip) {
2063+ addr -= pool->first_ip;
2064+ if (test_bit(addr, pool->members)) {
2065+ res = 1;
2066+#ifdef CONFIG_IP_POOL_STATISTICS
2067+ pool->nr_match++;
2068+#endif
2069+ }
2070+ }
2071+#ifdef CONFIG_IP_POOL_STATISTICS
2072+ pool->nr_use++;
2073+#endif
2074+ }
2075+ read_unlock_bh(&pool->lock);
2076+ return res;
2077+}
2078+EXPORT_SYMBOL(ip_pool_match);
2079+
2080+static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
2081+{
2082+ struct ip_pool *pool;
2083+ int res = -1;
2084+
2085+ pool = lookup(index);
2086+ if ( !pool || !pool->members
2087+ || addr < pool->first_ip || addr > pool->last_ip)
2088+ return -1;
2089+ read_lock_bh(&pool->lock);
2090+ if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
2091+ addr -= pool->first_ip;
2092+ res = isdel
2093+ ? (0 != test_and_clear_bit(addr, pool->members))
2094+ : (0 != test_and_set_bit(addr, pool->members));
2095+ }
2096+ read_unlock_bh(&pool->lock);
2097+ return res;
2098+}
2099+
2100+int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
2101+{
2102+ int res = pool_change(index,addr,isdel);
2103+
2104+ if (!isdel) res = !res;
2105+ return res;
2106+}
2107+EXPORT_SYMBOL(ip_pool_mod);
2108+
2109+static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
2110+{
2111+ return 4*((((b-a+8)/8)+3)/4);
2112+}
2113+
2114+static inline int poolbytes(ip_pool_t index)
2115+{
2116+ struct ip_pool *pool = lookup(index);
2117+
2118+ return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
2119+}
2120+
2121+static int setpool(
2122+ struct sock *sk,
2123+ int optval,
2124+ void *user,
2125+ unsigned int len
2126+) {
2127+ struct ip_pool_request req;
2128+
2129+ DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
2130+ if (!capable(CAP_NET_ADMIN))
2131+ return -EPERM;
2132+ if (optval != SO_IP_POOL)
2133+ return -EBADF;
2134+ if (len != sizeof(req))
2135+ return -EINVAL;
2136+ if (copy_from_user(&req, user, sizeof(req)) != 0)
2137+ return -EFAULT;
2138+ printk("obsolete op - upgrade your ippool(8) utility.\n");
2139+ return -EINVAL;
2140+}
2141+
2142+static int getpool(
2143+ struct sock *sk,
2144+ int optval,
2145+ void *user,
2146+ int *len
2147+) {
2148+ struct ip_pool_request req;
2149+ struct ip_pool *pool;
2150+ ip_pool_t i;
2151+ int newbytes;
2152+ void *newmembers;
2153+ int res;
2154+
2155+ DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
2156+ if (!capable(CAP_NET_ADMIN))
2157+ return -EINVAL;
2158+ if (optval != SO_IP_POOL)
2159+ return -EINVAL;
2160+ if (*len != sizeof(req)) {
2161+ return -EFAULT;
2162+ }
2163+ if (copy_from_user(&req, user, sizeof(req)) != 0)
2164+ return -EFAULT;
2165+ DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
2166+ if (req.op < IP_POOL_BAD001) {
2167+ printk("obsolete op - upgrade your ippool(8) utility.\n");
2168+ return -EFAULT;
2169+ }
2170+ switch(req.op) {
2171+ case IP_POOL_HIGH_NR:
2172+ DP("ip_pool HIGH_NR\n");
2173+ req.index = IP_POOL_NONE;
2174+ for (i=0; i<nr_pool; i++)
2175+ if (POOL[i].members)
2176+ req.index = i;
2177+ return copy_to_user(user, &req, sizeof(req));
2178+ case IP_POOL_LOOKUP:
2179+ DP("ip_pool LOOKUP\n");
2180+ pool = lookup(req.index);
2181+ if (!pool)
2182+ return -EINVAL;
2183+ if (!pool->members)
2184+ return -EBADF;
2185+ req.addr = htonl(pool->first_ip);
2186+ req.addr2 = htonl(pool->last_ip);
2187+ return copy_to_user(user, &req, sizeof(req));
2188+ case IP_POOL_USAGE:
2189+ DP("ip_pool USE\n");
2190+ pool = lookup(req.index);
2191+ if (!pool)
2192+ return -EINVAL;
2193+ if (!pool->members)
2194+ return -EBADF;
2195+ req.addr = pool->nr_use;
2196+ req.addr2 = pool->nr_match;
2197+ return copy_to_user(user, &req, sizeof(req));
2198+ case IP_POOL_TEST_ADDR:
2199+ DP("ip_pool TEST 0x%08x\n", req.addr);
2200+ pool = lookup(req.index);
2201+ if (!pool)
2202+ return -EINVAL;
2203+ res = 0;
2204+ read_lock_bh(&pool->lock);
2205+ if (!pool->members) {
2206+ DP("ip_pool TEST_ADDR no members in pool\n");
2207+ res = -EBADF;
2208+ goto unlock_and_return_res;
2209+ }
2210+ req.addr = ntohl(req.addr);
2211+ if (req.addr < pool->first_ip) {
2212+ DP("ip_pool TEST_ADDR address < pool bounds\n");
2213+ res = -ERANGE;
2214+ goto unlock_and_return_res;
2215+ }
2216+ if (req.addr > pool->last_ip) {
2217+ DP("ip_pool TEST_ADDR address > pool bounds\n");
2218+ res = -ERANGE;
2219+ goto unlock_and_return_res;
2220+ }
2221+ req.addr = (0 != test_bit((req.addr - pool->first_ip),
2222+ pool->members));
2223+ read_unlock_bh(&pool->lock);
2224+ return copy_to_user(user, &req, sizeof(req));
2225+ case IP_POOL_FLUSH:
2226+ DP("ip_pool FLUSH not yet implemented.\n");
2227+ return -EBUSY;
2228+ case IP_POOL_DESTROY:
2229+ DP("ip_pool DESTROY not yet implemented.\n");
2230+ return -EBUSY;
2231+ case IP_POOL_INIT:
2232+ DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
2233+ pool = lookup(req.index);
2234+ if (!pool)
2235+ return -EINVAL;
2236+ req.addr = ntohl(req.addr);
2237+ req.addr2 = ntohl(req.addr2);
2238+ if (req.addr > req.addr2) {
2239+ DP("ip_pool INIT bad ip range\n");
2240+ return -EINVAL;
2241+ }
2242+ newbytes = bitmap_bytes(req.addr, req.addr2);
2243+ newmembers = kmalloc(newbytes, GFP_KERNEL);
2244+ if (!newmembers) {
2245+ DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
2246+ return -ENOMEM;
2247+ }
2248+ memset(newmembers, 0, newbytes);
2249+ write_lock_bh(&pool->lock);
2250+ if (pool->members) {
2251+ DP("ip_pool INIT pool %d exists\n", req.index);
2252+ kfree(newmembers);
2253+ res = -EBUSY;
2254+ goto unlock_and_return_res;
2255+ }
2256+ pool->first_ip = req.addr;
2257+ pool->last_ip = req.addr2;
2258+ pool->nr_use = 0;
2259+ pool->nr_match = 0;
2260+ pool->members = newmembers;
2261+ write_unlock_bh(&pool->lock);
2262+ return 0;
2263+ case IP_POOL_ADD_ADDR:
2264+ DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
2265+ req.addr = pool_change(req.index, ntohl(req.addr), 0);
2266+ return copy_to_user(user, &req, sizeof(req));
2267+ case IP_POOL_DEL_ADDR:
2268+ DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
2269+ req.addr = pool_change(req.index, ntohl(req.addr), 1);
2270+ return copy_to_user(user, &req, sizeof(req));
2271+ default:
2272+ DP("ip_pool:getpool bad op %d\n", req.op);
2273+ return -EINVAL;
2274+ }
2275+ return -EINVAL;
2276+
2277+unlock_and_return_res:
2278+ if (pool)
2279+ read_unlock_bh(&pool->lock);
2280+ return res;
2281+}
2282+
2283+static struct nf_sockopt_ops so_pool
2284+= { { NULL, NULL }, PF_INET,
2285+ SO_IP_POOL, SO_IP_POOL+1, &setpool,
2286+ SO_IP_POOL, SO_IP_POOL+1, &getpool,
2287+ 0, NULL };
2288+
2289+MODULE_PARM(nr_pool, "i");
2290+
2291+static int __init init(void)
2292+{
2293+ ip_pool_t i;
2294+ int res;
2295+
2296+ if (nr_pool < 1) {
2297+ printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
2298+ return -EINVAL;
2299+ }
2300+ POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
2301+ if (!POOL) {
2302+ printk("ip_pool module init: out of memory for nr_pool %d\n",
2303+ nr_pool);
2304+ return -ENOMEM;
2305+ }
2306+ for (i=0; i<nr_pool; i++) {
2307+ POOL[i].first_ip = 0;
2308+ POOL[i].last_ip = 0;
2309+ POOL[i].members = 0;
2310+ POOL[i].nr_use = 0;
2311+ POOL[i].nr_match = 0;
2312+ POOL[i].lock = RW_LOCK_UNLOCKED;
2313+ }
2314+ res = nf_register_sockopt(&so_pool);
2315+ DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
2316+ if (res != 0) {
2317+ kfree(POOL);
2318+ POOL = 0;
2319+ }
2320+ return res;
2321+}
2322+
2323+static void __exit fini(void)
2324+{
2325+ ip_pool_t i;
2326+
2327+ DP("ip_pool:fini BYEBYE\n");
2328+ nf_unregister_sockopt(&so_pool);
2329+ for (i=0; i<nr_pool; i++) {
2330+ if (POOL[i].members) {
2331+ kfree(POOL[i].members);
2332+ POOL[i].members = 0;
2333+ }
2334+ }
2335+ kfree(POOL);
2336+ POOL = 0;
2337+ DP("ip_pool:fini these are the famous last words\n");
2338+ return;
2339+}
2340+
2341+module_init(init);
2342+module_exit(fini);
2343diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set.c linux-2.6.3/net/ipv4/netfilter/ip_set.c
2344--- linux-2.6.3.org/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
2345+++ linux-2.6.3/net/ipv4/netfilter/ip_set.c 2004-02-09 15:02:00.000000000 +0100
2346@@ -0,0 +1,1494 @@
2347+/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
2348+ * Patrick Schaaf (bof@bof.de)
2349+ * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2350+ *
2351+ * This program is free software; you can redistribute it and/or modify
2352+ * it under the terms of the GNU General Public License as published by
2353+ * the Free Software Foundation; either version 2 of the License, or
2354+ * (at your option) any later version.
2355+ *
2356+ * This program is distributed in the hope that it will be useful,
2357+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2358+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2359+ * GNU General Public License for more details.
2360+ *
2361+ * You should have received a copy of the GNU General Public License
2362+ * along with this program; if not, write to the Free Software
2363+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2364+ */
2365+
2366+/* Kernel module for IP set management */
2367+
2368+#include <linux/config.h>
2369+#include <linux/module.h>
2370+#include <linux/ip.h>
2371+#include <linux/skbuff.h>
2372+#include <linux/netfilter_ipv4/ip_tables.h>
2373+#include <linux/errno.h>
2374+#include <asm/uaccess.h>
2375+#include <asm/bitops.h>
2376+#include <asm/softirq.h>
2377+#include <linux/spinlock.h>
2378+#include <linux/vmalloc.h>
2379+
2380+#define ASSERT_READ_LOCK(x) /* dont use that */
2381+#define ASSERT_WRITE_LOCK(x)
2382+#include <linux/netfilter_ipv4/listhelp.h>
2383+#include <linux/netfilter_ipv4/ip_set.h>
2384+
2385+static struct list_head set_type_list; /* all registred set types */
2386+struct ip_set **ip_set_list; /* all individual sets */
2387+static rwlock_t list_lock = RW_LOCK_UNLOCKED; /* protects both set_type_list and ip_set_list */
2388+static unsigned int max_sets = 0; /* max number of sets, */
2389+
2390+/* Arrgh */
2391+#ifdef MODULE
2392+#define __MOD_INC(foo) __MOD_INC_USE_COUNT(foo)
2393+#define __MOD_DEC(foo) __MOD_DEC_USE_COUNT(foo)
2394+#else
2395+#define __MOD_INC(foo) do { } while (0)
2396+#define __MOD_DEC(foo) do { } while (0)
2397+#endif
2398+
2399+#define NOT_IN_CHILD_SET(fn,args...) \
2400+ !*private \
2401+ || !(*private)->childsets \
2402+ || (set->type[i]->fn(*private,##args) < 0)
2403+
2404+static struct ip_set_private **
2405+ip_set_find_private(struct ip_set *set,
2406+ struct ip_set_private **private,
2407+ ip_set_ip_t *ip,
2408+ u_int8_t level)
2409+{
2410+ int i;
2411+ ip_set_ip_t id;
2412+
2413+ for (i = 0; i < level; i++) {
2414+ if (NOT_IN_CHILD_SET(matchip, ip[i], &id))
2415+ return NULL;
2416+ private = &(*private)->childsets[id];
2417+ }
2418+ DP("id: %i private: %p %p", id, private, *private);
2419+ return private;
2420+}
2421+
2422+/* Destroy function for the private part of the (child)sets.
2423+ * Must be called without holding any locks.
2424+ */
2425+static void
2426+ip_set_destroy_private(struct ip_set *set,
2427+ struct ip_set_private **private,
2428+ u_int8_t level)
2429+{
2430+ int i;
2431+
2432+ DP("set %p private %p %p %p", set, private, *private, (*private)->childsets);
2433+ if ((*private)->childsets) {
2434+ for (i = 0; i < set->type[level]->sizeid(*private); i++)
2435+ if ((*private)->childsets[i]) {
2436+ DP("%i -> %p", i, (*private)->childsets[i]);
2437+ ip_set_destroy_private(set,
2438+ &(*private)->childsets[i],
2439+ level + 1);
2440+ }
2441+ vfree((*private)->childsets);
2442+ }
2443+
2444+ set->type[level]->destroy(private);
2445+ DP("%p %p", private, *private);
2446+}
2447+
2448+static void ip_set_flush_private(struct ip_set *set,
2449+ struct ip_set_private *private,
2450+ u_int8_t level,
2451+ u_int8_t childsets)
2452+{
2453+ int i;
2454+
2455+ if (childsets && private->childsets)
2456+ for (i = 0; i < set->type[level]->sizeid(private); i++)
2457+ if (private->childsets[i])
2458+ ip_set_flush_private(set,
2459+ private->childsets[i],
2460+ level + 1,
2461+ childsets);
2462+
2463+ set->type[level]->flush(private);
2464+
2465+}
2466+
2467+/* ip_set_flush() - flush data in a set
2468+ */
2469+static int ip_set_flush(struct ip_set *set,
2470+ ip_set_ip_t *ip,
2471+ u_int8_t level,
2472+ u_int8_t childsets)
2473+{
2474+ int res = 0;
2475+ struct ip_set_private **private;
2476+
2477+ write_lock_bh(&set->lock);
2478+ if (set->subref) {
2479+ res = -EBUSY;
2480+ goto unlock;
2481+ }
2482+
2483+ private = ip_set_find_private(set, &set->private, ip, level);
2484+
2485+ if (private)
2486+ ip_set_flush_private(set, *private, level, childsets);
2487+
2488+ unlock:
2489+ write_unlock_bh(&set->lock);
2490+ return res;
2491+}
2492+
2493+int
2494+ip_set_testip_kernel(struct ip_set *set,
2495+ const struct sk_buff *skb,
2496+ const u_int32_t *flags,
2497+ u_int8_t set_level,
2498+ u_int8_t ip_level)
2499+{
2500+ struct ip_set_private **private = &set->private;
2501+ ip_set_ip_t id;
2502+ int i, res = 0;
2503+
2504+ read_lock_bh(&set->lock);
2505+ if (set->levels < ip_level || set->subref)
2506+ goto unlock;
2507+
2508+ for (i = 0; i < set_level; i++) {
2509+ if (NOT_IN_CHILD_SET(testip_kernel, skb,
2510+ flags[i] | set->type[i]->typecode, &id))
2511+ goto unlock;
2512+ DP("id: %i private: %p", id, *private);
2513+ private = &(*private)->childsets[id];
2514+ }
2515+ for (i = set_level; private && *private && i < ip_level; i++) {
2516+ if (set->type[i]->testip_kernel(*private, skb,
2517+ flags[i] | set->type[i]->typecode, &id) <= 0)
2518+ goto unlock;
2519+ private = (*private)->childsets
2520+ ? &(*private)->childsets[id] : NULL;
2521+ }
2522+ res = 1;
2523+ unlock:
2524+ read_unlock_bh(&set->lock);
2525+ return res;
2526+}
2527+
2528+void
2529+ip_set_addip_kernel(struct ip_set *set,
2530+ const struct sk_buff *skb,
2531+ const u_int32_t *flags,
2532+ u_int8_t set_level,
2533+ u_int8_t ip_level)
2534+{
2535+ struct ip_set_private **private = &set->private;
2536+ ip_set_ip_t id;
2537+ int i, res;
2538+
2539+ write_lock_bh(&set->lock);
2540+ if (set->levels < ip_level || set->subref) {
2541+ write_unlock_bh(&set->lock);
2542+ return;
2543+ }
2544+ for (i = 0; i < set_level; i++) {
2545+ if (NOT_IN_CHILD_SET(testip_kernel, skb,
2546+ flags[i] | set->type[i]->typecode, &id)) {
2547+ write_unlock_bh(&set->lock);
2548+ return;
2549+ }
2550+ private = &(*private)->childsets[id];
2551+ }
2552+ for (i = set_level; private && *private && i < ip_level; i++) {
2553+ res = set->type[i]->addip_kernel(*private, skb,
2554+ flags[i] | set->type[i]->typecode, &id);
2555+ if (!(res == 0 || res == -EEXIST)) {
2556+ write_unlock_bh(&set->lock);
2557+ return;
2558+ }
2559+ private = (*private)->childsets
2560+ ? &(*private)->childsets[id] : NULL;
2561+ }
2562+ write_unlock_bh(&set->lock);
2563+}
2564+
2565+void
2566+ip_set_delip_kernel(struct ip_set *set,
2567+ const struct sk_buff *skb,
2568+ const u_int32_t *flags,
2569+ u_int8_t set_level,
2570+ u_int8_t ip_level)
2571+{
2572+ struct ip_set_private **private = &set->private;
2573+ ip_set_ip_t id;
2574+ int i, res;
2575+
2576+ write_lock_bh(&set->lock);
2577+ if (set->levels < ip_level || set->subref) {
2578+ write_unlock_bh(&set->lock);
2579+ return;
2580+ }
2581+ for (i = 0; i < set_level; i++) {
2582+ if (NOT_IN_CHILD_SET(testip_kernel, skb,
2583+ flags[i] | set->type[i]->typecode, &id)) {
2584+ write_unlock_bh(&set->lock);
2585+ return;
2586+ }
2587+ private = &(*private)->childsets[id];
2588+ }
2589+ for (i = set_level; private && *private && i < ip_level; i++) {
2590+ res = set->type[i]->delip_kernel(*private, skb,
2591+ flags[i] | set->type[i]->typecode, &id);
2592+ if (!(res == 0 || res == -EEXIST)) {
2593+ write_unlock_bh(&set->lock);
2594+ return;
2595+ }
2596+ private = (*private)->childsets
2597+ ? &(*private)->childsets[id] : NULL;
2598+ }
2599+ write_unlock_bh(&set->lock);
2600+}
2601+
2602+static int
2603+ip_set_addip(struct ip_set *set,
2604+ ip_set_ip_t *ip,
2605+ u_int8_t level,
2606+ const void *data,
2607+ size_t size)
2608+{
2609+ struct ip_set_private **private;
2610+ ip_set_ip_t id;
2611+ int res = 0;
2612+
2613+ DP("%s %i %d", set->name, level, size);
2614+ write_lock_bh(&set->lock);
2615+ if (set->subref) {
2616+ res = -EBUSY;
2617+ goto unlock;
2618+ }
2619+ private = ip_set_find_private(set, &set->private, ip, level);
2620+ DP("%s %i %d", set->name, level, size);
2621+ while (level <= set->levels && size) {
2622+ DP("%s %i %d", set->name, level, size);
2623+ if (!(private && *private)) {
2624+ res = -ENOENT;
2625+ goto unlock;
2626+ }
2627+ if (size < set->type[level]->reqsize) {
2628+ res = -EINVAL;
2629+ goto unlock;
2630+ }
2631+ res = set->type[level]->addip(*private, data,
2632+ set->type[level]->reqsize, &id);
2633+ if (!(res == 0 || res == -EEXIST))
2634+ goto unlock;
2635+ private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2636+ data += set->type[level]->reqsize;
2637+ size -= set->type[level++]->reqsize;
2638+ }
2639+ if (size)
2640+ res = -EINVAL;
2641+ unlock:
2642+ write_unlock_bh(&set->lock);
2643+ return res;
2644+}
2645+
2646+static int
2647+ip_set_delip(struct ip_set *set,
2648+ ip_set_ip_t *ip,
2649+ u_int8_t level,
2650+ const void *data,
2651+ size_t size)
2652+{
2653+ struct ip_set_private **private;
2654+ ip_set_ip_t id;
2655+ int res = 0;
2656+
2657+ write_lock_bh(&set->lock);
2658+ if (set->subref) {
2659+ res = -EBUSY;
2660+ goto unlock;
2661+ }
2662+ private = ip_set_find_private(set, &set->private, ip, level);
2663+ while (level <= set->levels && size) {
2664+ if (!(private && *private)) {
2665+ res = -ENOENT;
2666+ goto unlock;
2667+ }
2668+ if (size < set->type[level]->reqsize) {
2669+ res = -EINVAL;
2670+ goto unlock;
2671+ }
2672+ res = set->type[level]->delip(*private, data,
2673+ set->type[level]->reqsize, &id);
2674+ if (!(res == 0 || res == -EEXIST))
2675+ goto unlock;
2676+ private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2677+ data += set->type[level]->reqsize;
2678+ size -= set->type[level++]->reqsize;
2679+ }
2680+ if (size)
2681+ res = -EINVAL;
2682+ unlock:
2683+ write_unlock_bh(&set->lock);
2684+ return res;
2685+}
2686+
2687+static int
2688+ip_set_testip(struct ip_set *set,
2689+ ip_set_ip_t *ip,
2690+ u_int8_t level,
2691+ const void *data,
2692+ size_t size)
2693+{
2694+ struct ip_set_private **private;
2695+ ip_set_ip_t id;
2696+ int res = 0;
2697+
2698+ write_lock_bh(&set->lock);
2699+ if (set->subref) {
2700+ res = -EBUSY;
2701+ goto unlock;
2702+ }
2703+ private = ip_set_find_private(set, &set->private, ip, level);
2704+ while (level <= set->levels && size) {
2705+ if (!(private && *private)) {
2706+ res = -ENOENT;
2707+ goto unlock;
2708+ }
2709+ if (size < set->type[level]->reqsize) {
2710+ res = -EINVAL;
2711+ goto unlock;
2712+ }
2713+ res = set->type[level]->testip(*private, data,
2714+ set->type[level]->reqsize, &id);
2715+ DP("level: %i res: %i", level, res);
2716+ if (res <= 0)
2717+ goto unlock;
2718+ private = (*private)->childsets ? &(*private)->childsets[id] : NULL;
2719+ data += set->type[level]->reqsize;
2720+ size -= set->type[level++]->reqsize;
2721+ }
2722+ if (size)
2723+ res = -EINVAL;
2724+ unlock:
2725+ write_unlock_bh(&set->lock);
2726+ return (res > 0);
2727+}
2728+
2729+static inline int
2730+set_type_equal(const struct ip_set_type *set_type, const char *str2)
2731+{
2732+ DP("'%s' vs. '%s'", set_type->typename, str2);
2733+ return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
2734+}
2735+
2736+/*
2737+ * Always use find_setfoo() under the &list_lock.
2738+ */
2739+static inline struct ip_set_type *find_set_type(const char name[IP_SET_MAXNAMELEN])
2740+{
2741+ return LIST_FIND(&set_type_list,
2742+ set_type_equal,
2743+ struct ip_set_type *,
2744+ name);
2745+}
2746+
2747+int ip_set_register_set_type(struct ip_set_type *set_type)
2748+{
2749+ if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
2750+ ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
2751+ set_type->typename,
2752+ set_type->protocol_version,
2753+ IP_SET_PROTOCOL_VERSION);
2754+ return -EINVAL;
2755+ }
2756+
2757+ write_lock_bh(&list_lock);
2758+ if (find_set_type(set_type->typename)) {
2759+ /* Duplicate! */
2760+ write_unlock_bh(&list_lock);
2761+ ip_set_printk("'%s' already registered!",
2762+ set_type->typename);
2763+ return -EINVAL;
2764+ }
2765+ MOD_INC_USE_COUNT;
2766+ list_append(&set_type_list, set_type);
2767+ write_unlock_bh(&list_lock);
2768+ DP("'%s' registered.", set_type->typename);
2769+ return 0;
2770+}
2771+
2772+void ip_set_unregister_set_type(struct ip_set_type *set_type)
2773+{
2774+ write_lock_bh(&list_lock);
2775+ if (!find_set_type(set_type->typename)) {
2776+ ip_set_printk("'%s' not registered?",
2777+ set_type->typename);
2778+ write_unlock_bh(&list_lock);
2779+ return;
2780+ }
2781+ LIST_DELETE(&set_type_list, set_type);
2782+ write_unlock_bh(&list_lock);
2783+ MOD_DEC_USE_COUNT;
2784+
2785+ DP("'%s' unregistered.", set_type->typename);
2786+}
2787+
2788+/* Create the private part of a (child)set.
2789+ * Must be called without holding any locks.
2790+ */
2791+static int
2792+ip_set_create_private(struct ip_set_type *set_type,
2793+ struct ip_set_private **private,
2794+ const void *data,
2795+ size_t size,
2796+ u_int8_t childsets)
2797+{
2798+ int res = 0;
2799+ int newbytes;
2800+
2801+ DP("%s %p %p %i", set_type->typename, private, *private, childsets);
2802+
2803+ if (*private)
2804+ printk("%p: %p as private already occupied", private, *private);
2805+
2806+ /* Call the set_type initializer. */
2807+ res = set_type->create(private, data, size);
2808+ if (res != 0)
2809+ return res;
2810+
2811+ if (!childsets) {
2812+ (*private)->childsets = NULL;
2813+ return res;
2814+ }
2815+
2816+ /* Create room for subsets */
2817+ newbytes = set_type->sizeid(*private) * sizeof(struct ip_set_private *);
2818+ DP("%s (%p) %i", set_type->typename, *private, newbytes);
2819+ (*private)->childsets = vmalloc(newbytes); \
2820+ if (!(*private)->childsets) {
2821+ set_type->destroy(private);
2822+ return -ENOMEM;
2823+ }
2824+ DP("%s %p %p %p", set_type->typename, private, *private, (*private)->childsets);
2825+ memset((*private)->childsets, 0, newbytes);
2826+ return res;
2827+}
2828+
2829+static int
2830+ip_set_create_childset(struct ip_set *set,
2831+ ip_set_ip_t *ip,
2832+ u_int8_t level,
2833+ u_int8_t childsets,
2834+ const void *data,
2835+ size_t size)
2836+{
2837+ struct ip_set_private **private = &set->private;
2838+ ip_set_ip_t id;
2839+ int res;
2840+
2841+ DP("%s (%i %i)", set->name, level, childsets);
2842+ write_lock_bh(&set->lock);
2843+ if (set->subref) {
2844+ res = -EBUSY;
2845+ goto unlock;
2846+ }
2847+ if (level > 1)
2848+ private = ip_set_find_private(set, private, ip, level - 1);
2849+ DP("%s (%i %i) %p %p", set->name, level, childsets, private, *private);
2850+ if (!(private && *private && (*private)->childsets)) {
2851+ res = -ENOENT;
2852+ goto unlock;
2853+ }
2854+ DP("%s (%i %i) %p %p", set->name, level, childsets, private, *private);
2855+ set->type[level - 1]->matchip(*private, ip[level - 1], &id);
2856+ DP("%s (%i %i) %p %p %i", set->name, level, childsets, private, *private, id);
2857+ if (id < 0) {
2858+ res = -ENOENT;
2859+ goto unlock;
2860+ }
2861+ if ((*private)->childsets[id]) {
2862+ res = -EEXIST;
2863+ goto unlock;
2864+ }
2865+ set->subref++;
2866+ write_unlock_bh(&set->lock);
2867+
2868+ /* Without holding any locks, create private part. */
2869+ res = ip_set_create_private(set->type[level],
2870+ &(*private)->childsets[id],
2871+ data, size, childsets);
2872+
2873+ write_lock_bh(&set->lock);
2874+ set->subref--;
2875+ unlock:
2876+ DP("%s (%p %p) res=%i", set->name, private, *private, res);
2877+ write_unlock_bh(&set->lock);
2878+ return res;
2879+}
2880+
2881+static int
2882+ip_set_create(const char name[IP_SET_MAXNAMELEN],
2883+ char typename[IP_SET_LEVELS][IP_SET_MAXNAMELEN],
2884+ u_int8_t level,
2885+ const void *data,
2886+ size_t size)
2887+{
2888+ int i, id, res = 0;
2889+ struct ip_set *set;
2890+
2891+ DP("%s (%i): %s", typename[0], level, name);
2892+ /*
2893+ * First, and without any locks, allocate and initialize
2894+ * a normal base set structure.
2895+ */
2896+ set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
2897+ if (!set)
2898+ return -ENOMEM;
2899+ set->lock = RW_LOCK_UNLOCKED;
2900+ strncpy(set->name, name, IP_SET_MAXNAMELEN);
2901+ set->name[IP_SET_MAXNAMELEN - 1] = '\0';
2902+ set->ref = 0;
2903+ set->subref = 0;
2904+ set->levels = level;
2905+ set->private = NULL;
2906+
2907+ /*
2908+ * Next, take the &list_lock, check that we know the type,
2909+ * and take a reference on the type, to make sure it
2910+ * stays available while constructing our new set.
2911+ *
2912+ * After referencing the type, we drop the &list_lock,
2913+ * and let the new set construction run without locks.
2914+ */
2915+ write_lock_bh(&list_lock);
2916+ for (i = 0; i < level; i++) {
2917+ set->type[i] = find_set_type(typename[i]);
2918+ if (set->type[i] == NULL) {
2919+ /* FIXME: try loading the module */
2920+ write_unlock_bh(&list_lock);
2921+ ip_set_printk("no set type '%s', set '%s' not created",
2922+ typename[i], name);
2923+ kfree(set);
2924+ return -EINVAL;
2925+ }
2926+ }
2927+ for (i = 0; i < level; i++)
2928+ __MOD_INC(set->type[i]->me);
2929+ write_unlock_bh(&list_lock);
2930+
2931+ /*
2932+ * Without holding any locks, create private part.
2933+ */
2934+ res = ip_set_create_private(set->type[0],
2935+ &set->private,
2936+ data, size, level - 1);
2937+ if (res != 0) {
2938+ for (i = 0; i <= level; i++)
2939+ __MOD_DEC(set->type[i]->me);
2940+ kfree(set);
2941+ return res;
2942+ }
2943+
2944+ /* BTW, res==0 here. */
2945+
2946+ /*
2947+ * Here, we have a valid, constructed set. &list_lock again,
2948+ * and check that it is not already in ip_set_list.
2949+ */
2950+ write_lock_bh(&list_lock);
2951+ id = -1;
2952+ for (i = 0; i < max_sets; i++) {
2953+ if (ip_set_list[i] != NULL
2954+ && strncmp(ip_set_list[i]->name, set->name,
2955+ IP_SET_MAXNAMELEN - 1) == 0) {
2956+ res = -EEXIST;
2957+ goto cleanup;
2958+ } else if (id < 0 && ip_set_list[i] == NULL)
2959+ id = i;
2960+ }
2961+ if (id < 0) {
2962+ /* No free slot remained */
2963+ res = -ERANGE;
2964+ goto cleanup;
2965+ }
2966+ /*
2967+ * Finally! Append our shiny new set into the list, and be done.
2968+ */
2969+ DP("create: '%s' created with id %i!", set->name, id);
2970+ ip_set_list[id] = set;
2971+ write_unlock_bh(&list_lock);
2972+ return res;
2973+
2974+ cleanup:
2975+ write_unlock_bh(&list_lock);
2976+ ip_set_destroy_private(set, &set->private, 0);
2977+ for (i = 0; i < level; i++)
2978+ __MOD_DEC(set->type[i]->me);
2979+ kfree(set);
2980+ return res;
2981+}
2982+
2983+static int ip_set_destroy(struct ip_set *set,
2984+ ip_set_ip_t *ip,
2985+ u_int8_t level)
2986+{
2987+ struct ip_set_private **private;
2988+ int i, res = 0;
2989+
2990+ write_lock_bh(&list_lock);
2991+ /* there is no race, here. ->ref modification always happens
2992+ * under &list_lock. Fine.
2993+ */
2994+ if (level == 0) {
2995+ /* one ref from caller */
2996+ if (set->ref > 1 || set->subref) {
2997+ res = -EBUSY;
2998+ goto unlock;
2999+ }
3000+
3001+ for (i = 0; i < max_sets; i++)
3002+ if (ip_set_list[i] == set) {
3003+ ip_set_list[i] = NULL;
3004+ break;
3005+ }
3006+ write_unlock_bh(&list_lock);
3007+
3008+ ip_set_destroy_private(set, &set->private, 0);
3009+ for (i = 0; i < set->levels; i++)
3010+ __MOD_DEC(set->type[i]->me);
3011+ kfree(set);
3012+ return res;
3013+ }
3014+
3015+ private = ip_set_find_private(set, &set->private,
3016+ ip, level);
3017+
3018+ if (private && *private) {
3019+ if (set->subref) {
3020+ res = -EBUSY;
3021+ goto unlock;
3022+ }
3023+ set->subref++;
3024+ write_unlock_bh(&list_lock);
3025+
3026+ DP("%p %p", private, *private);
3027+ ip_set_destroy_private(set, private, level);
3028+ DP("%p %p", private, *private);
3029+
3030+ write_lock_bh(&list_lock);
3031+ set->subref--;
3032+ } else
3033+ res = -ENOENT;
3034+
3035+ unlock:
3036+ write_unlock_bh(&list_lock);
3037+ return res;
3038+}
3039+
3040+/*
3041+ * Find set by name, reference it once. The reference makes sure the
3042+ * thing pointed to, does not go away under our feet. Drop the reference
3043+ * later, using ip_set_put().
3044+ */
3045+struct ip_set *ip_set_get_byname(const char name[IP_SET_MAXNAMELEN],
3046+ int *id)
3047+{
3048+ struct ip_set *set = NULL;
3049+ int i;
3050+
3051+ read_lock_bh(&list_lock);
3052+ for (i = 0; i < max_sets; i++) {
3053+ set = ip_set_list[i];
3054+ if (set != NULL
3055+ && strncmp(set->name, name, IP_SET_MAXNAMELEN - 1) == 0) {
3056+ set->ref++;
3057+ *id = i;
3058+ break;
3059+ }
3060+ }
3061+ read_unlock_bh(&list_lock);
3062+ return set;
3063+}
3064+
3065+/*
3066+ * Find set by id, reference it once. The reference makes sure the
3067+ * thing pointed to, does not go away under our feet. Drop the reference
3068+ * later, using ip_set_put().
3069+ */
3070+struct ip_set *ip_set_get_byid(int id)
3071+{
3072+ struct ip_set *set;
3073+
3074+ if (id < 0 || id >= max_sets)
3075+ return NULL;
3076+
3077+ write_lock_bh(&list_lock);
3078+ set = ip_set_list[id];;
3079+ if (set)
3080+ set->ref++;
3081+ write_unlock_bh(&list_lock);
3082+ return set;
3083+}
3084+
3085+/*
3086+ * If the given set pointer points to a valid set, decrement
3087+ * reference count by 1. The caller shall not assume the pointer
3088+ * to be valid, after calling this function.
3089+ */
3090+void ip_set_put(struct ip_set *set)
3091+{
3092+ write_lock_bh(&list_lock);
3093+ if (set)
3094+ set->ref--;
3095+ write_unlock_bh(&list_lock);
3096+}
3097+
3098+static int ip_set_rename(struct ip_set *set, const char *name)
3099+{
3100+ int i, res = 0;
3101+
3102+ write_lock_bh(&list_lock);
3103+ for (i = 0; i < max_sets; i++) {
3104+ if (ip_set_list[i] != NULL
3105+ && strncmp(ip_set_list[i]->name,
3106+ name,
3107+ IP_SET_MAXNAMELEN - 1) == 0) {
3108+ res = -EEXIST;
3109+ goto unlock;
3110+ }
3111+ }
3112+ strncpy(set->name, name, IP_SET_MAXNAMELEN);
3113+ set->name[IP_SET_MAXNAMELEN - 1] = '\0';
3114+ unlock:
3115+ write_unlock_bh(&list_lock);
3116+ return res;
3117+}
3118+
3119+static int ip_set_swap(struct ip_set *from, struct ip_set *to)
3120+{
3121+ char from_name[IP_SET_MAXNAMELEN];
3122+ unsigned from_ref;
3123+ int i, res = 0;
3124+ int from_id = -1, to_id = -1;
3125+
3126+ write_lock_bh(&list_lock);
3127+ for (i = 0; i < max_sets && (from_id < 0 || to_id < 0); i++) {
3128+ if (ip_set_list[i] == from)
3129+ from_id = i;
3130+ if (ip_set_list[i] == to)
3131+ to_id = i;
3132+ }
3133+ /* We must have got both sets: we hold refcounts against them! */
3134+ if (from_id < 0 || to_id < 0) {
3135+ res = -EINVAL;
3136+ goto unlock;
3137+ }
3138+
3139+ strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
3140+ from_ref = from->ref;
3141+
3142+ ip_set_list[from_id] = to;
3143+ ip_set_list[to_id] = from;
3144+
3145+ strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
3146+ from->ref = to->ref;
3147+ strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
3148+ to->ref = from_ref;
3149+ unlock:
3150+ write_unlock_bh(&list_lock);
3151+ return res;
3152+}
3153+
3154+size_t ip_set_listing_size(void)
3155+{
3156+ size_t size = 0;
3157+ int id;
3158+
3159+ read_lock_bh(&list_lock);
3160+ for (id = 0; id < max_sets; id++) {
3161+ if (ip_set_list[id] != NULL)
3162+ size += sizeof(struct ip_set_req_listing);
3163+ }
3164+ read_unlock_bh(&list_lock);
3165+
3166+ return size;
3167+}
3168+
3169+int ip_set_listing(void *data, int *len)
3170+{
3171+ int used = 0;
3172+ int res = 0; /* All OK */
3173+ int i, id;
3174+ struct ip_set *set;
3175+ struct ip_set_req_listing *header = data;
3176+
3177+ read_lock_bh(&list_lock);
3178+ for (id = 0; id < max_sets; id++) {
3179+ if (ip_set_list[id] == NULL)
3180+ continue;
3181+
3182+ /* Pointer to our header */
3183+ header = (struct ip_set_req_listing *) (data + used);
3184+
3185+ DP("used before= %d %p %p %p", used, header, data,
3186+ data + used);
3187+
3188+ /* Get and ensure header size */
3189+ if (used + sizeof(struct ip_set_req_listing) > *len)
3190+ goto not_enough_mem;
3191+
3192+ set = ip_set_list[id];
3193+
3194+ /* Fill with data */
3195+ strncpy(header->name, set->name, IP_SET_MAXNAMELEN - 1);
3196+ for (i = 0; i < set->levels; i++)
3197+ strncpy(header->typename[i], set->type[i]->typename,
3198+ IP_SET_MAXNAMELEN - 1);
3199+ header->levels = set->levels;
3200+ header->ref = set->ref;
3201+ header->id = id;
3202+
3203+ used += sizeof(struct ip_set_req_listing);
3204+ DP("used after= %d", used);
3205+ }
3206+ *len = used; /* How much did we use? */
3207+ goto unlock_and_return;
3208+
3209+ not_enough_mem:
3210+ DP("not enough mem, try again");
3211+ res = -ENOMEM;
3212+
3213+ unlock_and_return:
3214+ read_unlock_bh(&list_lock);
3215+ return res;
3216+}
3217+
3218+int ip_set_list_size(struct ip_set * set,
3219+ ip_set_ip_t *ip,
3220+ unsigned level,
3221+ size_t *size,
3222+ unsigned op)
3223+{
3224+ int res = 0; /* OK */
3225+ struct ip_set_private **private;
3226+
3227+ DP("%d %s %d", op, set->name, level);
3228+ read_lock_bh(&set->lock);
3229+ if (set->subref) {
3230+ res = -EBUSY;
3231+ goto unlock;
3232+ }
3233+ private = ip_set_find_private(set, &set->private, ip, level);
3234+ if (!(private && *private)) {
3235+ res = -ENOENT;
3236+ goto unlock;
3237+ }
3238+ switch (op) {
3239+ case IP_SET_OP_LIST_HEADER_SIZE:
3240+ *size = set->type[level]->list_header_size(*private);
3241+ break;
3242+ case IP_SET_OP_LIST_MEMBERS_SIZE:
3243+ *size = set->type[level]->list_members_size(*private);
3244+ break;
3245+ case IP_SET_OP_LIST_CHILDSETS_SIZE:
3246+ *size = (*private)->childsets == NULL ? 0
3247+ : bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3248+ break;
3249+ default:
3250+ res = -EINVAL;
3251+ }
3252+ unlock:
3253+ read_unlock_bh(&set->lock);
3254+ DP("%d %s %d: %u", op, set->name, level, *size);
3255+
3256+ return res;
3257+}
3258+
3259+static void list_childsets(const struct ip_set_private *private,
3260+ void *data,
3261+ ip_set_ip_t sizeid)
3262+{
3263+ ip_set_ip_t id;
3264+
3265+ memset(data, 0, bitmap_bytes(0, sizeid - 1));
3266+
3267+ if (private->childsets == NULL)
3268+ return;
3269+
3270+ for (id = 0; id < sizeid; id++)
3271+ if (private->childsets[id] != NULL)
3272+ set_bit(id, data);
3273+}
3274+
3275+int ip_set_list_data(struct ip_set *set,
3276+ ip_set_ip_t *ip,
3277+ unsigned level,
3278+ void *data,
3279+ int *len,
3280+ unsigned op)
3281+{
3282+ int res = 0; /* All OK */
3283+ size_t need;
3284+ struct ip_set_private **private;
3285+ void (*datafn)(const struct ip_set_private *, void *);
3286+
3287+ read_lock_bh(&set->lock);
3288+ if (set->subref) {
3289+ res = -EBUSY;
3290+ goto unlock;
3291+ }
3292+ private = ip_set_find_private(set, &set->private, ip, level);
3293+ if (!(private && *private)) {
3294+ res = -ENOENT;
3295+ goto unlock;
3296+ }
3297+ switch (op) {
3298+ case IP_SET_OP_LIST_HEADER:
3299+ need = set->type[level]->list_header_size(*private);
3300+ datafn = set->type[level]->list_header;
3301+ break;
3302+ case IP_SET_OP_LIST_MEMBERS:
3303+ need = set->type[level]->list_members_size(*private);
3304+ datafn = set->type[level]->list_members;
3305+ break;
3306+ case IP_SET_OP_LIST_CHILDSETS:
3307+ if ((*private)->childsets == NULL) {
3308+ res = -ENOENT;
3309+ goto unlock;
3310+ }
3311+ need = bitmap_bytes(0, set->type[level]->sizeid(*private) - 1);
3312+ datafn = NULL;
3313+ break;
3314+ default:
3315+ res = -EINVAL;
3316+ goto unlock;
3317+ }
3318+ if (need > *len) {
3319+ res = -ENOMEM;
3320+ goto unlock;
3321+ }
3322+ *len = need;
3323+ if (datafn)
3324+ datafn(*private, data);
3325+ else
3326+ list_childsets(*private, data, set->type[level]->sizeid(*private));
3327+
3328+ unlock:
3329+ read_unlock_bh(&set->lock);
3330+ return res;
3331+}
3332+
3333+static int
3334+ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
3335+{
3336+ void *data;
3337+ int res = 0; /* Assume OK */
3338+ struct ip_set_req_base *req_base;
3339+ struct ip_set_req_std *req_std;
3340+ struct ip_set *set = NULL;
3341+
3342+ DP("optval=%d, user=%p, len=%d", optval, user, len);
3343+ if (!capable(CAP_NET_ADMIN))
3344+ return -EPERM;
3345+ if (optval != SO_IP_SET)
3346+ return -EBADF;
3347+ if (len < sizeof(struct ip_set_req_base)) {
3348+ ip_set_printk("short userdata (want >=%d, got %d)",
3349+ sizeof(struct ip_set_req_base), len);
3350+ return -EINVAL;
3351+ }
3352+ data = vmalloc(len);
3353+ if (!data) {
3354+ DP("out of mem for %d bytes", len);
3355+ return -ENOMEM;
3356+ }
3357+ if (copy_from_user(data, user, len) != 0) {
3358+ res = -EFAULT;
3359+ goto done;
3360+ }
3361+
3362+ req_base = (struct ip_set_req_base *) data;
3363+
3364+ DP("op=%x id='%x'", req_base->op, req_base->id);
3365+
3366+ /* Handle set creation first - no incoming set specified */
3367+
3368+ if (req_base->op == IP_SET_OP_CREATE) {
3369+ struct ip_set_req_create *req_create
3370+ = (struct ip_set_req_create *) data;
3371+ int i;
3372+
3373+ if (len < sizeof(struct ip_set_req_create)) {
3374+ ip_set_printk("short CREATE data (want >%d, got %d)",
3375+ sizeof(struct ip_set_req_create), len);
3376+ res = -EINVAL;
3377+ goto done;
3378+ }
3379+ if (req_create->levels > IP_SET_LEVELS) {
3380+ ip_set_printk("set level %d too deep (max %d)",
3381+ req_create->levels, IP_SET_LEVELS);
3382+ res = -EINVAL;
3383+ goto done;
3384+ }
3385+ req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
3386+ for (i = 0; i < req_create->levels; i++)
3387+ req_create->typename[i][IP_SET_MAXNAMELEN - 1] = '\0';
3388+ res = ip_set_create(req_create->name,
3389+ req_create->typename,
3390+ req_create->levels,
3391+ data + sizeof(struct ip_set_req_create),
3392+ len - sizeof(struct ip_set_req_create));
3393+ goto done;
3394+ }
3395+
3396+ /* All remaining requests want a set by id.
3397+ * We take a proper reference here, and drop it after processing.
3398+ * From hereon, code goes to '*put_set', not to 'done'.
3399+ */
3400+
3401+ set = ip_set_get_byid(req_base->id);
3402+ if (set == NULL) {
3403+ res = -ESRCH;
3404+ goto done;
3405+ }
3406+
3407+ DP("set %s (%d) (%u)", set->name, req_base->id, set->ref);
3408+ /* Simple requests: no subsets */
3409+ switch (req_base->op) {
3410+ case IP_SET_OP_RENAME:{
3411+ struct ip_set_req_rename *req_rename
3412+ = (struct ip_set_req_rename *) data;
3413+
3414+ if (len != sizeof(struct ip_set_req_rename)) {
3415+ ip_set_printk("short RENAME data (want >%d, got %d)",
3416+ sizeof(struct ip_set_req_rename), len);
3417+ res = -EINVAL;
3418+ goto put_set;
3419+ }
3420+
3421+ res = ip_set_rename(set, req_rename->newname);
3422+ goto put_set;
3423+ }
3424+
3425+ case IP_SET_OP_SWAP:{
3426+ struct ip_set_req_swap *req_swap
3427+ = (struct ip_set_req_swap *) data;
3428+ struct ip_set *to;
3429+
3430+ if (len != sizeof(struct ip_set_req_swap)) {
3431+
3432+ ip_set_printk("short SWAP data (want >%d, got %d)",
3433+ sizeof(struct ip_set_req_swap), len);
3434+ res = -EINVAL;
3435+ goto put_set;
3436+ }
3437+
3438+ to = ip_set_get_byid(req_swap->to);
3439+ if (to == NULL) {
3440+ res = -ESRCH;
3441+ goto put_set;
3442+ }
3443+ res = ip_set_swap(set, to);
3444+ ip_set_put(to);
3445+ goto put_set;
3446+ }
3447+ default:
3448+ ; /* Requests with possible subsets: fall trough. */
3449+ }
3450+
3451+ req_std = (struct ip_set_req_std *) data;
3452+ if (len < sizeof(struct ip_set_req_std)) {
3453+ ip_set_printk("short data in std request (want >%d, got %d)",
3454+ sizeof(struct ip_set_req_std), len);
3455+ res = -EINVAL;
3456+ goto put_set;
3457+ } else if (req_std->level >= set->levels) {
3458+ res = -EINVAL;
3459+ goto put_set;
3460+ }
3461+
3462+ switch (req_base->op) {
3463+ case IP_SET_OP_ADD_IP:{
3464+ res = ip_set_addip(set,
3465+ req_std->ip, req_std->level,
3466+ data + sizeof(struct ip_set_req_std),
3467+ len - sizeof(struct ip_set_req_std));
3468+ goto put_set;
3469+ }
3470+ case IP_SET_OP_DEL_IP:{
3471+ res = ip_set_delip(set,
3472+ req_std->ip, req_std->level,
3473+ data + sizeof(struct ip_set_req_std),
3474+ len - sizeof(struct ip_set_req_std));
3475+ goto put_set;
3476+ }
3477+ case IP_SET_OP_DESTROY:{
3478+ res = ip_set_destroy(set, req_std->ip, req_std->level);
3479+ if (req_std->level == 0 && res == 0)
3480+ goto done; /* destroyed: no ip_set_put */
3481+ goto put_set;
3482+ }
3483+ case IP_SET_OP_FLUSH:{
3484+ struct ip_set_req_sub *req_sub =
3485+ (struct ip_set_req_sub *) data;
3486+
3487+ if (len < sizeof(struct ip_set_req_sub)) {
3488+ ip_set_printk("short data in flush request (want >%d, got %d)",
3489+ sizeof(struct ip_set_req_sub), len);
3490+ res = -EINVAL;
3491+ goto put_set;
3492+ }
3493+ res = ip_set_flush(set, req_sub->ip, req_sub->level, req_sub->childsets);
3494+ goto put_set;
3495+ }
3496+ case IP_SET_OP_CREATE_CHILD:{
3497+ struct ip_set_req_sub *req_sub
3498+ = (struct ip_set_req_sub *) data;
3499+
3500+ if (len < sizeof(struct ip_set_req_sub)) {
3501+ ip_set_printk("short CREATE_CHILD data (want >%d, got %d)",
3502+ sizeof(struct ip_set_req_sub), len);
3503+ res = -EINVAL;
3504+ goto put_set;
3505+ }
3506+ if (req_sub->level < 1) {
3507+ /* No entry supplied? */
3508+ res = -EINVAL;
3509+ goto put_set;
3510+ }
3511+ if (((req_sub->level >= set->levels - 1) && req_sub->childsets)) {
3512+ /* No room for subsets to be created. */
3513+ res = -ERANGE;
3514+ goto put_set;
3515+ }
3516+ res = ip_set_create_childset(set,
3517+ req_sub->ip,
3518+ req_sub->level,
3519+ req_sub->childsets,
3520+ data + sizeof(struct ip_set_req_sub),
3521+ len - sizeof(struct ip_set_req_sub));
3522+ goto put_set;
3523+ }
3524+ default:{
3525+ DP("unknown op %d", req_base->op);
3526+ ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3527+ res = -EINVAL;
3528+ }
3529+ } /* end of switch(op) */
3530+
3531+ put_set:
3532+ if (set)
3533+ ip_set_put(set);
3534+ done:
3535+ vfree(data);
3536+ if (res > 0)
3537+ res = 0;
3538+ return res;
3539+}
3540+
3541+static int
3542+ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
3543+{
3544+ int res = 0;
3545+ struct ip_set_req_base *req_base;
3546+ struct ip_set_req_std *req_std;
3547+ struct ip_set *set = NULL;
3548+ void *data;
3549+ int copylen = *len;
3550+
3551+ DP("optval=%d, user=%p, len=%d", optval, user, *len);
3552+ if (!capable(CAP_NET_ADMIN))
3553+ return -EPERM;
3554+ if (optval != SO_IP_SET)
3555+ return -EBADF;
3556+ if (*len < sizeof(struct ip_set_req_base)) {
3557+ ip_set_printk("short userdata (want >=%d, got %d)",
3558+ sizeof(struct ip_set_req_base), *len);
3559+ return -EINVAL;
3560+ }
3561+ data = vmalloc(*len);
3562+ if (!data) {
3563+ DP("out of mem for %d bytes", *len);
3564+ return -ENOMEM;
3565+ }
3566+ if (copy_from_user(data, user, *len) != 0) {
3567+ res = -EFAULT;
3568+ goto done;
3569+ }
3570+
3571+ req_base = (struct ip_set_req_base *) data;
3572+
3573+ DP("op=%x id='%x'", req_base->op, req_base->id);
3574+
3575+ /* Requests without a named set. */
3576+ switch (req_base->op) {
3577+ case IP_SET_OP_VERSION:{
3578+ struct ip_set_req_version *req_version =
3579+ (struct ip_set_req_version *) data;
3580+
3581+ if (*len != sizeof(struct ip_set_req_version)) {
3582+ ip_set_printk("short VERSION (want >=%d, got %d)",
3583+ sizeof(struct ip_set_req_version),
3584+ *len);
3585+ res = -EINVAL;
3586+ goto done;
3587+ }
3588+
3589+ req_version->version = IP_SET_PROTOCOL_VERSION;
3590+ res = copy_to_user(user, req_version,
3591+ sizeof(struct ip_set_req_version));
3592+ goto done;
3593+ }
3594+ case IP_SET_OP_LISTING_SIZE:{
3595+ struct ip_set_req_listing_size *req_list =
3596+ (struct ip_set_req_listing_size *) data;
3597+
3598+ DP("IP_SET_OP_LISTING_SIZE");
3599+
3600+ if (*len != sizeof(struct ip_set_req_listing_size)) {
3601+ ip_set_printk("short LISTING_SIZE (want >=%d, got %d)",
3602+ sizeof(struct ip_set_req_listing_size),
3603+ *len);
3604+ res = -EINVAL;
3605+ goto done;
3606+ }
3607+
3608+ req_list->size = ip_set_listing_size();
3609+ DP("req_list->size = %d", req_list->size);
3610+ res = copy_to_user(user, req_list,
3611+ sizeof(struct ip_set_req_listing_size));
3612+ goto done;
3613+ }
3614+ case IP_SET_OP_LISTING:{
3615+ DP("LISTING before len=%d", *len);
3616+ res = ip_set_listing(data, len);
3617+ DP("LISTING done len=%d", *len);
3618+ if (res < 0)
3619+ goto done; /* Error */
3620+
3621+ res = copy_to_user(user, data, *len); /* Only copy the mem used */
3622+ goto done;
3623+ }
3624+ default:
3625+ ; /* Requests with named set: fall trought */
3626+ }
3627+
3628+ /* Special cases: GETSET_BYNAME/BYID */
3629+ switch (req_base->op) {
3630+ case IP_SET_OP_GETSET_BYNAME: {
3631+ struct ip_set_req_get *req_get
3632+ = (struct ip_set_req_get *) data;
3633+
3634+ if (*len != sizeof(struct ip_set_req_get)) {
3635+ ip_set_printk("short _BYNAME (want >=%d, got %d)",
3636+ sizeof(struct ip_set_req_get), *len);
3637+ res = -EINVAL;
3638+ goto done;
3639+ }
3640+ req_get->name[IP_SET_MAXNAMELEN - 1] = '\0';
3641+ req_get->id = -1;
3642+ set = ip_set_get_byname(req_get->name, &req_get->id);
3643+ if (set) {
3644+ req_get->ref = set->ref - 1;
3645+ ip_set_put(set);
3646+ }
3647+ res = copy_to_user(user, data, copylen);
3648+ goto done;
3649+ }
3650+ case IP_SET_OP_GETSET_BYID: {
3651+ struct ip_set_req_get *req_get
3652+ = (struct ip_set_req_get *) data;
3653+
3654+ if (*len != sizeof(struct ip_set_req_get)) {
3655+ ip_set_printk("short _BYID (want >=%d, got %d)",
3656+ sizeof(struct ip_set_req_get), *len);
3657+ res = -EINVAL;
3658+ goto done;
3659+ }
3660+ set = ip_set_get_byid(req_get->id);
3661+ if (set) {
3662+ req_get->ref = set->ref - 1;
3663+ strncpy(req_get->name, set->name, IP_SET_MAXNAMELEN);
3664+ ip_set_put(set);
3665+ } else
3666+ req_get->id = -1;
3667+ res = copy_to_user(user, data, copylen);
3668+ goto done;
3669+ }
3670+ default:
3671+ ; /* Requests with set id: fall trought */
3672+ }
3673+
3674+ /* Requests with set id: */
3675+ if (req_base->id < 0 || req_base->id >= max_sets) {
3676+ res = -EINVAL;
3677+ goto done;
3678+ }
3679+ set = ip_set_get_byid(req_base->id); /* Reference lock */
3680+ if (!set) {
3681+ res = -ENOENT;
3682+ goto done;
3683+ }
3684+
3685+ DP("set %s (%d) (%u)", set->name, req_base->id, set->ref);
3686+ req_std = (struct ip_set_req_std *) data;
3687+ if (*len < sizeof(struct ip_set_req_std)) {
3688+ ip_set_printk("short data in std request (want >%d, got %d)",
3689+ sizeof(struct ip_set_req_std), *len);
3690+ goto put_inval;
3691+ } else if (req_std->level >= set->levels) {
3692+ res = -ERANGE;
3693+ goto put_set;
3694+ }
3695+
3696+ switch (req_base->op) {
3697+ case IP_SET_OP_TEST_IP:{
3698+ struct ip_set_req_test *req_test =
3699+ (struct ip_set_req_test *) data;
3700+
3701+ if (*len < sizeof(struct ip_set_req_test)) {
3702+ ip_set_printk("short data in testip request (want >%d, got %d)",
3703+ sizeof(struct ip_set_req_test), *len);
3704+ res = -EINVAL;
3705+ goto put_set;
3706+ }
3707+ req_test->reply = ip_set_testip(set,
3708+ req_test->ip,
3709+ req_test->level,
3710+ data + sizeof(struct ip_set_req_test),
3711+ *len - sizeof(struct ip_set_req_test));
3712+
3713+ DP("test result: %i", req_test->reply);
3714+ *len = copylen = sizeof(struct ip_set_req_test);
3715+ goto put_copy;
3716+ }
3717+ case IP_SET_OP_LIST_HEADER_SIZE:
3718+ case IP_SET_OP_LIST_MEMBERS_SIZE:
3719+ case IP_SET_OP_LIST_CHILDSETS_SIZE: {
3720+ struct ip_set_req_list *req_list =
3721+ (struct ip_set_req_list *) data;
3722+
3723+ if (*len != sizeof(struct ip_set_req_list)) {
3724+ ip_set_printk("short LIST (want >=%d, got %d)",
3725+ sizeof(struct ip_set_req_list),
3726+ *len);
3727+ goto put_inval;
3728+ }
3729+ res = ip_set_list_size(set,
3730+ req_list->ip,
3731+ req_list->level,
3732+ &req_list->size,
3733+ req_base->op);
3734+ DP("SIZEfoo size=%d", req_list->size);
3735+ if (res < 0)
3736+ goto put_set; /* Error */
3737+ goto put_copy;
3738+ }
3739+ case IP_SET_OP_LIST_HEADER:
3740+ case IP_SET_OP_LIST_MEMBERS:
3741+ case IP_SET_OP_LIST_CHILDSETS:{
3742+ DP("LISTfoo before len=%d", *len);
3743+ res = ip_set_list_data(set,
3744+ req_std->ip,
3745+ req_std->level,
3746+ data,
3747+ len,
3748+ req_base->op);
3749+ DP("LISTfoo done len=%d", *len);
3750+
3751+ if (res < 0)
3752+ goto put_set; /* Error */
3753+
3754+ copylen = *len; /* Only copy the mem used */
3755+ goto put_copy;
3756+ }
3757+ default:{
3758+ DP("unknown op %d", req_base->op);
3759+ ip_set_printk("obsolete - upgrade your ipset(8) utility.");
3760+ goto put_inval;
3761+ }
3762+ } /* end of switch(op) */
3763+
3764+ put_copy:
3765+ ip_set_put(set);
3766+ DP("set %s (%u)", set->name, set->ref);
3767+ res = copy_to_user(user, data, copylen);
3768+ goto done;
3769+ put_inval:
3770+ res = -EINVAL;
3771+ put_set:
3772+ ip_set_put(set);
3773+ DP("set %s (%u)", set->name, set->ref);
3774+ done:
3775+ vfree(data);
3776+ if (res > 0)
3777+ res = 0;
3778+ DP("final result %d", res);
3779+ return res;
3780+}
3781+
3782+static struct nf_sockopt_ops so_set = {
3783+ .pf = PF_INET,
3784+ .set_optmin = SO_IP_SET,
3785+ .set_optmax = SO_IP_SET + 1,
3786+ .set = &ip_set_sockfn_set,
3787+ .get_optmin = SO_IP_SET,
3788+ .get_optmax = SO_IP_SET + 1,
3789+ .get = &ip_set_sockfn_get,
3790+ .use = 0
3791+};
3792+
3793+MODULE_PARM(max_sets, "i");
3794+MODULE_PARM_DESC(max_sets, "maximal number of sets");
3795+
3796+static int __init init(void)
3797+{
3798+ int res;
3799+
3800+ if (max_sets <= 0)
3801+ max_sets = CONFIG_IP_NF_SET_MAX;
3802+ ip_set_list = vmalloc(sizeof(struct ip_set *) * max_sets);
3803+ if (!ip_set_list) {
3804+ printk(KERN_ERR "Unable to create ip_set_list\n");
3805+ return -ENOMEM;
3806+ }
3807+ memset(ip_set_list, 0, sizeof(struct ip_set *) * max_sets);
3808+ INIT_LIST_HEAD(&set_type_list);
3809+
3810+ res = nf_register_sockopt(&so_set);
3811+ if (res != 0) {
3812+ ip_set_printk("SO_SET registry failed: %d", res);
3813+ vfree(ip_set_list);
3814+ return res;
3815+ }
3816+ return 0;
3817+}
3818+
3819+static void __exit fini(void)
3820+{
3821+ nf_unregister_sockopt(&so_set);
3822+ vfree(ip_set_list);
3823+ DP("these are the famous last words");
3824+}
3825+
3826+EXPORT_SYMBOL(ip_set_register_set_type);
3827+EXPORT_SYMBOL(ip_set_unregister_set_type);
3828+
3829+EXPORT_SYMBOL(ip_set_list);
3830+EXPORT_SYMBOL(ip_set_get_byname);
3831+EXPORT_SYMBOL(ip_set_get_byid);
3832+EXPORT_SYMBOL(ip_set_put);
3833+
3834+EXPORT_SYMBOL(ip_set_addip_kernel);
3835+EXPORT_SYMBOL(ip_set_delip_kernel);
3836+EXPORT_SYMBOL(ip_set_testip_kernel);
3837+
3838+module_init(init);
3839+module_exit(fini);
3840+MODULE_LICENSE("GPL");
3841diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_iphash.c linux-2.6.3/net/ipv4/netfilter/ip_set_iphash.c
3842--- linux-2.6.3.org/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
3843+++ linux-2.6.3/net/ipv4/netfilter/ip_set_iphash.c 2004-02-09 15:02:00.000000000 +0100
3844@@ -0,0 +1,319 @@
3845+/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
3846+ *
3847+ * This program is free software; you can redistribute it and/or modify
3848+ * it under the terms of the GNU General Public License as published by
3849+ * the Free Software Foundation; either version 2 of the License, or
3850+ * (at your option) any later version.
3851+ *
3852+ * This program is distributed in the hope that it will be useful,
3853+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3854+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3855+ * GNU General Public License for more details.
3856+ *
3857+ * You should have received a copy of the GNU General Public License
3858+ * along with this program; if not, write to the Free Software
3859+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3860+ */
3861+
3862+/* Kernel module implementing an ip hash set */
3863+
3864+#include <linux/module.h>
3865+#include <linux/ip.h>
3866+#include <linux/skbuff.h>
3867+#include <linux/netfilter_ipv4/ip_tables.h>
3868+#include <linux/netfilter_ipv4/ip_set.h>
3869+#include <linux/errno.h>
3870+#include <asm/uaccess.h>
3871+#include <asm/bitops.h>
3872+#include <asm/softirq.h>
3873+#include <linux/spinlock.h>
3874+#include <linux/vmalloc.h>
3875+
3876+#include <net/ip.h>
3877+
3878+#include <linux/netfilter_ipv4/ip_set_iphash.h>
3879+#include <linux/netfilter_ipv4/ip_set_jhash.h>
3880+
3881+static inline ip_set_ip_t
3882+hash_ip(const struct ip_set_iphash *map, ip_set_ip_t ip)
3883+{
3884+ return (jhash_1word(ip & map->netmask, map->initval) % map->hashsize);
3885+}
3886+
3887+static inline int
3888+__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3889+{
3890+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3891+
3892+ *id = hash_ip(map, ip);
3893+ return (map->members[*id] == ip);
3894+}
3895+
3896+static int
3897+matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3898+{
3899+ return __testip(private, ip, id);
3900+}
3901+
3902+static int
3903+testip(struct ip_set_private *private, const void *data, size_t size,
3904+ ip_set_ip_t *id)
3905+{
3906+ struct ip_set_req_iphash *req =
3907+ (struct ip_set_req_iphash *) data;
3908+
3909+ if (size != sizeof(struct ip_set_req_iphash)) {
3910+ ip_set_printk("data length wrong (want %d, have %d)",
3911+ sizeof(struct ip_set_req_iphash),
3912+ size);
3913+ return -EINVAL;
3914+ }
3915+ return __testip(private, req->ip, id);
3916+}
3917+
3918+static int
3919+testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3920+ u_int32_t flags, ip_set_ip_t *id)
3921+{
3922+ if (!(flags & IPSET_TYPE_IP))
3923+ return -EINVAL;
3924+
3925+ return __testip(private,
3926+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
3927+ : skb->nh.iph->daddr),
3928+ id);
3929+}
3930+
3931+static inline int
3932+__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id,
3933+ u_int32_t flags)
3934+{
3935+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3936+
3937+ *id = hash_ip(map, ip);
3938+
3939+ if (map->members[*id] == ip)
3940+ return -EEXIST;
3941+
3942+ if (map->members[*id] != 0 && !(flags & IPSET_ADD_OVERWRITE))
3943+ return -EADDRINUSE;
3944+
3945+ map->members[*id] = ip;
3946+ return 0;
3947+}
3948+
3949+static int
3950+addip(struct ip_set_private *private, const void *data, size_t size,
3951+ ip_set_ip_t *id)
3952+{
3953+ struct ip_set_req_iphash *req =
3954+ (struct ip_set_req_iphash *) data;
3955+
3956+ if (size != sizeof(struct ip_set_req_iphash)) {
3957+ ip_set_printk("data length wrong (want %d, have %d)",
3958+ sizeof(struct ip_set_req_iphash),
3959+ size);
3960+ return -EINVAL;
3961+ }
3962+ return __addip(private, req->ip, id, req->flags);
3963+}
3964+
3965+static int
3966+addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
3967+ u_int32_t flags, ip_set_ip_t *id)
3968+{
3969+ if (!(flags & IPSET_TYPE_IP))
3970+ return -EINVAL;
3971+
3972+ return __addip(private,
3973+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
3974+ : skb->nh.iph->daddr),
3975+ id,
3976+ flags);
3977+}
3978+
3979+static inline int
3980+__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
3981+{
3982+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
3983+
3984+ *id = hash_ip(map, ip);
3985+
3986+ if (map->members[*id] == 0)
3987+ return -EEXIST;
3988+
3989+ if (map->members[*id] != ip)
3990+ return -EADDRINUSE;
3991+
3992+ map->members[*id] = 0;
3993+ return 0;
3994+}
3995+
3996+static int
3997+delip(struct ip_set_private *private, const void *data, size_t size,
3998+ ip_set_ip_t *id)
3999+{
4000+ struct ip_set_req_iphash *req =
4001+ (struct ip_set_req_iphash *) data;
4002+
4003+ if (size != sizeof(struct ip_set_req_iphash)) {
4004+ ip_set_printk("data length wrong (want %d, have %d)",
4005+ sizeof(struct ip_set_req_iphash),
4006+ size);
4007+ return -EINVAL;
4008+ }
4009+ return __delip(private, req->ip, id);
4010+}
4011+
4012+static int
4013+delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4014+ u_int32_t flags, ip_set_ip_t *id)
4015+{
4016+ if (!(flags & IPSET_TYPE_IP))
4017+ return -EINVAL;
4018+
4019+ return __delip(private,
4020+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4021+ : skb->nh.iph->daddr),
4022+ id);
4023+}
4024+
4025+static int create(struct ip_set_private **private, const void *data, size_t size)
4026+{
4027+ int newbytes;
4028+ struct ip_set_req_iphash_create *req =
4029+ (struct ip_set_req_iphash_create *) data;
4030+ struct ip_set_iphash *map;
4031+
4032+ if (size != sizeof(struct ip_set_req_iphash_create)) {
4033+ ip_set_printk("data length wrong (want %d, have %d)",
4034+ sizeof(struct ip_set_req_iphash_create),
4035+ size);
4036+ return -EINVAL;
4037+ }
4038+
4039+ if (req->hashsize > MAX_RANGE) {
4040+ ip_set_printk("hashsize too big (max %d)",
4041+ MAX_RANGE);
4042+ return -ERANGE;
4043+ }
4044+
4045+ if (req->hashsize < 1) {
4046+ ip_set_printk("hashsize too small");
4047+ return -ERANGE;
4048+ }
4049+
4050+ map = kmalloc(sizeof(struct ip_set_iphash), GFP_KERNEL);
4051+ if (!map) {
4052+ DP("out of memory for %d bytes",
4053+ sizeof(struct ip_set_iphash));
4054+ return -ENOMEM;
4055+ }
4056+ map->initval = req->initval;
4057+ map->hashsize = req->hashsize;
4058+ map->netmask = req->netmask;
4059+ newbytes = map->hashsize * sizeof(ip_set_ip_t);
4060+ map->members = vmalloc(newbytes);
4061+ if (!map->members) {
4062+ DP("out of memory for %d bytes", newbytes);
4063+ kfree(map);
4064+ return -ENOMEM;
4065+ }
4066+ memset(map->members, 0, newbytes);
4067+
4068+ *private = (struct ip_set_private *) map;
4069+ return 0;
4070+}
4071+
4072+static void destroy(struct ip_set_private **private)
4073+{
4074+ struct ip_set_iphash *map = (struct ip_set_iphash *) *private;
4075+
4076+ vfree(map->members);
4077+ kfree(map);
4078+
4079+ *private = NULL;
4080+}
4081+
4082+static void flush(struct ip_set_private *private)
4083+{
4084+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4085+ memset(map->members, 0, map->hashsize * sizeof(ip_set_ip_t));
4086+}
4087+
4088+static int list_header_size(const struct ip_set_private *private)
4089+{
4090+ return sizeof(struct ip_set_req_iphash_create);
4091+}
4092+
4093+static void list_header(const struct ip_set_private *private, void *data)
4094+{
4095+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4096+ struct ip_set_req_iphash_create *header =
4097+ (struct ip_set_req_iphash_create *) data;
4098+
4099+ header->initval = map->initval;
4100+ header->hashsize = map->hashsize;
4101+ header->netmask = map->netmask;
4102+}
4103+
4104+static int list_members_size(const struct ip_set_private *private)
4105+{
4106+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4107+
4108+ return (map->hashsize * sizeof(ip_set_ip_t));
4109+}
4110+
4111+static void list_members(const struct ip_set_private *private, void *data)
4112+{
4113+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4114+
4115+ int bytes = map->hashsize * sizeof(ip_set_ip_t);
4116+
4117+ memcpy(data, map->members, bytes);
4118+}
4119+
4120+static ip_set_ip_t sizeid(const struct ip_set_private *private)
4121+{
4122+ struct ip_set_iphash *map = (struct ip_set_iphash *) private;
4123+
4124+ return (map->hashsize);
4125+}
4126+
4127+static struct ip_set_type ip_set_iphash = {
4128+ .typename = SETTYPE_NAME,
4129+ .typecode = IPSET_TYPE_IP,
4130+ .protocol_version = IP_SET_PROTOCOL_VERSION,
4131+ .create = &create,
4132+ .destroy = &destroy,
4133+ .flush = &flush,
4134+ .reqsize = sizeof(struct ip_set_req_iphash),
4135+ .addip = &addip,
4136+ .addip_kernel = &addip_kernel,
4137+ .delip = &delip,
4138+ .delip_kernel = &delip_kernel,
4139+ .matchip = &matchip,
4140+ .testip = &testip,
4141+ .testip_kernel = &testip_kernel,
4142+ .list_header_size = &list_header_size,
4143+ .list_header = &list_header,
4144+ .list_members_size = &list_members_size,
4145+ .list_members = &list_members,
4146+ .sizeid = &sizeid,
4147+ .me = THIS_MODULE,
4148+};
4149+
4150+static int __init init(void)
4151+{
4152+ return ip_set_register_set_type(&ip_set_iphash);
4153+}
4154+
4155+static void __exit fini(void)
4156+{
4157+ /* FIXME: possible race with ip_set_create() */
4158+ ip_set_unregister_set_type(&ip_set_iphash);
4159+}
4160+
4161+module_init(init);
4162+module_exit(fini);
4163+MODULE_LICENSE("GPL");
4164diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_ipmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_ipmap.c
4165--- linux-2.6.3.org/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
4166+++ linux-2.6.3/net/ipv4/netfilter/ip_set_ipmap.c 2004-02-09 15:02:00.000000000 +0100
4167@@ -0,0 +1,348 @@
4168+/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4169+ * Patrick Schaaf (bof@bof.de)
4170+ * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4171+ *
4172+ * This program is free software; you can redistribute it and/or modify
4173+ * it under the terms of the GNU General Public License as published by
4174+ * the Free Software Foundation; either version 2 of the License, or
4175+ * (at your option) any later version.
4176+ *
4177+ * This program is distributed in the hope that it will be useful,
4178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4180+ * GNU General Public License for more details.
4181+ *
4182+ * You should have received a copy of the GNU General Public License
4183+ * along with this program; if not, write to the Free Software
4184+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4185+ */
4186+
4187+/* Kernel module implementing an IP set type: the single bitmap type */
4188+
4189+#include <linux/module.h>
4190+#include <linux/ip.h>
4191+#include <linux/skbuff.h>
4192+#include <linux/netfilter_ipv4/ip_tables.h>
4193+#include <linux/netfilter_ipv4/ip_set.h>
4194+#include <linux/errno.h>
4195+#include <asm/uaccess.h>
4196+#include <asm/bitops.h>
4197+#include <asm/softirq.h>
4198+#include <linux/spinlock.h>
4199+
4200+#include <linux/netfilter_ipv4/ip_set_ipmap.h>
4201+
4202+static inline ip_set_ip_t
4203+ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
4204+{
4205+ return ((ip & map->netmask) - map->first_ip)/map->hosts;
4206+}
4207+
4208+static inline int
4209+__testip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4210+{
4211+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4212+
4213+ if (ip < map->first_ip || ip > map->last_ip)
4214+ return -ERANGE;
4215+
4216+ *id = ip_to_id(map, ip);
4217+ return !!test_bit(*id, map->members);
4218+}
4219+
4220+static int
4221+matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4222+{
4223+ return __testip(private, ip, id);
4224+}
4225+
4226+static int
4227+testip(struct ip_set_private *private, const void *data, size_t size,
4228+ ip_set_ip_t *id)
4229+{
4230+ struct ip_set_req_ipmap *req =
4231+ (struct ip_set_req_ipmap *) data;
4232+
4233+ if (size != sizeof(struct ip_set_req_ipmap)) {
4234+ ip_set_printk("data length wrong (want %d, have %d)",
4235+ sizeof(struct ip_set_req_ipmap),
4236+ size);
4237+ return -EINVAL;
4238+ }
4239+ return __testip(private, req->ip, id);
4240+}
4241+
4242+static int
4243+testip_kernel(struct ip_set_private *private,
4244+ const struct sk_buff *skb,
4245+ u_int32_t flags,
4246+ ip_set_ip_t *id)
4247+{
4248+ if (!(flags & IPSET_TYPE_IP))
4249+ return -EINVAL;
4250+
4251+ DP("flags: %u (%s) ip %u.%u.%u.%u", flags,
4252+ flags & IPSET_SRC ? "SRC" : "DST",
4253+ NIPQUAD(skb->nh.iph->saddr));
4254+ DP("flags: %u (%s) ip %u.%u.%u.%u", flags,
4255+ flags & IPSET_SRC ? "SRC" : "DST",
4256+ NIPQUAD(skb->nh.iph->daddr));
4257+
4258+ return __testip(private,
4259+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4260+ : skb->nh.iph->daddr),
4261+ id);
4262+}
4263+
4264+static inline int
4265+__addip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4266+{
4267+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4268+
4269+ if (ip < map->first_ip || ip > map->last_ip)
4270+ return -ERANGE;
4271+
4272+ *id = ip_to_id(map, ip);
4273+ if (test_and_set_bit(*id, map->members))
4274+ return -EEXIST;
4275+
4276+ return 0;
4277+}
4278+
4279+static int
4280+addip(struct ip_set_private *private, const void *data, size_t size,
4281+ ip_set_ip_t *id)
4282+{
4283+ struct ip_set_req_ipmap *req =
4284+ (struct ip_set_req_ipmap *) data;
4285+
4286+ if (size != sizeof(struct ip_set_req_ipmap)) {
4287+ ip_set_printk("data length wrong (want %d, have %d)",
4288+ sizeof(struct ip_set_req_ipmap),
4289+ size);
4290+ return -EINVAL;
4291+ }
4292+ DP("%u.%u.%u.%u", NIPQUAD(req->ip));
4293+ return __addip(private, req->ip, id);
4294+}
4295+
4296+static int
4297+addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4298+ u_int32_t flags, ip_set_ip_t *id)
4299+{
4300+ if (!(flags & IPSET_TYPE_IP))
4301+ return -EINVAL;
4302+
4303+ return __addip(private,
4304+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4305+ : skb->nh.iph->daddr),
4306+ id);
4307+}
4308+
4309+static inline int
4310+__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4311+{
4312+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4313+
4314+ if (ip < map->first_ip || ip > map->last_ip)
4315+ return -ERANGE;
4316+
4317+ *id = ip_to_id(map, ip);
4318+ if (!test_and_clear_bit(*id, map->members))
4319+ return -EEXIST;
4320+
4321+ return 0;
4322+}
4323+
4324+static int
4325+delip(struct ip_set_private *private, const void *data, size_t size,
4326+ ip_set_ip_t *id)
4327+{
4328+ struct ip_set_req_ipmap *req =
4329+ (struct ip_set_req_ipmap *) data;
4330+
4331+ if (size != sizeof(struct ip_set_req_ipmap)) {
4332+ ip_set_printk("data length wrong (want %d, have %d)",
4333+ sizeof(struct ip_set_req_ipmap),
4334+ size);
4335+ return -EINVAL;
4336+ }
4337+ return __delip(private, req->ip, id);
4338+}
4339+
4340+static int
4341+delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4342+ u_int32_t flags, ip_set_ip_t *id)
4343+{
4344+ if (!(flags & IPSET_TYPE_IP))
4345+ return -EINVAL;
4346+
4347+ return __delip(private,
4348+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4349+ : skb->nh.iph->daddr),
4350+ id);
4351+}
4352+
4353+static int create(struct ip_set_private **private, const void *data, size_t size)
4354+{
4355+ int newbytes;
4356+ struct ip_set_req_ipmap_create *req =
4357+ (struct ip_set_req_ipmap_create *) data;
4358+ struct ip_set_ipmap *map;
4359+
4360+ if (size != sizeof(struct ip_set_req_ipmap_create)) {
4361+ ip_set_printk("data length wrong (want %d, have %d)",
4362+ sizeof(struct ip_set_req_ipmap_create),
4363+ size);
4364+ return -EINVAL;
4365+ }
4366+
4367+ DP("from 0x%08x to 0x%08x", req->from, req->to);
4368+
4369+ if (req->from > req->to) {
4370+ DP("bad ip range");
4371+ return -EINVAL;
4372+ }
4373+
4374+ if (req->to - req->from > MAX_RANGE) {
4375+ ip_set_printk("range too big (max %d addresses)",
4376+ MAX_RANGE);
4377+ return -ERANGE;
4378+ }
4379+
4380+ map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
4381+ if (!map) {
4382+ DP("out of memory for %d bytes",
4383+ sizeof(struct ip_set_ipmap));
4384+ return -ENOMEM;
4385+ }
4386+ map->first_ip = req->from;
4387+ map->last_ip = req->to;
4388+ map->netmask = req->netmask;
4389+
4390+ if (req->netmask == 0xFFFFFFFF) {
4391+ map->hosts = 1;
4392+ map->sizeid = map->last_ip - map->first_ip + 1;
4393+ } else {
4394+ unsigned int mask_bits, netmask_bits;
4395+ ip_set_ip_t mask;
4396+
4397+ map->first_ip &= map->netmask; /* Should we better bark? */
4398+
4399+ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
4400+ netmask_bits = mask_to_bits(map->netmask);
4401+
4402+ if (!mask || netmask_bits <= mask_bits)
4403+ return -EINVAL;
4404+
4405+ map->hosts = 2 << (32 - netmask_bits - 1);
4406+ map->sizeid = 2 << (netmask_bits - mask_bits - 1);
4407+ }
4408+ newbytes = bitmap_bytes(0, map->sizeid - 1);
4409+ DP("%x %x %i", map->first_ip, map->last_ip, newbytes);
4410+ map->members = kmalloc(newbytes, GFP_KERNEL);
4411+ if (!map->members) {
4412+ DP("out of memory for %d bytes", newbytes);
4413+ kfree(map);
4414+ return -ENOMEM;
4415+ }
4416+ memset(map->members, 0, newbytes);
4417+
4418+ *private = (struct ip_set_private *) map;
4419+ return 0;
4420+}
4421+
4422+static void destroy(struct ip_set_private **private)
4423+{
4424+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) *private;
4425+
4426+ kfree(map->members);
4427+ kfree(map);
4428+
4429+ *private = NULL;
4430+}
4431+
4432+static void flush(struct ip_set_private *private)
4433+{
4434+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4435+ memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
4436+}
4437+
4438+static int list_header_size(const struct ip_set_private *private)
4439+{
4440+ return sizeof(struct ip_set_req_ipmap_create);
4441+}
4442+
4443+static void list_header(const struct ip_set_private *private, void *data)
4444+{
4445+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4446+ struct ip_set_req_ipmap_create *header =
4447+ (struct ip_set_req_ipmap_create *) data;
4448+
4449+ DP("list_header %x %x", map->first_ip, map->last_ip);
4450+
4451+ header->from = map->first_ip;
4452+ header->to = map->last_ip;
4453+ header->netmask = map->netmask;
4454+}
4455+
4456+static int list_members_size(const struct ip_set_private *private)
4457+{
4458+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4459+
4460+ return bitmap_bytes(0, map->sizeid - 1);
4461+}
4462+
4463+static void list_members(const struct ip_set_private *private, void *data)
4464+{
4465+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4466+
4467+ int bytes = bitmap_bytes(0, map->sizeid - 1);
4468+
4469+ memcpy(data, map->members, bytes);
4470+}
4471+
4472+static ip_set_ip_t sizeid(const struct ip_set_private *private)
4473+{
4474+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) private;
4475+
4476+ return (map->sizeid);
4477+}
4478+
4479+static struct ip_set_type ip_set_ipmap = {
4480+ .typename = SETTYPE_NAME,
4481+ .typecode = IPSET_TYPE_IP,
4482+ .protocol_version = IP_SET_PROTOCOL_VERSION,
4483+ .create = &create,
4484+ .destroy = &destroy,
4485+ .flush = &flush,
4486+ .reqsize = sizeof(struct ip_set_req_ipmap),
4487+ .addip = &addip,
4488+ .addip_kernel = &addip_kernel,
4489+ .delip = &delip,
4490+ .delip_kernel = &delip_kernel,
4491+ .matchip = &matchip,
4492+ .testip = &testip,
4493+ .testip_kernel = &testip_kernel,
4494+ .list_header_size = &list_header_size,
4495+ .list_header = &list_header,
4496+ .list_members_size = &list_members_size,
4497+ .list_members = &list_members,
4498+ .sizeid = &sizeid,
4499+ .me = THIS_MODULE,
4500+};
4501+
4502+static int __init init(void)
4503+{
4504+ return ip_set_register_set_type(&ip_set_ipmap);
4505+}
4506+
4507+static void __exit fini(void)
4508+{
4509+ /* FIXME: possible race with ip_set_create() */
4510+ ip_set_unregister_set_type(&ip_set_ipmap);
4511+}
4512+
4513+module_init(init);
4514+module_exit(fini);
4515+MODULE_LICENSE("GPL");
4516diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_macipmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_macipmap.c
4517--- linux-2.6.3.org/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
4518+++ linux-2.6.3/net/ipv4/netfilter/ip_set_macipmap.c 2004-02-09 15:02:00.000000000 +0100
4519@@ -0,0 +1,371 @@
4520+/* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
4521+ * Patrick Schaaf (bof@bof.de)
4522+ * Martin Josefsson (gandalf@wlug.westbo.se)
4523+ *
4524+ * This program is free software; you can redistribute it and/or modify
4525+ * it under the terms of the GNU General Public License as published by
4526+ * the Free Software Foundation; either version 2 of the License, or
4527+ * (at your option) any later version.
4528+ *
4529+ * This program is distributed in the hope that it will be useful,
4530+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4531+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4532+ * GNU General Public License for more details.
4533+ *
4534+ * You should have received a copy of the GNU General Public License
4535+ * along with this program; if not, write to the Free Software
4536+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4537+ */
4538+
4539+/* Kernel module implementing an IP set type: the macipmap type */
4540+
4541+#include <linux/module.h>
4542+#include <linux/ip.h>
4543+#include <linux/skbuff.h>
4544+#include <linux/netfilter_ipv4/ip_tables.h>
4545+#include <linux/netfilter_ipv4/ip_set.h>
4546+#include <linux/errno.h>
4547+#include <asm/uaccess.h>
4548+#include <asm/bitops.h>
4549+#include <asm/softirq.h>
4550+#include <linux/spinlock.h>
4551+#include <linux/if_ether.h>
4552+#include <linux/vmalloc.h>
4553+
4554+#include <linux/netfilter_ipv4/ip_set_macipmap.h>
4555+
4556+static int
4557+matchip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4558+{
4559+ struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4560+ struct ip_set_macip *table =
4561+ (struct ip_set_macip *) map->members;
4562+
4563+ if (ip < map->first_ip || ip > map->last_ip)
4564+ return -ERANGE;
4565+
4566+ *id = ip - map->first_ip;
4567+ return !!test_bit(IPSET_MACIP_ISSET, &table[*id].flags);
4568+}
4569+
4570+static int
4571+testip(struct ip_set_private *private, const void *data, size_t size,
4572+ ip_set_ip_t *id)
4573+{
4574+ struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4575+ struct ip_set_macip *table =
4576+ (struct ip_set_macip *) map->members;
4577+
4578+ struct ip_set_req_macipmap *req =
4579+ (struct ip_set_req_macipmap *) data;
4580+
4581+ if (size != sizeof(struct ip_set_req_macipmap)) {
4582+ ip_set_printk("data length wrong (want %d, have %d)",
4583+ sizeof(struct ip_set_req_macipmap),
4584+ size);
4585+ return -EINVAL;
4586+ }
4587+
4588+ if (req->ip < map->first_ip || req->ip > map->last_ip)
4589+ return -ERANGE;
4590+
4591+ *id = req->ip - map->first_ip;
4592+ if (test_bit(IPSET_MACIP_ISSET, &table[*id].flags)) {
4593+ /* Is mac pointer valid?
4594+ * If so, compare... */
4595+ return (memcmp(req->ethernet,
4596+ &table[*id].ethernet,
4597+ ETH_ALEN) == 0);
4598+ } else {
4599+ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4600+ }
4601+}
4602+
4603+static int
4604+testip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4605+ u_int32_t flags, ip_set_ip_t *id)
4606+{
4607+ struct ip_set_macipmap *map =
4608+ (struct ip_set_macipmap *) private;
4609+ struct ip_set_macip *table =
4610+ (struct ip_set_macip *) map->members;
4611+ ip_set_ip_t ip;
4612+
4613+ if (!(flags & IPSET_TYPE_IP))
4614+ return -EINVAL;
4615+
4616+ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4617+ : skb->nh.iph->daddr);
4618+
4619+ if (ip < map->first_ip || ip > map->last_ip)
4620+ return -ERANGE;
4621+
4622+ *id = ip - map->first_ip;
4623+ if (test_bit(IPSET_MACIP_ISSET, &table[*id].flags)) {
4624+ /* Is mac pointer valid?
4625+ * If so, compare... */
4626+ return (skb->mac.raw >= skb->head
4627+ && (skb->mac.raw + ETH_HLEN) <= skb->data
4628+ && (memcmp(skb->mac.ethernet->h_source,
4629+ &table[*id].ethernet,
4630+ ETH_ALEN) == 0));
4631+ } else {
4632+ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
4633+ }
4634+}
4635+
4636+/* returns 0 on success */
4637+static inline int
4638+__addip(struct ip_set_private *private,
4639+ ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *id)
4640+{
4641+ struct ip_set_macipmap *map =
4642+ (struct ip_set_macipmap *) private;
4643+ struct ip_set_macip *table =
4644+ (struct ip_set_macip *) map->members;
4645+
4646+ if (ip < map->first_ip || ip > map->last_ip)
4647+ return -ERANGE;
4648+ if (test_and_set_bit(IPSET_MACIP_ISSET,
4649+ &table[ip - map->first_ip].flags))
4650+ return -EEXIST;
4651+
4652+ *id = ip - map->first_ip;
4653+ memcpy(&table[*id].ethernet, ethernet, ETH_ALEN);
4654+ return 0;
4655+}
4656+
4657+static int
4658+addip(struct ip_set_private *private, const void *data, size_t size,
4659+ ip_set_ip_t *id)
4660+{
4661+ struct ip_set_req_macipmap *req =
4662+ (struct ip_set_req_macipmap *) data;
4663+
4664+ if (size != sizeof(struct ip_set_req_macipmap)) {
4665+ ip_set_printk("data length wrong (want %d, have %d)",
4666+ sizeof(struct ip_set_req_macipmap),
4667+ size);
4668+ return -EINVAL;
4669+ }
4670+ return __addip(private, req->ip, req->ethernet, id);
4671+}
4672+
4673+static int
4674+addip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4675+ u_int32_t flags, ip_set_ip_t *id)
4676+{
4677+ ip_set_ip_t ip;
4678+
4679+ if (!(flags & IPSET_TYPE_IP))
4680+ return -EINVAL;
4681+
4682+ ip = ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4683+ : skb->nh.iph->daddr);
4684+
4685+ if (!(skb->mac.raw >= skb->head
4686+ && (skb->mac.raw + ETH_HLEN) <= skb->data))
4687+ return -EINVAL;
4688+
4689+ return __addip(private, ip, skb->mac.ethernet->h_source, id);
4690+}
4691+
4692+static inline int
4693+__delip(struct ip_set_private *private, ip_set_ip_t ip, ip_set_ip_t *id)
4694+{
4695+ struct ip_set_macipmap *map =
4696+ (struct ip_set_macipmap *) private;
4697+ struct ip_set_macip *table =
4698+ (struct ip_set_macip *) map->members;
4699+
4700+ if (ip < map->first_ip || ip > map->last_ip)
4701+ return -ERANGE;
4702+ if (!test_and_clear_bit(IPSET_MACIP_ISSET,
4703+ &table[ip - map->first_ip].flags))
4704+ return -EEXIST;
4705+
4706+ *id = ip - map->first_ip;
4707+ return 0;
4708+}
4709+
4710+static int
4711+delip(struct ip_set_private *private, const void *data, size_t size,
4712+ ip_set_ip_t *id)
4713+{
4714+ struct ip_set_req_macipmap *req =
4715+ (struct ip_set_req_macipmap *) data;
4716+
4717+ if (size != sizeof(struct ip_set_req_macipmap)) {
4718+ ip_set_printk("data length wrong (want %d, have %d)",
4719+ sizeof(struct ip_set_req_macipmap),
4720+ size);
4721+ return -EINVAL;
4722+ }
4723+ return __delip(private, req->ip, id);
4724+}
4725+
4726+static int
4727+delip_kernel(struct ip_set_private *private, const struct sk_buff *skb,
4728+ u_int32_t flags, ip_set_ip_t *id)
4729+{
4730+ if (!(flags & IPSET_TYPE_IP))
4731+ return -EINVAL;
4732+
4733+ return __delip(private,
4734+ ntohl(flags & IPSET_SRC ? skb->nh.iph->saddr
4735+ : skb->nh.iph->daddr),
4736+ id);
4737+}
4738+
4739+static int create(struct ip_set_private **private, const void *data, size_t size)
4740+{
4741+ int newbytes;
4742+ struct ip_set_req_macipmap_create *req =
4743+ (struct ip_set_req_macipmap_create *) data;
4744+ struct ip_set_macipmap *map;
4745+
4746+ if (size != sizeof(struct ip_set_req_macipmap_create)) {
4747+ ip_set_printk("data length wrong (want %d, have %d)",
4748+ sizeof(struct ip_set_req_macipmap_create),
4749+ size);
4750+ return -EINVAL;
4751+ }
4752+
4753+ DP("from 0x%08x to 0x%08x", req->from, req->to);
4754+
4755+ if (req->from > req->to) {
4756+ DP("bad ip range");
4757+ return -EINVAL;
4758+ }
4759+
4760+ if (req->to - req->from > MAX_RANGE) {
4761+ ip_set_printk("range too big (max %d addresses)",
4762+ MAX_RANGE);
4763+ return -ERANGE;
4764+ }
4765+
4766+ map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
4767+ if (!map) {
4768+ DP("out of memory for %d bytes",
4769+ sizeof(struct ip_set_macipmap));
4770+ return -ENOMEM;
4771+ }
4772+ map->flags = req->flags;
4773+ map->first_ip = req->from;
4774+ map->last_ip = req->to;
4775+ newbytes = (req->to - req->from + 1) * sizeof(struct ip_set_macip);
4776+ map->members = vmalloc(newbytes);
4777+ if (!map->members) {
4778+ DP("out of memory for %d bytes", newbytes);
4779+ kfree(map);
4780+ return -ENOMEM;
4781+ }
4782+ memset(map->members, 0, newbytes);
4783+
4784+ *private = (struct ip_set_private *) map;
4785+ return 0;
4786+}
4787+
4788+static void destroy(struct ip_set_private **private)
4789+{
4790+ struct ip_set_macipmap *map =
4791+ (struct ip_set_macipmap *) *private;
4792+
4793+ vfree(map->members);
4794+ kfree(map);
4795+
4796+ *private = NULL;
4797+}
4798+
4799+static void flush(struct ip_set_private *private)
4800+{
4801+ struct ip_set_macipmap *map =
4802+ (struct ip_set_macipmap *) private;
4803+ memset(map->members, 0, (map->last_ip - map->first_ip)
4804+ * sizeof(struct ip_set_macip));
4805+}
4806+
4807+static int list_header_size(const struct ip_set_private *private)
4808+{
4809+ return sizeof(struct ip_set_req_macipmap_create);
4810+}
4811+
4812+static void list_header(const struct ip_set_private *private, void *data)
4813+{
4814+ struct ip_set_macipmap *map =
4815+ (struct ip_set_macipmap *) private;
4816+ struct ip_set_req_macipmap_create *header =
4817+ (struct ip_set_req_macipmap_create *) data;
4818+
4819+ DP("list_header %x %x %u", map->first_ip, map->last_ip,
4820+ map->flags);
4821+
4822+ header->from = map->first_ip;
4823+ header->to = map->last_ip;
4824+ header->flags = map->flags;
4825+}
4826+
4827+static int list_members_size(const struct ip_set_private *private)
4828+{
4829+ struct ip_set_macipmap *map =
4830+ (struct ip_set_macipmap *) private;
4831+
4832+ return (map->last_ip
4833+ - map->first_ip + 1) * sizeof(struct ip_set_macip);
4834+}
4835+
4836+static void list_members(const struct ip_set_private *private, void *data)
4837+{
4838+ struct ip_set_macipmap *map =
4839+ (struct ip_set_macipmap *) private;
4840+
4841+ int bytes = (map->last_ip -
4842+ - map->first_ip + 1) * sizeof(struct ip_set_macip);
4843+
4844+ memcpy(data, map->members, bytes);
4845+}
4846+
4847+static ip_set_ip_t sizeid(const struct ip_set_private *private)
4848+{
4849+ struct ip_set_macipmap *map = (struct ip_set_macipmap *) private;
4850+
4851+ return (map->last_ip - map->first_ip + 1);
4852+}
4853+
4854+static struct ip_set_type ip_set_macipmap = {
4855+ .typename = SETTYPE_NAME,
4856+ .typecode = IPSET_TYPE_IP,
4857+ .protocol_version = IP_SET_PROTOCOL_VERSION,
4858+ .create = &create,
4859+ .destroy = &destroy,
4860+ .flush = &flush,
4861+ .reqsize = sizeof(struct ip_set_req_macipmap),
4862+ .addip = &addip,
4863+ .addip_kernel = &addip_kernel,
4864+ .delip = &delip,
4865+ .delip_kernel = &delip_kernel,
4866+ .matchip = &matchip,
4867+ .testip = &testip,
4868+ .testip_kernel = &testip_kernel,
4869+ .list_header_size = &list_header_size,
4870+ .list_header = &list_header,
4871+ .list_members_size = &list_members_size,
4872+ .list_members = &list_members,
4873+ .sizeid = &sizeid,
4874+ .me = THIS_MODULE,
4875+};
4876+
4877+static int __init init(void)
4878+{
4879+ return ip_set_register_set_type(&ip_set_macipmap);
4880+}
4881+
4882+static void __exit fini(void)
4883+{
4884+ /* FIXME: possible race with ip_set_create() */
4885+ ip_set_unregister_set_type(&ip_set_macipmap);
4886+}
4887+
4888+module_init(init);
4889+module_exit(fini);
4890+MODULE_LICENSE("GPL");
4891diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ip_set_portmap.c linux-2.6.3/net/ipv4/netfilter/ip_set_portmap.c
4892--- linux-2.6.3.org/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
4893+++ linux-2.6.3/net/ipv4/netfilter/ip_set_portmap.c 2004-02-09 15:02:00.000000000 +0100
4894@@ -0,0 +1,363 @@
4895+/* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
4896+ *
4897+ * Based on ip_set_ipmap.c
4898+ *
4899+ * This program is free software; you can redistribute it and/or modify
4900+ * it under the terms of the GNU General Public License as published by
4901+ * the Free Software Foundation; either version 2 of the License, or
4902+ * (at your option) any later version.
4903+ *
4904+ * This program is distributed in the hope that it will be useful,
4905+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4906+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4907+ * GNU General Public License for more details.
4908+ *
4909+ * You should have received a copy of the GNU General Public License
4910+ * along with this program; if not, write to the Free Software
4911+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4912+ */
4913+
4914+/* Kernel module implementing a port set type as a bitmap */
4915+
4916+#include <linux/module.h>
4917+#include <linux/ip.h>
4918+#include <linux/tcp.h>
4919+#include <linux/udp.h>
4920+#include <linux/skbuff.h>
4921+#include <linux/netfilter_ipv4/ip_tables.h>
4922+#include <linux/netfilter_ipv4/ip_set.h>
4923+#include <linux/errno.h>
4924+#include <asm/uaccess.h>
4925+#include <asm/bitops.h>
4926+#include <asm/softirq.h>
4927+#include <linux/spinlock.h>
4928+
4929+#include <net/ip.h>
4930+
4931+#include <linux/netfilter_ipv4/ip_set_portmap.h>
4932+
4933+static inline ip_set_ip_t
4934+get_port(const struct sk_buff *skb, u_int32_t flags)
4935+{
4936+ struct iphdr *iph = skb->nh.iph;
4937+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
4938+
4939+ switch (iph->protocol) {
4940+ case IPPROTO_TCP: {
4941+ struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
4942+
4943+ /* See comments at tcp_match in ip_tables.c */
4944+ if (offset != 0
4945+ || (offset == 0
4946+ && (skb->len - iph->ihl * 4) < sizeof(struct tcphdr)))
4947+ return INVALID_PORT;
4948+
4949+ return ntohs(flags & IPSET_SRC ?
4950+ tcph->source : tcph->dest);
4951+ }
4952+ case IPPROTO_UDP: {
4953+ struct udphdr *udph = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
4954+
4955+ if (offset != 0
4956+ || (offset == 0
4957+ && (skb->len - iph->ihl * 4) < sizeof(struct udphdr)))
4958+ return INVALID_PORT;
4959+
4960+ return ntohs(flags & IPSET_SRC ?
4961+ udph->source : udph->dest);
4962+ }
4963+ default:
4964+ return INVALID_PORT;
4965+ }
4966+}
4967+
4968+static inline int
4969+__testport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4970+{
4971+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
4972+
4973+ if (port < map->first_port || port > map->last_port)
4974+ return -ERANGE;
4975+
4976+ *id = port - map->first_port;
4977+ return !!test_bit(*id, map->members);
4978+}
4979+
4980+static int
4981+matchport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
4982+{
4983+ return __testport(private, port, id);
4984+}
4985+
4986+static int
4987+testport(struct ip_set_private *private, const void *data, size_t size,
4988+ ip_set_ip_t *id)
4989+{
4990+ struct ip_set_req_portmap *req =
4991+ (struct ip_set_req_portmap *) data;
4992+
4993+ if (size != sizeof(struct ip_set_req_portmap)) {
4994+ ip_set_printk("data length wrong (want %d, have %d)",
4995+ sizeof(struct ip_set_req_portmap),
4996+ size);
4997+ return -EINVAL;
4998+ }
4999+ return __testport(private, req->port, id);
5000+}
5001+
5002+static int
5003+testport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5004+ u_int32_t flags, ip_set_ip_t *id)
5005+{
5006+ ip_set_ip_t port;
5007+
5008+ if (!(flags & IPSET_TYPE_PORT))
5009+ return -EINVAL;
5010+
5011+ port = get_port(skb, flags);
5012+ DP("flags %u %s port %u",
5013+ flags,
5014+ flags & IPSET_SRC ? "SRC" : "DST",
5015+ port);
5016+
5017+ if (port == INVALID_PORT)
5018+ return -EINVAL;
5019+
5020+ return __testport(private, port, id);
5021+}
5022+
5023+static inline int
5024+__addport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5025+{
5026+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5027+
5028+ if (port < map->first_port || port > map->last_port)
5029+ return -ERANGE;
5030+ if (test_and_set_bit(port - map->first_port, map->members))
5031+ return -EEXIST;
5032+
5033+ *id = port - map->first_port;
5034+ return 0;
5035+}
5036+
5037+static int
5038+addport(struct ip_set_private *private, const void *data, size_t size,
5039+ ip_set_ip_t *id)
5040+{
5041+ struct ip_set_req_portmap *req =
5042+ (struct ip_set_req_portmap *) data;
5043+
5044+ if (size != sizeof(struct ip_set_req_portmap)) {
5045+ ip_set_printk("data length wrong (want %d, have %d)",
5046+ sizeof(struct ip_set_req_portmap),
5047+ size);
5048+ return -EINVAL;
5049+ }
5050+ return __addport(private, req->port, id);
5051+}
5052+
5053+static int
5054+addport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5055+ u_int32_t flags, ip_set_ip_t *id)
5056+{
5057+ ip_set_ip_t port;
5058+
5059+ if (!(flags & IPSET_TYPE_PORT))
5060+ return -EINVAL;
5061+
5062+ port = get_port(skb, flags);
5063+
5064+ if (port == INVALID_PORT)
5065+ return -EINVAL;
5066+
5067+ return __addport(private, port, id);
5068+}
5069+
5070+static inline int
5071+__delport(struct ip_set_private *private, ip_set_ip_t port, ip_set_ip_t *id)
5072+{
5073+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5074+
5075+ if (port < map->first_port || port > map->last_port)
5076+ return -ERANGE;
5077+ if (!test_and_clear_bit(port - map->first_port, map->members))
5078+ return -EEXIST;
5079+
5080+ *id = port - map->first_port;
5081+ return 0;
5082+}
5083+
5084+static int
5085+delport(struct ip_set_private *private, const void *data, size_t size,
5086+ ip_set_ip_t *id)
5087+{
5088+ struct ip_set_req_portmap *req =
5089+ (struct ip_set_req_portmap *) data;
5090+
5091+ if (size != sizeof(struct ip_set_req_portmap)) {
5092+ ip_set_printk("data length wrong (want %d, have %d)",
5093+ sizeof(struct ip_set_req_portmap),
5094+ size);
5095+ return -EINVAL;
5096+ }
5097+ return __delport(private, req->port, id);
5098+}
5099+
5100+static int
5101+delport_kernel(struct ip_set_private *private, const struct sk_buff *skb,
5102+ u_int32_t flags, ip_set_ip_t *id)
5103+{
5104+ ip_set_ip_t port;
5105+
5106+ if (!(flags & IPSET_TYPE_PORT))
5107+ return -EINVAL;
5108+
5109+ port = get_port(skb, flags);
5110+
5111+ if (port == INVALID_PORT)
5112+ return -EINVAL;
5113+
5114+ return __delport(private, port, id);
5115+}
5116+
5117+static int create(struct ip_set_private **private, const void *data, size_t size)
5118+{
5119+ int newbytes;
5120+ struct ip_set_req_portmap_create *req =
5121+ (struct ip_set_req_portmap_create *) data;
5122+ struct ip_set_portmap *map;
5123+
5124+ if (size != sizeof(struct ip_set_req_portmap_create)) {
5125+ ip_set_printk("data length wrong (want %d, have %d)",
5126+ sizeof(struct ip_set_req_portmap_create),
5127+ size);
5128+ return -EINVAL;
5129+ }
5130+
5131+ DP("from 0x%08x to 0x%08x", req->from, req->to);
5132+
5133+ if (req->from > req->to) {
5134+ DP("bad port range");
5135+ return -EINVAL;
5136+ }
5137+
5138+ if (req->to - req->from > MAX_RANGE) {
5139+ ip_set_printk("range too big (max %d ports)",
5140+ MAX_RANGE);
5141+ return -ERANGE;
5142+ }
5143+
5144+ map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
5145+ if (!map) {
5146+ DP("out of memory for %d bytes",
5147+ sizeof(struct ip_set_portmap));
5148+ return -ENOMEM;
5149+ }
5150+ map->first_port = req->from;
5151+ map->last_port = req->to;
5152+ newbytes = bitmap_bytes(req->from, req->to);
5153+ map->members = kmalloc(newbytes, GFP_KERNEL);
5154+ if (!map->members) {
5155+ DP("out of memory for %d bytes", newbytes);
5156+ kfree(map);
5157+ return -ENOMEM;
5158+ }
5159+ memset(map->members, 0, newbytes);
5160+
5161+ *private = (struct ip_set_private *) map;
5162+ return 0;
5163+}
5164+
5165+static void destroy(struct ip_set_private **private)
5166+{
5167+ struct ip_set_portmap *map = (struct ip_set_portmap *) *private;
5168+
5169+ kfree(map->members);
5170+ kfree(map);
5171+
5172+ *private = NULL;
5173+}
5174+
5175+static void flush(struct ip_set_private *private)
5176+{
5177+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5178+ memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
5179+}
5180+
5181+static int list_header_size(const struct ip_set_private *private)
5182+{
5183+ return sizeof(struct ip_set_req_portmap_create);
5184+}
5185+
5186+static void list_header(const struct ip_set_private *private, void *data)
5187+{
5188+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5189+ struct ip_set_req_portmap_create *header =
5190+ (struct ip_set_req_portmap_create *) data;
5191+
5192+ DP("list_header %x %x", map->first_port, map->last_port);
5193+
5194+ header->from = map->first_port;
5195+ header->to = map->last_port;
5196+}
5197+
5198+static int list_members_size(const struct ip_set_private *private)
5199+{
5200+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5201+
5202+ return bitmap_bytes(map->first_port, map->last_port);
5203+}
5204+
5205+static void list_members(const struct ip_set_private *private, void *data)
5206+{
5207+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5208+
5209+ int bytes = bitmap_bytes(map->first_port, map->last_port);
5210+
5211+ memcpy(data, map->members, bytes);
5212+}
5213+
5214+static ip_set_ip_t sizeid(const struct ip_set_private *private)
5215+{
5216+ struct ip_set_portmap *map = (struct ip_set_portmap *) private;
5217+
5218+ return (map->last_port - map->first_port + 1);
5219+}
5220+
5221+static struct ip_set_type ip_set_portmap = {
5222+ .typename = SETTYPE_NAME,
5223+ .typecode = IPSET_TYPE_PORT,
5224+ .protocol_version = IP_SET_PROTOCOL_VERSION,
5225+ .create = &create,
5226+ .destroy = &destroy,
5227+ .flush = &flush,
5228+ .reqsize = sizeof(struct ip_set_req_portmap),
5229+ .addip = &addport,
5230+ .addip_kernel = &addport_kernel,
5231+ .delip = &delport,
5232+ .delip_kernel = &delport_kernel,
5233+ .matchip = &matchport,
5234+ .testip = &testport,
5235+ .testip_kernel = &testport_kernel,
5236+ .list_header_size = &list_header_size,
5237+ .list_header = &list_header,
5238+ .list_members_size = &list_members_size,
5239+ .list_members = &list_members,
5240+ .sizeid = &sizeid,
5241+ .me = THIS_MODULE,
5242+};
5243+
5244+static int __init init(void)
5245+{
5246+ return ip_set_register_set_type(&ip_set_portmap);
5247+}
5248+
5249+static void __exit fini(void)
5250+{
5251+ /* FIXME: possible race with ip_set_create() */
5252+ ip_set_unregister_set_type(&ip_set_portmap);
5253+}
5254+
5255+module_init(init);
5256+module_exit(fini);
5257+MODULE_LICENSE("GPL");
5258diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.6.3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
5259--- linux-2.6.3.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 1970-01-01 01:00:00.000000000 +0100
5260+++ linux-2.6.3/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c 2004-02-19 08:47:22.288007614 +0100
5261@@ -0,0 +1,84 @@
5262+/**
5263+ * Strip all IP options in the IP packet header.
5264+ *
5265+ * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
5266+ * This software is distributed under GNU GPL v2, 1991
5267+ */
5268+
5269+#include <linux/module.h>
5270+#include <linux/skbuff.h>
5271+#include <linux/ip.h>
5272+#include <net/checksum.h>
5273+
5274+#include <linux/netfilter_ipv4/ip_tables.h>
5275+
5276+MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
5277+MODULE_DESCRIPTION("Strip all options in IPv4 packets");
5278+MODULE_LICENSE("GPL");
5279+
5280+static unsigned int
5281+target(struct sk_buff **pskb,
5282+ unsigned int hooknum,
5283+ const struct net_device *in,
5284+ const struct net_device *out,
5285+ const void *targinfo,
5286+ void *userinfo)
5287+{
5288+ struct iphdr *iph = (*pskb)->nh.iph;
5289+ struct sk_buff *skb = (*pskb);
5290+ struct ip_options * opt;
5291+ unsigned char * optiph = skb->nh.raw;
5292+ int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
5293+
5294+
5295+ /* if no options in packet then nothing to clear. */
5296+ if (iph->ihl * 4 == sizeof(struct iphdr))
5297+ return IPT_CONTINUE;
5298+
5299+ /* else clear all options */
5300+ memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
5301+ memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
5302+ opt = &(IPCB(skb)->opt);
5303+ opt->is_data = 0;
5304+ opt->optlen = l;
5305+
5306+ skb->nfcache |= NFC_ALTERED;
5307+
5308+ return IPT_CONTINUE;
5309+}
5310+
5311+static int
5312+checkentry(const char *tablename,
5313+ const struct ipt_entry *e,
5314+ void *targinfo,
5315+ unsigned int targinfosize,
5316+ unsigned int hook_mask)
5317+{
5318+ if (strcmp(tablename, "mangle")) {
5319+ printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5320+ return 0;
5321+ }
5322+ /* nothing else to check because no parameters */
5323+ return 1;
5324+}
5325+
5326+static struct ipt_target ipt_ipv4optsstrip_reg
5327+= { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
5328+
5329+static int __init init(void)
5330+{
5331+ if (ipt_register_target(&ipt_ipv4optsstrip_reg))
5332+ return -EINVAL;
5333+ printk("ipt_IPV4OPTSSTRIP loaded\n");
5334+
5335+ return 0;
5336+}
5337+
5338+static void __exit fini(void)
5339+{
5340+ ipt_unregister_target(&ipt_ipv4optsstrip_reg);
5341+ printk("ipt_IPV4OPTSSTRIP unloaded\n");
5342+}
5343+
5344+module_init(init);
5345+module_exit(fini);
5346diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.6.3/net/ipv4/netfilter/ipt_NETLINK.c
5347--- linux-2.6.3.org/net/ipv4/netfilter/ipt_NETLINK.c 1970-01-01 01:00:00.000000000 +0100
5348+++ linux-2.6.3/net/ipv4/netfilter/ipt_NETLINK.c 2004-02-19 08:47:24.269530314 +0100
5349@@ -0,0 +1,119 @@
5350+#include <linux/module.h>
5351+#include <linux/version.h>
5352+#include <linux/config.h>
5353+#include <linux/socket.h>
5354+#include <linux/skbuff.h>
5355+#include <linux/kernel.h>
5356+#include <linux/netlink.h>
5357+#include <linux/netdevice.h>
5358+#include <linux/mm.h>
5359+#include <linux/socket.h>
5360+#include <linux/netfilter_ipv4/ip_tables.h>
5361+#include <linux/netfilter_ipv4/ipt_NETLINK.h>
5362+#include <net/sock.h>
5363+
5364+MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
5365+MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
5366+MODULE_LICENSE("GPL");
5367+
5368+#if 0
5369+#define DEBUGP printk
5370+#else
5371+#define DEBUGP(format, args...)
5372+#endif
5373+
5374+static struct sock *ipfwsk;
5375+
5376+static unsigned int ipt_netlink_target(struct sk_buff **pskb,
5377+ unsigned int hooknum,
5378+ const struct net_device *in,
5379+ const struct net_device *out,
5380+ const void *targinfo, void *userinfo)
5381+{
5382+ struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5383+ struct iphdr *ip = (*pskb)->nh.iph;
5384+ struct sk_buff *outskb;
5385+ struct netlink_t nlhdr;
5386+ size_t len=0;
5387+
5388+ /* Allocate a socket buffer */
5389+ if ( MASK(nld->flags, USE_SIZE) )
5390+ len = nld->size+sizeof(nlhdr);
5391+ else
5392+ len = ntohs(ip->tot_len)+sizeof(nlhdr);
5393+
5394+ outskb=alloc_skb(len, GFP_ATOMIC);
5395+
5396+ if (outskb) {
5397+ nlhdr.len=len;
5398+
5399+ if ( MASK(nld->flags, USE_MARK) )
5400+ nlhdr.mark=(*pskb)->nfmark=nld->mark;
5401+ else
5402+ nlhdr.mark=(*pskb)->nfmark;
5403+
5404+ if ( in && in->name ) {
5405+ strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
5406+ }else if ( out && out->name ){
5407+ strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
5408+ }
5409+
5410+ skb_put(outskb, len);
5411+ memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
5412+ memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
5413+ netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
5414+ }else{
5415+ if (net_ratelimit())
5416+ printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
5417+ }
5418+
5419+ if ( MASK(nld->flags, USE_DROP) )
5420+ return NF_DROP;
5421+
5422+ return IPT_CONTINUE;
5423+}
5424+
5425+static int ipt_netlink_checkentry(const char *tablename,
5426+ const struct ipt_entry *e,
5427+ void *targinfo,
5428+ unsigned int targinfosize,
5429+ unsigned int hookmask)
5430+{
5431+ //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
5432+
5433+ return 1;
5434+}
5435+
5436+static struct ipt_target ipt_netlink_reg = {
5437+ {NULL, NULL},
5438+ "NETLINK",
5439+ ipt_netlink_target,
5440+ ipt_netlink_checkentry,
5441+ NULL,
5442+ THIS_MODULE
5443+};
5444+
5445+static int __init init(void)
5446+{
5447+ DEBUGP("ipt_NETLINK: init module\n");
5448+
5449+ if (ipt_register_target(&ipt_netlink_reg) != 0) {
5450+ return -EINVAL;
5451+ }
5452+
5453+ if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
5454+ return -EINVAL;
5455+ }
5456+
5457+ return 0;
5458+}
5459+
5460+static void __exit fini(void)
5461+{
5462+ DEBUGP("ipt_NETLINK: cleanup_module\n");
5463+ ipt_unregister_target(&ipt_netlink_reg);
5464+ if(ipfwsk->socket) sock_release(ipfwsk->socket);
5465+}
5466+
5467+module_init(init);
5468+module_exit(fini);
5469diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_POOL.c linux-2.6.3/net/ipv4/netfilter/ipt_POOL.c
5470--- linux-2.6.3.org/net/ipv4/netfilter/ipt_POOL.c 1970-01-01 01:00:00.000000000 +0100
5471+++ linux-2.6.3/net/ipv4/netfilter/ipt_POOL.c 2004-02-19 08:47:30.712978249 +0100
5472@@ -0,0 +1,116 @@
5473+/* ipt_POOL.c - netfilter target to manipulate IP pools
5474+ *
5475+ * This target can be used almost everywhere. It acts on some specified
5476+ * IP pool, adding or deleting some IP address in the pool. The address
5477+ * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
5478+ * of the packet under inspection.
5479+ *
5480+ * The target normally returns IPT_CONTINUE.
5481+ */
5482+
5483+#include <linux/types.h>
5484+#include <linux/ip.h>
5485+#include <linux/timer.h>
5486+#include <linux/module.h>
5487+#include <linux/netfilter.h>
5488+#include <linux/netdevice.h>
5489+#include <linux/if.h>
5490+#include <linux/inetdevice.h>
5491+#include <net/protocol.h>
5492+#include <net/checksum.h>
5493+#include <linux/netfilter_ipv4.h>
5494+#include <linux/netfilter_ipv4/ip_nat_rule.h>
5495+#include <linux/netfilter_ipv4/ipt_pool.h>
5496+
5497+#if 0
5498+#define DEBUGP printk
5499+#else
5500+#define DEBUGP(format, args...)
5501+#endif
5502+
5503+/*** NOTE NOTE NOTE NOTE ***
5504+**
5505+** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
5506+** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
5507+** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
5508+** is modified for the source IP address of the packet under inspection.
5509+** The same way, the ipt_pool_info.dst pool is modified for the destination.
5510+**
5511+** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
5512+** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
5513+**
5514+** If a modification was done to the pool, we possibly return ACCEPT or DROP,
5515+** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
5516+** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
5517+** ACCEPT and DROP flags are evaluated when the pool was not modified.)
5518+*/
5519+
5520+static int
5521+do_check(const char *tablename,
5522+ const struct ipt_entry *e,
5523+ void *targinfo,
5524+ unsigned int targinfosize,
5525+ unsigned int hook_mask)
5526+{
5527+ const struct ipt_pool_info *ipi = targinfo;
5528+
5529+ if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
5530+ DEBUGP("POOL_check: size %u.\n", targinfosize);
5531+ return 0;
5532+ }
5533+ DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
5534+ return 1;
5535+}
5536+
5537+static unsigned int
5538+do_target(struct sk_buff **pskb,
5539+ unsigned int hooknum,
5540+ const struct net_device *in,
5541+ const struct net_device *out,
5542+ const void *targinfo,
5543+ void *userinfo)
5544+{
5545+ const struct ipt_pool_info *ipi = targinfo;
5546+ int modified;
5547+ unsigned int verdict = IPT_CONTINUE;
5548+
5549+ if (ipi->src != IP_POOL_NONE) {
5550+ modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
5551+ ipi->flags & IPT_POOL_DEL_SRC);
5552+ if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
5553+ if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
5554+ verdict = NF_ACCEPT;
5555+ else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
5556+ verdict = NF_DROP;
5557+ }
5558+ }
5559+ if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
5560+ modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
5561+ ipi->flags & IPT_POOL_DEL_DST);
5562+ if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
5563+ if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
5564+ verdict = NF_ACCEPT;
5565+ else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
5566+ verdict = NF_DROP;
5567+ }
5568+ }
5569+ return verdict;
5570+}
5571+
5572+static struct ipt_target pool_reg
5573+= { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
5574+
5575+static int __init init(void)
5576+{
5577+ DEBUGP("init ipt_POOL\n");
5578+ return ipt_register_target(&pool_reg);
5579+}
5580+
5581+static void __exit fini(void)
5582+{
5583+ DEBUGP("fini ipt_POOL\n");
5584+ ipt_unregister_target(&pool_reg);
5585+}
5586+
5587+module_init(init);
5588+module_exit(fini);
5589diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_SET.c linux-2.6.3/net/ipv4/netfilter/ipt_SET.c
5590--- linux-2.6.3.org/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
5591+++ linux-2.6.3/net/ipv4/netfilter/ipt_SET.c 2004-02-09 15:02:00.000000000 +0100
5592@@ -0,0 +1,115 @@
5593+/* ipt_SET.c - netfilter target to manipulate IP sets
5594+ *
5595+ * This target can be used almost everywhere. It acts on some specified
5596+ * IP set, adding or deleting some IP addresses/ports in the set.
5597+ * The addresses/ports can be either the source, or destination
5598+ * of the packet under inspection.
5599+ *
5600+ */
5601+
5602+#include <linux/types.h>
5603+#include <linux/ip.h>
5604+#include <linux/timer.h>
5605+#include <linux/module.h>
5606+#include <linux/netfilter.h>
5607+#include <linux/netdevice.h>
5608+#include <linux/if.h>
5609+#include <linux/inetdevice.h>
5610+#include <net/protocol.h>
5611+#include <net/checksum.h>
5612+#include <linux/netfilter_ipv4.h>
5613+#include <linux/netfilter_ipv4/ip_nat_rule.h>
5614+#include <linux/netfilter_ipv4/ipt_set.h>
5615+
5616+static unsigned int
5617+target(struct sk_buff **pskb,
5618+ unsigned int hooknum,
5619+ const struct net_device *in,
5620+ const struct net_device *out,
5621+ const void *targinfo,
5622+ void *userinfo)
5623+{
5624+ const struct ipt_set_info_target *info = targinfo;
5625+
5626+ if (info->add_set.id >= 0)
5627+ ip_set_addip_kernel(ip_set_list[info->add_set.id],
5628+ *pskb,
5629+ info->add_set.flags,
5630+ info->add_set.set_level,
5631+ info->add_set.ip_level);
5632+ if (info->del_set.id >= 0)
5633+ ip_set_delip_kernel(ip_set_list[info->del_set.id],
5634+ *pskb,
5635+ info->del_set.flags,
5636+ info->del_set.set_level,
5637+ info->del_set.ip_level);
5638+
5639+ return IPT_CONTINUE;
5640+}
5641+
5642+static int
5643+checkentry(const char *tablename,
5644+ const struct ipt_entry *e,
5645+ void *targinfo,
5646+ unsigned int targinfosize, unsigned int hook_mask)
5647+{
5648+ struct ipt_set_info_target *info = targinfo;
5649+
5650+ if (targinfosize != IPT_ALIGN(sizeof(*info))) {
5651+ DP("bad target info size %u", targinfosize);
5652+ return 0;
5653+ }
5654+
5655+ if (info->add_set.id >= 0
5656+ && !ip_set_get_byid(info->add_set.id)) {
5657+ ip_set_printk("cannot verify add_set id %i as target",
5658+ info->add_set.id);
5659+ return 0; /* error */
5660+ }
5661+ if (info->del_set.id >= 0
5662+ && !ip_set_get_byid(info->del_set.id)) {
5663+ ip_set_printk("cannot verify del_set id %i as target",
5664+ info->del_set.id);
5665+ return 0; /* error */
5666+ }
5667+ DP("checkentry OK");
5668+
5669+ return 1;
5670+}
5671+
5672+static void destroy(void *targetinfo, unsigned int targetsize)
5673+{
5674+ struct ipt_set_info_target *info = targetinfo;
5675+
5676+ if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
5677+ ip_set_printk("invalid targetsize %d", targetsize);
5678+ return;
5679+ }
5680+
5681+ if (info->add_set.id >= 0)
5682+ ip_set_put(ip_set_list[info->add_set.id]);
5683+ if (info->del_set.id >= 0)
5684+ ip_set_put(ip_set_list[info->del_set.id]);
5685+}
5686+
5687+static struct ipt_target SET_target = {
5688+ .name = "SET",
5689+ .target = target,
5690+ .checkentry = checkentry,
5691+ .destroy = destroy,
5692+ .me = THIS_MODULE
5693+};
5694+
5695+static int __init init(void)
5696+{
5697+ return ipt_register_target(&SET_target);
5698+}
5699+
5700+static void __exit fini(void)
5701+{
5702+ ipt_unregister_target(&SET_target);
5703+}
5704+
5705+module_init(init);
5706+module_exit(fini);
5707+MODULE_LICENSE("GPL");
5708diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_TTL.c linux-2.6.3/net/ipv4/netfilter/ipt_TTL.c
5709--- linux-2.6.3.org/net/ipv4/netfilter/ipt_TTL.c 1970-01-01 01:00:00.000000000 +0100
5710+++ linux-2.6.3/net/ipv4/netfilter/ipt_TTL.c 2004-02-19 08:47:25.605208582 +0100
5711@@ -0,0 +1,110 @@
5712+/* TTL modification target for IP tables
5713+ * (C) 2000 by Harald Welte <laforge@gnumonks.org>
5714+ *
5715+ * Version: 1.8
5716+ *
5717+ * This software is distributed under the terms of GNU GPL
5718+ */
5719+
5720+#include <linux/module.h>
5721+#include <linux/skbuff.h>
5722+#include <linux/ip.h>
5723+#include <net/checksum.h>
5724+
5725+#include <linux/netfilter_ipv4/ip_tables.h>
5726+#include <linux/netfilter_ipv4/ipt_TTL.h>
5727+
5728+MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
5729+MODULE_DESCRIPTION("IP tables TTL modification module");
5730+MODULE_LICENSE("GPL");
5731+
5732+static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
5733+ const struct net_device *in, const struct net_device *out,
5734+ const void *targinfo, void *userinfo)
5735+{
5736+ struct iphdr *iph = (*pskb)->nh.iph;
5737+ const struct ipt_TTL_info *info = targinfo;
5738+ u_int16_t diffs[2];
5739+ int new_ttl;
5740+
5741+ switch (info->mode) {
5742+ case IPT_TTL_SET:
5743+ new_ttl = info->ttl;
5744+ break;
5745+ case IPT_TTL_INC:
5746+ new_ttl = iph->ttl + info->ttl;
5747+ if (new_ttl > 255)
5748+ new_ttl = 255;
5749+ break;
5750+ case IPT_TTL_DEC:
5751+ new_ttl = iph->ttl + info->ttl;
5752+ if (new_ttl < 0)
5753+ new_ttl = 0;
5754+ break;
5755+ default:
5756+ new_ttl = iph->ttl;
5757+ break;
5758+ }
5759+
5760+ if (new_ttl != iph->ttl) {
5761+ diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
5762+ iph->ttl = new_ttl;
5763+ diffs[1] = htons(((unsigned)iph->ttl) << 8);
5764+ iph->check = csum_fold(csum_partial((char *)diffs,
5765+ sizeof(diffs),
5766+ iph->check^0xFFFF));
5767+ (*pskb)->nfcache |= NFC_ALTERED;
5768+ }
5769+
5770+ return IPT_CONTINUE;
5771+}
5772+
5773+static int ipt_ttl_checkentry(const char *tablename,
5774+ const struct ipt_entry *e,
5775+ void *targinfo,
5776+ unsigned int targinfosize,
5777+ unsigned int hook_mask)
5778+{
5779+ struct ipt_TTL_info *info = targinfo;
5780+
5781+ if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
5782+ printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
5783+ targinfosize,
5784+ IPT_ALIGN(sizeof(struct ipt_TTL_info)));
5785+ return 0;
5786+ }
5787+
5788+ if (strcmp(tablename, "mangle")) {
5789+ printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
5790+ return 0;
5791+ }
5792+
5793+ if (info->mode > IPT_TTL_MAXMODE) {
5794+ printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
5795+ info->mode);
5796+ return 0;
5797+ }
5798+
5799+ if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
5800+ printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
5801+ return 0;
5802+ }
5803+
5804+ return 1;
5805+}
5806+
5807+static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
5808+ ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
5809+
5810+static int __init init(void)
5811+{
5812+ return ipt_register_target(&ipt_TTL);
5813+}
5814+
5815+static void __exit fini(void)
5816+{
5817+ ipt_unregister_target(&ipt_TTL);
5818+}
5819+
5820+module_init(init);
5821+module_exit(fini);
5822diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.6.3/net/ipv4/netfilter/ipt_connlimit.c
5823--- linux-2.6.3.org/net/ipv4/netfilter/ipt_connlimit.c 1970-01-01 01:00:00.000000000 +0100
5824+++ linux-2.6.3/net/ipv4/netfilter/ipt_connlimit.c 2004-02-19 08:47:26.593970414 +0100
5825@@ -0,0 +1,232 @@
5826+/*
5827+ * netfilter module to limit the number of parallel tcp
5828+ * connections per IP address.
5829+ * (c) 2000 Gerd Knorr <kraxel@bytesex.org>
5830+ * Nov 2002: Martin Bene <martin.bene@icomedias.com>:
5831+ * only ignore TIME_WAIT or gone connections
5832+ *
5833+ * based on ...
5834+ *
5835+ * Kernel module to match connection tracking information.
5836+ * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
5837+ */
5838+#include <linux/module.h>
5839+#include <linux/skbuff.h>
5840+#include <linux/list.h>
5841+#include <linux/netfilter_ipv4/ip_conntrack.h>
5842+#include <linux/netfilter_ipv4/ip_conntrack_core.h>
5843+#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
5844+#include <linux/netfilter_ipv4/ip_tables.h>
5845+#include <linux/netfilter_ipv4/ipt_connlimit.h>
5846+
5847+#define DEBUG 0
5848+
5849+MODULE_LICENSE("GPL");
5850+
5851+/* we'll save the tuples of all connections we care about */
5852+struct ipt_connlimit_conn
5853+{
5854+ struct list_head list;
5855+ struct ip_conntrack_tuple tuple;
5856+};
5857+
5858+struct ipt_connlimit_data {
5859+ spinlock_t lock;
5860+ struct list_head iphash[256];
5861+};
5862+
5863+static int ipt_iphash(u_int32_t addr)
5864+{
5865+ int hash;
5866+
5867+ hash = addr & 0xff;
5868+ hash ^= (addr >> 8) & 0xff;
5869+ hash ^= (addr >> 16) & 0xff;
5870+ hash ^= (addr >> 24) & 0xff;
5871+ return hash;
5872+}
5873+
5874+static int count_them(struct ipt_connlimit_data *data,
5875+ u_int32_t addr, u_int32_t mask,
5876+ struct ip_conntrack *ct)
5877+{
5878+#if DEBUG
5879+ const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
5880+ "fin_wait", "time_wait", "close", "close_wait",
5881+ "last_ack", "listen" };
5882+#endif
5883+ int addit = 1, matches = 0;
5884+ struct ip_conntrack_tuple tuple;
5885+ struct ip_conntrack_tuple_hash *found;
5886+ struct ipt_connlimit_conn *conn;
5887+ struct list_head *hash,*lh;
5888+
5889+ spin_lock(&data->lock);
5890+ tuple = ct->tuplehash[0].tuple;
5891+ hash = &data->iphash[ipt_iphash(addr & mask)];
5892+
5893+ /* check the saved connections */
5894+ for (lh = hash->next; lh != hash; lh = lh->next) {
5895+ conn = list_entry(lh,struct ipt_connlimit_conn,list);
5896+ found = ip_conntrack_find_get(&conn->tuple,ct);
5897+ if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
5898+ found != NULL &&
5899+ found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
5900+ /* Just to be sure we have it only once in the list.
5901+ We should'nt see tuples twice unless someone hooks this
5902+ into a table without "-p tcp --syn" */
5903+ addit = 0;
5904+ }
5905+#if DEBUG
5906+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
5907+ ipt_iphash(addr & mask),
5908+ NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
5909+ NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
5910+ (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
5911+#endif
5912+ if (NULL == found) {
5913+ /* this one is gone */
5914+ lh = lh->prev;
5915+ list_del(lh->next);
5916+ kfree(conn);
5917+ continue;
5918+ }
5919+ if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
5920+ /* we don't care about connections which are
5921+ closed already -> ditch it */
5922+ lh = lh->prev;
5923+ list_del(lh->next);
5924+ kfree(conn);
5925+ nf_conntrack_put(&found->ctrack->infos[0]);
5926+ continue;
5927+ }
5928+ if ((addr & mask) == (conn->tuple.src.ip & mask)) {
5929+ /* same source IP address -> be counted! */
5930+ matches++;
5931+ }
5932+ nf_conntrack_put(&found->ctrack->infos[0]);
5933+ }
5934+ if (addit) {
5935+ /* save the new connection in our list */
5936+#if DEBUG
5937+ printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
5938+ ipt_iphash(addr & mask),
5939+ NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
5940+ NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
5941+#endif
5942+ conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
5943+ if (NULL == conn)
5944+ return -1;
5945+ memset(conn,0,sizeof(*conn));
5946+ INIT_LIST_HEAD(&conn->list);
5947+ conn->tuple = tuple;
5948+ list_add(&conn->list,hash);
5949+ matches++;
5950+ }
5951+ spin_unlock(&data->lock);
5952+ return matches;
5953+}
5954+
5955+static int
5956+match(const struct sk_buff *skb,
5957+ const struct net_device *in,
5958+ const struct net_device *out,
5959+ const void *matchinfo,
5960+ int offset,
5961+ const void *hdr,
5962+ u_int16_t datalen,
5963+ int *hotdrop)
5964+{
5965+ const struct ipt_connlimit_info *info = matchinfo;
5966+ int connections, match;
5967+ struct ip_conntrack *ct;
5968+ enum ip_conntrack_info ctinfo;
5969+
5970+ ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
5971+ if (NULL == ct) {
5972+ printk("ipt_connlimit: Oops: invalid ct state ?\n");
5973+ *hotdrop = 1;
5974+ return 0;
5975+ }
5976+ connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
5977+ if (-1 == connections) {
5978+ printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
5979+ *hotdrop = 1; /* let's free some memory :-) */
5980+ return 0;
5981+ }
5982+ match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
5983+#if DEBUG
5984+ printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
5985+ "connections=%d limit=%d match=%s\n",
5986+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
5987+ connections, info->limit, match ? "yes" : "no");
5988+#endif
5989+
5990+ return match;
5991+}
5992+
5993+static int check(const char *tablename,
5994+ const struct ipt_ip *ip,
5995+ void *matchinfo,
5996+ unsigned int matchsize,
5997+ unsigned int hook_mask)
5998+{
5999+ struct ipt_connlimit_info *info = matchinfo;
6000+ int i;
6001+
6002+ /* verify size */
6003+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
6004+ return 0;
6005+
6006+ /* refuse anything but tcp */
6007+ if (ip->proto != IPPROTO_TCP)
6008+ return 0;
6009+
6010+ /* init private data */
6011+ info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
6012+ spin_lock_init(&(info->data->lock));
6013+ for (i = 0; i < 256; i++)
6014+ INIT_LIST_HEAD(&(info->data->iphash[i]));
6015+
6016+ return 1;
6017+}
6018+
6019+static void destroy(void *matchinfo, unsigned int matchinfosize)
6020+{
6021+ struct ipt_connlimit_info *info = matchinfo;
6022+ struct ipt_connlimit_conn *conn;
6023+ struct list_head *hash;
6024+ int i;
6025+
6026+ /* cleanup */
6027+ for (i = 0; i < 256; i++) {
6028+ hash = &(info->data->iphash[i]);
6029+ while (hash != hash->next) {
6030+ conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
6031+ list_del(hash->next);
6032+ kfree(conn);
6033+ }
6034+ }
6035+ kfree(info->data);
6036+}
6037+
6038+static struct ipt_match connlimit_match
6039+= { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
6040+
6041+static int __init init(void)
6042+{
6043+ /* NULL if ip_conntrack not a module */
6044+ if (ip_conntrack_module)
6045+ __MOD_INC_USE_COUNT(ip_conntrack_module);
6046+ return ipt_register_match(&connlimit_match);
6047+}
6048+
6049+static void __exit fini(void)
6050+{
6051+ ipt_unregister_match(&connlimit_match);
6052+ if (ip_conntrack_module)
6053+ __MOD_DEC_USE_COUNT(ip_conntrack_module);
6054+}
6055+
6056+module_init(init);
6057+module_exit(fini);
6058diff -Nur linux-2.6.3.org/net/ipv4/netfilter/ipt_dstlimit.c linux-2.6.3/net/ipv4/netfilter/ipt_dstlimit.c
6059--- linux-2.6.3.org/net/ipv4/netfilter/ipt_dstlimit.c 1970-01-01 01:00:00.000000000 +0100
6060+++ linux-2.6.3/net/ipv4/netfilter/ipt_dstlimit.c 2004-02-19 08:47:27.235815809 +0100
6061@@ -0,0 +1,677 @@
6062+/* iptables match extension to limit the number of packets per second
6063+ * seperately for each destination.
6064+ *
6065+ * (C) 2003 by Harald Welte <laforge@netfilter.org>
6066+ *
6067+ * $Id$
6068+ *
6069+ * Development of this code was funded by Astaro AG, http://www.astaro.com/
6070+ *
6071+ * based on ipt_limit.c by:
6072