]> git.pld-linux.org Git - packages/kernel.git/blame - pom-ng-set-20060504.patch
- addedd Linux-ABI support. Bcond, default disabled.
[packages/kernel.git] / pom-ng-set-20060504.patch
CommitLineData
c6410bf7 1 include/linux/netfilter_ipv4/ip_set.h | 498 +++++
2 include/linux/netfilter_ipv4/ip_set_iphash.h | 29
3 include/linux/netfilter_ipv4/ip_set_ipmap.h | 56
4 include/linux/netfilter_ipv4/ip_set_ipporthash.h | 33
5 include/linux/netfilter_ipv4/ip_set_iptree.h | 39
6 include/linux/netfilter_ipv4/ip_set_jhash.h | 148 +
7 include/linux/netfilter_ipv4/ip_set_macipmap.h | 38
8 include/linux/netfilter_ipv4/ip_set_malloc.h | 116 +
9 include/linux/netfilter_ipv4/ip_set_nethash.h | 54
10 include/linux/netfilter_ipv4/ip_set_portmap.h | 25
11 include/linux/netfilter_ipv4/ipt_set.h | 21
12 net/ipv4/netfilter/Kconfig | 109 +
13 net/ipv4/netfilter/Makefile | 12
14 net/ipv4/netfilter/ip_set.c | 1992 +++++++++++++++++++++++
15 net/ipv4/netfilter/ip_set_iphash.c | 398 ++++
16 net/ipv4/netfilter/ip_set_ipmap.c | 327 +++
17 net/ipv4/netfilter/ip_set_ipporthash.c | 524 ++++++
18 net/ipv4/netfilter/ip_set_iptree.c | 544 ++++++
19 net/ipv4/netfilter/ip_set_macipmap.c | 353 ++++
20 net/ipv4/netfilter/ip_set_nethash.c | 466 +++++
21 net/ipv4/netfilter/ip_set_portmap.c | 334 +++
22 net/ipv4/netfilter/ipt_SET.c | 128 +
23 net/ipv4/netfilter/ipt_set.c | 113 +
24 23 files changed, 6357 insertions(+)
25
26diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set.h linux/include/linux/netfilter_ipv4/ip_set.h
27--- linux.org/include/linux/netfilter_ipv4/ip_set.h 1970-01-01 01:00:00.000000000 +0100
28+++ linux/include/linux/netfilter_ipv4/ip_set.h 2006-05-04 10:26:33.000000000 +0200
29@@ -0,0 +1,498 @@
30+#ifndef _IP_SET_H
31+#define _IP_SET_H
32+
33+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
34+ * Patrick Schaaf <bof@bof.de>
35+ * Martin Josefsson <gandalf@wlug.westbo.se>
36+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
37+ *
38+ * This program is free software; you can redistribute it and/or modify
39+ * it under the terms of the GNU General Public License version 2 as
40+ * published by the Free Software Foundation.
41+ */
42+
43+#if 0
44+#define IP_SET_DEBUG
45+#endif
46+
47+/*
48+ * A sockopt of such quality has hardly ever been seen before on the open
49+ * market! This little beauty, hardly ever used: above 64, so it's
50+ * traditionally used for firewalling, not touched (even once!) by the
51+ * 2.0, 2.2 and 2.4 kernels!
52+ *
53+ * Comes with its own certificate of authenticity, valid anywhere in the
54+ * Free world!
55+ *
56+ * Rusty, 19.4.2000
57+ */
58+#define SO_IP_SET 83
59+
60+/*
61+ * Heavily modify by Joakim Axelsson 08.03.2002
62+ * - Made it more modulebased
63+ *
64+ * Additional heavy modifications by Jozsef Kadlecsik 22.02.2004
65+ * - bindings added
66+ * - in order to "deal with" backward compatibility, renamed to ipset
67+ */
68+
69+/*
70+ * Used so that the kernel module and ipset-binary can match their versions
71+ */
72+#define IP_SET_PROTOCOL_VERSION 2
73+
74+#define IP_SET_MAXNAMELEN 32 /* set names and set typenames */
75+
76+/* Lets work with our own typedef for representing an IP address.
77+ * We hope to make the code more portable, possibly to IPv6...
78+ *
79+ * The representation works in HOST byte order, because most set types
80+ * will perform arithmetic operations and compare operations.
81+ *
82+ * For now the type is an uint32_t.
83+ *
84+ * Make sure to ONLY use the functions when translating and parsing
85+ * in order to keep the host byte order and make it more portable:
86+ * parse_ip()
87+ * parse_mask()
88+ * parse_ipandmask()
89+ * ip_tostring()
90+ * (Joakim: where are they???)
91+ */
92+
93+typedef uint32_t ip_set_ip_t;
94+
95+/* Sets are identified by an id in kernel space. Tweak with ip_set_id_t
96+ * and IP_SET_INVALID_ID if you want to increase the max number of sets.
97+ */
98+typedef uint16_t ip_set_id_t;
99+
100+#define IP_SET_INVALID_ID 65535
101+
102+/* How deep we follow bindings */
103+#define IP_SET_MAX_BINDINGS 6
104+
105+/*
106+ * Option flags for kernel operations (ipt_set_info)
107+ */
108+#define IPSET_SRC 0x01 /* Source match/add */
109+#define IPSET_DST 0x02 /* Destination match/add */
110+#define IPSET_MATCH_INV 0x04 /* Inverse matching */
111+
112+/*
113+ * Set features
114+ */
115+#define IPSET_TYPE_IP 0x01 /* IP address type of set */
116+#define IPSET_TYPE_PORT 0x02 /* Port type of set */
117+#define IPSET_DATA_SINGLE 0x04 /* Single data storage */
118+#define IPSET_DATA_DOUBLE 0x08 /* Double data storage */
119+
120+/* Reserved keywords */
121+#define IPSET_TOKEN_DEFAULT ":default:"
122+#define IPSET_TOKEN_ALL ":all:"
123+
124+/* SO_IP_SET operation constants, and their request struct types.
125+ *
126+ * Operation ids:
127+ * 0-99: commands with version checking
128+ * 100-199: add/del/test/bind/unbind
129+ * 200-299: list, save, restore
130+ */
131+
132+/* Single shot operations:
133+ * version, create, destroy, flush, rename and swap
134+ *
135+ * Sets are identified by name.
136+ */
137+
138+#define IP_SET_REQ_STD \
139+ unsigned op; \
140+ unsigned version; \
141+ char name[IP_SET_MAXNAMELEN]
142+
143+#define IP_SET_OP_CREATE 0x00000001 /* Create a new (empty) set */
144+struct ip_set_req_create {
145+ IP_SET_REQ_STD;
146+ char typename[IP_SET_MAXNAMELEN];
147+};
148+
149+#define IP_SET_OP_DESTROY 0x00000002 /* Remove a (empty) set */
150+struct ip_set_req_std {
151+ IP_SET_REQ_STD;
152+};
153+
154+#define IP_SET_OP_FLUSH 0x00000003 /* Remove all IPs in a set */
155+/* Uses ip_set_req_std */
156+
157+#define IP_SET_OP_RENAME 0x00000004 /* Rename a set */
158+/* Uses ip_set_req_create */
159+
160+#define IP_SET_OP_SWAP 0x00000005 /* Swap two sets */
161+/* Uses ip_set_req_create */
162+
163+union ip_set_name_index {
164+ char name[IP_SET_MAXNAMELEN];
165+ ip_set_id_t index;
166+};
167+
168+#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
169+struct ip_set_req_get_set {
170+ unsigned op;
171+ unsigned version;
172+ union ip_set_name_index set;
173+};
174+
175+#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
176+/* Uses ip_set_req_get_set */
177+
178+#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
179+struct ip_set_req_version {
180+ unsigned op;
181+ unsigned version;
182+};
183+
184+/* Double shots operations:
185+ * add, del, test, bind and unbind.
186+ *
187+ * First we query the kernel to get the index and type of the target set,
188+ * then issue the command. Validity of IP is checked in kernel in order
189+ * to minimalize sockopt operations.
190+ */
191+
192+/* Get minimal set data for add/del/test/bind/unbind IP */
193+#define IP_SET_OP_ADT_GET 0x00000010 /* Get set and type */
194+struct ip_set_req_adt_get {
195+ unsigned op;
196+ unsigned version;
197+ union ip_set_name_index set;
198+ char typename[IP_SET_MAXNAMELEN];
199+};
200+
201+#define IP_SET_REQ_BYINDEX \
202+ unsigned op; \
203+ ip_set_id_t index;
204+
205+struct ip_set_req_adt {
206+ IP_SET_REQ_BYINDEX;
207+};
208+
209+#define IP_SET_OP_ADD_IP 0x00000101 /* Add an IP to a set */
210+/* Uses ip_set_req_adt, with type specific addage */
211+
212+#define IP_SET_OP_DEL_IP 0x00000102 /* Remove an IP from a set */
213+/* Uses ip_set_req_adt, with type specific addage */
214+
215+#define IP_SET_OP_TEST_IP 0x00000103 /* Test an IP in a set */
216+/* Uses ip_set_req_adt, with type specific addage */
217+
218+#define IP_SET_OP_BIND_SET 0x00000104 /* Bind an IP to a set */
219+/* Uses ip_set_req_bind, with type specific addage */
220+struct ip_set_req_bind {
221+ IP_SET_REQ_BYINDEX;
222+ char binding[IP_SET_MAXNAMELEN];
223+};
224+
225+#define IP_SET_OP_UNBIND_SET 0x00000105 /* Unbind an IP from a set */
226+/* Uses ip_set_req_bind, with type speficic addage
227+ * index = 0 means unbinding for all sets */
228+
229+#define IP_SET_OP_TEST_BIND_SET 0x00000106 /* Test binding an IP to a set */
230+/* Uses ip_set_req_bind, with type specific addage */
231+
232+/* Multiple shots operations: list, save, restore.
233+ *
234+ * - check kernel version and query the max number of sets
235+ * - get the basic information on all sets
236+ * and size required for the next step
237+ * - get actual set data: header, data, bindings
238+ */
239+
240+/* Get max_sets and the index of a queried set
241+ */
242+#define IP_SET_OP_MAX_SETS 0x00000020
243+struct ip_set_req_max_sets {
244+ unsigned op;
245+ unsigned version;
246+ ip_set_id_t max_sets; /* max_sets */
247+ ip_set_id_t sets; /* real number of sets */
248+ union ip_set_name_index set; /* index of set if name used */
249+};
250+
251+/* Get the id and name of the sets plus size for next step */
252+#define IP_SET_OP_LIST_SIZE 0x00000201
253+#define IP_SET_OP_SAVE_SIZE 0x00000202
254+struct ip_set_req_setnames {
255+ unsigned op;
256+ ip_set_id_t index; /* set to list/save */
257+ size_t size; /* size to get setdata/bindings */
258+ /* followed by sets number of struct ip_set_name_list */
259+};
260+
261+struct ip_set_name_list {
262+ char name[IP_SET_MAXNAMELEN];
263+ char typename[IP_SET_MAXNAMELEN];
264+ ip_set_id_t index;
265+ ip_set_id_t id;
266+};
267+
268+/* The actual list operation */
269+#define IP_SET_OP_LIST 0x00000203
270+struct ip_set_req_list {
271+ IP_SET_REQ_BYINDEX;
272+ /* sets number of struct ip_set_list in reply */
273+};
274+
275+struct ip_set_list {
276+ ip_set_id_t index;
277+ ip_set_id_t binding;
278+ u_int32_t ref;
279+ size_t header_size; /* Set header data of header_size */
280+ size_t members_size; /* Set members data of members_size */
281+ size_t bindings_size; /* Set bindings data of bindings_size */
282+};
283+
284+struct ip_set_hash_list {
285+ ip_set_ip_t ip;
286+ ip_set_id_t binding;
287+};
288+
289+/* The save operation */
290+#define IP_SET_OP_SAVE 0x00000204
291+/* Uses ip_set_req_list, in the reply replaced by
292+ * sets number of struct ip_set_save plus a marker
293+ * ip_set_save followed by ip_set_hash_save structures.
294+ */
295+struct ip_set_save {
296+ ip_set_id_t index;
297+ ip_set_id_t binding;
298+ size_t header_size; /* Set header data of header_size */
299+ size_t members_size; /* Set members data of members_size */
300+};
301+
302+/* At restoring, ip == 0 means default binding for the given set: */
303+struct ip_set_hash_save {
304+ ip_set_ip_t ip;
305+ ip_set_id_t id;
306+ ip_set_id_t binding;
307+};
308+
309+/* The restore operation */
310+#define IP_SET_OP_RESTORE 0x00000205
311+/* Uses ip_set_req_setnames followed by ip_set_restore structures
312+ * plus a marker ip_set_restore, followed by ip_set_hash_save
313+ * structures.
314+ */
315+struct ip_set_restore {
316+ char name[IP_SET_MAXNAMELEN];
317+ char typename[IP_SET_MAXNAMELEN];
318+ ip_set_id_t index;
319+ size_t header_size; /* Create data of header_size */
320+ size_t members_size; /* Set members data of members_size */
321+};
322+
323+static inline int bitmap_bytes(ip_set_ip_t a, ip_set_ip_t b)
324+{
325+ return 4 * ((((b - a + 8) / 8) + 3) / 4);
326+}
327+
328+#ifdef __KERNEL__
329+
330+#define ip_set_printk(format, args...) \
331+ do { \
332+ printk("%s: %s: ", __FILE__, __FUNCTION__); \
333+ printk(format "\n" , ## args); \
334+ } while (0)
335+
336+#if defined(IP_SET_DEBUG)
337+#define DP(format, args...) \
338+ do { \
339+ printk("%s: %s (DBG): ", __FILE__, __FUNCTION__);\
340+ printk(format "\n" , ## args); \
341+ } while (0)
342+#define IP_SET_ASSERT(x) \
343+ do { \
344+ if (!(x)) \
345+ printk("IP_SET_ASSERT: %s:%i(%s)\n", \
346+ __FILE__, __LINE__, __FUNCTION__); \
347+ } while (0)
348+#else
349+#define DP(format, args...)
350+#define IP_SET_ASSERT(x)
351+#endif
352+
353+struct ip_set;
354+
355+/*
356+ * The ip_set_type definition - one per set type, e.g. "ipmap".
357+ *
358+ * Each individual set has a pointer, set->type, going to one
359+ * of these structures. Function pointers inside the structure implement
360+ * the real behaviour of the sets.
361+ *
362+ * If not mentioned differently, the implementation behind the function
363+ * pointers of a set_type, is expected to return 0 if ok, and a negative
364+ * errno (e.g. -EINVAL) on error.
365+ */
366+struct ip_set_type {
367+ struct list_head list; /* next in list of set types */
368+
369+ /* test for IP in set (kernel: iptables -m set src|dst)
370+ * return 0 if not in set, 1 if in set.
371+ */
372+ int (*testip_kernel) (struct ip_set *set,
373+ const struct sk_buff * skb,
374+ ip_set_ip_t *ip,
375+ const u_int32_t *flags,
376+ unsigned char index);
377+
378+ /* test for IP in set (userspace: ipset -T set IP)
379+ * return 0 if not in set, 1 if in set.
380+ */
381+ int (*testip) (struct ip_set *set,
382+ const void *data, size_t size,
383+ ip_set_ip_t *ip);
384+
385+ /*
386+ * Size of the data structure passed by when
387+ * adding/deletin/testing an entry.
388+ */
389+ size_t reqsize;
390+
391+ /* Add IP into set (userspace: ipset -A set IP)
392+ * Return -EEXIST if the address is already in the set,
393+ * and -ERANGE if the address lies outside the set bounds.
394+ * If the address was not already in the set, 0 is returned.
395+ */
396+ int (*addip) (struct ip_set *set,
397+ const void *data, size_t size,
398+ ip_set_ip_t *ip);
399+
400+ /* Add IP into set (kernel: iptables ... -j SET set src|dst)
401+ * Return -EEXIST if the address is already in the set,
402+ * and -ERANGE if the address lies outside the set bounds.
403+ * If the address was not already in the set, 0 is returned.
404+ */
405+ int (*addip_kernel) (struct ip_set *set,
406+ const struct sk_buff * skb,
407+ ip_set_ip_t *ip,
408+ const u_int32_t *flags,
409+ unsigned char index);
410+
411+ /* remove IP from set (userspace: ipset -D set --entry x)
412+ * Return -EEXIST if the address is NOT in the set,
413+ * and -ERANGE if the address lies outside the set bounds.
414+ * If the address really was in the set, 0 is returned.
415+ */
416+ int (*delip) (struct ip_set *set,
417+ const void *data, size_t size,
418+ ip_set_ip_t *ip);
419+
420+ /* remove IP from set (kernel: iptables ... -j SET --entry x)
421+ * Return -EEXIST if the address is NOT in the set,
422+ * and -ERANGE if the address lies outside the set bounds.
423+ * If the address really was in the set, 0 is returned.
424+ */
425+ int (*delip_kernel) (struct ip_set *set,
426+ const struct sk_buff * skb,
427+ ip_set_ip_t *ip,
428+ const u_int32_t *flags,
429+ unsigned char index);
430+
431+ /* new set creation - allocated type specific items
432+ */
433+ int (*create) (struct ip_set *set,
434+ const void *data, size_t size);
435+
436+ /* retry the operation after successfully tweaking the set
437+ */
438+ int (*retry) (struct ip_set *set);
439+
440+ /* set destruction - free type specific items
441+ * There is no return value.
442+ * Can be called only when child sets are destroyed.
443+ */
444+ void (*destroy) (struct ip_set *set);
445+
446+ /* set flushing - reset all bits in the set, or something similar.
447+ * There is no return value.
448+ */
449+ void (*flush) (struct ip_set *set);
450+
451+ /* Listing: size needed for header
452+ */
453+ size_t header_size;
454+
455+ /* Listing: Get the header
456+ *
457+ * Fill in the information in "data".
458+ * This function is always run after list_header_size() under a
459+ * writelock on the set. Therefor is the length of "data" always
460+ * correct.
461+ */
462+ void (*list_header) (const struct ip_set *set,
463+ void *data);
464+
465+ /* Listing: Get the size for the set members
466+ */
467+ int (*list_members_size) (const struct ip_set *set);
468+
469+ /* Listing: Get the set members
470+ *
471+ * Fill in the information in "data".
472+ * This function is always run after list_member_size() under a
473+ * writelock on the set. Therefor is the length of "data" always
474+ * correct.
475+ */
476+ void (*list_members) (const struct ip_set *set,
477+ void *data);
478+
479+ char typename[IP_SET_MAXNAMELEN];
480+ unsigned char features;
481+ int protocol_version;
482+
483+ /* Set this to THIS_MODULE if you are a module, otherwise NULL */
484+ struct module *me;
485+};
486+
487+extern int ip_set_register_set_type(struct ip_set_type *set_type);
488+extern void ip_set_unregister_set_type(struct ip_set_type *set_type);
489+
490+/* A generic ipset */
491+struct ip_set {
492+ char name[IP_SET_MAXNAMELEN]; /* the name of the set */
493+ rwlock_t lock; /* lock for concurrency control */
494+ ip_set_id_t id; /* set id for swapping */
495+ ip_set_id_t binding; /* default binding for the set */
496+ atomic_t ref; /* in kernel and in hash references */
497+ struct ip_set_type *type; /* the set types */
498+ void *data; /* pooltype specific data */
499+};
500+
501+/* Structure to bind set elements to sets */
502+struct ip_set_hash {
503+ struct list_head list; /* list of clashing entries in hash */
504+ ip_set_ip_t ip; /* ip from set */
505+ ip_set_id_t id; /* set id */
506+ ip_set_id_t binding; /* set we bind the element to */
507+};
508+
509+/* register and unregister set references */
510+extern ip_set_id_t ip_set_get_byname(const char name[IP_SET_MAXNAMELEN]);
511+extern ip_set_id_t ip_set_get_byindex(ip_set_id_t id);
512+extern void ip_set_put(ip_set_id_t id);
513+
514+/* API for iptables set match, and SET target */
515+extern void ip_set_addip_kernel(ip_set_id_t id,
516+ const struct sk_buff *skb,
517+ const u_int32_t *flags);
518+extern void ip_set_delip_kernel(ip_set_id_t id,
519+ const struct sk_buff *skb,
520+ const u_int32_t *flags);
521+extern int ip_set_testip_kernel(ip_set_id_t id,
522+ const struct sk_buff *skb,
523+ const u_int32_t *flags);
524+
525+#endif /* __KERNEL__ */
526+
527+#endif /*_IP_SET_H*/
528diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_iphash.h linux/include/linux/netfilter_ipv4/ip_set_iphash.h
529--- linux.org/include/linux/netfilter_ipv4/ip_set_iphash.h 1970-01-01 01:00:00.000000000 +0100
530+++ linux/include/linux/netfilter_ipv4/ip_set_iphash.h 2006-05-04 10:26:33.000000000 +0200
531@@ -0,0 +1,29 @@
532+#ifndef __IP_SET_IPHASH_H
533+#define __IP_SET_IPHASH_H
534+
535+#include <linux/netfilter_ipv4/ip_set.h>
536+
537+#define SETTYPE_NAME "iphash"
538+#define MAX_RANGE 0x0000FFFF
539+
540+struct ip_set_iphash {
541+ ip_set_ip_t *members; /* the iphash proper */
542+ uint32_t hashsize; /* hash size */
543+ uint16_t probes; /* max number of probes */
544+ uint16_t resize; /* resize factor in percent */
545+ ip_set_ip_t netmask; /* netmask */
546+ void *initval[0]; /* initvals for jhash_1word */
547+};
548+
549+struct ip_set_req_iphash_create {
550+ uint32_t hashsize;
551+ uint16_t probes;
552+ uint16_t resize;
553+ ip_set_ip_t netmask;
554+};
555+
556+struct ip_set_req_iphash {
557+ ip_set_ip_t ip;
558+};
559+
560+#endif /* __IP_SET_IPHASH_H */
561diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_ipmap.h linux/include/linux/netfilter_ipv4/ip_set_ipmap.h
562--- linux.org/include/linux/netfilter_ipv4/ip_set_ipmap.h 1970-01-01 01:00:00.000000000 +0100
563+++ linux/include/linux/netfilter_ipv4/ip_set_ipmap.h 2006-05-04 10:26:33.000000000 +0200
564@@ -0,0 +1,56 @@
565+#ifndef __IP_SET_IPMAP_H
566+#define __IP_SET_IPMAP_H
567+
568+#include <linux/netfilter_ipv4/ip_set.h>
569+
570+#define SETTYPE_NAME "ipmap"
571+#define MAX_RANGE 0x0000FFFF
572+
573+struct ip_set_ipmap {
574+ void *members; /* the ipmap proper */
575+ ip_set_ip_t first_ip; /* host byte order, included in range */
576+ ip_set_ip_t last_ip; /* host byte order, included in range */
577+ ip_set_ip_t netmask; /* subnet netmask */
578+ ip_set_ip_t sizeid; /* size of set in IPs */
579+ ip_set_ip_t hosts; /* number of hosts in a subnet */
580+};
581+
582+struct ip_set_req_ipmap_create {
583+ ip_set_ip_t from;
584+ ip_set_ip_t to;
585+ ip_set_ip_t netmask;
586+};
587+
588+struct ip_set_req_ipmap {
589+ ip_set_ip_t ip;
590+};
591+
592+unsigned int
593+mask_to_bits(ip_set_ip_t mask)
594+{
595+ unsigned int bits = 32;
596+ ip_set_ip_t maskaddr;
597+
598+ if (mask == 0xFFFFFFFF)
599+ return bits;
600+
601+ maskaddr = 0xFFFFFFFE;
602+ while (--bits >= 0 && maskaddr != mask)
603+ maskaddr <<= 1;
604+
605+ return bits;
606+}
607+
608+ip_set_ip_t
609+range_to_mask(ip_set_ip_t from, ip_set_ip_t to, unsigned int *bits)
610+{
611+ ip_set_ip_t mask = 0xFFFFFFFE;
612+
613+ *bits = 32;
614+ while (--(*bits) >= 0 && mask && (to & mask) != from)
615+ mask <<= 1;
616+
617+ return mask;
618+}
619+
620+#endif /* __IP_SET_IPMAP_H */
621diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_ipporthash.h linux/include/linux/netfilter_ipv4/ip_set_ipporthash.h
622--- linux.org/include/linux/netfilter_ipv4/ip_set_ipporthash.h 1970-01-01 01:00:00.000000000 +0100
623+++ linux/include/linux/netfilter_ipv4/ip_set_ipporthash.h 2006-05-04 10:26:33.000000000 +0200
624@@ -0,0 +1,33 @@
625+#ifndef __IP_SET_IPPORTHASH_H
626+#define __IP_SET_IPPORTHASH_H
627+
628+#include <linux/netfilter_ipv4/ip_set.h>
629+
630+#define SETTYPE_NAME "ipporthash"
631+#define MAX_RANGE 0x0000FFFF
632+#define INVALID_PORT (MAX_RANGE + 1)
633+
634+struct ip_set_ipporthash {
635+ ip_set_ip_t *members; /* the ipporthash proper */
636+ uint32_t hashsize; /* hash size */
637+ uint16_t probes; /* max number of probes */
638+ uint16_t resize; /* resize factor in percent */
639+ ip_set_ip_t first_ip; /* host byte order, included in range */
640+ ip_set_ip_t last_ip; /* host byte order, included in range */
641+ void *initval[0]; /* initvals for jhash_1word */
642+};
643+
644+struct ip_set_req_ipporthash_create {
645+ uint32_t hashsize;
646+ uint16_t probes;
647+ uint16_t resize;
648+ ip_set_ip_t from;
649+ ip_set_ip_t to;
650+};
651+
652+struct ip_set_req_ipporthash {
653+ ip_set_ip_t ip;
654+ ip_set_ip_t port;
655+};
656+
657+#endif /* __IP_SET_IPPORTHASH_H */
658diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_iptree.h linux/include/linux/netfilter_ipv4/ip_set_iptree.h
659--- linux.org/include/linux/netfilter_ipv4/ip_set_iptree.h 1970-01-01 01:00:00.000000000 +0100
660+++ linux/include/linux/netfilter_ipv4/ip_set_iptree.h 2006-05-04 10:26:33.000000000 +0200
661@@ -0,0 +1,39 @@
662+#ifndef __IP_SET_IPTREE_H
663+#define __IP_SET_IPTREE_H
664+
665+#include <linux/netfilter_ipv4/ip_set.h>
666+
667+#define SETTYPE_NAME "iptree"
668+#define MAX_RANGE 0x0000FFFF
669+
670+struct ip_set_iptreed {
671+ unsigned long expires[256]; /* x.x.x.ADDR */
672+};
673+
674+struct ip_set_iptreec {
675+ struct ip_set_iptreed *tree[256]; /* x.x.ADDR.* */
676+};
677+
678+struct ip_set_iptreeb {
679+ struct ip_set_iptreec *tree[256]; /* x.ADDR.*.* */
680+};
681+
682+struct ip_set_iptree {
683+ unsigned int timeout;
684+ unsigned int gc_interval;
685+#ifdef __KERNEL__
686+ struct timer_list gc;
687+ struct ip_set_iptreeb *tree[256]; /* ADDR.*.*.* */
688+#endif
689+};
690+
691+struct ip_set_req_iptree_create {
692+ unsigned int timeout;
693+};
694+
695+struct ip_set_req_iptree {
696+ ip_set_ip_t ip;
697+ unsigned int timeout;
698+};
699+
700+#endif /* __IP_SET_IPTREE_H */
701diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_jhash.h linux/include/linux/netfilter_ipv4/ip_set_jhash.h
702--- linux.org/include/linux/netfilter_ipv4/ip_set_jhash.h 1970-01-01 01:00:00.000000000 +0100
703+++ linux/include/linux/netfilter_ipv4/ip_set_jhash.h 2006-05-04 10:26:33.000000000 +0200
704@@ -0,0 +1,148 @@
705+#ifndef _LINUX_IPSET_JHASH_H
706+#define _LINUX_IPSET_JHASH_H
707+
708+/* This is a copy of linux/jhash.h but the types u32/u8 are changed
709+ * to __u32/__u8 so that the header file can be included into
710+ * userspace code as well. Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
711+ */
712+
713+/* jhash.h: Jenkins hash support.
714+ *
715+ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
716+ *
717+ * http://burtleburtle.net/bob/hash/
718+ *
719+ * These are the credits from Bob's sources:
720+ *
721+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
722+ * hash(), hash2(), hash3, and mix() are externally useful functions.
723+ * Routines to test the hash are included if SELF_TEST is defined.
724+ * You can use this free for any purpose. It has no warranty.
725+ *
726+ * Copyright (C) 2003 David S. Miller (davem@redhat.com)
727+ *
728+ * I've modified Bob's hash to be useful in the Linux kernel, and
729+ * any bugs present are surely my fault. -DaveM
730+ */
731+
732+/* NOTE: Arguments are modified. */
733+#define __jhash_mix(a, b, c) \
734+{ \
735+ a -= b; a -= c; a ^= (c>>13); \
736+ b -= c; b -= a; b ^= (a<<8); \
737+ c -= a; c -= b; c ^= (b>>13); \
738+ a -= b; a -= c; a ^= (c>>12); \
739+ b -= c; b -= a; b ^= (a<<16); \
740+ c -= a; c -= b; c ^= (b>>5); \
741+ a -= b; a -= c; a ^= (c>>3); \
742+ b -= c; b -= a; b ^= (a<<10); \
743+ c -= a; c -= b; c ^= (b>>15); \
744+}
745+
746+/* The golden ration: an arbitrary value */
747+#define JHASH_GOLDEN_RATIO 0x9e3779b9
748+
749+/* The most generic version, hashes an arbitrary sequence
750+ * of bytes. No alignment or length assumptions are made about
751+ * the input key.
752+ */
753+static inline __u32 jhash(void *key, __u32 length, __u32 initval)
754+{
755+ __u32 a, b, c, len;
756+ __u8 *k = key;
757+
758+ len = length;
759+ a = b = JHASH_GOLDEN_RATIO;
760+ c = initval;
761+
762+ while (len >= 12) {
763+ a += (k[0] +((__u32)k[1]<<8) +((__u32)k[2]<<16) +((__u32)k[3]<<24));
764+ b += (k[4] +((__u32)k[5]<<8) +((__u32)k[6]<<16) +((__u32)k[7]<<24));
765+ c += (k[8] +((__u32)k[9]<<8) +((__u32)k[10]<<16)+((__u32)k[11]<<24));
766+
767+ __jhash_mix(a,b,c);
768+
769+ k += 12;
770+ len -= 12;
771+ }
772+
773+ c += length;
774+ switch (len) {
775+ case 11: c += ((__u32)k[10]<<24);
776+ case 10: c += ((__u32)k[9]<<16);
777+ case 9 : c += ((__u32)k[8]<<8);
778+ case 8 : b += ((__u32)k[7]<<24);
779+ case 7 : b += ((__u32)k[6]<<16);
780+ case 6 : b += ((__u32)k[5]<<8);
781+ case 5 : b += k[4];
782+ case 4 : a += ((__u32)k[3]<<24);
783+ case 3 : a += ((__u32)k[2]<<16);
784+ case 2 : a += ((__u32)k[1]<<8);
785+ case 1 : a += k[0];
786+ };
787+
788+ __jhash_mix(a,b,c);
789+
790+ return c;
791+}
792+
793+/* A special optimized version that handles 1 or more of __u32s.
794+ * The length parameter here is the number of __u32s in the key.
795+ */
796+static inline __u32 jhash2(__u32 *k, __u32 length, __u32 initval)
797+{
798+ __u32 a, b, c, len;
799+
800+ a = b = JHASH_GOLDEN_RATIO;
801+ c = initval;
802+ len = length;
803+
804+ while (len >= 3) {
805+ a += k[0];
806+ b += k[1];
807+ c += k[2];
808+ __jhash_mix(a, b, c);
809+ k += 3; len -= 3;
810+ }
811+
812+ c += length * 4;
813+
814+ switch (len) {
815+ case 2 : b += k[1];
816+ case 1 : a += k[0];
817+ };
818+
819+ __jhash_mix(a,b,c);
820+
821+ return c;
822+}
823+
824+
825+/* A special ultra-optimized versions that knows they are hashing exactly
826+ * 3, 2 or 1 word(s).
827+ *
828+ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
829+ * done at the end is not done here.
830+ */
831+static inline __u32 jhash_3words(__u32 a, __u32 b, __u32 c, __u32 initval)
832+{
833+ a += JHASH_GOLDEN_RATIO;
834+ b += JHASH_GOLDEN_RATIO;
835+ c += initval;
836+
837+ __jhash_mix(a, b, c);
838+
839+ return c;
840+}
841+
842+static inline __u32 jhash_2words(__u32 a, __u32 b, __u32 initval)
843+{
844+ return jhash_3words(a, b, 0, initval);
845+}
846+
847+static inline __u32 jhash_1word(__u32 a, __u32 initval)
848+{
849+ return jhash_3words(a, 0, 0, initval);
850+}
851+
852+#endif /* _LINUX_IPSET_JHASH_H */
853diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_macipmap.h linux/include/linux/netfilter_ipv4/ip_set_macipmap.h
854--- linux.org/include/linux/netfilter_ipv4/ip_set_macipmap.h 1970-01-01 01:00:00.000000000 +0100
855+++ linux/include/linux/netfilter_ipv4/ip_set_macipmap.h 2006-05-04 10:26:33.000000000 +0200
856@@ -0,0 +1,38 @@
857+#ifndef __IP_SET_MACIPMAP_H
858+#define __IP_SET_MACIPMAP_H
859+
860+#include <linux/netfilter_ipv4/ip_set.h>
861+
862+#define SETTYPE_NAME "macipmap"
863+#define MAX_RANGE 0x0000FFFF
864+
865+/* general flags */
866+#define IPSET_MACIP_MATCHUNSET 1
867+
868+/* per ip flags */
869+#define IPSET_MACIP_ISSET 1
870+
871+struct ip_set_macipmap {
872+ void *members; /* the macipmap proper */
873+ ip_set_ip_t first_ip; /* host byte order, included in range */
874+ ip_set_ip_t last_ip; /* host byte order, included in range */
875+ u_int32_t flags;
876+};
877+
878+struct ip_set_req_macipmap_create {
879+ ip_set_ip_t from;
880+ ip_set_ip_t to;
881+ u_int32_t flags;
882+};
883+
884+struct ip_set_req_macipmap {
885+ ip_set_ip_t ip;
886+ unsigned char ethernet[ETH_ALEN];
887+};
888+
889+struct ip_set_macip {
890+ unsigned short flags;
891+ unsigned char ethernet[ETH_ALEN];
892+};
893+
894+#endif /* __IP_SET_MACIPMAP_H */
895diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_malloc.h linux/include/linux/netfilter_ipv4/ip_set_malloc.h
896--- linux.org/include/linux/netfilter_ipv4/ip_set_malloc.h 1970-01-01 01:00:00.000000000 +0100
897+++ linux/include/linux/netfilter_ipv4/ip_set_malloc.h 2006-05-04 10:26:33.000000000 +0200
898@@ -0,0 +1,116 @@
899+#ifndef _IP_SET_MALLOC_H
900+#define _IP_SET_MALLOC_H
901+
902+#ifdef __KERNEL__
903+
904+/* Memory allocation and deallocation */
905+static size_t max_malloc_size = 0;
906+
907+static inline void init_max_malloc_size(void)
908+{
909+#define CACHE(x) max_malloc_size = x;
910+#include <linux/kmalloc_sizes.h>
911+#undef CACHE
912+}
913+
914+static inline void * ip_set_malloc(size_t bytes)
915+{
916+ if (bytes > max_malloc_size)
917+ return vmalloc(bytes);
918+ else
919+ return kmalloc(bytes, GFP_KERNEL);
920+}
921+
922+static inline void ip_set_free(void * data, size_t bytes)
923+{
924+ if (bytes > max_malloc_size)
925+ vfree(data);
926+ else
927+ kfree(data);
928+}
929+
930+struct harray {
931+ size_t max_elements;
932+ void *arrays[0];
933+};
934+
935+static inline void *
936+harray_malloc(size_t hashsize, size_t typesize, int flags)
937+{
938+ struct harray *harray;
939+ size_t max_elements, size, i, j;
940+
941+ if (!max_malloc_size)
942+ init_max_malloc_size();
943+
944+ if (typesize > max_malloc_size)
945+ return NULL;
946+
947+ max_elements = max_malloc_size/typesize;
948+ size = hashsize/max_elements;
949+ if (hashsize % max_elements)
950+ size++;
951+
952+ /* Last pointer signals end of arrays */
953+ harray = kmalloc(sizeof(struct harray) + (size + 1) * sizeof(void *),
954+ flags);
955+
956+ if (!harray)
957+ return NULL;
958+
959+ for (i = 0; i < size - 1; i++) {
960+ harray->arrays[i] = kmalloc(max_elements * typesize, flags);
961+ if (!harray->arrays[i])
962+ goto undo;
963+ memset(harray->arrays[i], 0, max_elements * typesize);
964+ }
965+ harray->arrays[i] = kmalloc((hashsize - i * max_elements) * typesize,
966+ flags);
967+ if (!harray->arrays[i])
968+ goto undo;
969+ memset(harray->arrays[i], 0, (hashsize - i * max_elements) * typesize);
970+
971+ harray->max_elements = max_elements;
972+ harray->arrays[size] = NULL;
973+
974+ return (void *)harray;
975+
976+ undo:
977+ for (j = 0; j < i; j++) {
978+ kfree(harray->arrays[j]);
979+ }
980+ kfree(harray);
981+ return NULL;
982+}
983+
984+static inline void harray_free(void *h)
985+{
986+ struct harray *harray = (struct harray *) h;
987+ size_t i;
988+
989+ for (i = 0; harray->arrays[i] != NULL; i++)
990+ kfree(harray->arrays[i]);
991+ kfree(harray);
992+}
993+
994+static inline void harray_flush(void *h, size_t hashsize, size_t typesize)
995+{
996+ struct harray *harray = (struct harray *) h;
997+ size_t i;
998+
999+ for (i = 0; harray->arrays[i+1] != NULL; i++)
1000+ memset(harray->arrays[i], 0, harray->max_elements * typesize);
1001+ memset(harray->arrays[i], 0,
1002+ (hashsize - i * harray->max_elements) * typesize);
1003+}
1004+
1005+#define HARRAY_ELEM(h, type, which) \
1006+({ \
1007+ struct harray *__h = (struct harray *)(h); \
1008+ ((type)((__h)->arrays[(which)/(__h)->max_elements]) \
1009+ + (which)%(__h)->max_elements); \
1010+})
1011+
1012+#endif /* __KERNEL__ */
1013+
1014+#endif /*_IP_SET_MALLOC_H*/
1015diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_nethash.h linux/include/linux/netfilter_ipv4/ip_set_nethash.h
1016--- linux.org/include/linux/netfilter_ipv4/ip_set_nethash.h 1970-01-01 01:00:00.000000000 +0100
1017+++ linux/include/linux/netfilter_ipv4/ip_set_nethash.h 2006-05-04 10:26:33.000000000 +0200
1018@@ -0,0 +1,54 @@
1019+#ifndef __IP_SET_NETHASH_H
1020+#define __IP_SET_NETHASH_H
1021+
1022+#include <linux/netfilter_ipv4/ip_set.h>
1023+
1024+#define SETTYPE_NAME "nethash"
1025+#define MAX_RANGE 0x0000FFFF
1026+
1027+struct ip_set_nethash {
1028+ ip_set_ip_t *members; /* the nethash proper */
1029+ uint32_t hashsize; /* hash size */
1030+ uint16_t probes; /* max number of probes */
1031+ uint16_t resize; /* resize factor in percent */
1032+ unsigned char cidr[30]; /* CIDR sizes */
1033+ void *initval[0]; /* initvals for jhash_1word */
1034+};
1035+
1036+struct ip_set_req_nethash_create {
1037+ uint32_t hashsize;
1038+ uint16_t probes;
1039+ uint16_t resize;
1040+};
1041+
1042+struct ip_set_req_nethash {
1043+ ip_set_ip_t ip;
1044+ unsigned char cidr;
1045+};
1046+
1047+static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};
1048+
1049+static inline ip_set_ip_t
1050+pack(ip_set_ip_t ip, unsigned char cidr)
1051+{
1052+ ip_set_ip_t addr, *paddr = &addr;
1053+ unsigned char n, t, *a;
1054+
1055+ addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
1056+#ifdef __KERNEL__
1057+ DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
1058+#endif
1059+ n = cidr / 8;
1060+ t = cidr % 8;
1061+ a = &((unsigned char *)paddr)[n];
1062+ *a = *a /(1 << (8 - t)) + shifts[t];
1063+#ifdef __KERNEL__
1064+ DP("n: %u, t: %u, a: %u", n, t, *a);
1065+ DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
1066+ HIPQUAD(ip), cidr, NIPQUAD(addr));
1067+#endif
1068+
1069+ return ntohl(addr);
1070+}
1071+
1072+#endif /* __IP_SET_NETHASH_H */
1073diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ip_set_portmap.h linux/include/linux/netfilter_ipv4/ip_set_portmap.h
1074--- linux.org/include/linux/netfilter_ipv4/ip_set_portmap.h 1970-01-01 01:00:00.000000000 +0100
1075+++ linux/include/linux/netfilter_ipv4/ip_set_portmap.h 2006-05-04 10:26:33.000000000 +0200
1076@@ -0,0 +1,25 @@
1077+#ifndef __IP_SET_PORTMAP_H
1078+#define __IP_SET_PORTMAP_H
1079+
1080+#include <linux/netfilter_ipv4/ip_set.h>
1081+
1082+#define SETTYPE_NAME "portmap"
1083+#define MAX_RANGE 0x0000FFFF
1084+#define INVALID_PORT (MAX_RANGE + 1)
1085+
1086+struct ip_set_portmap {
1087+ void *members; /* the portmap proper */
1088+ ip_set_ip_t first_port; /* host byte order, included in range */
1089+ ip_set_ip_t last_port; /* host byte order, included in range */
1090+};
1091+
1092+struct ip_set_req_portmap_create {
1093+ ip_set_ip_t from;
1094+ ip_set_ip_t to;
1095+};
1096+
1097+struct ip_set_req_portmap {
1098+ ip_set_ip_t port;
1099+};
1100+
1101+#endif /* __IP_SET_PORTMAP_H */
1102diff -Nur --exclude '*.orig' linux.org/include/linux/netfilter_ipv4/ipt_set.h linux/include/linux/netfilter_ipv4/ipt_set.h
1103--- linux.org/include/linux/netfilter_ipv4/ipt_set.h 1970-01-01 01:00:00.000000000 +0100
1104+++ linux/include/linux/netfilter_ipv4/ipt_set.h 2006-05-04 10:26:33.000000000 +0200
1105@@ -0,0 +1,21 @@
1106+#ifndef _IPT_SET_H
1107+#define _IPT_SET_H
1108+
1109+#include <linux/netfilter_ipv4/ip_set.h>
1110+
1111+struct ipt_set_info {
1112+ ip_set_id_t index;
1113+ u_int32_t flags[IP_SET_MAX_BINDINGS + 1];
1114+};
1115+
1116+/* match info */
1117+struct ipt_set_info_match {
1118+ struct ipt_set_info match_set;
1119+};
1120+
1121+struct ipt_set_info_target {
1122+ struct ipt_set_info add_set;
1123+ struct ipt_set_info del_set;
1124+};
1125+
1126+#endif /*_IPT_SET_H*/
1127diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Kconfig linux/net/ipv4/netfilter/Kconfig
1128--- linux.org/net/ipv4/netfilter/Kconfig 2006-05-02 23:38:44.000000000 +0200
1129+++ linux/net/ipv4/netfilter/Kconfig 2006-05-04 10:26:33.000000000 +0200
1130@@ -606,5 +606,114 @@
1131 Allows altering the ARP packet payload: source and destination
1132 hardware and network addresses.
1133
1134+config IP_NF_SET
1135+ tristate "IP set support"
1136+ depends on INET && NETFILTER
1137+ help
1138+ This option adds IP set support to the kernel.
1139+ In order to define and use sets, you need the userspace utility
1140+ ipset(8).
1141+
1142+ To compile it as a module, choose M here. If unsure, say N.
1143+
1144+config IP_NF_SET_MAX
1145+ int "Maximum number of IP sets"
1146+ default 256
1147+ range 2 65534
1148+ depends on IP_NF_SET
1149+ help
1150+ You can define here default value of the maximum number
1151+ of IP sets for the kernel.
1152+
1153+ The value can be overriden by the 'max_sets' module
1154+ parameter of the 'ip_set' module.
1155+
1156+config IP_NF_SET_HASHSIZE
1157+ int "Hash size for bindings of IP sets"
1158+ default 1024
1159+ depends on IP_NF_SET
1160+ help
1161+ You can define here default value of the hash size for
1162+ bindings of IP sets.
1163+
1164+ The value can be overriden by the 'hash_size' module
1165+ parameter of the 'ip_set' module.
1166+
1167+config IP_NF_SET_IPMAP
1168+ tristate "ipmap set support"
1169+ depends on IP_NF_SET
1170+ help
1171+ This option adds the ipmap set type support.
1172+
1173+ To compile it as a module, choose M here. If unsure, say N.
1174+
1175+config IP_NF_SET_MACIPMAP
1176+ tristate "macipmap set support"
1177+ depends on IP_NF_SET
1178+ help
1179+ This option adds the macipmap set type support.
1180+
1181+ To compile it as a module, choose M here. If unsure, say N.
1182+
1183+config IP_NF_SET_PORTMAP
1184+ tristate "portmap set support"
1185+ depends on IP_NF_SET
1186+ help
1187+ This option adds the portmap set type support.
1188+
1189+ To compile it as a module, choose M here. If unsure, say N.
1190+
1191+config IP_NF_SET_IPHASH
1192+ tristate "iphash set support"
1193+ depends on IP_NF_SET
1194+ help
1195+ This option adds the iphash set type support.
1196+
1197+ To compile it as a module, choose M here. If unsure, say N.
1198+
1199+config IP_NF_SET_NETHASH
1200+ tristate "nethash set support"
1201+ depends on IP_NF_SET
1202+ help
1203+ This option adds the nethash set type support.
1204+
1205+ To compile it as a module, choose M here. If unsure, say N.
1206+
1207+config IP_NF_SET_IPPORTHASH
1208+ tristate "ipporthash set support"
1209+ depends on IP_NF_SET
1210+ help
1211+ This option adds the ipporthash set type support.
1212+
1213+ To compile it as a module, choose M here. If unsure, say N.
1214+
1215+config IP_NF_SET_IPTREE
1216+ tristate "iptree set support"
1217+ depends on IP_NF_SET
1218+ help
1219+ This option adds the iptree set type support.
1220+
1221+ To compile it as a module, choose M here. If unsure, say N.
1222+
1223+config IP_NF_MATCH_SET
1224+ tristate "set match support"
1225+ depends on IP_NF_SET
1226+ help
1227+ Set matching matches against given IP sets.
1228+ You need the ipset utility to create and set up the sets.
1229+
1230+ To compile it as a module, choose M here. If unsure, say N.
1231+
1232+config IP_NF_TARGET_SET
1233+ tristate "SET target support"
1234+ depends on IP_NF_SET
1235+ help
1236+ The SET target makes possible to add/delete entries
1237+ in IP sets.
1238+ You need the ipset utility to create and set up the sets.
1239+
1240+ To compile it as a module, choose M here. If unsure, say N.
1241+
1242+
1243 endmenu
1244
1245diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/Makefile linux/net/ipv4/netfilter/Makefile
1246--- linux.org/net/ipv4/netfilter/Makefile 2006-05-02 23:38:44.000000000 +0200
1247+++ linux/net/ipv4/netfilter/Makefile 2006-05-04 10:26:33.000000000 +0200
1248@@ -0,0 +0,12 @@
1249+obj-$(CONFIG_IP_NF_MATCH_SET) += ipt_set.o
1250+obj-$(CONFIG_IP_NF_TARGET_SET) += ipt_SET.o
1251+
1252+# sets
1253+obj-$(CONFIG_IP_NF_SET) += ip_set.o
1254+obj-$(CONFIG_IP_NF_SET_IPMAP) += ip_set_ipmap.o
1255+obj-$(CONFIG_IP_NF_SET_PORTMAP) += ip_set_portmap.o
1256+obj-$(CONFIG_IP_NF_SET_MACIPMAP) += ip_set_macipmap.o
1257+obj-$(CONFIG_IP_NF_SET_IPHASH) += ip_set_iphash.o
1258+obj-$(CONFIG_IP_NF_SET_NETHASH) += ip_set_nethash.o
1259+obj-$(CONFIG_IP_NF_SET_IPPORTHASH) += ip_set_ipporthash.o
1260+obj-$(CONFIG_IP_NF_SET_IPTREE) += ip_set_iptree.o
1261diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set.c linux/net/ipv4/netfilter/ip_set.c
1262--- linux.org/net/ipv4/netfilter/ip_set.c 1970-01-01 01:00:00.000000000 +0100
1263+++ linux/net/ipv4/netfilter/ip_set.c 2006-05-04 10:26:33.000000000 +0200
1264@@ -0,0 +1,1992 @@
1265+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
1266+ * Patrick Schaaf <bof@bof.de>
1267+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
1268+ *
1269+ * This program is free software; you can redistribute it and/or modify
1270+ * it under the terms of the GNU General Public License version 2 as
1271+ * published by the Free Software Foundation.
1272+ */
1273+
1274+/* Kernel module for IP set management */
1275+
1276+#include <linux/config.h>
1277+#include <linux/module.h>
1278+#include <linux/moduleparam.h>
1279+#include <linux/kmod.h>
1280+#include <linux/ip.h>
1281+#include <linux/skbuff.h>
1282+#include <linux/random.h>
1283+#include <linux/jhash.h>
1284+#include <linux/netfilter_ipv4/ip_tables.h>
1285+#include <linux/errno.h>
1286+#include <asm/uaccess.h>
1287+#include <asm/bitops.h>
1288+#include <asm/semaphore.h>
1289+#include <linux/spinlock.h>
1290+#include <linux/vmalloc.h>
1291+
1292+#define ASSERT_READ_LOCK(x) /* dont use that */
1293+#define ASSERT_WRITE_LOCK(x)
1294+#include <linux/netfilter_ipv4/listhelp.h>
1295+#include <linux/netfilter_ipv4/ip_set.h>
1296+
1297+static struct list_head set_type_list; /* all registered sets */
1298+static struct ip_set **ip_set_list; /* all individual sets */
1299+static DEFINE_RWLOCK(ip_set_lock); /* protects the lists and the hash */
1300+static DECLARE_MUTEX(ip_set_app_mutex); /* serializes user access */
1301+static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
1302+static ip_set_id_t ip_set_bindings_hash_size = CONFIG_IP_NF_SET_HASHSIZE;
1303+static struct list_head *ip_set_hash; /* hash of bindings */
1304+static unsigned int ip_set_hash_random; /* random seed */
1305+
1306+/*
1307+ * Sets are identified either by the index in ip_set_list or by id.
1308+ * The id never changes and is used to find a key in the hash.
1309+ * The index may change by swapping and used at all other places
1310+ * (set/SET netfilter modules, binding value, etc.)
1311+ *
1312+ * Userspace requests are serialized by ip_set_mutex and sets can
1313+ * be deleted only from userspace. Therefore ip_set_list locking
1314+ * must obey the following rules:
1315+ *
1316+ * - kernel requests: read and write locking mandatory
1317+ * - user requests: read locking optional, write locking mandatory
1318+ */
1319+
1320+static inline void
1321+__ip_set_get(ip_set_id_t index)
1322+{
1323+ atomic_inc(&ip_set_list[index]->ref);
1324+}
1325+
1326+static inline void
1327+__ip_set_put(ip_set_id_t index)
1328+{
1329+ atomic_dec(&ip_set_list[index]->ref);
1330+}
1331+
1332+/*
1333+ * Binding routines
1334+ */
1335+
1336+static inline int
1337+ip_hash_cmp(const struct ip_set_hash *set_hash,
1338+ ip_set_id_t id, ip_set_ip_t ip)
1339+{
1340+ return set_hash->id == id && set_hash->ip == ip;
1341+}
1342+
1343+static ip_set_id_t
1344+ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip)
1345+{
1346+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
1347+ % ip_set_bindings_hash_size;
1348+ struct ip_set_hash *set_hash;
1349+
1350+ ASSERT_READ_LOCK(&ip_set_lock);
1351+ IP_SET_ASSERT(ip_set_list[id]);
1352+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
1353+
1354+ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
1355+ struct ip_set_hash *, id, ip);
1356+
1357+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
1358+ HIPQUAD(ip),
1359+ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
1360+
1361+ return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
1362+}
1363+
1364+static inline void
1365+__set_hash_del(struct ip_set_hash *set_hash)
1366+{
1367+ ASSERT_WRITE_LOCK(&ip_set_lock);
1368+ IP_SET_ASSERT(ip_set_list[set_hash->binding]);
1369+
1370+ __ip_set_put(set_hash->binding);
1371+ list_del(&set_hash->list);
1372+ kfree(set_hash);
1373+}
1374+
1375+static int
1376+ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip)
1377+{
1378+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
1379+ % ip_set_bindings_hash_size;
1380+ struct ip_set_hash *set_hash;
1381+
1382+ IP_SET_ASSERT(ip_set_list[id]);
1383+ DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));
1384+ write_lock_bh(&ip_set_lock);
1385+ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
1386+ struct ip_set_hash *, id, ip);
1387+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
1388+ HIPQUAD(ip),
1389+ set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
1390+
1391+ if (set_hash != NULL)
1392+ __set_hash_del(set_hash);
1393+ write_unlock_bh(&ip_set_lock);
1394+ return 0;
1395+}
1396+
1397+static int
1398+ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding)
1399+{
1400+ u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
1401+ % ip_set_bindings_hash_size;
1402+ struct ip_set_hash *set_hash;
1403+ int ret = 0;
1404+
1405+ IP_SET_ASSERT(ip_set_list[id]);
1406+ IP_SET_ASSERT(ip_set_list[binding]);
1407+ DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
1408+ HIPQUAD(ip), ip_set_list[binding]->name);
1409+ write_lock_bh(&ip_set_lock);
1410+ set_hash = LIST_FIND(&ip_set_hash[key], ip_hash_cmp,
1411+ struct ip_set_hash *, id, ip);
1412+ if (!set_hash) {
1413+ set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_KERNEL);
1414+ if (!set_hash) {
1415+ ret = -ENOMEM;
1416+ goto unlock;
1417+ }
1418+ INIT_LIST_HEAD(&set_hash->list);
1419+ set_hash->id = id;
1420+ set_hash->ip = ip;
1421+ list_add(&ip_set_hash[key], &set_hash->list);
1422+ } else {
1423+ IP_SET_ASSERT(ip_set_list[set_hash->binding]);
1424+ DP("overwrite binding: %s",
1425+ ip_set_list[set_hash->binding]->name);
1426+ __ip_set_put(set_hash->binding);
1427+ }
1428+ set_hash->binding = binding;
1429+ __ip_set_get(set_hash->binding);
1430+ unlock:
1431+ write_unlock_bh(&ip_set_lock);
1432+ return ret;
1433+}
1434+
1435+#define FOREACH_HASH_DO(fn, args...) \
1436+({ \
1437+ ip_set_id_t __key; \
1438+ struct ip_set_hash *__set_hash; \
1439+ \
1440+ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \
1441+ list_for_each_entry(__set_hash, &ip_set_hash[__key], list) \
1442+ fn(__set_hash , ## args); \
1443+ } \
1444+})
1445+
1446+#define FOREACH_HASH_RW_DO(fn, args...) \
1447+({ \
1448+ ip_set_id_t __key; \
1449+ struct ip_set_hash *__set_hash, *__n; \
1450+ \
1451+ ASSERT_WRITE_LOCK(&ip_set_lock); \
1452+ for (__key = 0; __key < ip_set_bindings_hash_size; __key++) { \
1453+ list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\
1454+ fn(__set_hash , ## args); \
1455+ } \
1456+})
1457+
1458+/* Add, del and test set entries from kernel */
1459+
1460+#define follow_bindings(index, set, ip) \
1461+((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID \
1462+ || (index = (set)->binding) != IP_SET_INVALID_ID)
1463+
1464+int
1465+ip_set_testip_kernel(ip_set_id_t index,
1466+ const struct sk_buff *skb,
1467+ const u_int32_t *flags)
1468+{
1469+ struct ip_set *set;
1470+ ip_set_ip_t ip;
1471+ int res;
1472+ unsigned char i = 0;
1473+
1474+ IP_SET_ASSERT(flags[i]);
1475+ read_lock_bh(&ip_set_lock);
1476+ do {
1477+ set = ip_set_list[index];
1478+ IP_SET_ASSERT(set);
1479+ DP("set %s, index %u", set->name, index);
1480+ read_lock_bh(&set->lock);
1481+ res = set->type->testip_kernel(set, skb, &ip, flags, i++);
1482+ read_unlock_bh(&set->lock);
1483+ i += !!(set->type->features & IPSET_DATA_DOUBLE);
1484+ } while (res > 0
1485+ && flags[i]
1486+ && follow_bindings(index, set, ip));
1487+ read_unlock_bh(&ip_set_lock);
1488+
1489+ return res;
1490+}
1491+
1492+void
1493+ip_set_addip_kernel(ip_set_id_t index,
1494+ const struct sk_buff *skb,
1495+ const u_int32_t *flags)
1496+{
1497+ struct ip_set *set;
1498+ ip_set_ip_t ip;
1499+ int res;
1500+ unsigned char i = 0;
1501+
1502+ IP_SET_ASSERT(flags[i]);
1503+ retry:
1504+ read_lock_bh(&ip_set_lock);
1505+ do {
1506+ set = ip_set_list[index];
1507+ IP_SET_ASSERT(set);
1508+ DP("set %s, index %u", set->name, index);
1509+ write_lock_bh(&set->lock);
1510+ res = set->type->addip_kernel(set, skb, &ip, flags, i++);
1511+ write_unlock_bh(&set->lock);
1512+ i += !!(set->type->features & IPSET_DATA_DOUBLE);
1513+ } while ((res == 0 || res == -EEXIST)
1514+ && flags[i]
1515+ && follow_bindings(index, set, ip));
1516+ read_unlock_bh(&ip_set_lock);
1517+
1518+ if (res == -EAGAIN
1519+ && set->type->retry
1520+ && (res = set->type->retry(set)) == 0)
1521+ goto retry;
1522+}
1523+
1524+void
1525+ip_set_delip_kernel(ip_set_id_t index,
1526+ const struct sk_buff *skb,
1527+ const u_int32_t *flags)
1528+{
1529+ struct ip_set *set;
1530+ ip_set_ip_t ip;
1531+ int res;
1532+ unsigned char i = 0;
1533+
1534+ IP_SET_ASSERT(flags[i]);
1535+ read_lock_bh(&ip_set_lock);
1536+ do {
1537+ set = ip_set_list[index];
1538+ IP_SET_ASSERT(set);
1539+ DP("set %s, index %u", set->name, index);
1540+ write_lock_bh(&set->lock);
1541+ res = set->type->delip_kernel(set, skb, &ip, flags, i++);
1542+ write_unlock_bh(&set->lock);
1543+ i += !!(set->type->features & IPSET_DATA_DOUBLE);
1544+ } while ((res == 0 || res == -EEXIST)
1545+ && flags[i]
1546+ && follow_bindings(index, set, ip));
1547+ read_unlock_bh(&ip_set_lock);
1548+}
1549+
1550+/* Register and deregister settype */
1551+
1552+static inline int
1553+set_type_equal(const struct ip_set_type *set_type, const char *str2)
1554+{
1555+ return !strncmp(set_type->typename, str2, IP_SET_MAXNAMELEN - 1);
1556+}
1557+
1558+static inline struct ip_set_type *
1559+find_set_type(const char *name)
1560+{
1561+ return LIST_FIND(&set_type_list,
1562+ set_type_equal,
1563+ struct ip_set_type *,
1564+ name);
1565+}
1566+
1567+int
1568+ip_set_register_set_type(struct ip_set_type *set_type)
1569+{
1570+ int ret = 0;
1571+
1572+ if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
1573+ ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
1574+ set_type->typename,
1575+ set_type->protocol_version,
1576+ IP_SET_PROTOCOL_VERSION);
1577+ return -EINVAL;
1578+ }
1579+
1580+ write_lock_bh(&ip_set_lock);
1581+ if (find_set_type(set_type->typename)) {
1582+ /* Duplicate! */
1583+ ip_set_printk("'%s' already registered!",
1584+ set_type->typename);
1585+ ret = -EINVAL;
1586+ goto unlock;
1587+ }
1588+ if (!try_module_get(THIS_MODULE)) {
1589+ ret = -EFAULT;
1590+ goto unlock;
1591+ }
1592+ list_append(&set_type_list, set_type);
1593+ DP("'%s' registered.", set_type->typename);
1594+ unlock:
1595+ write_unlock_bh(&ip_set_lock);
1596+ return ret;
1597+}
1598+
1599+void
1600+ip_set_unregister_set_type(struct ip_set_type *set_type)
1601+{
1602+ write_lock_bh(&ip_set_lock);
1603+ if (!find_set_type(set_type->typename)) {
1604+ ip_set_printk("'%s' not registered?",
1605+ set_type->typename);
1606+ goto unlock;
1607+ }
1608+ LIST_DELETE(&set_type_list, set_type);
1609+ module_put(THIS_MODULE);
1610+ DP("'%s' unregistered.", set_type->typename);
1611+ unlock:
1612+ write_unlock_bh(&ip_set_lock);
1613+
1614+}
1615+
1616+/*
1617+ * Userspace routines
1618+ */
1619+
1620+/*
1621+ * Find set by name, reference it once. The reference makes sure the
1622+ * thing pointed to, does not go away under our feet. Drop the reference
1623+ * later, using ip_set_put().
1624+ */
1625+ip_set_id_t
1626+ip_set_get_byname(const char *name)
1627+{
1628+ ip_set_id_t i, index = IP_SET_INVALID_ID;
1629+
1630+ down(&ip_set_app_mutex);
1631+ for (i = 0; i < ip_set_max; i++) {
1632+ if (ip_set_list[i] != NULL
1633+ && strcmp(ip_set_list[i]->name, name) == 0) {
1634+ __ip_set_get(i);
1635+ index = i;
1636+ break;
1637+ }
1638+ }
1639+ up(&ip_set_app_mutex);
1640+ return index;
1641+}
1642+
1643+/*
1644+ * Find set by index, reference it once. The reference makes sure the
1645+ * thing pointed to, does not go away under our feet. Drop the reference
1646+ * later, using ip_set_put().
1647+ */
1648+ip_set_id_t
1649+ip_set_get_byindex(ip_set_id_t index)
1650+{
1651+ down(&ip_set_app_mutex);
1652+
1653+ if (index >= ip_set_max)
1654+ return IP_SET_INVALID_ID;
1655+
1656+ if (ip_set_list[index])
1657+ __ip_set_get(index);
1658+ else
1659+ index = IP_SET_INVALID_ID;
1660+
1661+ up(&ip_set_app_mutex);
1662+ return index;
1663+}
1664+
1665+/*
1666+ * If the given set pointer points to a valid set, decrement
1667+ * reference count by 1. The caller shall not assume the index
1668+ * to be valid, after calling this function.
1669+ */
1670+void ip_set_put(ip_set_id_t index)
1671+{
1672+ down(&ip_set_app_mutex);
1673+ if (ip_set_list[index])
1674+ __ip_set_put(index);
1675+ up(&ip_set_app_mutex);
1676+}
1677+
1678+/* Find a set by name or index */
1679+static ip_set_id_t
1680+ip_set_find_byname(const char *name)
1681+{
1682+ ip_set_id_t i, index = IP_SET_INVALID_ID;
1683+
1684+ for (i = 0; i < ip_set_max; i++) {
1685+ if (ip_set_list[i] != NULL
1686+ && strcmp(ip_set_list[i]->name, name) == 0) {
1687+ index = i;
1688+ break;
1689+ }
1690+ }
1691+ return index;
1692+}
1693+
1694+static ip_set_id_t
1695+ip_set_find_byindex(ip_set_id_t index)
1696+{
1697+ if (index >= ip_set_max || ip_set_list[index] == NULL)
1698+ index = IP_SET_INVALID_ID;
1699+
1700+ return index;
1701+}
1702+
1703+/*
1704+ * Add, del, test, bind and unbind
1705+ */
1706+
1707+static inline int
1708+__ip_set_testip(struct ip_set *set,
1709+ const void *data,
1710+ size_t size,
1711+ ip_set_ip_t *ip)
1712+{
1713+ int res;
1714+
1715+ read_lock_bh(&set->lock);
1716+ res = set->type->testip(set, data, size, ip);
1717+ read_unlock_bh(&set->lock);
1718+
1719+ return res;
1720+}
1721+
1722+static int
1723+__ip_set_addip(ip_set_id_t index,
1724+ const void *data,
1725+ size_t size)
1726+{
1727+ struct ip_set *set = ip_set_list[index];
1728+ ip_set_ip_t ip;
1729+ int res;
1730+
1731+ IP_SET_ASSERT(set);
1732+ do {
1733+ write_lock_bh(&set->lock);
1734+ res = set->type->addip(set, data, size, &ip);
1735+ write_unlock_bh(&set->lock);
1736+ } while (res == -EAGAIN
1737+ && set->type->retry
1738+ && (res = set->type->retry(set)) == 0);
1739+
1740+ return res;
1741+}
1742+
1743+static int
1744+ip_set_addip(ip_set_id_t index,
1745+ const void *data,
1746+ size_t size)
1747+{
1748+
1749+ return __ip_set_addip(index,
1750+ data + sizeof(struct ip_set_req_adt),
1751+ size - sizeof(struct ip_set_req_adt));
1752+}
1753+
1754+static int
1755+ip_set_delip(ip_set_id_t index,
1756+ const void *data,
1757+ size_t size)
1758+{
1759+ struct ip_set *set = ip_set_list[index];
1760+ ip_set_ip_t ip;
1761+ int res;
1762+
1763+ IP_SET_ASSERT(set);
1764+ write_lock_bh(&set->lock);
1765+ res = set->type->delip(set,
1766+ data + sizeof(struct ip_set_req_adt),
1767+ size - sizeof(struct ip_set_req_adt),
1768+ &ip);
1769+ write_unlock_bh(&set->lock);
1770+
1771+ return res;
1772+}
1773+
1774+static int
1775+ip_set_testip(ip_set_id_t index,
1776+ const void *data,
1777+ size_t size)
1778+{
1779+ struct ip_set *set = ip_set_list[index];
1780+ ip_set_ip_t ip;
1781+ int res;
1782+
1783+ IP_SET_ASSERT(set);
1784+ res = __ip_set_testip(set,
1785+ data + sizeof(struct ip_set_req_adt),
1786+ size - sizeof(struct ip_set_req_adt),
1787+ &ip);
1788+
1789+ return (res > 0 ? -EEXIST : res);
1790+}
1791+
1792+static int
1793+ip_set_bindip(ip_set_id_t index,
1794+ const void *data,
1795+ size_t size)
1796+{
1797+ struct ip_set *set = ip_set_list[index];
1798+ struct ip_set_req_bind *req_bind;
1799+ ip_set_id_t binding;
1800+ ip_set_ip_t ip;
1801+ int res;
1802+
1803+ IP_SET_ASSERT(set);
1804+ if (size < sizeof(struct ip_set_req_bind))
1805+ return -EINVAL;
1806+
1807+ req_bind = (struct ip_set_req_bind *) data;
1808+ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
1809+
1810+ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
1811+ /* Default binding of a set */
1812+ char *binding_name;
1813+
1814+ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
1815+ return -EINVAL;
1816+
1817+ binding_name = (char *)(data + sizeof(struct ip_set_req_bind));
1818+ binding_name[IP_SET_MAXNAMELEN - 1] = '\0';
1819+
1820+ binding = ip_set_find_byname(binding_name);
1821+ if (binding == IP_SET_INVALID_ID)
1822+ return -ENOENT;
1823+
1824+ write_lock_bh(&ip_set_lock);
1825+ /* Sets as binding values are referenced */
1826+ if (set->binding != IP_SET_INVALID_ID)
1827+ __ip_set_put(set->binding);
1828+ set->binding = binding;
1829+ __ip_set_get(set->binding);
1830+ write_unlock_bh(&ip_set_lock);
1831+
1832+ return 0;
1833+ }
1834+ binding = ip_set_find_byname(req_bind->binding);
1835+ if (binding == IP_SET_INVALID_ID)
1836+ return -ENOENT;
1837+
1838+ res = __ip_set_testip(set,
1839+ data + sizeof(struct ip_set_req_bind),
1840+ size - sizeof(struct ip_set_req_bind),
1841+ &ip);
1842+ DP("set %s, ip: %u.%u.%u.%u, binding %s",
1843+ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
1844+
1845+ if (res >= 0)
1846+ res = ip_set_hash_add(set->id, ip, binding);
1847+
1848+ return res;
1849+}
1850+
1851+#define FOREACH_SET_DO(fn, args...) \
1852+({ \
1853+ ip_set_id_t __i; \
1854+ struct ip_set *__set; \
1855+ \
1856+ for (__i = 0; __i < ip_set_max; __i++) { \
1857+ __set = ip_set_list[__i]; \
1858+ if (__set != NULL) \
1859+ fn(__set , ##args); \
1860+ } \
1861+})
1862+
1863+static inline void
1864+__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id)
1865+{
1866+ if (set_hash->id == id)
1867+ __set_hash_del(set_hash);
1868+}
1869+
1870+static inline void
1871+__unbind_default(struct ip_set *set)
1872+{
1873+ if (set->binding != IP_SET_INVALID_ID) {
1874+ /* Sets as binding values are referenced */
1875+ __ip_set_put(set->binding);
1876+ set->binding = IP_SET_INVALID_ID;
1877+ }
1878+}
1879+
1880+static int
1881+ip_set_unbindip(ip_set_id_t index,
1882+ const void *data,
1883+ size_t size)
1884+{
1885+ struct ip_set *set;
1886+ struct ip_set_req_bind *req_bind;
1887+ ip_set_ip_t ip;
1888+ int res;
1889+
1890+ DP("");
1891+ if (size < sizeof(struct ip_set_req_bind))
1892+ return -EINVAL;
1893+
1894+ req_bind = (struct ip_set_req_bind *) data;
1895+ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
1896+
1897+ DP("%u %s", index, req_bind->binding);
1898+ if (index == IP_SET_INVALID_ID) {
1899+ /* unbind :all: */
1900+ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
1901+ /* Default binding of sets */
1902+ write_lock_bh(&ip_set_lock);
1903+ FOREACH_SET_DO(__unbind_default);
1904+ write_unlock_bh(&ip_set_lock);
1905+ return 0;
1906+ } else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
1907+ /* Flush all bindings of all sets*/
1908+ write_lock_bh(&ip_set_lock);
1909+ FOREACH_HASH_RW_DO(__set_hash_del);
1910+ write_unlock_bh(&ip_set_lock);
1911+ return 0;
1912+ }
1913+ DP("unreachable reached!");
1914+ return -EINVAL;
1915+ }
1916+
1917+ set = ip_set_list[index];
1918+ IP_SET_ASSERT(set);
1919+ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
1920+ /* Default binding of set */
1921+ ip_set_id_t binding = ip_set_find_byindex(set->binding);
1922+
1923+ if (binding == IP_SET_INVALID_ID)
1924+ return -ENOENT;
1925+
1926+ write_lock_bh(&ip_set_lock);
1927+ /* Sets in hash values are referenced */
1928+ __ip_set_put(set->binding);
1929+ set->binding = IP_SET_INVALID_ID;
1930+ write_unlock_bh(&ip_set_lock);
1931+
1932+ return 0;
1933+ } else if (strcmp(req_bind->binding, IPSET_TOKEN_ALL) == 0) {
1934+ /* Flush all bindings */
1935+
1936+ write_lock_bh(&ip_set_lock);
1937+ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
1938+ write_unlock_bh(&ip_set_lock);
1939+ return 0;
1940+ }
1941+
1942+ res = __ip_set_testip(set,
1943+ data + sizeof(struct ip_set_req_bind),
1944+ size - sizeof(struct ip_set_req_bind),
1945+ &ip);
1946+
1947+ DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
1948+ if (res >= 0)
1949+ res = ip_set_hash_del(set->id, ip);
1950+
1951+ return res;
1952+}
1953+
1954+static int
1955+ip_set_testbind(ip_set_id_t index,
1956+ const void *data,
1957+ size_t size)
1958+{
1959+ struct ip_set *set = ip_set_list[index];
1960+ struct ip_set_req_bind *req_bind;
1961+ ip_set_id_t binding;
1962+ ip_set_ip_t ip;
1963+ int res;
1964+
1965+ IP_SET_ASSERT(set);
1966+ if (size < sizeof(struct ip_set_req_bind))
1967+ return -EINVAL;
1968+
1969+ req_bind = (struct ip_set_req_bind *) data;
1970+ req_bind->binding[IP_SET_MAXNAMELEN - 1] = '\0';
1971+
1972+ if (strcmp(req_bind->binding, IPSET_TOKEN_DEFAULT) == 0) {
1973+ /* Default binding of set */
1974+ char *binding_name;
1975+
1976+ if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
1977+ return -EINVAL;
1978+
1979+ binding_name = (char *)(data + sizeof(struct ip_set_req_bind));
1980+ binding_name[IP_SET_MAXNAMELEN - 1] = '\0';
1981+
1982+ binding = ip_set_find_byname(binding_name);
1983+ if (binding == IP_SET_INVALID_ID)
1984+ return -ENOENT;
1985+
1986+ res = (set->binding == binding) ? -EEXIST : 0;
1987+
1988+ return res;
1989+ }
1990+ binding = ip_set_find_byname(req_bind->binding);
1991+ if (binding == IP_SET_INVALID_ID)
1992+ return -ENOENT;
1993+
1994+
1995+ res = __ip_set_testip(set,
1996+ data + sizeof(struct ip_set_req_bind),
1997+ size - sizeof(struct ip_set_req_bind),
1998+ &ip);
1999+ DP("set %s, ip: %u.%u.%u.%u, binding %s",
2000+ set->name, HIPQUAD(ip), ip_set_list[binding]->name);
2001+
2002+ if (res >= 0)
2003+ res = (ip_set_find_in_hash(set->id, ip) == binding)
2004+ ? -EEXIST : 0;
2005+
2006+ return res;
2007+}
2008+
2009+static struct ip_set_type *
2010+find_set_type_rlock(const char *typename)
2011+{
2012+ struct ip_set_type *type;
2013+
2014+ read_lock_bh(&ip_set_lock);
2015+ type = find_set_type(typename);
2016+ if (type == NULL)
2017+ read_unlock_bh(&ip_set_lock);
2018+
2019+ return type;
2020+}
2021+
2022+static int
2023+find_free_id(const char *name,
2024+ ip_set_id_t *index,
2025+ ip_set_id_t *id)
2026+{
2027+ ip_set_id_t i;
2028+
2029+ *id = IP_SET_INVALID_ID;
2030+ for (i = 0; i < ip_set_max; i++) {
2031+ if (ip_set_list[i] == NULL) {
2032+ if (*id == IP_SET_INVALID_ID)
2033+ *id = *index = i;
2034+ } else if (strcmp(name, ip_set_list[i]->name) == 0)
2035+ /* Name clash */
2036+ return -EEXIST;
2037+ }
2038+ if (*id == IP_SET_INVALID_ID)
2039+ /* No free slot remained */
2040+ return -ERANGE;
2041+ /* Check that index is usable as id (swapping) */
2042+ check:
2043+ for (i = 0; i < ip_set_max; i++) {
2044+ if (ip_set_list[i] != NULL
2045+ && ip_set_list[i]->id == *id) {
2046+ *id = i;
2047+ goto check;
2048+ }
2049+ }
2050+ return 0;
2051+}
2052+
2053+/*
2054+ * Create a set
2055+ */
2056+static int
2057+ip_set_create(const char *name,
2058+ const char *typename,
2059+ ip_set_id_t restore,
2060+ const void *data,
2061+ size_t size)
2062+{
2063+ struct ip_set *set;
2064+ ip_set_id_t index, id;
2065+ int res = 0;
2066+
2067+ DP("setname: %s, typename: %s, id: %u", name, typename, restore);
2068+ /*
2069+ * First, and without any locks, allocate and initialize
2070+ * a normal base set structure.
2071+ */
2072+ set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
2073+ if (!set)
2074+ return -ENOMEM;
2075+ set->lock = RW_LOCK_UNLOCKED;
2076+ strncpy(set->name, name, IP_SET_MAXNAMELEN);
2077+ set->binding = IP_SET_INVALID_ID;
2078+ atomic_set(&set->ref, 0);
2079+
2080+ /*
2081+ * Next, take the &ip_set_lock, check that we know the type,
2082+ * and take a reference on the type, to make sure it
2083+ * stays available while constructing our new set.
2084+ *
2085+ * After referencing the type, we drop the &ip_set_lock,
2086+ * and let the new set construction run without locks.
2087+ */
2088+ set->type = find_set_type_rlock(typename);
2089+ if (set->type == NULL) {
2090+ /* Try loading the module */
2091+ char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1];
2092+ strcpy(modulename, "ip_set_");
2093+ strcat(modulename, typename);
2094+ DP("try to load %s", modulename);
2095+ request_module(modulename);
2096+ set->type = find_set_type_rlock(typename);
2097+ }
2098+ if (set->type == NULL) {
2099+ ip_set_printk("no set type '%s', set '%s' not created",
2100+ typename, name);
2101+ res = -ENOENT;
2102+ goto out;
2103+ }
2104+ if (!try_module_get(set->type->me)) {
2105+ read_unlock_bh(&ip_set_lock);
2106+ res = -EFAULT;
2107+ goto out;
2108+ }
2109+ read_unlock_bh(&ip_set_lock);
2110+
2111+ /*
2112+ * Without holding any locks, create private part.
2113+ */
2114+ res = set->type->create(set, data, size);
2115+ if (res != 0)
2116+ goto put_out;
2117+
2118+ /* BTW, res==0 here. */
2119+
2120+ /*
2121+ * Here, we have a valid, constructed set. &ip_set_lock again,
2122+ * find free id/index and check that it is not already in
2123+ * ip_set_list.
2124+ */
2125+ write_lock_bh(&ip_set_lock);
2126+ if ((res = find_free_id(set->name, &index, &id)) != 0) {
2127+ DP("no free id!");
2128+ goto cleanup;
2129+ }
2130+
2131+ /* Make sure restore gets the same index */
2132+ if (restore != IP_SET_INVALID_ID && index != restore) {
2133+ DP("Can't restore, sets are screwed up");
2134+ res = -ERANGE;
2135+ goto cleanup;
2136+ }
2137+
2138+ /*
2139+ * Finally! Add our shiny new set to the list, and be done.
2140+ */
2141+ DP("create: '%s' created with index %u, id %u!", set->name, index, id);
2142+ set->id = id;
2143+ ip_set_list[index] = set;
2144+ write_unlock_bh(&ip_set_lock);
2145+ return res;
2146+
2147+ cleanup:
2148+ write_unlock_bh(&ip_set_lock);
2149+ set->type->destroy(set);
2150+ put_out:
2151+ module_put(set->type->me);
2152+ out:
2153+ kfree(set);
2154+ return res;
2155+}
2156+
2157+/*
2158+ * Destroy a given existing set
2159+ */
2160+static void
2161+ip_set_destroy_set(ip_set_id_t index)
2162+{
2163+ struct ip_set *set = ip_set_list[index];
2164+
2165+ IP_SET_ASSERT(set);
2166+ DP("set: %s", set->name);
2167+ write_lock_bh(&ip_set_lock);
2168+ FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
2169+ if (set->binding != IP_SET_INVALID_ID)
2170+ __ip_set_put(set->binding);
2171+ ip_set_list[index] = NULL;
2172+ write_unlock_bh(&ip_set_lock);
2173+
2174+ /* Must call it without holding any lock */
2175+ set->type->destroy(set);
2176+ module_put(set->type->me);
2177+ kfree(set);
2178+}
2179+
2180+/*
2181+ * Destroy a set - or all sets
2182+ * Sets must not be referenced/used.
2183+ */
2184+static int
2185+ip_set_destroy(ip_set_id_t index)
2186+{
2187+ ip_set_id_t i;
2188+
2189+ /* ref modification always protected by the mutex */
2190+ if (index != IP_SET_INVALID_ID) {
2191+ if (atomic_read(&ip_set_list[index]->ref))
2192+ return -EBUSY;
2193+ ip_set_destroy_set(index);
2194+ } else {
2195+ for (i = 0; i < ip_set_max; i++) {
2196+ if (ip_set_list[i] != NULL
2197+ && (atomic_read(&ip_set_list[i]->ref)))
2198+ return -EBUSY;
2199+ }
2200+
2201+ for (i = 0; i < ip_set_max; i++) {
2202+ if (ip_set_list[i] != NULL)
2203+ ip_set_destroy_set(i);
2204+ }
2205+ }
2206+ return 0;
2207+}
2208+
2209+static void
2210+ip_set_flush_set(struct ip_set *set)
2211+{
2212+ DP("set: %s %u", set->name, set->id);
2213+
2214+ write_lock_bh(&set->lock);
2215+ set->type->flush(set);
2216+ write_unlock_bh(&set->lock);
2217+}
2218+
2219+/*
2220+ * Flush data in a set - or in all sets
2221+ */
2222+static int
2223+ip_set_flush(ip_set_id_t index)
2224+{
2225+ if (index != IP_SET_INVALID_ID) {
2226+ IP_SET_ASSERT(ip_set_list[index]);
2227+ ip_set_flush_set(ip_set_list[index]);
2228+ } else
2229+ FOREACH_SET_DO(ip_set_flush_set);
2230+
2231+ return 0;
2232+}
2233+
2234+/* Rename a set */
2235+static int
2236+ip_set_rename(ip_set_id_t index, const char *name)
2237+{
2238+ struct ip_set *set = ip_set_list[index];
2239+ ip_set_id_t i;
2240+ int res = 0;
2241+
2242+ DP("set: %s to %s", set->name, name);
2243+ write_lock_bh(&ip_set_lock);
2244+ for (i = 0; i < ip_set_max; i++) {
2245+ if (ip_set_list[i] != NULL
2246+ && strncmp(ip_set_list[i]->name,
2247+ name,
2248+ IP_SET_MAXNAMELEN - 1) == 0) {
2249+ res = -EEXIST;
2250+ goto unlock;
2251+ }
2252+ }
2253+ strncpy(set->name, name, IP_SET_MAXNAMELEN);
2254+ unlock:
2255+ write_unlock_bh(&ip_set_lock);
2256+ return res;
2257+}
2258+
2259+/*
2260+ * Swap two sets so that name/index points to the other.
2261+ * References are also swapped.
2262+ */
2263+static int
2264+ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
2265+{
2266+ struct ip_set *from = ip_set_list[from_index];
2267+ struct ip_set *to = ip_set_list[to_index];
2268+ char from_name[IP_SET_MAXNAMELEN];
2269+ u_int32_t from_ref;
2270+
2271+ DP("set: %s to %s", from->name, to->name);
2272+ /* Features must not change. Artifical restriction. */
2273+ if (from->type->features != to->type->features)
2274+ return -ENOEXEC;
2275+
2276+ /* No magic here: ref munging protected by the mutex */
2277+ write_lock_bh(&ip_set_lock);
2278+ strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
2279+ from_ref = atomic_read(&from->ref);
2280+
2281+ strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
2282+ atomic_set(&from->ref, atomic_read(&to->ref));
2283+ strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
2284+ atomic_set(&to->ref, from_ref);
2285+
2286+ ip_set_list[from_index] = to;
2287+ ip_set_list[to_index] = from;
2288+
2289+ write_unlock_bh(&ip_set_lock);
2290+ return 0;
2291+}
2292+
2293+/*
2294+ * List set data
2295+ */
2296+
2297+static inline void
2298+__set_hash_bindings_size_list(struct ip_set_hash *set_hash,
2299+ ip_set_id_t id, size_t *size)
2300+{
2301+ if (set_hash->id == id)
2302+ *size += sizeof(struct ip_set_hash_list);
2303+}
2304+
2305+static inline void
2306+__set_hash_bindings_size_save(struct ip_set_hash *set_hash,
2307+ ip_set_id_t id, size_t *size)
2308+{
2309+ if (set_hash->id == id)
2310+ *size += sizeof(struct ip_set_hash_save);
2311+}
2312+
2313+static inline void
2314+__set_hash_bindings(struct ip_set_hash *set_hash,
2315+ ip_set_id_t id, void *data, int *used)
2316+{
2317+ if (set_hash->id == id) {
2318+ struct ip_set_hash_list *hash_list =
2319+ (struct ip_set_hash_list *)(data + *used);
2320+
2321+ hash_list->ip = set_hash->ip;
2322+ hash_list->binding = set_hash->binding;
2323+ *used += sizeof(struct ip_set_hash_list);
2324+ }
2325+}
2326+
2327+static int ip_set_list_set(ip_set_id_t index,
2328+ void *data,
2329+ int *used,
2330+ int len)
2331+{
2332+ struct ip_set *set = ip_set_list[index];
2333+ struct ip_set_list *set_list;
2334+
2335+ /* Pointer to our header */
2336+ set_list = (struct ip_set_list *) (data + *used);
2337+
2338+ DP("set: %s, used: %d %p %p", set->name, *used, data, data + *used);
2339+
2340+ /* Get and ensure header size */
2341+ if (*used + sizeof(struct ip_set_list) > len)
2342+ goto not_enough_mem;
2343+ *used += sizeof(struct ip_set_list);
2344+
2345+ read_lock_bh(&set->lock);
2346+ /* Get and ensure set specific header size */
2347+ set_list->header_size = set->type->header_size;
2348+ if (*used + set_list->header_size > len)
2349+ goto unlock_set;
2350+
2351+ /* Fill in the header */
2352+ set_list->index = index;
2353+ set_list->binding = set->binding;
2354+ set_list->ref = atomic_read(&set->ref);
2355+
2356+ /* Fill in set spefific header data */
2357+ set->type->list_header(set, data + *used);
2358+ *used += set_list->header_size;
2359+
2360+ /* Get and ensure set specific members size */
2361+ set_list->members_size = set->type->list_members_size(set);
2362+ if (*used + set_list->members_size > len)
2363+ goto unlock_set;
2364+
2365+ /* Fill in set spefific members data */
2366+ set->type->list_members(set, data + *used);
2367+ *used += set_list->members_size;
2368+ read_unlock_bh(&set->lock);
2369+
2370+ /* Bindings */
2371+
2372+ /* Get and ensure set specific bindings size */
2373+ set_list->bindings_size = 0;
2374+ FOREACH_HASH_DO(__set_hash_bindings_size_list,
2375+ set->id, &set_list->bindings_size);
2376+ if (*used + set_list->bindings_size > len)
2377+ goto not_enough_mem;
2378+
2379+ /* Fill in set spefific bindings data */
2380+ FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
2381+
2382+ return 0;
2383+
2384+ unlock_set:
2385+ read_unlock_bh(&set->lock);
2386+ not_enough_mem:
2387+ DP("not enough mem, try again");
2388+ return -EAGAIN;
2389+}
2390+
2391+/*
2392+ * Save sets
2393+ */
2394+static int ip_set_save_set(ip_set_id_t index,
2395+ void *data,
2396+ int *used,
2397+ int len)
2398+{
2399+ struct ip_set *set;
2400+ struct ip_set_save *set_save;
2401+
2402+ /* Pointer to our header */
2403+ set_save = (struct ip_set_save *) (data + *used);
2404+
2405+ /* Get and ensure header size */
2406+ if (*used + sizeof(struct ip_set_save) > len)
2407+ goto not_enough_mem;
2408+ *used += sizeof(struct ip_set_save);
2409+
2410+ set = ip_set_list[index];
2411+ DP("set: %s, used: %u(%u) %p %p", set->name, *used, len,
2412+ data, data + *used);
2413+
2414+ read_lock_bh(&set->lock);
2415+ /* Get and ensure set specific header size */
2416+ set_save->header_size = set->type->header_size;
2417+ if (*used + set_save->header_size > len)
2418+ goto unlock_set;
2419+
2420+ /* Fill in the header */
2421+ set_save->index = index;
2422+ set_save->binding = set->binding;
2423+
2424+ /* Fill in set spefific header data */
2425+ set->type->list_header(set, data + *used);
2426+ *used += set_save->header_size;
2427+
2428+ DP("set header filled: %s, used: %u %p %p", set->name, *used,
2429+ data, data + *used);
2430+ /* Get and ensure set specific members size */
2431+ set_save->members_size = set->type->list_members_size(set);
2432+ if (*used + set_save->members_size > len)
2433+ goto unlock_set;
2434+
2435+ /* Fill in set spefific members data */
2436+ set->type->list_members(set, data + *used);
2437+ *used += set_save->members_size;
2438+ read_unlock_bh(&set->lock);
2439+ DP("set members filled: %s, used: %u %p %p", set->name, *used,
2440+ data, data + *used);
2441+ return 0;
2442+
2443+ unlock_set:
2444+ read_unlock_bh(&set->lock);
2445+ not_enough_mem:
2446+ DP("not enough mem, try again");
2447+ return -EAGAIN;
2448+}
2449+
2450+static inline void
2451+__set_hash_save_bindings(struct ip_set_hash *set_hash,
2452+ ip_set_id_t id,
2453+ void *data,
2454+ int *used,
2455+ int len,
2456+ int *res)
2457+{
2458+ if (*res == 0
2459+ && (id == IP_SET_INVALID_ID || set_hash->id == id)) {
2460+ struct ip_set_hash_save *hash_save =
2461+ (struct ip_set_hash_save *)(data + *used);
2462+ /* Ensure bindings size */
2463+ if (*used + sizeof(struct ip_set_hash_save) > len) {
2464+ *res = -ENOMEM;
2465+ return;
2466+ }
2467+ hash_save->id = set_hash->id;
2468+ hash_save->ip = set_hash->ip;
2469+ hash_save->binding = set_hash->binding;
2470+ *used += sizeof(struct ip_set_hash_save);
2471+ }
2472+}
2473+
2474+static int ip_set_save_bindings(ip_set_id_t index,
2475+ void *data,
2476+ int *used,
2477+ int len)
2478+{
2479+ int res = 0;
2480+ struct ip_set_save *set_save;
2481+
2482+ DP("used %u, len %u", *used, len);
2483+ /* Get and ensure header size */
2484+ if (*used + sizeof(struct ip_set_save) > len)
2485+ return -ENOMEM;
2486+
2487+ /* Marker */
2488+ set_save = (struct ip_set_save *) (data + *used);
2489+ set_save->index = IP_SET_INVALID_ID;
2490+ *used += sizeof(struct ip_set_save);
2491+
2492+ DP("marker added used %u, len %u", *used, len);
2493+ /* Fill in bindings data */
2494+ if (index != IP_SET_INVALID_ID)
2495+ /* Sets are identified by id in hash */
2496+ index = ip_set_list[index]->id;
2497+ FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res);
2498+
2499+ return res;
2500+}
2501+
2502+/*
2503+ * Restore sets
2504+ */
2505+static int ip_set_restore(void *data,
2506+ int len)
2507+{
2508+ int res = 0;
2509+ int line = 0, used = 0, members_size;
2510+ struct ip_set *set;
2511+ struct ip_set_hash_save *hash_save;
2512+ struct ip_set_restore *set_restore;
2513+ ip_set_id_t index;
2514+
2515+ /* Loop to restore sets */
2516+ while (1) {
2517+ line++;
2518+
2519+ DP("%u %u %u", used, sizeof(struct ip_set_restore), len);
2520+ /* Get and ensure header size */
2521+ if (used + sizeof(struct ip_set_restore) > len)
2522+ return line;
2523+ set_restore = (struct ip_set_restore *) (data + used);
2524+ used += sizeof(struct ip_set_restore);
2525+
2526+ /* Ensure data size */
2527+ if (used
2528+ + set_restore->header_size
2529+ + set_restore->members_size > len)
2530+ return line;
2531+
2532+ /* Check marker */
2533+ if (set_restore->index == IP_SET_INVALID_ID) {
2534+ line--;
2535+ goto bindings;
2536+ }
2537+
2538+ /* Try to create the set */
2539+ DP("restore %s %s", set_restore->name, set_restore->typename);
2540+ res = ip_set_create(set_restore->name,
2541+ set_restore->typename,
2542+ set_restore->index,
2543+ data + used,
2544+ set_restore->header_size);
2545+
2546+ if (res != 0)
2547+ return line;
2548+ used += set_restore->header_size;
2549+
2550+ index = ip_set_find_byindex(set_restore->index);
2551+ DP("index %u, restore_index %u", index, set_restore->index);
2552+ if (index != set_restore->index)
2553+ return line;
2554+ /* Try to restore members data */
2555+ set = ip_set_list[index];
2556+ members_size = 0;
2557+ DP("members_size %u reqsize %u",
2558+ set_restore->members_size, set->type->reqsize);
2559+ while (members_size + set->type->reqsize <=
2560+ set_restore->members_size) {
2561+ line++;
2562+ DP("members: %u, line %u", members_size, line);
2563+ res = __ip_set_addip(index,
2564+ data + used + members_size,
2565+ set->type->reqsize);
2566+ if (!(res == 0 || res == -EEXIST))
2567+ return line;
2568+ members_size += set->type->reqsize;
2569+ }
2570+
2571+ DP("members_size %u %u",
2572+ set_restore->members_size, members_size);
2573+ if (members_size != set_restore->members_size)
2574+ return line++;
2575+ used += set_restore->members_size;
2576+ }
2577+
2578+ bindings:
2579+ /* Loop to restore bindings */
2580+ while (used < len) {
2581+ line++;
2582+
2583+ DP("restore binding, line %u", line);
2584+ /* Get and ensure size */
2585+ if (used + sizeof(struct ip_set_hash_save) > len)
2586+ return line;
2587+ hash_save = (struct ip_set_hash_save *) (data + used);
2588+ used += sizeof(struct ip_set_hash_save);
2589+
2590+ /* hash_save->id is used to store the index */
2591+ index = ip_set_find_byindex(hash_save->id);
2592+ DP("restore binding index %u, id %u, %u -> %u",
2593+ index, hash_save->id, hash_save->ip, hash_save->binding);
2594+ if (index != hash_save->id)
2595+ return line;
2596+
2597+ set = ip_set_list[hash_save->id];
2598+ /* Null valued IP means default binding */
2599+ if (hash_save->ip)
2600+ res = ip_set_hash_add(set->id,
2601+ hash_save->ip,
2602+ hash_save->binding);
2603+ else {
2604+ IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
2605+ write_lock_bh(&ip_set_lock);
2606+ set->binding = hash_save->binding;
2607+ __ip_set_get(set->binding);
2608+ write_unlock_bh(&ip_set_lock);
2609+ DP("default binding: %u", set->binding);
2610+ }
2611+ if (res != 0)
2612+ return line;
2613+ }
2614+ if (used != len)
2615+ return line;
2616+
2617+ return 0;
2618+}
2619+
2620+static int
2621+ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
2622+{
2623+ void *data;
2624+ int res = 0; /* Assume OK */
2625+ unsigned *op;
2626+ struct ip_set_req_adt *req_adt;
2627+ ip_set_id_t index = IP_SET_INVALID_ID;
2628+ int (*adtfn)(ip_set_id_t index,
2629+ const void *data, size_t size);
2630+ struct fn_table {
2631+ int (*fn)(ip_set_id_t index,
2632+ const void *data, size_t size);
2633+ } adtfn_table[] =
2634+ { { ip_set_addip }, { ip_set_delip }, { ip_set_testip},
2635+ { ip_set_bindip}, { ip_set_unbindip }, { ip_set_testbind },
2636+ };
2637+
2638+ DP("optval=%d, user=%p, len=%d", optval, user, len);
2639+ if (!capable(CAP_NET_ADMIN))
2640+ return -EPERM;
2641+ if (optval != SO_IP_SET)
2642+ return -EBADF;
2643+ if (len <= sizeof(unsigned)) {
2644+ ip_set_printk("short userdata (want >%zu, got %u)",
2645+ sizeof(unsigned), len);
2646+ return -EINVAL;
2647+ }
2648+ data = vmalloc(len);
2649+ if (!data) {
2650+ DP("out of mem for %u bytes", len);
2651+ return -ENOMEM;
2652+ }
2653+ if (copy_from_user(data, user, len) != 0) {
2654+ res = -EFAULT;
2655+ goto done;
2656+ }
2657+ if (down_interruptible(&ip_set_app_mutex)) {
2658+ res = -EINTR;
2659+ goto done;
2660+ }
2661+
2662+ op = (unsigned *)data;
2663+ DP("op=%x", *op);
2664+
2665+ if (*op < IP_SET_OP_VERSION) {
2666+ /* Check the version at the beginning of operations */
2667+ struct ip_set_req_version *req_version =
2668+ (struct ip_set_req_version *) data;
2669+ if (req_version->version != IP_SET_PROTOCOL_VERSION) {
2670+ res = -EPROTO;
2671+ goto done;
2672+ }
2673+ }
2674+
2675+ switch (*op) {
2676+ case IP_SET_OP_CREATE:{
2677+ struct ip_set_req_create *req_create
2678+ = (struct ip_set_req_create *) data;
2679+
2680+ if (len <= sizeof(struct ip_set_req_create)) {
2681+ ip_set_printk("short CREATE data (want >%zu, got %u)",
2682+ sizeof(struct ip_set_req_create), len);
2683+ res = -EINVAL;
2684+ goto done;
2685+ }
2686+ req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
2687+ req_create->typename[IP_SET_MAXNAMELEN - 1] = '\0';
2688+ res = ip_set_create(req_create->name,
2689+ req_create->typename,
2690+ IP_SET_INVALID_ID,
2691+ data + sizeof(struct ip_set_req_create),
2692+ len - sizeof(struct ip_set_req_create));
2693+ goto done;
2694+ }
2695+ case IP_SET_OP_DESTROY:{
2696+ struct ip_set_req_std *req_destroy
2697+ = (struct ip_set_req_std *) data;
2698+
2699+ if (len != sizeof(struct ip_set_req_std)) {
2700+ ip_set_printk("invalid DESTROY data (want %zu, got %u)",
2701+ sizeof(struct ip_set_req_std), len);
2702+ res = -EINVAL;
2703+ goto done;
2704+ }
2705+ if (strcmp(req_destroy->name, IPSET_TOKEN_ALL) == 0) {
2706+ /* Destroy all sets */
2707+ index = IP_SET_INVALID_ID;
2708+ } else {
2709+ req_destroy->name[IP_SET_MAXNAMELEN - 1] = '\0';
2710+ index = ip_set_find_byname(req_destroy->name);
2711+
2712+ if (index == IP_SET_INVALID_ID) {
2713+ res = -ENOENT;
2714+ goto done;
2715+ }
2716+ }
2717+
2718+ res = ip_set_destroy(index);
2719+ goto done;
2720+ }
2721+ case IP_SET_OP_FLUSH:{
2722+ struct ip_set_req_std *req_flush =
2723+ (struct ip_set_req_std *) data;
2724+
2725+ if (len != sizeof(struct ip_set_req_std)) {
2726+ ip_set_printk("invalid FLUSH data (want %zu, got %u)",
2727+ sizeof(struct ip_set_req_std), len);
2728+ res = -EINVAL;
2729+ goto done;
2730+ }
2731+ if (strcmp(req_flush->name, IPSET_TOKEN_ALL) == 0) {
2732+ /* Flush all sets */
2733+ index = IP_SET_INVALID_ID;
2734+ } else {
2735+ req_flush->name[IP_SET_MAXNAMELEN - 1] = '\0';
2736+ index = ip_set_find_byname(req_flush->name);
2737+
2738+ if (index == IP_SET_INVALID_ID) {
2739+ res = -ENOENT;
2740+ goto done;
2741+ }
2742+ }
2743+ res = ip_set_flush(index);
2744+ goto done;
2745+ }
2746+ case IP_SET_OP_RENAME:{
2747+ struct ip_set_req_create *req_rename
2748+ = (struct ip_set_req_create *) data;
2749+
2750+ if (len != sizeof(struct ip_set_req_create)) {
2751+ ip_set_printk("invalid RENAME data (want %zu, got %u)",
2752+ sizeof(struct ip_set_req_create), len);
2753+ res = -EINVAL;
2754+ goto done;
2755+ }
2756+
2757+ req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0';
2758+ req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0';
2759+
2760+ index = ip_set_find_byname(req_rename->name);
2761+ if (index == IP_SET_INVALID_ID) {
2762+ res = -ENOENT;
2763+ goto done;
2764+ }
2765+ res = ip_set_rename(index, req_rename->typename);
2766+ goto done;
2767+ }
2768+ case IP_SET_OP_SWAP:{
2769+ struct ip_set_req_create *req_swap
2770+ = (struct ip_set_req_create *) data;
2771+ ip_set_id_t to_index;
2772+
2773+ if (len != sizeof(struct ip_set_req_create)) {
2774+ ip_set_printk("invalid SWAP data (want %zu, got %u)",
2775+ sizeof(struct ip_set_req_create), len);
2776+ res = -EINVAL;
2777+ goto done;
2778+ }
2779+
2780+ req_swap->name[IP_SET_MAXNAMELEN - 1] = '\0';
2781+ req_swap->typename[IP_SET_MAXNAMELEN - 1] = '\0';
2782+
2783+ index = ip_set_find_byname(req_swap->name);
2784+ if (index == IP_SET_INVALID_ID) {
2785+ res = -ENOENT;
2786+ goto done;
2787+ }
2788+ to_index = ip_set_find_byname(req_swap->typename);
2789+ if (to_index == IP_SET_INVALID_ID) {
2790+ res = -ENOENT;
2791+ goto done;
2792+ }
2793+ res = ip_set_swap(index, to_index);
2794+ goto done;
2795+ }
2796+ default:
2797+ break; /* Set identified by id */
2798+ }
2799+
2800+ /* There we may have add/del/test/bind/unbind/test_bind operations */
2801+ if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) {
2802+ res = -EBADMSG;
2803+ goto done;
2804+ }
2805+ adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn;
2806+
2807+ if (len < sizeof(struct ip_set_req_adt)) {
2808+ ip_set_printk("short data in adt request (want >=%zu, got %u)",
2809+ sizeof(struct ip_set_req_adt), len);
2810+ res = -EINVAL;
2811+ goto done;
2812+ }
2813+ req_adt = (struct ip_set_req_adt *) data;
2814+
2815+ /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */
2816+ if (!(*op == IP_SET_OP_UNBIND_SET
2817+ && req_adt->index == IP_SET_INVALID_ID)) {
2818+ index = ip_set_find_byindex(req_adt->index);
2819+ if (index == IP_SET_INVALID_ID) {
2820+ res = -ENOENT;
2821+ goto done;
2822+ }
2823+ }
2824+ res = adtfn(index, data, len);
2825+
2826+ done:
2827+ up(&ip_set_app_mutex);
2828+ vfree(data);
2829+ if (res > 0)
2830+ res = 0;
2831+ DP("final result %d", res);
2832+ return res;
2833+}
2834+
2835+static int
2836+ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
2837+{
2838+ int res = 0;
2839+ unsigned *op;
2840+ ip_set_id_t index = IP_SET_INVALID_ID;
2841+ void *data;
2842+ int copylen = *len;
2843+
2844+ DP("optval=%d, user=%p, len=%d", optval, user, *len);
2845+ if (!capable(CAP_NET_ADMIN))
2846+ return -EPERM;
2847+ if (optval != SO_IP_SET)
2848+ return -EBADF;
2849+ if (*len < sizeof(unsigned)) {
2850+ ip_set_printk("short userdata (want >=%zu, got %d)",
2851+ sizeof(unsigned), *len);
2852+ return -EINVAL;
2853+ }
2854+ data = vmalloc(*len);
2855+ if (!data) {
2856+ DP("out of mem for %d bytes", *len);
2857+ return -ENOMEM;
2858+ }
2859+ if (copy_from_user(data, user, *len) != 0) {
2860+ res = -EFAULT;
2861+ goto done;
2862+ }
2863+ if (down_interruptible(&ip_set_app_mutex)) {
2864+ res = -EINTR;
2865+ goto done;
2866+ }
2867+
2868+ op = (unsigned *) data;
2869+ DP("op=%x", *op);
2870+
2871+ if (*op < IP_SET_OP_VERSION) {
2872+ /* Check the version at the beginning of operations */
2873+ struct ip_set_req_version *req_version =
2874+ (struct ip_set_req_version *) data;
2875+ if (req_version->version != IP_SET_PROTOCOL_VERSION) {
2876+ res = -EPROTO;
2877+ goto done;
2878+ }
2879+ }
2880+
2881+ switch (*op) {
2882+ case IP_SET_OP_VERSION: {
2883+ struct ip_set_req_version *req_version =
2884+ (struct ip_set_req_version *) data;
2885+
2886+ if (*len != sizeof(struct ip_set_req_version)) {
2887+ ip_set_printk("invalid VERSION (want %zu, got %d)",
2888+ sizeof(struct ip_set_req_version),
2889+ *len);
2890+ res = -EINVAL;
2891+ goto done;
2892+ }
2893+
2894+ req_version->version = IP_SET_PROTOCOL_VERSION;
2895+ res = copy_to_user(user, req_version,
2896+ sizeof(struct ip_set_req_version));
2897+ goto done;
2898+ }
2899+ case IP_SET_OP_GET_BYNAME: {
2900+ struct ip_set_req_get_set *req_get
2901+ = (struct ip_set_req_get_set *) data;
2902+
2903+ if (*len != sizeof(struct ip_set_req_get_set)) {
2904+ ip_set_printk("invalid GET_BYNAME (want %zu, got %d)",
2905+ sizeof(struct ip_set_req_get_set), *len);
2906+ res = -EINVAL;
2907+ goto done;
2908+ }
2909+ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
2910+ index = ip_set_find_byname(req_get->set.name);
2911+ req_get->set.index = index;
2912+ goto copy;
2913+ }
2914+ case IP_SET_OP_GET_BYINDEX: {
2915+ struct ip_set_req_get_set *req_get
2916+ = (struct ip_set_req_get_set *) data;
2917+
2918+ if (*len != sizeof(struct ip_set_req_get_set)) {
2919+ ip_set_printk("invalid GET_BYINDEX (want %zu, got %d)",
2920+ sizeof(struct ip_set_req_get_set), *len);
2921+ res = -EINVAL;
2922+ goto done;
2923+ }
2924+ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
2925+ index = ip_set_find_byindex(req_get->set.index);
2926+ strncpy(req_get->set.name,
2927+ index == IP_SET_INVALID_ID ? ""
2928+ : ip_set_list[index]->name, IP_SET_MAXNAMELEN);
2929+ goto copy;
2930+ }
2931+ case IP_SET_OP_ADT_GET: {
2932+ struct ip_set_req_adt_get *req_get
2933+ = (struct ip_set_req_adt_get *) data;
2934+
2935+ if (*len != sizeof(struct ip_set_req_adt_get)) {
2936+ ip_set_printk("invalid ADT_GET (want %zu, got %d)",
2937+ sizeof(struct ip_set_req_adt_get), *len);
2938+ res = -EINVAL;
2939+ goto done;
2940+ }
2941+ req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
2942+ index = ip_set_find_byname(req_get->set.name);
2943+ if (index != IP_SET_INVALID_ID) {
2944+ req_get->set.index = index;
2945+ strncpy(req_get->typename,
2946+ ip_set_list[index]->type->typename,
2947+ IP_SET_MAXNAMELEN - 1);
2948+ } else {
2949+ res = -ENOENT;
2950+ goto done;
2951+ }
2952+ goto copy;
2953+ }
2954+ case IP_SET_OP_MAX_SETS: {
2955+ struct ip_set_req_max_sets *req_max_sets
2956+ = (struct ip_set_req_max_sets *) data;
2957+ ip_set_id_t i;
2958+
2959+ if (*len != sizeof(struct ip_set_req_max_sets)) {
2960+ ip_set_printk("invalid MAX_SETS (want %zu, got %d)",
2961+ sizeof(struct ip_set_req_max_sets), *len);
2962+ res = -EINVAL;
2963+ goto done;
2964+ }
2965+
2966+ if (strcmp(req_max_sets->set.name, IPSET_TOKEN_ALL) == 0) {
2967+ req_max_sets->set.index = IP_SET_INVALID_ID;
2968+ } else {
2969+ req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
2970+ req_max_sets->set.index =
2971+ ip_set_find_byname(req_max_sets->set.name);
2972+ if (req_max_sets->set.index == IP_SET_INVALID_ID) {
2973+ res = -ENOENT;
2974+ goto done;
2975+ }
2976+ }
2977+ req_max_sets->max_sets = ip_set_max;
2978+ req_max_sets->sets = 0;
2979+ for (i = 0; i < ip_set_max; i++) {
2980+ if (ip_set_list[i] != NULL)
2981+ req_max_sets->sets++;
2982+ }
2983+ goto copy;
2984+ }
2985+ case IP_SET_OP_LIST_SIZE:
2986+ case IP_SET_OP_SAVE_SIZE: {
2987+ struct ip_set_req_setnames *req_setnames
2988+ = (struct ip_set_req_setnames *) data;
2989+ struct ip_set_name_list *name_list;
2990+ struct ip_set *set;
2991+ ip_set_id_t i;
2992+ int used;
2993+
2994+ if (*len < sizeof(struct ip_set_req_setnames)) {
2995+ ip_set_printk("short LIST_SIZE (want >=%zu, got %d)",
2996+ sizeof(struct ip_set_req_setnames), *len);
2997+ res = -EINVAL;
2998+ goto done;
2999+ }
3000+
3001+ req_setnames->size = 0;
3002+ used = sizeof(struct ip_set_req_setnames);
3003+ for (i = 0; i < ip_set_max; i++) {
3004+ if (ip_set_list[i] == NULL)
3005+ continue;
3006+ name_list = (struct ip_set_name_list *)
3007+ (data + used);
3008+ used += sizeof(struct ip_set_name_list);
3009+ if (used > copylen) {
3010+ res = -EAGAIN;
3011+ goto done;
3012+ }
3013+ set = ip_set_list[i];
3014+ /* Fill in index, name, etc. */
3015+ name_list->index = i;
3016+ name_list->id = set->id;
3017+ strncpy(name_list->name,
3018+ set->name,
3019+ IP_SET_MAXNAMELEN - 1);
3020+ strncpy(name_list->typename,
3021+ set->type->typename,
3022+ IP_SET_MAXNAMELEN - 1);
3023+ DP("filled %s of type %s, index %u\n",
3024+ name_list->name, name_list->typename,
3025+ name_list->index);
3026+ if (!(req_setnames->index == IP_SET_INVALID_ID
3027+ || req_setnames->index == i))
3028+ continue;
3029+ /* Update size */
3030+ switch (*op) {
3031+ case IP_SET_OP_LIST_SIZE: {
3032+ req_setnames->size += sizeof(struct ip_set_list)
3033+ + set->type->header_size
3034+ + set->type->list_members_size(set);
3035+ FOREACH_HASH_DO(__set_hash_bindings_size_list,
3036+ i, &req_setnames->size);
3037+ break;
3038+ }
3039+ case IP_SET_OP_SAVE_SIZE: {
3040+ req_setnames->size += sizeof(struct ip_set_save)
3041+ + set->type->header_size
3042+ + set->type->list_members_size(set);
3043+ FOREACH_HASH_DO(__set_hash_bindings_size_save,
3044+ i, &req_setnames->size);
3045+ break;
3046+ }
3047+ default:
3048+ break;
3049+ }
3050+ }
3051+ if (copylen != used) {
3052+ res = -EAGAIN;
3053+ goto done;
3054+ }
3055+ goto copy;
3056+ }
3057+ case IP_SET_OP_LIST: {
3058+ struct ip_set_req_list *req_list
3059+ = (struct ip_set_req_list *) data;
3060+ ip_set_id_t i;
3061+ int used;
3062+
3063+ if (*len < sizeof(struct ip_set_req_list)) {
3064+ ip_set_printk("short LIST (want >=%zu, got %d)",
3065+ sizeof(struct ip_set_req_list), *len);
3066+ res = -EINVAL;
3067+ goto done;
3068+ }
3069+ index = req_list->index;
3070+ if (index != IP_SET_INVALID_ID
3071+ && ip_set_find_byindex(index) != index) {
3072+ res = -ENOENT;
3073+ goto done;
3074+ }
3075+ used = 0;
3076+ if (index == IP_SET_INVALID_ID) {
3077+ /* List all sets */
3078+ for (i = 0; i < ip_set_max && res == 0; i++) {
3079+ if (ip_set_list[i] != NULL)
3080+ res = ip_set_list_set(i, data, &used, *len);
3081+ }
3082+ } else {
3083+ /* List an individual set */
3084+ res = ip_set_list_set(index, data, &used, *len);
3085+ }
3086+ if (res != 0)
3087+ goto done;
3088+ else if (copylen != used) {
3089+ res = -EAGAIN;
3090+ goto done;
3091+ }
3092+ goto copy;
3093+ }
3094+ case IP_SET_OP_SAVE: {
3095+ struct ip_set_req_list *req_save
3096+ = (struct ip_set_req_list *) data;
3097+ ip_set_id_t i;
3098+ int used;
3099+
3100+ if (*len < sizeof(struct ip_set_req_list)) {
3101+ ip_set_printk("short SAVE (want >=%zu, got %d)",
3102+ sizeof(struct ip_set_req_list), *len);
3103+ res = -EINVAL;
3104+ goto done;
3105+ }
3106+ index = req_save->index;
3107+ if (index != IP_SET_INVALID_ID
3108+ && ip_set_find_byindex(index) != index) {
3109+ res = -ENOENT;
3110+ goto done;
3111+ }
3112+ used = 0;
3113+ if (index == IP_SET_INVALID_ID) {
3114+ /* Save all sets */
3115+ for (i = 0; i < ip_set_max && res == 0; i++) {
3116+ if (ip_set_list[i] != NULL)
3117+ res = ip_set_save_set(i, data, &used, *len);
3118+ }
3119+ } else {
3120+ /* Save an individual set */
3121+ res = ip_set_save_set(index, data, &used, *len);
3122+ }
3123+ if (res == 0)
3124+ res = ip_set_save_bindings(index, data, &used, *len);
3125+
3126+ if (res != 0)
3127+ goto done;
3128+ else if (copylen != used) {
3129+ res = -EAGAIN;
3130+ goto done;
3131+ }
3132+ goto copy;
3133+ }
3134+ case IP_SET_OP_RESTORE: {
3135+ struct ip_set_req_setnames *req_restore
3136+ = (struct ip_set_req_setnames *) data;
3137+ int line;
3138+
3139+ if (*len < sizeof(struct ip_set_req_setnames)
3140+ || *len != req_restore->size) {
3141+ ip_set_printk("invalid RESTORE (want =%zu, got %d)",
3142+ req_restore->size, *len);
3143+ res = -EINVAL;
3144+ goto done;
3145+ }
3146+ line = ip_set_restore(data + sizeof(struct ip_set_req_setnames),
3147+ req_restore->size - sizeof(struct ip_set_req_setnames));
3148+ DP("ip_set_restore: %u", line);
3149+ if (line != 0) {
3150+ res = -EAGAIN;
3151+ req_restore->size = line;
3152+ copylen = sizeof(struct ip_set_req_setnames);
3153+ goto copy;
3154+ }
3155+ goto done;
3156+ }
3157+ default:
3158+ res = -EBADMSG;
3159+ goto done;
3160+ } /* end of switch(op) */
3161+
3162+ copy:
3163+ DP("set %s, copylen %u", index != IP_SET_INVALID_ID
3164+ && ip_set_list[index]
3165+ ? ip_set_list[index]->name
3166+ : ":all:", copylen);
3167+ res = copy_to_user(user, data, copylen);
3168+
3169+ done:
3170+ up(&ip_set_app_mutex);
3171+ vfree(data);
3172+ if (res > 0)
3173+ res = 0;
3174+ DP("final result %d", res);
3175+ return res;
3176+}
3177+
3178+static struct nf_sockopt_ops so_set = {
3179+ .pf = PF_INET,
3180+ .set_optmin = SO_IP_SET,
3181+ .set_optmax = SO_IP_SET + 1,
3182+ .set = &ip_set_sockfn_set,
3183+ .get_optmin = SO_IP_SET,
3184+ .get_optmax = SO_IP_SET + 1,
3185+ .get = &ip_set_sockfn_get,
3186+ .use = 0
3187+};
3188+
3189+static int max_sets, hash_size;
3190+module_param(max_sets, int, 0600);
3191+MODULE_PARM_DESC(max_sets, "maximal number of sets");
3192+module_param(hash_size, int, 0600);
3193+MODULE_PARM_DESC(hash_size, "hash size for bindings");
3194+MODULE_LICENSE("GPL");
3195+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3196+MODULE_DESCRIPTION("module implementing core IP set support");
3197+
3198+static int __init init(void)
3199+{
3200+ int res;
3201+ ip_set_id_t i;
3202+
3203+ get_random_bytes(&ip_set_hash_random, 4);
3204+ if (max_sets)
3205+ ip_set_max = max_sets;
3206+ ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max);
3207+ if (!ip_set_list) {
3208+ printk(KERN_ERR "Unable to create ip_set_list\n");
3209+ return -ENOMEM;
3210+ }
3211+ memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max);
3212+ if (hash_size)
3213+ ip_set_bindings_hash_size = hash_size;
3214+ ip_set_hash = vmalloc(sizeof(struct list_head) * ip_set_bindings_hash_size);
3215+ if (!ip_set_hash) {
3216+ printk(KERN_ERR "Unable to create ip_set_hash\n");
3217+ vfree(ip_set_list);
3218+ return -ENOMEM;
3219+ }
3220+ for (i = 0; i < ip_set_bindings_hash_size; i++)
3221+ INIT_LIST_HEAD(&ip_set_hash[i]);
3222+
3223+ INIT_LIST_HEAD(&set_type_list);
3224+
3225+ res = nf_register_sockopt(&so_set);
3226+ if (res != 0) {
3227+ ip_set_printk("SO_SET registry failed: %d", res);
3228+ vfree(ip_set_list);
3229+ vfree(ip_set_hash);
3230+ return res;
3231+ }
3232+ return 0;
3233+}
3234+
3235+static void __exit fini(void)
3236+{
3237+ /* There can't be any existing set or binding */
3238+ nf_unregister_sockopt(&so_set);
3239+ vfree(ip_set_list);
3240+ vfree(ip_set_hash);
3241+ DP("these are the famous last words");
3242+}
3243+
3244+EXPORT_SYMBOL(ip_set_register_set_type);
3245+EXPORT_SYMBOL(ip_set_unregister_set_type);
3246+
3247+EXPORT_SYMBOL(ip_set_get_byname);
3248+EXPORT_SYMBOL(ip_set_get_byindex);
3249+EXPORT_SYMBOL(ip_set_put);
3250+
3251+EXPORT_SYMBOL(ip_set_addip_kernel);
3252+EXPORT_SYMBOL(ip_set_delip_kernel);
3253+EXPORT_SYMBOL(ip_set_testip_kernel);
3254+
3255+module_init(init);
3256+module_exit(fini);
3257diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_iphash.c linux/net/ipv4/netfilter/ip_set_iphash.c
3258--- linux.org/net/ipv4/netfilter/ip_set_iphash.c 1970-01-01 01:00:00.000000000 +0100
3259+++ linux/net/ipv4/netfilter/ip_set_iphash.c 2006-05-04 10:26:33.000000000 +0200
3260@@ -0,0 +1,398 @@
3261+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3262+ *
3263+ * This program is free software; you can redistribute it and/or modify
3264+ * it under the terms of the GNU General Public License version 2 as
3265+ * published by the Free Software Foundation.
3266+ */
3267+
3268+/* Kernel module implementing an ip hash set */
3269+
3270+#include <linux/module.h>
3271+#include <linux/ip.h>
3272+#include <linux/skbuff.h>
3273+#include <linux/netfilter_ipv4/ip_tables.h>
3274+#include <linux/netfilter_ipv4/ip_set.h>
3275+#include <linux/errno.h>
3276+#include <asm/uaccess.h>
3277+#include <asm/bitops.h>
3278+#include <linux/spinlock.h>
3279+#include <linux/vmalloc.h>
3280+#include <linux/random.h>
3281+
3282+#include <net/ip.h>
3283+
3284+#include <linux/netfilter_ipv4/ip_set_malloc.h>
3285+#include <linux/netfilter_ipv4/ip_set_iphash.h>
3286+#include <linux/netfilter_ipv4/ip_set_jhash.h>
3287+
3288+static inline __u32
3289+jhash_ip(const struct ip_set_iphash *map, uint16_t i, ip_set_ip_t ip)
3290+{
3291+ return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
3292+}
3293+
3294+static inline __u32
3295+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3296+{
3297+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3298+ __u32 id;
3299+ u_int16_t i;
3300+ ip_set_ip_t *elem;
3301+
3302+ *hash_ip = ip & map->netmask;
3303+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u, %u.%u.%u.%u",
3304+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip), HIPQUAD(map->netmask));
3305+
3306+ for (i = 0; i < map->probes; i++) {
3307+ id = jhash_ip(map, i, *hash_ip) % map->hashsize;
3308+ DP("hash key: %u", id);
3309+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
3310+ if (*elem == *hash_ip)
3311+ return id;
3312+ /* No shortcut at testing - there can be deleted
3313+ * entries. */
3314+ }
3315+ return UINT_MAX;
3316+}
3317+
3318+static inline int
3319+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3320+{
3321+ return (hash_id(set, ip, hash_ip) != UINT_MAX);
3322+}
3323+
3324+static int
3325+testip(struct ip_set *set, const void *data, size_t size,
3326+ ip_set_ip_t *hash_ip)
3327+{
3328+ struct ip_set_req_iphash *req =
3329+ (struct ip_set_req_iphash *) data;
3330+
3331+ if (size != sizeof(struct ip_set_req_iphash)) {
3332+ ip_set_printk("data length wrong (want %zu, have %zu)",
3333+ sizeof(struct ip_set_req_iphash),
3334+ size);
3335+ return -EINVAL;
3336+ }
3337+ return __testip(set, req->ip, hash_ip);
3338+}
3339+
3340+static int
3341+testip_kernel(struct ip_set *set,
3342+ const struct sk_buff *skb,
3343+ ip_set_ip_t *hash_ip,
3344+ const u_int32_t *flags,
3345+ unsigned char index)
3346+{
3347+ return __testip(set,
3348+ ntohl(flags[index] & IPSET_SRC
3349+ ? skb->nh.iph->saddr
3350+ : skb->nh.iph->daddr),
3351+ hash_ip);
3352+}
3353+
3354+static inline int
3355+__addip(struct ip_set_iphash *map, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3356+{
3357+ __u32 probe;
3358+ u_int16_t i;
3359+ ip_set_ip_t *elem;
3360+
3361+ *hash_ip = ip & map->netmask;
3362+
3363+ for (i = 0; i < map->probes; i++) {
3364+ probe = jhash_ip(map, i, *hash_ip) % map->hashsize;
3365+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
3366+ if (*elem == *hash_ip)
3367+ return -EEXIST;
3368+ if (!*elem) {
3369+ *elem = *hash_ip;
3370+ return 0;
3371+ }
3372+ }
3373+ /* Trigger rehashing */
3374+ return -EAGAIN;
3375+}
3376+
3377+static int
3378+addip(struct ip_set *set, const void *data, size_t size,
3379+ ip_set_ip_t *hash_ip)
3380+{
3381+ struct ip_set_req_iphash *req =
3382+ (struct ip_set_req_iphash *) data;
3383+
3384+ if (size != sizeof(struct ip_set_req_iphash)) {
3385+ ip_set_printk("data length wrong (want %zu, have %zu)",
3386+ sizeof(struct ip_set_req_iphash),
3387+ size);
3388+ return -EINVAL;
3389+ }
3390+ return __addip((struct ip_set_iphash *) set->data, req->ip, hash_ip);
3391+}
3392+
3393+static int
3394+addip_kernel(struct ip_set *set,
3395+ const struct sk_buff *skb,
3396+ ip_set_ip_t *hash_ip,
3397+ const u_int32_t *flags,
3398+ unsigned char index)
3399+{
3400+ return __addip((struct ip_set_iphash *) set->data,
3401+ ntohl(flags[index] & IPSET_SRC
3402+ ? skb->nh.iph->saddr
3403+ : skb->nh.iph->daddr),
3404+ hash_ip);
3405+}
3406+
3407+static int retry(struct ip_set *set)
3408+{
3409+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3410+ ip_set_ip_t hash_ip, *elem;
3411+ void *members;
3412+ u_int32_t i, hashsize = map->hashsize;
3413+ int res;
3414+ struct ip_set_iphash *tmp;
3415+
3416+ if (map->resize == 0)
3417+ return -ERANGE;
3418+
3419+ again:
3420+ res = 0;
3421+
3422+ /* Calculate new hash size */
3423+ hashsize += (hashsize * map->resize)/100;
3424+ if (hashsize == map->hashsize)
3425+ hashsize++;
3426+
3427+ ip_set_printk("rehashing of set %s triggered: "
3428+ "hashsize grows from %u to %u",
3429+ set->name, map->hashsize, hashsize);
3430+
3431+ tmp = kmalloc(sizeof(struct ip_set_iphash)
3432+ + map->probes * sizeof(uint32_t), GFP_ATOMIC);
3433+ if (!tmp) {
3434+ DP("out of memory for %d bytes",
3435+ sizeof(struct ip_set_iphash)
3436+ + map->probes * sizeof(uint32_t));
3437+ return -ENOMEM;
3438+ }
3439+ tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
3440+ if (!tmp->members) {
3441+ DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
3442+ kfree(tmp);
3443+ return -ENOMEM;
3444+ }
3445+ tmp->hashsize = hashsize;
3446+ tmp->probes = map->probes;
3447+ tmp->resize = map->resize;
3448+ tmp->netmask = map->netmask;
3449+ memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
3450+
3451+ write_lock_bh(&set->lock);
3452+ map = (struct ip_set_iphash *) set->data; /* Play safe */
3453+ for (i = 0; i < map->hashsize && res == 0; i++) {
3454+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
3455+ if (*elem)
3456+ res = __addip(tmp, *elem, &hash_ip);
3457+ }
3458+ if (res) {
3459+ /* Failure, try again */
3460+ write_unlock_bh(&set->lock);
3461+ harray_free(tmp->members);
3462+ kfree(tmp);
3463+ goto again;
3464+ }
3465+
3466+ /* Success at resizing! */
3467+ members = map->members;
3468+
3469+ map->hashsize = tmp->hashsize;
3470+ map->members = tmp->members;
3471+ write_unlock_bh(&set->lock);
3472+
3473+ harray_free(members);
3474+ kfree(tmp);
3475+
3476+ return 0;
3477+}
3478+
3479+static inline int
3480+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3481+{
3482+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3483+ ip_set_ip_t id = hash_id(set, ip, hash_ip);
3484+ ip_set_ip_t *elem;
3485+
3486+ if (id == UINT_MAX)
3487+ return -EEXIST;
3488+
3489+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
3490+ *elem = 0;
3491+
3492+ return 0;
3493+}
3494+
3495+static int
3496+delip(struct ip_set *set, const void *data, size_t size,
3497+ ip_set_ip_t *hash_ip)
3498+{
3499+ struct ip_set_req_iphash *req =
3500+ (struct ip_set_req_iphash *) data;
3501+
3502+ if (size != sizeof(struct ip_set_req_iphash)) {
3503+ ip_set_printk("data length wrong (want %zu, have %zu)",
3504+ sizeof(struct ip_set_req_iphash),
3505+ size);
3506+ return -EINVAL;
3507+ }
3508+ return __delip(set, req->ip, hash_ip);
3509+}
3510+
3511+static int
3512+delip_kernel(struct ip_set *set,
3513+ const struct sk_buff *skb,
3514+ ip_set_ip_t *hash_ip,
3515+ const u_int32_t *flags,
3516+ unsigned char index)
3517+{
3518+ return __delip(set,
3519+ ntohl(flags[index] & IPSET_SRC
3520+ ? skb->nh.iph->saddr
3521+ : skb->nh.iph->daddr),
3522+ hash_ip);
3523+}
3524+
3525+static int create(struct ip_set *set, const void *data, size_t size)
3526+{
3527+ struct ip_set_req_iphash_create *req =
3528+ (struct ip_set_req_iphash_create *) data;
3529+ struct ip_set_iphash *map;
3530+ uint16_t i;
3531+
3532+ if (size != sizeof(struct ip_set_req_iphash_create)) {
3533+ ip_set_printk("data length wrong (want %zu, have %zu)",
3534+ sizeof(struct ip_set_req_iphash_create),
3535+ size);
3536+ return -EINVAL;
3537+ }
3538+
3539+ if (req->hashsize < 1) {
3540+ ip_set_printk("hashsize too small");
3541+ return -ENOEXEC;
3542+ }
3543+
3544+ if (req->probes < 1) {
3545+ ip_set_printk("probes too small");
3546+ return -ENOEXEC;
3547+ }
3548+
3549+ map = kmalloc(sizeof(struct ip_set_iphash)
3550+ + req->probes * sizeof(uint32_t), GFP_KERNEL);
3551+ if (!map) {
3552+ DP("out of memory for %d bytes",
3553+ sizeof(struct ip_set_iphash)
3554+ + req->probes * sizeof(uint32_t));
3555+ return -ENOMEM;
3556+ }
3557+ for (i = 0; i < req->probes; i++)
3558+ get_random_bytes(((uint32_t *) map->initval)+i, 4);
3559+ map->hashsize = req->hashsize;
3560+ map->probes = req->probes;
3561+ map->resize = req->resize;
3562+ map->netmask = req->netmask;
3563+ map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
3564+ if (!map->members) {
3565+ DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
3566+ kfree(map);
3567+ return -ENOMEM;
3568+ }
3569+
3570+ set->data = map;
3571+ return 0;
3572+}
3573+
3574+static void destroy(struct ip_set *set)
3575+{
3576+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3577+
3578+ harray_free(map->members);
3579+ kfree(map);
3580+
3581+ set->data = NULL;
3582+}
3583+
3584+static void flush(struct ip_set *set)
3585+{
3586+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3587+ harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
3588+}
3589+
3590+static void list_header(const struct ip_set *set, void *data)
3591+{
3592+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3593+ struct ip_set_req_iphash_create *header =
3594+ (struct ip_set_req_iphash_create *) data;
3595+
3596+ header->hashsize = map->hashsize;
3597+ header->probes = map->probes;
3598+ header->resize = map->resize;
3599+ header->netmask = map->netmask;
3600+}
3601+
3602+static int list_members_size(const struct ip_set *set)
3603+{
3604+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3605+
3606+ return (map->hashsize * sizeof(ip_set_ip_t));
3607+}
3608+
3609+static void list_members(const struct ip_set *set, void *data)
3610+{
3611+ struct ip_set_iphash *map = (struct ip_set_iphash *) set->data;
3612+ ip_set_ip_t i, *elem;
3613+
3614+ for (i = 0; i < map->hashsize; i++) {
3615+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
3616+ ((ip_set_ip_t *)data)[i] = *elem;
3617+ }
3618+}
3619+
3620+static struct ip_set_type ip_set_iphash = {
3621+ .typename = SETTYPE_NAME,
3622+ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
3623+ .protocol_version = IP_SET_PROTOCOL_VERSION,
3624+ .create = &create,
3625+ .destroy = &destroy,
3626+ .flush = &flush,
3627+ .reqsize = sizeof(struct ip_set_req_iphash),
3628+ .addip = &addip,
3629+ .addip_kernel = &addip_kernel,
3630+ .retry = &retry,
3631+ .delip = &delip,
3632+ .delip_kernel = &delip_kernel,
3633+ .testip = &testip,
3634+ .testip_kernel = &testip_kernel,
3635+ .header_size = sizeof(struct ip_set_req_iphash_create),
3636+ .list_header = &list_header,
3637+ .list_members_size = &list_members_size,
3638+ .list_members = &list_members,
3639+ .me = THIS_MODULE,
3640+};
3641+
3642+MODULE_LICENSE("GPL");
3643+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3644+MODULE_DESCRIPTION("iphash type of IP sets");
3645+
3646+static int __init init(void)
3647+{
3648+ return ip_set_register_set_type(&ip_set_iphash);
3649+}
3650+
3651+static void __exit fini(void)
3652+{
3653+ /* FIXME: possible race with ip_set_create() */
3654+ ip_set_unregister_set_type(&ip_set_iphash);
3655+}
3656+
3657+module_init(init);
3658+module_exit(fini);
3659diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_ipmap.c linux/net/ipv4/netfilter/ip_set_ipmap.c
3660--- linux.org/net/ipv4/netfilter/ip_set_ipmap.c 1970-01-01 01:00:00.000000000 +0100
3661+++ linux/net/ipv4/netfilter/ip_set_ipmap.c 2006-05-04 10:26:33.000000000 +0200
3662@@ -0,0 +1,327 @@
3663+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
3664+ * Patrick Schaaf <bof@bof.de>
3665+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3666+ *
3667+ * This program is free software; you can redistribute it and/or modify
3668+ * it under the terms of the GNU General Public License version 2 as
3669+ * published by the Free Software Foundation.
3670+ */
3671+
3672+/* Kernel module implementing an IP set type: the single bitmap type */
3673+
3674+#include <linux/module.h>
3675+#include <linux/ip.h>
3676+#include <linux/skbuff.h>
3677+#include <linux/netfilter_ipv4/ip_tables.h>
3678+#include <linux/netfilter_ipv4/ip_set.h>
3679+#include <linux/errno.h>
3680+#include <asm/uaccess.h>
3681+#include <asm/bitops.h>
3682+#include <linux/spinlock.h>
3683+
3684+#include <linux/netfilter_ipv4/ip_set_ipmap.h>
3685+
3686+static inline ip_set_ip_t
3687+ip_to_id(const struct ip_set_ipmap *map, ip_set_ip_t ip)
3688+{
3689+ return (ip - map->first_ip)/map->hosts;
3690+}
3691+
3692+static inline int
3693+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3694+{
3695+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3696+
3697+ if (ip < map->first_ip || ip > map->last_ip)
3698+ return -ERANGE;
3699+
3700+ *hash_ip = ip & map->netmask;
3701+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
3702+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
3703+ return !!test_bit(ip_to_id(map, *hash_ip), map->members);
3704+}
3705+
3706+static int
3707+testip(struct ip_set *set, const void *data, size_t size,
3708+ ip_set_ip_t *hash_ip)
3709+{
3710+ struct ip_set_req_ipmap *req =
3711+ (struct ip_set_req_ipmap *) data;
3712+
3713+ if (size != sizeof(struct ip_set_req_ipmap)) {
3714+ ip_set_printk("data length wrong (want %zu, have %zu)",
3715+ sizeof(struct ip_set_req_ipmap),
3716+ size);
3717+ return -EINVAL;
3718+ }
3719+ return __testip(set, req->ip, hash_ip);
3720+}
3721+
3722+static int
3723+testip_kernel(struct ip_set *set,
3724+ const struct sk_buff *skb,
3725+ ip_set_ip_t *hash_ip,
3726+ const u_int32_t *flags,
3727+ unsigned char index)
3728+{
3729+ int res;
3730+
3731+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
3732+ flags[index] & IPSET_SRC ? "SRC" : "DST",
3733+ NIPQUAD(skb->nh.iph->saddr),
3734+ NIPQUAD(skb->nh.iph->daddr));
3735+
3736+ res = __testip(set,
3737+ ntohl(flags[index] & IPSET_SRC
3738+ ? skb->nh.iph->saddr
3739+ : skb->nh.iph->daddr),
3740+ hash_ip);
3741+ return (res < 0 ? 0 : res);
3742+}
3743+
3744+static inline int
3745+__addip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3746+{
3747+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3748+
3749+ if (ip < map->first_ip || ip > map->last_ip)
3750+ return -ERANGE;
3751+
3752+ *hash_ip = ip & map->netmask;
3753+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
3754+ if (test_and_set_bit(ip_to_id(map, *hash_ip), map->members))
3755+ return -EEXIST;
3756+
3757+ return 0;
3758+}
3759+
3760+static int
3761+addip(struct ip_set *set, const void *data, size_t size,
3762+ ip_set_ip_t *hash_ip)
3763+{
3764+ struct ip_set_req_ipmap *req =
3765+ (struct ip_set_req_ipmap *) data;
3766+
3767+ if (size != sizeof(struct ip_set_req_ipmap)) {
3768+ ip_set_printk("data length wrong (want %zu, have %zu)",
3769+ sizeof(struct ip_set_req_ipmap),
3770+ size);
3771+ return -EINVAL;
3772+ }
3773+ DP("%u.%u.%u.%u", HIPQUAD(req->ip));
3774+ return __addip(set, req->ip, hash_ip);
3775+}
3776+
3777+static int
3778+addip_kernel(struct ip_set *set,
3779+ const struct sk_buff *skb,
3780+ ip_set_ip_t *hash_ip,
3781+ const u_int32_t *flags,
3782+ unsigned char index)
3783+{
3784+ return __addip(set,
3785+ ntohl(flags[index] & IPSET_SRC
3786+ ? skb->nh.iph->saddr
3787+ : skb->nh.iph->daddr),
3788+ hash_ip);
3789+}
3790+
3791+static inline int
3792+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
3793+{
3794+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3795+
3796+ if (ip < map->first_ip || ip > map->last_ip)
3797+ return -ERANGE;
3798+
3799+ *hash_ip = ip & map->netmask;
3800+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
3801+ if (!test_and_clear_bit(ip_to_id(map, *hash_ip), map->members))
3802+ return -EEXIST;
3803+
3804+ return 0;
3805+}
3806+
3807+static int
3808+delip(struct ip_set *set, const void *data, size_t size,
3809+ ip_set_ip_t *hash_ip)
3810+{
3811+ struct ip_set_req_ipmap *req =
3812+ (struct ip_set_req_ipmap *) data;
3813+
3814+ if (size != sizeof(struct ip_set_req_ipmap)) {
3815+ ip_set_printk("data length wrong (want %zu, have %zu)",
3816+ sizeof(struct ip_set_req_ipmap),
3817+ size);
3818+ return -EINVAL;
3819+ }
3820+ return __delip(set, req->ip, hash_ip);
3821+}
3822+
3823+static int
3824+delip_kernel(struct ip_set *set,
3825+ const struct sk_buff *skb,
3826+ ip_set_ip_t *hash_ip,
3827+ const u_int32_t *flags,
3828+ unsigned char index)
3829+{
3830+ return __delip(set,
3831+ ntohl(flags[index] & IPSET_SRC
3832+ ? skb->nh.iph->saddr
3833+ : skb->nh.iph->daddr),
3834+ hash_ip);
3835+}
3836+
3837+static int create(struct ip_set *set, const void *data, size_t size)
3838+{
3839+ int newbytes;
3840+ struct ip_set_req_ipmap_create *req =
3841+ (struct ip_set_req_ipmap_create *) data;
3842+ struct ip_set_ipmap *map;
3843+
3844+ if (size != sizeof(struct ip_set_req_ipmap_create)) {
3845+ ip_set_printk("data length wrong (want %zu, have %zu)",
3846+ sizeof(struct ip_set_req_ipmap_create),
3847+ size);
3848+ return -EINVAL;
3849+ }
3850+
3851+ DP("from %u.%u.%u.%u to %u.%u.%u.%u",
3852+ HIPQUAD(req->from), HIPQUAD(req->to));
3853+
3854+ if (req->from > req->to) {
3855+ DP("bad ip range");
3856+ return -ENOEXEC;
3857+ }
3858+
3859+ map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL);
3860+ if (!map) {
3861+ DP("out of memory for %d bytes",
3862+ sizeof(struct ip_set_ipmap));
3863+ return -ENOMEM;
3864+ }
3865+ map->first_ip = req->from;
3866+ map->last_ip = req->to;
3867+ map->netmask = req->netmask;
3868+
3869+ if (req->netmask == 0xFFFFFFFF) {
3870+ map->hosts = 1;
3871+ map->sizeid = map->last_ip - map->first_ip + 1;
3872+ } else {
3873+ unsigned int mask_bits, netmask_bits;
3874+ ip_set_ip_t mask;
3875+
3876+ map->first_ip &= map->netmask; /* Should we better bark? */
3877+
3878+ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits);
3879+ netmask_bits = mask_to_bits(map->netmask);
3880+
3881+ if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF))
3882+ || netmask_bits <= mask_bits)
3883+ return -ENOEXEC;
3884+
3885+ DP("mask_bits %u, netmask_bits %u",
3886+ mask_bits, netmask_bits);
3887+ map->hosts = 2 << (32 - netmask_bits - 1);
3888+ map->sizeid = 2 << (netmask_bits - mask_bits - 1);
3889+ }
3890+ if (map->sizeid > MAX_RANGE + 1) {
3891+ ip_set_printk("range too big (max %d addresses)",
3892+ MAX_RANGE+1);
3893+ kfree(map);
3894+ return -ENOEXEC;
3895+ }
3896+ DP("hosts %u, sizeid %u", map->hosts, map->sizeid);
3897+ newbytes = bitmap_bytes(0, map->sizeid - 1);
3898+ map->members = kmalloc(newbytes, GFP_KERNEL);
3899+ if (!map->members) {
3900+ DP("out of memory for %d bytes", newbytes);
3901+ kfree(map);
3902+ return -ENOMEM;
3903+ }
3904+ memset(map->members, 0, newbytes);
3905+
3906+ set->data = map;
3907+ return 0;
3908+}
3909+
3910+static void destroy(struct ip_set *set)
3911+{
3912+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3913+
3914+ kfree(map->members);
3915+ kfree(map);
3916+
3917+ set->data = NULL;
3918+}
3919+
3920+static void flush(struct ip_set *set)
3921+{
3922+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3923+ memset(map->members, 0, bitmap_bytes(0, map->sizeid - 1));
3924+}
3925+
3926+static void list_header(const struct ip_set *set, void *data)
3927+{
3928+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3929+ struct ip_set_req_ipmap_create *header =
3930+ (struct ip_set_req_ipmap_create *) data;
3931+
3932+ header->from = map->first_ip;
3933+ header->to = map->last_ip;
3934+ header->netmask = map->netmask;
3935+}
3936+
3937+static int list_members_size(const struct ip_set *set)
3938+{
3939+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3940+
3941+ return bitmap_bytes(0, map->sizeid - 1);
3942+}
3943+
3944+static void list_members(const struct ip_set *set, void *data)
3945+{
3946+ struct ip_set_ipmap *map = (struct ip_set_ipmap *) set->data;
3947+ int bytes = bitmap_bytes(0, map->sizeid - 1);
3948+
3949+ memcpy(data, map->members, bytes);
3950+}
3951+
3952+static struct ip_set_type ip_set_ipmap = {
3953+ .typename = SETTYPE_NAME,
3954+ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
3955+ .protocol_version = IP_SET_PROTOCOL_VERSION,
3956+ .create = &create,
3957+ .destroy = &destroy,
3958+ .flush = &flush,
3959+ .reqsize = sizeof(struct ip_set_req_ipmap),
3960+ .addip = &addip,
3961+ .addip_kernel = &addip_kernel,
3962+ .delip = &delip,
3963+ .delip_kernel = &delip_kernel,
3964+ .testip = &testip,
3965+ .testip_kernel = &testip_kernel,
3966+ .header_size = sizeof(struct ip_set_req_ipmap_create),
3967+ .list_header = &list_header,
3968+ .list_members_size = &list_members_size,
3969+ .list_members = &list_members,
3970+ .me = THIS_MODULE,
3971+};
3972+
3973+MODULE_LICENSE("GPL");
3974+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
3975+MODULE_DESCRIPTION("ipmap type of IP sets");
3976+
3977+static int __init init(void)
3978+{
3979+ return ip_set_register_set_type(&ip_set_ipmap);
3980+}
3981+
3982+static void __exit fini(void)
3983+{
3984+ /* FIXME: possible race with ip_set_create() */
3985+ ip_set_unregister_set_type(&ip_set_ipmap);
3986+}
3987+
3988+module_init(init);
3989+module_exit(fini);
3990diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_ipporthash.c linux/net/ipv4/netfilter/ip_set_ipporthash.c
3991--- linux.org/net/ipv4/netfilter/ip_set_ipporthash.c 1970-01-01 01:00:00.000000000 +0100
3992+++ linux/net/ipv4/netfilter/ip_set_ipporthash.c 2006-05-04 10:26:33.000000000 +0200
3993@@ -0,0 +1,524 @@
3994+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3995+ *
3996+ * This program is free software; you can redistribute it and/or modify
3997+ * it under the terms of the GNU General Public License version 2 as
3998+ * published by the Free Software Foundation.
3999+ */
4000+
4001+/* Kernel module implementing an ip+port hash set */
4002+
4003+#include <linux/module.h>
4004+#include <linux/ip.h>
4005+#include <linux/tcp.h>
4006+#include <linux/udp.h>
4007+#include <linux/skbuff.h>
4008+#include <linux/netfilter_ipv4/ip_tables.h>
4009+#include <linux/netfilter_ipv4/ip_set.h>
4010+#include <linux/errno.h>
4011+#include <asm/uaccess.h>
4012+#include <asm/bitops.h>
4013+#include <linux/spinlock.h>
4014+#include <linux/vmalloc.h>
4015+#include <linux/random.h>
4016+
4017+#include <net/ip.h>
4018+
4019+#include <linux/netfilter_ipv4/ip_set_malloc.h>
4020+#include <linux/netfilter_ipv4/ip_set_ipporthash.h>
4021+#include <linux/netfilter_ipv4/ip_set_jhash.h>
4022+
4023+/* We must handle non-linear skbs */
4024+static inline ip_set_ip_t
4025+get_port(const struct sk_buff *skb, u_int32_t flags)
4026+{
4027+ struct iphdr *iph = skb->nh.iph;
4028+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
4029+
4030+ switch (iph->protocol) {
4031+ case IPPROTO_TCP: {
4032+ struct tcphdr tcph;
4033+
4034+ /* See comments at tcp_match in ip_tables.c */
4035+ if (offset)
4036+ return INVALID_PORT;
4037+
4038+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
4039+ /* No choice either */
4040+ return INVALID_PORT;
4041+
4042+ return ntohs(flags & IPSET_SRC ?
4043+ tcph.source : tcph.dest);
4044+ }
4045+ case IPPROTO_UDP: {
4046+ struct udphdr udph;
4047+
4048+ if (offset)
4049+ return INVALID_PORT;
4050+
4051+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
4052+ /* No choice either */
4053+ return INVALID_PORT;
4054+
4055+ return ntohs(flags & IPSET_SRC ?
4056+ udph.source : udph.dest);
4057+ }
4058+ default:
4059+ return INVALID_PORT;
4060+ }
4061+}
4062+
4063+static inline __u32
4064+jhash_ip(const struct ip_set_ipporthash *map, uint16_t i, ip_set_ip_t ip)
4065+{
4066+ return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
4067+}
4068+
4069+#define HASH_IP(map, ip, port) (port + ((ip - ((map)->first_ip)) << 16))
4070+
4071+static inline __u32
4072+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
4073+ ip_set_ip_t *hash_ip)
4074+{
4075+ struct ip_set_ipporthash *map =
4076+ (struct ip_set_ipporthash *) set->data;
4077+ __u32 id;
4078+ u_int16_t i;
4079+ ip_set_ip_t *elem;
4080+
4081+ *hash_ip = HASH_IP(map, ip, port);
4082+ DP("set: %s, ipport:%u.%u.%u.%u:%u, %u.%u.%u.%u",
4083+ set->name, HIPQUAD(ip), port, HIPQUAD(*hash_ip));
4084+
4085+ for (i = 0; i < map->probes; i++) {
4086+ id = jhash_ip(map, i, *hash_ip) % map->hashsize;
4087+ DP("hash key: %u", id);
4088+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
4089+ if (*elem == *hash_ip)
4090+ return id;
4091+ /* No shortcut at testing - there can be deleted
4092+ * entries. */
4093+ }
4094+ return UINT_MAX;
4095+}
4096+
4097+static inline int
4098+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
4099+ ip_set_ip_t *hash_ip)
4100+{
4101+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4102+
4103+ if (ip < map->first_ip || ip > map->last_ip)
4104+ return -ERANGE;
4105+
4106+ return (hash_id(set, ip, port, hash_ip) != UINT_MAX);
4107+}
4108+
4109+static int
4110+testip(struct ip_set *set, const void *data, size_t size,
4111+ ip_set_ip_t *hash_ip)
4112+{
4113+ struct ip_set_req_ipporthash *req =
4114+ (struct ip_set_req_ipporthash *) data;
4115+
4116+ if (size != sizeof(struct ip_set_req_ipporthash)) {
4117+ ip_set_printk("data length wrong (want %zu, have %zu)",
4118+ sizeof(struct ip_set_req_ipporthash),
4119+ size);
4120+ return -EINVAL;
4121+ }
4122+ return __testip(set, req->ip, req->port, hash_ip);
4123+}
4124+
4125+static int
4126+testip_kernel(struct ip_set *set,
4127+ const struct sk_buff *skb,
4128+ ip_set_ip_t *hash_ip,
4129+ const u_int32_t *flags,
4130+ unsigned char index)
4131+{
4132+ ip_set_ip_t port;
4133+
4134+ if (flags[index+1] == 0)
4135+ return -EINVAL;
4136+
4137+ port = get_port(skb, flags[index+1]);
4138+
4139+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
4140+ flags[index] & IPSET_SRC ? "SRC" : "DST",
4141+ NIPQUAD(skb->nh.iph->saddr),
4142+ NIPQUAD(skb->nh.iph->daddr));
4143+ DP("flag %s port %u",
4144+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
4145+ port);
4146+ if (port == INVALID_PORT)
4147+ return 0;
4148+
4149+ return __testip(set,
4150+ ntohl(flags[index] & IPSET_SRC
4151+ ? skb->nh.iph->saddr
4152+ : skb->nh.iph->daddr),
4153+ port,
4154+ hash_ip);
4155+}
4156+
4157+static inline int
4158+__add_haship(struct ip_set_ipporthash *map, ip_set_ip_t hash_ip)
4159+{
4160+ __u32 probe;
4161+ u_int16_t i;
4162+ ip_set_ip_t *elem;
4163+
4164+ for (i = 0; i < map->probes; i++) {
4165+ probe = jhash_ip(map, i, hash_ip) % map->hashsize;
4166+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
4167+ if (*elem == hash_ip)
4168+ return -EEXIST;
4169+ if (!*elem) {
4170+ *elem = hash_ip;
4171+ return 0;
4172+ }
4173+ }
4174+ /* Trigger rehashing */
4175+ return -EAGAIN;
4176+}
4177+
4178+static inline int
4179+__addip(struct ip_set_ipporthash *map, ip_set_ip_t ip, ip_set_ip_t port,
4180+ ip_set_ip_t *hash_ip)
4181+{
4182+ if (ip < map->first_ip || ip > map->last_ip)
4183+ return -ERANGE;
4184+
4185+ *hash_ip = HASH_IP(map, ip, port);
4186+
4187+ return __add_haship(map, *hash_ip);
4188+}
4189+
4190+static int
4191+addip(struct ip_set *set, const void *data, size_t size,
4192+ ip_set_ip_t *hash_ip)
4193+{
4194+ struct ip_set_req_ipporthash *req =
4195+ (struct ip_set_req_ipporthash *) data;
4196+
4197+ if (size != sizeof(struct ip_set_req_ipporthash)) {
4198+ ip_set_printk("data length wrong (want %zu, have %zu)",
4199+ sizeof(struct ip_set_req_ipporthash),
4200+ size);
4201+ return -EINVAL;
4202+ }
4203+ return __addip((struct ip_set_ipporthash *) set->data,
4204+ req->ip, req->port, hash_ip);
4205+}
4206+
4207+static int
4208+addip_kernel(struct ip_set *set,
4209+ const struct sk_buff *skb,
4210+ ip_set_ip_t *hash_ip,
4211+ const u_int32_t *flags,
4212+ unsigned char index)
4213+{
4214+ ip_set_ip_t port;
4215+
4216+ if (flags[index+1] == 0)
4217+ return -EINVAL;
4218+
4219+ port = get_port(skb, flags[index+1]);
4220+
4221+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
4222+ flags[index] & IPSET_SRC ? "SRC" : "DST",
4223+ NIPQUAD(skb->nh.iph->saddr),
4224+ NIPQUAD(skb->nh.iph->daddr));
4225+ DP("flag %s port %u",
4226+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
4227+ port);
4228+ if (port == INVALID_PORT)
4229+ return -EINVAL;
4230+
4231+ return __addip((struct ip_set_ipporthash *) set->data,
4232+ ntohl(flags[index] & IPSET_SRC
4233+ ? skb->nh.iph->saddr
4234+ : skb->nh.iph->daddr),
4235+ port,
4236+ hash_ip);
4237+}
4238+
4239+static int retry(struct ip_set *set)
4240+{
4241+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4242+ ip_set_ip_t *elem;
4243+ void *members;
4244+ u_int32_t i, hashsize = map->hashsize;
4245+ int res;
4246+ struct ip_set_ipporthash *tmp;
4247+
4248+ if (map->resize == 0)
4249+ return -ERANGE;
4250+
4251+ again:
4252+ res = 0;
4253+
4254+ /* Calculate new hash size */
4255+ hashsize += (hashsize * map->resize)/100;
4256+ if (hashsize == map->hashsize)
4257+ hashsize++;
4258+
4259+ ip_set_printk("rehashing of set %s triggered: "
4260+ "hashsize grows from %u to %u",
4261+ set->name, map->hashsize, hashsize);
4262+
4263+ tmp = kmalloc(sizeof(struct ip_set_ipporthash)
4264+ + map->probes * sizeof(uint32_t), GFP_ATOMIC);
4265+ if (!tmp) {
4266+ DP("out of memory for %d bytes",
4267+ sizeof(struct ip_set_ipporthash)
4268+ + map->probes * sizeof(uint32_t));
4269+ return -ENOMEM;
4270+ }
4271+ tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
4272+ if (!tmp->members) {
4273+ DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
4274+ kfree(tmp);
4275+ return -ENOMEM;
4276+ }
4277+ tmp->hashsize = hashsize;
4278+ tmp->probes = map->probes;
4279+ tmp->resize = map->resize;
4280+ tmp->first_ip = map->first_ip;
4281+ tmp->last_ip = map->last_ip;
4282+ memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
4283+
4284+ write_lock_bh(&set->lock);
4285+ map = (struct ip_set_ipporthash *) set->data; /* Play safe */
4286+ for (i = 0; i < map->hashsize && res == 0; i++) {
4287+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
4288+ if (*elem)
4289+ res = __add_haship(tmp, *elem);
4290+ }
4291+ if (res) {
4292+ /* Failure, try again */
4293+ write_unlock_bh(&set->lock);
4294+ harray_free(tmp->members);
4295+ kfree(tmp);
4296+ goto again;
4297+ }
4298+
4299+ /* Success at resizing! */
4300+ members = map->members;
4301+
4302+ map->hashsize = tmp->hashsize;
4303+ map->members = tmp->members;
4304+ write_unlock_bh(&set->lock);
4305+
4306+ harray_free(members);
4307+ kfree(tmp);
4308+
4309+ return 0;
4310+}
4311+
4312+static inline int
4313+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t port,
4314+ ip_set_ip_t *hash_ip)
4315+{
4316+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4317+ ip_set_ip_t id;
4318+ ip_set_ip_t *elem;
4319+
4320+ if (ip < map->first_ip || ip > map->last_ip)
4321+ return -ERANGE;
4322+
4323+ id = hash_id(set, ip, port, hash_ip);
4324+
4325+ if (id == UINT_MAX)
4326+ return -EEXIST;
4327+
4328+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
4329+ *elem = 0;
4330+
4331+ return 0;
4332+}
4333+
4334+static int
4335+delip(struct ip_set *set, const void *data, size_t size,
4336+ ip_set_ip_t *hash_ip)
4337+{
4338+ struct ip_set_req_ipporthash *req =
4339+ (struct ip_set_req_ipporthash *) data;
4340+
4341+ if (size != sizeof(struct ip_set_req_ipporthash)) {
4342+ ip_set_printk("data length wrong (want %zu, have %zu)",
4343+ sizeof(struct ip_set_req_ipporthash),
4344+ size);
4345+ return -EINVAL;
4346+ }
4347+ return __delip(set, req->ip, req->port, hash_ip);
4348+}
4349+
4350+static int
4351+delip_kernel(struct ip_set *set,
4352+ const struct sk_buff *skb,
4353+ ip_set_ip_t *hash_ip,
4354+ const u_int32_t *flags,
4355+ unsigned char index)
4356+{
4357+ ip_set_ip_t port;
4358+
4359+ if (flags[index+1] == 0)
4360+ return -EINVAL;
4361+
4362+ port = get_port(skb, flags[index+1]);
4363+
4364+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
4365+ flags[index] & IPSET_SRC ? "SRC" : "DST",
4366+ NIPQUAD(skb->nh.iph->saddr),
4367+ NIPQUAD(skb->nh.iph->daddr));
4368+ DP("flag %s port %u",
4369+ flags[index+1] & IPSET_SRC ? "SRC" : "DST",
4370+ port);
4371+ if (port == INVALID_PORT)
4372+ return -EINVAL;
4373+
4374+ return __delip(set,
4375+ ntohl(flags[index] & IPSET_SRC
4376+ ? skb->nh.iph->saddr
4377+ : skb->nh.iph->daddr),
4378+ port,
4379+ hash_ip);
4380+}
4381+
4382+static int create(struct ip_set *set, const void *data, size_t size)
4383+{
4384+ struct ip_set_req_ipporthash_create *req =
4385+ (struct ip_set_req_ipporthash_create *) data;
4386+ struct ip_set_ipporthash *map;
4387+ uint16_t i;
4388+
4389+ if (size != sizeof(struct ip_set_req_ipporthash_create)) {
4390+ ip_set_printk("data length wrong (want %zu, have %zu)",
4391+ sizeof(struct ip_set_req_ipporthash_create),
4392+ size);
4393+ return -EINVAL;
4394+ }
4395+
4396+ if (req->hashsize < 1) {
4397+ ip_set_printk("hashsize too small");
4398+ return -ENOEXEC;
4399+ }
4400+
4401+ if (req->probes < 1) {
4402+ ip_set_printk("probes too small");
4403+ return -ENOEXEC;
4404+ }
4405+
4406+ map = kmalloc(sizeof(struct ip_set_ipporthash)
4407+ + req->probes * sizeof(uint32_t), GFP_KERNEL);
4408+ if (!map) {
4409+ DP("out of memory for %d bytes",
4410+ sizeof(struct ip_set_ipporthash)
4411+ + req->probes * sizeof(uint32_t));
4412+ return -ENOMEM;
4413+ }
4414+ for (i = 0; i < req->probes; i++)
4415+ get_random_bytes(((uint32_t *) map->initval)+i, 4);
4416+ map->hashsize = req->hashsize;
4417+ map->probes = req->probes;
4418+ map->resize = req->resize;
4419+ map->first_ip = req->from;
4420+ map->last_ip = req->to;
4421+ map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
4422+ if (!map->members) {
4423+ DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
4424+ kfree(map);
4425+ return -ENOMEM;
4426+ }
4427+
4428+ set->data = map;
4429+ return 0;
4430+}
4431+
4432+static void destroy(struct ip_set *set)
4433+{
4434+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4435+
4436+ harray_free(map->members);
4437+ kfree(map);
4438+
4439+ set->data = NULL;
4440+}
4441+
4442+static void flush(struct ip_set *set)
4443+{
4444+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4445+ harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
4446+}
4447+
4448+static void list_header(const struct ip_set *set, void *data)
4449+{
4450+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4451+ struct ip_set_req_ipporthash_create *header =
4452+ (struct ip_set_req_ipporthash_create *) data;
4453+
4454+ header->hashsize = map->hashsize;
4455+ header->probes = map->probes;
4456+ header->resize = map->resize;
4457+ header->from = map->first_ip;
4458+ header->to = map->last_ip;
4459+}
4460+
4461+static int list_members_size(const struct ip_set *set)
4462+{
4463+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4464+
4465+ return (map->hashsize * sizeof(ip_set_ip_t));
4466+}
4467+
4468+static void list_members(const struct ip_set *set, void *data)
4469+{
4470+ struct ip_set_ipporthash *map = (struct ip_set_ipporthash *) set->data;
4471+ ip_set_ip_t i, *elem;
4472+
4473+ for (i = 0; i < map->hashsize; i++) {
4474+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
4475+ ((ip_set_ip_t *)data)[i] = *elem;
4476+ }
4477+}
4478+
4479+static struct ip_set_type ip_set_ipporthash = {
4480+ .typename = SETTYPE_NAME,
4481+ .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_DATA_DOUBLE,
4482+ .protocol_version = IP_SET_PROTOCOL_VERSION,
4483+ .create = &create,
4484+ .destroy = &destroy,
4485+ .flush = &flush,
4486+ .reqsize = sizeof(struct ip_set_req_ipporthash),
4487+ .addip = &addip,
4488+ .addip_kernel = &addip_kernel,
4489+ .retry = &retry,
4490+ .delip = &delip,
4491+ .delip_kernel = &delip_kernel,
4492+ .testip = &testip,
4493+ .testip_kernel = &testip_kernel,
4494+ .header_size = sizeof(struct ip_set_req_ipporthash_create),
4495+ .list_header = &list_header,
4496+ .list_members_size = &list_members_size,
4497+ .list_members = &list_members,
4498+ .me = THIS_MODULE,
4499+};
4500+
4501+MODULE_LICENSE("GPL");
4502+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
4503+MODULE_DESCRIPTION("ipporthash type of IP sets");
4504+
4505+static int __init init(void)
4506+{
4507+ return ip_set_register_set_type(&ip_set_ipporthash);
4508+}
4509+
4510+static void __exit fini(void)
4511+{
4512+ /* FIXME: possible race with ip_set_create() */
4513+ ip_set_unregister_set_type(&ip_set_ipporthash);
4514+}
4515+
4516+module_init(init);
4517+module_exit(fini);
4518diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_iptree.c linux/net/ipv4/netfilter/ip_set_iptree.c
4519--- linux.org/net/ipv4/netfilter/ip_set_iptree.c 1970-01-01 01:00:00.000000000 +0100
4520+++ linux/net/ipv4/netfilter/ip_set_iptree.c 2006-05-04 10:26:33.000000000 +0200
4521@@ -0,0 +1,544 @@
4522+/* Copyright (C) 2005 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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 version 2 as
4526+ * published by the Free Software Foundation.
4527+ */
4528+
4529+/* Kernel module implementing an IP set type: the iptree type */
4530+
4531+#include <linux/module.h>
4532+#include <linux/ip.h>
4533+#include <linux/skbuff.h>
4534+#include <linux/slab.h>
4535+#include <linux/delay.h>
4536+#include <linux/netfilter_ipv4/ip_tables.h>
4537+#include <linux/netfilter_ipv4/ip_set.h>
4538+#include <linux/errno.h>
4539+#include <asm/uaccess.h>
4540+#include <asm/bitops.h>
4541+#include <linux/spinlock.h>
4542+
4543+/* Backward compatibility */
4544+#ifndef __nocast
4545+#define __nocast
4546+#endif
4547+
4548+#include <linux/netfilter_ipv4/ip_set_iptree.h>
4549+
4550+/* Garbage collection interval in seconds: */
4551+#define IPTREE_GC_TIME 5*60
4552+/* Sleep so many milliseconds before trying again
4553+ * to delete the gc timer at destroying/flushing a set */
4554+#define IPTREE_DESTROY_SLEEP 100
4555+
4556+static kmem_cache_t *branch_cachep;
4557+static kmem_cache_t *leaf_cachep;
4558+
4559+#define ABCD(a,b,c,d,addrp) do { \
4560+ a = ((unsigned char *)addrp)[3]; \
4561+ b = ((unsigned char *)addrp)[2]; \
4562+ c = ((unsigned char *)addrp)[1]; \
4563+ d = ((unsigned char *)addrp)[0]; \
4564+} while (0)
4565+
4566+#define TESTIP_WALK(map, elem, branch) do { \
4567+ if ((map)->tree[elem]) { \
4568+ branch = (map)->tree[elem]; \
4569+ } else \
4570+ return 0; \
4571+} while (0)
4572+
4573+static inline int
4574+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
4575+{
4576+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4577+ struct ip_set_iptreeb *btree;
4578+ struct ip_set_iptreec *ctree;
4579+ struct ip_set_iptreed *dtree;
4580+ unsigned char a,b,c,d;
4581+
4582+ *hash_ip = ip;
4583+ ABCD(a, b, c, d, hash_ip);
4584+ DP("%u %u %u %u timeout %u", a, b, c, d, map->timeout);
4585+ TESTIP_WALK(map, a, btree);
4586+ TESTIP_WALK(btree, b, ctree);
4587+ TESTIP_WALK(ctree, c, dtree);
4588+ DP("%lu %lu", dtree->expires[d], jiffies);
4589+ return !!(map->timeout ? (time_after(dtree->expires[d], jiffies))
4590+ : dtree->expires[d]);
4591+}
4592+
4593+static int
4594+testip(struct ip_set *set, const void *data, size_t size,
4595+ ip_set_ip_t *hash_ip)
4596+{
4597+ struct ip_set_req_iptree *req =
4598+ (struct ip_set_req_iptree *) data;
4599+
4600+ if (size != sizeof(struct ip_set_req_iptree)) {
4601+ ip_set_printk("data length wrong (want %zu, have %zu)",
4602+ sizeof(struct ip_set_req_iptree),
4603+ size);
4604+ return -EINVAL;
4605+ }
4606+ return __testip(set, req->ip, hash_ip);
4607+}
4608+
4609+static int
4610+testip_kernel(struct ip_set *set,
4611+ const struct sk_buff *skb,
4612+ ip_set_ip_t *hash_ip,
4613+ const u_int32_t *flags,
4614+ unsigned char index)
4615+{
4616+ int res;
4617+
4618+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
4619+ flags[index] & IPSET_SRC ? "SRC" : "DST",
4620+ NIPQUAD(skb->nh.iph->saddr),
4621+ NIPQUAD(skb->nh.iph->daddr));
4622+
4623+ res = __testip(set,
4624+ ntohl(flags[index] & IPSET_SRC
4625+ ? skb->nh.iph->saddr
4626+ : skb->nh.iph->daddr),
4627+ hash_ip);
4628+ return (res < 0 ? 0 : res);
4629+}
4630+
4631+#define ADDIP_WALK(map, elem, branch, type, cachep, flags) do { \
4632+ if ((map)->tree[elem]) { \
4633+ DP("found %u", elem); \
4634+ branch = (map)->tree[elem]; \
4635+ } else { \
4636+ branch = (type *) \
4637+ kmem_cache_alloc(cachep, flags); \
4638+ if (branch == NULL) \
4639+ return -ENOMEM; \
4640+ memset(branch, 0, sizeof(*branch)); \
4641+ (map)->tree[elem] = branch; \
4642+ DP("alloc %u", elem); \
4643+ } \
4644+} while (0)
4645+
4646+static inline int
4647+__addip(struct ip_set *set, ip_set_ip_t ip, unsigned int timeout,
4648+ ip_set_ip_t *hash_ip,
4649+ unsigned int __nocast flags)
4650+{
4651+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4652+ struct ip_set_iptreeb *btree;
4653+ struct ip_set_iptreec *ctree;
4654+ struct ip_set_iptreed *dtree;
4655+ unsigned char a,b,c,d;
4656+ int ret = 0;
4657+
4658+ *hash_ip = ip;
4659+ ABCD(a, b, c, d, hash_ip);
4660+ DP("%u %u %u %u timeout %u", a, b, c, d, timeout);
4661+ ADDIP_WALK(map, a, btree, struct ip_set_iptreeb, branch_cachep, flags);
4662+ ADDIP_WALK(btree, b, ctree, struct ip_set_iptreec, branch_cachep, flags);
4663+ ADDIP_WALK(ctree, c, dtree, struct ip_set_iptreed, leaf_cachep, flags);
4664+ if (dtree->expires[d]
4665+ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
4666+ ret = -EEXIST;
4667+ dtree->expires[d] = map->timeout ? (timeout * HZ + jiffies) : 1;
4668+ /* Lottery */
4669+ if (dtree->expires[d] == 0)
4670+ dtree->expires[d] = 1;
4671+ DP("%u %lu", d, dtree->expires[d]);
4672+ return ret;
4673+}
4674+
4675+static int
4676+addip(struct ip_set *set, const void *data, size_t size,
4677+ ip_set_ip_t *hash_ip)
4678+{
4679+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4680+ struct ip_set_req_iptree *req =
4681+ (struct ip_set_req_iptree *) data;
4682+
4683+ if (size != sizeof(struct ip_set_req_iptree)) {
4684+ ip_set_printk("data length wrong (want %zu, have %zu)",
4685+ sizeof(struct ip_set_req_iptree),
4686+ size);
4687+ return -EINVAL;
4688+ }
4689+ DP("%u.%u.%u.%u %u", HIPQUAD(req->ip), req->timeout);
4690+ return __addip(set, req->ip,
4691+ req->timeout ? req->timeout : map->timeout,
4692+ hash_ip,
4693+ GFP_ATOMIC);
4694+}
4695+
4696+static int
4697+addip_kernel(struct ip_set *set,
4698+ const struct sk_buff *skb,
4699+ ip_set_ip_t *hash_ip,
4700+ const u_int32_t *flags,
4701+ unsigned char index)
4702+{
4703+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4704+
4705+ return __addip(set,
4706+ ntohl(flags[index] & IPSET_SRC
4707+ ? skb->nh.iph->saddr
4708+ : skb->nh.iph->daddr),
4709+ map->timeout,
4710+ hash_ip,
4711+ GFP_ATOMIC);
4712+}
4713+
4714+#define DELIP_WALK(map, elem, branch) do { \
4715+ if ((map)->tree[elem]) { \
4716+ branch = (map)->tree[elem]; \
4717+ } else \
4718+ return -EEXIST; \
4719+} while (0)
4720+
4721+static inline int
4722+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
4723+{
4724+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4725+ struct ip_set_iptreeb *btree;
4726+ struct ip_set_iptreec *ctree;
4727+ struct ip_set_iptreed *dtree;
4728+ unsigned char a,b,c,d;
4729+
4730+ *hash_ip = ip;
4731+ ABCD(a, b, c, d, hash_ip);
4732+ DELIP_WALK(map, a, btree);
4733+ DELIP_WALK(btree, b, ctree);
4734+ DELIP_WALK(ctree, c, dtree);
4735+
4736+ if (dtree->expires[d]) {
4737+ dtree->expires[d] = 0;
4738+ return 0;
4739+ }
4740+ return -EEXIST;
4741+}
4742+
4743+static int
4744+delip(struct ip_set *set, const void *data, size_t size,
4745+ ip_set_ip_t *hash_ip)
4746+{
4747+ struct ip_set_req_iptree *req =
4748+ (struct ip_set_req_iptree *) data;
4749+
4750+ if (size != sizeof(struct ip_set_req_iptree)) {
4751+ ip_set_printk("data length wrong (want %zu, have %zu)",
4752+ sizeof(struct ip_set_req_iptree),
4753+ size);
4754+ return -EINVAL;
4755+ }
4756+ return __delip(set, req->ip, hash_ip);
4757+}
4758+
4759+static int
4760+delip_kernel(struct ip_set *set,
4761+ const struct sk_buff *skb,
4762+ ip_set_ip_t *hash_ip,
4763+ const u_int32_t *flags,
4764+ unsigned char index)
4765+{
4766+ return __delip(set,
4767+ ntohl(flags[index] & IPSET_SRC
4768+ ? skb->nh.iph->saddr
4769+ : skb->nh.iph->daddr),
4770+ hash_ip);
4771+}
4772+
4773+#define LOOP_WALK_BEGIN(map, i, branch) \
4774+ for (i = 0; i < 256; i++) { \
4775+ if (!(map)->tree[i]) \
4776+ continue; \
4777+ branch = (map)->tree[i]
4778+
4779+#define LOOP_WALK_END }
4780+
4781+static void ip_tree_gc(unsigned long ul_set)
4782+{
4783+ struct ip_set *set = (void *) ul_set;
4784+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4785+ struct ip_set_iptreeb *btree;
4786+ struct ip_set_iptreec *ctree;
4787+ struct ip_set_iptreed *dtree;
4788+ unsigned int a,b,c,d;
4789+ unsigned char i,j,k;
4790+
4791+ i = j = k = 0;
4792+ DP("gc: %s", set->name);
4793+ write_lock_bh(&set->lock);
4794+ LOOP_WALK_BEGIN(map, a, btree);
4795+ LOOP_WALK_BEGIN(btree, b, ctree);
4796+ LOOP_WALK_BEGIN(ctree, c, dtree);
4797+ for (d = 0; d < 256; d++) {
4798+ if (dtree->expires[d]) {
4799+ DP("gc: %u %u %u %u: expires %lu jiffies %lu",
4800+ a, b, c, d,
4801+ dtree->expires[d], jiffies);
4802+ if (map->timeout
4803+ && time_before(dtree->expires[d], jiffies))
4804+ dtree->expires[d] = 0;
4805+ else
4806+ k = 1;
4807+ }
4808+ }
4809+ if (k == 0) {
4810+ DP("gc: %s: leaf %u %u %u empty",
4811+ set->name, a, b, c);
4812+ kmem_cache_free(leaf_cachep, dtree);
4813+ ctree->tree[c] = NULL;
4814+ } else {
4815+ DP("gc: %s: leaf %u %u %u not empty",
4816+ set->name, a, b, c);
4817+ j = 1;
4818+ k = 0;
4819+ }
4820+ LOOP_WALK_END;
4821+ if (j == 0) {
4822+ DP("gc: %s: branch %u %u empty",
4823+ set->name, a, b);
4824+ kmem_cache_free(branch_cachep, ctree);
4825+ btree->tree[b] = NULL;
4826+ } else {
4827+ DP("gc: %s: branch %u %u not empty",
4828+ set->name, a, b);
4829+ i = 1;
4830+ j = k = 0;
4831+ }
4832+ LOOP_WALK_END;
4833+ if (i == 0) {
4834+ DP("gc: %s: branch %u empty",
4835+ set->name, a);
4836+ kmem_cache_free(branch_cachep, btree);
4837+ map->tree[a] = NULL;
4838+ } else {
4839+ DP("gc: %s: branch %u not empty",
4840+ set->name, a);
4841+ i = j = k = 0;
4842+ }
4843+ LOOP_WALK_END;
4844+ write_unlock_bh(&set->lock);
4845+
4846+ map->gc.expires = jiffies + map->gc_interval * HZ;
4847+ add_timer(&map->gc);
4848+}
4849+
4850+static inline void init_gc_timer(struct ip_set *set)
4851+{
4852+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4853+
4854+ /* Even if there is no timeout for the entries,
4855+ * we still have to call gc because delete
4856+ * do not clean up empty branches */
4857+ map->gc_interval = IPTREE_GC_TIME;
4858+ init_timer(&map->gc);
4859+ map->gc.data = (unsigned long) set;
4860+ map->gc.function = ip_tree_gc;
4861+ map->gc.expires = jiffies + map->gc_interval * HZ;
4862+ add_timer(&map->gc);
4863+}
4864+
4865+static int create(struct ip_set *set, const void *data, size_t size)
4866+{
4867+ struct ip_set_req_iptree_create *req =
4868+ (struct ip_set_req_iptree_create *) data;
4869+ struct ip_set_iptree *map;
4870+
4871+ if (size != sizeof(struct ip_set_req_iptree_create)) {
4872+ ip_set_printk("data length wrong (want %zu, have %zu)",
4873+ sizeof(struct ip_set_req_iptree_create),
4874+ size);
4875+ return -EINVAL;
4876+ }
4877+
4878+ map = kmalloc(sizeof(struct ip_set_iptree), GFP_KERNEL);
4879+ if (!map) {
4880+ DP("out of memory for %d bytes",
4881+ sizeof(struct ip_set_iptree));
4882+ return -ENOMEM;
4883+ }
4884+ memset(map, 0, sizeof(*map));
4885+ map->timeout = req->timeout;
4886+ set->data = map;
4887+
4888+ init_gc_timer(set);
4889+
4890+ return 0;
4891+}
4892+
4893+static void __flush(struct ip_set_iptree *map)
4894+{
4895+ struct ip_set_iptreeb *btree;
4896+ struct ip_set_iptreec *ctree;
4897+ struct ip_set_iptreed *dtree;
4898+ unsigned int a,b,c;
4899+
4900+ LOOP_WALK_BEGIN(map, a, btree);
4901+ LOOP_WALK_BEGIN(btree, b, ctree);
4902+ LOOP_WALK_BEGIN(ctree, c, dtree);
4903+ kmem_cache_free(leaf_cachep, dtree);
4904+ LOOP_WALK_END;
4905+ kmem_cache_free(branch_cachep, ctree);
4906+ LOOP_WALK_END;
4907+ kmem_cache_free(branch_cachep, btree);
4908+ LOOP_WALK_END;
4909+}
4910+
4911+static void destroy(struct ip_set *set)
4912+{
4913+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4914+
4915+ /* gc might be running */
4916+ while (!del_timer(&map->gc))
4917+ msleep(IPTREE_DESTROY_SLEEP);
4918+ __flush(map);
4919+ kfree(map);
4920+ set->data = NULL;
4921+}
4922+
4923+static void flush(struct ip_set *set)
4924+{
4925+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4926+ unsigned int timeout = map->timeout;
4927+
4928+ /* gc might be running */
4929+ while (!del_timer(&map->gc))
4930+ msleep(IPTREE_DESTROY_SLEEP);
4931+ __flush(map);
4932+ memset(map, 0, sizeof(*map));
4933+ map->timeout = timeout;
4934+
4935+ init_gc_timer(set);
4936+}
4937+
4938+static void list_header(const struct ip_set *set, void *data)
4939+{
4940+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4941+ struct ip_set_req_iptree_create *header =
4942+ (struct ip_set_req_iptree_create *) data;
4943+
4944+ header->timeout = map->timeout;
4945+}
4946+
4947+static int list_members_size(const struct ip_set *set)
4948+{
4949+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4950+ struct ip_set_iptreeb *btree;
4951+ struct ip_set_iptreec *ctree;
4952+ struct ip_set_iptreed *dtree;
4953+ unsigned int a,b,c,d;
4954+ unsigned int count = 0;
4955+
4956+ LOOP_WALK_BEGIN(map, a, btree);
4957+ LOOP_WALK_BEGIN(btree, b, ctree);
4958+ LOOP_WALK_BEGIN(ctree, c, dtree);
4959+ for (d = 0; d < 256; d++) {
4960+ if (dtree->expires[d]
4961+ && (!map->timeout || time_after(dtree->expires[d], jiffies)))
4962+ count++;
4963+ }
4964+ LOOP_WALK_END;
4965+ LOOP_WALK_END;
4966+ LOOP_WALK_END;
4967+
4968+ DP("members %u", count);
4969+ return (count * sizeof(struct ip_set_req_iptree));
4970+}
4971+
4972+static void list_members(const struct ip_set *set, void *data)
4973+{
4974+ struct ip_set_iptree *map = (struct ip_set_iptree *) set->data;
4975+ struct ip_set_iptreeb *btree;
4976+ struct ip_set_iptreec *ctree;
4977+ struct ip_set_iptreed *dtree;
4978+ unsigned int a,b,c,d;
4979+ size_t offset = 0;
4980+ struct ip_set_req_iptree *entry;
4981+
4982+ LOOP_WALK_BEGIN(map, a, btree);
4983+ LOOP_WALK_BEGIN(btree, b, ctree);
4984+ LOOP_WALK_BEGIN(ctree, c, dtree);
4985+ for (d = 0; d < 256; d++) {
4986+ if (dtree->expires[d]
4987+ && (!map->timeout || time_after(dtree->expires[d], jiffies))) {
4988+ entry = (struct ip_set_req_iptree *)(data + offset);
4989+ entry->ip = ((a << 24) | (b << 16) | (c << 8) | d);
4990+ entry->timeout = !map->timeout ? 0
4991+ : (dtree->expires[d] - jiffies)/HZ;
4992+ offset += sizeof(struct ip_set_req_iptree);
4993+ }
4994+ }
4995+ LOOP_WALK_END;
4996+ LOOP_WALK_END;
4997+ LOOP_WALK_END;
4998+}
4999+
5000+static struct ip_set_type ip_set_iptree = {
5001+ .typename = SETTYPE_NAME,
5002+ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
5003+ .protocol_version = IP_SET_PROTOCOL_VERSION,
5004+ .create = &create,
5005+ .destroy = &destroy,
5006+ .flush = &flush,
5007+ .reqsize = sizeof(struct ip_set_req_iptree),
5008+ .addip = &addip,
5009+ .addip_kernel = &addip_kernel,
5010+ .delip = &delip,
5011+ .delip_kernel = &delip_kernel,
5012+ .testip = &testip,
5013+ .testip_kernel = &testip_kernel,
5014+ .header_size = sizeof(struct ip_set_req_iptree_create),
5015+ .list_header = &list_header,
5016+ .list_members_size = &list_members_size,
5017+ .list_members = &list_members,
5018+ .me = THIS_MODULE,
5019+};
5020+
5021+MODULE_LICENSE("GPL");
5022+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5023+MODULE_DESCRIPTION("iptree type of IP sets");
5024+
5025+static int __init init(void)
5026+{
5027+ int ret;
5028+
5029+ branch_cachep = kmem_cache_create("ip_set_iptreeb",
5030+ sizeof(struct ip_set_iptreeb),
5031+ 0, 0, NULL, NULL);
5032+ if (!branch_cachep) {
5033+ printk(KERN_ERR "Unable to create ip_set_iptreeb slab cache\n");
5034+ ret = -ENOMEM;
5035+ goto out;
5036+ }
5037+ leaf_cachep = kmem_cache_create("ip_set_iptreed",
5038+ sizeof(struct ip_set_iptreed),
5039+ 0, 0, NULL, NULL);
5040+ if (!leaf_cachep) {
5041+ printk(KERN_ERR "Unable to create ip_set_iptreed slab cache\n");
5042+ ret = -ENOMEM;
5043+ goto free_branch;
5044+ }
5045+ ret = ip_set_register_set_type(&ip_set_iptree);
5046+ if (ret == 0)
5047+ goto out;
5048+
5049+ kmem_cache_destroy(leaf_cachep);
5050+ free_branch:
5051+ kmem_cache_destroy(branch_cachep);
5052+ out:
5053+ return ret;
5054+}
5055+
5056+static void __exit fini(void)
5057+{
5058+ /* FIXME: possible race with ip_set_create() */
5059+ ip_set_unregister_set_type(&ip_set_iptree);
5060+ kmem_cache_destroy(leaf_cachep);
5061+ kmem_cache_destroy(branch_cachep);
5062+}
5063+
5064+module_init(init);
5065+module_exit(fini);
5066diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_macipmap.c linux/net/ipv4/netfilter/ip_set_macipmap.c
5067--- linux.org/net/ipv4/netfilter/ip_set_macipmap.c 1970-01-01 01:00:00.000000000 +0100
5068+++ linux/net/ipv4/netfilter/ip_set_macipmap.c 2006-05-04 10:26:33.000000000 +0200
5069@@ -0,0 +1,353 @@
5070+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
5071+ * Patrick Schaaf <bof@bof.de>
5072+ * Martin Josefsson <gandalf@wlug.westbo.se>
5073+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5074+ *
5075+ * This program is free software; you can redistribute it and/or modify
5076+ * it under the terms of the GNU General Public License version 2 as
5077+ * published by the Free Software Foundation.
5078+ */
5079+
5080+/* Kernel module implementing an IP set type: the macipmap type */
5081+
5082+#include <linux/module.h>
5083+#include <linux/ip.h>
5084+#include <linux/skbuff.h>
5085+#include <linux/netfilter_ipv4/ip_tables.h>
5086+#include <linux/netfilter_ipv4/ip_set.h>
5087+#include <linux/errno.h>
5088+#include <asm/uaccess.h>
5089+#include <asm/bitops.h>
5090+#include <linux/spinlock.h>
5091+#include <linux/if_ether.h>
5092+#include <linux/vmalloc.h>
5093+
5094+#include <linux/netfilter_ipv4/ip_set_malloc.h>
5095+#include <linux/netfilter_ipv4/ip_set_macipmap.h>
5096+
5097+static int
5098+testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
5099+{
5100+ struct ip_set_macipmap *map = (struct ip_set_macipmap *) set->data;
5101+ struct ip_set_macip *table = (struct ip_set_macip *) map->members;
5102+ struct ip_set_req_macipmap *req = (struct ip_set_req_macipmap *) data;
5103+
5104+ if (size != sizeof(struct ip_set_req_macipmap)) {
5105+ ip_set_printk("data length wrong (want %zu, have %zu)",
5106+ sizeof(struct ip_set_req_macipmap),
5107+ size);
5108+ return -EINVAL;
5109+ }
5110+
5111+ if (req->ip < map->first_ip || req->ip > map->last_ip)
5112+ return -ERANGE;
5113+
5114+ *hash_ip = req->ip;
5115+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
5116+ set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
5117+ if (test_bit(IPSET_MACIP_ISSET,
5118+ (void *) &table[req->ip - map->first_ip].flags)) {
5119+ return (memcmp(req->ethernet,
5120+ &table[req->ip - map->first_ip].ethernet,
5121+ ETH_ALEN) == 0);
5122+ } else {
5123+ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
5124+ }
5125+}
5126+
5127+static int
5128+testip_kernel(struct ip_set *set,
5129+ const struct sk_buff *skb,
5130+ ip_set_ip_t *hash_ip,
5131+ const u_int32_t *flags,
5132+ unsigned char index)
5133+{
5134+ struct ip_set_macipmap *map =
5135+ (struct ip_set_macipmap *) set->data;
5136+ struct ip_set_macip *table =
5137+ (struct ip_set_macip *) map->members;
5138+ ip_set_ip_t ip;
5139+
5140+ ip = ntohl(flags[index] & IPSET_SRC
5141+ ? skb->nh.iph->saddr
5142+ : skb->nh.iph->daddr);
5143+ DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
5144+ flags[index] & IPSET_SRC ? "SRC" : "DST",
5145+ NIPQUAD(skb->nh.iph->saddr),
5146+ NIPQUAD(skb->nh.iph->daddr));
5147+
5148+ if (ip < map->first_ip || ip > map->last_ip)
5149+ return 0;
5150+
5151+ *hash_ip = ip;
5152+ DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
5153+ set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
5154+ if (test_bit(IPSET_MACIP_ISSET,
5155+ (void *) &table[ip - map->first_ip].flags)) {
5156+ /* Is mac pointer valid?
5157+ * If so, compare... */
5158+ return (skb->mac.raw >= skb->head
5159+ && (skb->mac.raw + ETH_HLEN) <= skb->data
5160+ && (memcmp(eth_hdr(skb)->h_source,
5161+ &table[ip - map->first_ip].ethernet,
5162+ ETH_ALEN) == 0));
5163+ } else {
5164+ return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
5165+ }
5166+}
5167+
5168+/* returns 0 on success */
5169+static inline int
5170+__addip(struct ip_set *set,
5171+ ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *hash_ip)
5172+{
5173+ struct ip_set_macipmap *map =
5174+ (struct ip_set_macipmap *) set->data;
5175+ struct ip_set_macip *table =
5176+ (struct ip_set_macip *) map->members;
5177+
5178+ if (ip < map->first_ip || ip > map->last_ip)
5179+ return -ERANGE;
5180+ if (test_and_set_bit(IPSET_MACIP_ISSET,
5181+ (void *) &table[ip - map->first_ip].flags))
5182+ return -EEXIST;
5183+
5184+ *hash_ip = ip;
5185+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
5186+ memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
5187+ return 0;
5188+}
5189+
5190+static int
5191+addip(struct ip_set *set, const void *data, size_t size,
5192+ ip_set_ip_t *hash_ip)
5193+{
5194+ struct ip_set_req_macipmap *req =
5195+ (struct ip_set_req_macipmap *) data;
5196+
5197+ if (size != sizeof(struct ip_set_req_macipmap)) {
5198+ ip_set_printk("data length wrong (want %zu, have %zu)",
5199+ sizeof(struct ip_set_req_macipmap),
5200+ size);
5201+ return -EINVAL;
5202+ }
5203+ return __addip(set, req->ip, req->ethernet, hash_ip);
5204+}
5205+
5206+static int
5207+addip_kernel(struct ip_set *set,
5208+ const struct sk_buff *skb,
5209+ ip_set_ip_t *hash_ip,
5210+ const u_int32_t *flags,
5211+ unsigned char index)
5212+{
5213+ ip_set_ip_t ip;
5214+
5215+ ip = ntohl(flags[index] & IPSET_SRC
5216+ ? skb->nh.iph->saddr
5217+ : skb->nh.iph->daddr);
5218+
5219+ if (!(skb->mac.raw >= skb->head
5220+ && (skb->mac.raw + ETH_HLEN) <= skb->data))
5221+ return -EINVAL;
5222+
5223+ return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
5224+}
5225+
5226+static inline int
5227+__delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
5228+{
5229+ struct ip_set_macipmap *map =
5230+ (struct ip_set_macipmap *) set->data;
5231+ struct ip_set_macip *table =
5232+ (struct ip_set_macip *) map->members;
5233+
5234+ if (ip < map->first_ip || ip > map->last_ip)
5235+ return -ERANGE;
5236+ if (!test_and_clear_bit(IPSET_MACIP_ISSET,
5237+ (void *)&table[ip - map->first_ip].flags))
5238+ return -EEXIST;
5239+
5240+ *hash_ip = ip;
5241+ DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
5242+ return 0;
5243+}
5244+
5245+static int
5246+delip(struct ip_set *set, const void *data, size_t size,
5247+ ip_set_ip_t *hash_ip)
5248+{
5249+ struct ip_set_req_macipmap *req =
5250+ (struct ip_set_req_macipmap *) data;
5251+
5252+ if (size != sizeof(struct ip_set_req_macipmap)) {
5253+ ip_set_printk("data length wrong (want %zu, have %zu)",
5254+ sizeof(struct ip_set_req_macipmap),
5255+ size);
5256+ return -EINVAL;
5257+ }
5258+ return __delip(set, req->ip, hash_ip);
5259+}
5260+
5261+static int
5262+delip_kernel(struct ip_set *set,
5263+ const struct sk_buff *skb,
5264+ ip_set_ip_t *hash_ip,
5265+ const u_int32_t *flags,
5266+ unsigned char index)
5267+{
5268+ return __delip(set,
5269+ ntohl(flags[index] & IPSET_SRC
5270+ ? skb->nh.iph->saddr
5271+ : skb->nh.iph->daddr),
5272+ hash_ip);
5273+}
5274+
5275+static inline size_t members_size(ip_set_id_t from, ip_set_id_t to)
5276+{
5277+ return (size_t)((to - from + 1) * sizeof(struct ip_set_macip));
5278+}
5279+
5280+static int create(struct ip_set *set, const void *data, size_t size)
5281+{
5282+ int newbytes;
5283+ struct ip_set_req_macipmap_create *req =
5284+ (struct ip_set_req_macipmap_create *) data;
5285+ struct ip_set_macipmap *map;
5286+
5287+ if (size != sizeof(struct ip_set_req_macipmap_create)) {
5288+ ip_set_printk("data length wrong (want %zu, have %zu)",
5289+ sizeof(struct ip_set_req_macipmap_create),
5290+ size);
5291+ return -EINVAL;
5292+ }
5293+
5294+ DP("from %u.%u.%u.%u to %u.%u.%u.%u",
5295+ HIPQUAD(req->from), HIPQUAD(req->to));
5296+
5297+ if (req->from > req->to) {
5298+ DP("bad ip range");
5299+ return -ENOEXEC;
5300+ }
5301+
5302+ if (req->to - req->from > MAX_RANGE) {
5303+ ip_set_printk("range too big (max %d addresses)",
5304+ MAX_RANGE+1);
5305+ return -ENOEXEC;
5306+ }
5307+
5308+ map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
5309+ if (!map) {
5310+ DP("out of memory for %d bytes",
5311+ sizeof(struct ip_set_macipmap));
5312+ return -ENOMEM;
5313+ }
5314+ map->flags = req->flags;
5315+ map->first_ip = req->from;
5316+ map->last_ip = req->to;
5317+ newbytes = members_size(map->first_ip, map->last_ip);
5318+ map->members = ip_set_malloc(newbytes);
5319+ DP("members: %u %p", newbytes, map->members);
5320+ if (!map->members) {
5321+ DP("out of memory for %d bytes", newbytes);
5322+ kfree(map);
5323+ return -ENOMEM;
5324+ }
5325+ memset(map->members, 0, newbytes);
5326+
5327+ set->data = map;
5328+ return 0;
5329+}
5330+
5331+static void destroy(struct ip_set *set)
5332+{
5333+ struct ip_set_macipmap *map =
5334+ (struct ip_set_macipmap *) set->data;
5335+
5336+ ip_set_free(map->members, members_size(map->first_ip, map->last_ip));
5337+ kfree(map);
5338+
5339+ set->data = NULL;
5340+}
5341+
5342+static void flush(struct ip_set *set)
5343+{
5344+ struct ip_set_macipmap *map =
5345+ (struct ip_set_macipmap *) set->data;
5346+ memset(map->members, 0, members_size(map->first_ip, map->last_ip));
5347+}
5348+
5349+static void list_header(const struct ip_set *set, void *data)
5350+{
5351+ struct ip_set_macipmap *map =
5352+ (struct ip_set_macipmap *) set->data;
5353+ struct ip_set_req_macipmap_create *header =
5354+ (struct ip_set_req_macipmap_create *) data;
5355+
5356+ DP("list_header %x %x %u", map->first_ip, map->last_ip,
5357+ map->flags);
5358+
5359+ header->from = map->first_ip;
5360+ header->to = map->last_ip;
5361+ header->flags = map->flags;
5362+}
5363+
5364+static int list_members_size(const struct ip_set *set)
5365+{
5366+ struct ip_set_macipmap *map =
5367+ (struct ip_set_macipmap *) set->data;
5368+
5369+ DP("%u", members_size(map->first_ip, map->last_ip));
5370+ return members_size(map->first_ip, map->last_ip);
5371+}
5372+
5373+static void list_members(const struct ip_set *set, void *data)
5374+{
5375+ struct ip_set_macipmap *map =
5376+ (struct ip_set_macipmap *) set->data;
5377+
5378+ int bytes = members_size(map->first_ip, map->last_ip);
5379+
5380+ DP("members: %u %p", bytes, map->members);
5381+ memcpy(data, map->members, bytes);
5382+}
5383+
5384+static struct ip_set_type ip_set_macipmap = {
5385+ .typename = SETTYPE_NAME,
5386+ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
5387+ .protocol_version = IP_SET_PROTOCOL_VERSION,
5388+ .create = &create,
5389+ .destroy = &destroy,
5390+ .flush = &flush,
5391+ .reqsize = sizeof(struct ip_set_req_macipmap),
5392+ .addip = &addip,
5393+ .addip_kernel = &addip_kernel,
5394+ .delip = &delip,
5395+ .delip_kernel = &delip_kernel,
5396+ .testip = &testip,
5397+ .testip_kernel = &testip_kernel,
5398+ .header_size = sizeof(struct ip_set_req_macipmap_create),
5399+ .list_header = &list_header,
5400+ .list_members_size = &list_members_size,
5401+ .list_members = &list_members,
5402+ .me = THIS_MODULE,
5403+};
5404+
5405+MODULE_LICENSE("GPL");
5406+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5407+MODULE_DESCRIPTION("macipmap type of IP sets");
5408+
5409+static int __init init(void)
5410+{
5411+ init_max_malloc_size();
5412+ return ip_set_register_set_type(&ip_set_macipmap);
5413+}
5414+
5415+static void __exit fini(void)
5416+{
5417+ /* FIXME: possible race with ip_set_create() */
5418+ ip_set_unregister_set_type(&ip_set_macipmap);
5419+}
5420+
5421+module_init(init);
5422+module_exit(fini);
5423diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_nethash.c linux/net/ipv4/netfilter/ip_set_nethash.c
5424--- linux.org/net/ipv4/netfilter/ip_set_nethash.c 1970-01-01 01:00:00.000000000 +0100
5425+++ linux/net/ipv4/netfilter/ip_set_nethash.c 2006-05-04 10:26:33.000000000 +0200
5426@@ -0,0 +1,466 @@
5427+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5428+ *
5429+ * This program is free software; you can redistribute it and/or modify
5430+ * it under the terms of the GNU General Public License version 2 as
5431+ * published by the Free Software Foundation.
5432+ */
5433+
5434+/* Kernel module implementing a cidr nethash set */
5435+
5436+#include <linux/module.h>
5437+#include <linux/ip.h>
5438+#include <linux/skbuff.h>
5439+#include <linux/netfilter_ipv4/ip_tables.h>
5440+#include <linux/netfilter_ipv4/ip_set.h>
5441+#include <linux/errno.h>
5442+#include <asm/uaccess.h>
5443+#include <asm/bitops.h>
5444+#include <linux/spinlock.h>
5445+#include <linux/vmalloc.h>
5446+#include <linux/random.h>
5447+
5448+#include <net/ip.h>
5449+
5450+#include <linux/netfilter_ipv4/ip_set_malloc.h>
5451+#include <linux/netfilter_ipv4/ip_set_nethash.h>
5452+#include <linux/netfilter_ipv4/ip_set_jhash.h>
5453+
5454+static inline __u32
5455+jhash_ip(const struct ip_set_nethash *map, uint16_t i, ip_set_ip_t ip)
5456+{
5457+ return jhash_1word(ip, *(((uint32_t *) map->initval) + i));
5458+}
5459+
5460+static inline __u32
5461+hash_id_cidr(struct ip_set_nethash *map,
5462+ ip_set_ip_t ip,
5463+ unsigned char cidr,
5464+ ip_set_ip_t *hash_ip)
5465+{
5466+ __u32 id;
5467+ u_int16_t i;
5468+ ip_set_ip_t *elem;
5469+
5470+ *hash_ip = pack(ip, cidr);
5471+
5472+ for (i = 0; i < map->probes; i++) {
5473+ id = jhash_ip(map, i, *hash_ip) % map->hashsize;
5474+ DP("hash key: %u", id);
5475+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
5476+ if (*elem == *hash_ip)
5477+ return id;
5478+ }
5479+ return UINT_MAX;
5480+}
5481+
5482+static inline __u32
5483+hash_id(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
5484+{
5485+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5486+ __u32 id = UINT_MAX;
5487+ int i;
5488+
5489+ for (i = 0; i < 30 && map->cidr[i]; i++) {
5490+ id = hash_id_cidr(map, ip, map->cidr[i], hash_ip);
5491+ if (id != UINT_MAX)
5492+ break;
5493+ }
5494+ return id;
5495+}
5496+
5497+static inline int
5498+__testip_cidr(struct ip_set *set, ip_set_ip_t ip, unsigned char cidr,
5499+ ip_set_ip_t *hash_ip)
5500+{
5501+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5502+
5503+ return (hash_id_cidr(map, ip, cidr, hash_ip) != UINT_MAX);
5504+}
5505+
5506+static inline int
5507+__testip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
5508+{
5509+ return (hash_id(set, ip, hash_ip) != UINT_MAX);
5510+}
5511+
5512+static int
5513+testip(struct ip_set *set, const void *data, size_t size,
5514+ ip_set_ip_t *hash_ip)
5515+{
5516+ struct ip_set_req_nethash *req =
5517+ (struct ip_set_req_nethash *) data;
5518+
5519+ if (size != sizeof(struct ip_set_req_nethash)) {
5520+ ip_set_printk("data length wrong (want %zu, have %zu)",
5521+ sizeof(struct ip_set_req_nethash),
5522+ size);
5523+ return -EINVAL;
5524+ }
5525+ return (req->cidr == 32 ? __testip(set, req->ip, hash_ip)
5526+ : __testip_cidr(set, req->ip, req->cidr, hash_ip));
5527+}
5528+
5529+static int
5530+testip_kernel(struct ip_set *set,
5531+ const struct sk_buff *skb,
5532+ ip_set_ip_t *hash_ip,
5533+ const u_int32_t *flags,
5534+ unsigned char index)
5535+{
5536+ return __testip(set,
5537+ ntohl(flags[index] & IPSET_SRC
5538+ ? skb->nh.iph->saddr
5539+ : skb->nh.iph->daddr),
5540+ hash_ip);
5541+}
5542+
5543+static inline int
5544+__addip_base(struct ip_set_nethash *map, ip_set_ip_t ip)
5545+{
5546+ __u32 probe;
5547+ u_int16_t i;
5548+ ip_set_ip_t *elem;
5549+
5550+ for (i = 0; i < map->probes; i++) {
5551+ probe = jhash_ip(map, i, ip) % map->hashsize;
5552+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
5553+ if (*elem == ip)
5554+ return -EEXIST;
5555+ if (!*elem) {
5556+ *elem = ip;
5557+ return 0;
5558+ }
5559+ }
5560+ /* Trigger rehashing */
5561+ return -EAGAIN;
5562+}
5563+
5564+static inline int
5565+__addip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
5566+ ip_set_ip_t *hash_ip)
5567+{
5568+ *hash_ip = pack(ip, cidr);
5569+ DP("%u.%u.%u.%u/%u, %u.%u.%u.%u", HIPQUAD(ip), cidr, HIPQUAD(*hash_ip));
5570+
5571+ return __addip_base(map, *hash_ip);
5572+}
5573+
5574+static void
5575+update_cidr_sizes(struct ip_set_nethash *map, unsigned char cidr)
5576+{
5577+ unsigned char next;
5578+ int i;
5579+
5580+ for (i = 0; i < 30 && map->cidr[i]; i++) {
5581+ if (map->cidr[i] == cidr) {
5582+ return;
5583+ } else if (map->cidr[i] < cidr) {
5584+ next = map->cidr[i];
5585+ map->cidr[i] = cidr;
5586+ cidr = next;
5587+ }
5588+ }
5589+ if (i < 30)
5590+ map->cidr[i] = cidr;
5591+}
5592+
5593+static int
5594+addip(struct ip_set *set, const void *data, size_t size,
5595+ ip_set_ip_t *hash_ip)
5596+{
5597+ struct ip_set_req_nethash *req =
5598+ (struct ip_set_req_nethash *) data;
5599+ int ret;
5600+
5601+ if (size != sizeof(struct ip_set_req_nethash)) {
5602+ ip_set_printk("data length wrong (want %zu, have %zu)",
5603+ sizeof(struct ip_set_req_nethash),
5604+ size);
5605+ return -EINVAL;
5606+ }
5607+ ret = __addip((struct ip_set_nethash *) set->data,
5608+ req->ip, req->cidr, hash_ip);
5609+
5610+ if (ret == 0)
5611+ update_cidr_sizes((struct ip_set_nethash *) set->data,
5612+ req->cidr);
5613+
5614+ return ret;
5615+}
5616+
5617+static int
5618+addip_kernel(struct ip_set *set,
5619+ const struct sk_buff *skb,
5620+ ip_set_ip_t *hash_ip,
5621+ const u_int32_t *flags,
5622+ unsigned char index)
5623+{
5624+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5625+ int ret = -ERANGE;
5626+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
5627+ ? skb->nh.iph->saddr
5628+ : skb->nh.iph->daddr);
5629+
5630+ if (map->cidr[0])
5631+ ret = __addip(map, ip, map->cidr[0], hash_ip);
5632+
5633+ return ret;
5634+}
5635+
5636+static int retry(struct ip_set *set)
5637+{
5638+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5639+ ip_set_ip_t *elem;
5640+ void *members;
5641+ u_int32_t i, hashsize = map->hashsize;
5642+ int res;
5643+ struct ip_set_nethash *tmp;
5644+
5645+ if (map->resize == 0)
5646+ return -ERANGE;
5647+
5648+ again:
5649+ res = 0;
5650+
5651+ /* Calculate new parameters */
5652+ hashsize += (hashsize * map->resize)/100;
5653+ if (hashsize == map->hashsize)
5654+ hashsize++;
5655+
5656+ ip_set_printk("rehashing of set %s triggered: "
5657+ "hashsize grows from %u to %u",
5658+ set->name, map->hashsize, hashsize);
5659+
5660+ tmp = kmalloc(sizeof(struct ip_set_nethash)
5661+ + map->probes * sizeof(uint32_t), GFP_ATOMIC);
5662+ if (!tmp) {
5663+ DP("out of memory for %d bytes",
5664+ sizeof(struct ip_set_nethash)
5665+ + map->probes * sizeof(uint32_t));
5666+ return -ENOMEM;
5667+ }
5668+ tmp->members = harray_malloc(hashsize, sizeof(ip_set_ip_t), GFP_ATOMIC);
5669+ if (!tmp->members) {
5670+ DP("out of memory for %d bytes", hashsize * sizeof(ip_set_ip_t));
5671+ kfree(tmp);
5672+ return -ENOMEM;
5673+ }
5674+ tmp->hashsize = hashsize;
5675+ tmp->probes = map->probes;
5676+ tmp->resize = map->resize;
5677+ memcpy(tmp->initval, map->initval, map->probes * sizeof(uint32_t));
5678+ memcpy(tmp->cidr, map->cidr, 30 * sizeof(unsigned char));
5679+
5680+ write_lock_bh(&set->lock);
5681+ map = (struct ip_set_nethash *) set->data; /* Play safe */
5682+ for (i = 0; i < map->hashsize && res == 0; i++) {
5683+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
5684+ if (*elem)
5685+ res = __addip_base(tmp, *elem);
5686+ }
5687+ if (res) {
5688+ /* Failure, try again */
5689+ write_unlock_bh(&set->lock);
5690+ harray_free(tmp->members);
5691+ kfree(tmp);
5692+ goto again;
5693+ }
5694+
5695+ /* Success at resizing! */
5696+ members = map->members;
5697+
5698+ map->hashsize = tmp->hashsize;
5699+ map->members = tmp->members;
5700+ write_unlock_bh(&set->lock);
5701+
5702+ harray_free(members);
5703+ kfree(tmp);
5704+
5705+ return 0;
5706+}
5707+
5708+static inline int
5709+__delip(struct ip_set_nethash *map, ip_set_ip_t ip, unsigned char cidr,
5710+ ip_set_ip_t *hash_ip)
5711+{
5712+ ip_set_ip_t id = hash_id_cidr(map, ip, cidr, hash_ip);
5713+ ip_set_ip_t *elem;
5714+
5715+ if (id == UINT_MAX)
5716+ return -EEXIST;
5717+
5718+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
5719+ *elem = 0;
5720+ return 0;
5721+}
5722+
5723+static int
5724+delip(struct ip_set *set, const void *data, size_t size,
5725+ ip_set_ip_t *hash_ip)
5726+{
5727+ struct ip_set_req_nethash *req =
5728+ (struct ip_set_req_nethash *) data;
5729+
5730+ if (size != sizeof(struct ip_set_req_nethash)) {
5731+ ip_set_printk("data length wrong (want %zu, have %zu)",
5732+ sizeof(struct ip_set_req_nethash),
5733+ size);
5734+ return -EINVAL;
5735+ }
5736+ /* TODO: no garbage collection in map->cidr */
5737+ return __delip((struct ip_set_nethash *) set->data,
5738+ req->ip, req->cidr, hash_ip);
5739+}
5740+
5741+static int
5742+delip_kernel(struct ip_set *set,
5743+ const struct sk_buff *skb,
5744+ ip_set_ip_t *hash_ip,
5745+ const u_int32_t *flags,
5746+ unsigned char index)
5747+{
5748+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5749+ int ret = -ERANGE;
5750+ ip_set_ip_t ip = ntohl(flags[index] & IPSET_SRC
5751+ ? skb->nh.iph->saddr
5752+ : skb->nh.iph->daddr);
5753+
5754+ if (map->cidr[0])
5755+ ret = __delip(map, ip, map->cidr[0], hash_ip);
5756+
5757+ return ret;
5758+}
5759+
5760+static int create(struct ip_set *set, const void *data, size_t size)
5761+{
5762+ struct ip_set_req_nethash_create *req =
5763+ (struct ip_set_req_nethash_create *) data;
5764+ struct ip_set_nethash *map;
5765+ uint16_t i;
5766+
5767+ if (size != sizeof(struct ip_set_req_nethash_create)) {
5768+ ip_set_printk("data length wrong (want %zu, have %zu)",
5769+ sizeof(struct ip_set_req_nethash_create),
5770+ size);
5771+ return -EINVAL;
5772+ }
5773+
5774+ if (req->hashsize < 1) {
5775+ ip_set_printk("hashsize too small");
5776+ return -ENOEXEC;
5777+ }
5778+ if (req->probes < 1) {
5779+ ip_set_printk("probes too small");
5780+ return -ENOEXEC;
5781+ }
5782+
5783+ map = kmalloc(sizeof(struct ip_set_nethash)
5784+ + req->probes * sizeof(uint32_t), GFP_KERNEL);
5785+ if (!map) {
5786+ DP("out of memory for %d bytes",
5787+ sizeof(struct ip_set_nethash)
5788+ + req->probes * sizeof(uint32_t));
5789+ return -ENOMEM;
5790+ }
5791+ for (i = 0; i < req->probes; i++)
5792+ get_random_bytes(((uint32_t *) map->initval)+i, 4);
5793+ map->hashsize = req->hashsize;
5794+ map->probes = req->probes;
5795+ map->resize = req->resize;
5796+ memset(map->cidr, 0, 30 * sizeof(unsigned char));
5797+ map->members = harray_malloc(map->hashsize, sizeof(ip_set_ip_t), GFP_KERNEL);
5798+ if (!map->members) {
5799+ DP("out of memory for %d bytes", map->hashsize * sizeof(ip_set_ip_t));
5800+ kfree(map);
5801+ return -ENOMEM;
5802+ }
5803+
5804+ set->data = map;
5805+ return 0;
5806+}
5807+
5808+static void destroy(struct ip_set *set)
5809+{
5810+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5811+
5812+ harray_free(map->members);
5813+ kfree(map);
5814+
5815+ set->data = NULL;
5816+}
5817+
5818+static void flush(struct ip_set *set)
5819+{
5820+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5821+ harray_flush(map->members, map->hashsize, sizeof(ip_set_ip_t));
5822+ memset(map->cidr, 0, 30 * sizeof(unsigned char));
5823+}
5824+
5825+static void list_header(const struct ip_set *set, void *data)
5826+{
5827+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5828+ struct ip_set_req_nethash_create *header =
5829+ (struct ip_set_req_nethash_create *) data;
5830+
5831+ header->hashsize = map->hashsize;
5832+ header->probes = map->probes;
5833+ header->resize = map->resize;
5834+}
5835+
5836+static int list_members_size(const struct ip_set *set)
5837+{
5838+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5839+
5840+ return (map->hashsize * sizeof(ip_set_ip_t));
5841+}
5842+
5843+static void list_members(const struct ip_set *set, void *data)
5844+{
5845+ struct ip_set_nethash *map = (struct ip_set_nethash *) set->data;
5846+ ip_set_ip_t i, *elem;
5847+
5848+ for (i = 0; i < map->hashsize; i++) {
5849+ elem = HARRAY_ELEM(map->members, ip_set_ip_t *, i);
5850+ ((ip_set_ip_t *)data)[i] = *elem;
5851+ }
5852+}
5853+
5854+static struct ip_set_type ip_set_nethash = {
5855+ .typename = SETTYPE_NAME,
5856+ .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
5857+ .protocol_version = IP_SET_PROTOCOL_VERSION,
5858+ .create = &create,
5859+ .destroy = &destroy,
5860+ .flush = &flush,
5861+ .reqsize = sizeof(struct ip_set_req_nethash),
5862+ .addip = &addip,
5863+ .addip_kernel = &addip_kernel,
5864+ .retry = &retry,
5865+ .delip = &delip,
5866+ .delip_kernel = &delip_kernel,
5867+ .testip = &testip,
5868+ .testip_kernel = &testip_kernel,
5869+ .header_size = sizeof(struct ip_set_req_nethash_create),
5870+ .list_header = &list_header,
5871+ .list_members_size = &list_members_size,
5872+ .list_members = &list_members,
5873+ .me = THIS_MODULE,
5874+};
5875+
5876+MODULE_LICENSE("GPL");
5877+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
5878+MODULE_DESCRIPTION("nethash type of IP sets");
5879+
5880+static int __init init(void)
5881+{
5882+ return ip_set_register_set_type(&ip_set_nethash);
5883+}
5884+
5885+static void __exit fini(void)
5886+{
5887+ /* FIXME: possible race with ip_set_create() */
5888+ ip_set_unregister_set_type(&ip_set_nethash);
5889+}
5890+
5891+module_init(init);
5892+module_exit(fini);
5893diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ip_set_portmap.c linux/net/ipv4/netfilter/ip_set_portmap.c
5894--- linux.org/net/ipv4/netfilter/ip_set_portmap.c 1970-01-01 01:00:00.000000000 +0100
5895+++ linux/net/ipv4/netfilter/ip_set_portmap.c 2006-05-04 10:26:33.000000000 +0200
5896@@ -0,0 +1,334 @@
5897+/* Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5898+ *
5899+ * This program is free software; you can redistribute it and/or modify
5900+ * it under the terms of the GNU General Public License version 2 as
5901+ * published by the Free Software Foundation.
5902+ */
5903+
5904+/* Kernel module implementing a port set type as a bitmap */
5905+
5906+#include <linux/module.h>
5907+#include <linux/ip.h>
5908+#include <linux/tcp.h>
5909+#include <linux/udp.h>
5910+#include <linux/skbuff.h>
5911+#include <linux/netfilter_ipv4/ip_tables.h>
5912+#include <linux/netfilter_ipv4/ip_set.h>
5913+#include <linux/errno.h>
5914+#include <asm/uaccess.h>
5915+#include <asm/bitops.h>
5916+#include <linux/spinlock.h>
5917+
5918+#include <net/ip.h>
5919+
5920+#include <linux/netfilter_ipv4/ip_set_portmap.h>
5921+
5922+/* We must handle non-linear skbs */
5923+static inline ip_set_ip_t
5924+get_port(const struct sk_buff *skb, u_int32_t flags)
5925+{
5926+ struct iphdr *iph = skb->nh.iph;
5927+ u_int16_t offset = ntohs(iph->frag_off) & IP_OFFSET;
5928+
5929+ switch (iph->protocol) {
5930+ case IPPROTO_TCP: {
5931+ struct tcphdr tcph;
5932+
5933+ /* See comments at tcp_match in ip_tables.c */
5934+ if (offset)
5935+ return INVALID_PORT;
5936+
5937+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) < 0)
5938+ /* No choice either */
5939+ return INVALID_PORT;
5940+
5941+ return ntohs(flags & IPSET_SRC ?
5942+ tcph.source : tcph.dest);
5943+ }
5944+ case IPPROTO_UDP: {
5945+ struct udphdr udph;
5946+
5947+ if (offset)
5948+ return INVALID_PORT;
5949+
5950+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &udph, sizeof(udph)) < 0)
5951+ /* No choice either */
5952+ return INVALID_PORT;
5953+
5954+ return ntohs(flags & IPSET_SRC ?
5955+ udph.source : udph.dest);
5956+ }
5957+ default:
5958+ return INVALID_PORT;
5959+ }
5960+}
5961+
5962+static inline int
5963+__testport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
5964+{
5965+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
5966+
5967+ if (port < map->first_port || port > map->last_port)
5968+ return -ERANGE;
5969+
5970+ *hash_port = port;
5971+ DP("set: %s, port:%u, %u", set->name, port, *hash_port);
5972+ return !!test_bit(port - map->first_port, map->members);
5973+}
5974+
5975+static int
5976+testport(struct ip_set *set, const void *data, size_t size,
5977+ ip_set_ip_t *hash_port)
5978+{
5979+ struct ip_set_req_portmap *req =
5980+ (struct ip_set_req_portmap *) data;
5981+
5982+ if (size != sizeof(struct ip_set_req_portmap)) {
5983+ ip_set_printk("data length wrong (want %zu, have %zu)",
5984+ sizeof(struct ip_set_req_portmap),
5985+ size);
5986+ return -EINVAL;
5987+ }
5988+ return __testport(set, req->port, hash_port);
5989+}
5990+
5991+static int
5992+testport_kernel(struct ip_set *set,
5993+ const struct sk_buff *skb,
5994+ ip_set_ip_t *hash_port,
5995+ const u_int32_t *flags,
5996+ unsigned char index)
5997+{
5998+ int res;
5999+ ip_set_ip_t port = get_port(skb, flags[index]);
6000+
6001+ DP("flag %s port %u", flags[index] & IPSET_SRC ? "SRC" : "DST", port);
6002+ if (port == INVALID_PORT)
6003+ return 0;
6004+
6005+ res = __testport(set, port, hash_port);
6006+
6007+ return (res < 0 ? 0 : res);
6008+}
6009+
6010+static inline int
6011+__addport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
6012+{
6013+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6014+
6015+ if (port < map->first_port || port > map->last_port)
6016+ return -ERANGE;
6017+ if (test_and_set_bit(port - map->first_port, map->members))
6018+ return -EEXIST;
6019+
6020+ *hash_port = port;
6021+ DP("port %u", port);
6022+ return 0;
6023+}
6024+
6025+static int
6026+addport(struct ip_set *set, const void *data, size_t size,
6027+ ip_set_ip_t *hash_port)
6028+{
6029+ struct ip_set_req_portmap *req =
6030+ (struct ip_set_req_portmap *) data;
6031+
6032+ if (size != sizeof(struct ip_set_req_portmap)) {
6033+ ip_set_printk("data length wrong (want %zu, have %zu)",
6034+ sizeof(struct ip_set_req_portmap),
6035+ size);
6036+ return -EINVAL;
6037+ }
6038+ return __addport(set, req->port, hash_port);
6039+}
6040+
6041+static int
6042+addport_kernel(struct ip_set *set,
6043+ const struct sk_buff *skb,
6044+ ip_set_ip_t *hash_port,
6045+ const u_int32_t *flags,
6046+ unsigned char index)
6047+{
6048+ ip_set_ip_t port = get_port(skb, flags[index]);
6049+
6050+ if (port == INVALID_PORT)
6051+ return -EINVAL;
6052+
6053+ return __addport(set, port, hash_port);
6054+}
6055+
6056+static inline int
6057+__delport(struct ip_set *set, ip_set_ip_t port, ip_set_ip_t *hash_port)
6058+{
6059+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6060+
6061+ if (port < map->first_port || port > map->last_port)
6062+ return -ERANGE;
6063+ if (!test_and_clear_bit(port - map->first_port, map->members))
6064+ return -EEXIST;
6065+
6066+ *hash_port = port;
6067+ DP("port %u", port);
6068+ return 0;
6069+}
6070+
6071+static int
6072+delport(struct ip_set *set, const void *data, size_t size,
6073+ ip_set_ip_t *hash_port)
6074+{
6075+ struct ip_set_req_portmap *req =
6076+ (struct ip_set_req_portmap *) data;
6077+
6078+ if (size != sizeof(struct ip_set_req_portmap)) {
6079+ ip_set_printk("data length wrong (want %zu, have %zu)",
6080+ sizeof(struct ip_set_req_portmap),
6081+ size);
6082+ return -EINVAL;
6083+ }
6084+ return __delport(set, req->port, hash_port);
6085+}
6086+
6087+static int
6088+delport_kernel(struct ip_set *set,
6089+ const struct sk_buff *skb,
6090+ ip_set_ip_t *hash_port,
6091+ const u_int32_t *flags,
6092+ unsigned char index)
6093+{
6094+ ip_set_ip_t port = get_port(skb, flags[index]);
6095+
6096+ if (port == INVALID_PORT)
6097+ return -EINVAL;
6098+
6099+ return __delport(set, port, hash_port);
6100+}
6101+
6102+static int create(struct ip_set *set, const void *data, size_t size)
6103+{
6104+ int newbytes;
6105+ struct ip_set_req_portmap_create *req =
6106+ (struct ip_set_req_portmap_create *) data;
6107+ struct ip_set_portmap *map;
6108+
6109+ if (size != sizeof(struct ip_set_req_portmap_create)) {
6110+ ip_set_printk("data length wrong (want %zu, have %zu)",
6111+ sizeof(struct ip_set_req_portmap_create),
6112+ size);
6113+ return -EINVAL;
6114+ }
6115+
6116+ DP("from %u to %u", req->from, req->to);
6117+
6118+ if (req->from > req->to) {
6119+ DP("bad port range");
6120+ return -ENOEXEC;
6121+ }
6122+
6123+ if (req->to - req->from > MAX_RANGE) {
6124+ ip_set_printk("range too big (max %d ports)",
6125+ MAX_RANGE+1);
6126+ return -ENOEXEC;
6127+ }
6128+
6129+ map = kmalloc(sizeof(struct ip_set_portmap), GFP_KERNEL);
6130+ if (!map) {
6131+ DP("out of memory for %d bytes",
6132+ sizeof(struct ip_set_portmap));
6133+ return -ENOMEM;
6134+ }
6135+ map->first_port = req->from;
6136+ map->last_port = req->to;
6137+ newbytes = bitmap_bytes(req->from, req->to);
6138+ map->members = kmalloc(newbytes, GFP_KERNEL);
6139+ if (!map->members) {
6140+ DP("out of memory for %d bytes", newbytes);
6141+ kfree(map);
6142+ return -ENOMEM;
6143+ }
6144+ memset(map->members, 0, newbytes);
6145+
6146+ set->data = map;
6147+ return 0;
6148+}
6149+
6150+static void destroy(struct ip_set *set)
6151+{
6152+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6153+
6154+ kfree(map->members);
6155+ kfree(map);
6156+
6157+ set->data = NULL;
6158+}
6159+
6160+static void flush(struct ip_set *set)
6161+{
6162+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6163+ memset(map->members, 0, bitmap_bytes(map->first_port, map->last_port));
6164+}
6165+
6166+static void list_header(const struct ip_set *set, void *data)
6167+{
6168+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6169+ struct ip_set_req_portmap_create *header =
6170+ (struct ip_set_req_portmap_create *) data;
6171+
6172+ DP("list_header %u %u", map->first_port, map->last_port);
6173+
6174+ header->from = map->first_port;
6175+ header->to = map->last_port;
6176+}
6177+
6178+static int list_members_size(const struct ip_set *set)
6179+{
6180+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6181+
6182+ return bitmap_bytes(map->first_port, map->last_port);
6183+}
6184+
6185+static void list_members(const struct ip_set *set, void *data)
6186+{
6187+ struct ip_set_portmap *map = (struct ip_set_portmap *) set->data;
6188+ int bytes = bitmap_bytes(map->first_port, map->last_port);
6189+
6190+ memcpy(data, map->members, bytes);
6191+}
6192+
6193+static struct ip_set_type ip_set_portmap = {
6194+ .typename = SETTYPE_NAME,
6195+ .features = IPSET_TYPE_PORT | IPSET_DATA_SINGLE,
6196+ .protocol_version = IP_SET_PROTOCOL_VERSION,
6197+ .create = &create,
6198+ .destroy = &destroy,
6199+ .flush = &flush,
6200+ .reqsize = sizeof(struct ip_set_req_portmap),
6201+ .addip = &addport,
6202+ .addip_kernel = &addport_kernel,
6203+ .delip = &delport,
6204+ .delip_kernel = &delport_kernel,
6205+ .testip = &testport,
6206+ .testip_kernel = &testport_kernel,
6207+ .header_size = sizeof(struct ip_set_req_portmap_create),
6208+ .list_header = &list_header,
6209+ .list_members_size = &list_members_size,
6210+ .list_members = &list_members,
6211+ .me = THIS_MODULE,
6212+};
6213+
6214+MODULE_LICENSE("GPL");
6215+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6216+MODULE_DESCRIPTION("portmap type of IP sets");
6217+
6218+static int __init init(void)
6219+{
6220+ return ip_set_register_set_type(&ip_set_portmap);
6221+}
6222+
6223+static void __exit fini(void)
6224+{
6225+ /* FIXME: possible race with ip_set_create() */
6226+ ip_set_unregister_set_type(&ip_set_portmap);
6227+}
6228+
6229+module_init(init);
6230+module_exit(fini);
6231diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_SET.c linux/net/ipv4/netfilter/ipt_SET.c
6232--- linux.org/net/ipv4/netfilter/ipt_SET.c 1970-01-01 01:00:00.000000000 +0100
6233+++ linux/net/ipv4/netfilter/ipt_SET.c 2006-05-04 10:26:33.000000000 +0200
6234@@ -0,0 +1,128 @@
6235+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
6236+ * Patrick Schaaf <bof@bof.de>
6237+ * Martin Josefsson <gandalf@wlug.westbo.se>
6238+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6239+ *
6240+ * This program is free software; you can redistribute it and/or modify
6241+ * it under the terms of the GNU General Public License version 2 as
6242+ * published by the Free Software Foundation.
6243+ */
6244+
6245+/* ipt_SET.c - netfilter target to manipulate IP sets */
6246+
6247+#include <linux/types.h>
6248+#include <linux/ip.h>
6249+#include <linux/timer.h>
6250+#include <linux/module.h>
6251+#include <linux/netfilter.h>
6252+#include <linux/netdevice.h>
6253+#include <linux/if.h>
6254+#include <linux/inetdevice.h>
6255+#include <net/protocol.h>
6256+#include <net/checksum.h>
6257+#include <linux/netfilter_ipv4.h>
6258+#include <linux/netfilter_ipv4/ip_nat_rule.h>
6259+#include <linux/netfilter_ipv4/ipt_set.h>
6260+
6261+static unsigned int
6262+target(struct sk_buff **pskb,
6263+ const struct net_device *in,
6264+ const struct net_device *out,
6265+ unsigned int hooknum,
6266+ const void *targinfo,
6267+ void *userinfo)
6268+{
6269+ const struct ipt_set_info_target *info = targinfo;
6270+
6271+ if (info->add_set.index != IP_SET_INVALID_ID)
6272+ ip_set_addip_kernel(info->add_set.index,
6273+ *pskb,
6274+ info->add_set.flags);
6275+ if (info->del_set.index != IP_SET_INVALID_ID)
6276+ ip_set_delip_kernel(info->del_set.index,
6277+ *pskb,
6278+ info->del_set.flags);
6279+
6280+ return IPT_CONTINUE;
6281+}
6282+
6283+static int
6284+checkentry(const char *tablename,
6285+ const struct ipt_entry *e,
6286+ void *targinfo,
6287+ unsigned int targinfosize, unsigned int hook_mask)
6288+{
6289+ struct ipt_set_info_target *info =
6290+ (struct ipt_set_info_target *) targinfo;
6291+ ip_set_id_t index;
6292+
6293+ if (targinfosize != IPT_ALIGN(sizeof(*info))) {
6294+ DP("bad target info size %u", targinfosize);
6295+ return 0;
6296+ }
6297+
6298+ if (info->add_set.index != IP_SET_INVALID_ID) {
6299+ index = ip_set_get_byindex(info->add_set.index);
6300+ if (index == IP_SET_INVALID_ID) {
6301+ ip_set_printk("cannot find add_set index %u as target",
6302+ info->add_set.index);
6303+ return 0; /* error */
6304+ }
6305+ }
6306+
6307+ if (info->del_set.index != IP_SET_INVALID_ID) {
6308+ index = ip_set_get_byindex(info->del_set.index);
6309+ if (index == IP_SET_INVALID_ID) {
6310+ ip_set_printk("cannot find del_set index %u as target",
6311+ info->del_set.index);
6312+ return 0; /* error */
6313+ }
6314+ }
6315+ if (info->add_set.flags[IP_SET_MAX_BINDINGS] != 0
6316+ || info->del_set.flags[IP_SET_MAX_BINDINGS] != 0) {
6317+ ip_set_printk("That's nasty!");
6318+ return 0; /* error */
6319+ }
6320+
6321+ return 1;
6322+}
6323+
6324+static void destroy(void *targetinfo, unsigned int targetsize)
6325+{
6326+ struct ipt_set_info_target *info = targetinfo;
6327+
6328+ if (targetsize != IPT_ALIGN(sizeof(struct ipt_set_info_target))) {
6329+ ip_set_printk("invalid targetsize %d", targetsize);
6330+ return;
6331+ }
6332+
6333+ if (info->add_set.index != IP_SET_INVALID_ID)
6334+ ip_set_put(info->add_set.index);
6335+ if (info->del_set.index != IP_SET_INVALID_ID)
6336+ ip_set_put(info->del_set.index);
6337+}
6338+
6339+static struct ipt_target SET_target = {
6340+ .name = "SET",
6341+ .target = target,
6342+ .checkentry = checkentry,
6343+ .destroy = destroy,
6344+ .me = THIS_MODULE
6345+};
6346+
6347+MODULE_LICENSE("GPL");
6348+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6349+MODULE_DESCRIPTION("iptables IP set target module");
6350+
6351+static int __init init(void)
6352+{
6353+ return ipt_register_target(&SET_target);
6354+}
6355+
6356+static void __exit fini(void)
6357+{
6358+ ipt_unregister_target(&SET_target);
6359+}
6360+
6361+module_init(init);
6362+module_exit(fini);
6363diff -Nur --exclude '*.orig' linux.org/net/ipv4/netfilter/ipt_set.c linux/net/ipv4/netfilter/ipt_set.c
6364--- linux.org/net/ipv4/netfilter/ipt_set.c 1970-01-01 01:00:00.000000000 +0100
6365+++ linux/net/ipv4/netfilter/ipt_set.c 2006-05-04 10:26:33.000000000 +0200
6366@@ -0,0 +1,112 @@
6367+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
6368+ * Patrick Schaaf <bof@bof.de>
6369+ * Martin Josefsson <gandalf@wlug.westbo.se>
6370+ * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6371+ *
6372+ * This program is free software; you can redistribute it and/or modify
6373+ * it under the terms of the GNU General Public License version 2 as
6374+ * published by the Free Software Foundation.
6375+ */
6376+
6377+/* Kernel module to match an IP set. */
6378+
6379+#include <linux/module.h>
6380+#include <linux/ip.h>
6381+#include <linux/skbuff.h>
6382+
6383+#include <linux/netfilter_ipv4/ip_tables.h>
6384+#include <linux/netfilter_ipv4/ip_set.h>
6385+#include <linux/netfilter_ipv4/ipt_set.h>
6386+
6387+static inline int
6388+match_set(const struct ipt_set_info *info,
6389+ const struct sk_buff *skb,
6390+ int inv)
6391+{
6392+ if (ip_set_testip_kernel(info->index, skb, info->flags))
6393+ inv = !inv;
6394+ return inv;
6395+}
6396+
6397+static int
6398+match(const struct sk_buff *skb,
6399+ const struct net_device *in,
6400+ const struct net_device *out,
6401+ const void *matchinfo,
6402+ int offset,
6403+ int *hotdrop)
6404+{
6405+ const struct ipt_set_info_match *info = matchinfo;
6406+
6407+ return match_set(&info->match_set,
6408+ skb,
6409+ info->match_set.flags[0] & IPSET_MATCH_INV);
6410+}
6411+
6412+static int
6413+checkentry(const char *tablename,
6414+ const struct ipt_ip *ip,
6415+ void *matchinfo,
6416+ unsigned int matchsize,
6417+ unsigned int hook_mask)
6418+{
6419+ struct ipt_set_info_match *info =
6420+ (struct ipt_set_info_match *) matchinfo;
6421+ ip_set_id_t index;
6422+
6423+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
6424+ ip_set_printk("invalid matchsize %d", matchsize);
6425+ return 0;
6426+ }
6427+
6428+ index = ip_set_get_byindex(info->match_set.index);
6429+
6430+ if (index == IP_SET_INVALID_ID) {
6431+ ip_set_printk("Cannot find set indentified by id %u to match",
6432+ info->match_set.index);
6433+ return 0; /* error */
6434+ }
6435+ if (info->match_set.flags[IP_SET_MAX_BINDINGS] != 0) {
6436+ ip_set_printk("That's nasty!");
6437+ return 0; /* error */
6438+ }
6439+
6440+ return 1;
6441+}
6442+
6443+static void destroy(void *matchinfo, unsigned int matchsize)
6444+{
6445+ struct ipt_set_info_match *info = matchinfo;
6446+
6447+ if (matchsize != IPT_ALIGN(sizeof(struct ipt_set_info_match))) {
6448+ ip_set_printk("invalid matchsize %d", matchsize);
6449+ return;
6450+ }
6451+
6452+ ip_set_put(info->match_set.index);
6453+}
6454+
6455+static struct ipt_match set_match = {
6456+ .name = "set",
6457+ .match = &match,
6458+ .checkentry = &checkentry,
6459+ .destroy = &destroy,
6460+ .me = THIS_MODULE
6461+};
6462+
6463+MODULE_LICENSE("GPL");
6464+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6465+MODULE_DESCRIPTION("iptables IP set match module");
6466+
6467+static int __init init(void)
6468+{
6469+ return ipt_register_match(&set_match);
6470+}
6471+
6472+static void __exit fini(void)
6473+{
6474+ ipt_unregister_match(&set_match);
6475+}
6476+
6477+module_init(init);
6478+module_exit(fini);
This page took 2.27432 seconds and 4 git commands to generate.