aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-02-02 18:24:48 -0500
committerDavid S. Miller <davem@davemloft.net>2011-02-02 18:24:48 -0500
commit8fe73503fae8cb8f00c80dd6444c1ddcd19257bd (patch)
tree39cc6d38a628c445da7d52c006df6930a2c58411 /include/linux
parent123b9731b14f49cd41c91ed2b6c31e515615347c (diff)
parent9291747f118d6404e509747b85ff5f6dfec368d2 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/netfilter/Kbuild4
-rw-r--r--include/linux/netfilter/ipset/Kbuild4
-rw-r--r--include/linux/netfilter/ipset/ip_set.h452
-rw-r--r--include/linux/netfilter/ipset/ip_set_ahash.h1074
-rw-r--r--include/linux/netfilter/ipset/ip_set_bitmap.h31
-rw-r--r--include/linux/netfilter/ipset/ip_set_getport.h21
-rw-r--r--include/linux/netfilter/ipset/ip_set_hash.h26
-rw-r--r--include/linux/netfilter/ipset/ip_set_list.h27
-rw-r--r--include/linux/netfilter/ipset/ip_set_timeout.h127
-rw-r--r--include/linux/netfilter/ipset/pfxlen.h35
-rw-r--r--include/linux/netfilter/nfnetlink.h3
-rw-r--r--include/linux/netfilter/xt_devgroup.h21
-rw-r--r--include/linux/netfilter/xt_set.h56
13 files changed, 1880 insertions, 1 deletions
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 89c0d1e20d72..15e83bf3dd58 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -1,3 +1,5 @@
1header-y += ipset/
2
1header-y += nf_conntrack_common.h 3header-y += nf_conntrack_common.h
2header-y += nf_conntrack_ftp.h 4header-y += nf_conntrack_ftp.h
3header-y += nf_conntrack_sctp.h 5header-y += nf_conntrack_sctp.h
@@ -35,6 +37,7 @@ header-y += xt_connmark.h
35header-y += xt_conntrack.h 37header-y += xt_conntrack.h
36header-y += xt_cpu.h 38header-y += xt_cpu.h
37header-y += xt_dccp.h 39header-y += xt_dccp.h
40header-y += xt_devgroup.h
38header-y += xt_dscp.h 41header-y += xt_dscp.h
39header-y += xt_esp.h 42header-y += xt_esp.h
40header-y += xt_hashlimit.h 43header-y += xt_hashlimit.h
@@ -55,6 +58,7 @@ header-y += xt_quota.h
55header-y += xt_rateest.h 58header-y += xt_rateest.h
56header-y += xt_realm.h 59header-y += xt_realm.h
57header-y += xt_recent.h 60header-y += xt_recent.h
61header-y += xt_set.h
58header-y += xt_sctp.h 62header-y += xt_sctp.h
59header-y += xt_socket.h 63header-y += xt_socket.h
60header-y += xt_state.h 64header-y += xt_state.h
diff --git a/include/linux/netfilter/ipset/Kbuild b/include/linux/netfilter/ipset/Kbuild
new file mode 100644
index 000000000000..601fe71d34d5
--- /dev/null
+++ b/include/linux/netfilter/ipset/Kbuild
@@ -0,0 +1,4 @@
1header-y += ip_set.h
2header-y += ip_set_bitmap.h
3header-y += ip_set_hash.h
4header-y += ip_set_list.h
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
new file mode 100644
index 000000000000..ec333d83f3b4
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -0,0 +1,452 @@
1#ifndef _IP_SET_H
2#define _IP_SET_H
3
4/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
5 * Patrick Schaaf <bof@bof.de>
6 * Martin Josefsson <gandalf@wlug.westbo.se>
7 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14/* The protocol version */
15#define IPSET_PROTOCOL 6
16
17/* The max length of strings including NUL: set and type identifiers */
18#define IPSET_MAXNAMELEN 32
19
20/* Message types and commands */
21enum ipset_cmd {
22 IPSET_CMD_NONE,
23 IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
24 IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
25 IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
26 IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
27 IPSET_CMD_RENAME, /* 5: Rename a set */
28 IPSET_CMD_SWAP, /* 6: Swap two sets */
29 IPSET_CMD_LIST, /* 7: List sets */
30 IPSET_CMD_SAVE, /* 8: Save sets */
31 IPSET_CMD_ADD, /* 9: Add an element to a set */
32 IPSET_CMD_DEL, /* 10: Delete an element from a set */
33 IPSET_CMD_TEST, /* 11: Test an element in a set */
34 IPSET_CMD_HEADER, /* 12: Get set header data only */
35 IPSET_CMD_TYPE, /* 13: Get set type */
36 IPSET_MSG_MAX, /* Netlink message commands */
37
38 /* Commands in userspace: */
39 IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
40 IPSET_CMD_HELP, /* 15: Get help */
41 IPSET_CMD_VERSION, /* 16: Get program version */
42 IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
43
44 IPSET_CMD_MAX,
45
46 IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
47};
48
49/* Attributes at command level */
50enum {
51 IPSET_ATTR_UNSPEC,
52 IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
53 IPSET_ATTR_SETNAME, /* 2: Name of the set */
54 IPSET_ATTR_TYPENAME, /* 3: Typename */
55 IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
56 IPSET_ATTR_REVISION, /* 4: Settype revision */
57 IPSET_ATTR_FAMILY, /* 5: Settype family */
58 IPSET_ATTR_FLAGS, /* 6: Flags at command level */
59 IPSET_ATTR_DATA, /* 7: Nested attributes */
60 IPSET_ATTR_ADT, /* 8: Multiple data containers */
61 IPSET_ATTR_LINENO, /* 9: Restore lineno */
62 IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
63 IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
64 __IPSET_ATTR_CMD_MAX,
65};
66#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
67
68/* CADT specific attributes */
69enum {
70 IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
71 IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
72 IPSET_ATTR_IP_TO, /* 2 */
73 IPSET_ATTR_CIDR, /* 3 */
74 IPSET_ATTR_PORT, /* 4 */
75 IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
76 IPSET_ATTR_PORT_TO, /* 5 */
77 IPSET_ATTR_TIMEOUT, /* 6 */
78 IPSET_ATTR_PROTO, /* 7 */
79 IPSET_ATTR_CADT_FLAGS, /* 8 */
80 IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
81 /* Reserve empty slots */
82 IPSET_ATTR_CADT_MAX = 16,
83 /* Create-only specific attributes */
84 IPSET_ATTR_GC,
85 IPSET_ATTR_HASHSIZE,
86 IPSET_ATTR_MAXELEM,
87 IPSET_ATTR_NETMASK,
88 IPSET_ATTR_PROBES,
89 IPSET_ATTR_RESIZE,
90 IPSET_ATTR_SIZE,
91 /* Kernel-only */
92 IPSET_ATTR_ELEMENTS,
93 IPSET_ATTR_REFERENCES,
94 IPSET_ATTR_MEMSIZE,
95
96 __IPSET_ATTR_CREATE_MAX,
97};
98#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
99
100/* ADT specific attributes */
101enum {
102 IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
103 IPSET_ATTR_NAME,
104 IPSET_ATTR_NAMEREF,
105 IPSET_ATTR_IP2,
106 IPSET_ATTR_CIDR2,
107 __IPSET_ATTR_ADT_MAX,
108};
109#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
110
111/* IP specific attributes */
112enum {
113 IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
114 IPSET_ATTR_IPADDR_IPV6,
115 __IPSET_ATTR_IPADDR_MAX,
116};
117#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
118
119/* Error codes */
120enum ipset_errno {
121 IPSET_ERR_PRIVATE = 4096,
122 IPSET_ERR_PROTOCOL,
123 IPSET_ERR_FIND_TYPE,
124 IPSET_ERR_MAX_SETS,
125 IPSET_ERR_BUSY,
126 IPSET_ERR_EXIST_SETNAME2,
127 IPSET_ERR_TYPE_MISMATCH,
128 IPSET_ERR_EXIST,
129 IPSET_ERR_INVALID_CIDR,
130 IPSET_ERR_INVALID_NETMASK,
131 IPSET_ERR_INVALID_FAMILY,
132 IPSET_ERR_TIMEOUT,
133 IPSET_ERR_REFERENCED,
134 IPSET_ERR_IPADDR_IPV4,
135 IPSET_ERR_IPADDR_IPV6,
136
137 /* Type specific error codes */
138 IPSET_ERR_TYPE_SPECIFIC = 4352,
139};
140
141/* Flags at command level */
142enum ipset_cmd_flags {
143 IPSET_FLAG_BIT_EXIST = 0,
144 IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
145};
146
147/* Flags at CADT attribute level */
148enum ipset_cadt_flags {
149 IPSET_FLAG_BIT_BEFORE = 0,
150 IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
151};
152
153/* Commands with settype-specific attributes */
154enum ipset_adt {
155 IPSET_ADD,
156 IPSET_DEL,
157 IPSET_TEST,
158 IPSET_ADT_MAX,
159 IPSET_CREATE = IPSET_ADT_MAX,
160 IPSET_CADT_MAX,
161};
162
163#ifdef __KERNEL__
164#include <linux/ip.h>
165#include <linux/ipv6.h>
166#include <linux/netlink.h>
167#include <linux/netfilter.h>
168#include <linux/vmalloc.h>
169#include <net/netlink.h>
170
171/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
172 * and IPSET_INVALID_ID if you want to increase the max number of sets.
173 */
174typedef u16 ip_set_id_t;
175
176#define IPSET_INVALID_ID 65535
177
178enum ip_set_dim {
179 IPSET_DIM_ZERO = 0,
180 IPSET_DIM_ONE,
181 IPSET_DIM_TWO,
182 IPSET_DIM_THREE,
183 /* Max dimension in elements.
184 * If changed, new revision of iptables match/target is required.
185 */
186 IPSET_DIM_MAX = 6,
187};
188
189/* Option flags for kernel operations */
190enum ip_set_kopt {
191 IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
192 IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
193 IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
194 IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
195};
196
197/* Set features */
198enum ip_set_feature {
199 IPSET_TYPE_IP_FLAG = 0,
200 IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),
201 IPSET_TYPE_PORT_FLAG = 1,
202 IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),
203 IPSET_TYPE_MAC_FLAG = 2,
204 IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),
205 IPSET_TYPE_IP2_FLAG = 3,
206 IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
207 IPSET_TYPE_NAME_FLAG = 4,
208 IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
209 /* Strictly speaking not a feature, but a flag for dumping:
210 * this settype must be dumped last */
211 IPSET_DUMP_LAST_FLAG = 7,
212 IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
213};
214
215struct ip_set;
216
217typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
218
219/* Set type, variant-specific part */
220struct ip_set_type_variant {
221 /* Kernelspace: test/add/del entries
222 * returns negative error code,
223 * zero for no match/success to add/delete
224 * positive for matching element */
225 int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
226 enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
227
228 /* Userspace: test/add/del entries
229 * returns negative error code,
230 * zero for no match/success to add/delete
231 * positive for matching element */
232 int (*uadt)(struct ip_set *set, struct nlattr *tb[],
233 enum ipset_adt adt, u32 *lineno, u32 flags);
234
235 /* Low level add/del/test functions */
236 ipset_adtfn adt[IPSET_ADT_MAX];
237
238 /* When adding entries and set is full, try to resize the set */
239 int (*resize)(struct ip_set *set, bool retried);
240 /* Destroy the set */
241 void (*destroy)(struct ip_set *set);
242 /* Flush the elements */
243 void (*flush)(struct ip_set *set);
244 /* Expire entries before listing */
245 void (*expire)(struct ip_set *set);
246 /* List set header data */
247 int (*head)(struct ip_set *set, struct sk_buff *skb);
248 /* List elements */
249 int (*list)(const struct ip_set *set, struct sk_buff *skb,
250 struct netlink_callback *cb);
251
252 /* Return true if "b" set is the same as "a"
253 * according to the create set parameters */
254 bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
255};
256
257/* The core set type structure */
258struct ip_set_type {
259 struct list_head list;
260
261 /* Typename */
262 char name[IPSET_MAXNAMELEN];
263 /* Protocol version */
264 u8 protocol;
265 /* Set features to control swapping */
266 u8 features;
267 /* Set type dimension */
268 u8 dimension;
269 /* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
270 u8 family;
271 /* Type revision */
272 u8 revision;
273
274 /* Create set */
275 int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
276
277 /* Attribute policies */
278 const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1];
279 const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1];
280
281 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
282 struct module *me;
283};
284
285/* register and unregister set type */
286extern int ip_set_type_register(struct ip_set_type *set_type);
287extern void ip_set_type_unregister(struct ip_set_type *set_type);
288
289/* A generic IP set */
290struct ip_set {
291 /* The name of the set */
292 char name[IPSET_MAXNAMELEN];
293 /* Lock protecting the set data */
294 rwlock_t lock;
295 /* References to the set */
296 atomic_t ref;
297 /* The core set type */
298 struct ip_set_type *type;
299 /* The type variant doing the real job */
300 const struct ip_set_type_variant *variant;
301 /* The actual INET family of the set */
302 u8 family;
303 /* The type specific data */
304 void *data;
305};
306
307/* register and unregister set references */
308extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
309extern void ip_set_put_byindex(ip_set_id_t index);
310extern const char * ip_set_name_byindex(ip_set_id_t index);
311extern ip_set_id_t ip_set_nfnl_get(const char *name);
312extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
313extern void ip_set_nfnl_put(ip_set_id_t index);
314
315/* API for iptables set match, and SET target */
316extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
317 u8 family, u8 dim, u8 flags);
318extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
319 u8 family, u8 dim, u8 flags);
320extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
321 u8 family, u8 dim, u8 flags);
322
323/* Utility functions */
324extern void * ip_set_alloc(size_t size);
325extern void ip_set_free(void *members);
326extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
327extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
328
329static inline int
330ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
331{
332 __be32 ip;
333 int ret = ip_set_get_ipaddr4(nla, &ip);
334
335 if (ret)
336 return ret;
337 *ipaddr = ntohl(ip);
338 return 0;
339}
340
341/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
342static inline bool
343ip_set_eexist(int ret, u32 flags)
344{
345 return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
346}
347
348/* Check the NLA_F_NET_BYTEORDER flag */
349static inline bool
350ip_set_attr_netorder(struct nlattr *tb[], int type)
351{
352 return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
353}
354
355static inline bool
356ip_set_optattr_netorder(struct nlattr *tb[], int type)
357{
358 return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
359}
360
361/* Useful converters */
362static inline u32
363ip_set_get_h32(const struct nlattr *attr)
364{
365 return ntohl(nla_get_be32(attr));
366}
367
368static inline u16
369ip_set_get_h16(const struct nlattr *attr)
370{
371 return ntohs(nla_get_be16(attr));
372}
373
374#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
375#define ipset_nest_end(skb, start) nla_nest_end(skb, start)
376
377#define NLA_PUT_IPADDR4(skb, type, ipaddr) \
378do { \
379 struct nlattr *__nested = ipset_nest_start(skb, type); \
380 \
381 if (!__nested) \
382 goto nla_put_failure; \
383 NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \
384 ipset_nest_end(skb, __nested); \
385} while (0)
386
387#define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \
388do { \
389 struct nlattr *__nested = ipset_nest_start(skb, type); \
390 \
391 if (!__nested) \
392 goto nla_put_failure; \
393 NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \
394 sizeof(struct in6_addr), ipaddrptr); \
395 ipset_nest_end(skb, __nested); \
396} while (0)
397
398/* Get address from skbuff */
399static inline __be32
400ip4addr(const struct sk_buff *skb, bool src)
401{
402 return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
403}
404
405static inline void
406ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
407{
408 *addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
409}
410
411static inline void
412ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
413{
414 memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,
415 sizeof(*addr));
416}
417
418/* Calculate the bytes required to store the inclusive range of a-b */
419static inline int
420bitmap_bytes(u32 a, u32 b)
421{
422 return 4 * ((((b - a + 8) / 8) + 3) / 4);
423}
424
425/* Interface to iptables/ip6tables */
426
427#define SO_IP_SET 83
428
429union ip_set_name_index {
430 char name[IPSET_MAXNAMELEN];
431 ip_set_id_t index;
432};
433
434#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
435struct ip_set_req_get_set {
436 unsigned op;
437 unsigned version;
438 union ip_set_name_index set;
439};
440
441#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
442/* Uses ip_set_req_get_set */
443
444#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
445struct ip_set_req_version {
446 unsigned op;
447 unsigned version;
448};
449
450#endif /* __KERNEL__ */
451
452#endif /*_IP_SET_H */
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
new file mode 100644
index 000000000000..ec9d9bea1e37
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -0,0 +1,1074 @@
1#ifndef _IP_SET_AHASH_H
2#define _IP_SET_AHASH_H
3
4#include <linux/rcupdate.h>
5#include <linux/jhash.h>
6#include <linux/netfilter/ipset/ip_set_timeout.h>
7
8/* Hashing which uses arrays to resolve clashing. The hash table is resized
9 * (doubled) when searching becomes too long.
10 * Internally jhash is used with the assumption that the size of the
11 * stored data is a multiple of sizeof(u32). If storage supports timeout,
12 * the timeout field must be the last one in the data structure - that field
13 * is ignored when computing the hash key.
14 *
15 * Readers and resizing
16 *
17 * Resizing can be triggered by userspace command only, and those
18 * are serialized by the nfnl mutex. During resizing the set is
19 * read-locked, so the only possible concurrent operations are
20 * the kernel side readers. Those must be protected by proper RCU locking.
21 */
22
23/* Number of elements to store in an initial array block */
24#define AHASH_INIT_SIZE 4
25/* Max number of elements to store in an array block */
26#define AHASH_MAX_SIZE (3*4)
27
28/* A hash bucket */
29struct hbucket {
30 void *value; /* the array of the values */
31 u8 size; /* size of the array */
32 u8 pos; /* position of the first free entry */
33};
34
35/* The hash table: the table size stored here in order to make resizing easy */
36struct htable {
37 u8 htable_bits; /* size of hash table == 2^htable_bits */
38 struct hbucket bucket[0]; /* hashtable buckets */
39};
40
41#define hbucket(h, i) &((h)->bucket[i])
42
43/* Book-keeping of the prefixes added to the set */
44struct ip_set_hash_nets {
45 u8 cidr; /* the different cidr values in the set */
46 u32 nets; /* number of elements per cidr */
47};
48
49/* The generic ip_set hash structure */
50struct ip_set_hash {
51 struct htable *table; /* the hash table */
52 u32 maxelem; /* max elements in the hash */
53 u32 elements; /* current element (vs timeout) */
54 u32 initval; /* random jhash init value */
55 u32 timeout; /* timeout value, if enabled */
56 struct timer_list gc; /* garbage collection when timeout enabled */
57#ifdef IP_SET_HASH_WITH_NETMASK
58 u8 netmask; /* netmask value for subnets to store */
59#endif
60#ifdef IP_SET_HASH_WITH_NETS
61 struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */
62#endif
63};
64
65/* Compute htable_bits from the user input parameter hashsize */
66static u8
67htable_bits(u32 hashsize)
68{
69 /* Assume that hashsize == 2^htable_bits */
70 u8 bits = fls(hashsize - 1);
71 if (jhash_size(bits) != hashsize)
72 /* Round up to the first 2^n value */
73 bits = fls(hashsize);
74
75 return bits;
76}
77
78#ifdef IP_SET_HASH_WITH_NETS
79
80#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
81
82/* Network cidr size book keeping when the hash stores different
83 * sized networks */
84static void
85add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
86{
87 u8 i;
88
89 ++h->nets[cidr-1].nets;
90
91 pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);
92
93 if (h->nets[cidr-1].nets > 1)
94 return;
95
96 /* New cidr size */
97 for (i = 0; i < host_mask && h->nets[i].cidr; i++) {
98 /* Add in increasing prefix order, so larger cidr first */
99 if (h->nets[i].cidr < cidr)
100 swap(h->nets[i].cidr, cidr);
101 }
102 if (i < host_mask)
103 h->nets[i].cidr = cidr;
104}
105
106static void
107del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
108{
109 u8 i;
110
111 --h->nets[cidr-1].nets;
112
113 pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
114
115 if (h->nets[cidr-1].nets != 0)
116 return;
117
118 /* All entries with this cidr size deleted, so cleanup h->cidr[] */
119 for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) {
120 if (h->nets[i].cidr == cidr)
121 h->nets[i].cidr = cidr = h->nets[i+1].cidr;
122 }
123 h->nets[i - 1].cidr = 0;
124}
125#endif
126
127/* Destroy the hashtable part of the set */
128static void
129ahash_destroy(struct htable *t)
130{
131 struct hbucket *n;
132 u32 i;
133
134 for (i = 0; i < jhash_size(t->htable_bits); i++) {
135 n = hbucket(t, i);
136 if (n->size)
137 /* FIXME: use slab cache */
138 kfree(n->value);
139 }
140
141 ip_set_free(t);
142}
143
144/* Calculate the actual memory size of the set data */
145static size_t
146ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)
147{
148 u32 i;
149 struct htable *t = h->table;
150 size_t memsize = sizeof(*h)
151 + sizeof(*t)
152#ifdef IP_SET_HASH_WITH_NETS
153 + sizeof(struct ip_set_hash_nets) * host_mask
154#endif
155 + jhash_size(t->htable_bits) * sizeof(struct hbucket);
156
157 for (i = 0; i < jhash_size(t->htable_bits); i++)
158 memsize += t->bucket[i].size * dsize;
159
160 return memsize;
161}
162
163/* Flush a hash type of set: destroy all elements */
164static void
165ip_set_hash_flush(struct ip_set *set)
166{
167 struct ip_set_hash *h = set->data;
168 struct htable *t = h->table;
169 struct hbucket *n;
170 u32 i;
171
172 for (i = 0; i < jhash_size(t->htable_bits); i++) {
173 n = hbucket(t, i);
174 if (n->size) {
175 n->size = n->pos = 0;
176 /* FIXME: use slab cache */
177 kfree(n->value);
178 }
179 }
180#ifdef IP_SET_HASH_WITH_NETS
181 memset(h->nets, 0, sizeof(struct ip_set_hash_nets)
182 * SET_HOST_MASK(set->family));
183#endif
184 h->elements = 0;
185}
186
187/* Destroy a hash type of set */
188static void
189ip_set_hash_destroy(struct ip_set *set)
190{
191 struct ip_set_hash *h = set->data;
192
193 if (with_timeout(h->timeout))
194 del_timer_sync(&h->gc);
195
196 ahash_destroy(h->table);
197 kfree(h);
198
199 set->data = NULL;
200}
201
202#define HKEY(data, initval, htable_bits) \
203(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \
204 & jhash_mask(htable_bits))
205
206#endif /* _IP_SET_AHASH_H */
207
208#define CONCAT(a, b, c) a##b##c
209#define TOKEN(a, b, c) CONCAT(a, b, c)
210
211/* Type/family dependent function prototypes */
212
213#define type_pf_data_equal TOKEN(TYPE, PF, _data_equal)
214#define type_pf_data_isnull TOKEN(TYPE, PF, _data_isnull)
215#define type_pf_data_copy TOKEN(TYPE, PF, _data_copy)
216#define type_pf_data_zero_out TOKEN(TYPE, PF, _data_zero_out)
217#define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask)
218#define type_pf_data_list TOKEN(TYPE, PF, _data_list)
219#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
220
221#define type_pf_elem TOKEN(TYPE, PF, _elem)
222#define type_pf_telem TOKEN(TYPE, PF, _telem)
223#define type_pf_data_timeout TOKEN(TYPE, PF, _data_timeout)
224#define type_pf_data_expired TOKEN(TYPE, PF, _data_expired)
225#define type_pf_data_timeout_set TOKEN(TYPE, PF, _data_timeout_set)
226
227#define type_pf_elem_add TOKEN(TYPE, PF, _elem_add)
228#define type_pf_add TOKEN(TYPE, PF, _add)
229#define type_pf_del TOKEN(TYPE, PF, _del)
230#define type_pf_test_cidrs TOKEN(TYPE, PF, _test_cidrs)
231#define type_pf_test TOKEN(TYPE, PF, _test)
232
233#define type_pf_elem_tadd TOKEN(TYPE, PF, _elem_tadd)
234#define type_pf_del_telem TOKEN(TYPE, PF, _ahash_del_telem)
235#define type_pf_expire TOKEN(TYPE, PF, _expire)
236#define type_pf_tadd TOKEN(TYPE, PF, _tadd)
237#define type_pf_tdel TOKEN(TYPE, PF, _tdel)
238#define type_pf_ttest_cidrs TOKEN(TYPE, PF, _ahash_ttest_cidrs)
239#define type_pf_ttest TOKEN(TYPE, PF, _ahash_ttest)
240
241#define type_pf_resize TOKEN(TYPE, PF, _resize)
242#define type_pf_tresize TOKEN(TYPE, PF, _tresize)
243#define type_pf_flush ip_set_hash_flush
244#define type_pf_destroy ip_set_hash_destroy
245#define type_pf_head TOKEN(TYPE, PF, _head)
246#define type_pf_list TOKEN(TYPE, PF, _list)
247#define type_pf_tlist TOKEN(TYPE, PF, _tlist)
248#define type_pf_same_set TOKEN(TYPE, PF, _same_set)
249#define type_pf_kadt TOKEN(TYPE, PF, _kadt)
250#define type_pf_uadt TOKEN(TYPE, PF, _uadt)
251#define type_pf_gc TOKEN(TYPE, PF, _gc)
252#define type_pf_gc_init TOKEN(TYPE, PF, _gc_init)
253#define type_pf_variant TOKEN(TYPE, PF, _variant)
254#define type_pf_tvariant TOKEN(TYPE, PF, _tvariant)
255
256/* Flavour without timeout */
257
258/* Get the ith element from the array block n */
259#define ahash_data(n, i) \
260 ((struct type_pf_elem *)((n)->value) + (i))
261
262/* Add an element to the hash table when resizing the set:
263 * we spare the maintenance of the internal counters. */
264static int
265type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value)
266{
267 if (n->pos >= n->size) {
268 void *tmp;
269
270 if (n->size >= AHASH_MAX_SIZE)
271 /* Trigger rehashing */
272 return -EAGAIN;
273
274 tmp = kzalloc((n->size + AHASH_INIT_SIZE)
275 * sizeof(struct type_pf_elem),
276 GFP_ATOMIC);
277 if (!tmp)
278 return -ENOMEM;
279 if (n->size) {
280 memcpy(tmp, n->value,
281 sizeof(struct type_pf_elem) * n->size);
282 kfree(n->value);
283 }
284 n->value = tmp;
285 n->size += AHASH_INIT_SIZE;
286 }
287 type_pf_data_copy(ahash_data(n, n->pos++), value);
288 return 0;
289}
290
291/* Resize a hash: create a new hash table with doubling the hashsize
292 * and inserting the elements to it. Repeat until we succeed or
293 * fail due to memory pressures. */
294static int
295type_pf_resize(struct ip_set *set, bool retried)
296{
297 struct ip_set_hash *h = set->data;
298 struct htable *t, *orig = h->table;
299 u8 htable_bits = orig->htable_bits;
300 const struct type_pf_elem *data;
301 struct hbucket *n, *m;
302 u32 i, j;
303 int ret;
304
305retry:
306 ret = 0;
307 htable_bits++;
308 pr_debug("attempt to resize set %s from %u to %u, t %p\n",
309 set->name, orig->htable_bits, htable_bits, orig);
310 if (!htable_bits)
311 /* In case we have plenty of memory :-) */
312 return -IPSET_ERR_HASH_FULL;
313 t = ip_set_alloc(sizeof(*t)
314 + jhash_size(htable_bits) * sizeof(struct hbucket));
315 if (!t)
316 return -ENOMEM;
317 t->htable_bits = htable_bits;
318
319 read_lock_bh(&set->lock);
320 for (i = 0; i < jhash_size(orig->htable_bits); i++) {
321 n = hbucket(orig, i);
322 for (j = 0; j < n->pos; j++) {
323 data = ahash_data(n, j);
324 m = hbucket(t, HKEY(data, h->initval, htable_bits));
325 ret = type_pf_elem_add(m, data);
326 if (ret < 0) {
327 read_unlock_bh(&set->lock);
328 ahash_destroy(t);
329 if (ret == -EAGAIN)
330 goto retry;
331 return ret;
332 }
333 }
334 }
335
336 rcu_assign_pointer(h->table, t);
337 read_unlock_bh(&set->lock);
338
339 /* Give time to other readers of the set */
340 synchronize_rcu_bh();
341
342 pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
343 orig->htable_bits, orig, t->htable_bits, t);
344 ahash_destroy(orig);
345
346 return 0;
347}
348
349/* Add an element to a hash and update the internal counters when succeeded,
350 * otherwise report the proper error code. */
351static int
352type_pf_add(struct ip_set *set, void *value, u32 timeout)
353{
354 struct ip_set_hash *h = set->data;
355 struct htable *t;
356 const struct type_pf_elem *d = value;
357 struct hbucket *n;
358 int i, ret = 0;
359 u32 key;
360
361 if (h->elements >= h->maxelem)
362 return -IPSET_ERR_HASH_FULL;
363
364 rcu_read_lock_bh();
365 t = rcu_dereference_bh(h->table);
366 key = HKEY(value, h->initval, t->htable_bits);
367 n = hbucket(t, key);
368 for (i = 0; i < n->pos; i++)
369 if (type_pf_data_equal(ahash_data(n, i), d)) {
370 ret = -IPSET_ERR_EXIST;
371 goto out;
372 }
373
374 ret = type_pf_elem_add(n, value);
375 if (ret != 0)
376 goto out;
377
378#ifdef IP_SET_HASH_WITH_NETS
379 add_cidr(h, d->cidr, HOST_MASK);
380#endif
381 h->elements++;
382out:
383 rcu_read_unlock_bh();
384 return ret;
385}
386
387/* Delete an element from the hash: swap it with the last element
388 * and free up space if possible.
389 */
390static int
391type_pf_del(struct ip_set *set, void *value, u32 timeout)
392{
393 struct ip_set_hash *h = set->data;
394 struct htable *t = h->table;
395 const struct type_pf_elem *d = value;
396 struct hbucket *n;
397 int i;
398 struct type_pf_elem *data;
399 u32 key;
400
401 key = HKEY(value, h->initval, t->htable_bits);
402 n = hbucket(t, key);
403 for (i = 0; i < n->pos; i++) {
404 data = ahash_data(n, i);
405 if (!type_pf_data_equal(data, d))
406 continue;
407 if (i != n->pos - 1)
408 /* Not last one */
409 type_pf_data_copy(data, ahash_data(n, n->pos - 1));
410
411 n->pos--;
412 h->elements--;
413#ifdef IP_SET_HASH_WITH_NETS
414 del_cidr(h, d->cidr, HOST_MASK);
415#endif
416 if (n->pos + AHASH_INIT_SIZE < n->size) {
417 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
418 * sizeof(struct type_pf_elem),
419 GFP_ATOMIC);
420 if (!tmp)
421 return 0;
422 n->size -= AHASH_INIT_SIZE;
423 memcpy(tmp, n->value,
424 n->size * sizeof(struct type_pf_elem));
425 kfree(n->value);
426 n->value = tmp;
427 }
428 return 0;
429 }
430
431 return -IPSET_ERR_EXIST;
432}
433
434#ifdef IP_SET_HASH_WITH_NETS
435
436/* Special test function which takes into account the different network
437 * sizes added to the set */
438static int
439type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
440{
441 struct ip_set_hash *h = set->data;
442 struct htable *t = h->table;
443 struct hbucket *n;
444 const struct type_pf_elem *data;
445 int i, j = 0;
446 u32 key;
447 u8 host_mask = SET_HOST_MASK(set->family);
448
449 pr_debug("test by nets\n");
450 for (; j < host_mask && h->nets[j].cidr; j++) {
451 type_pf_data_netmask(d, h->nets[j].cidr);
452 key = HKEY(d, h->initval, t->htable_bits);
453 n = hbucket(t, key);
454 for (i = 0; i < n->pos; i++) {
455 data = ahash_data(n, i);
456 if (type_pf_data_equal(data, d))
457 return 1;
458 }
459 }
460 return 0;
461}
462#endif
463
464/* Test whether the element is added to the set */
465static int
466type_pf_test(struct ip_set *set, void *value, u32 timeout)
467{
468 struct ip_set_hash *h = set->data;
469 struct htable *t = h->table;
470 struct type_pf_elem *d = value;
471 struct hbucket *n;
472 const struct type_pf_elem *data;
473 int i;
474 u32 key;
475
476#ifdef IP_SET_HASH_WITH_NETS
477 /* If we test an IP address and not a network address,
478 * try all possible network sizes */
479 if (d->cidr == SET_HOST_MASK(set->family))
480 return type_pf_test_cidrs(set, d, timeout);
481#endif
482
483 key = HKEY(d, h->initval, t->htable_bits);
484 n = hbucket(t, key);
485 for (i = 0; i < n->pos; i++) {
486 data = ahash_data(n, i);
487 if (type_pf_data_equal(data, d))
488 return 1;
489 }
490 return 0;
491}
492
493/* Reply a HEADER request: fill out the header part of the set */
494static int
495type_pf_head(struct ip_set *set, struct sk_buff *skb)
496{
497 const struct ip_set_hash *h = set->data;
498 struct nlattr *nested;
499 size_t memsize;
500
501 read_lock_bh(&set->lock);
502 memsize = ahash_memsize(h, with_timeout(h->timeout)
503 ? sizeof(struct type_pf_telem)
504 : sizeof(struct type_pf_elem),
505 set->family == AF_INET ? 32 : 128);
506 read_unlock_bh(&set->lock);
507
508 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
509 if (!nested)
510 goto nla_put_failure;
511 NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE,
512 htonl(jhash_size(h->table->htable_bits)));
513 NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem));
514#ifdef IP_SET_HASH_WITH_NETMASK
515 if (h->netmask != HOST_MASK)
516 NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
517#endif
518 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
519 htonl(atomic_read(&set->ref) - 1));
520 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));
521 if (with_timeout(h->timeout))
522 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout));
523 ipset_nest_end(skb, nested);
524
525 return 0;
526nla_put_failure:
527 return -EMSGSIZE;
528}
529
530/* Reply a LIST/SAVE request: dump the elements of the specified set */
531static int
532type_pf_list(const struct ip_set *set,
533 struct sk_buff *skb, struct netlink_callback *cb)
534{
535 const struct ip_set_hash *h = set->data;
536 const struct htable *t = h->table;
537 struct nlattr *atd, *nested;
538 const struct hbucket *n;
539 const struct type_pf_elem *data;
540 u32 first = cb->args[2];
541 /* We assume that one hash bucket fills into one page */
542 void *incomplete;
543 int i;
544
545 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
546 if (!atd)
547 return -EMSGSIZE;
548 pr_debug("list hash set %s\n", set->name);
549 for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
550 incomplete = skb_tail_pointer(skb);
551 n = hbucket(t, cb->args[2]);
552 pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);
553 for (i = 0; i < n->pos; i++) {
554 data = ahash_data(n, i);
555 pr_debug("list hash %lu hbucket %p i %u, data %p\n",
556 cb->args[2], n, i, data);
557 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
558 if (!nested) {
559 if (cb->args[2] == first) {
560 nla_nest_cancel(skb, atd);
561 return -EMSGSIZE;
562 } else
563 goto nla_put_failure;
564 }
565 if (type_pf_data_list(skb, data))
566 goto nla_put_failure;
567 ipset_nest_end(skb, nested);
568 }
569 }
570 ipset_nest_end(skb, atd);
571 /* Set listing finished */
572 cb->args[2] = 0;
573
574 return 0;
575
576nla_put_failure:
577 nlmsg_trim(skb, incomplete);
578 ipset_nest_end(skb, atd);
579 if (unlikely(first == cb->args[2])) {
580 pr_warning("Can't list set %s: one bucket does not fit into "
581 "a message. Please report it!\n", set->name);
582 cb->args[2] = 0;
583 return -EMSGSIZE;
584 }
585 return 0;
586}
587
588static int
589type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
590 enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
591static int
592type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
593 enum ipset_adt adt, u32 *lineno, u32 flags);
594
595static const struct ip_set_type_variant type_pf_variant = {
596 .kadt = type_pf_kadt,
597 .uadt = type_pf_uadt,
598 .adt = {
599 [IPSET_ADD] = type_pf_add,
600 [IPSET_DEL] = type_pf_del,
601 [IPSET_TEST] = type_pf_test,
602 },
603 .destroy = type_pf_destroy,
604 .flush = type_pf_flush,
605 .head = type_pf_head,
606 .list = type_pf_list,
607 .resize = type_pf_resize,
608 .same_set = type_pf_same_set,
609};
610
611/* Flavour with timeout support */
612
613#define ahash_tdata(n, i) \
614 (struct type_pf_elem *)((struct type_pf_telem *)((n)->value) + (i))
615
616static inline u32
617type_pf_data_timeout(const struct type_pf_elem *data)
618{
619 const struct type_pf_telem *tdata =
620 (const struct type_pf_telem *) data;
621
622 return tdata->timeout;
623}
624
625static inline bool
626type_pf_data_expired(const struct type_pf_elem *data)
627{
628 const struct type_pf_telem *tdata =
629 (const struct type_pf_telem *) data;
630
631 return ip_set_timeout_expired(tdata->timeout);
632}
633
634static inline void
635type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
636{
637 struct type_pf_telem *tdata = (struct type_pf_telem *) data;
638
639 tdata->timeout = ip_set_timeout_set(timeout);
640}
641
642static int
643type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
644 u32 timeout)
645{
646 struct type_pf_elem *data;
647
648 if (n->pos >= n->size) {
649 void *tmp;
650
651 if (n->size >= AHASH_MAX_SIZE)
652 /* Trigger rehashing */
653 return -EAGAIN;
654
655 tmp = kzalloc((n->size + AHASH_INIT_SIZE)
656 * sizeof(struct type_pf_telem),
657 GFP_ATOMIC);
658 if (!tmp)
659 return -ENOMEM;
660 if (n->size) {
661 memcpy(tmp, n->value,
662 sizeof(struct type_pf_telem) * n->size);
663 kfree(n->value);
664 }
665 n->value = tmp;
666 n->size += AHASH_INIT_SIZE;
667 }
668 data = ahash_tdata(n, n->pos++);
669 type_pf_data_copy(data, value);
670 type_pf_data_timeout_set(data, timeout);
671 return 0;
672}
673
674/* Delete expired elements from the hashtable */
675static void
676type_pf_expire(struct ip_set_hash *h)
677{
678 struct htable *t = h->table;
679 struct hbucket *n;
680 struct type_pf_elem *data;
681 u32 i;
682 int j;
683
684 for (i = 0; i < jhash_size(t->htable_bits); i++) {
685 n = hbucket(t, i);
686 for (j = 0; j < n->pos; j++) {
687 data = ahash_tdata(n, j);
688 if (type_pf_data_expired(data)) {
689 pr_debug("expired %u/%u\n", i, j);
690#ifdef IP_SET_HASH_WITH_NETS
691 del_cidr(h, data->cidr, HOST_MASK);
692#endif
693 if (j != n->pos - 1)
694 /* Not last one */
695 type_pf_data_copy(data,
696 ahash_tdata(n, n->pos - 1));
697 n->pos--;
698 h->elements--;
699 }
700 }
701 if (n->pos + AHASH_INIT_SIZE < n->size) {
702 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
703 * sizeof(struct type_pf_telem),
704 GFP_ATOMIC);
705 if (!tmp)
706 /* Still try to delete expired elements */
707 continue;
708 n->size -= AHASH_INIT_SIZE;
709 memcpy(tmp, n->value,
710 n->size * sizeof(struct type_pf_telem));
711 kfree(n->value);
712 n->value = tmp;
713 }
714 }
715}
716
717static int
718type_pf_tresize(struct ip_set *set, bool retried)
719{
720 struct ip_set_hash *h = set->data;
721 struct htable *t, *orig = h->table;
722 u8 htable_bits = orig->htable_bits;
723 const struct type_pf_elem *data;
724 struct hbucket *n, *m;
725 u32 i, j;
726 int ret;
727
728 /* Try to cleanup once */
729 if (!retried) {
730 i = h->elements;
731 write_lock_bh(&set->lock);
732 type_pf_expire(set->data);
733 write_unlock_bh(&set->lock);
734 if (h->elements < i)
735 return 0;
736 }
737
738retry:
739 ret = 0;
740 htable_bits++;
741 if (!htable_bits)
742 /* In case we have plenty of memory :-) */
743 return -IPSET_ERR_HASH_FULL;
744 t = ip_set_alloc(sizeof(*t)
745 + jhash_size(htable_bits) * sizeof(struct hbucket));
746 if (!t)
747 return -ENOMEM;
748 t->htable_bits = htable_bits;
749
750 read_lock_bh(&set->lock);
751 for (i = 0; i < jhash_size(orig->htable_bits); i++) {
752 n = hbucket(orig, i);
753 for (j = 0; j < n->pos; j++) {
754 data = ahash_tdata(n, j);
755 m = hbucket(t, HKEY(data, h->initval, htable_bits));
756 ret = type_pf_elem_tadd(m, data,
757 type_pf_data_timeout(data));
758 if (ret < 0) {
759 read_unlock_bh(&set->lock);
760 ahash_destroy(t);
761 if (ret == -EAGAIN)
762 goto retry;
763 return ret;
764 }
765 }
766 }
767
768 rcu_assign_pointer(h->table, t);
769 read_unlock_bh(&set->lock);
770
771 /* Give time to other readers of the set */
772 synchronize_rcu_bh();
773
774 ahash_destroy(orig);
775
776 return 0;
777}
778
779static int
780type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
781{
782 struct ip_set_hash *h = set->data;
783 struct htable *t = h->table;
784 const struct type_pf_elem *d = value;
785 struct hbucket *n;
786 struct type_pf_elem *data;
787 int ret = 0, i, j = AHASH_MAX_SIZE + 1;
788 u32 key;
789
790 if (h->elements >= h->maxelem)
791 /* FIXME: when set is full, we slow down here */
792 type_pf_expire(h);
793 if (h->elements >= h->maxelem)
794 return -IPSET_ERR_HASH_FULL;
795
796 rcu_read_lock_bh();
797 t = rcu_dereference_bh(h->table);
798 key = HKEY(d, h->initval, t->htable_bits);
799 n = hbucket(t, key);
800 for (i = 0; i < n->pos; i++) {
801 data = ahash_tdata(n, i);
802 if (type_pf_data_equal(data, d)) {
803 if (type_pf_data_expired(data))
804 j = i;
805 else {
806 ret = -IPSET_ERR_EXIST;
807 goto out;
808 }
809 } else if (j == AHASH_MAX_SIZE + 1 &&
810 type_pf_data_expired(data))
811 j = i;
812 }
813 if (j != AHASH_MAX_SIZE + 1) {
814 data = ahash_tdata(n, j);
815#ifdef IP_SET_HASH_WITH_NETS
816 del_cidr(h, data->cidr, HOST_MASK);
817 add_cidr(h, d->cidr, HOST_MASK);
818#endif
819 type_pf_data_copy(data, d);
820 type_pf_data_timeout_set(data, timeout);
821 goto out;
822 }
823 ret = type_pf_elem_tadd(n, d, timeout);
824 if (ret != 0)
825 goto out;
826
827#ifdef IP_SET_HASH_WITH_NETS
828 add_cidr(h, d->cidr, HOST_MASK);
829#endif
830 h->elements++;
831out:
832 rcu_read_unlock_bh();
833 return ret;
834}
835
836static int
837type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
838{
839 struct ip_set_hash *h = set->data;
840 struct htable *t = h->table;
841 const struct type_pf_elem *d = value;
842 struct hbucket *n;
843 int i, ret = 0;
844 struct type_pf_elem *data;
845 u32 key;
846
847 key = HKEY(value, h->initval, t->htable_bits);
848 n = hbucket(t, key);
849 for (i = 0; i < n->pos; i++) {
850 data = ahash_tdata(n, i);
851 if (!type_pf_data_equal(data, d))
852 continue;
853 if (type_pf_data_expired(data))
854 ret = -IPSET_ERR_EXIST;
855 if (i != n->pos - 1)
856 /* Not last one */
857 type_pf_data_copy(data, ahash_tdata(n, n->pos - 1));
858
859 n->pos--;
860 h->elements--;
861#ifdef IP_SET_HASH_WITH_NETS
862 del_cidr(h, d->cidr, HOST_MASK);
863#endif
864 if (n->pos + AHASH_INIT_SIZE < n->size) {
865 void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
866 * sizeof(struct type_pf_telem),
867 GFP_ATOMIC);
868 if (!tmp)
869 return 0;
870 n->size -= AHASH_INIT_SIZE;
871 memcpy(tmp, n->value,
872 n->size * sizeof(struct type_pf_telem));
873 kfree(n->value);
874 n->value = tmp;
875 }
876 return 0;
877 }
878
879 return -IPSET_ERR_EXIST;
880}
881
882#ifdef IP_SET_HASH_WITH_NETS
883static int
884type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
885{
886 struct ip_set_hash *h = set->data;
887 struct htable *t = h->table;
888 struct type_pf_elem *data;
889 struct hbucket *n;
890 int i, j = 0;
891 u32 key;
892 u8 host_mask = SET_HOST_MASK(set->family);
893
894 for (; j < host_mask && h->nets[j].cidr; j++) {
895 type_pf_data_netmask(d, h->nets[j].cidr);
896 key = HKEY(d, h->initval, t->htable_bits);
897 n = hbucket(t, key);
898 for (i = 0; i < n->pos; i++) {
899 data = ahash_tdata(n, i);
900 if (type_pf_data_equal(data, d))
901 return !type_pf_data_expired(data);
902 }
903 }
904 return 0;
905}
906#endif
907
908static int
909type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
910{
911 struct ip_set_hash *h = set->data;
912 struct htable *t = h->table;
913 struct type_pf_elem *data, *d = value;
914 struct hbucket *n;
915 int i;
916 u32 key;
917
918#ifdef IP_SET_HASH_WITH_NETS
919 if (d->cidr == SET_HOST_MASK(set->family))
920 return type_pf_ttest_cidrs(set, d, timeout);
921#endif
922 key = HKEY(d, h->initval, t->htable_bits);
923 n = hbucket(t, key);
924 for (i = 0; i < n->pos; i++) {
925 data = ahash_tdata(n, i);
926 if (type_pf_data_equal(data, d))
927 return !type_pf_data_expired(data);
928 }
929 return 0;
930}
931
932static int
933type_pf_tlist(const struct ip_set *set,
934 struct sk_buff *skb, struct netlink_callback *cb)
935{
936 const struct ip_set_hash *h = set->data;
937 const struct htable *t = h->table;
938 struct nlattr *atd, *nested;
939 const struct hbucket *n;
940 const struct type_pf_elem *data;
941 u32 first = cb->args[2];
942 /* We assume that one hash bucket fills into one page */
943 void *incomplete;
944 int i;
945
946 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
947 if (!atd)
948 return -EMSGSIZE;
949 for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
950 incomplete = skb_tail_pointer(skb);
951 n = hbucket(t, cb->args[2]);
952 for (i = 0; i < n->pos; i++) {
953 data = ahash_tdata(n, i);
954 pr_debug("list %p %u\n", n, i);
955 if (type_pf_data_expired(data))
956 continue;
957 pr_debug("do list %p %u\n", n, i);
958 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
959 if (!nested) {
960 if (cb->args[2] == first) {
961 nla_nest_cancel(skb, atd);
962 return -EMSGSIZE;
963 } else
964 goto nla_put_failure;
965 }
966 if (type_pf_data_tlist(skb, data))
967 goto nla_put_failure;
968 ipset_nest_end(skb, nested);
969 }
970 }
971 ipset_nest_end(skb, atd);
972 /* Set listing finished */
973 cb->args[2] = 0;
974
975 return 0;
976
977nla_put_failure:
978 nlmsg_trim(skb, incomplete);
979 ipset_nest_end(skb, atd);
980 if (unlikely(first == cb->args[2])) {
981 pr_warning("Can't list set %s: one bucket does not fit into "
982 "a message. Please report it!\n", set->name);
983 cb->args[2] = 0;
984 return -EMSGSIZE;
985 }
986 return 0;
987}
988
989static const struct ip_set_type_variant type_pf_tvariant = {
990 .kadt = type_pf_kadt,
991 .uadt = type_pf_uadt,
992 .adt = {
993 [IPSET_ADD] = type_pf_tadd,
994 [IPSET_DEL] = type_pf_tdel,
995 [IPSET_TEST] = type_pf_ttest,
996 },
997 .destroy = type_pf_destroy,
998 .flush = type_pf_flush,
999 .head = type_pf_head,
1000 .list = type_pf_tlist,
1001 .resize = type_pf_tresize,
1002 .same_set = type_pf_same_set,
1003};
1004
1005static void
1006type_pf_gc(unsigned long ul_set)
1007{
1008 struct ip_set *set = (struct ip_set *) ul_set;
1009 struct ip_set_hash *h = set->data;
1010
1011 pr_debug("called\n");
1012 write_lock_bh(&set->lock);
1013 type_pf_expire(h);
1014 write_unlock_bh(&set->lock);
1015
1016 h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
1017 add_timer(&h->gc);
1018}
1019
1020static void
1021type_pf_gc_init(struct ip_set *set)
1022{
1023 struct ip_set_hash *h = set->data;
1024
1025 init_timer(&h->gc);
1026 h->gc.data = (unsigned long) set;
1027 h->gc.function = type_pf_gc;
1028 h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
1029 add_timer(&h->gc);
1030 pr_debug("gc initialized, run in every %u\n",
1031 IPSET_GC_PERIOD(h->timeout));
1032}
1033
1034#undef type_pf_data_equal
1035#undef type_pf_data_isnull
1036#undef type_pf_data_copy
1037#undef type_pf_data_zero_out
1038#undef type_pf_data_list
1039#undef type_pf_data_tlist
1040
1041#undef type_pf_elem
1042#undef type_pf_telem
1043#undef type_pf_data_timeout
1044#undef type_pf_data_expired
1045#undef type_pf_data_netmask
1046#undef type_pf_data_timeout_set
1047
1048#undef type_pf_elem_add
1049#undef type_pf_add
1050#undef type_pf_del
1051#undef type_pf_test_cidrs
1052#undef type_pf_test
1053
1054#undef type_pf_elem_tadd
1055#undef type_pf_expire
1056#undef type_pf_tadd
1057#undef type_pf_tdel
1058#undef type_pf_ttest_cidrs
1059#undef type_pf_ttest
1060
1061#undef type_pf_resize
1062#undef type_pf_tresize
1063#undef type_pf_flush
1064#undef type_pf_destroy
1065#undef type_pf_head
1066#undef type_pf_list
1067#undef type_pf_tlist
1068#undef type_pf_same_set
1069#undef type_pf_kadt
1070#undef type_pf_uadt
1071#undef type_pf_gc
1072#undef type_pf_gc_init
1073#undef type_pf_variant
1074#undef type_pf_tvariant
diff --git a/include/linux/netfilter/ipset/ip_set_bitmap.h b/include/linux/netfilter/ipset/ip_set_bitmap.h
new file mode 100644
index 000000000000..61a9e8746c83
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_bitmap.h
@@ -0,0 +1,31 @@
1#ifndef __IP_SET_BITMAP_H
2#define __IP_SET_BITMAP_H
3
4/* Bitmap type specific error codes */
5enum {
6 /* The element is out of the range of the set */
7 IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
8 /* The range exceeds the size limit of the set type */
9 IPSET_ERR_BITMAP_RANGE_SIZE,
10};
11
12#ifdef __KERNEL__
13#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
14
15/* Common functions */
16
17static inline u32
18range_to_mask(u32 from, u32 to, u8 *bits)
19{
20 u32 mask = 0xFFFFFFFE;
21
22 *bits = 32;
23 while (--(*bits) > 0 && mask && (to & mask) != from)
24 mask <<= 1;
25
26 return mask;
27}
28
29#endif /* __KERNEL__ */
30
31#endif /* __IP_SET_BITMAP_H */
diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h
new file mode 100644
index 000000000000..3882a81a3b3c
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_getport.h
@@ -0,0 +1,21 @@
1#ifndef _IP_SET_GETPORT_H
2#define _IP_SET_GETPORT_H
3
4extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
5 __be16 *port, u8 *proto);
6
7#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
8extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
9 __be16 *port, u8 *proto);
10#else
11static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
12 __be16 *port, u8 *proto)
13{
14 return false;
15}
16#endif
17
18extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
19 __be16 *port);
20
21#endif /*_IP_SET_GETPORT_H*/
diff --git a/include/linux/netfilter/ipset/ip_set_hash.h b/include/linux/netfilter/ipset/ip_set_hash.h
new file mode 100644
index 000000000000..b86f15c04524
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_hash.h
@@ -0,0 +1,26 @@
1#ifndef __IP_SET_HASH_H
2#define __IP_SET_HASH_H
3
4/* Hash type specific error codes */
5enum {
6 /* Hash is full */
7 IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
8 /* Null-valued element */
9 IPSET_ERR_HASH_ELEM,
10 /* Invalid protocol */
11 IPSET_ERR_INVALID_PROTO,
12 /* Protocol missing but must be specified */
13 IPSET_ERR_MISSING_PROTO,
14};
15
16#ifdef __KERNEL__
17
18#define IPSET_DEFAULT_HASHSIZE 1024
19#define IPSET_MIMINAL_HASHSIZE 64
20#define IPSET_DEFAULT_MAXELEM 65536
21#define IPSET_DEFAULT_PROBES 4
22#define IPSET_DEFAULT_RESIZE 100
23
24#endif /* __KERNEL__ */
25
26#endif /* __IP_SET_HASH_H */
diff --git a/include/linux/netfilter/ipset/ip_set_list.h b/include/linux/netfilter/ipset/ip_set_list.h
new file mode 100644
index 000000000000..40a63f302613
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_list.h
@@ -0,0 +1,27 @@
1#ifndef __IP_SET_LIST_H
2#define __IP_SET_LIST_H
3
4/* List type specific error codes */
5enum {
6 /* Set name to be added/deleted/tested does not exist. */
7 IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
8 /* list:set type is not permitted to add */
9 IPSET_ERR_LOOP,
10 /* Missing reference set */
11 IPSET_ERR_BEFORE,
12 /* Reference set does not exist */
13 IPSET_ERR_NAMEREF,
14 /* Set is full */
15 IPSET_ERR_LIST_FULL,
16 /* Reference set is not added to the set */
17 IPSET_ERR_REF_EXIST,
18};
19
20#ifdef __KERNEL__
21
22#define IP_SET_LIST_DEFAULT_SIZE 8
23#define IP_SET_LIST_MIN_SIZE 4
24
25#endif /* __KERNEL__ */
26
27#endif /* __IP_SET_LIST_H */
diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
new file mode 100644
index 000000000000..9f30c5f2ec1c
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -0,0 +1,127 @@
1#ifndef _IP_SET_TIMEOUT_H
2#define _IP_SET_TIMEOUT_H
3
4/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifdef __KERNEL__
12
13/* How often should the gc be run by default */
14#define IPSET_GC_TIME (3 * 60)
15
16/* Timeout period depending on the timeout value of the given set */
17#define IPSET_GC_PERIOD(timeout) \
18 ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)
19
20/* Set is defined without timeout support: timeout value may be 0 */
21#define IPSET_NO_TIMEOUT UINT_MAX
22
23#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)
24
25static inline unsigned int
26ip_set_timeout_uget(struct nlattr *tb)
27{
28 unsigned int timeout = ip_set_get_h32(tb);
29
30 /* Userspace supplied TIMEOUT parameter: adjust crazy size */
31 return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
32}
33
34#ifdef IP_SET_BITMAP_TIMEOUT
35
36/* Bitmap specific timeout constants and macros for the entries */
37
38/* Bitmap entry is unset */
39#define IPSET_ELEM_UNSET 0
40/* Bitmap entry is set with no timeout value */
41#define IPSET_ELEM_PERMANENT (UINT_MAX/2)
42
43static inline bool
44ip_set_timeout_test(unsigned long timeout)
45{
46 return timeout != IPSET_ELEM_UNSET &&
47 (timeout == IPSET_ELEM_PERMANENT ||
48 time_after(timeout, jiffies));
49}
50
51static inline bool
52ip_set_timeout_expired(unsigned long timeout)
53{
54 return timeout != IPSET_ELEM_UNSET &&
55 timeout != IPSET_ELEM_PERMANENT &&
56 time_before(timeout, jiffies);
57}
58
59static inline unsigned long
60ip_set_timeout_set(u32 timeout)
61{
62 unsigned long t;
63
64 if (!timeout)
65 return IPSET_ELEM_PERMANENT;
66
67 t = timeout * HZ + jiffies;
68 if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
69 /* Bingo! */
70 t++;
71
72 return t;
73}
74
75static inline u32
76ip_set_timeout_get(unsigned long timeout)
77{
78 return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
79}
80
81#else
82
83/* Hash specific timeout constants and macros for the entries */
84
85/* Hash entry is set with no timeout value */
86#define IPSET_ELEM_PERMANENT 0
87
88static inline bool
89ip_set_timeout_test(unsigned long timeout)
90{
91 return timeout == IPSET_ELEM_PERMANENT ||
92 time_after(timeout, jiffies);
93}
94
95static inline bool
96ip_set_timeout_expired(unsigned long timeout)
97{
98 return timeout != IPSET_ELEM_PERMANENT &&
99 time_before(timeout, jiffies);
100}
101
102static inline unsigned long
103ip_set_timeout_set(u32 timeout)
104{
105 unsigned long t;
106
107 if (!timeout)
108 return IPSET_ELEM_PERMANENT;
109
110 t = timeout * HZ + jiffies;
111 if (t == IPSET_ELEM_PERMANENT)
112 /* Bingo! :-) */
113 t++;
114
115 return t;
116}
117
118static inline u32
119ip_set_timeout_get(unsigned long timeout)
120{
121 return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
122}
123#endif /* ! IP_SET_BITMAP_TIMEOUT */
124
125#endif /* __KERNEL__ */
126
127#endif /* _IP_SET_TIMEOUT_H */
diff --git a/include/linux/netfilter/ipset/pfxlen.h b/include/linux/netfilter/ipset/pfxlen.h
new file mode 100644
index 000000000000..0e1fb50da562
--- /dev/null
+++ b/include/linux/netfilter/ipset/pfxlen.h
@@ -0,0 +1,35 @@
1#ifndef _PFXLEN_H
2#define _PFXLEN_H
3
4#include <asm/byteorder.h>
5#include <linux/netfilter.h>
6
7/* Prefixlen maps, by Jan Engelhardt */
8extern const union nf_inet_addr ip_set_netmask_map[];
9extern const union nf_inet_addr ip_set_hostmask_map[];
10
11static inline __be32
12ip_set_netmask(u8 pfxlen)
13{
14 return ip_set_netmask_map[pfxlen].ip;
15}
16
17static inline const __be32 *
18ip_set_netmask6(u8 pfxlen)
19{
20 return &ip_set_netmask_map[pfxlen].ip6[0];
21}
22
23static inline u32
24ip_set_hostmask(u8 pfxlen)
25{
26 return (__force u32) ip_set_hostmask_map[pfxlen].ip;
27}
28
29static inline const __be32 *
30ip_set_hostmask6(u8 pfxlen)
31{
32 return &ip_set_hostmask_map[pfxlen].ip6[0];
33}
34
35#endif /*_PFXLEN_H */
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 361d6b5630ee..2b11fc1a86be 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -47,7 +47,8 @@ struct nfgenmsg {
47#define NFNL_SUBSYS_QUEUE 3 47#define NFNL_SUBSYS_QUEUE 3
48#define NFNL_SUBSYS_ULOG 4 48#define NFNL_SUBSYS_ULOG 4
49#define NFNL_SUBSYS_OSF 5 49#define NFNL_SUBSYS_OSF 5
50#define NFNL_SUBSYS_COUNT 6 50#define NFNL_SUBSYS_IPSET 6
51#define NFNL_SUBSYS_COUNT 7
51 52
52#ifdef __KERNEL__ 53#ifdef __KERNEL__
53 54
diff --git a/include/linux/netfilter/xt_devgroup.h b/include/linux/netfilter/xt_devgroup.h
new file mode 100644
index 000000000000..1babde0ec900
--- /dev/null
+++ b/include/linux/netfilter/xt_devgroup.h
@@ -0,0 +1,21 @@
1#ifndef _XT_DEVGROUP_H
2#define _XT_DEVGROUP_H
3
4#include <linux/types.h>
5
6enum xt_devgroup_flags {
7 XT_DEVGROUP_MATCH_SRC = 0x1,
8 XT_DEVGROUP_INVERT_SRC = 0x2,
9 XT_DEVGROUP_MATCH_DST = 0x4,
10 XT_DEVGROUP_INVERT_DST = 0x8,
11};
12
13struct xt_devgroup_info {
14 __u32 flags;
15 __u32 src_group;
16 __u32 src_mask;
17 __u32 dst_group;
18 __u32 dst_mask;
19};
20
21#endif /* _XT_DEVGROUP_H */
diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h
new file mode 100644
index 000000000000..081f1ded2842
--- /dev/null
+++ b/include/linux/netfilter/xt_set.h
@@ -0,0 +1,56 @@
1#ifndef _XT_SET_H
2#define _XT_SET_H
3
4#include <linux/types.h>
5#include <linux/netfilter/ipset/ip_set.h>
6
7/* Revision 0 interface: backward compatible with netfilter/iptables */
8
9/*
10 * Option flags for kernel operations (xt_set_info_v0)
11 */
12#define IPSET_SRC 0x01 /* Source match/add */
13#define IPSET_DST 0x02 /* Destination match/add */
14#define IPSET_MATCH_INV 0x04 /* Inverse matching */
15
16struct xt_set_info_v0 {
17 ip_set_id_t index;
18 union {
19 __u32 flags[IPSET_DIM_MAX + 1];
20 struct {
21 __u32 __flags[IPSET_DIM_MAX];
22 __u8 dim;
23 __u8 flags;
24 } compat;
25 } u;
26};
27
28/* match and target infos */
29struct xt_set_info_match_v0 {
30 struct xt_set_info_v0 match_set;
31};
32
33struct xt_set_info_target_v0 {
34 struct xt_set_info_v0 add_set;
35 struct xt_set_info_v0 del_set;
36};
37
38/* Revision 1: current interface to netfilter/iptables */
39
40struct xt_set_info {
41 ip_set_id_t index;
42 __u8 dim;
43 __u8 flags;
44};
45
46/* match and target infos */
47struct xt_set_info_match {
48 struct xt_set_info match_set;
49};
50
51struct xt_set_info_target {
52 struct xt_set_info add_set;
53 struct xt_set_info del_set;
54};
55
56#endif /*_XT_SET_H*/