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