aboutsummaryrefslogtreecommitdiffstats
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
parent123b9731b14f49cd41c91ed2b6c31e515615347c (diff)
parent9291747f118d6404e509747b85ff5f6dfec368d2 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
-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
-rw-r--r--include/net/ip_vs.h2
-rw-r--r--include/net/netlink.h9
-rw-r--r--net/netfilter/Kconfig23
-rw-r--r--net/netfilter/Makefile5
-rw-r--r--net/netfilter/ipset/Kconfig121
-rw-r--r--net/netfilter/ipset/Makefile24
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c587
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c652
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c515
-rw-r--r--net/netfilter/ipset/ip_set_core.c1671
-rw-r--r--net/netfilter/ipset/ip_set_getport.c141
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c464
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c544
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c562
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c628
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c458
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c578
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c584
-rw-r--r--net/netfilter/ipset/pfxlen.c291
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c17
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c20
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c20
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c2
-rw-r--r--net/netfilter/nf_conntrack_netlink.c2
-rw-r--r--net/netfilter/xt_devgroup.c82
-rw-r--r--net/netfilter/xt_set.c359
40 files changed, 10210 insertions, 34 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*/
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index b23bea62f708..5d75feadf4f4 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -1109,8 +1109,6 @@ extern int ip_vs_icmp_xmit_v6
1109 * we are loaded. Just set ip_vs_drop_rate to 'n' and 1109 * we are loaded. Just set ip_vs_drop_rate to 'n' and
1110 * we start to drop 1/rate of the packets 1110 * we start to drop 1/rate of the packets
1111 */ 1111 */
1112extern int ip_vs_drop_rate;
1113extern int ip_vs_drop_counter;
1114 1112
1115static inline int ip_vs_todrop(struct netns_ipvs *ipvs) 1113static inline int ip_vs_todrop(struct netns_ipvs *ipvs)
1116{ 1114{
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 373f1a900cf4..8a3906a08f5f 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -856,18 +856,27 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
856#define NLA_PUT_BE16(skb, attrtype, value) \ 856#define NLA_PUT_BE16(skb, attrtype, value) \
857 NLA_PUT_TYPE(skb, __be16, attrtype, value) 857 NLA_PUT_TYPE(skb, __be16, attrtype, value)
858 858
859#define NLA_PUT_NET16(skb, attrtype, value) \
860 NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
861
859#define NLA_PUT_U32(skb, attrtype, value) \ 862#define NLA_PUT_U32(skb, attrtype, value) \
860 NLA_PUT_TYPE(skb, u32, attrtype, value) 863 NLA_PUT_TYPE(skb, u32, attrtype, value)
861 864
862#define NLA_PUT_BE32(skb, attrtype, value) \ 865#define NLA_PUT_BE32(skb, attrtype, value) \
863 NLA_PUT_TYPE(skb, __be32, attrtype, value) 866 NLA_PUT_TYPE(skb, __be32, attrtype, value)
864 867
868#define NLA_PUT_NET32(skb, attrtype, value) \
869 NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
870
865#define NLA_PUT_U64(skb, attrtype, value) \ 871#define NLA_PUT_U64(skb, attrtype, value) \
866 NLA_PUT_TYPE(skb, u64, attrtype, value) 872 NLA_PUT_TYPE(skb, u64, attrtype, value)
867 873
868#define NLA_PUT_BE64(skb, attrtype, value) \ 874#define NLA_PUT_BE64(skb, attrtype, value) \
869 NLA_PUT_TYPE(skb, __be64, attrtype, value) 875 NLA_PUT_TYPE(skb, __be64, attrtype, value)
870 876
877#define NLA_PUT_NET64(skb, attrtype, value) \
878 NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
879
871#define NLA_PUT_STRING(skb, attrtype, value) \ 880#define NLA_PUT_STRING(skb, attrtype, value) \
872 NLA_PUT(skb, attrtype, strlen(value) + 1, value) 881 NLA_PUT(skb, attrtype, strlen(value) + 1, value)
873 882
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index faf7412ea453..82a6e0d80f05 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -352,6 +352,18 @@ config NETFILTER_XT_CONNMARK
352 ctmark), similarly to the packet mark (nfmark). Using this 352 ctmark), similarly to the packet mark (nfmark). Using this
353 target and match, you can set and match on this mark. 353 target and match, you can set and match on this mark.
354 354
355config NETFILTER_XT_SET
356 tristate 'set target and match support'
357 depends on IP_SET
358 depends on NETFILTER_ADVANCED
359 help
360 This option adds the "SET" target and "set" match.
361
362 Using this target and match, you can add/delete and match
363 elements in the sets created by ipset(8).
364
365 To compile it as a module, choose M here. If unsure, say N.
366
355# alphabetically ordered list of targets 367# alphabetically ordered list of targets
356 368
357comment "Xtables targets" 369comment "Xtables targets"
@@ -726,6 +738,15 @@ config NETFILTER_XT_MATCH_DCCP
726 If you want to compile it as a module, say M here and read 738 If you want to compile it as a module, say M here and read
727 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. 739 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
728 740
741config NETFILTER_XT_MATCH_DEVGROUP
742 tristate '"devgroup" match support'
743 depends on NETFILTER_ADVANCED
744 help
745 This options adds a `devgroup' match, which allows to match on the
746 device group a network device is assigned to.
747
748 To compile it as a module, choose M here. If unsure, say N.
749
729config NETFILTER_XT_MATCH_DSCP 750config NETFILTER_XT_MATCH_DSCP
730 tristate '"dscp" and "tos" match support' 751 tristate '"dscp" and "tos" match support'
731 depends on NETFILTER_ADVANCED 752 depends on NETFILTER_ADVANCED
@@ -1052,4 +1073,6 @@ endif # NETFILTER_XTABLES
1052 1073
1053endmenu 1074endmenu
1054 1075
1076source "net/netfilter/ipset/Kconfig"
1077
1055source "net/netfilter/ipvs/Kconfig" 1078source "net/netfilter/ipvs/Kconfig"
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 9ae6878a85b1..d57a890eaee5 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
46# combos 46# combos
47obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o 47obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o
48obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o 48obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o
49obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o
49 50
50# targets 51# targets
51obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o 52obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o
@@ -76,6 +77,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
76obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o 77obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
77obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o 78obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o
78obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o 79obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
80obj-$(CONFIG_NETFILTER_XT_MATCH_DEVGROUP) += xt_devgroup.o
79obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o 81obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
80obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o 82obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
81obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o 83obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
@@ -105,5 +107,8 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
105obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o 107obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
106obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o 108obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
107 109
110# ipset
111obj-$(CONFIG_IP_SET) += ipset/
112
108# IPVS 113# IPVS
109obj-$(CONFIG_IP_VS) += ipvs/ 114obj-$(CONFIG_IP_VS) += ipvs/
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig
new file mode 100644
index 000000000000..3b970d343023
--- /dev/null
+++ b/net/netfilter/ipset/Kconfig
@@ -0,0 +1,121 @@
1menuconfig IP_SET
2 tristate "IP set support"
3 depends on INET && NETFILTER
4 help
5 This option adds IP set support to the kernel.
6 In order to define and use the sets, you need the userspace utility
7 ipset(8). You can use the sets in netfilter via the "set" match
8 and "SET" target.
9
10 To compile it as a module, choose M here. If unsure, say N.
11
12if IP_SET
13
14config IP_SET_MAX
15 int "Maximum number of IP sets"
16 default 256
17 range 2 65534
18 depends on IP_SET
19 help
20 You can define here default value of the maximum number
21 of IP sets for the kernel.
22
23 The value can be overriden by the 'max_sets' module
24 parameter of the 'ip_set' module.
25
26config IP_SET_BITMAP_IP
27 tristate "bitmap:ip set support"
28 depends on IP_SET
29 help
30 This option adds the bitmap:ip set type support, by which one
31 can store IPv4 addresses (or network addresse) from a range.
32
33 To compile it as a module, choose M here. If unsure, say N.
34
35config IP_SET_BITMAP_IPMAC
36 tristate "bitmap:ip,mac set support"
37 depends on IP_SET
38 help
39 This option adds the bitmap:ip,mac set type support, by which one
40 can store IPv4 address and (source) MAC address pairs from a range.
41
42 To compile it as a module, choose M here. If unsure, say N.
43
44config IP_SET_BITMAP_PORT
45 tristate "bitmap:port set support"
46 depends on IP_SET
47 help
48 This option adds the bitmap:port set type support, by which one
49 can store TCP/UDP port numbers from a range.
50
51 To compile it as a module, choose M here. If unsure, say N.
52
53config IP_SET_HASH_IP
54 tristate "hash:ip set support"
55 depends on IP_SET
56 help
57 This option adds the hash:ip set type support, by which one
58 can store arbitrary IPv4 or IPv6 addresses (or network addresses)
59 in a set.
60
61 To compile it as a module, choose M here. If unsure, say N.
62
63config IP_SET_HASH_IPPORT
64 tristate "hash:ip,port set support"
65 depends on IP_SET
66 help
67 This option adds the hash:ip,port set type support, by which one
68 can store IPv4/IPv6 address and protocol/port pairs.
69
70 To compile it as a module, choose M here. If unsure, say N.
71
72config IP_SET_HASH_IPPORTIP
73 tristate "hash:ip,port,ip set support"
74 depends on IP_SET
75 help
76 This option adds the hash:ip,port,ip set type support, by which
77 one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv6
78 address triples in a set.
79
80 To compile it as a module, choose M here. If unsure, say N.
81
82config IP_SET_HASH_IPPORTNET
83 tristate "hash:ip,port,net set support"
84 depends on IP_SET
85 help
86 This option adds the hash:ip,port,net set type support, by which
87 one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv6
88 network address/prefix triples in a set.
89
90 To compile it as a module, choose M here. If unsure, say N.
91
92config IP_SET_HASH_NET
93 tristate "hash:net set support"
94 depends on IP_SET
95 help
96 This option adds the hash:net set type support, by which
97 one can store IPv4/IPv6 network address/prefix elements in a set.
98
99 To compile it as a module, choose M here. If unsure, say N.
100
101config IP_SET_HASH_NETPORT
102 tristate "hash:net,port set support"
103 depends on IP_SET
104 help
105 This option adds the hash:net,port set type support, by which
106 one can store IPv4/IPv6 network address/prefix and
107 protocol/port pairs as elements in a set.
108
109 To compile it as a module, choose M here. If unsure, say N.
110
111config IP_SET_LIST_SET
112 tristate "list:set set support"
113 depends on IP_SET
114 help
115 This option adds the list:set set type support. In this
116 kind of set one can store the name of other sets and it forms
117 an ordered union of the member sets.
118
119 To compile it as a module, choose M here. If unsure, say N.
120
121endif # IP_SET
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile
new file mode 100644
index 000000000000..5adbdab67bd2
--- /dev/null
+++ b/net/netfilter/ipset/Makefile
@@ -0,0 +1,24 @@
1#
2# Makefile for the ipset modules
3#
4
5ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o
6
7# ipset core
8obj-$(CONFIG_IP_SET) += ip_set.o
9
10# bitmap types
11obj-$(CONFIG_IP_SET_BITMAP_IP) += ip_set_bitmap_ip.o
12obj-$(CONFIG_IP_SET_BITMAP_IPMAC) += ip_set_bitmap_ipmac.o
13obj-$(CONFIG_IP_SET_BITMAP_PORT) += ip_set_bitmap_port.o
14
15# hash types
16obj-$(CONFIG_IP_SET_HASH_IP) += ip_set_hash_ip.o
17obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o
18obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o
19obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
20obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
21obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
22
23# list types
24obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
new file mode 100644
index 000000000000..bca96990218d
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -0,0 +1,587 @@
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10/* Kernel module implementing an IP set type: the bitmap:ip type */
11
12#include <linux/module.h>
13#include <linux/ip.h>
14#include <linux/skbuff.h>
15#include <linux/errno.h>
16#include <linux/bitops.h>
17#include <linux/spinlock.h>
18#include <linux/netlink.h>
19#include <linux/jiffies.h>
20#include <linux/timer.h>
21#include <net/netlink.h>
22#include <net/tcp.h>
23
24#include <linux/netfilter/ipset/pfxlen.h>
25#include <linux/netfilter/ipset/ip_set.h>
26#include <linux/netfilter/ipset/ip_set_bitmap.h>
27#define IP_SET_BITMAP_TIMEOUT
28#include <linux/netfilter/ipset/ip_set_timeout.h>
29
30MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
32MODULE_DESCRIPTION("bitmap:ip type of IP sets");
33MODULE_ALIAS("ip_set_bitmap:ip");
34
35/* Type structure */
36struct bitmap_ip {
37 void *members; /* the set members */
38 u32 first_ip; /* host byte order, included in range */
39 u32 last_ip; /* host byte order, included in range */
40 u32 elements; /* number of max elements in the set */
41 u32 hosts; /* number of hosts in a subnet */
42 size_t memsize; /* members size */
43 u8 netmask; /* subnet netmask */
44 u32 timeout; /* timeout parameter */
45 struct timer_list gc; /* garbage collection */
46};
47
48/* Base variant */
49
50static inline u32
51ip_to_id(const struct bitmap_ip *m, u32 ip)
52{
53 return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
54}
55
56static int
57bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
58{
59 const struct bitmap_ip *map = set->data;
60 u16 id = *(u16 *)value;
61
62 return !!test_bit(id, map->members);
63}
64
65static int
66bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
67{
68 struct bitmap_ip *map = set->data;
69 u16 id = *(u16 *)value;
70
71 if (test_and_set_bit(id, map->members))
72 return -IPSET_ERR_EXIST;
73
74 return 0;
75}
76
77static int
78bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
79{
80 struct bitmap_ip *map = set->data;
81 u16 id = *(u16 *)value;
82
83 if (!test_and_clear_bit(id, map->members))
84 return -IPSET_ERR_EXIST;
85
86 return 0;
87}
88
89static int
90bitmap_ip_list(const struct ip_set *set,
91 struct sk_buff *skb, struct netlink_callback *cb)
92{
93 const struct bitmap_ip *map = set->data;
94 struct nlattr *atd, *nested;
95 u32 id, first = cb->args[2];
96
97 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
98 if (!atd)
99 return -EMSGSIZE;
100 for (; cb->args[2] < map->elements; cb->args[2]++) {
101 id = cb->args[2];
102 if (!test_bit(id, map->members))
103 continue;
104 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
105 if (!nested) {
106 if (id == first) {
107 nla_nest_cancel(skb, atd);
108 return -EMSGSIZE;
109 } else
110 goto nla_put_failure;
111 }
112 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
113 htonl(map->first_ip + id * map->hosts));
114 ipset_nest_end(skb, nested);
115 }
116 ipset_nest_end(skb, atd);
117 /* Set listing finished */
118 cb->args[2] = 0;
119 return 0;
120
121nla_put_failure:
122 nla_nest_cancel(skb, nested);
123 ipset_nest_end(skb, atd);
124 if (unlikely(id == first)) {
125 cb->args[2] = 0;
126 return -EMSGSIZE;
127 }
128 return 0;
129}
130
131/* Timeout variant */
132
133static int
134bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
135{
136 const struct bitmap_ip *map = set->data;
137 const unsigned long *members = map->members;
138 u16 id = *(u16 *)value;
139
140 return ip_set_timeout_test(members[id]);
141}
142
143static int
144bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
145{
146 struct bitmap_ip *map = set->data;
147 unsigned long *members = map->members;
148 u16 id = *(u16 *)value;
149
150 if (ip_set_timeout_test(members[id]))
151 return -IPSET_ERR_EXIST;
152
153 members[id] = ip_set_timeout_set(timeout);
154
155 return 0;
156}
157
158static int
159bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
160{
161 struct bitmap_ip *map = set->data;
162 unsigned long *members = map->members;
163 u16 id = *(u16 *)value;
164 int ret = -IPSET_ERR_EXIST;
165
166 if (ip_set_timeout_test(members[id]))
167 ret = 0;
168
169 members[id] = IPSET_ELEM_UNSET;
170 return ret;
171}
172
173static int
174bitmap_ip_tlist(const struct ip_set *set,
175 struct sk_buff *skb, struct netlink_callback *cb)
176{
177 const struct bitmap_ip *map = set->data;
178 struct nlattr *adt, *nested;
179 u32 id, first = cb->args[2];
180 const unsigned long *members = map->members;
181
182 adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
183 if (!adt)
184 return -EMSGSIZE;
185 for (; cb->args[2] < map->elements; cb->args[2]++) {
186 id = cb->args[2];
187 if (!ip_set_timeout_test(members[id]))
188 continue;
189 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
190 if (!nested) {
191 if (id == first) {
192 nla_nest_cancel(skb, adt);
193 return -EMSGSIZE;
194 } else
195 goto nla_put_failure;
196 }
197 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
198 htonl(map->first_ip + id * map->hosts));
199 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
200 htonl(ip_set_timeout_get(members[id])));
201 ipset_nest_end(skb, nested);
202 }
203 ipset_nest_end(skb, adt);
204
205 /* Set listing finished */
206 cb->args[2] = 0;
207
208 return 0;
209
210nla_put_failure:
211 nla_nest_cancel(skb, nested);
212 ipset_nest_end(skb, adt);
213 if (unlikely(id == first)) {
214 cb->args[2] = 0;
215 return -EMSGSIZE;
216 }
217 return 0;
218}
219
220static int
221bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
222 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
223{
224 struct bitmap_ip *map = set->data;
225 ipset_adtfn adtfn = set->variant->adt[adt];
226 u32 ip;
227
228 ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
229 if (ip < map->first_ip || ip > map->last_ip)
230 return -IPSET_ERR_BITMAP_RANGE;
231
232 ip = ip_to_id(map, ip);
233
234 return adtfn(set, &ip, map->timeout);
235}
236
237static int
238bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
239 enum ipset_adt adt, u32 *lineno, u32 flags)
240{
241 struct bitmap_ip *map = set->data;
242 ipset_adtfn adtfn = set->variant->adt[adt];
243 u32 timeout = map->timeout;
244 u32 ip, ip_to, id;
245 int ret = 0;
246
247 if (unlikely(!tb[IPSET_ATTR_IP] ||
248 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
249 return -IPSET_ERR_PROTOCOL;
250
251 if (tb[IPSET_ATTR_LINENO])
252 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
253
254 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
255 if (ret)
256 return ret;
257
258 if (ip < map->first_ip || ip > map->last_ip)
259 return -IPSET_ERR_BITMAP_RANGE;
260
261 if (tb[IPSET_ATTR_TIMEOUT]) {
262 if (!with_timeout(map->timeout))
263 return -IPSET_ERR_TIMEOUT;
264 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
265 }
266
267 if (adt == IPSET_TEST) {
268 id = ip_to_id(map, ip);
269 return adtfn(set, &id, timeout);
270 }
271
272 if (tb[IPSET_ATTR_IP_TO]) {
273 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
274 if (ret)
275 return ret;
276 if (ip > ip_to) {
277 swap(ip, ip_to);
278 if (ip < map->first_ip)
279 return -IPSET_ERR_BITMAP_RANGE;
280 }
281 } else if (tb[IPSET_ATTR_CIDR]) {
282 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
283
284 if (cidr > 32)
285 return -IPSET_ERR_INVALID_CIDR;
286 ip &= ip_set_hostmask(cidr);
287 ip_to = ip | ~ip_set_hostmask(cidr);
288 } else
289 ip_to = ip;
290
291 if (ip_to > map->last_ip)
292 return -IPSET_ERR_BITMAP_RANGE;
293
294 for (; !before(ip_to, ip); ip += map->hosts) {
295 id = ip_to_id(map, ip);
296 ret = adtfn(set, &id, timeout);;
297
298 if (ret && !ip_set_eexist(ret, flags))
299 return ret;
300 else
301 ret = 0;
302 }
303 return ret;
304}
305
306static void
307bitmap_ip_destroy(struct ip_set *set)
308{
309 struct bitmap_ip *map = set->data;
310
311 if (with_timeout(map->timeout))
312 del_timer_sync(&map->gc);
313
314 ip_set_free(map->members);
315 kfree(map);
316
317 set->data = NULL;
318}
319
320static void
321bitmap_ip_flush(struct ip_set *set)
322{
323 struct bitmap_ip *map = set->data;
324
325 memset(map->members, 0, map->memsize);
326}
327
328static int
329bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
330{
331 const struct bitmap_ip *map = set->data;
332 struct nlattr *nested;
333
334 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
335 if (!nested)
336 goto nla_put_failure;
337 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
338 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
339 if (map->netmask != 32)
340 NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
341 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
342 htonl(atomic_read(&set->ref) - 1));
343 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
344 htonl(sizeof(*map) + map->memsize));
345 if (with_timeout(map->timeout))
346 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
347 ipset_nest_end(skb, nested);
348
349 return 0;
350nla_put_failure:
351 return -EMSGSIZE;
352}
353
354static bool
355bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
356{
357 const struct bitmap_ip *x = a->data;
358 const struct bitmap_ip *y = b->data;
359
360 return x->first_ip == y->first_ip &&
361 x->last_ip == y->last_ip &&
362 x->netmask == y->netmask &&
363 x->timeout == y->timeout;
364}
365
366static const struct ip_set_type_variant bitmap_ip = {
367 .kadt = bitmap_ip_kadt,
368 .uadt = bitmap_ip_uadt,
369 .adt = {
370 [IPSET_ADD] = bitmap_ip_add,
371 [IPSET_DEL] = bitmap_ip_del,
372 [IPSET_TEST] = bitmap_ip_test,
373 },
374 .destroy = bitmap_ip_destroy,
375 .flush = bitmap_ip_flush,
376 .head = bitmap_ip_head,
377 .list = bitmap_ip_list,
378 .same_set = bitmap_ip_same_set,
379};
380
381static const struct ip_set_type_variant bitmap_tip = {
382 .kadt = bitmap_ip_kadt,
383 .uadt = bitmap_ip_uadt,
384 .adt = {
385 [IPSET_ADD] = bitmap_ip_tadd,
386 [IPSET_DEL] = bitmap_ip_tdel,
387 [IPSET_TEST] = bitmap_ip_ttest,
388 },
389 .destroy = bitmap_ip_destroy,
390 .flush = bitmap_ip_flush,
391 .head = bitmap_ip_head,
392 .list = bitmap_ip_tlist,
393 .same_set = bitmap_ip_same_set,
394};
395
396static void
397bitmap_ip_gc(unsigned long ul_set)
398{
399 struct ip_set *set = (struct ip_set *) ul_set;
400 struct bitmap_ip *map = set->data;
401 unsigned long *table = map->members;
402 u32 id;
403
404 /* We run parallel with other readers (test element)
405 * but adding/deleting new entries is locked out */
406 read_lock_bh(&set->lock);
407 for (id = 0; id < map->elements; id++)
408 if (ip_set_timeout_expired(table[id]))
409 table[id] = IPSET_ELEM_UNSET;
410 read_unlock_bh(&set->lock);
411
412 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
413 add_timer(&map->gc);
414}
415
416static void
417bitmap_ip_gc_init(struct ip_set *set)
418{
419 struct bitmap_ip *map = set->data;
420
421 init_timer(&map->gc);
422 map->gc.data = (unsigned long) set;
423 map->gc.function = bitmap_ip_gc;
424 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
425 add_timer(&map->gc);
426}
427
428/* Create bitmap:ip type of sets */
429
430static bool
431init_map_ip(struct ip_set *set, struct bitmap_ip *map,
432 u32 first_ip, u32 last_ip,
433 u32 elements, u32 hosts, u8 netmask)
434{
435 map->members = ip_set_alloc(map->memsize);
436 if (!map->members)
437 return false;
438 map->first_ip = first_ip;
439 map->last_ip = last_ip;
440 map->elements = elements;
441 map->hosts = hosts;
442 map->netmask = netmask;
443 map->timeout = IPSET_NO_TIMEOUT;
444
445 set->data = map;
446 set->family = AF_INET;
447
448 return true;
449}
450
451static int
452bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
453{
454 struct bitmap_ip *map;
455 u32 first_ip, last_ip, hosts, elements;
456 u8 netmask = 32;
457 int ret;
458
459 if (unlikely(!tb[IPSET_ATTR_IP] ||
460 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
461 return -IPSET_ERR_PROTOCOL;
462
463 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
464 if (ret)
465 return ret;
466
467 if (tb[IPSET_ATTR_IP_TO]) {
468 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
469 if (ret)
470 return ret;
471 if (first_ip > last_ip) {
472 u32 tmp = first_ip;
473
474 first_ip = last_ip;
475 last_ip = tmp;
476 }
477 } else if (tb[IPSET_ATTR_CIDR]) {
478 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
479
480 if (cidr >= 32)
481 return -IPSET_ERR_INVALID_CIDR;
482 last_ip = first_ip | ~ip_set_hostmask(cidr);
483 } else
484 return -IPSET_ERR_PROTOCOL;
485
486 if (tb[IPSET_ATTR_NETMASK]) {
487 netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
488
489 if (netmask > 32)
490 return -IPSET_ERR_INVALID_NETMASK;
491
492 first_ip &= ip_set_hostmask(netmask);
493 last_ip |= ~ip_set_hostmask(netmask);
494 }
495
496 if (netmask == 32) {
497 hosts = 1;
498 elements = last_ip - first_ip + 1;
499 } else {
500 u8 mask_bits;
501 u32 mask;
502
503 mask = range_to_mask(first_ip, last_ip, &mask_bits);
504
505 if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
506 netmask <= mask_bits)
507 return -IPSET_ERR_BITMAP_RANGE;
508
509 pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
510 hosts = 2 << (32 - netmask - 1);
511 elements = 2 << (netmask - mask_bits - 1);
512 }
513 if (elements > IPSET_BITMAP_MAX_RANGE + 1)
514 return -IPSET_ERR_BITMAP_RANGE_SIZE;
515
516 pr_debug("hosts %u, elements %u\n", hosts, elements);
517
518 map = kzalloc(sizeof(*map), GFP_KERNEL);
519 if (!map)
520 return -ENOMEM;
521
522 if (tb[IPSET_ATTR_TIMEOUT]) {
523 map->memsize = elements * sizeof(unsigned long);
524
525 if (!init_map_ip(set, map, first_ip, last_ip,
526 elements, hosts, netmask)) {
527 kfree(map);
528 return -ENOMEM;
529 }
530
531 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
532 set->variant = &bitmap_tip;
533
534 bitmap_ip_gc_init(set);
535 } else {
536 map->memsize = bitmap_bytes(0, elements - 1);
537
538 if (!init_map_ip(set, map, first_ip, last_ip,
539 elements, hosts, netmask)) {
540 kfree(map);
541 return -ENOMEM;
542 }
543
544 set->variant = &bitmap_ip;
545 }
546 return 0;
547}
548
549static struct ip_set_type bitmap_ip_type __read_mostly = {
550 .name = "bitmap:ip",
551 .protocol = IPSET_PROTOCOL,
552 .features = IPSET_TYPE_IP,
553 .dimension = IPSET_DIM_ONE,
554 .family = AF_INET,
555 .revision = 0,
556 .create = bitmap_ip_create,
557 .create_policy = {
558 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
559 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
560 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
561 [IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
562 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
563 },
564 .adt_policy = {
565 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
566 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
567 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
568 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
569 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
570 },
571 .me = THIS_MODULE,
572};
573
574static int __init
575bitmap_ip_init(void)
576{
577 return ip_set_type_register(&bitmap_ip_type);
578}
579
580static void __exit
581bitmap_ip_fini(void)
582{
583 ip_set_type_unregister(&bitmap_ip_type);
584}
585
586module_init(bitmap_ip_init);
587module_exit(bitmap_ip_fini);
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
new file mode 100644
index 000000000000..5e790172deff
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -0,0 +1,652 @@
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Martin Josefsson <gandalf@wlug.westbo.se>
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/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
12
13#include <linux/module.h>
14#include <linux/ip.h>
15#include <linux/etherdevice.h>
16#include <linux/skbuff.h>
17#include <linux/errno.h>
18#include <linux/if_ether.h>
19#include <linux/netlink.h>
20#include <linux/jiffies.h>
21#include <linux/timer.h>
22#include <net/netlink.h>
23
24#include <linux/netfilter/ipset/pfxlen.h>
25#include <linux/netfilter/ipset/ip_set.h>
26#include <linux/netfilter/ipset/ip_set_timeout.h>
27#include <linux/netfilter/ipset/ip_set_bitmap.h>
28
29MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
31MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
32MODULE_ALIAS("ip_set_bitmap:ip,mac");
33
34enum {
35 MAC_EMPTY, /* element is not set */
36 MAC_FILLED, /* element is set with MAC */
37 MAC_UNSET, /* element is set, without MAC */
38};
39
40/* Type structure */
41struct bitmap_ipmac {
42 void *members; /* the set members */
43 u32 first_ip; /* host byte order, included in range */
44 u32 last_ip; /* host byte order, included in range */
45 u32 timeout; /* timeout value */
46 struct timer_list gc; /* garbage collector */
47 size_t dsize; /* size of element */
48};
49
50/* ADT structure for generic function args */
51struct ipmac {
52 u32 id; /* id in array */
53 unsigned char *ether; /* ethernet address */
54};
55
56/* Member element without and with timeout */
57
58struct ipmac_elem {
59 unsigned char ether[ETH_ALEN];
60 unsigned char match;
61} __attribute__ ((aligned));
62
63struct ipmac_telem {
64 unsigned char ether[ETH_ALEN];
65 unsigned char match;
66 unsigned long timeout;
67} __attribute__ ((aligned));
68
69static inline void *
70bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
71{
72 return (void *)((char *)map->members + id * map->dsize);
73}
74
75static inline bool
76bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
77{
78 const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
79
80 return ip_set_timeout_test(elem->timeout);
81}
82
83static inline bool
84bitmap_expired(const struct bitmap_ipmac *map, u32 id)
85{
86 const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
87
88 return ip_set_timeout_expired(elem->timeout);
89}
90
91static inline int
92bitmap_ipmac_exist(const struct ipmac_telem *elem)
93{
94 return elem->match == MAC_UNSET ||
95 (elem->match == MAC_FILLED &&
96 !ip_set_timeout_expired(elem->timeout));
97}
98
99/* Base variant */
100
101static int
102bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
103{
104 const struct bitmap_ipmac *map = set->data;
105 const struct ipmac *data = value;
106 const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
107
108 switch (elem->match) {
109 case MAC_UNSET:
110 /* Trigger kernel to fill out the ethernet address */
111 return -EAGAIN;
112 case MAC_FILLED:
113 return data->ether == NULL ||
114 compare_ether_addr(data->ether, elem->ether) == 0;
115 }
116 return 0;
117}
118
119static int
120bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
121{
122 struct bitmap_ipmac *map = set->data;
123 const struct ipmac *data = value;
124 struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
125
126 switch (elem->match) {
127 case MAC_UNSET:
128 if (!data->ether)
129 /* Already added without ethernet address */
130 return -IPSET_ERR_EXIST;
131 /* Fill the MAC address */
132 memcpy(elem->ether, data->ether, ETH_ALEN);
133 elem->match = MAC_FILLED;
134 break;
135 case MAC_FILLED:
136 return -IPSET_ERR_EXIST;
137 case MAC_EMPTY:
138 if (data->ether) {
139 memcpy(elem->ether, data->ether, ETH_ALEN);
140 elem->match = MAC_FILLED;
141 } else
142 elem->match = MAC_UNSET;
143 }
144
145 return 0;
146}
147
148static int
149bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
150{
151 struct bitmap_ipmac *map = set->data;
152 const struct ipmac *data = value;
153 struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
154
155 if (elem->match == MAC_EMPTY)
156 return -IPSET_ERR_EXIST;
157
158 elem->match = MAC_EMPTY;
159
160 return 0;
161}
162
163static int
164bitmap_ipmac_list(const struct ip_set *set,
165 struct sk_buff *skb, struct netlink_callback *cb)
166{
167 const struct bitmap_ipmac *map = set->data;
168 const struct ipmac_elem *elem;
169 struct nlattr *atd, *nested;
170 u32 id, first = cb->args[2];
171 u32 last = map->last_ip - map->first_ip;
172
173 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
174 if (!atd)
175 return -EMSGSIZE;
176 for (; cb->args[2] <= last; cb->args[2]++) {
177 id = cb->args[2];
178 elem = bitmap_ipmac_elem(map, id);
179 if (elem->match == MAC_EMPTY)
180 continue;
181 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
182 if (!nested) {
183 if (id == first) {
184 nla_nest_cancel(skb, atd);
185 return -EMSGSIZE;
186 } else
187 goto nla_put_failure;
188 }
189 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
190 htonl(map->first_ip + id));
191 if (elem->match == MAC_FILLED)
192 NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
193 elem->ether);
194 ipset_nest_end(skb, nested);
195 }
196 ipset_nest_end(skb, atd);
197 /* Set listing finished */
198 cb->args[2] = 0;
199
200 return 0;
201
202nla_put_failure:
203 nla_nest_cancel(skb, nested);
204 ipset_nest_end(skb, atd);
205 if (unlikely(id == first)) {
206 cb->args[2] = 0;
207 return -EMSGSIZE;
208 }
209 return 0;
210}
211
212/* Timeout variant */
213
214static int
215bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
216{
217 const struct bitmap_ipmac *map = set->data;
218 const struct ipmac *data = value;
219 const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
220
221 switch (elem->match) {
222 case MAC_UNSET:
223 /* Trigger kernel to fill out the ethernet address */
224 return -EAGAIN;
225 case MAC_FILLED:
226 return (data->ether == NULL ||
227 compare_ether_addr(data->ether, elem->ether) == 0) &&
228 !bitmap_expired(map, data->id);
229 }
230 return 0;
231}
232
233static int
234bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
235{
236 struct bitmap_ipmac *map = set->data;
237 const struct ipmac *data = value;
238 struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
239
240 switch (elem->match) {
241 case MAC_UNSET:
242 if (!data->ether)
243 /* Already added without ethernet address */
244 return -IPSET_ERR_EXIST;
245 /* Fill the MAC address and activate the timer */
246 memcpy(elem->ether, data->ether, ETH_ALEN);
247 elem->match = MAC_FILLED;
248 if (timeout == map->timeout)
249 /* Timeout was not specified, get stored one */
250 timeout = elem->timeout;
251 elem->timeout = ip_set_timeout_set(timeout);
252 break;
253 case MAC_FILLED:
254 if (!bitmap_expired(map, data->id))
255 return -IPSET_ERR_EXIST;
256 /* Fall through */
257 case MAC_EMPTY:
258 if (data->ether) {
259 memcpy(elem->ether, data->ether, ETH_ALEN);
260 elem->match = MAC_FILLED;
261 } else
262 elem->match = MAC_UNSET;
263 /* If MAC is unset yet, we store plain timeout value
264 * because the timer is not activated yet
265 * and we can reuse it later when MAC is filled out,
266 * possibly by the kernel */
267 elem->timeout = data->ether ? ip_set_timeout_set(timeout)
268 : timeout;
269 break;
270 }
271
272 return 0;
273}
274
275static int
276bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
277{
278 struct bitmap_ipmac *map = set->data;
279 const struct ipmac *data = value;
280 struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
281
282 if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
283 return -IPSET_ERR_EXIST;
284
285 elem->match = MAC_EMPTY;
286
287 return 0;
288}
289
290static int
291bitmap_ipmac_tlist(const struct ip_set *set,
292 struct sk_buff *skb, struct netlink_callback *cb)
293{
294 const struct bitmap_ipmac *map = set->data;
295 const struct ipmac_telem *elem;
296 struct nlattr *atd, *nested;
297 u32 id, first = cb->args[2];
298 u32 timeout, last = map->last_ip - map->first_ip;
299
300 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
301 if (!atd)
302 return -EMSGSIZE;
303 for (; cb->args[2] <= last; cb->args[2]++) {
304 id = cb->args[2];
305 elem = bitmap_ipmac_elem(map, id);
306 if (!bitmap_ipmac_exist(elem))
307 continue;
308 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
309 if (!nested) {
310 if (id == first) {
311 nla_nest_cancel(skb, atd);
312 return -EMSGSIZE;
313 } else
314 goto nla_put_failure;
315 }
316 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
317 htonl(map->first_ip + id));
318 if (elem->match == MAC_FILLED)
319 NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
320 elem->ether);
321 timeout = elem->match == MAC_UNSET ? elem->timeout
322 : ip_set_timeout_get(elem->timeout);
323 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
324 ipset_nest_end(skb, nested);
325 }
326 ipset_nest_end(skb, atd);
327 /* Set listing finished */
328 cb->args[2] = 0;
329
330 return 0;
331
332nla_put_failure:
333 nla_nest_cancel(skb, nested);
334 ipset_nest_end(skb, atd);
335 return -EMSGSIZE;
336}
337
338static int
339bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
340 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
341{
342 struct bitmap_ipmac *map = set->data;
343 ipset_adtfn adtfn = set->variant->adt[adt];
344 struct ipmac data;
345
346 data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
347 if (data.id < map->first_ip || data.id > map->last_ip)
348 return -IPSET_ERR_BITMAP_RANGE;
349
350 /* Backward compatibility: we don't check the second flag */
351 if (skb_mac_header(skb) < skb->head ||
352 (skb_mac_header(skb) + ETH_HLEN) > skb->data)
353 return -EINVAL;
354
355 data.id -= map->first_ip;
356 data.ether = eth_hdr(skb)->h_source;
357
358 return adtfn(set, &data, map->timeout);
359}
360
361static int
362bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
363 enum ipset_adt adt, u32 *lineno, u32 flags)
364{
365 const struct bitmap_ipmac *map = set->data;
366 ipset_adtfn adtfn = set->variant->adt[adt];
367 struct ipmac data;
368 u32 timeout = map->timeout;
369 int ret = 0;
370
371 if (unlikely(!tb[IPSET_ATTR_IP] ||
372 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
373 return -IPSET_ERR_PROTOCOL;
374
375 if (tb[IPSET_ATTR_LINENO])
376 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
377
378 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id);
379 if (ret)
380 return ret;
381
382 if (data.id < map->first_ip || data.id > map->last_ip)
383 return -IPSET_ERR_BITMAP_RANGE;
384
385 if (tb[IPSET_ATTR_ETHER])
386 data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
387 else
388 data.ether = NULL;
389
390 if (tb[IPSET_ATTR_TIMEOUT]) {
391 if (!with_timeout(map->timeout))
392 return -IPSET_ERR_TIMEOUT;
393 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
394 }
395
396 data.id -= map->first_ip;
397
398 ret = adtfn(set, &data, timeout);
399
400 return ip_set_eexist(ret, flags) ? 0 : ret;
401}
402
403static void
404bitmap_ipmac_destroy(struct ip_set *set)
405{
406 struct bitmap_ipmac *map = set->data;
407
408 if (with_timeout(map->timeout))
409 del_timer_sync(&map->gc);
410
411 ip_set_free(map->members);
412 kfree(map);
413
414 set->data = NULL;
415}
416
417static void
418bitmap_ipmac_flush(struct ip_set *set)
419{
420 struct bitmap_ipmac *map = set->data;
421
422 memset(map->members, 0,
423 (map->last_ip - map->first_ip + 1) * map->dsize);
424}
425
426static int
427bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
428{
429 const struct bitmap_ipmac *map = set->data;
430 struct nlattr *nested;
431
432 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
433 if (!nested)
434 goto nla_put_failure;
435 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
436 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
437 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
438 htonl(atomic_read(&set->ref) - 1));
439 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
440 htonl(sizeof(*map)
441 + (map->last_ip - map->first_ip + 1) * map->dsize));
442 if (with_timeout(map->timeout))
443 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
444 ipset_nest_end(skb, nested);
445
446 return 0;
447nla_put_failure:
448 return -EMSGSIZE;
449}
450
451static bool
452bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
453{
454 const struct bitmap_ipmac *x = a->data;
455 const struct bitmap_ipmac *y = b->data;
456
457 return x->first_ip == y->first_ip &&
458 x->last_ip == y->last_ip &&
459 x->timeout == y->timeout;
460}
461
462static const struct ip_set_type_variant bitmap_ipmac = {
463 .kadt = bitmap_ipmac_kadt,
464 .uadt = bitmap_ipmac_uadt,
465 .adt = {
466 [IPSET_ADD] = bitmap_ipmac_add,
467 [IPSET_DEL] = bitmap_ipmac_del,
468 [IPSET_TEST] = bitmap_ipmac_test,
469 },
470 .destroy = bitmap_ipmac_destroy,
471 .flush = bitmap_ipmac_flush,
472 .head = bitmap_ipmac_head,
473 .list = bitmap_ipmac_list,
474 .same_set = bitmap_ipmac_same_set,
475};
476
477static const struct ip_set_type_variant bitmap_tipmac = {
478 .kadt = bitmap_ipmac_kadt,
479 .uadt = bitmap_ipmac_uadt,
480 .adt = {
481 [IPSET_ADD] = bitmap_ipmac_tadd,
482 [IPSET_DEL] = bitmap_ipmac_tdel,
483 [IPSET_TEST] = bitmap_ipmac_ttest,
484 },
485 .destroy = bitmap_ipmac_destroy,
486 .flush = bitmap_ipmac_flush,
487 .head = bitmap_ipmac_head,
488 .list = bitmap_ipmac_tlist,
489 .same_set = bitmap_ipmac_same_set,
490};
491
492static void
493bitmap_ipmac_gc(unsigned long ul_set)
494{
495 struct ip_set *set = (struct ip_set *) ul_set;
496 struct bitmap_ipmac *map = set->data;
497 struct ipmac_telem *elem;
498 u32 id, last = map->last_ip - map->first_ip;
499
500 /* We run parallel with other readers (test element)
501 * but adding/deleting new entries is locked out */
502 read_lock_bh(&set->lock);
503 for (id = 0; id <= last; id++) {
504 elem = bitmap_ipmac_elem(map, id);
505 if (elem->match == MAC_FILLED &&
506 ip_set_timeout_expired(elem->timeout))
507 elem->match = MAC_EMPTY;
508 }
509 read_unlock_bh(&set->lock);
510
511 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
512 add_timer(&map->gc);
513}
514
515static void
516bitmap_ipmac_gc_init(struct ip_set *set)
517{
518 struct bitmap_ipmac *map = set->data;
519
520 init_timer(&map->gc);
521 map->gc.data = (unsigned long) set;
522 map->gc.function = bitmap_ipmac_gc;
523 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
524 add_timer(&map->gc);
525}
526
527/* Create bitmap:ip,mac type of sets */
528
529static bool
530init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
531 u32 first_ip, u32 last_ip)
532{
533 map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
534 if (!map->members)
535 return false;
536 map->first_ip = first_ip;
537 map->last_ip = last_ip;
538 map->timeout = IPSET_NO_TIMEOUT;
539
540 set->data = map;
541 set->family = AF_INET;
542
543 return true;
544}
545
546static int
547bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
548 u32 flags)
549{
550 u32 first_ip, last_ip, elements;
551 struct bitmap_ipmac *map;
552 int ret;
553
554 if (unlikely(!tb[IPSET_ATTR_IP] ||
555 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
556 return -IPSET_ERR_PROTOCOL;
557
558 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
559 if (ret)
560 return ret;
561
562 if (tb[IPSET_ATTR_IP_TO]) {
563 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
564 if (ret)
565 return ret;
566 if (first_ip > last_ip) {
567 u32 tmp = first_ip;
568
569 first_ip = last_ip;
570 last_ip = tmp;
571 }
572 } else if (tb[IPSET_ATTR_CIDR]) {
573 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
574
575 if (cidr >= 32)
576 return -IPSET_ERR_INVALID_CIDR;
577 last_ip = first_ip | ~ip_set_hostmask(cidr);
578 } else
579 return -IPSET_ERR_PROTOCOL;
580
581 elements = last_ip - first_ip + 1;
582
583 if (elements > IPSET_BITMAP_MAX_RANGE + 1)
584 return -IPSET_ERR_BITMAP_RANGE_SIZE;
585
586 map = kzalloc(sizeof(*map), GFP_KERNEL);
587 if (!map)
588 return -ENOMEM;
589
590 if (tb[IPSET_ATTR_TIMEOUT]) {
591 map->dsize = sizeof(struct ipmac_telem);
592
593 if (!init_map_ipmac(set, map, first_ip, last_ip)) {
594 kfree(map);
595 return -ENOMEM;
596 }
597
598 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
599
600 set->variant = &bitmap_tipmac;
601
602 bitmap_ipmac_gc_init(set);
603 } else {
604 map->dsize = sizeof(struct ipmac_elem);
605
606 if (!init_map_ipmac(set, map, first_ip, last_ip)) {
607 kfree(map);
608 return -ENOMEM;
609 }
610 set->variant = &bitmap_ipmac;
611
612 }
613 return 0;
614}
615
616static struct ip_set_type bitmap_ipmac_type = {
617 .name = "bitmap:ip,mac",
618 .protocol = IPSET_PROTOCOL,
619 .features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
620 .dimension = IPSET_DIM_TWO,
621 .family = AF_INET,
622 .revision = 0,
623 .create = bitmap_ipmac_create,
624 .create_policy = {
625 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
626 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
627 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
628 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
629 },
630 .adt_policy = {
631 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
632 [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
633 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
634 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
635 },
636 .me = THIS_MODULE,
637};
638
639static int __init
640bitmap_ipmac_init(void)
641{
642 return ip_set_type_register(&bitmap_ipmac_type);
643}
644
645static void __exit
646bitmap_ipmac_fini(void)
647{
648 ip_set_type_unregister(&bitmap_ipmac_type);
649}
650
651module_init(bitmap_ipmac_init);
652module_exit(bitmap_ipmac_fini);
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
new file mode 100644
index 000000000000..165f09b1a9cb
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -0,0 +1,515 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the bitmap:port type */
9
10#include <linux/module.h>
11#include <linux/ip.h>
12#include <linux/skbuff.h>
13#include <linux/errno.h>
14#include <linux/netlink.h>
15#include <linux/jiffies.h>
16#include <linux/timer.h>
17#include <net/netlink.h>
18
19#include <linux/netfilter/ipset/ip_set.h>
20#include <linux/netfilter/ipset/ip_set_bitmap.h>
21#include <linux/netfilter/ipset/ip_set_getport.h>
22#define IP_SET_BITMAP_TIMEOUT
23#include <linux/netfilter/ipset/ip_set_timeout.h>
24
25MODULE_LICENSE("GPL");
26MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
27MODULE_DESCRIPTION("bitmap:port type of IP sets");
28MODULE_ALIAS("ip_set_bitmap:port");
29
30/* Type structure */
31struct bitmap_port {
32 void *members; /* the set members */
33 u16 first_port; /* host byte order, included in range */
34 u16 last_port; /* host byte order, included in range */
35 size_t memsize; /* members size */
36 u32 timeout; /* timeout parameter */
37 struct timer_list gc; /* garbage collection */
38};
39
40/* Base variant */
41
42static int
43bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
44{
45 const struct bitmap_port *map = set->data;
46 u16 id = *(u16 *)value;
47
48 return !!test_bit(id, map->members);
49}
50
51static int
52bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
53{
54 struct bitmap_port *map = set->data;
55 u16 id = *(u16 *)value;
56
57 if (test_and_set_bit(id, map->members))
58 return -IPSET_ERR_EXIST;
59
60 return 0;
61}
62
63static int
64bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
65{
66 struct bitmap_port *map = set->data;
67 u16 id = *(u16 *)value;
68
69 if (!test_and_clear_bit(id, map->members))
70 return -IPSET_ERR_EXIST;
71
72 return 0;
73}
74
75static int
76bitmap_port_list(const struct ip_set *set,
77 struct sk_buff *skb, struct netlink_callback *cb)
78{
79 const struct bitmap_port *map = set->data;
80 struct nlattr *atd, *nested;
81 u16 id, first = cb->args[2];
82 u16 last = map->last_port - map->first_port;
83
84 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
85 if (!atd)
86 return -EMSGSIZE;
87 for (; cb->args[2] <= last; cb->args[2]++) {
88 id = cb->args[2];
89 if (!test_bit(id, map->members))
90 continue;
91 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
92 if (!nested) {
93 if (id == first) {
94 nla_nest_cancel(skb, atd);
95 return -EMSGSIZE;
96 } else
97 goto nla_put_failure;
98 }
99 NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
100 htons(map->first_port + id));
101 ipset_nest_end(skb, nested);
102 }
103 ipset_nest_end(skb, atd);
104 /* Set listing finished */
105 cb->args[2] = 0;
106
107 return 0;
108
109nla_put_failure:
110 nla_nest_cancel(skb, nested);
111 ipset_nest_end(skb, atd);
112 if (unlikely(id == first)) {
113 cb->args[2] = 0;
114 return -EMSGSIZE;
115 }
116 return 0;
117}
118
119/* Timeout variant */
120
121static int
122bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
123{
124 const struct bitmap_port *map = set->data;
125 const unsigned long *members = map->members;
126 u16 id = *(u16 *)value;
127
128 return ip_set_timeout_test(members[id]);
129}
130
131static int
132bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
133{
134 struct bitmap_port *map = set->data;
135 unsigned long *members = map->members;
136 u16 id = *(u16 *)value;
137
138 if (ip_set_timeout_test(members[id]))
139 return -IPSET_ERR_EXIST;
140
141 members[id] = ip_set_timeout_set(timeout);
142
143 return 0;
144}
145
146static int
147bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
148{
149 struct bitmap_port *map = set->data;
150 unsigned long *members = map->members;
151 u16 id = *(u16 *)value;
152 int ret = -IPSET_ERR_EXIST;
153
154 if (ip_set_timeout_test(members[id]))
155 ret = 0;
156
157 members[id] = IPSET_ELEM_UNSET;
158 return ret;
159}
160
161static int
162bitmap_port_tlist(const struct ip_set *set,
163 struct sk_buff *skb, struct netlink_callback *cb)
164{
165 const struct bitmap_port *map = set->data;
166 struct nlattr *adt, *nested;
167 u16 id, first = cb->args[2];
168 u16 last = map->last_port - map->first_port;
169 const unsigned long *members = map->members;
170
171 adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
172 if (!adt)
173 return -EMSGSIZE;
174 for (; cb->args[2] <= last; cb->args[2]++) {
175 id = cb->args[2];
176 if (!ip_set_timeout_test(members[id]))
177 continue;
178 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
179 if (!nested) {
180 if (id == first) {
181 nla_nest_cancel(skb, adt);
182 return -EMSGSIZE;
183 } else
184 goto nla_put_failure;
185 }
186 NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
187 htons(map->first_port + id));
188 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
189 htonl(ip_set_timeout_get(members[id])));
190 ipset_nest_end(skb, nested);
191 }
192 ipset_nest_end(skb, adt);
193
194 /* Set listing finished */
195 cb->args[2] = 0;
196
197 return 0;
198
199nla_put_failure:
200 nla_nest_cancel(skb, nested);
201 ipset_nest_end(skb, adt);
202 if (unlikely(id == first)) {
203 cb->args[2] = 0;
204 return -EMSGSIZE;
205 }
206 return 0;
207}
208
209static int
210bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
211 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
212{
213 struct bitmap_port *map = set->data;
214 ipset_adtfn adtfn = set->variant->adt[adt];
215 __be16 __port;
216 u16 port = 0;
217
218 if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
219 return -EINVAL;
220
221 port = ntohs(__port);
222
223 if (port < map->first_port || port > map->last_port)
224 return -IPSET_ERR_BITMAP_RANGE;
225
226 port -= map->first_port;
227
228 return adtfn(set, &port, map->timeout);
229}
230
231static int
232bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
233 enum ipset_adt adt, u32 *lineno, u32 flags)
234{
235 struct bitmap_port *map = set->data;
236 ipset_adtfn adtfn = set->variant->adt[adt];
237 u32 timeout = map->timeout;
238 u32 port; /* wraparound */
239 u16 id, port_to;
240 int ret = 0;
241
242 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
243 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
244 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
245 return -IPSET_ERR_PROTOCOL;
246
247 if (tb[IPSET_ATTR_LINENO])
248 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
249
250 port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
251 if (port < map->first_port || port > map->last_port)
252 return -IPSET_ERR_BITMAP_RANGE;
253
254 if (tb[IPSET_ATTR_TIMEOUT]) {
255 if (!with_timeout(map->timeout))
256 return -IPSET_ERR_TIMEOUT;
257 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
258 }
259
260 if (adt == IPSET_TEST) {
261 id = port - map->first_port;
262 return adtfn(set, &id, timeout);
263 }
264
265 if (tb[IPSET_ATTR_PORT_TO]) {
266 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
267 if (port > port_to) {
268 swap(port, port_to);
269 if (port < map->first_port)
270 return -IPSET_ERR_BITMAP_RANGE;
271 }
272 } else
273 port_to = port;
274
275 if (port_to > map->last_port)
276 return -IPSET_ERR_BITMAP_RANGE;
277
278 for (; port <= port_to; port++) {
279 id = port - map->first_port;
280 ret = adtfn(set, &id, timeout);
281
282 if (ret && !ip_set_eexist(ret, flags))
283 return ret;
284 else
285 ret = 0;
286 }
287 return ret;
288}
289
290static void
291bitmap_port_destroy(struct ip_set *set)
292{
293 struct bitmap_port *map = set->data;
294
295 if (with_timeout(map->timeout))
296 del_timer_sync(&map->gc);
297
298 ip_set_free(map->members);
299 kfree(map);
300
301 set->data = NULL;
302}
303
304static void
305bitmap_port_flush(struct ip_set *set)
306{
307 struct bitmap_port *map = set->data;
308
309 memset(map->members, 0, map->memsize);
310}
311
312static int
313bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
314{
315 const struct bitmap_port *map = set->data;
316 struct nlattr *nested;
317
318 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
319 if (!nested)
320 goto nla_put_failure;
321 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
322 NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
323 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
324 htonl(atomic_read(&set->ref) - 1));
325 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
326 htonl(sizeof(*map) + map->memsize));
327 if (with_timeout(map->timeout))
328 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
329 ipset_nest_end(skb, nested);
330
331 return 0;
332nla_put_failure:
333 return -EMSGSIZE;
334}
335
336static bool
337bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
338{
339 const struct bitmap_port *x = a->data;
340 const struct bitmap_port *y = b->data;
341
342 return x->first_port == y->first_port &&
343 x->last_port == y->last_port &&
344 x->timeout == y->timeout;
345}
346
347static const struct ip_set_type_variant bitmap_port = {
348 .kadt = bitmap_port_kadt,
349 .uadt = bitmap_port_uadt,
350 .adt = {
351 [IPSET_ADD] = bitmap_port_add,
352 [IPSET_DEL] = bitmap_port_del,
353 [IPSET_TEST] = bitmap_port_test,
354 },
355 .destroy = bitmap_port_destroy,
356 .flush = bitmap_port_flush,
357 .head = bitmap_port_head,
358 .list = bitmap_port_list,
359 .same_set = bitmap_port_same_set,
360};
361
362static const struct ip_set_type_variant bitmap_tport = {
363 .kadt = bitmap_port_kadt,
364 .uadt = bitmap_port_uadt,
365 .adt = {
366 [IPSET_ADD] = bitmap_port_tadd,
367 [IPSET_DEL] = bitmap_port_tdel,
368 [IPSET_TEST] = bitmap_port_ttest,
369 },
370 .destroy = bitmap_port_destroy,
371 .flush = bitmap_port_flush,
372 .head = bitmap_port_head,
373 .list = bitmap_port_tlist,
374 .same_set = bitmap_port_same_set,
375};
376
377static void
378bitmap_port_gc(unsigned long ul_set)
379{
380 struct ip_set *set = (struct ip_set *) ul_set;
381 struct bitmap_port *map = set->data;
382 unsigned long *table = map->members;
383 u32 id; /* wraparound */
384 u16 last = map->last_port - map->first_port;
385
386 /* We run parallel with other readers (test element)
387 * but adding/deleting new entries is locked out */
388 read_lock_bh(&set->lock);
389 for (id = 0; id <= last; id++)
390 if (ip_set_timeout_expired(table[id]))
391 table[id] = IPSET_ELEM_UNSET;
392 read_unlock_bh(&set->lock);
393
394 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
395 add_timer(&map->gc);
396}
397
398static void
399bitmap_port_gc_init(struct ip_set *set)
400{
401 struct bitmap_port *map = set->data;
402
403 init_timer(&map->gc);
404 map->gc.data = (unsigned long) set;
405 map->gc.function = bitmap_port_gc;
406 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
407 add_timer(&map->gc);
408}
409
410/* Create bitmap:ip type of sets */
411
412static bool
413init_map_port(struct ip_set *set, struct bitmap_port *map,
414 u16 first_port, u16 last_port)
415{
416 map->members = ip_set_alloc(map->memsize);
417 if (!map->members)
418 return false;
419 map->first_port = first_port;
420 map->last_port = last_port;
421 map->timeout = IPSET_NO_TIMEOUT;
422
423 set->data = map;
424 set->family = AF_UNSPEC;
425
426 return true;
427}
428
429static int
430bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
431 u32 flags)
432{
433 struct bitmap_port *map;
434 u16 first_port, last_port;
435
436 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
437 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
438 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
439 return -IPSET_ERR_PROTOCOL;
440
441 first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
442 last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
443 if (first_port > last_port) {
444 u16 tmp = first_port;
445
446 first_port = last_port;
447 last_port = tmp;
448 }
449
450 map = kzalloc(sizeof(*map), GFP_KERNEL);
451 if (!map)
452 return -ENOMEM;
453
454 if (tb[IPSET_ATTR_TIMEOUT]) {
455 map->memsize = (last_port - first_port + 1)
456 * sizeof(unsigned long);
457
458 if (!init_map_port(set, map, first_port, last_port)) {
459 kfree(map);
460 return -ENOMEM;
461 }
462
463 map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
464 set->variant = &bitmap_tport;
465
466 bitmap_port_gc_init(set);
467 } else {
468 map->memsize = bitmap_bytes(0, last_port - first_port);
469 pr_debug("memsize: %zu\n", map->memsize);
470 if (!init_map_port(set, map, first_port, last_port)) {
471 kfree(map);
472 return -ENOMEM;
473 }
474
475 set->variant = &bitmap_port;
476 }
477 return 0;
478}
479
480static struct ip_set_type bitmap_port_type = {
481 .name = "bitmap:port",
482 .protocol = IPSET_PROTOCOL,
483 .features = IPSET_TYPE_PORT,
484 .dimension = IPSET_DIM_ONE,
485 .family = AF_UNSPEC,
486 .revision = 0,
487 .create = bitmap_port_create,
488 .create_policy = {
489 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
490 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
491 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
492 },
493 .adt_policy = {
494 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
495 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
496 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
497 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
498 },
499 .me = THIS_MODULE,
500};
501
502static int __init
503bitmap_port_init(void)
504{
505 return ip_set_type_register(&bitmap_port_type);
506}
507
508static void __exit
509bitmap_port_fini(void)
510{
511 ip_set_type_unregister(&bitmap_port_type);
512}
513
514module_init(bitmap_port_init);
515module_exit(bitmap_port_fini);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
new file mode 100644
index 000000000000..8b1a54c1e400
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -0,0 +1,1671 @@
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10/* Kernel module for IP set management */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/ip.h>
16#include <linux/skbuff.h>
17#include <linux/spinlock.h>
18#include <linux/netlink.h>
19#include <linux/rculist.h>
20#include <linux/version.h>
21#include <net/netlink.h>
22
23#include <linux/netfilter.h>
24#include <linux/netfilter/nfnetlink.h>
25#include <linux/netfilter/ipset/ip_set.h>
26
27static LIST_HEAD(ip_set_type_list); /* all registered set types */
28static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
29
30static struct ip_set **ip_set_list; /* all individual sets */
31static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
32
33#define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
34
35static unsigned int max_sets;
36
37module_param(max_sets, int, 0600);
38MODULE_PARM_DESC(max_sets, "maximal number of sets");
39MODULE_LICENSE("GPL");
40MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
41MODULE_DESCRIPTION("core IP set support");
42MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
43
44/*
45 * The set types are implemented in modules and registered set types
46 * can be found in ip_set_type_list. Adding/deleting types is
47 * serialized by ip_set_type_mutex.
48 */
49
50static inline void
51ip_set_type_lock(void)
52{
53 mutex_lock(&ip_set_type_mutex);
54}
55
56static inline void
57ip_set_type_unlock(void)
58{
59 mutex_unlock(&ip_set_type_mutex);
60}
61
62/* Register and deregister settype */
63
64static struct ip_set_type *
65find_set_type(const char *name, u8 family, u8 revision)
66{
67 struct ip_set_type *type;
68
69 list_for_each_entry_rcu(type, &ip_set_type_list, list)
70 if (STREQ(type->name, name) &&
71 (type->family == family || type->family == AF_UNSPEC) &&
72 type->revision == revision)
73 return type;
74 return NULL;
75}
76
77/* Unlock, try to load a set type module and lock again */
78static int
79try_to_load_type(const char *name)
80{
81 nfnl_unlock();
82 pr_debug("try to load ip_set_%s\n", name);
83 if (request_module("ip_set_%s", name) < 0) {
84 pr_warning("Can't find ip_set type %s\n", name);
85 nfnl_lock();
86 return -IPSET_ERR_FIND_TYPE;
87 }
88 nfnl_lock();
89 return -EAGAIN;
90}
91
92/* Find a set type and reference it */
93static int
94find_set_type_get(const char *name, u8 family, u8 revision,
95 struct ip_set_type **found)
96{
97 rcu_read_lock();
98 *found = find_set_type(name, family, revision);
99 if (*found) {
100 int err = !try_module_get((*found)->me);
101 rcu_read_unlock();
102 return err ? -EFAULT : 0;
103 }
104 rcu_read_unlock();
105
106 return try_to_load_type(name);
107}
108
109/* Find a given set type by name and family.
110 * If we succeeded, the supported minimal and maximum revisions are
111 * filled out.
112 */
113static int
114find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
115{
116 struct ip_set_type *type;
117 bool found = false;
118
119 *min = *max = 0;
120 rcu_read_lock();
121 list_for_each_entry_rcu(type, &ip_set_type_list, list)
122 if (STREQ(type->name, name) &&
123 (type->family == family || type->family == AF_UNSPEC)) {
124 found = true;
125 if (type->revision < *min)
126 *min = type->revision;
127 else if (type->revision > *max)
128 *max = type->revision;
129 }
130 rcu_read_unlock();
131 if (found)
132 return 0;
133
134 return try_to_load_type(name);
135}
136
137#define family_name(f) ((f) == AF_INET ? "inet" : \
138 (f) == AF_INET6 ? "inet6" : "any")
139
140/* Register a set type structure. The type is identified by
141 * the unique triple of name, family and revision.
142 */
143int
144ip_set_type_register(struct ip_set_type *type)
145{
146 int ret = 0;
147
148 if (type->protocol != IPSET_PROTOCOL) {
149 pr_warning("ip_set type %s, family %s, revision %u uses "
150 "wrong protocol version %u (want %u)\n",
151 type->name, family_name(type->family),
152 type->revision, type->protocol, IPSET_PROTOCOL);
153 return -EINVAL;
154 }
155
156 ip_set_type_lock();
157 if (find_set_type(type->name, type->family, type->revision)) {
158 /* Duplicate! */
159 pr_warning("ip_set type %s, family %s, revision %u "
160 "already registered!\n", type->name,
161 family_name(type->family), type->revision);
162 ret = -EINVAL;
163 goto unlock;
164 }
165 list_add_rcu(&type->list, &ip_set_type_list);
166 pr_debug("type %s, family %s, revision %u registered.\n",
167 type->name, family_name(type->family), type->revision);
168unlock:
169 ip_set_type_unlock();
170 return ret;
171}
172EXPORT_SYMBOL_GPL(ip_set_type_register);
173
174/* Unregister a set type. There's a small race with ip_set_create */
175void
176ip_set_type_unregister(struct ip_set_type *type)
177{
178 ip_set_type_lock();
179 if (!find_set_type(type->name, type->family, type->revision)) {
180 pr_warning("ip_set type %s, family %s, revision %u "
181 "not registered\n", type->name,
182 family_name(type->family), type->revision);
183 goto unlock;
184 }
185 list_del_rcu(&type->list);
186 pr_debug("type %s, family %s, revision %u unregistered.\n",
187 type->name, family_name(type->family), type->revision);
188unlock:
189 ip_set_type_unlock();
190
191 synchronize_rcu();
192}
193EXPORT_SYMBOL_GPL(ip_set_type_unregister);
194
195/* Utility functions */
196void *
197ip_set_alloc(size_t size)
198{
199 void *members = NULL;
200
201 if (size < KMALLOC_MAX_SIZE)
202 members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
203
204 if (members) {
205 pr_debug("%p: allocated with kmalloc\n", members);
206 return members;
207 }
208
209 members = vzalloc(size);
210 if (!members)
211 return NULL;
212 pr_debug("%p: allocated with vmalloc\n", members);
213
214 return members;
215}
216EXPORT_SYMBOL_GPL(ip_set_alloc);
217
218void
219ip_set_free(void *members)
220{
221 pr_debug("%p: free with %s\n", members,
222 is_vmalloc_addr(members) ? "vfree" : "kfree");
223 if (is_vmalloc_addr(members))
224 vfree(members);
225 else
226 kfree(members);
227}
228EXPORT_SYMBOL_GPL(ip_set_free);
229
230static inline bool
231flag_nested(const struct nlattr *nla)
232{
233 return nla->nla_type & NLA_F_NESTED;
234}
235
236static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
237 [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
238 [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
239 .len = sizeof(struct in6_addr) },
240};
241
242int
243ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
244{
245 struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
246
247 if (unlikely(!flag_nested(nla)))
248 return -IPSET_ERR_PROTOCOL;
249 if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
250 return -IPSET_ERR_PROTOCOL;
251 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
252 return -IPSET_ERR_PROTOCOL;
253
254 *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]);
255 return 0;
256}
257EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
258
259int
260ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
261{
262 struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
263
264 if (unlikely(!flag_nested(nla)))
265 return -IPSET_ERR_PROTOCOL;
266
267 if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
268 return -IPSET_ERR_PROTOCOL;
269 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
270 return -IPSET_ERR_PROTOCOL;
271
272 memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
273 sizeof(struct in6_addr));
274 return 0;
275}
276EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
277
278/*
279 * Creating/destroying/renaming/swapping affect the existence and
280 * the properties of a set. All of these can be executed from userspace
281 * only and serialized by the nfnl mutex indirectly from nfnetlink.
282 *
283 * Sets are identified by their index in ip_set_list and the index
284 * is used by the external references (set/SET netfilter modules).
285 *
286 * The set behind an index may change by swapping only, from userspace.
287 */
288
289static inline void
290__ip_set_get(ip_set_id_t index)
291{
292 atomic_inc(&ip_set_list[index]->ref);
293}
294
295static inline void
296__ip_set_put(ip_set_id_t index)
297{
298 atomic_dec(&ip_set_list[index]->ref);
299}
300
301/*
302 * Add, del and test set entries from kernel.
303 *
304 * The set behind the index must exist and must be referenced
305 * so it can't be destroyed (or changed) under our foot.
306 */
307
308int
309ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
310 u8 family, u8 dim, u8 flags)
311{
312 struct ip_set *set = ip_set_list[index];
313 int ret = 0;
314
315 BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
316 pr_debug("set %s, index %u\n", set->name, index);
317
318 if (dim < set->type->dimension ||
319 !(family == set->family || set->family == AF_UNSPEC))
320 return 0;
321
322 read_lock_bh(&set->lock);
323 ret = set->variant->kadt(set, skb, IPSET_TEST, family, dim, flags);
324 read_unlock_bh(&set->lock);
325
326 if (ret == -EAGAIN) {
327 /* Type requests element to be completed */
328 pr_debug("element must be competed, ADD is triggered\n");
329 write_lock_bh(&set->lock);
330 set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
331 write_unlock_bh(&set->lock);
332 ret = 1;
333 }
334
335 /* Convert error codes to nomatch */
336 return (ret < 0 ? 0 : ret);
337}
338EXPORT_SYMBOL_GPL(ip_set_test);
339
340int
341ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
342 u8 family, u8 dim, u8 flags)
343{
344 struct ip_set *set = ip_set_list[index];
345 int ret;
346
347 BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
348 pr_debug("set %s, index %u\n", set->name, index);
349
350 if (dim < set->type->dimension ||
351 !(family == set->family || set->family == AF_UNSPEC))
352 return 0;
353
354 write_lock_bh(&set->lock);
355 ret = set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
356 write_unlock_bh(&set->lock);
357
358 return ret;
359}
360EXPORT_SYMBOL_GPL(ip_set_add);
361
362int
363ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
364 u8 family, u8 dim, u8 flags)
365{
366 struct ip_set *set = ip_set_list[index];
367 int ret = 0;
368
369 BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
370 pr_debug("set %s, index %u\n", set->name, index);
371
372 if (dim < set->type->dimension ||
373 !(family == set->family || set->family == AF_UNSPEC))
374 return 0;
375
376 write_lock_bh(&set->lock);
377 ret = set->variant->kadt(set, skb, IPSET_DEL, family, dim, flags);
378 write_unlock_bh(&set->lock);
379
380 return ret;
381}
382EXPORT_SYMBOL_GPL(ip_set_del);
383
384/*
385 * Find set by name, reference it once. The reference makes sure the
386 * thing pointed to, does not go away under our feet.
387 *
388 * The nfnl mutex must already be activated.
389 */
390ip_set_id_t
391ip_set_get_byname(const char *name, struct ip_set **set)
392{
393 ip_set_id_t i, index = IPSET_INVALID_ID;
394 struct ip_set *s;
395
396 for (i = 0; i < ip_set_max; i++) {
397 s = ip_set_list[i];
398 if (s != NULL && STREQ(s->name, name)) {
399 __ip_set_get(i);
400 index = i;
401 *set = s;
402 }
403 }
404
405 return index;
406}
407EXPORT_SYMBOL_GPL(ip_set_get_byname);
408
409/*
410 * If the given set pointer points to a valid set, decrement
411 * reference count by 1. The caller shall not assume the index
412 * to be valid, after calling this function.
413 *
414 * The nfnl mutex must already be activated.
415 */
416void
417ip_set_put_byindex(ip_set_id_t index)
418{
419 if (ip_set_list[index] != NULL) {
420 BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
421 __ip_set_put(index);
422 }
423}
424EXPORT_SYMBOL_GPL(ip_set_put_byindex);
425
426/*
427 * Get the name of a set behind a set index.
428 * We assume the set is referenced, so it does exist and
429 * can't be destroyed. The set cannot be renamed due to
430 * the referencing either.
431 *
432 * The nfnl mutex must already be activated.
433 */
434const char *
435ip_set_name_byindex(ip_set_id_t index)
436{
437 const struct ip_set *set = ip_set_list[index];
438
439 BUG_ON(set == NULL);
440 BUG_ON(atomic_read(&set->ref) == 0);
441
442 /* Referenced, so it's safe */
443 return set->name;
444}
445EXPORT_SYMBOL_GPL(ip_set_name_byindex);
446
447/*
448 * Routines to call by external subsystems, which do not
449 * call nfnl_lock for us.
450 */
451
452/*
453 * Find set by name, reference it once. The reference makes sure the
454 * thing pointed to, does not go away under our feet.
455 *
456 * The nfnl mutex is used in the function.
457 */
458ip_set_id_t
459ip_set_nfnl_get(const char *name)
460{
461 struct ip_set *s;
462 ip_set_id_t index;
463
464 nfnl_lock();
465 index = ip_set_get_byname(name, &s);
466 nfnl_unlock();
467
468 return index;
469}
470EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
471
472/*
473 * Find set by index, reference it once. The reference makes sure the
474 * thing pointed to, does not go away under our feet.
475 *
476 * The nfnl mutex is used in the function.
477 */
478ip_set_id_t
479ip_set_nfnl_get_byindex(ip_set_id_t index)
480{
481 if (index > ip_set_max)
482 return IPSET_INVALID_ID;
483
484 nfnl_lock();
485 if (ip_set_list[index])
486 __ip_set_get(index);
487 else
488 index = IPSET_INVALID_ID;
489 nfnl_unlock();
490
491 return index;
492}
493EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
494
495/*
496 * If the given set pointer points to a valid set, decrement
497 * reference count by 1. The caller shall not assume the index
498 * to be valid, after calling this function.
499 *
500 * The nfnl mutex is used in the function.
501 */
502void
503ip_set_nfnl_put(ip_set_id_t index)
504{
505 nfnl_lock();
506 if (ip_set_list[index] != NULL) {
507 BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
508 __ip_set_put(index);
509 }
510 nfnl_unlock();
511}
512EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
513
514/*
515 * Communication protocol with userspace over netlink.
516 *
517 * We already locked by nfnl_lock.
518 */
519
520static inline bool
521protocol_failed(const struct nlattr * const tb[])
522{
523 return !tb[IPSET_ATTR_PROTOCOL] ||
524 nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
525}
526
527static inline u32
528flag_exist(const struct nlmsghdr *nlh)
529{
530 return nlh->nlmsg_flags & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
531}
532
533static struct nlmsghdr *
534start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
535 enum ipset_cmd cmd)
536{
537 struct nlmsghdr *nlh;
538 struct nfgenmsg *nfmsg;
539
540 nlh = nlmsg_put(skb, pid, seq, cmd | (NFNL_SUBSYS_IPSET << 8),
541 sizeof(*nfmsg), flags);
542 if (nlh == NULL)
543 return NULL;
544
545 nfmsg = nlmsg_data(nlh);
546 nfmsg->nfgen_family = AF_INET;
547 nfmsg->version = NFNETLINK_V0;
548 nfmsg->res_id = 0;
549
550 return nlh;
551}
552
553/* Create a set */
554
555static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
556 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
557 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
558 .len = IPSET_MAXNAMELEN - 1 },
559 [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
560 .len = IPSET_MAXNAMELEN - 1},
561 [IPSET_ATTR_REVISION] = { .type = NLA_U8 },
562 [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
563 [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
564};
565
566static ip_set_id_t
567find_set_id(const char *name)
568{
569 ip_set_id_t i, index = IPSET_INVALID_ID;
570 const struct ip_set *set;
571
572 for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) {
573 set = ip_set_list[i];
574 if (set != NULL && STREQ(set->name, name))
575 index = i;
576 }
577 return index;
578}
579
580static inline struct ip_set *
581find_set(const char *name)
582{
583 ip_set_id_t index = find_set_id(name);
584
585 return index == IPSET_INVALID_ID ? NULL : ip_set_list[index];
586}
587
588static int
589find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
590{
591 ip_set_id_t i;
592
593 *index = IPSET_INVALID_ID;
594 for (i = 0; i < ip_set_max; i++) {
595 if (ip_set_list[i] == NULL) {
596 if (*index == IPSET_INVALID_ID)
597 *index = i;
598 } else if (STREQ(name, ip_set_list[i]->name)) {
599 /* Name clash */
600 *set = ip_set_list[i];
601 return -EEXIST;
602 }
603 }
604 if (*index == IPSET_INVALID_ID)
605 /* No free slot remained */
606 return -IPSET_ERR_MAX_SETS;
607 return 0;
608}
609
610static int
611ip_set_create(struct sock *ctnl, struct sk_buff *skb,
612 const struct nlmsghdr *nlh,
613 const struct nlattr * const attr[])
614{
615 struct ip_set *set, *clash;
616 ip_set_id_t index = IPSET_INVALID_ID;
617 struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {};
618 const char *name, *typename;
619 u8 family, revision;
620 u32 flags = flag_exist(nlh);
621 int ret = 0;
622
623 if (unlikely(protocol_failed(attr) ||
624 attr[IPSET_ATTR_SETNAME] == NULL ||
625 attr[IPSET_ATTR_TYPENAME] == NULL ||
626 attr[IPSET_ATTR_REVISION] == NULL ||
627 attr[IPSET_ATTR_FAMILY] == NULL ||
628 (attr[IPSET_ATTR_DATA] != NULL &&
629 !flag_nested(attr[IPSET_ATTR_DATA]))))
630 return -IPSET_ERR_PROTOCOL;
631
632 name = nla_data(attr[IPSET_ATTR_SETNAME]);
633 typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
634 family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
635 revision = nla_get_u8(attr[IPSET_ATTR_REVISION]);
636 pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
637 name, typename, family_name(family), revision);
638
639 /*
640 * First, and without any locks, allocate and initialize
641 * a normal base set structure.
642 */
643 set = kzalloc(sizeof(struct ip_set), GFP_KERNEL);
644 if (!set)
645 return -ENOMEM;
646 rwlock_init(&set->lock);
647 strlcpy(set->name, name, IPSET_MAXNAMELEN);
648 atomic_set(&set->ref, 0);
649 set->family = family;
650
651 /*
652 * Next, check that we know the type, and take
653 * a reference on the type, to make sure it stays available
654 * while constructing our new set.
655 *
656 * After referencing the type, we try to create the type
657 * specific part of the set without holding any locks.
658 */
659 ret = find_set_type_get(typename, family, revision, &(set->type));
660 if (ret)
661 goto out;
662
663 /*
664 * Without holding any locks, create private part.
665 */
666 if (attr[IPSET_ATTR_DATA] &&
667 nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
668 set->type->create_policy)) {
669 ret = -IPSET_ERR_PROTOCOL;
670 goto put_out;
671 }
672
673 ret = set->type->create(set, tb, flags);
674 if (ret != 0)
675 goto put_out;
676
677 /* BTW, ret==0 here. */
678
679 /*
680 * Here, we have a valid, constructed set and we are protected
681 * by nfnl_lock. Find the first free index in ip_set_list and
682 * check clashing.
683 */
684 if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
685 /* If this is the same set and requested, ignore error */
686 if (ret == -EEXIST &&
687 (flags & IPSET_FLAG_EXIST) &&
688 STREQ(set->type->name, clash->type->name) &&
689 set->type->family == clash->type->family &&
690 set->type->revision == clash->type->revision &&
691 set->variant->same_set(set, clash))
692 ret = 0;
693 goto cleanup;
694 }
695
696 /*
697 * Finally! Add our shiny new set to the list, and be done.
698 */
699 pr_debug("create: '%s' created with index %u!\n", set->name, index);
700 ip_set_list[index] = set;
701
702 return ret;
703
704cleanup:
705 set->variant->destroy(set);
706put_out:
707 module_put(set->type->me);
708out:
709 kfree(set);
710 return ret;
711}
712
713/* Destroy sets */
714
715static const struct nla_policy
716ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
717 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
718 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
719 .len = IPSET_MAXNAMELEN - 1 },
720};
721
722static void
723ip_set_destroy_set(ip_set_id_t index)
724{
725 struct ip_set *set = ip_set_list[index];
726
727 pr_debug("set: %s\n", set->name);
728 ip_set_list[index] = NULL;
729
730 /* Must call it without holding any lock */
731 set->variant->destroy(set);
732 module_put(set->type->me);
733 kfree(set);
734}
735
736static int
737ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
738 const struct nlmsghdr *nlh,
739 const struct nlattr * const attr[])
740{
741 ip_set_id_t i;
742
743 if (unlikely(protocol_failed(attr)))
744 return -IPSET_ERR_PROTOCOL;
745
746 /* References are protected by the nfnl mutex */
747 if (!attr[IPSET_ATTR_SETNAME]) {
748 for (i = 0; i < ip_set_max; i++) {
749 if (ip_set_list[i] != NULL &&
750 (atomic_read(&ip_set_list[i]->ref)))
751 return -IPSET_ERR_BUSY;
752 }
753 for (i = 0; i < ip_set_max; i++) {
754 if (ip_set_list[i] != NULL)
755 ip_set_destroy_set(i);
756 }
757 } else {
758 i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
759 if (i == IPSET_INVALID_ID)
760 return -ENOENT;
761 else if (atomic_read(&ip_set_list[i]->ref))
762 return -IPSET_ERR_BUSY;
763
764 ip_set_destroy_set(i);
765 }
766 return 0;
767}
768
769/* Flush sets */
770
771static void
772ip_set_flush_set(struct ip_set *set)
773{
774 pr_debug("set: %s\n", set->name);
775
776 write_lock_bh(&set->lock);
777 set->variant->flush(set);
778 write_unlock_bh(&set->lock);
779}
780
781static int
782ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
783 const struct nlmsghdr *nlh,
784 const struct nlattr * const attr[])
785{
786 ip_set_id_t i;
787
788 if (unlikely(protocol_failed(attr)))
789 return -EPROTO;
790
791 if (!attr[IPSET_ATTR_SETNAME]) {
792 for (i = 0; i < ip_set_max; i++)
793 if (ip_set_list[i] != NULL)
794 ip_set_flush_set(ip_set_list[i]);
795 } else {
796 i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
797 if (i == IPSET_INVALID_ID)
798 return -ENOENT;
799
800 ip_set_flush_set(ip_set_list[i]);
801 }
802
803 return 0;
804}
805
806/* Rename a set */
807
808static const struct nla_policy
809ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
810 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
811 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
812 .len = IPSET_MAXNAMELEN - 1 },
813 [IPSET_ATTR_SETNAME2] = { .type = NLA_NUL_STRING,
814 .len = IPSET_MAXNAMELEN - 1 },
815};
816
817static int
818ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
819 const struct nlmsghdr *nlh,
820 const struct nlattr * const attr[])
821{
822 struct ip_set *set;
823 const char *name2;
824 ip_set_id_t i;
825
826 if (unlikely(protocol_failed(attr) ||
827 attr[IPSET_ATTR_SETNAME] == NULL ||
828 attr[IPSET_ATTR_SETNAME2] == NULL))
829 return -IPSET_ERR_PROTOCOL;
830
831 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
832 if (set == NULL)
833 return -ENOENT;
834 if (atomic_read(&set->ref) != 0)
835 return -IPSET_ERR_REFERENCED;
836
837 name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
838 for (i = 0; i < ip_set_max; i++) {
839 if (ip_set_list[i] != NULL &&
840 STREQ(ip_set_list[i]->name, name2))
841 return -IPSET_ERR_EXIST_SETNAME2;
842 }
843 strncpy(set->name, name2, IPSET_MAXNAMELEN);
844
845 return 0;
846}
847
848/* Swap two sets so that name/index points to the other.
849 * References and set names are also swapped.
850 *
851 * We are protected by the nfnl mutex and references are
852 * manipulated only by holding the mutex. The kernel interfaces
853 * do not hold the mutex but the pointer settings are atomic
854 * so the ip_set_list always contains valid pointers to the sets.
855 */
856
857static int
858ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
859 const struct nlmsghdr *nlh,
860 const struct nlattr * const attr[])
861{
862 struct ip_set *from, *to;
863 ip_set_id_t from_id, to_id;
864 char from_name[IPSET_MAXNAMELEN];
865 u32 from_ref;
866
867 if (unlikely(protocol_failed(attr) ||
868 attr[IPSET_ATTR_SETNAME] == NULL ||
869 attr[IPSET_ATTR_SETNAME2] == NULL))
870 return -IPSET_ERR_PROTOCOL;
871
872 from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
873 if (from_id == IPSET_INVALID_ID)
874 return -ENOENT;
875
876 to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
877 if (to_id == IPSET_INVALID_ID)
878 return -IPSET_ERR_EXIST_SETNAME2;
879
880 from = ip_set_list[from_id];
881 to = ip_set_list[to_id];
882
883 /* Features must not change.
884 * Not an artifical restriction anymore, as we must prevent
885 * possible loops created by swapping in setlist type of sets. */
886 if (!(from->type->features == to->type->features &&
887 from->type->family == to->type->family))
888 return -IPSET_ERR_TYPE_MISMATCH;
889
890 /* No magic here: ref munging protected by the nfnl_lock */
891 strncpy(from_name, from->name, IPSET_MAXNAMELEN);
892 from_ref = atomic_read(&from->ref);
893
894 strncpy(from->name, to->name, IPSET_MAXNAMELEN);
895 atomic_set(&from->ref, atomic_read(&to->ref));
896 strncpy(to->name, from_name, IPSET_MAXNAMELEN);
897 atomic_set(&to->ref, from_ref);
898
899 ip_set_list[from_id] = to;
900 ip_set_list[to_id] = from;
901
902 return 0;
903}
904
905/* List/save set data */
906
907#define DUMP_INIT 0L
908#define DUMP_ALL 1L
909#define DUMP_ONE 2L
910#define DUMP_LAST 3L
911
912static int
913ip_set_dump_done(struct netlink_callback *cb)
914{
915 if (cb->args[2]) {
916 pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
917 __ip_set_put((ip_set_id_t) cb->args[1]);
918 }
919 return 0;
920}
921
922static inline void
923dump_attrs(struct nlmsghdr *nlh)
924{
925 const struct nlattr *attr;
926 int rem;
927
928 pr_debug("dump nlmsg\n");
929 nlmsg_for_each_attr(attr, nlh, sizeof(struct nfgenmsg), rem) {
930 pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len);
931 }
932}
933
934static int
935dump_init(struct netlink_callback *cb)
936{
937 struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
938 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
939 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
940 struct nlattr *attr = (void *)nlh + min_len;
941 ip_set_id_t index;
942
943 /* Second pass, so parser can't fail */
944 nla_parse(cda, IPSET_ATTR_CMD_MAX,
945 attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
946
947 /* cb->args[0] : dump single set/all sets
948 * [1] : set index
949 * [..]: type specific
950 */
951
952 if (!cda[IPSET_ATTR_SETNAME]) {
953 cb->args[0] = DUMP_ALL;
954 return 0;
955 }
956
957 index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
958 if (index == IPSET_INVALID_ID)
959 return -ENOENT;
960
961 cb->args[0] = DUMP_ONE;
962 cb->args[1] = index;
963 return 0;
964}
965
966static int
967ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
968{
969 ip_set_id_t index = IPSET_INVALID_ID, max;
970 struct ip_set *set = NULL;
971 struct nlmsghdr *nlh = NULL;
972 unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
973 int ret = 0;
974
975 if (cb->args[0] == DUMP_INIT) {
976 ret = dump_init(cb);
977 if (ret < 0) {
978 nlh = nlmsg_hdr(cb->skb);
979 /* We have to create and send the error message
980 * manually :-( */
981 if (nlh->nlmsg_flags & NLM_F_ACK)
982 netlink_ack(cb->skb, nlh, ret);
983 return ret;
984 }
985 }
986
987 if (cb->args[1] >= ip_set_max)
988 goto out;
989
990 pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
991 max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
992 for (; cb->args[1] < max; cb->args[1]++) {
993 index = (ip_set_id_t) cb->args[1];
994 set = ip_set_list[index];
995 if (set == NULL) {
996 if (cb->args[0] == DUMP_ONE) {
997 ret = -ENOENT;
998 goto out;
999 }
1000 continue;
1001 }
1002 /* When dumping all sets, we must dump "sorted"
1003 * so that lists (unions of sets) are dumped last.
1004 */
1005 if (cb->args[0] != DUMP_ONE &&
1006 !((cb->args[0] == DUMP_ALL) ^
1007 (set->type->features & IPSET_DUMP_LAST)))
1008 continue;
1009 pr_debug("List set: %s\n", set->name);
1010 if (!cb->args[2]) {
1011 /* Start listing: make sure set won't be destroyed */
1012 pr_debug("reference set\n");
1013 __ip_set_get(index);
1014 }
1015 nlh = start_msg(skb, NETLINK_CB(cb->skb).pid,
1016 cb->nlh->nlmsg_seq, flags,
1017 IPSET_CMD_LIST);
1018 if (!nlh) {
1019 ret = -EMSGSIZE;
1020 goto release_refcount;
1021 }
1022 NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1023 NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
1024 switch (cb->args[2]) {
1025 case 0:
1026 /* Core header data */
1027 NLA_PUT_STRING(skb, IPSET_ATTR_TYPENAME,
1028 set->type->name);
1029 NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
1030 set->family);
1031 NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
1032 set->type->revision);
1033 ret = set->variant->head(set, skb);
1034 if (ret < 0)
1035 goto release_refcount;
1036 /* Fall through and add elements */
1037 default:
1038 read_lock_bh(&set->lock);
1039 ret = set->variant->list(set, skb, cb);
1040 read_unlock_bh(&set->lock);
1041 if (!cb->args[2]) {
1042 /* Set is done, proceed with next one */
1043 if (cb->args[0] == DUMP_ONE)
1044 cb->args[1] = IPSET_INVALID_ID;
1045 else
1046 cb->args[1]++;
1047 }
1048 goto release_refcount;
1049 }
1050 }
1051 goto out;
1052
1053nla_put_failure:
1054 ret = -EFAULT;
1055release_refcount:
1056 /* If there was an error or set is done, release set */
1057 if (ret || !cb->args[2]) {
1058 pr_debug("release set %s\n", ip_set_list[index]->name);
1059 __ip_set_put(index);
1060 }
1061
1062 /* If we dump all sets, continue with dumping last ones */
1063 if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2])
1064 cb->args[0] = DUMP_LAST;
1065
1066out:
1067 if (nlh) {
1068 nlmsg_end(skb, nlh);
1069 pr_debug("nlmsg_len: %u\n", nlh->nlmsg_len);
1070 dump_attrs(nlh);
1071 }
1072
1073 return ret < 0 ? ret : skb->len;
1074}
1075
1076static int
1077ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
1078 const struct nlmsghdr *nlh,
1079 const struct nlattr * const attr[])
1080{
1081 if (unlikely(protocol_failed(attr)))
1082 return -IPSET_ERR_PROTOCOL;
1083
1084 return netlink_dump_start(ctnl, skb, nlh,
1085 ip_set_dump_start,
1086 ip_set_dump_done);
1087}
1088
1089/* Add, del and test */
1090
1091static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
1092 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1093 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
1094 .len = IPSET_MAXNAMELEN - 1 },
1095 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
1096 [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
1097 [IPSET_ATTR_ADT] = { .type = NLA_NESTED },
1098};
1099
1100static int
1101call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
1102 struct nlattr *tb[], enum ipset_adt adt,
1103 u32 flags, bool use_lineno)
1104{
1105 int ret, retried = 0;
1106 u32 lineno = 0;
1107 bool eexist = flags & IPSET_FLAG_EXIST;
1108
1109 do {
1110 write_lock_bh(&set->lock);
1111 ret = set->variant->uadt(set, tb, adt, &lineno, flags);
1112 write_unlock_bh(&set->lock);
1113 } while (ret == -EAGAIN &&
1114 set->variant->resize &&
1115 (ret = set->variant->resize(set, retried++)) == 0);
1116
1117 if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
1118 return 0;
1119 if (lineno && use_lineno) {
1120 /* Error in restore/batch mode: send back lineno */
1121 struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
1122 struct sk_buff *skb2;
1123 struct nlmsgerr *errmsg;
1124 size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
1125 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
1126 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
1127 struct nlattr *cmdattr;
1128 u32 *errline;
1129
1130 skb2 = nlmsg_new(payload, GFP_KERNEL);
1131 if (skb2 == NULL)
1132 return -ENOMEM;
1133 rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid,
1134 nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
1135 errmsg = nlmsg_data(rep);
1136 errmsg->error = ret;
1137 memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
1138 cmdattr = (void *)&errmsg->msg + min_len;
1139
1140 nla_parse(cda, IPSET_ATTR_CMD_MAX,
1141 cmdattr, nlh->nlmsg_len - min_len,
1142 ip_set_adt_policy);
1143
1144 errline = nla_data(cda[IPSET_ATTR_LINENO]);
1145
1146 *errline = lineno;
1147
1148 netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1149 /* Signal netlink not to send its ACK/errmsg. */
1150 return -EINTR;
1151 }
1152
1153 return ret;
1154}
1155
1156static int
1157ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
1158 const struct nlmsghdr *nlh,
1159 const struct nlattr * const attr[])
1160{
1161 struct ip_set *set;
1162 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1163 const struct nlattr *nla;
1164 u32 flags = flag_exist(nlh);
1165 bool use_lineno;
1166 int ret = 0;
1167
1168 if (unlikely(protocol_failed(attr) ||
1169 attr[IPSET_ATTR_SETNAME] == NULL ||
1170 !((attr[IPSET_ATTR_DATA] != NULL) ^
1171 (attr[IPSET_ATTR_ADT] != NULL)) ||
1172 (attr[IPSET_ATTR_DATA] != NULL &&
1173 !flag_nested(attr[IPSET_ATTR_DATA])) ||
1174 (attr[IPSET_ATTR_ADT] != NULL &&
1175 (!flag_nested(attr[IPSET_ATTR_ADT]) ||
1176 attr[IPSET_ATTR_LINENO] == NULL))))
1177 return -IPSET_ERR_PROTOCOL;
1178
1179 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1180 if (set == NULL)
1181 return -ENOENT;
1182
1183 use_lineno = !!attr[IPSET_ATTR_LINENO];
1184 if (attr[IPSET_ATTR_DATA]) {
1185 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
1186 attr[IPSET_ATTR_DATA],
1187 set->type->adt_policy))
1188 return -IPSET_ERR_PROTOCOL;
1189 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags,
1190 use_lineno);
1191 } else {
1192 int nla_rem;
1193
1194 nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
1195 memset(tb, 0, sizeof(tb));
1196 if (nla_type(nla) != IPSET_ATTR_DATA ||
1197 !flag_nested(nla) ||
1198 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1199 set->type->adt_policy))
1200 return -IPSET_ERR_PROTOCOL;
1201 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
1202 flags, use_lineno);
1203 if (ret < 0)
1204 return ret;
1205 }
1206 }
1207 return ret;
1208}
1209
1210static int
1211ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
1212 const struct nlmsghdr *nlh,
1213 const struct nlattr * const attr[])
1214{
1215 struct ip_set *set;
1216 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1217 const struct nlattr *nla;
1218 u32 flags = flag_exist(nlh);
1219 bool use_lineno;
1220 int ret = 0;
1221
1222 if (unlikely(protocol_failed(attr) ||
1223 attr[IPSET_ATTR_SETNAME] == NULL ||
1224 !((attr[IPSET_ATTR_DATA] != NULL) ^
1225 (attr[IPSET_ATTR_ADT] != NULL)) ||
1226 (attr[IPSET_ATTR_DATA] != NULL &&
1227 !flag_nested(attr[IPSET_ATTR_DATA])) ||
1228 (attr[IPSET_ATTR_ADT] != NULL &&
1229 (!flag_nested(attr[IPSET_ATTR_ADT]) ||
1230 attr[IPSET_ATTR_LINENO] == NULL))))
1231 return -IPSET_ERR_PROTOCOL;
1232
1233 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1234 if (set == NULL)
1235 return -ENOENT;
1236
1237 use_lineno = !!attr[IPSET_ATTR_LINENO];
1238 if (attr[IPSET_ATTR_DATA]) {
1239 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
1240 attr[IPSET_ATTR_DATA],
1241 set->type->adt_policy))
1242 return -IPSET_ERR_PROTOCOL;
1243 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags,
1244 use_lineno);
1245 } else {
1246 int nla_rem;
1247
1248 nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
1249 memset(tb, 0, sizeof(*tb));
1250 if (nla_type(nla) != IPSET_ATTR_DATA ||
1251 !flag_nested(nla) ||
1252 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1253 set->type->adt_policy))
1254 return -IPSET_ERR_PROTOCOL;
1255 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
1256 flags, use_lineno);
1257 if (ret < 0)
1258 return ret;
1259 }
1260 }
1261 return ret;
1262}
1263
1264static int
1265ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
1266 const struct nlmsghdr *nlh,
1267 const struct nlattr * const attr[])
1268{
1269 struct ip_set *set;
1270 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1271 int ret = 0;
1272
1273 if (unlikely(protocol_failed(attr) ||
1274 attr[IPSET_ATTR_SETNAME] == NULL ||
1275 attr[IPSET_ATTR_DATA] == NULL ||
1276 !flag_nested(attr[IPSET_ATTR_DATA])))
1277 return -IPSET_ERR_PROTOCOL;
1278
1279 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1280 if (set == NULL)
1281 return -ENOENT;
1282
1283 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
1284 set->type->adt_policy))
1285 return -IPSET_ERR_PROTOCOL;
1286
1287 read_lock_bh(&set->lock);
1288 ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
1289 read_unlock_bh(&set->lock);
1290 /* Userspace can't trigger element to be re-added */
1291 if (ret == -EAGAIN)
1292 ret = 1;
1293
1294 return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST;
1295}
1296
1297/* Get headed data of a set */
1298
1299static int
1300ip_set_header(struct sock *ctnl, struct sk_buff *skb,
1301 const struct nlmsghdr *nlh,
1302 const struct nlattr * const attr[])
1303{
1304 const struct ip_set *set;
1305 struct sk_buff *skb2;
1306 struct nlmsghdr *nlh2;
1307 ip_set_id_t index;
1308 int ret = 0;
1309
1310 if (unlikely(protocol_failed(attr) ||
1311 attr[IPSET_ATTR_SETNAME] == NULL))
1312 return -IPSET_ERR_PROTOCOL;
1313
1314 index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
1315 if (index == IPSET_INVALID_ID)
1316 return -ENOENT;
1317 set = ip_set_list[index];
1318
1319 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1320 if (skb2 == NULL)
1321 return -ENOMEM;
1322
1323 nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
1324 IPSET_CMD_HEADER);
1325 if (!nlh2)
1326 goto nlmsg_failure;
1327 NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1328 NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
1329 NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
1330 NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
1331 NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision);
1332 nlmsg_end(skb2, nlh2);
1333
1334 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1335 if (ret < 0)
1336 return ret;
1337
1338 return 0;
1339
1340nla_put_failure:
1341 nlmsg_cancel(skb2, nlh2);
1342nlmsg_failure:
1343 kfree_skb(skb2);
1344 return -EMSGSIZE;
1345}
1346
1347/* Get type data */
1348
1349static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
1350 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1351 [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
1352 .len = IPSET_MAXNAMELEN - 1 },
1353 [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
1354};
1355
1356static int
1357ip_set_type(struct sock *ctnl, struct sk_buff *skb,
1358 const struct nlmsghdr *nlh,
1359 const struct nlattr * const attr[])
1360{
1361 struct sk_buff *skb2;
1362 struct nlmsghdr *nlh2;
1363 u8 family, min, max;
1364 const char *typename;
1365 int ret = 0;
1366
1367 if (unlikely(protocol_failed(attr) ||
1368 attr[IPSET_ATTR_TYPENAME] == NULL ||
1369 attr[IPSET_ATTR_FAMILY] == NULL))
1370 return -IPSET_ERR_PROTOCOL;
1371
1372 family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
1373 typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
1374 ret = find_set_type_minmax(typename, family, &min, &max);
1375 if (ret)
1376 return ret;
1377
1378 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1379 if (skb2 == NULL)
1380 return -ENOMEM;
1381
1382 nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
1383 IPSET_CMD_TYPE);
1384 if (!nlh2)
1385 goto nlmsg_failure;
1386 NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1387 NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, typename);
1388 NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, family);
1389 NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, max);
1390 NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min);
1391 nlmsg_end(skb2, nlh2);
1392
1393 pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
1394 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1395 if (ret < 0)
1396 return ret;
1397
1398 return 0;
1399
1400nla_put_failure:
1401 nlmsg_cancel(skb2, nlh2);
1402nlmsg_failure:
1403 kfree_skb(skb2);
1404 return -EMSGSIZE;
1405}
1406
1407/* Get protocol version */
1408
1409static const struct nla_policy
1410ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
1411 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1412};
1413
1414static int
1415ip_set_protocol(struct sock *ctnl, struct sk_buff *skb,
1416 const struct nlmsghdr *nlh,
1417 const struct nlattr * const attr[])
1418{
1419 struct sk_buff *skb2;
1420 struct nlmsghdr *nlh2;
1421 int ret = 0;
1422
1423 if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
1424 return -IPSET_ERR_PROTOCOL;
1425
1426 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1427 if (skb2 == NULL)
1428 return -ENOMEM;
1429
1430 nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
1431 IPSET_CMD_PROTOCOL);
1432 if (!nlh2)
1433 goto nlmsg_failure;
1434 NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1435 nlmsg_end(skb2, nlh2);
1436
1437 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1438 if (ret < 0)
1439 return ret;
1440
1441 return 0;
1442
1443nla_put_failure:
1444 nlmsg_cancel(skb2, nlh2);
1445nlmsg_failure:
1446 kfree_skb(skb2);
1447 return -EMSGSIZE;
1448}
1449
1450static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
1451 [IPSET_CMD_CREATE] = {
1452 .call = ip_set_create,
1453 .attr_count = IPSET_ATTR_CMD_MAX,
1454 .policy = ip_set_create_policy,
1455 },
1456 [IPSET_CMD_DESTROY] = {
1457 .call = ip_set_destroy,
1458 .attr_count = IPSET_ATTR_CMD_MAX,
1459 .policy = ip_set_setname_policy,
1460 },
1461 [IPSET_CMD_FLUSH] = {
1462 .call = ip_set_flush,
1463 .attr_count = IPSET_ATTR_CMD_MAX,
1464 .policy = ip_set_setname_policy,
1465 },
1466 [IPSET_CMD_RENAME] = {
1467 .call = ip_set_rename,
1468 .attr_count = IPSET_ATTR_CMD_MAX,
1469 .policy = ip_set_setname2_policy,
1470 },
1471 [IPSET_CMD_SWAP] = {
1472 .call = ip_set_swap,
1473 .attr_count = IPSET_ATTR_CMD_MAX,
1474 .policy = ip_set_setname2_policy,
1475 },
1476 [IPSET_CMD_LIST] = {
1477 .call = ip_set_dump,
1478 .attr_count = IPSET_ATTR_CMD_MAX,
1479 .policy = ip_set_setname_policy,
1480 },
1481 [IPSET_CMD_SAVE] = {
1482 .call = ip_set_dump,
1483 .attr_count = IPSET_ATTR_CMD_MAX,
1484 .policy = ip_set_setname_policy,
1485 },
1486 [IPSET_CMD_ADD] = {
1487 .call = ip_set_uadd,
1488 .attr_count = IPSET_ATTR_CMD_MAX,
1489 .policy = ip_set_adt_policy,
1490 },
1491 [IPSET_CMD_DEL] = {
1492 .call = ip_set_udel,
1493 .attr_count = IPSET_ATTR_CMD_MAX,
1494 .policy = ip_set_adt_policy,
1495 },
1496 [IPSET_CMD_TEST] = {
1497 .call = ip_set_utest,
1498 .attr_count = IPSET_ATTR_CMD_MAX,
1499 .policy = ip_set_adt_policy,
1500 },
1501 [IPSET_CMD_HEADER] = {
1502 .call = ip_set_header,
1503 .attr_count = IPSET_ATTR_CMD_MAX,
1504 .policy = ip_set_setname_policy,
1505 },
1506 [IPSET_CMD_TYPE] = {
1507 .call = ip_set_type,
1508 .attr_count = IPSET_ATTR_CMD_MAX,
1509 .policy = ip_set_type_policy,
1510 },
1511 [IPSET_CMD_PROTOCOL] = {
1512 .call = ip_set_protocol,
1513 .attr_count = IPSET_ATTR_CMD_MAX,
1514 .policy = ip_set_protocol_policy,
1515 },
1516};
1517
1518static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = {
1519 .name = "ip_set",
1520 .subsys_id = NFNL_SUBSYS_IPSET,
1521 .cb_count = IPSET_MSG_MAX,
1522 .cb = ip_set_netlink_subsys_cb,
1523};
1524
1525/* Interface to iptables/ip6tables */
1526
1527static int
1528ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
1529{
1530 unsigned *op;
1531 void *data;
1532 int copylen = *len, ret = 0;
1533
1534 if (!capable(CAP_NET_ADMIN))
1535 return -EPERM;
1536 if (optval != SO_IP_SET)
1537 return -EBADF;
1538 if (*len < sizeof(unsigned))
1539 return -EINVAL;
1540
1541 data = vmalloc(*len);
1542 if (!data)
1543 return -ENOMEM;
1544 if (copy_from_user(data, user, *len) != 0) {
1545 ret = -EFAULT;
1546 goto done;
1547 }
1548 op = (unsigned *) data;
1549
1550 if (*op < IP_SET_OP_VERSION) {
1551 /* Check the version at the beginning of operations */
1552 struct ip_set_req_version *req_version = data;
1553 if (req_version->version != IPSET_PROTOCOL) {
1554 ret = -EPROTO;
1555 goto done;
1556 }
1557 }
1558
1559 switch (*op) {
1560 case IP_SET_OP_VERSION: {
1561 struct ip_set_req_version *req_version = data;
1562
1563 if (*len != sizeof(struct ip_set_req_version)) {
1564 ret = -EINVAL;
1565 goto done;
1566 }
1567
1568 req_version->version = IPSET_PROTOCOL;
1569 ret = copy_to_user(user, req_version,
1570 sizeof(struct ip_set_req_version));
1571 goto done;
1572 }
1573 case IP_SET_OP_GET_BYNAME: {
1574 struct ip_set_req_get_set *req_get = data;
1575
1576 if (*len != sizeof(struct ip_set_req_get_set)) {
1577 ret = -EINVAL;
1578 goto done;
1579 }
1580 req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
1581 nfnl_lock();
1582 req_get->set.index = find_set_id(req_get->set.name);
1583 nfnl_unlock();
1584 goto copy;
1585 }
1586 case IP_SET_OP_GET_BYINDEX: {
1587 struct ip_set_req_get_set *req_get = data;
1588
1589 if (*len != sizeof(struct ip_set_req_get_set) ||
1590 req_get->set.index >= ip_set_max) {
1591 ret = -EINVAL;
1592 goto done;
1593 }
1594 nfnl_lock();
1595 strncpy(req_get->set.name,
1596 ip_set_list[req_get->set.index]
1597 ? ip_set_list[req_get->set.index]->name : "",
1598 IPSET_MAXNAMELEN);
1599 nfnl_unlock();
1600 goto copy;
1601 }
1602 default:
1603 ret = -EBADMSG;
1604 goto done;
1605 } /* end of switch(op) */
1606
1607copy:
1608 ret = copy_to_user(user, data, copylen);
1609
1610done:
1611 vfree(data);
1612 if (ret > 0)
1613 ret = 0;
1614 return ret;
1615}
1616
1617static struct nf_sockopt_ops so_set __read_mostly = {
1618 .pf = PF_INET,
1619 .get_optmin = SO_IP_SET,
1620 .get_optmax = SO_IP_SET + 1,
1621 .get = &ip_set_sockfn_get,
1622 .owner = THIS_MODULE,
1623};
1624
1625static int __init
1626ip_set_init(void)
1627{
1628 int ret;
1629
1630 if (max_sets)
1631 ip_set_max = max_sets;
1632 if (ip_set_max >= IPSET_INVALID_ID)
1633 ip_set_max = IPSET_INVALID_ID - 1;
1634
1635 ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
1636 GFP_KERNEL);
1637 if (!ip_set_list) {
1638 pr_err("ip_set: Unable to create ip_set_list\n");
1639 return -ENOMEM;
1640 }
1641
1642 ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
1643 if (ret != 0) {
1644 pr_err("ip_set: cannot register with nfnetlink.\n");
1645 kfree(ip_set_list);
1646 return ret;
1647 }
1648 ret = nf_register_sockopt(&so_set);
1649 if (ret != 0) {
1650 pr_err("SO_SET registry failed: %d\n", ret);
1651 nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
1652 kfree(ip_set_list);
1653 return ret;
1654 }
1655
1656 pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
1657 return 0;
1658}
1659
1660static void __exit
1661ip_set_fini(void)
1662{
1663 /* There can't be any existing set */
1664 nf_unregister_sockopt(&so_set);
1665 nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
1666 kfree(ip_set_list);
1667 pr_debug("these are the famous last words\n");
1668}
1669
1670module_init(ip_set_init);
1671module_exit(ip_set_fini);
diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c
new file mode 100644
index 000000000000..8d5227212686
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_getport.c
@@ -0,0 +1,141 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Get Layer-4 data from the packets */
9
10#include <linux/ip.h>
11#include <linux/skbuff.h>
12#include <linux/icmp.h>
13#include <linux/icmpv6.h>
14#include <linux/netfilter_ipv6/ip6_tables.h>
15#include <net/ip.h>
16#include <net/ipv6.h>
17
18#include <linux/netfilter/ipset/ip_set_getport.h>
19
20/* We must handle non-linear skbs */
21static bool
22get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
23 bool src, __be16 *port, u8 *proto)
24{
25 switch (protocol) {
26 case IPPROTO_TCP: {
27 struct tcphdr _tcph;
28 const struct tcphdr *th;
29
30 th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
31 if (th == NULL)
32 /* No choice either */
33 return false;
34
35 *port = src ? th->source : th->dest;
36 break;
37 }
38 case IPPROTO_UDP: {
39 struct udphdr _udph;
40 const struct udphdr *uh;
41
42 uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
43 if (uh == NULL)
44 /* No choice either */
45 return false;
46
47 *port = src ? uh->source : uh->dest;
48 break;
49 }
50 case IPPROTO_ICMP: {
51 struct icmphdr _ich;
52 const struct icmphdr *ic;
53
54 ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
55 if (ic == NULL)
56 return false;
57
58 *port = (__force __be16)htons((ic->type << 8) | ic->code);
59 break;
60 }
61 case IPPROTO_ICMPV6: {
62 struct icmp6hdr _ich;
63 const struct icmp6hdr *ic;
64
65 ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
66 if (ic == NULL)
67 return false;
68
69 *port = (__force __be16)
70 htons((ic->icmp6_type << 8) | ic->icmp6_code);
71 break;
72 }
73 default:
74 break;
75 }
76 *proto = protocol;
77
78 return true;
79}
80
81bool
82ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
83 __be16 *port, u8 *proto)
84{
85 const struct iphdr *iph = ip_hdr(skb);
86 unsigned int protooff = ip_hdrlen(skb);
87 int protocol = iph->protocol;
88
89 /* See comments at tcp_match in ip_tables.c */
90 if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
91 return false;
92
93 return get_port(skb, protocol, protooff, src, port, proto);
94}
95EXPORT_SYMBOL_GPL(ip_set_get_ip4_port);
96
97#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
98bool
99ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
100 __be16 *port, u8 *proto)
101{
102 int protoff;
103 u8 nexthdr;
104
105 nexthdr = ipv6_hdr(skb)->nexthdr;
106 protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
107 if (protoff < 0)
108 return false;
109
110 return get_port(skb, nexthdr, protoff, src, port, proto);
111}
112EXPORT_SYMBOL_GPL(ip_set_get_ip6_port);
113#endif
114
115bool
116ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
117{
118 bool ret;
119 u8 proto;
120
121 switch (pf) {
122 case AF_INET:
123 ret = ip_set_get_ip4_port(skb, src, port, &proto);
124 break;
125 case AF_INET6:
126 ret = ip_set_get_ip6_port(skb, src, port, &proto);
127 break;
128 default:
129 return false;
130 }
131 if (!ret)
132 return ret;
133 switch (proto) {
134 case IPPROTO_TCP:
135 case IPPROTO_UDP:
136 return true;
137 default:
138 return false;
139 }
140}
141EXPORT_SYMBOL_GPL(ip_set_get_ip_port);
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
new file mode 100644
index 000000000000..43bcce200129
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -0,0 +1,464 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:ip type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19#include <net/tcp.h>
20
21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.h>
24#include <linux/netfilter/ipset/ip_set_timeout.h>
25#include <linux/netfilter/ipset/ip_set_hash.h>
26
27MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29MODULE_DESCRIPTION("hash:ip type of IP sets");
30MODULE_ALIAS("ip_set_hash:ip");
31
32/* Type specific function prefix */
33#define TYPE hash_ip
34
35static bool
36hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
37
38#define hash_ip4_same_set hash_ip_same_set
39#define hash_ip6_same_set hash_ip_same_set
40
41/* The type variant functions: IPv4 */
42
43/* Member elements without timeout */
44struct hash_ip4_elem {
45 __be32 ip;
46};
47
48/* Member elements with timeout support */
49struct hash_ip4_telem {
50 __be32 ip;
51 unsigned long timeout;
52};
53
54static inline bool
55hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
56 const struct hash_ip4_elem *ip2)
57{
58 return ip1->ip == ip2->ip;
59}
60
61static inline bool
62hash_ip4_data_isnull(const struct hash_ip4_elem *elem)
63{
64 return elem->ip == 0;
65}
66
67static inline void
68hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
69{
70 dst->ip = src->ip;
71}
72
73/* Zero valued IP addresses cannot be stored */
74static inline void
75hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
76{
77 elem->ip = 0;
78}
79
80static inline bool
81hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data)
82{
83 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
84 return 0;
85
86nla_put_failure:
87 return 1;
88}
89
90static bool
91hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
92{
93 const struct hash_ip4_telem *tdata =
94 (const struct hash_ip4_telem *)data;
95
96 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
97 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
98 htonl(ip_set_timeout_get(tdata->timeout)));
99
100 return 0;
101
102nla_put_failure:
103 return 1;
104}
105
106#define IP_SET_HASH_WITH_NETMASK
107#define PF 4
108#define HOST_MASK 32
109#include <linux/netfilter/ipset/ip_set_ahash.h>
110
111static int
112hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
113 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
114{
115 const struct ip_set_hash *h = set->data;
116 ipset_adtfn adtfn = set->variant->adt[adt];
117 __be32 ip;
118
119 ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
120 ip &= ip_set_netmask(h->netmask);
121 if (ip == 0)
122 return -EINVAL;
123
124 return adtfn(set, &ip, h->timeout);
125}
126
127static int
128hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
129 enum ipset_adt adt, u32 *lineno, u32 flags)
130{
131 const struct ip_set_hash *h = set->data;
132 ipset_adtfn adtfn = set->variant->adt[adt];
133 u32 ip, ip_to, hosts, timeout = h->timeout;
134 __be32 nip;
135 int ret = 0;
136
137 if (unlikely(!tb[IPSET_ATTR_IP] ||
138 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
139 return -IPSET_ERR_PROTOCOL;
140
141 if (tb[IPSET_ATTR_LINENO])
142 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
143
144 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
145 if (ret)
146 return ret;
147
148 ip &= ip_set_hostmask(h->netmask);
149
150 if (tb[IPSET_ATTR_TIMEOUT]) {
151 if (!with_timeout(h->timeout))
152 return -IPSET_ERR_TIMEOUT;
153 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
154 }
155
156 if (adt == IPSET_TEST) {
157 nip = htonl(ip);
158 if (nip == 0)
159 return -IPSET_ERR_HASH_ELEM;
160 return adtfn(set, &nip, timeout);
161 }
162
163 if (tb[IPSET_ATTR_IP_TO]) {
164 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
165 if (ret)
166 return ret;
167 if (ip > ip_to)
168 swap(ip, ip_to);
169 } else if (tb[IPSET_ATTR_CIDR]) {
170 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
171
172 if (cidr > 32)
173 return -IPSET_ERR_INVALID_CIDR;
174 ip &= ip_set_hostmask(cidr);
175 ip_to = ip | ~ip_set_hostmask(cidr);
176 } else
177 ip_to = ip;
178
179 hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
180
181 for (; !before(ip_to, ip); ip += hosts) {
182 nip = htonl(ip);
183 if (nip == 0)
184 return -IPSET_ERR_HASH_ELEM;
185 ret = adtfn(set, &nip, timeout);
186
187 if (ret && !ip_set_eexist(ret, flags))
188 return ret;
189 else
190 ret = 0;
191 }
192 return ret;
193}
194
195static bool
196hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
197{
198 const struct ip_set_hash *x = a->data;
199 const struct ip_set_hash *y = b->data;
200
201 /* Resizing changes htable_bits, so we ignore it */
202 return x->maxelem == y->maxelem &&
203 x->timeout == y->timeout &&
204 x->netmask == y->netmask;
205}
206
207/* The type variant functions: IPv6 */
208
209struct hash_ip6_elem {
210 union nf_inet_addr ip;
211};
212
213struct hash_ip6_telem {
214 union nf_inet_addr ip;
215 unsigned long timeout;
216};
217
218static inline bool
219hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
220 const struct hash_ip6_elem *ip2)
221{
222 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
223}
224
225static inline bool
226hash_ip6_data_isnull(const struct hash_ip6_elem *elem)
227{
228 return ipv6_addr_any(&elem->ip.in6);
229}
230
231static inline void
232hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
233{
234 ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
235}
236
237static inline void
238hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
239{
240 ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0);
241}
242
243static inline void
244ip6_netmask(union nf_inet_addr *ip, u8 prefix)
245{
246 ip->ip6[0] &= ip_set_netmask6(prefix)[0];
247 ip->ip6[1] &= ip_set_netmask6(prefix)[1];
248 ip->ip6[2] &= ip_set_netmask6(prefix)[2];
249 ip->ip6[3] &= ip_set_netmask6(prefix)[3];
250}
251
252static bool
253hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
254{
255 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
256 return 0;
257
258nla_put_failure:
259 return 1;
260}
261
262static bool
263hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
264{
265 const struct hash_ip6_telem *e =
266 (const struct hash_ip6_telem *)data;
267
268 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
269 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
270 htonl(ip_set_timeout_get(e->timeout)));
271 return 0;
272
273nla_put_failure:
274 return 1;
275}
276
277#undef PF
278#undef HOST_MASK
279
280#define PF 6
281#define HOST_MASK 128
282#include <linux/netfilter/ipset/ip_set_ahash.h>
283
284static int
285hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
286 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
287{
288 const struct ip_set_hash *h = set->data;
289 ipset_adtfn adtfn = set->variant->adt[adt];
290 union nf_inet_addr ip;
291
292 ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6);
293 ip6_netmask(&ip, h->netmask);
294 if (ipv6_addr_any(&ip.in6))
295 return -EINVAL;
296
297 return adtfn(set, &ip, h->timeout);
298}
299
300static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
301 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
302 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
303 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
304};
305
306static int
307hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
308 enum ipset_adt adt, u32 *lineno, u32 flags)
309{
310 const struct ip_set_hash *h = set->data;
311 ipset_adtfn adtfn = set->variant->adt[adt];
312 union nf_inet_addr ip;
313 u32 timeout = h->timeout;
314 int ret;
315
316 if (unlikely(!tb[IPSET_ATTR_IP] ||
317 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
318 tb[IPSET_ATTR_IP_TO] ||
319 tb[IPSET_ATTR_CIDR]))
320 return -IPSET_ERR_PROTOCOL;
321
322 if (tb[IPSET_ATTR_LINENO])
323 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
324
325 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip);
326 if (ret)
327 return ret;
328
329 ip6_netmask(&ip, h->netmask);
330 if (ipv6_addr_any(&ip.in6))
331 return -IPSET_ERR_HASH_ELEM;
332
333 if (tb[IPSET_ATTR_TIMEOUT]) {
334 if (!with_timeout(h->timeout))
335 return -IPSET_ERR_TIMEOUT;
336 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
337 }
338
339 ret = adtfn(set, &ip, timeout);
340
341 return ip_set_eexist(ret, flags) ? 0 : ret;
342}
343
344/* Create hash:ip type of sets */
345
346static int
347hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
348{
349 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
350 u8 netmask, hbits;
351 struct ip_set_hash *h;
352
353 if (!(set->family == AF_INET || set->family == AF_INET6))
354 return -IPSET_ERR_INVALID_FAMILY;
355 netmask = set->family == AF_INET ? 32 : 128;
356 pr_debug("Create set %s with family %s\n",
357 set->name, set->family == AF_INET ? "inet" : "inet6");
358
359 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
360 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
361 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
362 return -IPSET_ERR_PROTOCOL;
363
364 if (tb[IPSET_ATTR_HASHSIZE]) {
365 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
366 if (hashsize < IPSET_MIMINAL_HASHSIZE)
367 hashsize = IPSET_MIMINAL_HASHSIZE;
368 }
369
370 if (tb[IPSET_ATTR_MAXELEM])
371 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
372
373 if (tb[IPSET_ATTR_NETMASK]) {
374 netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
375
376 if ((set->family == AF_INET && netmask > 32) ||
377 (set->family == AF_INET6 && netmask > 128) ||
378 netmask == 0)
379 return -IPSET_ERR_INVALID_NETMASK;
380 }
381
382 h = kzalloc(sizeof(*h), GFP_KERNEL);
383 if (!h)
384 return -ENOMEM;
385
386 h->maxelem = maxelem;
387 h->netmask = netmask;
388 get_random_bytes(&h->initval, sizeof(h->initval));
389 h->timeout = IPSET_NO_TIMEOUT;
390
391 hbits = htable_bits(hashsize);
392 h->table = ip_set_alloc(
393 sizeof(struct htable)
394 + jhash_size(hbits) * sizeof(struct hbucket));
395 if (!h->table) {
396 kfree(h);
397 return -ENOMEM;
398 }
399 h->table->htable_bits = hbits;
400
401 set->data = h;
402
403 if (tb[IPSET_ATTR_TIMEOUT]) {
404 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
405
406 set->variant = set->family == AF_INET
407 ? &hash_ip4_tvariant : &hash_ip6_tvariant;
408
409 if (set->family == AF_INET)
410 hash_ip4_gc_init(set);
411 else
412 hash_ip6_gc_init(set);
413 } else {
414 set->variant = set->family == AF_INET
415 ? &hash_ip4_variant : &hash_ip6_variant;
416 }
417
418 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
419 set->name, jhash_size(h->table->htable_bits),
420 h->table->htable_bits, h->maxelem, set->data, h->table);
421
422 return 0;
423}
424
425static struct ip_set_type hash_ip_type __read_mostly = {
426 .name = "hash:ip",
427 .protocol = IPSET_PROTOCOL,
428 .features = IPSET_TYPE_IP,
429 .dimension = IPSET_DIM_ONE,
430 .family = AF_UNSPEC,
431 .revision = 0,
432 .create = hash_ip_create,
433 .create_policy = {
434 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
435 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
436 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
437 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
438 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
439 [IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
440 },
441 .adt_policy = {
442 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
443 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
444 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
445 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
446 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
447 },
448 .me = THIS_MODULE,
449};
450
451static int __init
452hash_ip_init(void)
453{
454 return ip_set_type_register(&hash_ip_type);
455}
456
457static void __exit
458hash_ip_fini(void)
459{
460 ip_set_type_unregister(&hash_ip_type);
461}
462
463module_init(hash_ip_init);
464module_exit(hash_ip_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
new file mode 100644
index 000000000000..adbe787ea5dc
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -0,0 +1,544 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:ip,port type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19#include <net/tcp.h>
20
21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.h>
24#include <linux/netfilter/ipset/ip_set_timeout.h>
25#include <linux/netfilter/ipset/ip_set_getport.h>
26#include <linux/netfilter/ipset/ip_set_hash.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30MODULE_DESCRIPTION("hash:ip,port type of IP sets");
31MODULE_ALIAS("ip_set_hash:ip,port");
32
33/* Type specific function prefix */
34#define TYPE hash_ipport
35
36static bool
37hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
38
39#define hash_ipport4_same_set hash_ipport_same_set
40#define hash_ipport6_same_set hash_ipport_same_set
41
42/* The type variant functions: IPv4 */
43
44/* Member elements without timeout */
45struct hash_ipport4_elem {
46 __be32 ip;
47 __be16 port;
48 u8 proto;
49 u8 padding;
50};
51
52/* Member elements with timeout support */
53struct hash_ipport4_telem {
54 __be32 ip;
55 __be16 port;
56 u8 proto;
57 u8 padding;
58 unsigned long timeout;
59};
60
61static inline bool
62hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
63 const struct hash_ipport4_elem *ip2)
64{
65 return ip1->ip == ip2->ip &&
66 ip1->port == ip2->port &&
67 ip1->proto == ip2->proto;
68}
69
70static inline bool
71hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
72{
73 return elem->proto == 0;
74}
75
76static inline void
77hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
78 const struct hash_ipport4_elem *src)
79{
80 dst->ip = src->ip;
81 dst->port = src->port;
82 dst->proto = src->proto;
83}
84
85static inline void
86hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
87{
88 elem->proto = 0;
89}
90
91static bool
92hash_ipport4_data_list(struct sk_buff *skb,
93 const struct hash_ipport4_elem *data)
94{
95 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
96 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
97 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
98 return 0;
99
100nla_put_failure:
101 return 1;
102}
103
104static bool
105hash_ipport4_data_tlist(struct sk_buff *skb,
106 const struct hash_ipport4_elem *data)
107{
108 const struct hash_ipport4_telem *tdata =
109 (const struct hash_ipport4_telem *)data;
110
111 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
112 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
113 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
114 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
115 htonl(ip_set_timeout_get(tdata->timeout)));
116
117 return 0;
118
119nla_put_failure:
120 return 1;
121}
122
123#define PF 4
124#define HOST_MASK 32
125#include <linux/netfilter/ipset/ip_set_ahash.h>
126
127static int
128hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
129 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
130{
131 const struct ip_set_hash *h = set->data;
132 ipset_adtfn adtfn = set->variant->adt[adt];
133 struct hash_ipport4_elem data = { };
134
135 if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
136 &data.port, &data.proto))
137 return -EINVAL;
138
139 ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
140
141 return adtfn(set, &data, h->timeout);
142}
143
144static int
145hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
146 enum ipset_adt adt, u32 *lineno, u32 flags)
147{
148 const struct ip_set_hash *h = set->data;
149 ipset_adtfn adtfn = set->variant->adt[adt];
150 struct hash_ipport4_elem data = { };
151 u32 ip, ip_to, p, port, port_to;
152 u32 timeout = h->timeout;
153 int ret;
154
155 if (unlikely(!tb[IPSET_ATTR_IP] ||
156 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
157 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
158 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
159 return -IPSET_ERR_PROTOCOL;
160
161 if (tb[IPSET_ATTR_LINENO])
162 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
163
164 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
165 if (ret)
166 return ret;
167
168 if (tb[IPSET_ATTR_PORT])
169 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
170 else
171 return -IPSET_ERR_PROTOCOL;
172
173 if (tb[IPSET_ATTR_PROTO]) {
174 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
175
176 if (data.proto == 0)
177 return -IPSET_ERR_INVALID_PROTO;
178 } else
179 return -IPSET_ERR_MISSING_PROTO;
180
181 switch (data.proto) {
182 case IPPROTO_UDP:
183 case IPPROTO_TCP:
184 case IPPROTO_ICMP:
185 break;
186 default:
187 data.port = 0;
188 break;
189 }
190
191 if (tb[IPSET_ATTR_TIMEOUT]) {
192 if (!with_timeout(h->timeout))
193 return -IPSET_ERR_TIMEOUT;
194 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
195 }
196
197 if (adt == IPSET_TEST ||
198 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
199 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
200 tb[IPSET_ATTR_PORT_TO])) {
201 ret = adtfn(set, &data, timeout);
202 return ip_set_eexist(ret, flags) ? 0 : ret;
203 }
204
205 ip = ntohl(data.ip);
206 if (tb[IPSET_ATTR_IP_TO]) {
207 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
208 if (ret)
209 return ret;
210 if (ip > ip_to)
211 swap(ip, ip_to);
212 } else if (tb[IPSET_ATTR_CIDR]) {
213 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
214
215 if (cidr > 32)
216 return -IPSET_ERR_INVALID_CIDR;
217 ip &= ip_set_hostmask(cidr);
218 ip_to = ip | ~ip_set_hostmask(cidr);
219 } else
220 ip_to = ip;
221
222 port = ntohs(data.port);
223 if (tb[IPSET_ATTR_PORT_TO]) {
224 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
225 if (port > port_to)
226 swap(port, port_to);
227 } else
228 port_to = port;
229
230 for (; !before(ip_to, ip); ip++)
231 for (p = port; p <= port_to; p++) {
232 data.ip = htonl(ip);
233 data.port = htons(p);
234 ret = adtfn(set, &data, timeout);
235
236 if (ret && !ip_set_eexist(ret, flags))
237 return ret;
238 else
239 ret = 0;
240 }
241 return ret;
242}
243
244static bool
245hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
246{
247 const struct ip_set_hash *x = a->data;
248 const struct ip_set_hash *y = b->data;
249
250 /* Resizing changes htable_bits, so we ignore it */
251 return x->maxelem == y->maxelem &&
252 x->timeout == y->timeout;
253}
254
255/* The type variant functions: IPv6 */
256
257struct hash_ipport6_elem {
258 union nf_inet_addr ip;
259 __be16 port;
260 u8 proto;
261 u8 padding;
262};
263
264struct hash_ipport6_telem {
265 union nf_inet_addr ip;
266 __be16 port;
267 u8 proto;
268 u8 padding;
269 unsigned long timeout;
270};
271
272static inline bool
273hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
274 const struct hash_ipport6_elem *ip2)
275{
276 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
277 ip1->port == ip2->port &&
278 ip1->proto == ip2->proto;
279}
280
281static inline bool
282hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
283{
284 return elem->proto == 0;
285}
286
287static inline void
288hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
289 const struct hash_ipport6_elem *src)
290{
291 memcpy(dst, src, sizeof(*dst));
292}
293
294static inline void
295hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
296{
297 elem->proto = 0;
298}
299
300static bool
301hash_ipport6_data_list(struct sk_buff *skb,
302 const struct hash_ipport6_elem *data)
303{
304 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
305 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
306 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
307 return 0;
308
309nla_put_failure:
310 return 1;
311}
312
313static bool
314hash_ipport6_data_tlist(struct sk_buff *skb,
315 const struct hash_ipport6_elem *data)
316{
317 const struct hash_ipport6_telem *e =
318 (const struct hash_ipport6_telem *)data;
319
320 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
321 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
322 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
323 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
324 htonl(ip_set_timeout_get(e->timeout)));
325 return 0;
326
327nla_put_failure:
328 return 1;
329}
330
331#undef PF
332#undef HOST_MASK
333
334#define PF 6
335#define HOST_MASK 128
336#include <linux/netfilter/ipset/ip_set_ahash.h>
337
338static int
339hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
340 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
341{
342 const struct ip_set_hash *h = set->data;
343 ipset_adtfn adtfn = set->variant->adt[adt];
344 struct hash_ipport6_elem data = { };
345
346 if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
347 &data.port, &data.proto))
348 return -EINVAL;
349
350 ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
351
352 return adtfn(set, &data, h->timeout);
353}
354
355static int
356hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
357 enum ipset_adt adt, u32 *lineno, u32 flags)
358{
359 const struct ip_set_hash *h = set->data;
360 ipset_adtfn adtfn = set->variant->adt[adt];
361 struct hash_ipport6_elem data = { };
362 u32 port, port_to;
363 u32 timeout = h->timeout;
364 int ret;
365
366 if (unlikely(!tb[IPSET_ATTR_IP] ||
367 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
368 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
369 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
370 tb[IPSET_ATTR_IP_TO] ||
371 tb[IPSET_ATTR_CIDR]))
372 return -IPSET_ERR_PROTOCOL;
373
374 if (tb[IPSET_ATTR_LINENO])
375 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
376
377 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
378 if (ret)
379 return ret;
380
381 if (tb[IPSET_ATTR_PORT])
382 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
383 else
384 return -IPSET_ERR_PROTOCOL;
385
386 if (tb[IPSET_ATTR_PROTO]) {
387 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
388
389 if (data.proto == 0)
390 return -IPSET_ERR_INVALID_PROTO;
391 } else
392 return -IPSET_ERR_MISSING_PROTO;
393
394 switch (data.proto) {
395 case IPPROTO_UDP:
396 case IPPROTO_TCP:
397 case IPPROTO_ICMPV6:
398 break;
399 default:
400 data.port = 0;
401 break;
402 }
403
404 if (tb[IPSET_ATTR_TIMEOUT]) {
405 if (!with_timeout(h->timeout))
406 return -IPSET_ERR_TIMEOUT;
407 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
408 }
409
410 if (adt == IPSET_TEST ||
411 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
412 !tb[IPSET_ATTR_PORT_TO]) {
413 ret = adtfn(set, &data, timeout);
414 return ip_set_eexist(ret, flags) ? 0 : ret;
415 }
416
417 port = ntohs(data.port);
418 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
419 if (port > port_to)
420 swap(port, port_to);
421
422 for (; port <= port_to; port++) {
423 data.port = htons(port);
424 ret = adtfn(set, &data, timeout);
425
426 if (ret && !ip_set_eexist(ret, flags))
427 return ret;
428 else
429 ret = 0;
430 }
431 return ret;
432}
433
434/* Create hash:ip type of sets */
435
436static int
437hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
438{
439 struct ip_set_hash *h;
440 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
441 u8 hbits;
442
443 if (!(set->family == AF_INET || set->family == AF_INET6))
444 return -IPSET_ERR_INVALID_FAMILY;
445
446 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
447 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
448 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
449 return -IPSET_ERR_PROTOCOL;
450
451 if (tb[IPSET_ATTR_HASHSIZE]) {
452 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
453 if (hashsize < IPSET_MIMINAL_HASHSIZE)
454 hashsize = IPSET_MIMINAL_HASHSIZE;
455 }
456
457 if (tb[IPSET_ATTR_MAXELEM])
458 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
459
460 h = kzalloc(sizeof(*h), GFP_KERNEL);
461 if (!h)
462 return -ENOMEM;
463
464 h->maxelem = maxelem;
465 get_random_bytes(&h->initval, sizeof(h->initval));
466 h->timeout = IPSET_NO_TIMEOUT;
467
468 hbits = htable_bits(hashsize);
469 h->table = ip_set_alloc(
470 sizeof(struct htable)
471 + jhash_size(hbits) * sizeof(struct hbucket));
472 if (!h->table) {
473 kfree(h);
474 return -ENOMEM;
475 }
476 h->table->htable_bits = hbits;
477
478 set->data = h;
479
480 if (tb[IPSET_ATTR_TIMEOUT]) {
481 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
482
483 set->variant = set->family == AF_INET
484 ? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
485
486 if (set->family == AF_INET)
487 hash_ipport4_gc_init(set);
488 else
489 hash_ipport6_gc_init(set);
490 } else {
491 set->variant = set->family == AF_INET
492 ? &hash_ipport4_variant : &hash_ipport6_variant;
493 }
494
495 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
496 set->name, jhash_size(h->table->htable_bits),
497 h->table->htable_bits, h->maxelem, set->data, h->table);
498
499 return 0;
500}
501
502static struct ip_set_type hash_ipport_type __read_mostly = {
503 .name = "hash:ip,port",
504 .protocol = IPSET_PROTOCOL,
505 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
506 .dimension = IPSET_DIM_TWO,
507 .family = AF_UNSPEC,
508 .revision = 0,
509 .create = hash_ipport_create,
510 .create_policy = {
511 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
512 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
513 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
514 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
515 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
516 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
517 },
518 .adt_policy = {
519 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
520 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
521 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
522 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
523 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
524 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
525 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
526 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
527 },
528 .me = THIS_MODULE,
529};
530
531static int __init
532hash_ipport_init(void)
533{
534 return ip_set_type_register(&hash_ipport_type);
535}
536
537static void __exit
538hash_ipport_fini(void)
539{
540 ip_set_type_unregister(&hash_ipport_type);
541}
542
543module_init(hash_ipport_init);
544module_exit(hash_ipport_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
new file mode 100644
index 000000000000..22e23abb86c6
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -0,0 +1,562 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19#include <net/tcp.h>
20
21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.h>
24#include <linux/netfilter/ipset/ip_set_timeout.h>
25#include <linux/netfilter/ipset/ip_set_getport.h>
26#include <linux/netfilter/ipset/ip_set_hash.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
31MODULE_ALIAS("ip_set_hash:ip,port,ip");
32
33/* Type specific function prefix */
34#define TYPE hash_ipportip
35
36static bool
37hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
38
39#define hash_ipportip4_same_set hash_ipportip_same_set
40#define hash_ipportip6_same_set hash_ipportip_same_set
41
42/* The type variant functions: IPv4 */
43
44/* Member elements without timeout */
45struct hash_ipportip4_elem {
46 __be32 ip;
47 __be32 ip2;
48 __be16 port;
49 u8 proto;
50 u8 padding;
51};
52
53/* Member elements with timeout support */
54struct hash_ipportip4_telem {
55 __be32 ip;
56 __be32 ip2;
57 __be16 port;
58 u8 proto;
59 u8 padding;
60 unsigned long timeout;
61};
62
63static inline bool
64hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
65 const struct hash_ipportip4_elem *ip2)
66{
67 return ip1->ip == ip2->ip &&
68 ip1->ip2 == ip2->ip2 &&
69 ip1->port == ip2->port &&
70 ip1->proto == ip2->proto;
71}
72
73static inline bool
74hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
75{
76 return elem->proto == 0;
77}
78
79static inline void
80hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
81 const struct hash_ipportip4_elem *src)
82{
83 memcpy(dst, src, sizeof(*dst));
84}
85
86static inline void
87hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
88{
89 elem->proto = 0;
90}
91
92static bool
93hash_ipportip4_data_list(struct sk_buff *skb,
94 const struct hash_ipportip4_elem *data)
95{
96 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
97 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
98 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
99 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
100 return 0;
101
102nla_put_failure:
103 return 1;
104}
105
106static bool
107hash_ipportip4_data_tlist(struct sk_buff *skb,
108 const struct hash_ipportip4_elem *data)
109{
110 const struct hash_ipportip4_telem *tdata =
111 (const struct hash_ipportip4_telem *)data;
112
113 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
114 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
115 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
116 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
117 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
118 htonl(ip_set_timeout_get(tdata->timeout)));
119
120 return 0;
121
122nla_put_failure:
123 return 1;
124}
125
126#define PF 4
127#define HOST_MASK 32
128#include <linux/netfilter/ipset/ip_set_ahash.h>
129
130static int
131hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
132 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
133{
134 const struct ip_set_hash *h = set->data;
135 ipset_adtfn adtfn = set->variant->adt[adt];
136 struct hash_ipportip4_elem data = { };
137
138 if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
139 &data.port, &data.proto))
140 return -EINVAL;
141
142 ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
143 ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
144
145 return adtfn(set, &data, h->timeout);
146}
147
148static int
149hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
150 enum ipset_adt adt, u32 *lineno, u32 flags)
151{
152 const struct ip_set_hash *h = set->data;
153 ipset_adtfn adtfn = set->variant->adt[adt];
154 struct hash_ipportip4_elem data = { };
155 u32 ip, ip_to, p, port, port_to;
156 u32 timeout = h->timeout;
157 int ret;
158
159 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
160 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
161 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
162 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
163 return -IPSET_ERR_PROTOCOL;
164
165 if (tb[IPSET_ATTR_LINENO])
166 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
167
168 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
169 if (ret)
170 return ret;
171
172 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
173 if (ret)
174 return ret;
175
176 if (tb[IPSET_ATTR_PORT])
177 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
178 else
179 return -IPSET_ERR_PROTOCOL;
180
181 if (tb[IPSET_ATTR_PROTO]) {
182 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
183
184 if (data.proto == 0)
185 return -IPSET_ERR_INVALID_PROTO;
186 } else
187 return -IPSET_ERR_MISSING_PROTO;
188
189 switch (data.proto) {
190 case IPPROTO_UDP:
191 case IPPROTO_TCP:
192 case IPPROTO_ICMP:
193 break;
194 default:
195 data.port = 0;
196 break;
197 }
198
199 if (tb[IPSET_ATTR_TIMEOUT]) {
200 if (!with_timeout(h->timeout))
201 return -IPSET_ERR_TIMEOUT;
202 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
203 }
204
205 if (adt == IPSET_TEST ||
206 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
207 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
208 tb[IPSET_ATTR_PORT_TO])) {
209 ret = adtfn(set, &data, timeout);
210 return ip_set_eexist(ret, flags) ? 0 : ret;
211 }
212
213 ip = ntohl(data.ip);
214 if (tb[IPSET_ATTR_IP_TO]) {
215 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
216 if (ret)
217 return ret;
218 if (ip > ip_to)
219 swap(ip, ip_to);
220 } else if (tb[IPSET_ATTR_CIDR]) {
221 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
222
223 if (cidr > 32)
224 return -IPSET_ERR_INVALID_CIDR;
225 ip &= ip_set_hostmask(cidr);
226 ip_to = ip | ~ip_set_hostmask(cidr);
227 } else
228 ip_to = ip;
229
230 port = ntohs(data.port);
231 if (tb[IPSET_ATTR_PORT_TO]) {
232 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
233 if (port > port_to)
234 swap(port, port_to);
235 } else
236 port_to = port;
237
238 for (; !before(ip_to, ip); ip++)
239 for (p = port; p <= port_to; p++) {
240 data.ip = htonl(ip);
241 data.port = htons(p);
242 ret = adtfn(set, &data, timeout);
243
244 if (ret && !ip_set_eexist(ret, flags))
245 return ret;
246 else
247 ret = 0;
248 }
249 return ret;
250}
251
252static bool
253hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
254{
255 const struct ip_set_hash *x = a->data;
256 const struct ip_set_hash *y = b->data;
257
258 /* Resizing changes htable_bits, so we ignore it */
259 return x->maxelem == y->maxelem &&
260 x->timeout == y->timeout;
261}
262
263/* The type variant functions: IPv6 */
264
265struct hash_ipportip6_elem {
266 union nf_inet_addr ip;
267 union nf_inet_addr ip2;
268 __be16 port;
269 u8 proto;
270 u8 padding;
271};
272
273struct hash_ipportip6_telem {
274 union nf_inet_addr ip;
275 union nf_inet_addr ip2;
276 __be16 port;
277 u8 proto;
278 u8 padding;
279 unsigned long timeout;
280};
281
282static inline bool
283hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
284 const struct hash_ipportip6_elem *ip2)
285{
286 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
287 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
288 ip1->port == ip2->port &&
289 ip1->proto == ip2->proto;
290}
291
292static inline bool
293hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
294{
295 return elem->proto == 0;
296}
297
298static inline void
299hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
300 const struct hash_ipportip6_elem *src)
301{
302 memcpy(dst, src, sizeof(*dst));
303}
304
305static inline void
306hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
307{
308 elem->proto = 0;
309}
310
311static bool
312hash_ipportip6_data_list(struct sk_buff *skb,
313 const struct hash_ipportip6_elem *data)
314{
315 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
316 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
317 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
318 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
319 return 0;
320
321nla_put_failure:
322 return 1;
323}
324
325static bool
326hash_ipportip6_data_tlist(struct sk_buff *skb,
327 const struct hash_ipportip6_elem *data)
328{
329 const struct hash_ipportip6_telem *e =
330 (const struct hash_ipportip6_telem *)data;
331
332 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
333 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
334 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
335 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
336 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
337 htonl(ip_set_timeout_get(e->timeout)));
338 return 0;
339
340nla_put_failure:
341 return 1;
342}
343
344#undef PF
345#undef HOST_MASK
346
347#define PF 6
348#define HOST_MASK 128
349#include <linux/netfilter/ipset/ip_set_ahash.h>
350
351static int
352hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
353 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
354{
355 const struct ip_set_hash *h = set->data;
356 ipset_adtfn adtfn = set->variant->adt[adt];
357 struct hash_ipportip6_elem data = { };
358
359 if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
360 &data.port, &data.proto))
361 return -EINVAL;
362
363 ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
364 ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
365
366 return adtfn(set, &data, h->timeout);
367}
368
369static int
370hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
371 enum ipset_adt adt, u32 *lineno, u32 flags)
372{
373 const struct ip_set_hash *h = set->data;
374 ipset_adtfn adtfn = set->variant->adt[adt];
375 struct hash_ipportip6_elem data = { };
376 u32 port, port_to;
377 u32 timeout = h->timeout;
378 int ret;
379
380 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
381 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
382 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
383 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
384 tb[IPSET_ATTR_IP_TO] ||
385 tb[IPSET_ATTR_CIDR]))
386 return -IPSET_ERR_PROTOCOL;
387
388 if (tb[IPSET_ATTR_LINENO])
389 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
390
391 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
392 if (ret)
393 return ret;
394
395 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
396 if (ret)
397 return ret;
398
399 if (tb[IPSET_ATTR_PORT])
400 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
401 else
402 return -IPSET_ERR_PROTOCOL;
403
404 if (tb[IPSET_ATTR_PROTO]) {
405 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
406
407 if (data.proto == 0)
408 return -IPSET_ERR_INVALID_PROTO;
409 } else
410 return -IPSET_ERR_MISSING_PROTO;
411
412 switch (data.proto) {
413 case IPPROTO_UDP:
414 case IPPROTO_TCP:
415 case IPPROTO_ICMPV6:
416 break;
417 default:
418 data.port = 0;
419 break;
420 }
421
422 if (tb[IPSET_ATTR_TIMEOUT]) {
423 if (!with_timeout(h->timeout))
424 return -IPSET_ERR_TIMEOUT;
425 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
426 }
427
428 if (adt == IPSET_TEST ||
429 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
430 !tb[IPSET_ATTR_PORT_TO]) {
431 ret = adtfn(set, &data, timeout);
432 return ip_set_eexist(ret, flags) ? 0 : ret;
433 }
434
435 port = ntohs(data.port);
436 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
437 if (port > port_to)
438 swap(port, port_to);
439
440 for (; port <= port_to; port++) {
441 data.port = htons(port);
442 ret = adtfn(set, &data, timeout);
443
444 if (ret && !ip_set_eexist(ret, flags))
445 return ret;
446 else
447 ret = 0;
448 }
449 return ret;
450}
451
452/* Create hash:ip type of sets */
453
454static int
455hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
456{
457 struct ip_set_hash *h;
458 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
459 u8 hbits;
460
461 if (!(set->family == AF_INET || set->family == AF_INET6))
462 return -IPSET_ERR_INVALID_FAMILY;
463
464 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
465 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
466 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
467 return -IPSET_ERR_PROTOCOL;
468
469 if (tb[IPSET_ATTR_HASHSIZE]) {
470 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
471 if (hashsize < IPSET_MIMINAL_HASHSIZE)
472 hashsize = IPSET_MIMINAL_HASHSIZE;
473 }
474
475 if (tb[IPSET_ATTR_MAXELEM])
476 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
477
478 h = kzalloc(sizeof(*h), GFP_KERNEL);
479 if (!h)
480 return -ENOMEM;
481
482 h->maxelem = maxelem;
483 get_random_bytes(&h->initval, sizeof(h->initval));
484 h->timeout = IPSET_NO_TIMEOUT;
485
486 hbits = htable_bits(hashsize);
487 h->table = ip_set_alloc(
488 sizeof(struct htable)
489 + jhash_size(hbits) * sizeof(struct hbucket));
490 if (!h->table) {
491 kfree(h);
492 return -ENOMEM;
493 }
494 h->table->htable_bits = hbits;
495
496 set->data = h;
497
498 if (tb[IPSET_ATTR_TIMEOUT]) {
499 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
500
501 set->variant = set->family == AF_INET
502 ? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
503
504 if (set->family == AF_INET)
505 hash_ipportip4_gc_init(set);
506 else
507 hash_ipportip6_gc_init(set);
508 } else {
509 set->variant = set->family == AF_INET
510 ? &hash_ipportip4_variant : &hash_ipportip6_variant;
511 }
512
513 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
514 set->name, jhash_size(h->table->htable_bits),
515 h->table->htable_bits, h->maxelem, set->data, h->table);
516
517 return 0;
518}
519
520static struct ip_set_type hash_ipportip_type __read_mostly = {
521 .name = "hash:ip,port,ip",
522 .protocol = IPSET_PROTOCOL,
523 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
524 .dimension = IPSET_DIM_THREE,
525 .family = AF_UNSPEC,
526 .revision = 0,
527 .create = hash_ipportip_create,
528 .create_policy = {
529 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
530 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
531 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
532 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
533 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
534 },
535 .adt_policy = {
536 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
537 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
538 [IPSET_ATTR_IP2] = { .type = NLA_NESTED },
539 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
540 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
541 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
542 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
543 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
544 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
545 },
546 .me = THIS_MODULE,
547};
548
549static int __init
550hash_ipportip_init(void)
551{
552 return ip_set_type_register(&hash_ipportip_type);
553}
554
555static void __exit
556hash_ipportip_fini(void)
557{
558 ip_set_type_unregister(&hash_ipportip_type);
559}
560
561module_init(hash_ipportip_init);
562module_exit(hash_ipportip_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
new file mode 100644
index 000000000000..6033e8b54bbd
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -0,0 +1,628 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:ip,port,net type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19#include <net/tcp.h>
20
21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.h>
24#include <linux/netfilter/ipset/ip_set_timeout.h>
25#include <linux/netfilter/ipset/ip_set_getport.h>
26#include <linux/netfilter/ipset/ip_set_hash.h>
27
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
31MODULE_ALIAS("ip_set_hash:ip,port,net");
32
33/* Type specific function prefix */
34#define TYPE hash_ipportnet
35
36static bool
37hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
38
39#define hash_ipportnet4_same_set hash_ipportnet_same_set
40#define hash_ipportnet6_same_set hash_ipportnet_same_set
41
42/* The type variant functions: IPv4 */
43
44/* Member elements without timeout */
45struct hash_ipportnet4_elem {
46 __be32 ip;
47 __be32 ip2;
48 __be16 port;
49 u8 cidr;
50 u8 proto;
51};
52
53/* Member elements with timeout support */
54struct hash_ipportnet4_telem {
55 __be32 ip;
56 __be32 ip2;
57 __be16 port;
58 u8 cidr;
59 u8 proto;
60 unsigned long timeout;
61};
62
63static inline bool
64hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
65 const struct hash_ipportnet4_elem *ip2)
66{
67 return ip1->ip == ip2->ip &&
68 ip1->ip2 == ip2->ip2 &&
69 ip1->cidr == ip2->cidr &&
70 ip1->port == ip2->port &&
71 ip1->proto == ip2->proto;
72}
73
74static inline bool
75hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
76{
77 return elem->proto == 0;
78}
79
80static inline void
81hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
82 const struct hash_ipportnet4_elem *src)
83{
84 memcpy(dst, src, sizeof(*dst));
85}
86
87static inline void
88hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
89{
90 elem->ip2 &= ip_set_netmask(cidr);
91 elem->cidr = cidr;
92}
93
94static inline void
95hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
96{
97 elem->proto = 0;
98}
99
100static bool
101hash_ipportnet4_data_list(struct sk_buff *skb,
102 const struct hash_ipportnet4_elem *data)
103{
104 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
105 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
106 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
107 NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
108 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
109 return 0;
110
111nla_put_failure:
112 return 1;
113}
114
115static bool
116hash_ipportnet4_data_tlist(struct sk_buff *skb,
117 const struct hash_ipportnet4_elem *data)
118{
119 const struct hash_ipportnet4_telem *tdata =
120 (const struct hash_ipportnet4_telem *)data;
121
122 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
123 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
124 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
125 NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
126 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
127 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
128 htonl(ip_set_timeout_get(tdata->timeout)));
129
130 return 0;
131
132nla_put_failure:
133 return 1;
134}
135
136#define IP_SET_HASH_WITH_PROTO
137#define IP_SET_HASH_WITH_NETS
138
139#define PF 4
140#define HOST_MASK 32
141#include <linux/netfilter/ipset/ip_set_ahash.h>
142
143static int
144hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
145 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
146{
147 const struct ip_set_hash *h = set->data;
148 ipset_adtfn adtfn = set->variant->adt[adt];
149 struct hash_ipportnet4_elem data =
150 { .cidr = h->nets[0].cidr || HOST_MASK };
151
152 if (data.cidr == 0)
153 return -EINVAL;
154 if (adt == IPSET_TEST)
155 data.cidr = HOST_MASK;
156
157 if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
158 &data.port, &data.proto))
159 return -EINVAL;
160
161 ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
162 ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
163 data.ip2 &= ip_set_netmask(data.cidr);
164
165 return adtfn(set, &data, h->timeout);
166}
167
168static int
169hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
170 enum ipset_adt adt, u32 *lineno, u32 flags)
171{
172 const struct ip_set_hash *h = set->data;
173 ipset_adtfn adtfn = set->variant->adt[adt];
174 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
175 u32 ip, ip_to, p, port, port_to;
176 u32 timeout = h->timeout;
177 int ret;
178
179 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
180 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
181 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
182 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
183 return -IPSET_ERR_PROTOCOL;
184
185 if (tb[IPSET_ATTR_LINENO])
186 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
187
188 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
189 if (ret)
190 return ret;
191
192 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
193 if (ret)
194 return ret;
195
196 if (tb[IPSET_ATTR_CIDR2])
197 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
198
199 if (!data.cidr)
200 return -IPSET_ERR_INVALID_CIDR;
201
202 data.ip2 &= ip_set_netmask(data.cidr);
203
204 if (tb[IPSET_ATTR_PORT])
205 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
206 else
207 return -IPSET_ERR_PROTOCOL;
208
209 if (tb[IPSET_ATTR_PROTO]) {
210 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
211
212 if (data.proto == 0)
213 return -IPSET_ERR_INVALID_PROTO;
214 } else
215 return -IPSET_ERR_MISSING_PROTO;
216
217 switch (data.proto) {
218 case IPPROTO_UDP:
219 case IPPROTO_TCP:
220 case IPPROTO_ICMP:
221 break;
222 default:
223 data.port = 0;
224 break;
225 }
226
227 if (tb[IPSET_ATTR_TIMEOUT]) {
228 if (!with_timeout(h->timeout))
229 return -IPSET_ERR_TIMEOUT;
230 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
231 }
232
233 if (adt == IPSET_TEST ||
234 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
235 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
236 tb[IPSET_ATTR_PORT_TO])) {
237 ret = adtfn(set, &data, timeout);
238 return ip_set_eexist(ret, flags) ? 0 : ret;
239 }
240
241 ip = ntohl(data.ip);
242 if (tb[IPSET_ATTR_IP_TO]) {
243 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
244 if (ret)
245 return ret;
246 if (ip > ip_to)
247 swap(ip, ip_to);
248 } else if (tb[IPSET_ATTR_CIDR]) {
249 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
250
251 if (cidr > 32)
252 return -IPSET_ERR_INVALID_CIDR;
253 ip &= ip_set_hostmask(cidr);
254 ip_to = ip | ~ip_set_hostmask(cidr);
255 } else
256 ip_to = ip;
257
258 port = ntohs(data.port);
259 if (tb[IPSET_ATTR_PORT_TO]) {
260 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
261 if (port > port_to)
262 swap(port, port_to);
263 } else
264 port_to = port;
265
266 for (; !before(ip_to, ip); ip++)
267 for (p = port; p <= port_to; p++) {
268 data.ip = htonl(ip);
269 data.port = htons(p);
270 ret = adtfn(set, &data, timeout);
271
272 if (ret && !ip_set_eexist(ret, flags))
273 return ret;
274 else
275 ret = 0;
276 }
277 return ret;
278}
279
280static bool
281hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
282{
283 const struct ip_set_hash *x = a->data;
284 const struct ip_set_hash *y = b->data;
285
286 /* Resizing changes htable_bits, so we ignore it */
287 return x->maxelem == y->maxelem &&
288 x->timeout == y->timeout;
289}
290
291/* The type variant functions: IPv6 */
292
293struct hash_ipportnet6_elem {
294 union nf_inet_addr ip;
295 union nf_inet_addr ip2;
296 __be16 port;
297 u8 cidr;
298 u8 proto;
299};
300
301struct hash_ipportnet6_telem {
302 union nf_inet_addr ip;
303 union nf_inet_addr ip2;
304 __be16 port;
305 u8 cidr;
306 u8 proto;
307 unsigned long timeout;
308};
309
310static inline bool
311hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
312 const struct hash_ipportnet6_elem *ip2)
313{
314 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
315 ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
316 ip1->cidr == ip2->cidr &&
317 ip1->port == ip2->port &&
318 ip1->proto == ip2->proto;
319}
320
321static inline bool
322hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
323{
324 return elem->proto == 0;
325}
326
327static inline void
328hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
329 const struct hash_ipportnet6_elem *src)
330{
331 memcpy(dst, src, sizeof(*dst));
332}
333
334static inline void
335hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
336{
337 elem->proto = 0;
338}
339
340static inline void
341ip6_netmask(union nf_inet_addr *ip, u8 prefix)
342{
343 ip->ip6[0] &= ip_set_netmask6(prefix)[0];
344 ip->ip6[1] &= ip_set_netmask6(prefix)[1];
345 ip->ip6[2] &= ip_set_netmask6(prefix)[2];
346 ip->ip6[3] &= ip_set_netmask6(prefix)[3];
347}
348
349static inline void
350hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
351{
352 ip6_netmask(&elem->ip2, cidr);
353 elem->cidr = cidr;
354}
355
356static bool
357hash_ipportnet6_data_list(struct sk_buff *skb,
358 const struct hash_ipportnet6_elem *data)
359{
360 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
361 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
362 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
363 NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
364 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
365 return 0;
366
367nla_put_failure:
368 return 1;
369}
370
371static bool
372hash_ipportnet6_data_tlist(struct sk_buff *skb,
373 const struct hash_ipportnet6_elem *data)
374{
375 const struct hash_ipportnet6_telem *e =
376 (const struct hash_ipportnet6_telem *)data;
377
378 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
379 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
380 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
381 NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
382 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
383 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
384 htonl(ip_set_timeout_get(e->timeout)));
385 return 0;
386
387nla_put_failure:
388 return 1;
389}
390
391#undef PF
392#undef HOST_MASK
393
394#define PF 6
395#define HOST_MASK 128
396#include <linux/netfilter/ipset/ip_set_ahash.h>
397
398static int
399hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
400 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
401{
402 const struct ip_set_hash *h = set->data;
403 ipset_adtfn adtfn = set->variant->adt[adt];
404 struct hash_ipportnet6_elem data =
405 { .cidr = h->nets[0].cidr || HOST_MASK };
406
407 if (data.cidr == 0)
408 return -EINVAL;
409 if (adt == IPSET_TEST)
410 data.cidr = HOST_MASK;
411
412 if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
413 &data.port, &data.proto))
414 return -EINVAL;
415
416 ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
417 ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
418 ip6_netmask(&data.ip2, data.cidr);
419
420 return adtfn(set, &data, h->timeout);
421}
422
423static int
424hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
425 enum ipset_adt adt, u32 *lineno, u32 flags)
426{
427 const struct ip_set_hash *h = set->data;
428 ipset_adtfn adtfn = set->variant->adt[adt];
429 struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
430 u32 port, port_to;
431 u32 timeout = h->timeout;
432 int ret;
433
434 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
435 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
436 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
437 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
438 tb[IPSET_ATTR_IP_TO] ||
439 tb[IPSET_ATTR_CIDR]))
440 return -IPSET_ERR_PROTOCOL;
441
442 if (tb[IPSET_ATTR_LINENO])
443 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
444
445 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
446 if (ret)
447 return ret;
448
449 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
450 if (ret)
451 return ret;
452
453 if (tb[IPSET_ATTR_CIDR2])
454 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
455
456 if (!data.cidr)
457 return -IPSET_ERR_INVALID_CIDR;
458
459 ip6_netmask(&data.ip2, data.cidr);
460
461 if (tb[IPSET_ATTR_PORT])
462 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
463 else
464 return -IPSET_ERR_PROTOCOL;
465
466 if (tb[IPSET_ATTR_PROTO]) {
467 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
468
469 if (data.proto == 0)
470 return -IPSET_ERR_INVALID_PROTO;
471 } else
472 return -IPSET_ERR_MISSING_PROTO;
473
474 switch (data.proto) {
475 case IPPROTO_UDP:
476 case IPPROTO_TCP:
477 case IPPROTO_ICMPV6:
478 break;
479 default:
480 data.port = 0;
481 break;
482 }
483
484 if (tb[IPSET_ATTR_TIMEOUT]) {
485 if (!with_timeout(h->timeout))
486 return -IPSET_ERR_TIMEOUT;
487 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
488 }
489
490 if (adt == IPSET_TEST ||
491 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
492 !tb[IPSET_ATTR_PORT_TO]) {
493 ret = adtfn(set, &data, timeout);
494 return ip_set_eexist(ret, flags) ? 0 : ret;
495 }
496
497 port = ntohs(data.port);
498 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
499 if (port > port_to)
500 swap(port, port_to);
501
502 for (; port <= port_to; port++) {
503 data.port = htons(port);
504 ret = adtfn(set, &data, timeout);
505
506 if (ret && !ip_set_eexist(ret, flags))
507 return ret;
508 else
509 ret = 0;
510 }
511 return ret;
512}
513
514/* Create hash:ip type of sets */
515
516static int
517hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
518{
519 struct ip_set_hash *h;
520 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
521 u8 hbits;
522
523 if (!(set->family == AF_INET || set->family == AF_INET6))
524 return -IPSET_ERR_INVALID_FAMILY;
525
526 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
527 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
528 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
529 return -IPSET_ERR_PROTOCOL;
530
531 if (tb[IPSET_ATTR_HASHSIZE]) {
532 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
533 if (hashsize < IPSET_MIMINAL_HASHSIZE)
534 hashsize = IPSET_MIMINAL_HASHSIZE;
535 }
536
537 if (tb[IPSET_ATTR_MAXELEM])
538 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
539
540 h = kzalloc(sizeof(*h)
541 + sizeof(struct ip_set_hash_nets)
542 * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
543 if (!h)
544 return -ENOMEM;
545
546 h->maxelem = maxelem;
547 get_random_bytes(&h->initval, sizeof(h->initval));
548 h->timeout = IPSET_NO_TIMEOUT;
549
550 hbits = htable_bits(hashsize);
551 h->table = ip_set_alloc(
552 sizeof(struct htable)
553 + jhash_size(hbits) * sizeof(struct hbucket));
554 if (!h->table) {
555 kfree(h);
556 return -ENOMEM;
557 }
558 h->table->htable_bits = hbits;
559
560 set->data = h;
561
562 if (tb[IPSET_ATTR_TIMEOUT]) {
563 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
564
565 set->variant = set->family == AF_INET
566 ? &hash_ipportnet4_tvariant
567 : &hash_ipportnet6_tvariant;
568
569 if (set->family == AF_INET)
570 hash_ipportnet4_gc_init(set);
571 else
572 hash_ipportnet6_gc_init(set);
573 } else {
574 set->variant = set->family == AF_INET
575 ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
576 }
577
578 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
579 set->name, jhash_size(h->table->htable_bits),
580 h->table->htable_bits, h->maxelem, set->data, h->table);
581
582 return 0;
583}
584
585static struct ip_set_type hash_ipportnet_type __read_mostly = {
586 .name = "hash:ip,port,net",
587 .protocol = IPSET_PROTOCOL,
588 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
589 .dimension = IPSET_DIM_THREE,
590 .family = AF_UNSPEC,
591 .revision = 0,
592 .create = hash_ipportnet_create,
593 .create_policy = {
594 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
595 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
596 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
597 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
598 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
599 },
600 .adt_policy = {
601 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
602 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
603 [IPSET_ATTR_IP2] = { .type = NLA_NESTED },
604 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
605 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
606 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
607 [IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
608 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
609 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
610 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
611 },
612 .me = THIS_MODULE,
613};
614
615static int __init
616hash_ipportnet_init(void)
617{
618 return ip_set_type_register(&hash_ipportnet_type);
619}
620
621static void __exit
622hash_ipportnet_fini(void)
623{
624 ip_set_type_unregister(&hash_ipportnet_type);
625}
626
627module_init(hash_ipportnet_init);
628module_exit(hash_ipportnet_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
new file mode 100644
index 000000000000..c4db202b7da4
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -0,0 +1,458 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:net type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter/ipset/pfxlen.h>
22#include <linux/netfilter/ipset/ip_set.h>
23#include <linux/netfilter/ipset/ip_set_timeout.h>
24#include <linux/netfilter/ipset/ip_set_hash.h>
25
26MODULE_LICENSE("GPL");
27MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
28MODULE_DESCRIPTION("hash:net type of IP sets");
29MODULE_ALIAS("ip_set_hash:net");
30
31/* Type specific function prefix */
32#define TYPE hash_net
33
34static bool
35hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
36
37#define hash_net4_same_set hash_net_same_set
38#define hash_net6_same_set hash_net_same_set
39
40/* The type variant functions: IPv4 */
41
42/* Member elements without timeout */
43struct hash_net4_elem {
44 __be32 ip;
45 u16 padding0;
46 u8 padding1;
47 u8 cidr;
48};
49
50/* Member elements with timeout support */
51struct hash_net4_telem {
52 __be32 ip;
53 u16 padding0;
54 u8 padding1;
55 u8 cidr;
56 unsigned long timeout;
57};
58
59static inline bool
60hash_net4_data_equal(const struct hash_net4_elem *ip1,
61 const struct hash_net4_elem *ip2)
62{
63 return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
64}
65
66static inline bool
67hash_net4_data_isnull(const struct hash_net4_elem *elem)
68{
69 return elem->cidr == 0;
70}
71
72static inline void
73hash_net4_data_copy(struct hash_net4_elem *dst,
74 const struct hash_net4_elem *src)
75{
76 dst->ip = src->ip;
77 dst->cidr = src->cidr;
78}
79
80static inline void
81hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
82{
83 elem->ip &= ip_set_netmask(cidr);
84 elem->cidr = cidr;
85}
86
87/* Zero CIDR values cannot be stored */
88static inline void
89hash_net4_data_zero_out(struct hash_net4_elem *elem)
90{
91 elem->cidr = 0;
92}
93
94static bool
95hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
96{
97 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
98 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
99 return 0;
100
101nla_put_failure:
102 return 1;
103}
104
105static bool
106hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
107{
108 const struct hash_net4_telem *tdata =
109 (const struct hash_net4_telem *)data;
110
111 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
112 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr);
113 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
114 htonl(ip_set_timeout_get(tdata->timeout)));
115
116 return 0;
117
118nla_put_failure:
119 return 1;
120}
121
122#define IP_SET_HASH_WITH_NETS
123
124#define PF 4
125#define HOST_MASK 32
126#include <linux/netfilter/ipset/ip_set_ahash.h>
127
128static int
129hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
130 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
131{
132 const struct ip_set_hash *h = set->data;
133 ipset_adtfn adtfn = set->variant->adt[adt];
134 struct hash_net4_elem data = { .cidr = h->nets[0].cidr || HOST_MASK };
135
136 if (data.cidr == 0)
137 return -EINVAL;
138 if (adt == IPSET_TEST)
139 data.cidr = HOST_MASK;
140
141 ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
142 data.ip &= ip_set_netmask(data.cidr);
143
144 return adtfn(set, &data, h->timeout);
145}
146
147static int
148hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
149 enum ipset_adt adt, u32 *lineno, u32 flags)
150{
151 const struct ip_set_hash *h = set->data;
152 ipset_adtfn adtfn = set->variant->adt[adt];
153 struct hash_net4_elem data = { .cidr = HOST_MASK };
154 u32 timeout = h->timeout;
155 int ret;
156
157 if (unlikely(!tb[IPSET_ATTR_IP] ||
158 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
159 return -IPSET_ERR_PROTOCOL;
160
161 if (tb[IPSET_ATTR_LINENO])
162 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
163
164 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
165 if (ret)
166 return ret;
167
168 if (tb[IPSET_ATTR_CIDR])
169 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
170
171 if (!data.cidr)
172 return -IPSET_ERR_INVALID_CIDR;
173
174 data.ip &= ip_set_netmask(data.cidr);
175
176 if (tb[IPSET_ATTR_TIMEOUT]) {
177 if (!with_timeout(h->timeout))
178 return -IPSET_ERR_TIMEOUT;
179 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
180 }
181
182 ret = adtfn(set, &data, timeout);
183
184 return ip_set_eexist(ret, flags) ? 0 : ret;
185}
186
187static bool
188hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
189{
190 const struct ip_set_hash *x = a->data;
191 const struct ip_set_hash *y = b->data;
192
193 /* Resizing changes htable_bits, so we ignore it */
194 return x->maxelem == y->maxelem &&
195 x->timeout == y->timeout;
196}
197
198/* The type variant functions: IPv6 */
199
200struct hash_net6_elem {
201 union nf_inet_addr ip;
202 u16 padding0;
203 u8 padding1;
204 u8 cidr;
205};
206
207struct hash_net6_telem {
208 union nf_inet_addr ip;
209 u16 padding0;
210 u8 padding1;
211 u8 cidr;
212 unsigned long timeout;
213};
214
215static inline bool
216hash_net6_data_equal(const struct hash_net6_elem *ip1,
217 const struct hash_net6_elem *ip2)
218{
219 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
220 ip1->cidr == ip2->cidr;
221}
222
223static inline bool
224hash_net6_data_isnull(const struct hash_net6_elem *elem)
225{
226 return elem->cidr == 0;
227}
228
229static inline void
230hash_net6_data_copy(struct hash_net6_elem *dst,
231 const struct hash_net6_elem *src)
232{
233 ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
234 dst->cidr = src->cidr;
235}
236
237static inline void
238hash_net6_data_zero_out(struct hash_net6_elem *elem)
239{
240 elem->cidr = 0;
241}
242
243static inline void
244ip6_netmask(union nf_inet_addr *ip, u8 prefix)
245{
246 ip->ip6[0] &= ip_set_netmask6(prefix)[0];
247 ip->ip6[1] &= ip_set_netmask6(prefix)[1];
248 ip->ip6[2] &= ip_set_netmask6(prefix)[2];
249 ip->ip6[3] &= ip_set_netmask6(prefix)[3];
250}
251
252static inline void
253hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
254{
255 ip6_netmask(&elem->ip, cidr);
256 elem->cidr = cidr;
257}
258
259static bool
260hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
261{
262 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
263 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
264 return 0;
265
266nla_put_failure:
267 return 1;
268}
269
270static bool
271hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
272{
273 const struct hash_net6_telem *e =
274 (const struct hash_net6_telem *)data;
275
276 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
277 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr);
278 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
279 htonl(ip_set_timeout_get(e->timeout)));
280 return 0;
281
282nla_put_failure:
283 return 1;
284}
285
286#undef PF
287#undef HOST_MASK
288
289#define PF 6
290#define HOST_MASK 128
291#include <linux/netfilter/ipset/ip_set_ahash.h>
292
293static int
294hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
295 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
296{
297 const struct ip_set_hash *h = set->data;
298 ipset_adtfn adtfn = set->variant->adt[adt];
299 struct hash_net6_elem data = { .cidr = h->nets[0].cidr || HOST_MASK };
300
301 if (data.cidr == 0)
302 return -EINVAL;
303 if (adt == IPSET_TEST)
304 data.cidr = HOST_MASK;
305
306 ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
307 ip6_netmask(&data.ip, data.cidr);
308
309 return adtfn(set, &data, h->timeout);
310}
311
312static int
313hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
314 enum ipset_adt adt, u32 *lineno, u32 flags)
315{
316 const struct ip_set_hash *h = set->data;
317 ipset_adtfn adtfn = set->variant->adt[adt];
318 struct hash_net6_elem data = { .cidr = HOST_MASK };
319 u32 timeout = h->timeout;
320 int ret;
321
322 if (unlikely(!tb[IPSET_ATTR_IP] ||
323 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
324 return -IPSET_ERR_PROTOCOL;
325
326 if (tb[IPSET_ATTR_LINENO])
327 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
328
329 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
330 if (ret)
331 return ret;
332
333 if (tb[IPSET_ATTR_CIDR])
334 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
335
336 if (!data.cidr)
337 return -IPSET_ERR_INVALID_CIDR;
338
339 ip6_netmask(&data.ip, data.cidr);
340
341 if (tb[IPSET_ATTR_TIMEOUT]) {
342 if (!with_timeout(h->timeout))
343 return -IPSET_ERR_TIMEOUT;
344 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
345 }
346
347 ret = adtfn(set, &data, timeout);
348
349 return ip_set_eexist(ret, flags) ? 0 : ret;
350}
351
352/* Create hash:ip type of sets */
353
354static int
355hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
356{
357 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
358 struct ip_set_hash *h;
359 u8 hbits;
360
361 if (!(set->family == AF_INET || set->family == AF_INET6))
362 return -IPSET_ERR_INVALID_FAMILY;
363
364 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
365 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
366 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
367 return -IPSET_ERR_PROTOCOL;
368
369 if (tb[IPSET_ATTR_HASHSIZE]) {
370 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
371 if (hashsize < IPSET_MIMINAL_HASHSIZE)
372 hashsize = IPSET_MIMINAL_HASHSIZE;
373 }
374
375 if (tb[IPSET_ATTR_MAXELEM])
376 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
377
378 h = kzalloc(sizeof(*h)
379 + sizeof(struct ip_set_hash_nets)
380 * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
381 if (!h)
382 return -ENOMEM;
383
384 h->maxelem = maxelem;
385 get_random_bytes(&h->initval, sizeof(h->initval));
386 h->timeout = IPSET_NO_TIMEOUT;
387
388 hbits = htable_bits(hashsize);
389 h->table = ip_set_alloc(
390 sizeof(struct htable)
391 + jhash_size(hbits) * sizeof(struct hbucket));
392 if (!h->table) {
393 kfree(h);
394 return -ENOMEM;
395 }
396 h->table->htable_bits = hbits;
397
398 set->data = h;
399
400 if (tb[IPSET_ATTR_TIMEOUT]) {
401 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
402
403 set->variant = set->family == AF_INET
404 ? &hash_net4_tvariant : &hash_net6_tvariant;
405
406 if (set->family == AF_INET)
407 hash_net4_gc_init(set);
408 else
409 hash_net6_gc_init(set);
410 } else {
411 set->variant = set->family == AF_INET
412 ? &hash_net4_variant : &hash_net6_variant;
413 }
414
415 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
416 set->name, jhash_size(h->table->htable_bits),
417 h->table->htable_bits, h->maxelem, set->data, h->table);
418
419 return 0;
420}
421
422static struct ip_set_type hash_net_type __read_mostly = {
423 .name = "hash:net",
424 .protocol = IPSET_PROTOCOL,
425 .features = IPSET_TYPE_IP,
426 .dimension = IPSET_DIM_ONE,
427 .family = AF_UNSPEC,
428 .revision = 0,
429 .create = hash_net_create,
430 .create_policy = {
431 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
432 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
433 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
434 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
435 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
436 },
437 .adt_policy = {
438 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
439 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
440 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
441 },
442 .me = THIS_MODULE,
443};
444
445static int __init
446hash_net_init(void)
447{
448 return ip_set_type_register(&hash_net_type);
449}
450
451static void __exit
452hash_net_fini(void)
453{
454 ip_set_type_unregister(&hash_net_type);
455}
456
457module_init(hash_net_init);
458module_exit(hash_net_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
new file mode 100644
index 000000000000..34a165626ee9
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -0,0 +1,578 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:net,port type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/ip.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/random.h>
16#include <net/ip.h>
17#include <net/ipv6.h>
18#include <net/netlink.h>
19
20#include <linux/netfilter.h>
21#include <linux/netfilter/ipset/pfxlen.h>
22#include <linux/netfilter/ipset/ip_set.h>
23#include <linux/netfilter/ipset/ip_set_timeout.h>
24#include <linux/netfilter/ipset/ip_set_getport.h>
25#include <linux/netfilter/ipset/ip_set_hash.h>
26
27MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29MODULE_DESCRIPTION("hash:net,port type of IP sets");
30MODULE_ALIAS("ip_set_hash:net,port");
31
32/* Type specific function prefix */
33#define TYPE hash_netport
34
35static bool
36hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
37
38#define hash_netport4_same_set hash_netport_same_set
39#define hash_netport6_same_set hash_netport_same_set
40
41/* The type variant functions: IPv4 */
42
43/* Member elements without timeout */
44struct hash_netport4_elem {
45 __be32 ip;
46 __be16 port;
47 u8 proto;
48 u8 cidr;
49};
50
51/* Member elements with timeout support */
52struct hash_netport4_telem {
53 __be32 ip;
54 __be16 port;
55 u8 proto;
56 u8 cidr;
57 unsigned long timeout;
58};
59
60static inline bool
61hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
62 const struct hash_netport4_elem *ip2)
63{
64 return ip1->ip == ip2->ip &&
65 ip1->port == ip2->port &&
66 ip1->proto == ip2->proto &&
67 ip1->cidr == ip2->cidr;
68}
69
70static inline bool
71hash_netport4_data_isnull(const struct hash_netport4_elem *elem)
72{
73 return elem->proto == 0;
74}
75
76static inline void
77hash_netport4_data_copy(struct hash_netport4_elem *dst,
78 const struct hash_netport4_elem *src)
79{
80 dst->ip = src->ip;
81 dst->port = src->port;
82 dst->proto = src->proto;
83 dst->cidr = src->cidr;
84}
85
86static inline void
87hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
88{
89 elem->ip &= ip_set_netmask(cidr);
90 elem->cidr = cidr;
91}
92
93static inline void
94hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
95{
96 elem->proto = 0;
97}
98
99static bool
100hash_netport4_data_list(struct sk_buff *skb,
101 const struct hash_netport4_elem *data)
102{
103 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
104 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
105 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
106 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
107 return 0;
108
109nla_put_failure:
110 return 1;
111}
112
113static bool
114hash_netport4_data_tlist(struct sk_buff *skb,
115 const struct hash_netport4_elem *data)
116{
117 const struct hash_netport4_telem *tdata =
118 (const struct hash_netport4_telem *)data;
119
120 NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
121 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
122 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
123 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
124 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
125 htonl(ip_set_timeout_get(tdata->timeout)));
126
127 return 0;
128
129nla_put_failure:
130 return 1;
131}
132
133#define IP_SET_HASH_WITH_PROTO
134#define IP_SET_HASH_WITH_NETS
135
136#define PF 4
137#define HOST_MASK 32
138#include <linux/netfilter/ipset/ip_set_ahash.h>
139
140static int
141hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
142 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
143{
144 const struct ip_set_hash *h = set->data;
145 ipset_adtfn adtfn = set->variant->adt[adt];
146 struct hash_netport4_elem data = {
147 .cidr = h->nets[0].cidr || HOST_MASK };
148
149 if (data.cidr == 0)
150 return -EINVAL;
151 if (adt == IPSET_TEST)
152 data.cidr = HOST_MASK;
153
154 if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
155 &data.port, &data.proto))
156 return -EINVAL;
157
158 ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
159 data.ip &= ip_set_netmask(data.cidr);
160
161 return adtfn(set, &data, h->timeout);
162}
163
164static int
165hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
166 enum ipset_adt adt, u32 *lineno, u32 flags)
167{
168 const struct ip_set_hash *h = set->data;
169 ipset_adtfn adtfn = set->variant->adt[adt];
170 struct hash_netport4_elem data = { .cidr = HOST_MASK };
171 u32 port, port_to;
172 u32 timeout = h->timeout;
173 int ret;
174
175 if (unlikely(!tb[IPSET_ATTR_IP] ||
176 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
177 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
178 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
179 return -IPSET_ERR_PROTOCOL;
180
181 if (tb[IPSET_ATTR_LINENO])
182 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
183
184 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
185 if (ret)
186 return ret;
187
188 if (tb[IPSET_ATTR_CIDR])
189 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
190 if (!data.cidr)
191 return -IPSET_ERR_INVALID_CIDR;
192 data.ip &= ip_set_netmask(data.cidr);
193
194 if (tb[IPSET_ATTR_PORT])
195 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
196 else
197 return -IPSET_ERR_PROTOCOL;
198
199 if (tb[IPSET_ATTR_PROTO]) {
200 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
201
202 if (data.proto == 0)
203 return -IPSET_ERR_INVALID_PROTO;
204 } else
205 return -IPSET_ERR_MISSING_PROTO;
206
207 switch (data.proto) {
208 case IPPROTO_UDP:
209 case IPPROTO_TCP:
210 case IPPROTO_ICMP:
211 break;
212 default:
213 data.port = 0;
214 break;
215 }
216
217 if (tb[IPSET_ATTR_TIMEOUT]) {
218 if (!with_timeout(h->timeout))
219 return -IPSET_ERR_TIMEOUT;
220 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
221 }
222
223 if (adt == IPSET_TEST ||
224 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
225 !tb[IPSET_ATTR_PORT_TO]) {
226 ret = adtfn(set, &data, timeout);
227 return ip_set_eexist(ret, flags) ? 0 : ret;
228 }
229
230 port = ntohs(data.port);
231 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
232 if (port > port_to)
233 swap(port, port_to);
234
235 for (; port <= port_to; port++) {
236 data.port = htons(port);
237 ret = adtfn(set, &data, timeout);
238
239 if (ret && !ip_set_eexist(ret, flags))
240 return ret;
241 else
242 ret = 0;
243 }
244 return ret;
245}
246
247static bool
248hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
249{
250 const struct ip_set_hash *x = a->data;
251 const struct ip_set_hash *y = b->data;
252
253 /* Resizing changes htable_bits, so we ignore it */
254 return x->maxelem == y->maxelem &&
255 x->timeout == y->timeout;
256}
257
258/* The type variant functions: IPv6 */
259
260struct hash_netport6_elem {
261 union nf_inet_addr ip;
262 __be16 port;
263 u8 proto;
264 u8 cidr;
265};
266
267struct hash_netport6_telem {
268 union nf_inet_addr ip;
269 __be16 port;
270 u8 proto;
271 u8 cidr;
272 unsigned long timeout;
273};
274
275static inline bool
276hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
277 const struct hash_netport6_elem *ip2)
278{
279 return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
280 ip1->port == ip2->port &&
281 ip1->proto == ip2->proto &&
282 ip1->cidr == ip2->cidr;
283}
284
285static inline bool
286hash_netport6_data_isnull(const struct hash_netport6_elem *elem)
287{
288 return elem->proto == 0;
289}
290
291static inline void
292hash_netport6_data_copy(struct hash_netport6_elem *dst,
293 const struct hash_netport6_elem *src)
294{
295 memcpy(dst, src, sizeof(*dst));
296}
297
298static inline void
299hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
300{
301 elem->proto = 0;
302}
303
304static inline void
305ip6_netmask(union nf_inet_addr *ip, u8 prefix)
306{
307 ip->ip6[0] &= ip_set_netmask6(prefix)[0];
308 ip->ip6[1] &= ip_set_netmask6(prefix)[1];
309 ip->ip6[2] &= ip_set_netmask6(prefix)[2];
310 ip->ip6[3] &= ip_set_netmask6(prefix)[3];
311}
312
313static inline void
314hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
315{
316 ip6_netmask(&elem->ip, cidr);
317 elem->cidr = cidr;
318}
319
320static bool
321hash_netport6_data_list(struct sk_buff *skb,
322 const struct hash_netport6_elem *data)
323{
324 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
325 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
326 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
327 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
328 return 0;
329
330nla_put_failure:
331 return 1;
332}
333
334static bool
335hash_netport6_data_tlist(struct sk_buff *skb,
336 const struct hash_netport6_elem *data)
337{
338 const struct hash_netport6_telem *e =
339 (const struct hash_netport6_telem *)data;
340
341 NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
342 NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
343 NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
344 NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
345 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
346 htonl(ip_set_timeout_get(e->timeout)));
347 return 0;
348
349nla_put_failure:
350 return 1;
351}
352
353#undef PF
354#undef HOST_MASK
355
356#define PF 6
357#define HOST_MASK 128
358#include <linux/netfilter/ipset/ip_set_ahash.h>
359
360static int
361hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
362 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
363{
364 const struct ip_set_hash *h = set->data;
365 ipset_adtfn adtfn = set->variant->adt[adt];
366 struct hash_netport6_elem data = {
367 .cidr = h->nets[0].cidr || HOST_MASK };
368
369 if (data.cidr == 0)
370 return -EINVAL;
371 if (adt == IPSET_TEST)
372 data.cidr = HOST_MASK;
373
374 if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
375 &data.port, &data.proto))
376 return -EINVAL;
377
378 ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
379 ip6_netmask(&data.ip, data.cidr);
380
381 return adtfn(set, &data, h->timeout);
382}
383
384static int
385hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
386 enum ipset_adt adt, u32 *lineno, u32 flags)
387{
388 const struct ip_set_hash *h = set->data;
389 ipset_adtfn adtfn = set->variant->adt[adt];
390 struct hash_netport6_elem data = { .cidr = HOST_MASK };
391 u32 port, port_to;
392 u32 timeout = h->timeout;
393 int ret;
394
395 if (unlikely(!tb[IPSET_ATTR_IP] ||
396 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
397 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
398 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
399 return -IPSET_ERR_PROTOCOL;
400
401 if (tb[IPSET_ATTR_LINENO])
402 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
403
404 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
405 if (ret)
406 return ret;
407
408 if (tb[IPSET_ATTR_CIDR])
409 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
410 if (!data.cidr)
411 return -IPSET_ERR_INVALID_CIDR;
412 ip6_netmask(&data.ip, data.cidr);
413
414 if (tb[IPSET_ATTR_PORT])
415 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
416 else
417 return -IPSET_ERR_PROTOCOL;
418
419 if (tb[IPSET_ATTR_PROTO]) {
420 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
421
422 if (data.proto == 0)
423 return -IPSET_ERR_INVALID_PROTO;
424 } else
425 return -IPSET_ERR_MISSING_PROTO;
426
427 switch (data.proto) {
428 case IPPROTO_UDP:
429 case IPPROTO_TCP:
430 case IPPROTO_ICMPV6:
431 break;
432 default:
433 data.port = 0;
434 break;
435 }
436
437 if (tb[IPSET_ATTR_TIMEOUT]) {
438 if (!with_timeout(h->timeout))
439 return -IPSET_ERR_TIMEOUT;
440 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
441 }
442
443 if (adt == IPSET_TEST ||
444 !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) ||
445 !tb[IPSET_ATTR_PORT_TO]) {
446 ret = adtfn(set, &data, timeout);
447 return ip_set_eexist(ret, flags) ? 0 : ret;
448 }
449
450 port = ntohs(data.port);
451 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
452 if (port > port_to)
453 swap(port, port_to);
454
455 for (; port <= port_to; port++) {
456 data.port = htons(port);
457 ret = adtfn(set, &data, timeout);
458
459 if (ret && !ip_set_eexist(ret, flags))
460 return ret;
461 else
462 ret = 0;
463 }
464 return ret;
465}
466
467/* Create hash:ip type of sets */
468
469static int
470hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
471{
472 struct ip_set_hash *h;
473 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
474 u8 hbits;
475
476 if (!(set->family == AF_INET || set->family == AF_INET6))
477 return -IPSET_ERR_INVALID_FAMILY;
478
479 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
480 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
481 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
482 return -IPSET_ERR_PROTOCOL;
483
484 if (tb[IPSET_ATTR_HASHSIZE]) {
485 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
486 if (hashsize < IPSET_MIMINAL_HASHSIZE)
487 hashsize = IPSET_MIMINAL_HASHSIZE;
488 }
489
490 if (tb[IPSET_ATTR_MAXELEM])
491 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
492
493 h = kzalloc(sizeof(*h)
494 + sizeof(struct ip_set_hash_nets)
495 * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
496 if (!h)
497 return -ENOMEM;
498
499 h->maxelem = maxelem;
500 get_random_bytes(&h->initval, sizeof(h->initval));
501 h->timeout = IPSET_NO_TIMEOUT;
502
503 hbits = htable_bits(hashsize);
504 h->table = ip_set_alloc(
505 sizeof(struct htable)
506 + jhash_size(hbits) * sizeof(struct hbucket));
507 if (!h->table) {
508 kfree(h);
509 return -ENOMEM;
510 }
511 h->table->htable_bits = hbits;
512
513 set->data = h;
514
515 if (tb[IPSET_ATTR_TIMEOUT]) {
516 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
517
518 set->variant = set->family == AF_INET
519 ? &hash_netport4_tvariant : &hash_netport6_tvariant;
520
521 if (set->family == AF_INET)
522 hash_netport4_gc_init(set);
523 else
524 hash_netport6_gc_init(set);
525 } else {
526 set->variant = set->family == AF_INET
527 ? &hash_netport4_variant : &hash_netport6_variant;
528 }
529
530 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
531 set->name, jhash_size(h->table->htable_bits),
532 h->table->htable_bits, h->maxelem, set->data, h->table);
533
534 return 0;
535}
536
537static struct ip_set_type hash_netport_type __read_mostly = {
538 .name = "hash:net,port",
539 .protocol = IPSET_PROTOCOL,
540 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
541 .dimension = IPSET_DIM_TWO,
542 .family = AF_UNSPEC,
543 .revision = 0,
544 .create = hash_netport_create,
545 .create_policy = {
546 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
547 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
548 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
549 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
550 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
551 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
552 },
553 .adt_policy = {
554 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
555 [IPSET_ATTR_PORT] = { .type = NLA_U16 },
556 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
557 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
558 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
559 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
560 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
561 },
562 .me = THIS_MODULE,
563};
564
565static int __init
566hash_netport_init(void)
567{
568 return ip_set_type_register(&hash_netport_type);
569}
570
571static void __exit
572hash_netport_fini(void)
573{
574 ip_set_type_unregister(&hash_netport_type);
575}
576
577module_init(hash_netport_init);
578module_exit(hash_netport_fini);
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
new file mode 100644
index 000000000000..a47c32982f06
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -0,0 +1,584 @@
1/* Copyright (C) 2008-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the list:set type */
9
10#include <linux/module.h>
11#include <linux/ip.h>
12#include <linux/skbuff.h>
13#include <linux/errno.h>
14
15#include <linux/netfilter/ipset/ip_set.h>
16#include <linux/netfilter/ipset/ip_set_timeout.h>
17#include <linux/netfilter/ipset/ip_set_list.h>
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
21MODULE_DESCRIPTION("list:set type of IP sets");
22MODULE_ALIAS("ip_set_list:set");
23
24/* Member elements without and with timeout */
25struct set_elem {
26 ip_set_id_t id;
27};
28
29struct set_telem {
30 ip_set_id_t id;
31 unsigned long timeout;
32};
33
34/* Type structure */
35struct list_set {
36 size_t dsize; /* element size */
37 u32 size; /* size of set list array */
38 u32 timeout; /* timeout value */
39 struct timer_list gc; /* garbage collection */
40 struct set_elem members[0]; /* the set members */
41};
42
43static inline struct set_elem *
44list_set_elem(const struct list_set *map, u32 id)
45{
46 return (struct set_elem *)((char *)map->members + id * map->dsize);
47}
48
49static inline bool
50list_set_timeout(const struct list_set *map, u32 id)
51{
52 const struct set_telem *elem =
53 (const struct set_telem *) list_set_elem(map, id);
54
55 return ip_set_timeout_test(elem->timeout);
56}
57
58static inline bool
59list_set_expired(const struct list_set *map, u32 id)
60{
61 const struct set_telem *elem =
62 (const struct set_telem *) list_set_elem(map, id);
63
64 return ip_set_timeout_expired(elem->timeout);
65}
66
67static inline int
68list_set_exist(const struct set_telem *elem)
69{
70 return elem->id != IPSET_INVALID_ID &&
71 !ip_set_timeout_expired(elem->timeout);
72}
73
74/* Set list without and with timeout */
75
76static int
77list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
78 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
79{
80 struct list_set *map = set->data;
81 struct set_elem *elem;
82 u32 i;
83 int ret;
84
85 for (i = 0; i < map->size; i++) {
86 elem = list_set_elem(map, i);
87 if (elem->id == IPSET_INVALID_ID)
88 return 0;
89 if (with_timeout(map->timeout) && list_set_expired(map, i))
90 continue;
91 switch (adt) {
92 case IPSET_TEST:
93 ret = ip_set_test(elem->id, skb, pf, dim, flags);
94 if (ret > 0)
95 return ret;
96 break;
97 case IPSET_ADD:
98 ret = ip_set_add(elem->id, skb, pf, dim, flags);
99 if (ret == 0)
100 return ret;
101 break;
102 case IPSET_DEL:
103 ret = ip_set_del(elem->id, skb, pf, dim, flags);
104 if (ret == 0)
105 return ret;
106 break;
107 default:
108 break;
109 }
110 }
111 return -EINVAL;
112}
113
114static bool
115next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
116{
117 const struct set_elem *elem;
118
119 if (i + 1 < map->size) {
120 elem = list_set_elem(map, i + 1);
121 return !!(elem->id == id &&
122 !(with_timeout(map->timeout) &&
123 list_set_expired(map, i + 1)));
124 }
125
126 return 0;
127}
128
129static void
130list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
131{
132 struct set_elem *e;
133
134 for (; i < map->size; i++) {
135 e = list_set_elem(map, i);
136 swap(e->id, id);
137 if (e->id == IPSET_INVALID_ID)
138 break;
139 }
140}
141
142static void
143list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
144 unsigned long timeout)
145{
146 struct set_telem *e;
147
148 for (; i < map->size; i++) {
149 e = (struct set_telem *)list_set_elem(map, i);
150 swap(e->id, id);
151 if (e->id == IPSET_INVALID_ID)
152 break;
153 swap(e->timeout, timeout);
154 }
155}
156
157static int
158list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
159 unsigned long timeout)
160{
161 const struct set_elem *e = list_set_elem(map, i);
162
163 if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
164 /* Last element replaced: e.g. add new,before,last */
165 ip_set_put_byindex(e->id);
166 if (with_timeout(map->timeout))
167 list_elem_tadd(map, i, id, timeout);
168 else
169 list_elem_add(map, i, id);
170
171 return 0;
172}
173
174static int
175list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
176{
177 struct set_elem *a = list_set_elem(map, i), *b;
178
179 ip_set_put_byindex(id);
180
181 for (; i < map->size - 1; i++) {
182 b = list_set_elem(map, i + 1);
183 a->id = b->id;
184 if (with_timeout(map->timeout))
185 ((struct set_telem *)a)->timeout =
186 ((struct set_telem *)b)->timeout;
187 a = b;
188 if (a->id == IPSET_INVALID_ID)
189 break;
190 }
191 /* Last element */
192 a->id = IPSET_INVALID_ID;
193 return 0;
194}
195
196static int
197list_set_uadt(struct ip_set *set, struct nlattr *tb[],
198 enum ipset_adt adt, u32 *lineno, u32 flags)
199{
200 struct list_set *map = set->data;
201 bool with_timeout = with_timeout(map->timeout);
202 int before = 0;
203 u32 timeout = map->timeout;
204 ip_set_id_t id, refid = IPSET_INVALID_ID;
205 const struct set_elem *elem;
206 struct ip_set *s;
207 u32 i;
208 int ret = 0;
209
210 if (unlikely(!tb[IPSET_ATTR_NAME] ||
211 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
212 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
213 return -IPSET_ERR_PROTOCOL;
214
215 if (tb[IPSET_ATTR_LINENO])
216 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
217
218 id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
219 if (id == IPSET_INVALID_ID)
220 return -IPSET_ERR_NAME;
221 /* "Loop detection" */
222 if (s->type->features & IPSET_TYPE_NAME) {
223 ret = -IPSET_ERR_LOOP;
224 goto finish;
225 }
226
227 if (tb[IPSET_ATTR_CADT_FLAGS]) {
228 u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
229 before = f & IPSET_FLAG_BEFORE;
230 }
231
232 if (before && !tb[IPSET_ATTR_NAMEREF]) {
233 ret = -IPSET_ERR_BEFORE;
234 goto finish;
235 }
236
237 if (tb[IPSET_ATTR_NAMEREF]) {
238 refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]),
239 &s);
240 if (refid == IPSET_INVALID_ID) {
241 ret = -IPSET_ERR_NAMEREF;
242 goto finish;
243 }
244 if (!before)
245 before = -1;
246 }
247 if (tb[IPSET_ATTR_TIMEOUT]) {
248 if (!with_timeout) {
249 ret = -IPSET_ERR_TIMEOUT;
250 goto finish;
251 }
252 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
253 }
254
255 switch (adt) {
256 case IPSET_TEST:
257 for (i = 0; i < map->size && !ret; i++) {
258 elem = list_set_elem(map, i);
259 if (elem->id == IPSET_INVALID_ID ||
260 (before != 0 && i + 1 >= map->size))
261 break;
262 else if (with_timeout && list_set_expired(map, i))
263 continue;
264 else if (before > 0 && elem->id == id)
265 ret = next_id_eq(map, i, refid);
266 else if (before < 0 && elem->id == refid)
267 ret = next_id_eq(map, i, id);
268 else if (before == 0 && elem->id == id)
269 ret = 1;
270 }
271 break;
272 case IPSET_ADD:
273 for (i = 0; i < map->size && !ret; i++) {
274 elem = list_set_elem(map, i);
275 if (elem->id == id &&
276 !(with_timeout && list_set_expired(map, i)))
277 ret = -IPSET_ERR_EXIST;
278 }
279 if (ret == -IPSET_ERR_EXIST)
280 break;
281 ret = -IPSET_ERR_LIST_FULL;
282 for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
283 elem = list_set_elem(map, i);
284 if (elem->id == IPSET_INVALID_ID)
285 ret = before != 0 ? -IPSET_ERR_REF_EXIST
286 : list_set_add(map, i, id, timeout);
287 else if (elem->id != refid)
288 continue;
289 else if (with_timeout && list_set_expired(map, i))
290 ret = -IPSET_ERR_REF_EXIST;
291 else if (before)
292 ret = list_set_add(map, i, id, timeout);
293 else if (i + 1 < map->size)
294 ret = list_set_add(map, i + 1, id, timeout);
295 }
296 break;
297 case IPSET_DEL:
298 ret = -IPSET_ERR_EXIST;
299 for (i = 0; i < map->size && ret == -IPSET_ERR_EXIST; i++) {
300 elem = list_set_elem(map, i);
301 if (elem->id == IPSET_INVALID_ID) {
302 ret = before != 0 ? -IPSET_ERR_REF_EXIST
303 : -IPSET_ERR_EXIST;
304 break;
305 } else if (with_timeout && list_set_expired(map, i))
306 continue;
307 else if (elem->id == id &&
308 (before == 0 ||
309 (before > 0 &&
310 next_id_eq(map, i, refid))))
311 ret = list_set_del(map, id, i);
312 else if (before < 0 &&
313 elem->id == refid &&
314 next_id_eq(map, i, id))
315 ret = list_set_del(map, id, i + 1);
316 }
317 break;
318 default:
319 break;
320 }
321
322finish:
323 if (refid != IPSET_INVALID_ID)
324 ip_set_put_byindex(refid);
325 if (adt != IPSET_ADD || ret)
326 ip_set_put_byindex(id);
327
328 return ip_set_eexist(ret, flags) ? 0 : ret;
329}
330
331static void
332list_set_flush(struct ip_set *set)
333{
334 struct list_set *map = set->data;
335 struct set_elem *elem;
336 u32 i;
337
338 for (i = 0; i < map->size; i++) {
339 elem = list_set_elem(map, i);
340 if (elem->id != IPSET_INVALID_ID) {
341 ip_set_put_byindex(elem->id);
342 elem->id = IPSET_INVALID_ID;
343 }
344 }
345}
346
347static void
348list_set_destroy(struct ip_set *set)
349{
350 struct list_set *map = set->data;
351
352 if (with_timeout(map->timeout))
353 del_timer_sync(&map->gc);
354 list_set_flush(set);
355 kfree(map);
356
357 set->data = NULL;
358}
359
360static int
361list_set_head(struct ip_set *set, struct sk_buff *skb)
362{
363 const struct list_set *map = set->data;
364 struct nlattr *nested;
365
366 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
367 if (!nested)
368 goto nla_put_failure;
369 NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
370 if (with_timeout(map->timeout))
371 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
372 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
373 htonl(atomic_read(&set->ref) - 1));
374 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
375 htonl(sizeof(*map) + map->size * map->dsize));
376 ipset_nest_end(skb, nested);
377
378 return 0;
379nla_put_failure:
380 return -EMSGSIZE;
381}
382
383static int
384list_set_list(const struct ip_set *set,
385 struct sk_buff *skb, struct netlink_callback *cb)
386{
387 const struct list_set *map = set->data;
388 struct nlattr *atd, *nested;
389 u32 i, first = cb->args[2];
390 const struct set_elem *e;
391
392 atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
393 if (!atd)
394 return -EMSGSIZE;
395 for (; cb->args[2] < map->size; cb->args[2]++) {
396 i = cb->args[2];
397 e = list_set_elem(map, i);
398 if (e->id == IPSET_INVALID_ID)
399 goto finish;
400 if (with_timeout(map->timeout) && list_set_expired(map, i))
401 continue;
402 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
403 if (!nested) {
404 if (i == first) {
405 nla_nest_cancel(skb, atd);
406 return -EMSGSIZE;
407 } else
408 goto nla_put_failure;
409 }
410 NLA_PUT_STRING(skb, IPSET_ATTR_NAME,
411 ip_set_name_byindex(e->id));
412 if (with_timeout(map->timeout)) {
413 const struct set_telem *te =
414 (const struct set_telem *) e;
415 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
416 htonl(ip_set_timeout_get(te->timeout)));
417 }
418 ipset_nest_end(skb, nested);
419 }
420finish:
421 ipset_nest_end(skb, atd);
422 /* Set listing finished */
423 cb->args[2] = 0;
424 return 0;
425
426nla_put_failure:
427 nla_nest_cancel(skb, nested);
428 ipset_nest_end(skb, atd);
429 if (unlikely(i == first)) {
430 cb->args[2] = 0;
431 return -EMSGSIZE;
432 }
433 return 0;
434}
435
436static bool
437list_set_same_set(const struct ip_set *a, const struct ip_set *b)
438{
439 const struct list_set *x = a->data;
440 const struct list_set *y = b->data;
441
442 return x->size == y->size &&
443 x->timeout == y->timeout;
444}
445
446static const struct ip_set_type_variant list_set = {
447 .kadt = list_set_kadt,
448 .uadt = list_set_uadt,
449 .destroy = list_set_destroy,
450 .flush = list_set_flush,
451 .head = list_set_head,
452 .list = list_set_list,
453 .same_set = list_set_same_set,
454};
455
456static void
457list_set_gc(unsigned long ul_set)
458{
459 struct ip_set *set = (struct ip_set *) ul_set;
460 struct list_set *map = set->data;
461 struct set_telem *e;
462 u32 i;
463
464 /* We run parallel with other readers (test element)
465 * but adding/deleting new entries is locked out */
466 read_lock_bh(&set->lock);
467 for (i = map->size - 1; i >= 0; i--) {
468 e = (struct set_telem *) list_set_elem(map, i);
469 if (e->id != IPSET_INVALID_ID &&
470 list_set_expired(map, i))
471 list_set_del(map, e->id, i);
472 }
473 read_unlock_bh(&set->lock);
474
475 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
476 add_timer(&map->gc);
477}
478
479static void
480list_set_gc_init(struct ip_set *set)
481{
482 struct list_set *map = set->data;
483
484 init_timer(&map->gc);
485 map->gc.data = (unsigned long) set;
486 map->gc.function = list_set_gc;
487 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
488 add_timer(&map->gc);
489}
490
491/* Create list:set type of sets */
492
493static bool
494init_list_set(struct ip_set *set, u32 size, size_t dsize,
495 unsigned long timeout)
496{
497 struct list_set *map;
498 struct set_elem *e;
499 u32 i;
500
501 map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL);
502 if (!map)
503 return false;
504
505 map->size = size;
506 map->dsize = dsize;
507 map->timeout = timeout;
508 set->data = map;
509
510 for (i = 0; i < size; i++) {
511 e = list_set_elem(map, i);
512 e->id = IPSET_INVALID_ID;
513 }
514
515 return true;
516}
517
518static int
519list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
520{
521 u32 size = IP_SET_LIST_DEFAULT_SIZE;
522
523 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
524 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
525 return -IPSET_ERR_PROTOCOL;
526
527 if (tb[IPSET_ATTR_SIZE])
528 size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
529 if (size < IP_SET_LIST_MIN_SIZE)
530 size = IP_SET_LIST_MIN_SIZE;
531
532 if (tb[IPSET_ATTR_TIMEOUT]) {
533 if (!init_list_set(set, size, sizeof(struct set_telem),
534 ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT])))
535 return -ENOMEM;
536
537 list_set_gc_init(set);
538 } else {
539 if (!init_list_set(set, size, sizeof(struct set_elem),
540 IPSET_NO_TIMEOUT))
541 return -ENOMEM;
542 }
543 set->variant = &list_set;
544 return 0;
545}
546
547static struct ip_set_type list_set_type __read_mostly = {
548 .name = "list:set",
549 .protocol = IPSET_PROTOCOL,
550 .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
551 .dimension = IPSET_DIM_ONE,
552 .family = AF_UNSPEC,
553 .revision = 0,
554 .create = list_set_create,
555 .create_policy = {
556 [IPSET_ATTR_SIZE] = { .type = NLA_U32 },
557 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
558 },
559 .adt_policy = {
560 [IPSET_ATTR_NAME] = { .type = NLA_STRING,
561 .len = IPSET_MAXNAMELEN },
562 [IPSET_ATTR_NAMEREF] = { .type = NLA_STRING,
563 .len = IPSET_MAXNAMELEN },
564 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
565 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
566 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
567 },
568 .me = THIS_MODULE,
569};
570
571static int __init
572list_set_init(void)
573{
574 return ip_set_type_register(&list_set_type);
575}
576
577static void __exit
578list_set_fini(void)
579{
580 ip_set_type_unregister(&list_set_type);
581}
582
583module_init(list_set_init);
584module_exit(list_set_fini);
diff --git a/net/netfilter/ipset/pfxlen.c b/net/netfilter/ipset/pfxlen.c
new file mode 100644
index 000000000000..23f8c8162214
--- /dev/null
+++ b/net/netfilter/ipset/pfxlen.c
@@ -0,0 +1,291 @@
1#include <linux/netfilter/ipset/pfxlen.h>
2
3/*
4 * Prefixlen maps for fast conversions, by Jan Engelhardt.
5 */
6
7#define E(a, b, c, d) \
8 {.ip6 = { \
9 __constant_htonl(a), __constant_htonl(b), \
10 __constant_htonl(c), __constant_htonl(d), \
11 } }
12
13/*
14 * This table works for both IPv4 and IPv6;
15 * just use prefixlen_netmask_map[prefixlength].ip.
16 */
17const union nf_inet_addr ip_set_netmask_map[] = {
18 E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
19 E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
20 E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
21 E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
22 E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
23 E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
24 E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
25 E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
26 E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
27 E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
28 E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
29 E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
30 E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
31 E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
32 E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
33 E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
34 E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
35 E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
36 E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
37 E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
38 E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
39 E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
40 E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
41 E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
42 E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
43 E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
44 E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
45 E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
46 E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
47 E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
48 E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
49 E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
50 E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
51 E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
52 E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
53 E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
54 E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
55 E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
56 E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
57 E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
58 E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
59 E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
60 E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
61 E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
62 E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
63 E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
64 E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
65 E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
66 E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
67 E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
68 E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
69 E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
70 E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
71 E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
72 E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
73 E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
74 E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
75 E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
76 E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
77 E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
78 E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
79 E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
80 E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
81 E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
82 E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
83 E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
84 E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
85 E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
86 E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
87 E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
88 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
89 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
90 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
91 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
92 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
93 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
94 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
95 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
96 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
97 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
98 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
99 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
100 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
101 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
102 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
103 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
104 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
105 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
106 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
107 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
108 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
109 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
110 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
111 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
112 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
113 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
114 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
115 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
116 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
117 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
118 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
119 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
120 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
121 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
122 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
123 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
124 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
125 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
126 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
127 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
128 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
129 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
130 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
131 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
132 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
133 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
134 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
135 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
136 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
137 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
138 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
139 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
140 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
141 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
142 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
143 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
144 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
145 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
146 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
147};
148EXPORT_SYMBOL_GPL(ip_set_netmask_map);
149
150#undef E
151#define E(a, b, c, d) \
152 {.ip6 = { (__force __be32) a, (__force __be32) b, \
153 (__force __be32) c, (__force __be32) d, \
154 } }
155
156/*
157 * This table works for both IPv4 and IPv6;
158 * just use prefixlen_hostmask_map[prefixlength].ip.
159 */
160const union nf_inet_addr ip_set_hostmask_map[] = {
161 E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
162 E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
163 E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
164 E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
165 E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
166 E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
167 E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
168 E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
169 E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
170 E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
171 E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
172 E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
173 E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
174 E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
175 E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
176 E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
177 E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
178 E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
179 E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
180 E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
181 E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
182 E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
183 E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
184 E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
185 E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
186 E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
187 E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
188 E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
189 E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
190 E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
191 E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
192 E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
193 E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
194 E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
195 E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
196 E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
197 E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
198 E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
199 E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
200 E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
201 E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
202 E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
203 E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
204 E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
205 E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
206 E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
207 E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
208 E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
209 E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
210 E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
211 E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
212 E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
213 E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
214 E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
215 E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
216 E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
217 E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
218 E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
219 E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
220 E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
221 E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
222 E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
223 E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
224 E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
225 E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
226 E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
227 E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
228 E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
229 E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
230 E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
231 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
232 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
233 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
234 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
235 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
236 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
237 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
238 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
239 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
240 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
241 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
242 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
243 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
244 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
245 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
246 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
247 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
248 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
249 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
250 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
251 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
252 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
253 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
254 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
255 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
256 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
257 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
258 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
259 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
260 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
261 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
262 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
263 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
264 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
265 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
266 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
267 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
268 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
269 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
270 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
271 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
272 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
273 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
274 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
275 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
276 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
277 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
278 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
279 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
280 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
281 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
282 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
283 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
284 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
285 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
286 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
287 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
288 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
289 E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
290};
291EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index d889f4f6be99..4d06617fab6c 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1887,7 +1887,7 @@ static int __net_init __ip_vs_init(struct net *net)
1887 ipvs->gen = atomic_read(&ipvs_netns_cnt); 1887 ipvs->gen = atomic_read(&ipvs_netns_cnt);
1888 atomic_inc(&ipvs_netns_cnt); 1888 atomic_inc(&ipvs_netns_cnt);
1889 net->ipvs = ipvs; 1889 net->ipvs = ipvs;
1890 printk(KERN_INFO "IPVS: Creating netns size=%lu id=%d\n", 1890 printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
1891 sizeof(struct netns_ipvs), ipvs->gen); 1891 sizeof(struct netns_ipvs), ipvs->gen);
1892 return 0; 1892 return 0;
1893} 1893}
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 98df59a12453..c73b0c831a2d 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3515,9 +3515,6 @@ int __net_init __ip_vs_control_init(struct net *net)
3515 } 3515 }
3516 spin_lock_init(&ipvs->tot_stats->lock); 3516 spin_lock_init(&ipvs->tot_stats->lock);
3517 3517
3518 for (idx = 0; idx < IP_VS_RTAB_SIZE; idx++)
3519 INIT_LIST_HEAD(&ipvs->rs_table[idx]);
3520
3521 proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops); 3518 proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops);
3522 proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops); 3519 proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops);
3523 proc_net_fops_create(net, "ip_vs_stats_percpu", 0, 3520 proc_net_fops_create(net, "ip_vs_stats_percpu", 0,
@@ -3555,10 +3552,15 @@ int __net_init __ip_vs_control_init(struct net *net)
3555 tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; 3552 tbl[idx++].data = &ipvs->sysctl_nat_icmp_send;
3556 3553
3557 3554
3555#ifdef CONFIG_SYSCTL
3558 ipvs->sysctl_hdr = register_net_sysctl_table(net, net_vs_ctl_path, 3556 ipvs->sysctl_hdr = register_net_sysctl_table(net, net_vs_ctl_path,
3559 tbl); 3557 tbl);
3560 if (ipvs->sysctl_hdr == NULL) 3558 if (ipvs->sysctl_hdr == NULL) {
3561 goto err_reg; 3559 if (!net_eq(net, &init_net))
3560 kfree(tbl);
3561 goto err_dup;
3562 }
3563#endif
3562 ip_vs_new_estimator(net, ipvs->tot_stats); 3564 ip_vs_new_estimator(net, ipvs->tot_stats);
3563 ipvs->sysctl_tbl = tbl; 3565 ipvs->sysctl_tbl = tbl;
3564 /* Schedule defense work */ 3566 /* Schedule defense work */
@@ -3566,9 +3568,6 @@ int __net_init __ip_vs_control_init(struct net *net)
3566 schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD); 3568 schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD);
3567 return 0; 3569 return 0;
3568 3570
3569err_reg:
3570 if (!net_eq(net, &init_net))
3571 kfree(tbl);
3572err_dup: 3571err_dup:
3573 free_percpu(ipvs->cpustats); 3572 free_percpu(ipvs->cpustats);
3574err_alloc: 3573err_alloc:
@@ -3584,7 +3583,9 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net)
3584 ip_vs_kill_estimator(net, ipvs->tot_stats); 3583 ip_vs_kill_estimator(net, ipvs->tot_stats);
3585 cancel_delayed_work_sync(&ipvs->defense_work); 3584 cancel_delayed_work_sync(&ipvs->defense_work);
3586 cancel_work_sync(&ipvs->defense_work.work); 3585 cancel_work_sync(&ipvs->defense_work.work);
3586#ifdef CONFIG_SYSCTL
3587 unregister_net_sysctl_table(ipvs->sysctl_hdr); 3587 unregister_net_sysctl_table(ipvs->sysctl_hdr);
3588#endif
3588 proc_net_remove(net, "ip_vs_stats_percpu"); 3589 proc_net_remove(net, "ip_vs_stats_percpu");
3589 proc_net_remove(net, "ip_vs_stats"); 3590 proc_net_remove(net, "ip_vs_stats");
3590 proc_net_remove(net, "ip_vs"); 3591 proc_net_remove(net, "ip_vs");
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index d5bec3371871..00b5ffab3768 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -554,33 +554,33 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
554 sizeof(vs_vars_table), 554 sizeof(vs_vars_table),
555 GFP_KERNEL); 555 GFP_KERNEL);
556 if (ipvs->lblc_ctl_table == NULL) 556 if (ipvs->lblc_ctl_table == NULL)
557 goto err_dup; 557 return -ENOMEM;
558 } else 558 } else
559 ipvs->lblc_ctl_table = vs_vars_table; 559 ipvs->lblc_ctl_table = vs_vars_table;
560 ipvs->sysctl_lblc_expiration = 24*60*60*HZ; 560 ipvs->sysctl_lblc_expiration = 24*60*60*HZ;
561 ipvs->lblc_ctl_table[0].data = &ipvs->sysctl_lblc_expiration; 561 ipvs->lblc_ctl_table[0].data = &ipvs->sysctl_lblc_expiration;
562 562
563#ifdef CONFIG_SYSCTL
563 ipvs->lblc_ctl_header = 564 ipvs->lblc_ctl_header =
564 register_net_sysctl_table(net, net_vs_ctl_path, 565 register_net_sysctl_table(net, net_vs_ctl_path,
565 ipvs->lblc_ctl_table); 566 ipvs->lblc_ctl_table);
566 if (!ipvs->lblc_ctl_header) 567 if (!ipvs->lblc_ctl_header) {
567 goto err_reg; 568 if (!net_eq(net, &init_net))
569 kfree(ipvs->lblc_ctl_table);
570 return -ENOMEM;
571 }
572#endif
568 573
569 return 0; 574 return 0;
570
571err_reg:
572 if (!net_eq(net, &init_net))
573 kfree(ipvs->lblc_ctl_table);
574
575err_dup:
576 return -ENOMEM;
577} 575}
578 576
579static void __net_exit __ip_vs_lblc_exit(struct net *net) 577static void __net_exit __ip_vs_lblc_exit(struct net *net)
580{ 578{
581 struct netns_ipvs *ipvs = net_ipvs(net); 579 struct netns_ipvs *ipvs = net_ipvs(net);
582 580
581#ifdef CONFIG_SYSCTL
583 unregister_net_sysctl_table(ipvs->lblc_ctl_header); 582 unregister_net_sysctl_table(ipvs->lblc_ctl_header);
583#endif
584 584
585 if (!net_eq(net, &init_net)) 585 if (!net_eq(net, &init_net))
586 kfree(ipvs->lblc_ctl_table); 586 kfree(ipvs->lblc_ctl_table);
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 61ae8cfcf0b4..bfa25f1ea9e4 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -754,33 +754,33 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
754 sizeof(vs_vars_table), 754 sizeof(vs_vars_table),
755 GFP_KERNEL); 755 GFP_KERNEL);
756 if (ipvs->lblcr_ctl_table == NULL) 756 if (ipvs->lblcr_ctl_table == NULL)
757 goto err_dup; 757 return -ENOMEM;
758 } else 758 } else
759 ipvs->lblcr_ctl_table = vs_vars_table; 759 ipvs->lblcr_ctl_table = vs_vars_table;
760 ipvs->sysctl_lblcr_expiration = 24*60*60*HZ; 760 ipvs->sysctl_lblcr_expiration = 24*60*60*HZ;
761 ipvs->lblcr_ctl_table[0].data = &ipvs->sysctl_lblcr_expiration; 761 ipvs->lblcr_ctl_table[0].data = &ipvs->sysctl_lblcr_expiration;
762 762
763#ifdef CONFIG_SYSCTL
763 ipvs->lblcr_ctl_header = 764 ipvs->lblcr_ctl_header =
764 register_net_sysctl_table(net, net_vs_ctl_path, 765 register_net_sysctl_table(net, net_vs_ctl_path,
765 ipvs->lblcr_ctl_table); 766 ipvs->lblcr_ctl_table);
766 if (!ipvs->lblcr_ctl_header) 767 if (!ipvs->lblcr_ctl_header) {
767 goto err_reg; 768 if (!net_eq(net, &init_net))
769 kfree(ipvs->lblcr_ctl_table);
770 return -ENOMEM;
771 }
772#endif
768 773
769 return 0; 774 return 0;
770
771err_reg:
772 if (!net_eq(net, &init_net))
773 kfree(ipvs->lblcr_ctl_table);
774
775err_dup:
776 return -ENOMEM;
777} 775}
778 776
779static void __net_exit __ip_vs_lblcr_exit(struct net *net) 777static void __net_exit __ip_vs_lblcr_exit(struct net *net)
780{ 778{
781 struct netns_ipvs *ipvs = net_ipvs(net); 779 struct netns_ipvs *ipvs = net_ipvs(net);
782 780
781#ifdef CONFIG_SYSCTL
783 unregister_net_sysctl_table(ipvs->lblcr_ctl_header); 782 unregister_net_sysctl_table(ipvs->lblcr_ctl_header);
783#endif
784 784
785 if (!net_eq(net, &init_net)) 785 if (!net_eq(net, &init_net))
786 kfree(ipvs->lblcr_ctl_table); 786 kfree(ipvs->lblcr_ctl_table);
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index d5a6e640ea45..2a2a8363ca16 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -1686,7 +1686,7 @@ int __init ip_vs_sync_init(void)
1686 return register_pernet_subsys(&ipvs_sync_ops); 1686 return register_pernet_subsys(&ipvs_sync_ops);
1687} 1687}
1688 1688
1689void __exit ip_vs_sync_cleanup(void) 1689void ip_vs_sync_cleanup(void)
1690{ 1690{
1691 unregister_pernet_subsys(&ipvs_sync_ops); 1691 unregister_pernet_subsys(&ipvs_sync_ops);
1692} 1692}
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 3fec12c570a8..b4df3eff4240 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -803,7 +803,7 @@ static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
803static int 803static int
804ctnetlink_parse_tuple(const struct nlattr * const cda[], 804ctnetlink_parse_tuple(const struct nlattr * const cda[],
805 struct nf_conntrack_tuple *tuple, 805 struct nf_conntrack_tuple *tuple,
806 enum ctattr_tuple type, u_int8_t l3num) 806 enum ctattr_type type, u_int8_t l3num)
807{ 807{
808 struct nlattr *tb[CTA_TUPLE_MAX+1]; 808 struct nlattr *tb[CTA_TUPLE_MAX+1];
809 int err; 809 int err;
diff --git a/net/netfilter/xt_devgroup.c b/net/netfilter/xt_devgroup.c
new file mode 100644
index 000000000000..d9202cdd25c9
--- /dev/null
+++ b/net/netfilter/xt_devgroup.c
@@ -0,0 +1,82 @@
1/*
2 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <linux/netdevice.h>
12
13#include <linux/netfilter/xt_devgroup.h>
14#include <linux/netfilter/x_tables.h>
15
16MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
17MODULE_LICENSE("GPL");
18MODULE_DESCRIPTION("Xtables: Device group match");
19MODULE_ALIAS("ipt_devgroup");
20MODULE_ALIAS("ip6t_devgroup");
21
22static bool devgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
23{
24 const struct xt_devgroup_info *info = par->matchinfo;
25
26 if (info->flags & XT_DEVGROUP_MATCH_SRC &&
27 (((info->src_group ^ par->in->group) & info->src_mask ? 1 : 0) ^
28 ((info->flags & XT_DEVGROUP_INVERT_SRC) ? 1 : 0)))
29 return false;
30
31 if (info->flags & XT_DEVGROUP_MATCH_DST &&
32 (((info->dst_group ^ par->out->group) & info->dst_mask ? 1 : 0) ^
33 ((info->flags & XT_DEVGROUP_INVERT_DST) ? 1 : 0)))
34 return false;
35
36 return true;
37}
38
39static int devgroup_mt_checkentry(const struct xt_mtchk_param *par)
40{
41 const struct xt_devgroup_info *info = par->matchinfo;
42
43 if (info->flags & ~(XT_DEVGROUP_MATCH_SRC | XT_DEVGROUP_INVERT_SRC |
44 XT_DEVGROUP_MATCH_DST | XT_DEVGROUP_INVERT_DST))
45 return -EINVAL;
46
47 if (info->flags & XT_DEVGROUP_MATCH_SRC &&
48 par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) |
49 (1 << NF_INET_LOCAL_IN) |
50 (1 << NF_INET_FORWARD)))
51 return -EINVAL;
52
53 if (info->flags & XT_DEVGROUP_MATCH_DST &&
54 par->hook_mask & ~((1 << NF_INET_FORWARD) |
55 (1 << NF_INET_LOCAL_OUT) |
56 (1 << NF_INET_POST_ROUTING)))
57 return -EINVAL;
58
59 return 0;
60}
61
62static struct xt_match devgroup_mt_reg __read_mostly = {
63 .name = "devgroup",
64 .match = devgroup_mt,
65 .checkentry = devgroup_mt_checkentry,
66 .matchsize = sizeof(struct xt_devgroup_info),
67 .family = NFPROTO_UNSPEC,
68 .me = THIS_MODULE
69};
70
71static int __init devgroup_mt_init(void)
72{
73 return xt_register_match(&devgroup_mt_reg);
74}
75
76static void __exit devgroup_mt_exit(void)
77{
78 xt_unregister_match(&devgroup_mt_reg);
79}
80
81module_init(devgroup_mt_init);
82module_exit(devgroup_mt_exit);
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
new file mode 100644
index 000000000000..061d48cec137
--- /dev/null
+++ b/net/netfilter/xt_set.c
@@ -0,0 +1,359 @@
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Martin Josefsson <gandalf@wlug.westbo.se>
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/* Kernel module which implements the set match and SET target
12 * for netfilter/iptables. */
13
14#include <linux/module.h>
15#include <linux/skbuff.h>
16#include <linux/version.h>
17
18#include <linux/netfilter/x_tables.h>
19#include <linux/netfilter/xt_set.h>
20
21MODULE_LICENSE("GPL");
22MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
23MODULE_DESCRIPTION("Xtables: IP set match and target module");
24MODULE_ALIAS("xt_SET");
25MODULE_ALIAS("ipt_set");
26MODULE_ALIAS("ip6t_set");
27MODULE_ALIAS("ipt_SET");
28MODULE_ALIAS("ip6t_SET");
29
30static inline int
31match_set(ip_set_id_t index, const struct sk_buff *skb,
32 u8 pf, u8 dim, u8 flags, int inv)
33{
34 if (ip_set_test(index, skb, pf, dim, flags))
35 inv = !inv;
36 return inv;
37}
38
39/* Revision 0 interface: backward compatible with netfilter/iptables */
40
41static bool
42set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
43{
44 const struct xt_set_info_match_v0 *info = par->matchinfo;
45
46 return match_set(info->match_set.index, skb, par->family,
47 info->match_set.u.compat.dim,
48 info->match_set.u.compat.flags,
49 info->match_set.u.compat.flags & IPSET_INV_MATCH);
50}
51
52static void
53compat_flags(struct xt_set_info_v0 *info)
54{
55 u_int8_t i;
56
57 /* Fill out compatibility data according to enum ip_set_kopt */
58 info->u.compat.dim = IPSET_DIM_ZERO;
59 if (info->u.flags[0] & IPSET_MATCH_INV)
60 info->u.compat.flags |= IPSET_INV_MATCH;
61 for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) {
62 info->u.compat.dim++;
63 if (info->u.flags[i] & IPSET_SRC)
64 info->u.compat.flags |= (1<<info->u.compat.dim);
65 }
66}
67
68static int
69set_match_v0_checkentry(const struct xt_mtchk_param *par)
70{
71 struct xt_set_info_match_v0 *info = par->matchinfo;
72 ip_set_id_t index;
73
74 index = ip_set_nfnl_get_byindex(info->match_set.index);
75
76 if (index == IPSET_INVALID_ID) {
77 pr_warning("Cannot find set indentified by id %u to match\n",
78 info->match_set.index);
79 return -ENOENT;
80 }
81 if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
82 pr_warning("Protocol error: set match dimension "
83 "is over the limit!\n");
84 return -ERANGE;
85 }
86
87 /* Fill out compatibility data */
88 compat_flags(&info->match_set);
89
90 return 0;
91}
92
93static void
94set_match_v0_destroy(const struct xt_mtdtor_param *par)
95{
96 struct xt_set_info_match_v0 *info = par->matchinfo;
97
98 ip_set_nfnl_put(info->match_set.index);
99}
100
101static unsigned int
102set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
103{
104 const struct xt_set_info_target_v0 *info = par->targinfo;
105
106 if (info->add_set.index != IPSET_INVALID_ID)
107 ip_set_add(info->add_set.index, skb, par->family,
108 info->add_set.u.compat.dim,
109 info->add_set.u.compat.flags);
110 if (info->del_set.index != IPSET_INVALID_ID)
111 ip_set_del(info->del_set.index, skb, par->family,
112 info->del_set.u.compat.dim,
113 info->del_set.u.compat.flags);
114
115 return XT_CONTINUE;
116}
117
118static int
119set_target_v0_checkentry(const struct xt_tgchk_param *par)
120{
121 struct xt_set_info_target_v0 *info = par->targinfo;
122 ip_set_id_t index;
123
124 if (info->add_set.index != IPSET_INVALID_ID) {
125 index = ip_set_nfnl_get_byindex(info->add_set.index);
126 if (index == IPSET_INVALID_ID) {
127 pr_warning("Cannot find add_set index %u as target\n",
128 info->add_set.index);
129 return -ENOENT;
130 }
131 }
132
133 if (info->del_set.index != IPSET_INVALID_ID) {
134 index = ip_set_nfnl_get_byindex(info->del_set.index);
135 if (index == IPSET_INVALID_ID) {
136 pr_warning("Cannot find del_set index %u as target\n",
137 info->del_set.index);
138 return -ENOENT;
139 }
140 }
141 if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 ||
142 info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
143 pr_warning("Protocol error: SET target dimension "
144 "is over the limit!\n");
145 return -ERANGE;
146 }
147
148 /* Fill out compatibility data */
149 compat_flags(&info->add_set);
150 compat_flags(&info->del_set);
151
152 return 0;
153}
154
155static void
156set_target_v0_destroy(const struct xt_tgdtor_param *par)
157{
158 const struct xt_set_info_target_v0 *info = par->targinfo;
159
160 if (info->add_set.index != IPSET_INVALID_ID)
161 ip_set_nfnl_put(info->add_set.index);
162 if (info->del_set.index != IPSET_INVALID_ID)
163 ip_set_nfnl_put(info->del_set.index);
164}
165
166/* Revision 1: current interface to netfilter/iptables */
167
168static bool
169set_match(const struct sk_buff *skb, struct xt_action_param *par)
170{
171 const struct xt_set_info_match *info = par->matchinfo;
172
173 return match_set(info->match_set.index, skb, par->family,
174 info->match_set.dim,
175 info->match_set.flags,
176 info->match_set.flags & IPSET_INV_MATCH);
177}
178
179static int
180set_match_checkentry(const struct xt_mtchk_param *par)
181{
182 struct xt_set_info_match *info = par->matchinfo;
183 ip_set_id_t index;
184
185 index = ip_set_nfnl_get_byindex(info->match_set.index);
186
187 if (index == IPSET_INVALID_ID) {
188 pr_warning("Cannot find set indentified by id %u to match\n",
189 info->match_set.index);
190 return -ENOENT;
191 }
192 if (info->match_set.dim > IPSET_DIM_MAX) {
193 pr_warning("Protocol error: set match dimension "
194 "is over the limit!\n");
195 return -ERANGE;
196 }
197
198 return 0;
199}
200
201static void
202set_match_destroy(const struct xt_mtdtor_param *par)
203{
204 struct xt_set_info_match *info = par->matchinfo;
205
206 ip_set_nfnl_put(info->match_set.index);
207}
208
209static unsigned int
210set_target(struct sk_buff *skb, const struct xt_action_param *par)
211{
212 const struct xt_set_info_target *info = par->targinfo;
213
214 if (info->add_set.index != IPSET_INVALID_ID)
215 ip_set_add(info->add_set.index,
216 skb, par->family,
217 info->add_set.dim,
218 info->add_set.flags);
219 if (info->del_set.index != IPSET_INVALID_ID)
220 ip_set_del(info->del_set.index,
221 skb, par->family,
222 info->add_set.dim,
223 info->del_set.flags);
224
225 return XT_CONTINUE;
226}
227
228static int
229set_target_checkentry(const struct xt_tgchk_param *par)
230{
231 const struct xt_set_info_target *info = par->targinfo;
232 ip_set_id_t index;
233
234 if (info->add_set.index != IPSET_INVALID_ID) {
235 index = ip_set_nfnl_get_byindex(info->add_set.index);
236 if (index == IPSET_INVALID_ID) {
237 pr_warning("Cannot find add_set index %u as target\n",
238 info->add_set.index);
239 return -ENOENT;
240 }
241 }
242
243 if (info->del_set.index != IPSET_INVALID_ID) {
244 index = ip_set_nfnl_get_byindex(info->del_set.index);
245 if (index == IPSET_INVALID_ID) {
246 pr_warning("Cannot find del_set index %u as target\n",
247 info->del_set.index);
248 return -ENOENT;
249 }
250 }
251 if (info->add_set.dim > IPSET_DIM_MAX ||
252 info->del_set.flags > IPSET_DIM_MAX) {
253 pr_warning("Protocol error: SET target dimension "
254 "is over the limit!\n");
255 return -ERANGE;
256 }
257
258 return 0;
259}
260
261static void
262set_target_destroy(const struct xt_tgdtor_param *par)
263{
264 const struct xt_set_info_target *info = par->targinfo;
265
266 if (info->add_set.index != IPSET_INVALID_ID)
267 ip_set_nfnl_put(info->add_set.index);
268 if (info->del_set.index != IPSET_INVALID_ID)
269 ip_set_nfnl_put(info->del_set.index);
270}
271
272static struct xt_match set_matches[] __read_mostly = {
273 {
274 .name = "set",
275 .family = NFPROTO_IPV4,
276 .revision = 0,
277 .match = set_match_v0,
278 .matchsize = sizeof(struct xt_set_info_match_v0),
279 .checkentry = set_match_v0_checkentry,
280 .destroy = set_match_v0_destroy,
281 .me = THIS_MODULE
282 },
283 {
284 .name = "set",
285 .family = NFPROTO_IPV4,
286 .revision = 1,
287 .match = set_match,
288 .matchsize = sizeof(struct xt_set_info_match),
289 .checkentry = set_match_checkentry,
290 .destroy = set_match_destroy,
291 .me = THIS_MODULE
292 },
293 {
294 .name = "set",
295 .family = NFPROTO_IPV6,
296 .revision = 1,
297 .match = set_match,
298 .matchsize = sizeof(struct xt_set_info_match),
299 .checkentry = set_match_checkentry,
300 .destroy = set_match_destroy,
301 .me = THIS_MODULE
302 },
303};
304
305static struct xt_target set_targets[] __read_mostly = {
306 {
307 .name = "SET",
308 .revision = 0,
309 .family = NFPROTO_IPV4,
310 .target = set_target_v0,
311 .targetsize = sizeof(struct xt_set_info_target_v0),
312 .checkentry = set_target_v0_checkentry,
313 .destroy = set_target_v0_destroy,
314 .me = THIS_MODULE
315 },
316 {
317 .name = "SET",
318 .revision = 1,
319 .family = NFPROTO_IPV4,
320 .target = set_target,
321 .targetsize = sizeof(struct xt_set_info_target),
322 .checkentry = set_target_checkentry,
323 .destroy = set_target_destroy,
324 .me = THIS_MODULE
325 },
326 {
327 .name = "SET",
328 .revision = 1,
329 .family = NFPROTO_IPV6,
330 .target = set_target,
331 .targetsize = sizeof(struct xt_set_info_target),
332 .checkentry = set_target_checkentry,
333 .destroy = set_target_destroy,
334 .me = THIS_MODULE
335 },
336};
337
338static int __init xt_set_init(void)
339{
340 int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
341
342 if (!ret) {
343 ret = xt_register_targets(set_targets,
344 ARRAY_SIZE(set_targets));
345 if (ret)
346 xt_unregister_matches(set_matches,
347 ARRAY_SIZE(set_matches));
348 }
349 return ret;
350}
351
352static void __exit xt_set_fini(void)
353{
354 xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
355 xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
356}
357
358module_init(xt_set_init);
359module_exit(xt_set_fini);