aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2013-04-08 16:50:55 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-04-29 14:08:57 -0400
commit5d50e1d88336a9334348a338731c6a7bc4823d08 (patch)
tree3b1572add68fbb414ec8d386388feb588c6e5937 /net/netfilter
parent1feab10d7e6ddb5e13d6a4bd93a1b877390262ec (diff)
netfilter: ipset: Hash types using the unified code base
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c306
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c320
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c322
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c399
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c340
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c400
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c388
7 files changed, 610 insertions, 1865 deletions
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index c486ad2d43b7..2fcfb21d9f3c 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -21,7 +21,6 @@
21#include <linux/netfilter.h> 21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h> 22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.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> 24#include <linux/netfilter/ipset/ip_set_hash.h>
26 25
27#define REVISION_MIN 0 26#define REVISION_MIN 0
@@ -33,58 +32,36 @@ IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX);
33MODULE_ALIAS("ip_set_hash:ip"); 32MODULE_ALIAS("ip_set_hash:ip");
34 33
35/* Type specific function prefix */ 34/* Type specific function prefix */
36#define TYPE hash_ip 35#define HTYPE hash_ip
37 36#define IP_SET_HASH_WITH_NETMASK
38static bool
39hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
40
41#define hash_ip4_same_set hash_ip_same_set
42#define hash_ip6_same_set hash_ip_same_set
43 37
44/* The type variant functions: IPv4 */ 38/* IPv4 variants */
45 39
46/* Member elements without timeout */ 40/* Member elements */
47struct hash_ip4_elem { 41struct hash_ip4_elem {
42 /* Zero valued IP addresses cannot be stored */
48 __be32 ip; 43 __be32 ip;
49}; 44};
50 45
51/* Member elements with timeout support */ 46struct hash_ip4t_elem {
52struct hash_ip4_telem {
53 __be32 ip; 47 __be32 ip;
54 unsigned long timeout; 48 unsigned long timeout;
55}; 49};
56 50
57static inline bool 51/* Common functions */
58hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
59 const struct hash_ip4_elem *ip2,
60 u32 *multi)
61{
62 return ip1->ip == ip2->ip;
63}
64 52
65static inline bool 53static inline bool
66hash_ip4_data_isnull(const struct hash_ip4_elem *elem) 54hash_ip4_data_equal(const struct hash_ip4_elem *e1,
67{ 55 const struct hash_ip4_elem *e2,
68 return elem->ip == 0; 56 u32 *multi)
69}
70
71static inline void
72hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
73{
74 dst->ip = src->ip;
75}
76
77/* Zero valued IP addresses cannot be stored */
78static inline void
79hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
80{ 57{
81 elem->ip = 0; 58 return e1->ip == e2->ip;
82} 59}
83 60
84static inline bool 61static inline bool
85hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data) 62hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *e)
86{ 63{
87 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip)) 64 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, e->ip))
88 goto nla_put_failure; 65 goto nla_put_failure;
89 return 0; 66 return 0;
90 67
@@ -92,41 +69,26 @@ nla_put_failure:
92 return 1; 69 return 1;
93} 70}
94 71
95static bool 72static inline void
96hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data) 73hash_ip4_data_next(struct hash_ip4_elem *next, const struct hash_ip4_elem *e)
97{ 74{
98 const struct hash_ip4_telem *tdata = 75 next->ip = e->ip;
99 (const struct hash_ip4_telem *)data;
100
101 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
102 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
103 htonl(ip_set_timeout_get(tdata->timeout))))
104 goto nla_put_failure;
105
106 return 0;
107
108nla_put_failure:
109 return 1;
110} 76}
111 77
112#define IP_SET_HASH_WITH_NETMASK 78#define MTYPE hash_ip4
113#define PF 4 79#define PF 4
114#define HOST_MASK 32 80#define HOST_MASK 32
115#include <linux/netfilter/ipset/ip_set_ahash.h> 81#include "ip_set_hash_gen.h"
116
117static inline void
118hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
119{
120 h->next.ip = d->ip;
121}
122 82
123static int 83static int
124hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, 84hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
125 const struct xt_action_param *par, 85 const struct xt_action_param *par,
126 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 86 enum ipset_adt adt, struct ip_set_adt_opt *opt)
127{ 87{
128 const struct ip_set_hash *h = set->data; 88 const struct hash_ip *h = set->data;
129 ipset_adtfn adtfn = set->variant->adt[adt]; 89 ipset_adtfn adtfn = set->variant->adt[adt];
90 struct hash_ip4_elem e = {};
91 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
130 __be32 ip; 92 __be32 ip;
131 93
132 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip); 94 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
@@ -134,17 +96,19 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
134 if (ip == 0) 96 if (ip == 0)
135 return -EINVAL; 97 return -EINVAL;
136 98
137 return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags); 99 e.ip = ip;
100 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
138} 101}
139 102
140static int 103static int
141hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], 104hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
142 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 105 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
143{ 106{
144 const struct ip_set_hash *h = set->data; 107 const struct hash_ip *h = set->data;
145 ipset_adtfn adtfn = set->variant->adt[adt]; 108 ipset_adtfn adtfn = set->variant->adt[adt];
146 u32 ip, ip_to, hosts, timeout = h->timeout; 109 struct hash_ip4_elem e = {};
147 __be32 nip; 110 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
111 u32 ip, ip_to, hosts;
148 int ret = 0; 112 int ret = 0;
149 113
150 if (unlikely(!tb[IPSET_ATTR_IP] || 114 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -154,23 +118,18 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
154 if (tb[IPSET_ATTR_LINENO]) 118 if (tb[IPSET_ATTR_LINENO])
155 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 119 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
156 120
157 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 121 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
122 ip_set_get_extensions(set, tb, &ext);
158 if (ret) 123 if (ret)
159 return ret; 124 return ret;
160 125
161 ip &= ip_set_hostmask(h->netmask); 126 ip &= ip_set_hostmask(h->netmask);
162 127
163 if (tb[IPSET_ATTR_TIMEOUT]) {
164 if (!with_timeout(h->timeout))
165 return -IPSET_ERR_TIMEOUT;
166 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
167 }
168
169 if (adt == IPSET_TEST) { 128 if (adt == IPSET_TEST) {
170 nip = htonl(ip); 129 e.ip = htonl(ip);
171 if (nip == 0) 130 if (e.ip == 0)
172 return -IPSET_ERR_HASH_ELEM; 131 return -IPSET_ERR_HASH_ELEM;
173 return adtfn(set, &nip, timeout, flags); 132 return adtfn(set, &e, &ext, &ext, flags);
174 } 133 }
175 134
176 ip_to = ip; 135 ip_to = ip;
@@ -193,10 +152,10 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
193 if (retried) 152 if (retried)
194 ip = ntohl(h->next.ip); 153 ip = ntohl(h->next.ip);
195 for (; !before(ip_to, ip); ip += hosts) { 154 for (; !before(ip_to, ip); ip += hosts) {
196 nip = htonl(ip); 155 e.ip = htonl(ip);
197 if (nip == 0) 156 if (e.ip == 0)
198 return -IPSET_ERR_HASH_ELEM; 157 return -IPSET_ERR_HASH_ELEM;
199 ret = adtfn(set, &nip, timeout, flags); 158 ret = adtfn(set, &e, &ext, &ext, flags);
200 159
201 if (ret && !ip_set_eexist(ret, flags)) 160 if (ret && !ip_set_eexist(ret, flags))
202 return ret; 161 return ret;
@@ -206,29 +165,20 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
206 return ret; 165 return ret;
207} 166}
208 167
209static bool 168/* IPv6 variants */
210hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
211{
212 const struct ip_set_hash *x = a->data;
213 const struct ip_set_hash *y = b->data;
214
215 /* Resizing changes htable_bits, so we ignore it */
216 return x->maxelem == y->maxelem &&
217 x->timeout == y->timeout &&
218 x->netmask == y->netmask;
219}
220
221/* The type variant functions: IPv6 */
222 169
170/* Member elements */
223struct hash_ip6_elem { 171struct hash_ip6_elem {
224 union nf_inet_addr ip; 172 union nf_inet_addr ip;
225}; 173};
226 174
227struct hash_ip6_telem { 175struct hash_ip6t_elem {
228 union nf_inet_addr ip; 176 union nf_inet_addr ip;
229 unsigned long timeout; 177 unsigned long timeout;
230}; 178};
231 179
180/* Common functions */
181
232static inline bool 182static inline bool
233hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 183hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
234 const struct hash_ip6_elem *ip2, 184 const struct hash_ip6_elem *ip2,
@@ -237,28 +187,16 @@ hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
237 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6); 187 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6);
238} 188}
239 189
240static inline bool
241hash_ip6_data_isnull(const struct hash_ip6_elem *elem)
242{
243 return ipv6_addr_any(&elem->ip.in6);
244}
245
246static inline void 190static inline void
247hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src) 191hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix)
248{ 192{
249 dst->ip.in6 = src->ip.in6; 193 ip6_netmask(ip, prefix);
250}
251
252static inline void
253hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
254{
255 ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0);
256} 194}
257 195
258static bool 196static bool
259hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data) 197hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *e)
260{ 198{
261 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6)) 199 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6))
262 goto nla_put_failure; 200 goto nla_put_failure;
263 return 0; 201 return 0;
264 202
@@ -266,65 +204,49 @@ nla_put_failure:
266 return 1; 204 return 1;
267} 205}
268 206
269static bool 207static inline void
270hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data) 208hash_ip6_data_next(struct hash_ip4_elem *next, const struct hash_ip6_elem *e)
271{ 209{
272 const struct hash_ip6_telem *e =
273 (const struct hash_ip6_telem *)data;
274
275 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
276 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
277 htonl(ip_set_timeout_get(e->timeout))))
278 goto nla_put_failure;
279 return 0;
280
281nla_put_failure:
282 return 1;
283} 210}
284 211
212#undef MTYPE
285#undef PF 213#undef PF
286#undef HOST_MASK 214#undef HOST_MASK
215#undef HKEY_DATALEN
287 216
217#define MTYPE hash_ip6
288#define PF 6 218#define PF 6
289#define HOST_MASK 128 219#define HOST_MASK 128
290#include <linux/netfilter/ipset/ip_set_ahash.h>
291 220
292static inline void 221#define IP_SET_EMIT_CREATE
293hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d) 222#include "ip_set_hash_gen.h"
294{
295}
296 223
297static int 224static int
298hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, 225hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
299 const struct xt_action_param *par, 226 const struct xt_action_param *par,
300 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 227 enum ipset_adt adt, struct ip_set_adt_opt *opt)
301{ 228{
302 const struct ip_set_hash *h = set->data; 229 const struct hash_ip *h = set->data;
303 ipset_adtfn adtfn = set->variant->adt[adt]; 230 ipset_adtfn adtfn = set->variant->adt[adt];
304 union nf_inet_addr ip; 231 struct hash_ip6_elem e = {};
232 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
305 233
306 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip.in6); 234 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
307 ip6_netmask(&ip, h->netmask); 235 hash_ip6_netmask(&e.ip, h->netmask);
308 if (ipv6_addr_any(&ip.in6)) 236 if (ipv6_addr_any(&e.ip.in6))
309 return -EINVAL; 237 return -EINVAL;
310 238
311 return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags); 239 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
312} 240}
313 241
314static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
315 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
316 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
317 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
318};
319
320static int 242static int
321hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], 243hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
322 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 244 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
323{ 245{
324 const struct ip_set_hash *h = set->data; 246 const struct hash_ip *h = set->data;
325 ipset_adtfn adtfn = set->variant->adt[adt]; 247 ipset_adtfn adtfn = set->variant->adt[adt];
326 union nf_inet_addr ip; 248 struct hash_ip6_elem e = {};
327 u32 timeout = h->timeout; 249 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
328 int ret; 250 int ret;
329 251
330 if (unlikely(!tb[IPSET_ATTR_IP] || 252 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -336,110 +258,20 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
336 if (tb[IPSET_ATTR_LINENO]) 258 if (tb[IPSET_ATTR_LINENO])
337 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 259 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
338 260
339 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip); 261 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
262 ip_set_get_extensions(set, tb, &ext);
340 if (ret) 263 if (ret)
341 return ret; 264 return ret;
342 265
343 ip6_netmask(&ip, h->netmask); 266 hash_ip6_netmask(&e.ip, h->netmask);
344 if (ipv6_addr_any(&ip.in6)) 267 if (ipv6_addr_any(&e.ip.in6))
345 return -IPSET_ERR_HASH_ELEM; 268 return -IPSET_ERR_HASH_ELEM;
346 269
347 if (tb[IPSET_ATTR_TIMEOUT]) { 270 ret = adtfn(set, &e, &ext, &ext, flags);
348 if (!with_timeout(h->timeout))
349 return -IPSET_ERR_TIMEOUT;
350 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
351 }
352
353 ret = adtfn(set, &ip, timeout, flags);
354 271
355 return ip_set_eexist(ret, flags) ? 0 : ret; 272 return ip_set_eexist(ret, flags) ? 0 : ret;
356} 273}
357 274
358/* Create hash:ip type of sets */
359
360static int
361hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
362{
363 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
364 u8 netmask, hbits;
365 size_t hsize;
366 struct ip_set_hash *h;
367
368 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
369 return -IPSET_ERR_INVALID_FAMILY;
370 netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
371 pr_debug("Create set %s with family %s\n",
372 set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
373
374 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
375 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
376 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
377 return -IPSET_ERR_PROTOCOL;
378
379 if (tb[IPSET_ATTR_HASHSIZE]) {
380 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
381 if (hashsize < IPSET_MIMINAL_HASHSIZE)
382 hashsize = IPSET_MIMINAL_HASHSIZE;
383 }
384
385 if (tb[IPSET_ATTR_MAXELEM])
386 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
387
388 if (tb[IPSET_ATTR_NETMASK]) {
389 netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
390
391 if ((set->family == NFPROTO_IPV4 && netmask > 32) ||
392 (set->family == NFPROTO_IPV6 && netmask > 128) ||
393 netmask == 0)
394 return -IPSET_ERR_INVALID_NETMASK;
395 }
396
397 h = kzalloc(sizeof(*h), GFP_KERNEL);
398 if (!h)
399 return -ENOMEM;
400
401 h->maxelem = maxelem;
402 h->netmask = netmask;
403 get_random_bytes(&h->initval, sizeof(h->initval));
404 h->timeout = IPSET_NO_TIMEOUT;
405
406 hbits = htable_bits(hashsize);
407 hsize = htable_size(hbits);
408 if (hsize == 0) {
409 kfree(h);
410 return -ENOMEM;
411 }
412 h->table = ip_set_alloc(hsize);
413 if (!h->table) {
414 kfree(h);
415 return -ENOMEM;
416 }
417 h->table->htable_bits = hbits;
418
419 set->data = h;
420
421 if (tb[IPSET_ATTR_TIMEOUT]) {
422 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
423
424 set->variant = set->family == NFPROTO_IPV4
425 ? &hash_ip4_tvariant : &hash_ip6_tvariant;
426
427 if (set->family == NFPROTO_IPV4)
428 hash_ip4_gc_init(set);
429 else
430 hash_ip6_gc_init(set);
431 } else {
432 set->variant = set->family == NFPROTO_IPV4
433 ? &hash_ip4_variant : &hash_ip6_variant;
434 }
435
436 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
437 set->name, jhash_size(h->table->htable_bits),
438 h->table->htable_bits, h->maxelem, set->data, h->table);
439
440 return 0;
441}
442
443static struct ip_set_type hash_ip_type __read_mostly = { 275static struct ip_set_type hash_ip_type __read_mostly = {
444 .name = "hash:ip", 276 .name = "hash:ip",
445 .protocol = IPSET_PROTOCOL, 277 .protocol = IPSET_PROTOCOL,
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index d8f77bacae86..d89cf41c657e 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -21,7 +21,6 @@
21#include <linux/netfilter.h> 21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h> 22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.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> 24#include <linux/netfilter/ipset/ip_set_getport.h>
26#include <linux/netfilter/ipset/ip_set_hash.h> 25#include <linux/netfilter/ipset/ip_set_hash.h>
27 26
@@ -34,17 +33,11 @@ IP_SET_MODULE_DESC("hash:ip,port", REVISION_MIN, REVISION_MAX);
34MODULE_ALIAS("ip_set_hash:ip,port"); 33MODULE_ALIAS("ip_set_hash:ip,port");
35 34
36/* Type specific function prefix */ 35/* Type specific function prefix */
37#define TYPE hash_ipport 36#define HTYPE hash_ipport
38 37
39static bool 38/* IPv4 variants */
40hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
41
42#define hash_ipport4_same_set hash_ipport_same_set
43#define hash_ipport6_same_set hash_ipport_same_set
44
45/* The type variant functions: IPv4 */
46 39
47/* Member elements without timeout */ 40/* Member elements */
48struct hash_ipport4_elem { 41struct hash_ipport4_elem {
49 __be32 ip; 42 __be32 ip;
50 __be16 port; 43 __be16 port;
@@ -52,8 +45,7 @@ struct hash_ipport4_elem {
52 u8 padding; 45 u8 padding;
53}; 46};
54 47
55/* Member elements with timeout support */ 48struct hash_ipport4t_elem {
56struct hash_ipport4_telem {
57 __be32 ip; 49 __be32 ip;
58 __be16 port; 50 __be16 port;
59 u8 proto; 51 u8 proto;
@@ -61,6 +53,8 @@ struct hash_ipport4_telem {
61 unsigned long timeout; 53 unsigned long timeout;
62}; 54};
63 55
56/* Common functions */
57
64static inline bool 58static inline bool
65hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, 59hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
66 const struct hash_ipport4_elem *ip2, 60 const struct hash_ipport4_elem *ip2,
@@ -71,27 +65,6 @@ hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
71 ip1->proto == ip2->proto; 65 ip1->proto == ip2->proto;
72} 66}
73 67
74static inline bool
75hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
76{
77 return elem->proto == 0;
78}
79
80static inline void
81hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
82 const struct hash_ipport4_elem *src)
83{
84 dst->ip = src->ip;
85 dst->port = src->port;
86 dst->proto = src->proto;
87}
88
89static inline void
90hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
91{
92 elem->proto = 0;
93}
94
95static bool 68static bool
96hash_ipport4_data_list(struct sk_buff *skb, 69hash_ipport4_data_list(struct sk_buff *skb,
97 const struct hash_ipport4_elem *data) 70 const struct hash_ipport4_elem *data)
@@ -106,64 +79,47 @@ nla_put_failure:
106 return 1; 79 return 1;
107} 80}
108 81
109static bool
110hash_ipport4_data_tlist(struct sk_buff *skb,
111 const struct hash_ipport4_elem *data)
112{
113 const struct hash_ipport4_telem *tdata =
114 (const struct hash_ipport4_telem *)data;
115
116 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
117 nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) ||
118 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
119 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
120 htonl(ip_set_timeout_get(tdata->timeout))))
121 goto nla_put_failure;
122 return 0;
123
124nla_put_failure:
125 return 1;
126}
127
128#define PF 4
129#define HOST_MASK 32
130#include <linux/netfilter/ipset/ip_set_ahash.h>
131
132static inline void 82static inline void
133hash_ipport4_data_next(struct ip_set_hash *h, 83hash_ipport4_data_next(struct hash_ipport4_elem *next,
134 const struct hash_ipport4_elem *d) 84 const struct hash_ipport4_elem *d)
135{ 85{
136 h->next.ip = d->ip; 86 next->ip = d->ip;
137 h->next.port = d->port; 87 next->port = d->port;
138} 88}
139 89
90#define MTYPE hash_ipport4
91#define PF 4
92#define HOST_MASK 32
93#define HKEY_DATALEN sizeof(struct hash_ipport4_elem)
94#include "ip_set_hash_gen.h"
95
140static int 96static int
141hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, 97hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
142 const struct xt_action_param *par, 98 const struct xt_action_param *par,
143 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 99 enum ipset_adt adt, struct ip_set_adt_opt *opt)
144{ 100{
145 const struct ip_set_hash *h = set->data; 101 const struct hash_ipport *h = set->data;
146 ipset_adtfn adtfn = set->variant->adt[adt]; 102 ipset_adtfn adtfn = set->variant->adt[adt];
147 struct hash_ipport4_elem data = { }; 103 struct hash_ipport4_elem e = { };
104 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
148 105
149 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 106 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
150 &data.port, &data.proto)) 107 &e.port, &e.proto))
151 return -EINVAL; 108 return -EINVAL;
152 109
153 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 110 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
154 111 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
155 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
156} 112}
157 113
158static int 114static int
159hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], 115hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
160 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 116 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
161{ 117{
162 const struct ip_set_hash *h = set->data; 118 const struct hash_ipport *h = set->data;
163 ipset_adtfn adtfn = set->variant->adt[adt]; 119 ipset_adtfn adtfn = set->variant->adt[adt];
164 struct hash_ipport4_elem data = { }; 120 struct hash_ipport4_elem e = { };
121 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
165 u32 ip, ip_to, p = 0, port, port_to; 122 u32 ip, ip_to, p = 0, port, port_to;
166 u32 timeout = h->timeout;
167 bool with_ports = false; 123 bool with_ports = false;
168 int ret; 124 int ret;
169 125
@@ -176,41 +132,36 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
176 if (tb[IPSET_ATTR_LINENO]) 132 if (tb[IPSET_ATTR_LINENO])
177 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 133 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
178 134
179 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 135 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip) ||
136 ip_set_get_extensions(set, tb, &ext);
180 if (ret) 137 if (ret)
181 return ret; 138 return ret;
182 139
183 if (tb[IPSET_ATTR_PORT]) 140 if (tb[IPSET_ATTR_PORT])
184 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 141 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
185 else 142 else
186 return -IPSET_ERR_PROTOCOL; 143 return -IPSET_ERR_PROTOCOL;
187 144
188 if (tb[IPSET_ATTR_PROTO]) { 145 if (tb[IPSET_ATTR_PROTO]) {
189 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 146 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
190 with_ports = ip_set_proto_with_ports(data.proto); 147 with_ports = ip_set_proto_with_ports(e.proto);
191 148
192 if (data.proto == 0) 149 if (e.proto == 0)
193 return -IPSET_ERR_INVALID_PROTO; 150 return -IPSET_ERR_INVALID_PROTO;
194 } else 151 } else
195 return -IPSET_ERR_MISSING_PROTO; 152 return -IPSET_ERR_MISSING_PROTO;
196 153
197 if (!(with_ports || data.proto == IPPROTO_ICMP)) 154 if (!(with_ports || e.proto == IPPROTO_ICMP))
198 data.port = 0; 155 e.port = 0;
199
200 if (tb[IPSET_ATTR_TIMEOUT]) {
201 if (!with_timeout(h->timeout))
202 return -IPSET_ERR_TIMEOUT;
203 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
204 }
205 156
206 if (adt == IPSET_TEST || 157 if (adt == IPSET_TEST ||
207 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 158 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
208 tb[IPSET_ATTR_PORT_TO])) { 159 tb[IPSET_ATTR_PORT_TO])) {
209 ret = adtfn(set, &data, timeout, flags); 160 ret = adtfn(set, &e, &ext, &ext, flags);
210 return ip_set_eexist(ret, flags) ? 0 : ret; 161 return ip_set_eexist(ret, flags) ? 0 : ret;
211 } 162 }
212 163
213 ip_to = ip = ntohl(data.ip); 164 ip_to = ip = ntohl(e.ip);
214 if (tb[IPSET_ATTR_IP_TO]) { 165 if (tb[IPSET_ATTR_IP_TO]) {
215 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 166 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
216 if (ret) 167 if (ret)
@@ -225,7 +176,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
225 ip_set_mask_from_to(ip, ip_to, cidr); 176 ip_set_mask_from_to(ip, ip_to, cidr);
226 } 177 }
227 178
228 port_to = port = ntohs(data.port); 179 port_to = port = ntohs(e.port);
229 if (with_ports && tb[IPSET_ATTR_PORT_TO]) { 180 if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
230 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 181 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
231 if (port > port_to) 182 if (port > port_to)
@@ -238,9 +189,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
238 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 189 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
239 : port; 190 : port;
240 for (; p <= port_to; p++) { 191 for (; p <= port_to; p++) {
241 data.ip = htonl(ip); 192 e.ip = htonl(ip);
242 data.port = htons(p); 193 e.port = htons(p);
243 ret = adtfn(set, &data, timeout, flags); 194 ret = adtfn(set, &e, &ext, &ext, flags);
244 195
245 if (ret && !ip_set_eexist(ret, flags)) 196 if (ret && !ip_set_eexist(ret, flags))
246 return ret; 197 return ret;
@@ -251,18 +202,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
251 return ret; 202 return ret;
252} 203}
253 204
254static bool 205/* IPv6 variants */
255hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
256{
257 const struct ip_set_hash *x = a->data;
258 const struct ip_set_hash *y = b->data;
259
260 /* Resizing changes htable_bits, so we ignore it */
261 return x->maxelem == y->maxelem &&
262 x->timeout == y->timeout;
263}
264
265/* The type variant functions: IPv6 */
266 206
267struct hash_ipport6_elem { 207struct hash_ipport6_elem {
268 union nf_inet_addr ip; 208 union nf_inet_addr ip;
@@ -271,7 +211,7 @@ struct hash_ipport6_elem {
271 u8 padding; 211 u8 padding;
272}; 212};
273 213
274struct hash_ipport6_telem { 214struct hash_ipport6t_elem {
275 union nf_inet_addr ip; 215 union nf_inet_addr ip;
276 __be16 port; 216 __be16 port;
277 u8 proto; 217 u8 proto;
@@ -279,6 +219,8 @@ struct hash_ipport6_telem {
279 unsigned long timeout; 219 unsigned long timeout;
280}; 220};
281 221
222/* Common functions */
223
282static inline bool 224static inline bool
283hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, 225hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
284 const struct hash_ipport6_elem *ip2, 226 const struct hash_ipport6_elem *ip2,
@@ -289,25 +231,6 @@ hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
289 ip1->proto == ip2->proto; 231 ip1->proto == ip2->proto;
290} 232}
291 233
292static inline bool
293hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
294{
295 return elem->proto == 0;
296}
297
298static inline void
299hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
300 const struct hash_ipport6_elem *src)
301{
302 memcpy(dst, src, sizeof(*dst));
303}
304
305static inline void
306hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
307{
308 elem->proto = 0;
309}
310
311static bool 234static bool
312hash_ipport6_data_list(struct sk_buff *skb, 235hash_ipport6_data_list(struct sk_buff *skb,
313 const struct hash_ipport6_elem *data) 236 const struct hash_ipport6_elem *data)
@@ -322,66 +245,52 @@ nla_put_failure:
322 return 1; 245 return 1;
323} 246}
324 247
325static bool 248static inline void
326hash_ipport6_data_tlist(struct sk_buff *skb, 249hash_ipport6_data_next(struct hash_ipport4_elem *next,
327 const struct hash_ipport6_elem *data) 250 const struct hash_ipport6_elem *d)
328{ 251{
329 const struct hash_ipport6_telem *e = 252 next->port = d->port;
330 (const struct hash_ipport6_telem *)data;
331
332 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
333 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
334 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
335 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
336 htonl(ip_set_timeout_get(e->timeout))))
337 goto nla_put_failure;
338 return 0;
339
340nla_put_failure:
341 return 1;
342} 253}
343 254
255#undef MTYPE
344#undef PF 256#undef PF
345#undef HOST_MASK 257#undef HOST_MASK
258#undef HKEY_DATALEN
346 259
260#define MTYPE hash_ipport6
347#define PF 6 261#define PF 6
348#define HOST_MASK 128 262#define HOST_MASK 128
349#include <linux/netfilter/ipset/ip_set_ahash.h> 263#define HKEY_DATALEN sizeof(struct hash_ipport6_elem)
350 264#define IP_SET_EMIT_CREATE
351static inline void 265#include "ip_set_hash_gen.h"
352hash_ipport6_data_next(struct ip_set_hash *h,
353 const struct hash_ipport6_elem *d)
354{
355 h->next.port = d->port;
356}
357 266
358static int 267static int
359hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, 268hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
360 const struct xt_action_param *par, 269 const struct xt_action_param *par,
361 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 270 enum ipset_adt adt, struct ip_set_adt_opt *opt)
362{ 271{
363 const struct ip_set_hash *h = set->data; 272 const struct hash_ipport *h = set->data;
364 ipset_adtfn adtfn = set->variant->adt[adt]; 273 ipset_adtfn adtfn = set->variant->adt[adt];
365 struct hash_ipport6_elem data = { }; 274 struct hash_ipport6_elem e = { };
275 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
366 276
367 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 277 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
368 &data.port, &data.proto)) 278 &e.port, &e.proto))
369 return -EINVAL; 279 return -EINVAL;
370 280
371 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 281 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
372 282 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
373 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
374} 283}
375 284
376static int 285static int
377hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], 286hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
378 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 287 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
379{ 288{
380 const struct ip_set_hash *h = set->data; 289 const struct hash_ipport *h = set->data;
381 ipset_adtfn adtfn = set->variant->adt[adt]; 290 ipset_adtfn adtfn = set->variant->adt[adt];
382 struct hash_ipport6_elem data = { }; 291 struct hash_ipport6_elem e = { };
292 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
383 u32 port, port_to; 293 u32 port, port_to;
384 u32 timeout = h->timeout;
385 bool with_ports = false; 294 bool with_ports = false;
386 int ret; 295 int ret;
387 296
@@ -396,39 +305,34 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
396 if (tb[IPSET_ATTR_LINENO]) 305 if (tb[IPSET_ATTR_LINENO])
397 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 306 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
398 307
399 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 308 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
309 ip_set_get_extensions(set, tb, &ext);
400 if (ret) 310 if (ret)
401 return ret; 311 return ret;
402 312
403 if (tb[IPSET_ATTR_PORT]) 313 if (tb[IPSET_ATTR_PORT])
404 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 314 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
405 else 315 else
406 return -IPSET_ERR_PROTOCOL; 316 return -IPSET_ERR_PROTOCOL;
407 317
408 if (tb[IPSET_ATTR_PROTO]) { 318 if (tb[IPSET_ATTR_PROTO]) {
409 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 319 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
410 with_ports = ip_set_proto_with_ports(data.proto); 320 with_ports = ip_set_proto_with_ports(e.proto);
411 321
412 if (data.proto == 0) 322 if (e.proto == 0)
413 return -IPSET_ERR_INVALID_PROTO; 323 return -IPSET_ERR_INVALID_PROTO;
414 } else 324 } else
415 return -IPSET_ERR_MISSING_PROTO; 325 return -IPSET_ERR_MISSING_PROTO;
416 326
417 if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 327 if (!(with_ports || e.proto == IPPROTO_ICMPV6))
418 data.port = 0; 328 e.port = 0;
419
420 if (tb[IPSET_ATTR_TIMEOUT]) {
421 if (!with_timeout(h->timeout))
422 return -IPSET_ERR_TIMEOUT;
423 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
424 }
425 329
426 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 330 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
427 ret = adtfn(set, &data, timeout, flags); 331 ret = adtfn(set, &e, &ext, &ext, flags);
428 return ip_set_eexist(ret, flags) ? 0 : ret; 332 return ip_set_eexist(ret, flags) ? 0 : ret;
429 } 333 }
430 334
431 port = ntohs(data.port); 335 port = ntohs(e.port);
432 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 336 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
433 if (port > port_to) 337 if (port > port_to)
434 swap(port, port_to); 338 swap(port, port_to);
@@ -436,8 +340,8 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
436 if (retried) 340 if (retried)
437 port = ntohs(h->next.port); 341 port = ntohs(h->next.port);
438 for (; port <= port_to; port++) { 342 for (; port <= port_to; port++) {
439 data.port = htons(port); 343 e.port = htons(port);
440 ret = adtfn(set, &data, timeout, flags); 344 ret = adtfn(set, &e, &ext, &ext, flags);
441 345
442 if (ret && !ip_set_eexist(ret, flags)) 346 if (ret && !ip_set_eexist(ret, flags))
443 return ret; 347 return ret;
@@ -447,78 +351,6 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
447 return ret; 351 return ret;
448} 352}
449 353
450/* Create hash:ip type of sets */
451
452static int
453hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
454{
455 struct ip_set_hash *h;
456 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
457 u8 hbits;
458 size_t hsize;
459
460 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
461 return -IPSET_ERR_INVALID_FAMILY;
462
463 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
464 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
465 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
466 return -IPSET_ERR_PROTOCOL;
467
468 if (tb[IPSET_ATTR_HASHSIZE]) {
469 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
470 if (hashsize < IPSET_MIMINAL_HASHSIZE)
471 hashsize = IPSET_MIMINAL_HASHSIZE;
472 }
473
474 if (tb[IPSET_ATTR_MAXELEM])
475 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
476
477 h = kzalloc(sizeof(*h), GFP_KERNEL);
478 if (!h)
479 return -ENOMEM;
480
481 h->maxelem = maxelem;
482 get_random_bytes(&h->initval, sizeof(h->initval));
483 h->timeout = IPSET_NO_TIMEOUT;
484
485 hbits = htable_bits(hashsize);
486 hsize = htable_size(hbits);
487 if (hsize == 0) {
488 kfree(h);
489 return -ENOMEM;
490 }
491 h->table = ip_set_alloc(hsize);
492 if (!h->table) {
493 kfree(h);
494 return -ENOMEM;
495 }
496 h->table->htable_bits = hbits;
497
498 set->data = h;
499
500 if (tb[IPSET_ATTR_TIMEOUT]) {
501 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
502
503 set->variant = set->family == NFPROTO_IPV4
504 ? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
505
506 if (set->family == NFPROTO_IPV4)
507 hash_ipport4_gc_init(set);
508 else
509 hash_ipport6_gc_init(set);
510 } else {
511 set->variant = set->family == NFPROTO_IPV4
512 ? &hash_ipport4_variant : &hash_ipport6_variant;
513 }
514
515 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
516 set->name, jhash_size(h->table->htable_bits),
517 h->table->htable_bits, h->maxelem, set->data, h->table);
518
519 return 0;
520}
521
522static struct ip_set_type hash_ipport_type __read_mostly = { 354static struct ip_set_type hash_ipport_type __read_mostly = {
523 .name = "hash:ip,port", 355 .name = "hash:ip,port",
524 .protocol = IPSET_PROTOCOL, 356 .protocol = IPSET_PROTOCOL,
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 1da1e955f38b..4b58e5c50fff 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -21,7 +21,6 @@
21#include <linux/netfilter.h> 21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h> 22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.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> 24#include <linux/netfilter/ipset/ip_set_getport.h>
26#include <linux/netfilter/ipset/ip_set_hash.h> 25#include <linux/netfilter/ipset/ip_set_hash.h>
27 26
@@ -34,17 +33,11 @@ IP_SET_MODULE_DESC("hash:ip,port,ip", REVISION_MIN, REVISION_MAX);
34MODULE_ALIAS("ip_set_hash:ip,port,ip"); 33MODULE_ALIAS("ip_set_hash:ip,port,ip");
35 34
36/* Type specific function prefix */ 35/* Type specific function prefix */
37#define TYPE hash_ipportip 36#define HTYPE hash_ipportip
38 37
39static bool 38/* IPv4 variants */
40hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
41
42#define hash_ipportip4_same_set hash_ipportip_same_set
43#define hash_ipportip6_same_set hash_ipportip_same_set
44
45/* The type variant functions: IPv4 */
46 39
47/* Member elements without timeout */ 40/* Member elements */
48struct hash_ipportip4_elem { 41struct hash_ipportip4_elem {
49 __be32 ip; 42 __be32 ip;
50 __be32 ip2; 43 __be32 ip2;
@@ -53,8 +46,7 @@ struct hash_ipportip4_elem {
53 u8 padding; 46 u8 padding;
54}; 47};
55 48
56/* Member elements with timeout support */ 49struct hash_ipportip4t_elem {
57struct hash_ipportip4_telem {
58 __be32 ip; 50 __be32 ip;
59 __be32 ip2; 51 __be32 ip2;
60 __be16 port; 52 __be16 port;
@@ -74,25 +66,6 @@ hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
74 ip1->proto == ip2->proto; 66 ip1->proto == ip2->proto;
75} 67}
76 68
77static inline bool
78hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
79{
80 return elem->proto == 0;
81}
82
83static inline void
84hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
85 const struct hash_ipportip4_elem *src)
86{
87 memcpy(dst, src, sizeof(*dst));
88}
89
90static inline void
91hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
92{
93 elem->proto = 0;
94}
95
96static bool 69static bool
97hash_ipportip4_data_list(struct sk_buff *skb, 70hash_ipportip4_data_list(struct sk_buff *skb,
98 const struct hash_ipportip4_elem *data) 71 const struct hash_ipportip4_elem *data)
@@ -108,66 +81,48 @@ nla_put_failure:
108 return 1; 81 return 1;
109} 82}
110 83
111static bool 84static inline void
112hash_ipportip4_data_tlist(struct sk_buff *skb, 85hash_ipportip4_data_next(struct hash_ipportip4_elem *next,
113 const struct hash_ipportip4_elem *data) 86 const struct hash_ipportip4_elem *d)
114{ 87{
115 const struct hash_ipportip4_telem *tdata = 88 next->ip = d->ip;
116 (const struct hash_ipportip4_telem *)data; 89 next->port = d->port;
117
118 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
119 nla_put_ipaddr4(skb, IPSET_ATTR_IP2, tdata->ip2) ||
120 nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) ||
121 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
122 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
123 htonl(ip_set_timeout_get(tdata->timeout))))
124 goto nla_put_failure;
125 return 0;
126
127nla_put_failure:
128 return 1;
129} 90}
130 91
92/* Common functions */
93#define MTYPE hash_ipportip4
131#define PF 4 94#define PF 4
132#define HOST_MASK 32 95#define HOST_MASK 32
133#include <linux/netfilter/ipset/ip_set_ahash.h> 96#include "ip_set_hash_gen.h"
134
135static inline void
136hash_ipportip4_data_next(struct ip_set_hash *h,
137 const struct hash_ipportip4_elem *d)
138{
139 h->next.ip = d->ip;
140 h->next.port = d->port;
141}
142 97
143static int 98static int
144hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, 99hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
145 const struct xt_action_param *par, 100 const struct xt_action_param *par,
146 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 101 enum ipset_adt adt, struct ip_set_adt_opt *opt)
147{ 102{
148 const struct ip_set_hash *h = set->data; 103 const struct hash_ipportip *h = set->data;
149 ipset_adtfn adtfn = set->variant->adt[adt]; 104 ipset_adtfn adtfn = set->variant->adt[adt];
150 struct hash_ipportip4_elem data = { }; 105 struct hash_ipportip4_elem e = { };
106 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
151 107
152 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 108 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
153 &data.port, &data.proto)) 109 &e.port, &e.proto))
154 return -EINVAL; 110 return -EINVAL;
155 111
156 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 112 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
157 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2); 113 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2);
158 114 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
159 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
160} 115}
161 116
162static int 117static int
163hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], 118hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
164 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 119 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
165{ 120{
166 const struct ip_set_hash *h = set->data; 121 const struct hash_ipportip *h = set->data;
167 ipset_adtfn adtfn = set->variant->adt[adt]; 122 ipset_adtfn adtfn = set->variant->adt[adt];
168 struct hash_ipportip4_elem data = { }; 123 struct hash_ipportip4_elem e = { };
124 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
169 u32 ip, ip_to, p = 0, port, port_to; 125 u32 ip, ip_to, p = 0, port, port_to;
170 u32 timeout = h->timeout;
171 bool with_ports = false; 126 bool with_ports = false;
172 int ret; 127 int ret;
173 128
@@ -180,45 +135,40 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
180 if (tb[IPSET_ATTR_LINENO]) 135 if (tb[IPSET_ATTR_LINENO])
181 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 136 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
182 137
183 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 138 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip) ||
139 ip_set_get_extensions(set, tb, &ext);
184 if (ret) 140 if (ret)
185 return ret; 141 return ret;
186 142
187 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2); 143 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &e.ip2);
188 if (ret) 144 if (ret)
189 return ret; 145 return ret;
190 146
191 if (tb[IPSET_ATTR_PORT]) 147 if (tb[IPSET_ATTR_PORT])
192 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 148 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
193 else 149 else
194 return -IPSET_ERR_PROTOCOL; 150 return -IPSET_ERR_PROTOCOL;
195 151
196 if (tb[IPSET_ATTR_PROTO]) { 152 if (tb[IPSET_ATTR_PROTO]) {
197 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 153 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
198 with_ports = ip_set_proto_with_ports(data.proto); 154 with_ports = ip_set_proto_with_ports(e.proto);
199 155
200 if (data.proto == 0) 156 if (e.proto == 0)
201 return -IPSET_ERR_INVALID_PROTO; 157 return -IPSET_ERR_INVALID_PROTO;
202 } else 158 } else
203 return -IPSET_ERR_MISSING_PROTO; 159 return -IPSET_ERR_MISSING_PROTO;
204 160
205 if (!(with_ports || data.proto == IPPROTO_ICMP)) 161 if (!(with_ports || e.proto == IPPROTO_ICMP))
206 data.port = 0; 162 e.port = 0;
207
208 if (tb[IPSET_ATTR_TIMEOUT]) {
209 if (!with_timeout(h->timeout))
210 return -IPSET_ERR_TIMEOUT;
211 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
212 }
213 163
214 if (adt == IPSET_TEST || 164 if (adt == IPSET_TEST ||
215 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 165 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
216 tb[IPSET_ATTR_PORT_TO])) { 166 tb[IPSET_ATTR_PORT_TO])) {
217 ret = adtfn(set, &data, timeout, flags); 167 ret = adtfn(set, &e, &ext, &ext, flags);
218 return ip_set_eexist(ret, flags) ? 0 : ret; 168 return ip_set_eexist(ret, flags) ? 0 : ret;
219 } 169 }
220 170
221 ip_to = ip = ntohl(data.ip); 171 ip_to = ip = ntohl(e.ip);
222 if (tb[IPSET_ATTR_IP_TO]) { 172 if (tb[IPSET_ATTR_IP_TO]) {
223 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 173 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
224 if (ret) 174 if (ret)
@@ -233,7 +183,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
233 ip_set_mask_from_to(ip, ip_to, cidr); 183 ip_set_mask_from_to(ip, ip_to, cidr);
234 } 184 }
235 185
236 port_to = port = ntohs(data.port); 186 port_to = port = ntohs(e.port);
237 if (with_ports && tb[IPSET_ATTR_PORT_TO]) { 187 if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
238 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 188 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
239 if (port > port_to) 189 if (port > port_to)
@@ -246,9 +196,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
246 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 196 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
247 : port; 197 : port;
248 for (; p <= port_to; p++) { 198 for (; p <= port_to; p++) {
249 data.ip = htonl(ip); 199 e.ip = htonl(ip);
250 data.port = htons(p); 200 e.port = htons(p);
251 ret = adtfn(set, &data, timeout, flags); 201 ret = adtfn(set, &e, &ext, &ext, flags);
252 202
253 if (ret && !ip_set_eexist(ret, flags)) 203 if (ret && !ip_set_eexist(ret, flags))
254 return ret; 204 return ret;
@@ -259,18 +209,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
259 return ret; 209 return ret;
260} 210}
261 211
262static bool 212/* IPv6 variants */
263hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
264{
265 const struct ip_set_hash *x = a->data;
266 const struct ip_set_hash *y = b->data;
267
268 /* Resizing changes htable_bits, so we ignore it */
269 return x->maxelem == y->maxelem &&
270 x->timeout == y->timeout;
271}
272
273/* The type variant functions: IPv6 */
274 213
275struct hash_ipportip6_elem { 214struct hash_ipportip6_elem {
276 union nf_inet_addr ip; 215 union nf_inet_addr ip;
@@ -280,7 +219,7 @@ struct hash_ipportip6_elem {
280 u8 padding; 219 u8 padding;
281}; 220};
282 221
283struct hash_ipportip6_telem { 222struct hash_ipportip6t_elem {
284 union nf_inet_addr ip; 223 union nf_inet_addr ip;
285 union nf_inet_addr ip2; 224 union nf_inet_addr ip2;
286 __be16 port; 225 __be16 port;
@@ -289,6 +228,8 @@ struct hash_ipportip6_telem {
289 unsigned long timeout; 228 unsigned long timeout;
290}; 229};
291 230
231/* Common functions */
232
292static inline bool 233static inline bool
293hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 234hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
294 const struct hash_ipportip6_elem *ip2, 235 const struct hash_ipportip6_elem *ip2,
@@ -300,25 +241,6 @@ hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
300 ip1->proto == ip2->proto; 241 ip1->proto == ip2->proto;
301} 242}
302 243
303static inline bool
304hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
305{
306 return elem->proto == 0;
307}
308
309static inline void
310hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
311 const struct hash_ipportip6_elem *src)
312{
313 memcpy(dst, src, sizeof(*dst));
314}
315
316static inline void
317hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
318{
319 elem->proto = 0;
320}
321
322static bool 244static bool
323hash_ipportip6_data_list(struct sk_buff *skb, 245hash_ipportip6_data_list(struct sk_buff *skb,
324 const struct hash_ipportip6_elem *data) 246 const struct hash_ipportip6_elem *data)
@@ -334,68 +256,51 @@ nla_put_failure:
334 return 1; 256 return 1;
335} 257}
336 258
337static bool 259static inline void
338hash_ipportip6_data_tlist(struct sk_buff *skb, 260hash_ipportip6_data_next(struct hash_ipportip4_elem *next,
339 const struct hash_ipportip6_elem *data) 261 const struct hash_ipportip6_elem *d)
340{ 262{
341 const struct hash_ipportip6_telem *e = 263 next->port = d->port;
342 (const struct hash_ipportip6_telem *)data;
343
344 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
345 nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
346 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
347 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
348 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
349 htonl(ip_set_timeout_get(e->timeout))))
350 goto nla_put_failure;
351 return 0;
352
353nla_put_failure:
354 return 1;
355} 264}
356 265
266#undef MTYPE
357#undef PF 267#undef PF
358#undef HOST_MASK 268#undef HOST_MASK
359 269
270#define MTYPE hash_ipportip6
360#define PF 6 271#define PF 6
361#define HOST_MASK 128 272#define HOST_MASK 128
362#include <linux/netfilter/ipset/ip_set_ahash.h> 273#define IP_SET_EMIT_CREATE
363 274#include "ip_set_hash_gen.h"
364static inline void
365hash_ipportip6_data_next(struct ip_set_hash *h,
366 const struct hash_ipportip6_elem *d)
367{
368 h->next.port = d->port;
369}
370 275
371static int 276static int
372hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, 277hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
373 const struct xt_action_param *par, 278 const struct xt_action_param *par,
374 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 279 enum ipset_adt adt, struct ip_set_adt_opt *opt)
375{ 280{
376 const struct ip_set_hash *h = set->data; 281 const struct hash_ipportip *h = set->data;
377 ipset_adtfn adtfn = set->variant->adt[adt]; 282 ipset_adtfn adtfn = set->variant->adt[adt];
378 struct hash_ipportip6_elem data = { }; 283 struct hash_ipportip6_elem e = { };
284 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
379 285
380 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 286 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
381 &data.port, &data.proto)) 287 &e.port, &e.proto))
382 return -EINVAL; 288 return -EINVAL;
383 289
384 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 290 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
385 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); 291 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6);
386 292 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
387 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
388} 293}
389 294
390static int 295static int
391hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], 296hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
392 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 297 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
393{ 298{
394 const struct ip_set_hash *h = set->data; 299 const struct hash_ipportip *h = set->data;
395 ipset_adtfn adtfn = set->variant->adt[adt]; 300 ipset_adtfn adtfn = set->variant->adt[adt];
396 struct hash_ipportip6_elem data = { }; 301 struct hash_ipportip6_elem e = { };
302 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
397 u32 port, port_to; 303 u32 port, port_to;
398 u32 timeout = h->timeout;
399 bool with_ports = false; 304 bool with_ports = false;
400 int ret; 305 int ret;
401 306
@@ -410,43 +315,38 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
410 if (tb[IPSET_ATTR_LINENO]) 315 if (tb[IPSET_ATTR_LINENO])
411 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 316 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
412 317
413 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 318 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
319 ip_set_get_extensions(set, tb, &ext);
414 if (ret) 320 if (ret)
415 return ret; 321 return ret;
416 322
417 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); 323 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2);
418 if (ret) 324 if (ret)
419 return ret; 325 return ret;
420 326
421 if (tb[IPSET_ATTR_PORT]) 327 if (tb[IPSET_ATTR_PORT])
422 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 328 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
423 else 329 else
424 return -IPSET_ERR_PROTOCOL; 330 return -IPSET_ERR_PROTOCOL;
425 331
426 if (tb[IPSET_ATTR_PROTO]) { 332 if (tb[IPSET_ATTR_PROTO]) {
427 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 333 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
428 with_ports = ip_set_proto_with_ports(data.proto); 334 with_ports = ip_set_proto_with_ports(e.proto);
429 335
430 if (data.proto == 0) 336 if (e.proto == 0)
431 return -IPSET_ERR_INVALID_PROTO; 337 return -IPSET_ERR_INVALID_PROTO;
432 } else 338 } else
433 return -IPSET_ERR_MISSING_PROTO; 339 return -IPSET_ERR_MISSING_PROTO;
434 340
435 if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 341 if (!(with_ports || e.proto == IPPROTO_ICMPV6))
436 data.port = 0; 342 e.port = 0;
437
438 if (tb[IPSET_ATTR_TIMEOUT]) {
439 if (!with_timeout(h->timeout))
440 return -IPSET_ERR_TIMEOUT;
441 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
442 }
443 343
444 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 344 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
445 ret = adtfn(set, &data, timeout, flags); 345 ret = adtfn(set, &e, &ext, &ext, flags);
446 return ip_set_eexist(ret, flags) ? 0 : ret; 346 return ip_set_eexist(ret, flags) ? 0 : ret;
447 } 347 }
448 348
449 port = ntohs(data.port); 349 port = ntohs(e.port);
450 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 350 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
451 if (port > port_to) 351 if (port > port_to)
452 swap(port, port_to); 352 swap(port, port_to);
@@ -454,8 +354,8 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
454 if (retried) 354 if (retried)
455 port = ntohs(h->next.port); 355 port = ntohs(h->next.port);
456 for (; port <= port_to; port++) { 356 for (; port <= port_to; port++) {
457 data.port = htons(port); 357 e.port = htons(port);
458 ret = adtfn(set, &data, timeout, flags); 358 ret = adtfn(set, &e, &ext, &ext, flags);
459 359
460 if (ret && !ip_set_eexist(ret, flags)) 360 if (ret && !ip_set_eexist(ret, flags))
461 return ret; 361 return ret;
@@ -465,78 +365,6 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
465 return ret; 365 return ret;
466} 366}
467 367
468/* Create hash:ip type of sets */
469
470static int
471hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
472{
473 struct ip_set_hash *h;
474 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
475 u8 hbits;
476 size_t hsize;
477
478 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
479 return -IPSET_ERR_INVALID_FAMILY;
480
481 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
482 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
483 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
484 return -IPSET_ERR_PROTOCOL;
485
486 if (tb[IPSET_ATTR_HASHSIZE]) {
487 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
488 if (hashsize < IPSET_MIMINAL_HASHSIZE)
489 hashsize = IPSET_MIMINAL_HASHSIZE;
490 }
491
492 if (tb[IPSET_ATTR_MAXELEM])
493 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
494
495 h = kzalloc(sizeof(*h), 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 hsize = htable_size(hbits);
505 if (hsize == 0) {
506 kfree(h);
507 return -ENOMEM;
508 }
509 h->table = ip_set_alloc(hsize);
510 if (!h->table) {
511 kfree(h);
512 return -ENOMEM;
513 }
514 h->table->htable_bits = hbits;
515
516 set->data = h;
517
518 if (tb[IPSET_ATTR_TIMEOUT]) {
519 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
520
521 set->variant = set->family == NFPROTO_IPV4
522 ? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
523
524 if (set->family == NFPROTO_IPV4)
525 hash_ipportip4_gc_init(set);
526 else
527 hash_ipportip6_gc_init(set);
528 } else {
529 set->variant = set->family == NFPROTO_IPV4
530 ? &hash_ipportip4_variant : &hash_ipportip6_variant;
531 }
532
533 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
534 set->name, jhash_size(h->table->htable_bits),
535 h->table->htable_bits, h->maxelem, set->data, h->table);
536
537 return 0;
538}
539
540static struct ip_set_type hash_ipportip_type __read_mostly = { 368static struct ip_set_type hash_ipportip_type __read_mostly = {
541 .name = "hash:ip,port,ip", 369 .name = "hash:ip,port,ip",
542 .protocol = IPSET_PROTOCOL, 370 .protocol = IPSET_PROTOCOL,
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 352f8b4a63e5..bfde4ead9bbc 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -21,7 +21,6 @@
21#include <linux/netfilter.h> 21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h> 22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.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> 24#include <linux/netfilter/ipset/ip_set_getport.h>
26#include <linux/netfilter/ipset/ip_set_hash.h> 25#include <linux/netfilter/ipset/ip_set_hash.h>
27 26
@@ -36,23 +35,19 @@ IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX);
36MODULE_ALIAS("ip_set_hash:ip,port,net"); 35MODULE_ALIAS("ip_set_hash:ip,port,net");
37 36
38/* Type specific function prefix */ 37/* Type specific function prefix */
39#define TYPE hash_ipportnet 38#define HTYPE hash_ipportnet
40
41static bool
42hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
43
44#define hash_ipportnet4_same_set hash_ipportnet_same_set
45#define hash_ipportnet6_same_set hash_ipportnet_same_set
46
47/* The type variant functions: IPv4 */
48 39
49/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0 40/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0
50 * However this way we have to store internally cidr - 1, 41 * However this way we have to store internally cidr - 1,
51 * dancing back and forth. 42 * dancing back and forth.
52 */ 43 */
53#define IP_SET_HASH_WITH_NETS_PACKED 44#define IP_SET_HASH_WITH_NETS_PACKED
45#define IP_SET_HASH_WITH_PROTO
46#define IP_SET_HASH_WITH_NETS
54 47
55/* Member elements without timeout */ 48/* IPv4 variants */
49
50/* Member elements */
56struct hash_ipportnet4_elem { 51struct hash_ipportnet4_elem {
57 __be32 ip; 52 __be32 ip;
58 __be32 ip2; 53 __be32 ip2;
@@ -62,8 +57,7 @@ struct hash_ipportnet4_elem {
62 u8 proto; 57 u8 proto;
63}; 58};
64 59
65/* Member elements with timeout support */ 60struct hash_ipportnet4t_elem {
66struct hash_ipportnet4_telem {
67 __be32 ip; 61 __be32 ip;
68 __be32 ip2; 62 __be32 ip2;
69 __be16 port; 63 __be16 port;
@@ -73,6 +67,8 @@ struct hash_ipportnet4_telem {
73 unsigned long timeout; 67 unsigned long timeout;
74}; 68};
75 69
70/* Common functions */
71
76static inline bool 72static inline bool
77hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, 73hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
78 const struct hash_ipportnet4_elem *ip2, 74 const struct hash_ipportnet4_elem *ip2,
@@ -85,38 +81,22 @@ hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
85 ip1->proto == ip2->proto; 81 ip1->proto == ip2->proto;
86} 82}
87 83
88static inline bool 84static inline int
89hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem) 85hash_ipportnet4_do_data_match(const struct hash_ipportnet4_elem *elem)
90{ 86{
91 return elem->proto == 0; 87 return elem->nomatch ? -ENOTEMPTY : 1;
92} 88}
93 89
94static inline void 90static inline void
95hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst, 91hash_ipportnet4_data_set_flags(struct hash_ipportnet4_elem *elem, u32 flags)
96 const struct hash_ipportnet4_elem *src)
97{ 92{
98 memcpy(dst, src, sizeof(*dst)); 93 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
99} 94}
100 95
101static inline void 96static inline void
102hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags) 97hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *elem, u8 *flags)
103{ 98{
104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 99 swap(*flags, elem->nomatch);
105}
106
107static inline void
108hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *dst, u32 *flags)
109{
110 if (dst->nomatch) {
111 *flags = IPSET_FLAG_NOMATCH;
112 dst->nomatch = 0;
113 }
114}
115
116static inline int
117hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
118{
119 return elem->nomatch ? -ENOTEMPTY : 1;
120} 100}
121 101
122static inline void 102static inline void
@@ -126,12 +106,6 @@ hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
126 elem->cidr = cidr - 1; 106 elem->cidr = cidr - 1;
127} 107}
128 108
129static inline void
130hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
131{
132 elem->proto = 0;
133}
134
135static bool 109static bool
136hash_ipportnet4_data_list(struct sk_buff *skb, 110hash_ipportnet4_data_list(struct sk_buff *skb,
137 const struct hash_ipportnet4_elem *data) 111 const struct hash_ipportnet4_elem *data)
@@ -152,81 +126,56 @@ nla_put_failure:
152 return 1; 126 return 1;
153} 127}
154 128
155static bool 129static inline void
156hash_ipportnet4_data_tlist(struct sk_buff *skb, 130hash_ipportnet4_data_next(struct hash_ipportnet4_elem *next,
157 const struct hash_ipportnet4_elem *data) 131 const struct hash_ipportnet4_elem *d)
158{ 132{
159 const struct hash_ipportnet4_telem *tdata = 133 next->ip = d->ip;
160 (const struct hash_ipportnet4_telem *)data; 134 next->port = d->port;
161 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 135 next->ip2 = d->ip2;
162
163 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
164 nla_put_ipaddr4(skb, IPSET_ATTR_IP2, tdata->ip2) ||
165 nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) ||
166 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
167 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
168 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
169 htonl(ip_set_timeout_get(tdata->timeout))) ||
170 (flags &&
171 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
172 goto nla_put_failure;
173 return 0;
174
175nla_put_failure:
176 return 1;
177} 136}
178 137
179#define IP_SET_HASH_WITH_PROTO 138#define MTYPE hash_ipportnet4
180#define IP_SET_HASH_WITH_NETS
181
182#define PF 4 139#define PF 4
183#define HOST_MASK 32 140#define HOST_MASK 32
184#include <linux/netfilter/ipset/ip_set_ahash.h> 141#include "ip_set_hash_gen.h"
185
186static inline void
187hash_ipportnet4_data_next(struct ip_set_hash *h,
188 const struct hash_ipportnet4_elem *d)
189{
190 h->next.ip = d->ip;
191 h->next.port = d->port;
192 h->next.ip2 = d->ip2;
193}
194 142
195static int 143static int
196hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, 144hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
197 const struct xt_action_param *par, 145 const struct xt_action_param *par,
198 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 146 enum ipset_adt adt, struct ip_set_adt_opt *opt)
199{ 147{
200 const struct ip_set_hash *h = set->data; 148 const struct hash_ipportnet *h = set->data;
201 ipset_adtfn adtfn = set->variant->adt[adt]; 149 ipset_adtfn adtfn = set->variant->adt[adt];
202 struct hash_ipportnet4_elem data = { 150 struct hash_ipportnet4_elem e = {
203 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 151 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
204 }; 152 };
153 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
205 154
206 if (adt == IPSET_TEST) 155 if (adt == IPSET_TEST)
207 data.cidr = HOST_MASK - 1; 156 e.cidr = HOST_MASK - 1;
208 157
209 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 158 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
210 &data.port, &data.proto)) 159 &e.port, &e.proto))
211 return -EINVAL; 160 return -EINVAL;
212 161
213 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 162 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
214 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2); 163 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2);
215 data.ip2 &= ip_set_netmask(data.cidr + 1); 164 e.ip2 &= ip_set_netmask(e.cidr + 1);
216 165
217 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 166 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
218} 167}
219 168
220static int 169static int
221hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], 170hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
222 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 171 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
223{ 172{
224 const struct ip_set_hash *h = set->data; 173 const struct hash_ipportnet *h = set->data;
225 ipset_adtfn adtfn = set->variant->adt[adt]; 174 ipset_adtfn adtfn = set->variant->adt[adt];
226 struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 }; 175 struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
176 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
227 u32 ip, ip_to, p = 0, port, port_to; 177 u32 ip, ip_to, p = 0, port, port_to;
228 u32 ip2_from, ip2_to, ip2_last, ip2; 178 u32 ip2_from, ip2_to, ip2_last, ip2;
229 u32 timeout = h->timeout;
230 bool with_ports = false; 179 bool with_ports = false;
231 u8 cidr; 180 u8 cidr;
232 int ret; 181 int ret;
@@ -241,7 +190,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
241 if (tb[IPSET_ATTR_LINENO]) 190 if (tb[IPSET_ATTR_LINENO])
242 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 191 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
243 192
244 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 193 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
194 ip_set_get_extensions(set, tb, &ext);
245 if (ret) 195 if (ret)
246 return ret; 196 return ret;
247 197
@@ -253,31 +203,25 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
253 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 203 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
254 if (!cidr || cidr > HOST_MASK) 204 if (!cidr || cidr > HOST_MASK)
255 return -IPSET_ERR_INVALID_CIDR; 205 return -IPSET_ERR_INVALID_CIDR;
256 data.cidr = cidr - 1; 206 e.cidr = cidr - 1;
257 } 207 }
258 208
259 if (tb[IPSET_ATTR_PORT]) 209 if (tb[IPSET_ATTR_PORT])
260 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 210 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
261 else 211 else
262 return -IPSET_ERR_PROTOCOL; 212 return -IPSET_ERR_PROTOCOL;
263 213
264 if (tb[IPSET_ATTR_PROTO]) { 214 if (tb[IPSET_ATTR_PROTO]) {
265 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 215 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
266 with_ports = ip_set_proto_with_ports(data.proto); 216 with_ports = ip_set_proto_with_ports(e.proto);
267 217
268 if (data.proto == 0) 218 if (e.proto == 0)
269 return -IPSET_ERR_INVALID_PROTO; 219 return -IPSET_ERR_INVALID_PROTO;
270 } else 220 } else
271 return -IPSET_ERR_MISSING_PROTO; 221 return -IPSET_ERR_MISSING_PROTO;
272 222
273 if (!(with_ports || data.proto == IPPROTO_ICMP)) 223 if (!(with_ports || e.proto == IPPROTO_ICMP))
274 data.port = 0; 224 e.port = 0;
275
276 if (tb[IPSET_ATTR_TIMEOUT]) {
277 if (!with_timeout(h->timeout))
278 return -IPSET_ERR_TIMEOUT;
279 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
280 }
281 225
282 if (tb[IPSET_ATTR_CADT_FLAGS]) { 226 if (tb[IPSET_ATTR_CADT_FLAGS]) {
283 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 227 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -289,9 +233,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
289 if (adt == IPSET_TEST || 233 if (adt == IPSET_TEST ||
290 !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports || 234 !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
291 tb[IPSET_ATTR_IP2_TO])) { 235 tb[IPSET_ATTR_IP2_TO])) {
292 data.ip = htonl(ip); 236 e.ip = htonl(ip);
293 data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1)); 237 e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1));
294 ret = adtfn(set, &data, timeout, flags); 238 ret = adtfn(set, &e, &ext, &ext, flags);
295 return ip_set_enomatch(ret, flags, adt) ? 1 : 239 return ip_set_enomatch(ret, flags, adt) ? 1 :
296 ip_set_eexist(ret, flags) ? 0 : ret; 240 ip_set_eexist(ret, flags) ? 0 : ret;
297 } 241 }
@@ -311,7 +255,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
311 ip_set_mask_from_to(ip, ip_to, cidr); 255 ip_set_mask_from_to(ip, ip_to, cidr);
312 } 256 }
313 257
314 port_to = port = ntohs(data.port); 258 port_to = port = ntohs(e.port);
315 if (tb[IPSET_ATTR_PORT_TO]) { 259 if (tb[IPSET_ATTR_PORT_TO]) {
316 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 260 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
317 if (port > port_to) 261 if (port > port_to)
@@ -327,28 +271,27 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
327 swap(ip2_from, ip2_to); 271 swap(ip2_from, ip2_to);
328 if (ip2_from + UINT_MAX == ip2_to) 272 if (ip2_from + UINT_MAX == ip2_to)
329 return -IPSET_ERR_HASH_RANGE; 273 return -IPSET_ERR_HASH_RANGE;
330 } else { 274 } else
331 ip_set_mask_from_to(ip2_from, ip2_to, data.cidr + 1); 275 ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1);
332 }
333 276
334 if (retried) 277 if (retried)
335 ip = ntohl(h->next.ip); 278 ip = ntohl(h->next.ip);
336 for (; !before(ip_to, ip); ip++) { 279 for (; !before(ip_to, ip); ip++) {
337 data.ip = htonl(ip); 280 e.ip = htonl(ip);
338 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 281 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
339 : port; 282 : port;
340 for (; p <= port_to; p++) { 283 for (; p <= port_to; p++) {
341 data.port = htons(p); 284 e.port = htons(p);
342 ip2 = retried 285 ip2 = retried
343 && ip == ntohl(h->next.ip) 286 && ip == ntohl(h->next.ip)
344 && p == ntohs(h->next.port) 287 && p == ntohs(h->next.port)
345 ? ntohl(h->next.ip2) : ip2_from; 288 ? ntohl(h->next.ip2) : ip2_from;
346 while (!after(ip2, ip2_to)) { 289 while (!after(ip2, ip2_to)) {
347 data.ip2 = htonl(ip2); 290 e.ip2 = htonl(ip2);
348 ip2_last = ip_set_range_to_cidr(ip2, ip2_to, 291 ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
349 &cidr); 292 &cidr);
350 data.cidr = cidr - 1; 293 e.cidr = cidr - 1;
351 ret = adtfn(set, &data, timeout, flags); 294 ret = adtfn(set, &e, &ext, &ext, flags);
352 295
353 if (ret && !ip_set_eexist(ret, flags)) 296 if (ret && !ip_set_eexist(ret, flags))
354 return ret; 297 return ret;
@@ -361,18 +304,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
361 return ret; 304 return ret;
362} 305}
363 306
364static bool 307/* IPv6 variants */
365hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
366{
367 const struct ip_set_hash *x = a->data;
368 const struct ip_set_hash *y = b->data;
369
370 /* Resizing changes htable_bits, so we ignore it */
371 return x->maxelem == y->maxelem &&
372 x->timeout == y->timeout;
373}
374
375/* The type variant functions: IPv6 */
376 308
377struct hash_ipportnet6_elem { 309struct hash_ipportnet6_elem {
378 union nf_inet_addr ip; 310 union nf_inet_addr ip;
@@ -383,7 +315,7 @@ struct hash_ipportnet6_elem {
383 u8 proto; 315 u8 proto;
384}; 316};
385 317
386struct hash_ipportnet6_telem { 318struct hash_ipportnet6t_elem {
387 union nf_inet_addr ip; 319 union nf_inet_addr ip;
388 union nf_inet_addr ip2; 320 union nf_inet_addr ip2;
389 __be16 port; 321 __be16 port;
@@ -393,6 +325,8 @@ struct hash_ipportnet6_telem {
393 unsigned long timeout; 325 unsigned long timeout;
394}; 326};
395 327
328/* Common functions */
329
396static inline bool 330static inline bool
397hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 331hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
398 const struct hash_ipportnet6_elem *ip2, 332 const struct hash_ipportnet6_elem *ip2,
@@ -405,44 +339,22 @@ hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
405 ip1->proto == ip2->proto; 339 ip1->proto == ip2->proto;
406} 340}
407 341
408static inline bool 342static inline int
409hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem) 343hash_ipportnet6_do_data_match(const struct hash_ipportnet6_elem *elem)
410{
411 return elem->proto == 0;
412}
413
414static inline void
415hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
416 const struct hash_ipportnet6_elem *src)
417{
418 memcpy(dst, src, sizeof(*dst));
419}
420
421static inline void
422hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
423{ 344{
424 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 345 return elem->nomatch ? -ENOTEMPTY : 1;
425} 346}
426 347
427static inline void 348static inline void
428hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *dst, u32 *flags) 349hash_ipportnet6_data_set_flags(struct hash_ipportnet6_elem *elem, u32 flags)
429{
430 if (dst->nomatch) {
431 *flags = IPSET_FLAG_NOMATCH;
432 dst->nomatch = 0;
433 }
434}
435
436static inline int
437hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
438{ 350{
439 return elem->nomatch ? -ENOTEMPTY : 1; 351 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
440} 352}
441 353
442static inline void 354static inline void
443hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem) 355hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *elem, u8 *flags)
444{ 356{
445 elem->proto = 0; 357 swap(*flags, elem->nomatch);
446} 358}
447 359
448static inline void 360static inline void
@@ -472,78 +384,58 @@ nla_put_failure:
472 return 1; 384 return 1;
473} 385}
474 386
475static bool 387static inline void
476hash_ipportnet6_data_tlist(struct sk_buff *skb, 388hash_ipportnet6_data_next(struct hash_ipportnet4_elem *next,
477 const struct hash_ipportnet6_elem *data) 389 const struct hash_ipportnet6_elem *d)
478{ 390{
479 const struct hash_ipportnet6_telem *e = 391 next->port = d->port;
480 (const struct hash_ipportnet6_telem *)data;
481 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
482
483 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
484 nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
485 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
486 nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
487 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
488 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
489 htonl(ip_set_timeout_get(e->timeout))) ||
490 (flags &&
491 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
492 goto nla_put_failure;
493 return 0;
494
495nla_put_failure:
496 return 1;
497} 392}
498 393
394#undef MTYPE
499#undef PF 395#undef PF
500#undef HOST_MASK 396#undef HOST_MASK
501 397
398#define MTYPE hash_ipportnet6
502#define PF 6 399#define PF 6
503#define HOST_MASK 128 400#define HOST_MASK 128
504#include <linux/netfilter/ipset/ip_set_ahash.h> 401#define IP_SET_EMIT_CREATE
505 402#include "ip_set_hash_gen.h"
506static inline void
507hash_ipportnet6_data_next(struct ip_set_hash *h,
508 const struct hash_ipportnet6_elem *d)
509{
510 h->next.port = d->port;
511}
512 403
513static int 404static int
514hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 405hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
515 const struct xt_action_param *par, 406 const struct xt_action_param *par,
516 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 407 enum ipset_adt adt, struct ip_set_adt_opt *opt)
517{ 408{
518 const struct ip_set_hash *h = set->data; 409 const struct hash_ipportnet *h = set->data;
519 ipset_adtfn adtfn = set->variant->adt[adt]; 410 ipset_adtfn adtfn = set->variant->adt[adt];
520 struct hash_ipportnet6_elem data = { 411 struct hash_ipportnet6_elem e = {
521 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 412 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
522 }; 413 };
414 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
523 415
524 if (adt == IPSET_TEST) 416 if (adt == IPSET_TEST)
525 data.cidr = HOST_MASK - 1; 417 e.cidr = HOST_MASK - 1;
526 418
527 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 419 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
528 &data.port, &data.proto)) 420 &e.port, &e.proto))
529 return -EINVAL; 421 return -EINVAL;
530 422
531 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 423 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
532 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); 424 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6);
533 ip6_netmask(&data.ip2, data.cidr + 1); 425 ip6_netmask(&e.ip2, e.cidr + 1);
534 426
535 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 427 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
536} 428}
537 429
538static int 430static int
539hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], 431hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
540 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 432 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
541{ 433{
542 const struct ip_set_hash *h = set->data; 434 const struct hash_ipportnet *h = set->data;
543 ipset_adtfn adtfn = set->variant->adt[adt]; 435 ipset_adtfn adtfn = set->variant->adt[adt];
544 struct hash_ipportnet6_elem data = { .cidr = HOST_MASK - 1 }; 436 struct hash_ipportnet6_elem e = { .cidr = HOST_MASK - 1 };
437 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
545 u32 port, port_to; 438 u32 port, port_to;
546 u32 timeout = h->timeout;
547 bool with_ports = false; 439 bool with_ports = false;
548 u8 cidr; 440 u8 cidr;
549 int ret; 441 int ret;
@@ -562,11 +454,12 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
562 if (tb[IPSET_ATTR_LINENO]) 454 if (tb[IPSET_ATTR_LINENO])
563 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 455 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
564 456
565 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 457 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
458 ip_set_get_extensions(set, tb, &ext);
566 if (ret) 459 if (ret)
567 return ret; 460 return ret;
568 461
569 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); 462 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2);
570 if (ret) 463 if (ret)
571 return ret; 464 return ret;
572 465
@@ -574,33 +467,27 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
574 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 467 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
575 if (!cidr || cidr > HOST_MASK) 468 if (!cidr || cidr > HOST_MASK)
576 return -IPSET_ERR_INVALID_CIDR; 469 return -IPSET_ERR_INVALID_CIDR;
577 data.cidr = cidr - 1; 470 e.cidr = cidr - 1;
578 } 471 }
579 472
580 ip6_netmask(&data.ip2, data.cidr + 1); 473 ip6_netmask(&e.ip2, e.cidr + 1);
581 474
582 if (tb[IPSET_ATTR_PORT]) 475 if (tb[IPSET_ATTR_PORT])
583 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 476 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
584 else 477 else
585 return -IPSET_ERR_PROTOCOL; 478 return -IPSET_ERR_PROTOCOL;
586 479
587 if (tb[IPSET_ATTR_PROTO]) { 480 if (tb[IPSET_ATTR_PROTO]) {
588 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 481 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
589 with_ports = ip_set_proto_with_ports(data.proto); 482 with_ports = ip_set_proto_with_ports(e.proto);
590 483
591 if (data.proto == 0) 484 if (e.proto == 0)
592 return -IPSET_ERR_INVALID_PROTO; 485 return -IPSET_ERR_INVALID_PROTO;
593 } else 486 } else
594 return -IPSET_ERR_MISSING_PROTO; 487 return -IPSET_ERR_MISSING_PROTO;
595 488
596 if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 489 if (!(with_ports || e.proto == IPPROTO_ICMPV6))
597 data.port = 0; 490 e.port = 0;
598
599 if (tb[IPSET_ATTR_TIMEOUT]) {
600 if (!with_timeout(h->timeout))
601 return -IPSET_ERR_TIMEOUT;
602 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
603 }
604 491
605 if (tb[IPSET_ATTR_CADT_FLAGS]) { 492 if (tb[IPSET_ATTR_CADT_FLAGS]) {
606 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 493 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -609,12 +496,12 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
609 } 496 }
610 497
611 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 498 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
612 ret = adtfn(set, &data, timeout, flags); 499 ret = adtfn(set, &e, &ext, &ext, flags);
613 return ip_set_enomatch(ret, flags, adt) ? 1 : 500 return ip_set_enomatch(ret, flags, adt) ? 1 :
614 ip_set_eexist(ret, flags) ? 0 : ret; 501 ip_set_eexist(ret, flags) ? 0 : ret;
615 } 502 }
616 503
617 port = ntohs(data.port); 504 port = ntohs(e.port);
618 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 505 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
619 if (port > port_to) 506 if (port > port_to)
620 swap(port, port_to); 507 swap(port, port_to);
@@ -622,8 +509,8 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
622 if (retried) 509 if (retried)
623 port = ntohs(h->next.port); 510 port = ntohs(h->next.port);
624 for (; port <= port_to; port++) { 511 for (; port <= port_to; port++) {
625 data.port = htons(port); 512 e.port = htons(port);
626 ret = adtfn(set, &data, timeout, flags); 513 ret = adtfn(set, &e, &ext, &ext, flags);
627 514
628 if (ret && !ip_set_eexist(ret, flags)) 515 if (ret && !ip_set_eexist(ret, flags))
629 return ret; 516 return ret;
@@ -633,81 +520,6 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
633 return ret; 520 return ret;
634} 521}
635 522
636/* Create hash:ip type of sets */
637
638static int
639hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
640{
641 struct ip_set_hash *h;
642 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
643 u8 hbits;
644 size_t hsize;
645
646 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
647 return -IPSET_ERR_INVALID_FAMILY;
648
649 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
650 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
651 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
652 return -IPSET_ERR_PROTOCOL;
653
654 if (tb[IPSET_ATTR_HASHSIZE]) {
655 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
656 if (hashsize < IPSET_MIMINAL_HASHSIZE)
657 hashsize = IPSET_MIMINAL_HASHSIZE;
658 }
659
660 if (tb[IPSET_ATTR_MAXELEM])
661 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
662
663 h = kzalloc(sizeof(*h)
664 + sizeof(struct ip_set_hash_nets)
665 * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
666 if (!h)
667 return -ENOMEM;
668
669 h->maxelem = maxelem;
670 get_random_bytes(&h->initval, sizeof(h->initval));
671 h->timeout = IPSET_NO_TIMEOUT;
672
673 hbits = htable_bits(hashsize);
674 hsize = htable_size(hbits);
675 if (hsize == 0) {
676 kfree(h);
677 return -ENOMEM;
678 }
679 h->table = ip_set_alloc(hsize);
680 if (!h->table) {
681 kfree(h);
682 return -ENOMEM;
683 }
684 h->table->htable_bits = hbits;
685
686 set->data = h;
687
688 if (tb[IPSET_ATTR_TIMEOUT]) {
689 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
690
691 set->variant = set->family == NFPROTO_IPV4
692 ? &hash_ipportnet4_tvariant
693 : &hash_ipportnet6_tvariant;
694
695 if (set->family == NFPROTO_IPV4)
696 hash_ipportnet4_gc_init(set);
697 else
698 hash_ipportnet6_gc_init(set);
699 } else {
700 set->variant = set->family == NFPROTO_IPV4
701 ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
702 }
703
704 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
705 set->name, jhash_size(h->table->htable_bits),
706 h->table->htable_bits, h->maxelem, set->data, h->table);
707
708 return 0;
709}
710
711static struct ip_set_type hash_ipportnet_type __read_mostly = { 523static struct ip_set_type hash_ipportnet_type __read_mostly = {
712 .name = "hash:ip,port,net", 524 .name = "hash:ip,port,net",
713 .protocol = IPSET_PROTOCOL, 525 .protocol = IPSET_PROTOCOL,
@@ -724,6 +536,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
724 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 536 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
725 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 537 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
726 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 538 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
539 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
727 }, 540 },
728 .adt_policy = { 541 .adt_policy = {
729 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 542 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 370947c65b20..cfbcdd407064 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -20,7 +20,6 @@
20#include <linux/netfilter.h> 20#include <linux/netfilter.h>
21#include <linux/netfilter/ipset/pfxlen.h> 21#include <linux/netfilter/ipset/pfxlen.h>
22#include <linux/netfilter/ipset/ip_set.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> 23#include <linux/netfilter/ipset/ip_set_hash.h>
25 24
26#define REVISION_MIN 0 25#define REVISION_MIN 0
@@ -33,17 +32,12 @@ IP_SET_MODULE_DESC("hash:net", REVISION_MIN, REVISION_MAX);
33MODULE_ALIAS("ip_set_hash:net"); 32MODULE_ALIAS("ip_set_hash:net");
34 33
35/* Type specific function prefix */ 34/* Type specific function prefix */
36#define TYPE hash_net 35#define HTYPE hash_net
37 36#define IP_SET_HASH_WITH_NETS
38static bool
39hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
40
41#define hash_net4_same_set hash_net_same_set
42#define hash_net6_same_set hash_net_same_set
43 37
44/* The type variant functions: IPv4 */ 38/* IPv4 variants */
45 39
46/* Member elements without timeout */ 40/* Member elements */
47struct hash_net4_elem { 41struct hash_net4_elem {
48 __be32 ip; 42 __be32 ip;
49 u16 padding0; 43 u16 padding0;
@@ -51,8 +45,7 @@ struct hash_net4_elem {
51 u8 cidr; 45 u8 cidr;
52}; 46};
53 47
54/* Member elements with timeout support */ 48struct hash_net4t_elem {
55struct hash_net4_telem {
56 __be32 ip; 49 __be32 ip;
57 u16 padding0; 50 u16 padding0;
58 u8 nomatch; 51 u8 nomatch;
@@ -60,6 +53,8 @@ struct hash_net4_telem {
60 unsigned long timeout; 53 unsigned long timeout;
61}; 54};
62 55
56/* Common functions */
57
63static inline bool 58static inline bool
64hash_net4_data_equal(const struct hash_net4_elem *ip1, 59hash_net4_data_equal(const struct hash_net4_elem *ip1,
65 const struct hash_net4_elem *ip2, 60 const struct hash_net4_elem *ip2,
@@ -69,40 +64,22 @@ hash_net4_data_equal(const struct hash_net4_elem *ip1,
69 ip1->cidr == ip2->cidr; 64 ip1->cidr == ip2->cidr;
70} 65}
71 66
72static inline bool 67static inline int
73hash_net4_data_isnull(const struct hash_net4_elem *elem) 68hash_net4_do_data_match(const struct hash_net4_elem *elem)
74{
75 return elem->cidr == 0;
76}
77
78static inline void
79hash_net4_data_copy(struct hash_net4_elem *dst,
80 const struct hash_net4_elem *src)
81{ 69{
82 dst->ip = src->ip; 70 return elem->nomatch ? -ENOTEMPTY : 1;
83 dst->cidr = src->cidr;
84 dst->nomatch = src->nomatch;
85} 71}
86 72
87static inline void 73static inline void
88hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags) 74hash_net4_data_set_flags(struct hash_net4_elem *elem, u32 flags)
89{ 75{
90 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 76 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
91} 77}
92 78
93static inline void 79static inline void
94hash_net4_data_reset_flags(struct hash_net4_elem *dst, u32 *flags) 80hash_net4_data_reset_flags(struct hash_net4_elem *elem, u8 *flags)
95{
96 if (dst->nomatch) {
97 *flags = IPSET_FLAG_NOMATCH;
98 dst->nomatch = 0;
99 }
100}
101
102static inline int
103hash_net4_data_match(const struct hash_net4_elem *elem)
104{ 81{
105 return elem->nomatch ? -ENOTEMPTY : 1; 82 swap(*flags, elem->nomatch);
106} 83}
107 84
108static inline void 85static inline void
@@ -112,13 +89,6 @@ hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
112 elem->cidr = cidr; 89 elem->cidr = cidr;
113} 90}
114 91
115/* Zero CIDR values cannot be stored */
116static inline void
117hash_net4_data_zero_out(struct hash_net4_elem *elem)
118{
119 elem->cidr = 0;
120}
121
122static bool 92static bool
123hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data) 93hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
124{ 94{
@@ -135,69 +105,49 @@ nla_put_failure:
135 return 1; 105 return 1;
136} 106}
137 107
138static bool 108static inline void
139hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data) 109hash_net4_data_next(struct hash_net4_elem *next,
110 const struct hash_net4_elem *d)
140{ 111{
141 const struct hash_net4_telem *tdata = 112 next->ip = d->ip;
142 (const struct hash_net4_telem *)data;
143 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
144
145 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
146 nla_put_u8(skb, IPSET_ATTR_CIDR, tdata->cidr) ||
147 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
148 htonl(ip_set_timeout_get(tdata->timeout))) ||
149 (flags &&
150 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
151 goto nla_put_failure;
152 return 0;
153
154nla_put_failure:
155 return 1;
156} 113}
157 114
158#define IP_SET_HASH_WITH_NETS 115#define MTYPE hash_net4
159
160#define PF 4 116#define PF 4
161#define HOST_MASK 32 117#define HOST_MASK 32
162#include <linux/netfilter/ipset/ip_set_ahash.h> 118#include "ip_set_hash_gen.h"
163
164static inline void
165hash_net4_data_next(struct ip_set_hash *h,
166 const struct hash_net4_elem *d)
167{
168 h->next.ip = d->ip;
169}
170 119
171static int 120static int
172hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, 121hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
173 const struct xt_action_param *par, 122 const struct xt_action_param *par,
174 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 123 enum ipset_adt adt, struct ip_set_adt_opt *opt)
175{ 124{
176 const struct ip_set_hash *h = set->data; 125 const struct hash_net *h = set->data;
177 ipset_adtfn adtfn = set->variant->adt[adt]; 126 ipset_adtfn adtfn = set->variant->adt[adt];
178 struct hash_net4_elem data = { 127 struct hash_net4_elem e = {
179 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK 128 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
180 }; 129 };
130 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
181 131
182 if (data.cidr == 0) 132 if (e.cidr == 0)
183 return -EINVAL; 133 return -EINVAL;
184 if (adt == IPSET_TEST) 134 if (adt == IPSET_TEST)
185 data.cidr = HOST_MASK; 135 e.cidr = HOST_MASK;
186 136
187 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 137 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
188 data.ip &= ip_set_netmask(data.cidr); 138 e.ip &= ip_set_netmask(e.cidr);
189 139
190 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 140 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
191} 141}
192 142
193static int 143static int
194hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], 144hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
195 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 145 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
196{ 146{
197 const struct ip_set_hash *h = set->data; 147 const struct hash_net *h = set->data;
198 ipset_adtfn adtfn = set->variant->adt[adt]; 148 ipset_adtfn adtfn = set->variant->adt[adt];
199 struct hash_net4_elem data = { .cidr = HOST_MASK }; 149 struct hash_net4_elem e = { .cidr = HOST_MASK };
200 u32 timeout = h->timeout; 150 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
201 u32 ip = 0, ip_to, last; 151 u32 ip = 0, ip_to, last;
202 int ret; 152 int ret;
203 153
@@ -209,22 +159,17 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
209 if (tb[IPSET_ATTR_LINENO]) 159 if (tb[IPSET_ATTR_LINENO])
210 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 160 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
211 161
212 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 162 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
163 ip_set_get_extensions(set, tb, &ext);
213 if (ret) 164 if (ret)
214 return ret; 165 return ret;
215 166
216 if (tb[IPSET_ATTR_CIDR]) { 167 if (tb[IPSET_ATTR_CIDR]) {
217 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 168 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
218 if (!data.cidr || data.cidr > HOST_MASK) 169 if (!e.cidr || e.cidr > HOST_MASK)
219 return -IPSET_ERR_INVALID_CIDR; 170 return -IPSET_ERR_INVALID_CIDR;
220 } 171 }
221 172
222 if (tb[IPSET_ATTR_TIMEOUT]) {
223 if (!with_timeout(h->timeout))
224 return -IPSET_ERR_TIMEOUT;
225 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
226 }
227
228 if (tb[IPSET_ATTR_CADT_FLAGS]) { 173 if (tb[IPSET_ATTR_CADT_FLAGS]) {
229 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 174 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
230 if (cadt_flags & IPSET_FLAG_NOMATCH) 175 if (cadt_flags & IPSET_FLAG_NOMATCH)
@@ -232,8 +177,8 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
232 } 177 }
233 178
234 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { 179 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
235 data.ip = htonl(ip & ip_set_hostmask(data.cidr)); 180 e.ip = htonl(ip & ip_set_hostmask(e.cidr));
236 ret = adtfn(set, &data, timeout, flags); 181 ret = adtfn(set, &e, &ext, &ext, flags);
237 return ip_set_enomatch(ret, flags, adt) ? 1 : 182 return ip_set_enomatch(ret, flags, adt) ? 1 :
238 ip_set_eexist(ret, flags) ? 0 : ret; 183 ip_set_eexist(ret, flags) ? 0 : ret;
239 } 184 }
@@ -251,9 +196,9 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
251 if (retried) 196 if (retried)
252 ip = ntohl(h->next.ip); 197 ip = ntohl(h->next.ip);
253 while (!after(ip, ip_to)) { 198 while (!after(ip, ip_to)) {
254 data.ip = htonl(ip); 199 e.ip = htonl(ip);
255 last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); 200 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
256 ret = adtfn(set, &data, timeout, flags); 201 ret = adtfn(set, &e, &ext, &ext, flags);
257 if (ret && !ip_set_eexist(ret, flags)) 202 if (ret && !ip_set_eexist(ret, flags))
258 return ret; 203 return ret;
259 else 204 else
@@ -263,18 +208,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
263 return ret; 208 return ret;
264} 209}
265 210
266static bool 211/* IPv6 variants */
267hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
268{
269 const struct ip_set_hash *x = a->data;
270 const struct ip_set_hash *y = b->data;
271
272 /* Resizing changes htable_bits, so we ignore it */
273 return x->maxelem == y->maxelem &&
274 x->timeout == y->timeout;
275}
276
277/* The type variant functions: IPv6 */
278 212
279struct hash_net6_elem { 213struct hash_net6_elem {
280 union nf_inet_addr ip; 214 union nf_inet_addr ip;
@@ -283,7 +217,7 @@ struct hash_net6_elem {
283 u8 cidr; 217 u8 cidr;
284}; 218};
285 219
286struct hash_net6_telem { 220struct hash_net6t_elem {
287 union nf_inet_addr ip; 221 union nf_inet_addr ip;
288 u16 padding0; 222 u16 padding0;
289 u8 nomatch; 223 u8 nomatch;
@@ -291,6 +225,8 @@ struct hash_net6_telem {
291 unsigned long timeout; 225 unsigned long timeout;
292}; 226};
293 227
228/* Common functions */
229
294static inline bool 230static inline bool
295hash_net6_data_equal(const struct hash_net6_elem *ip1, 231hash_net6_data_equal(const struct hash_net6_elem *ip1,
296 const struct hash_net6_elem *ip2, 232 const struct hash_net6_elem *ip2,
@@ -300,46 +236,22 @@ hash_net6_data_equal(const struct hash_net6_elem *ip1,
300 ip1->cidr == ip2->cidr; 236 ip1->cidr == ip2->cidr;
301} 237}
302 238
303static inline bool 239static inline int
304hash_net6_data_isnull(const struct hash_net6_elem *elem) 240hash_net6_do_data_match(const struct hash_net6_elem *elem)
305{
306 return elem->cidr == 0;
307}
308
309static inline void
310hash_net6_data_copy(struct hash_net6_elem *dst,
311 const struct hash_net6_elem *src)
312{
313 dst->ip.in6 = src->ip.in6;
314 dst->cidr = src->cidr;
315 dst->nomatch = src->nomatch;
316}
317
318static inline void
319hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
320{ 241{
321 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 242 return elem->nomatch ? -ENOTEMPTY : 1;
322} 243}
323 244
324static inline void 245static inline void
325hash_net6_data_reset_flags(struct hash_net6_elem *dst, u32 *flags) 246hash_net6_data_set_flags(struct hash_net6_elem *elem, u32 flags)
326{
327 if (dst->nomatch) {
328 *flags = IPSET_FLAG_NOMATCH;
329 dst->nomatch = 0;
330 }
331}
332
333static inline int
334hash_net6_data_match(const struct hash_net6_elem *elem)
335{ 247{
336 return elem->nomatch ? -ENOTEMPTY : 1; 248 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
337} 249}
338 250
339static inline void 251static inline void
340hash_net6_data_zero_out(struct hash_net6_elem *elem) 252hash_net6_data_reset_flags(struct hash_net6_elem *elem, u8 *flags)
341{ 253{
342 elem->cidr = 0; 254 swap(*flags, elem->nomatch);
343} 255}
344 256
345static inline void 257static inline void
@@ -365,69 +277,53 @@ nla_put_failure:
365 return 1; 277 return 1;
366} 278}
367 279
368static bool 280static inline void
369hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data) 281hash_net6_data_next(struct hash_net4_elem *next,
282 const struct hash_net6_elem *d)
370{ 283{
371 const struct hash_net6_telem *e =
372 (const struct hash_net6_telem *)data;
373 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
374
375 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
376 nla_put_u8(skb, IPSET_ATTR_CIDR, e->cidr) ||
377 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
378 htonl(ip_set_timeout_get(e->timeout))) ||
379 (flags &&
380 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
381 goto nla_put_failure;
382 return 0;
383
384nla_put_failure:
385 return 1;
386} 284}
387 285
286#undef MTYPE
388#undef PF 287#undef PF
389#undef HOST_MASK 288#undef HOST_MASK
390 289
290#define MTYPE hash_net6
391#define PF 6 291#define PF 6
392#define HOST_MASK 128 292#define HOST_MASK 128
393#include <linux/netfilter/ipset/ip_set_ahash.h> 293#define IP_SET_EMIT_CREATE
394 294#include "ip_set_hash_gen.h"
395static inline void
396hash_net6_data_next(struct ip_set_hash *h,
397 const struct hash_net6_elem *d)
398{
399}
400 295
401static int 296static int
402hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, 297hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
403 const struct xt_action_param *par, 298 const struct xt_action_param *par,
404 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 299 enum ipset_adt adt, struct ip_set_adt_opt *opt)
405{ 300{
406 const struct ip_set_hash *h = set->data; 301 const struct hash_net *h = set->data;
407 ipset_adtfn adtfn = set->variant->adt[adt]; 302 ipset_adtfn adtfn = set->variant->adt[adt];
408 struct hash_net6_elem data = { 303 struct hash_net6_elem e = {
409 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK 304 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
410 }; 305 };
306 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
411 307
412 if (data.cidr == 0) 308 if (e.cidr == 0)
413 return -EINVAL; 309 return -EINVAL;
414 if (adt == IPSET_TEST) 310 if (adt == IPSET_TEST)
415 data.cidr = HOST_MASK; 311 e.cidr = HOST_MASK;
416 312
417 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 313 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
418 ip6_netmask(&data.ip, data.cidr); 314 ip6_netmask(&e.ip, e.cidr);
419 315
420 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 316 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
421} 317}
422 318
423static int 319static int
424hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], 320hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
425 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 321 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
426{ 322{
427 const struct ip_set_hash *h = set->data; 323 const struct hash_net *h = set->data;
428 ipset_adtfn adtfn = set->variant->adt[adt]; 324 ipset_adtfn adtfn = set->variant->adt[adt];
429 struct hash_net6_elem data = { .cidr = HOST_MASK }; 325 struct hash_net6_elem e = { .cidr = HOST_MASK };
430 u32 timeout = h->timeout; 326 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
431 int ret; 327 int ret;
432 328
433 if (unlikely(!tb[IPSET_ATTR_IP] || 329 if (unlikely(!tb[IPSET_ATTR_IP] ||
@@ -440,23 +336,18 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
440 if (tb[IPSET_ATTR_LINENO]) 336 if (tb[IPSET_ATTR_LINENO])
441 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 337 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
442 338
443 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 339 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
340 ip_set_get_extensions(set, tb, &ext);
444 if (ret) 341 if (ret)
445 return ret; 342 return ret;
446 343
447 if (tb[IPSET_ATTR_CIDR]) 344 if (tb[IPSET_ATTR_CIDR])
448 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 345 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
449 346
450 if (!data.cidr || data.cidr > HOST_MASK) 347 if (!e.cidr || e.cidr > HOST_MASK)
451 return -IPSET_ERR_INVALID_CIDR; 348 return -IPSET_ERR_INVALID_CIDR;
452 349
453 ip6_netmask(&data.ip, data.cidr); 350 ip6_netmask(&e.ip, e.cidr);
454
455 if (tb[IPSET_ATTR_TIMEOUT]) {
456 if (!with_timeout(h->timeout))
457 return -IPSET_ERR_TIMEOUT;
458 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
459 }
460 351
461 if (tb[IPSET_ATTR_CADT_FLAGS]) { 352 if (tb[IPSET_ATTR_CADT_FLAGS]) {
462 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 353 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -464,86 +355,12 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
464 flags |= (IPSET_FLAG_NOMATCH << 16); 355 flags |= (IPSET_FLAG_NOMATCH << 16);
465 } 356 }
466 357
467 ret = adtfn(set, &data, timeout, flags); 358 ret = adtfn(set, &e, &ext, &ext, flags);
468 359
469 return ip_set_enomatch(ret, flags, adt) ? 1 : 360 return ip_set_enomatch(ret, flags, adt) ? 1 :
470 ip_set_eexist(ret, flags) ? 0 : ret; 361 ip_set_eexist(ret, flags) ? 0 : ret;
471} 362}
472 363
473/* Create hash:ip type of sets */
474
475static int
476hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
477{
478 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
479 struct ip_set_hash *h;
480 u8 hbits;
481 size_t hsize;
482
483 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
484 return -IPSET_ERR_INVALID_FAMILY;
485
486 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
487 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
488 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
489 return -IPSET_ERR_PROTOCOL;
490
491 if (tb[IPSET_ATTR_HASHSIZE]) {
492 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
493 if (hashsize < IPSET_MIMINAL_HASHSIZE)
494 hashsize = IPSET_MIMINAL_HASHSIZE;
495 }
496
497 if (tb[IPSET_ATTR_MAXELEM])
498 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
499
500 h = kzalloc(sizeof(*h)
501 + sizeof(struct ip_set_hash_nets)
502 * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
503 if (!h)
504 return -ENOMEM;
505
506 h->maxelem = maxelem;
507 get_random_bytes(&h->initval, sizeof(h->initval));
508 h->timeout = IPSET_NO_TIMEOUT;
509
510 hbits = htable_bits(hashsize);
511 hsize = htable_size(hbits);
512 if (hsize == 0) {
513 kfree(h);
514 return -ENOMEM;
515 }
516 h->table = ip_set_alloc(hsize);
517 if (!h->table) {
518 kfree(h);
519 return -ENOMEM;
520 }
521 h->table->htable_bits = hbits;
522
523 set->data = h;
524
525 if (tb[IPSET_ATTR_TIMEOUT]) {
526 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
527
528 set->variant = set->family == NFPROTO_IPV4
529 ? &hash_net4_tvariant : &hash_net6_tvariant;
530
531 if (set->family == NFPROTO_IPV4)
532 hash_net4_gc_init(set);
533 else
534 hash_net6_gc_init(set);
535 } else {
536 set->variant = set->family == NFPROTO_IPV4
537 ? &hash_net4_variant : &hash_net6_variant;
538 }
539
540 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
541 set->name, jhash_size(h->table->htable_bits),
542 h->table->htable_bits, h->maxelem, set->data, h->table);
543
544 return 0;
545}
546
547static struct ip_set_type hash_net_type __read_mostly = { 364static struct ip_set_type hash_net_type __read_mostly = {
548 .name = "hash:net", 365 .name = "hash:net",
549 .protocol = IPSET_PROTOCOL, 366 .protocol = IPSET_PROTOCOL,
@@ -559,6 +376,7 @@ static struct ip_set_type hash_net_type __read_mostly = {
559 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 376 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
560 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 377 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
561 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 378 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
379 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
562 }, 380 },
563 .adt_policy = { 381 .adt_policy = {
564 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 382 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index dd9843e3b06c..555ebb76bc8e 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2011-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -21,7 +21,6 @@
21#include <linux/netfilter.h> 21#include <linux/netfilter.h>
22#include <linux/netfilter/ipset/pfxlen.h> 22#include <linux/netfilter/ipset/pfxlen.h>
23#include <linux/netfilter/ipset/ip_set.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> 24#include <linux/netfilter/ipset/ip_set_hash.h>
26 25
27#define REVISION_MIN 0 26#define REVISION_MIN 0
@@ -127,17 +126,14 @@ iface_add(struct rb_root *root, const char **iface)
127} 126}
128 127
129/* Type specific function prefix */ 128/* Type specific function prefix */
130#define TYPE hash_netiface 129#define HTYPE hash_netiface
131 130#define IP_SET_HASH_WITH_NETS
132static bool 131#define IP_SET_HASH_WITH_RBTREE
133hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b); 132#define IP_SET_HASH_WITH_MULTI
134
135#define hash_netiface4_same_set hash_netiface_same_set
136#define hash_netiface6_same_set hash_netiface_same_set
137 133
138#define STREQ(a, b) (strcmp(a, b) == 0) 134#define STREQ(a, b) (strcmp(a, b) == 0)
139 135
140/* The type variant functions: IPv4 */ 136/* IPv4 variants */
141 137
142struct hash_netiface4_elem_hashed { 138struct hash_netiface4_elem_hashed {
143 __be32 ip; 139 __be32 ip;
@@ -147,8 +143,6 @@ struct hash_netiface4_elem_hashed {
147 u8 elem; 143 u8 elem;
148}; 144};
149 145
150#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
151
152/* Member elements without timeout */ 146/* Member elements without timeout */
153struct hash_netiface4_elem { 147struct hash_netiface4_elem {
154 __be32 ip; 148 __be32 ip;
@@ -159,8 +153,7 @@ struct hash_netiface4_elem {
159 const char *iface; 153 const char *iface;
160}; 154};
161 155
162/* Member elements with timeout support */ 156struct hash_netiface4t_elem {
163struct hash_netiface4_telem {
164 __be32 ip; 157 __be32 ip;
165 u8 physdev; 158 u8 physdev;
166 u8 cidr; 159 u8 cidr;
@@ -170,6 +163,8 @@ struct hash_netiface4_telem {
170 unsigned long timeout; 163 unsigned long timeout;
171}; 164};
172 165
166/* Common functions */
167
173static inline bool 168static inline bool
174hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, 169hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
175 const struct hash_netiface4_elem *ip2, 170 const struct hash_netiface4_elem *ip2,
@@ -182,38 +177,22 @@ hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
182 ip1->iface == ip2->iface; 177 ip1->iface == ip2->iface;
183} 178}
184 179
185static inline bool 180static inline int
186hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem) 181hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
187{ 182{
188 return elem->elem == 0; 183 return elem->nomatch ? -ENOTEMPTY : 1;
189} 184}
190 185
191static inline void 186static inline void
192hash_netiface4_data_copy(struct hash_netiface4_elem *dst, 187hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
193 const struct hash_netiface4_elem *src)
194{ 188{
195 memcpy(dst, src, sizeof(*dst)); 189 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
196} 190}
197 191
198static inline void 192static inline void
199hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags) 193hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
200{ 194{
201 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 195 swap(*flags, elem->nomatch);
202}
203
204static inline void
205hash_netiface4_data_reset_flags(struct hash_netiface4_elem *dst, u32 *flags)
206{
207 if (dst->nomatch) {
208 *flags = IPSET_FLAG_NOMATCH;
209 dst->nomatch = 0;
210 }
211}
212
213static inline int
214hash_netiface4_data_match(const struct hash_netiface4_elem *elem)
215{
216 return elem->nomatch ? -ENOTEMPTY : 1;
217} 196}
218 197
219static inline void 198static inline void
@@ -223,12 +202,6 @@ hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
223 elem->cidr = cidr; 202 elem->cidr = cidr;
224} 203}
225 204
226static inline void
227hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
228{
229 elem->elem = 0;
230}
231
232static bool 205static bool
233hash_netiface4_data_list(struct sk_buff *skb, 206hash_netiface4_data_list(struct sk_buff *skb,
234 const struct hash_netiface4_elem *data) 207 const struct hash_netiface4_elem *data)
@@ -249,66 +222,40 @@ nla_put_failure:
249 return 1; 222 return 1;
250} 223}
251 224
252static bool 225static inline void
253hash_netiface4_data_tlist(struct sk_buff *skb, 226hash_netiface4_data_next(struct hash_netiface4_elem *next,
254 const struct hash_netiface4_elem *data) 227 const struct hash_netiface4_elem *d)
255{ 228{
256 const struct hash_netiface4_telem *tdata = 229 next->ip = d->ip;
257 (const struct hash_netiface4_telem *)data;
258 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
259
260 if (data->nomatch)
261 flags |= IPSET_FLAG_NOMATCH;
262 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
263 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
264 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
265 (flags &&
266 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))) ||
267 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
268 htonl(ip_set_timeout_get(tdata->timeout))))
269 goto nla_put_failure;
270
271 return 0;
272
273nla_put_failure:
274 return 1;
275} 230}
276 231
277#define IP_SET_HASH_WITH_NETS 232#define MTYPE hash_netiface4
278#define IP_SET_HASH_WITH_RBTREE
279#define IP_SET_HASH_WITH_MULTI
280
281#define PF 4 233#define PF 4
282#define HOST_MASK 32 234#define HOST_MASK 32
283#include <linux/netfilter/ipset/ip_set_ahash.h> 235#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
284 236#include "ip_set_hash_gen.h"
285static inline void
286hash_netiface4_data_next(struct ip_set_hash *h,
287 const struct hash_netiface4_elem *d)
288{
289 h->next.ip = d->ip;
290}
291 237
292static int 238static int
293hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, 239hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
294 const struct xt_action_param *par, 240 const struct xt_action_param *par,
295 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 241 enum ipset_adt adt, struct ip_set_adt_opt *opt)
296{ 242{
297 struct ip_set_hash *h = set->data; 243 struct hash_netiface *h = set->data;
298 ipset_adtfn adtfn = set->variant->adt[adt]; 244 ipset_adtfn adtfn = set->variant->adt[adt];
299 struct hash_netiface4_elem data = { 245 struct hash_netiface4_elem e = {
300 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK, 246 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
301 .elem = 1, 247 .elem = 1,
302 }; 248 };
249 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
303 int ret; 250 int ret;
304 251
305 if (data.cidr == 0) 252 if (e.cidr == 0)
306 return -EINVAL; 253 return -EINVAL;
307 if (adt == IPSET_TEST) 254 if (adt == IPSET_TEST)
308 data.cidr = HOST_MASK; 255 e.cidr = HOST_MASK;
309 256
310 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 257 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
311 data.ip &= ip_set_netmask(data.cidr); 258 e.ip &= ip_set_netmask(e.cidr);
312 259
313#define IFACE(dir) (par->dir ? par->dir->name : NULL) 260#define IFACE(dir) (par->dir ? par->dir->name : NULL)
314#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL) 261#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
@@ -320,38 +267,38 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
320 267
321 if (!nf_bridge) 268 if (!nf_bridge)
322 return -EINVAL; 269 return -EINVAL;
323 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev); 270 e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
324 data.physdev = 1; 271 e.physdev = 1;
325#else 272#else
326 data.iface = NULL; 273 e.iface = NULL;
327#endif 274#endif
328 } else 275 } else
329 data.iface = SRCDIR ? IFACE(in) : IFACE(out); 276 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
330 277
331 if (!data.iface) 278 if (!e.iface)
332 return -EINVAL; 279 return -EINVAL;
333 ret = iface_test(&h->rbtree, &data.iface); 280 ret = iface_test(&h->rbtree, &e.iface);
334 if (adt == IPSET_ADD) { 281 if (adt == IPSET_ADD) {
335 if (!ret) { 282 if (!ret) {
336 ret = iface_add(&h->rbtree, &data.iface); 283 ret = iface_add(&h->rbtree, &e.iface);
337 if (ret) 284 if (ret)
338 return ret; 285 return ret;
339 } 286 }
340 } else if (!ret) 287 } else if (!ret)
341 return ret; 288 return ret;
342 289
343 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 290 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
344} 291}
345 292
346static int 293static int
347hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], 294hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
348 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 295 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
349{ 296{
350 struct ip_set_hash *h = set->data; 297 struct hash_netiface *h = set->data;
351 ipset_adtfn adtfn = set->variant->adt[adt]; 298 ipset_adtfn adtfn = set->variant->adt[adt];
352 struct hash_netiface4_elem data = { .cidr = HOST_MASK, .elem = 1 }; 299 struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
300 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
353 u32 ip = 0, ip_to, last; 301 u32 ip = 0, ip_to, last;
354 u32 timeout = h->timeout;
355 char iface[IFNAMSIZ]; 302 char iface[IFNAMSIZ];
356 int ret; 303 int ret;
357 304
@@ -364,28 +311,23 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
364 if (tb[IPSET_ATTR_LINENO]) 311 if (tb[IPSET_ATTR_LINENO])
365 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 312 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
366 313
367 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 314 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
315 ip_set_get_extensions(set, tb, &ext);
368 if (ret) 316 if (ret)
369 return ret; 317 return ret;
370 318
371 if (tb[IPSET_ATTR_CIDR]) { 319 if (tb[IPSET_ATTR_CIDR]) {
372 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 320 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
373 if (data.cidr > HOST_MASK) 321 if (e.cidr > HOST_MASK)
374 return -IPSET_ERR_INVALID_CIDR; 322 return -IPSET_ERR_INVALID_CIDR;
375 } 323 }
376 324
377 if (tb[IPSET_ATTR_TIMEOUT]) {
378 if (!with_timeout(h->timeout))
379 return -IPSET_ERR_TIMEOUT;
380 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
381 }
382
383 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE])); 325 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
384 data.iface = iface; 326 e.iface = iface;
385 ret = iface_test(&h->rbtree, &data.iface); 327 ret = iface_test(&h->rbtree, &e.iface);
386 if (adt == IPSET_ADD) { 328 if (adt == IPSET_ADD) {
387 if (!ret) { 329 if (!ret) {
388 ret = iface_add(&h->rbtree, &data.iface); 330 ret = iface_add(&h->rbtree, &e.iface);
389 if (ret) 331 if (ret)
390 return ret; 332 return ret;
391 } 333 }
@@ -395,13 +337,13 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
395 if (tb[IPSET_ATTR_CADT_FLAGS]) { 337 if (tb[IPSET_ATTR_CADT_FLAGS]) {
396 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 338 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
397 if (cadt_flags & IPSET_FLAG_PHYSDEV) 339 if (cadt_flags & IPSET_FLAG_PHYSDEV)
398 data.physdev = 1; 340 e.physdev = 1;
399 if (cadt_flags & IPSET_FLAG_NOMATCH) 341 if (cadt_flags & IPSET_FLAG_NOMATCH)
400 flags |= (IPSET_FLAG_NOMATCH << 16); 342 flags |= (IPSET_FLAG_NOMATCH << 16);
401 } 343 }
402 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { 344 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
403 data.ip = htonl(ip & ip_set_hostmask(data.cidr)); 345 e.ip = htonl(ip & ip_set_hostmask(e.cidr));
404 ret = adtfn(set, &data, timeout, flags); 346 ret = adtfn(set, &e, &ext, &ext, flags);
405 return ip_set_enomatch(ret, flags, adt) ? 1 : 347 return ip_set_enomatch(ret, flags, adt) ? 1 :
406 ip_set_eexist(ret, flags) ? 0 : ret; 348 ip_set_eexist(ret, flags) ? 0 : ret;
407 } 349 }
@@ -414,16 +356,15 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
414 swap(ip, ip_to); 356 swap(ip, ip_to);
415 if (ip + UINT_MAX == ip_to) 357 if (ip + UINT_MAX == ip_to)
416 return -IPSET_ERR_HASH_RANGE; 358 return -IPSET_ERR_HASH_RANGE;
417 } else { 359 } else
418 ip_set_mask_from_to(ip, ip_to, data.cidr); 360 ip_set_mask_from_to(ip, ip_to, e.cidr);
419 }
420 361
421 if (retried) 362 if (retried)
422 ip = ntohl(h->next.ip); 363 ip = ntohl(h->next.ip);
423 while (!after(ip, ip_to)) { 364 while (!after(ip, ip_to)) {
424 data.ip = htonl(ip); 365 e.ip = htonl(ip);
425 last = ip_set_range_to_cidr(ip, ip_to, &data.cidr); 366 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
426 ret = adtfn(set, &data, timeout, flags); 367 ret = adtfn(set, &e, &ext, &ext, flags);
427 368
428 if (ret && !ip_set_eexist(ret, flags)) 369 if (ret && !ip_set_eexist(ret, flags))
429 return ret; 370 return ret;
@@ -434,18 +375,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
434 return ret; 375 return ret;
435} 376}
436 377
437static bool 378/* IPv6 variants */
438hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
439{
440 const struct ip_set_hash *x = a->data;
441 const struct ip_set_hash *y = b->data;
442
443 /* Resizing changes htable_bits, so we ignore it */
444 return x->maxelem == y->maxelem &&
445 x->timeout == y->timeout;
446}
447
448/* The type variant functions: IPv6 */
449 379
450struct hash_netiface6_elem_hashed { 380struct hash_netiface6_elem_hashed {
451 union nf_inet_addr ip; 381 union nf_inet_addr ip;
@@ -455,8 +385,6 @@ struct hash_netiface6_elem_hashed {
455 u8 elem; 385 u8 elem;
456}; 386};
457 387
458#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
459
460struct hash_netiface6_elem { 388struct hash_netiface6_elem {
461 union nf_inet_addr ip; 389 union nf_inet_addr ip;
462 u8 physdev; 390 u8 physdev;
@@ -466,7 +394,7 @@ struct hash_netiface6_elem {
466 const char *iface; 394 const char *iface;
467}; 395};
468 396
469struct hash_netiface6_telem { 397struct hash_netiface6t_elem {
470 union nf_inet_addr ip; 398 union nf_inet_addr ip;
471 u8 physdev; 399 u8 physdev;
472 u8 cidr; 400 u8 cidr;
@@ -476,6 +404,8 @@ struct hash_netiface6_telem {
476 unsigned long timeout; 404 unsigned long timeout;
477}; 405};
478 406
407/* Common functions */
408
479static inline bool 409static inline bool
480hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 410hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
481 const struct hash_netiface6_elem *ip2, 411 const struct hash_netiface6_elem *ip2,
@@ -488,44 +418,22 @@ hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
488 ip1->iface == ip2->iface; 418 ip1->iface == ip2->iface;
489} 419}
490 420
491static inline bool
492hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
493{
494 return elem->elem == 0;
495}
496
497static inline void
498hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
499 const struct hash_netiface6_elem *src)
500{
501 memcpy(dst, src, sizeof(*dst));
502}
503
504static inline void
505hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
506{
507 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
508}
509
510static inline int 421static inline int
511hash_netiface6_data_match(const struct hash_netiface6_elem *elem) 422hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
512{ 423{
513 return elem->nomatch ? -ENOTEMPTY : 1; 424 return elem->nomatch ? -ENOTEMPTY : 1;
514} 425}
515 426
516static inline void 427static inline void
517hash_netiface6_data_reset_flags(struct hash_netiface6_elem *dst, u32 *flags) 428hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
518{ 429{
519 if (dst->nomatch) { 430 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
520 *flags = IPSET_FLAG_NOMATCH;
521 dst->nomatch = 0;
522 }
523} 431}
524 432
525static inline void 433static inline void
526hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem) 434hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
527{ 435{
528 elem->elem = 0; 436 swap(*flags, elem->nomatch);
529} 437}
530 438
531static inline void 439static inline void
@@ -555,63 +463,45 @@ nla_put_failure:
555 return 1; 463 return 1;
556} 464}
557 465
558static bool 466static inline void
559hash_netiface6_data_tlist(struct sk_buff *skb, 467hash_netiface6_data_next(struct hash_netiface4_elem *next,
560 const struct hash_netiface6_elem *data) 468 const struct hash_netiface6_elem *d)
561{ 469{
562 const struct hash_netiface6_telem *e =
563 (const struct hash_netiface6_telem *)data;
564 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
565
566 if (data->nomatch)
567 flags |= IPSET_FLAG_NOMATCH;
568 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
569 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
570 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
571 (flags &&
572 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))) ||
573 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
574 htonl(ip_set_timeout_get(e->timeout))))
575 goto nla_put_failure;
576 return 0;
577
578nla_put_failure:
579 return 1;
580} 470}
581 471
472#undef MTYPE
582#undef PF 473#undef PF
583#undef HOST_MASK 474#undef HOST_MASK
475#undef HKEY_DATALEN
584 476
477#define MTYPE hash_netiface6
585#define PF 6 478#define PF 6
586#define HOST_MASK 128 479#define HOST_MASK 128
587#include <linux/netfilter/ipset/ip_set_ahash.h> 480#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
588 481#define IP_SET_EMIT_CREATE
589static inline void 482#include "ip_set_hash_gen.h"
590hash_netiface6_data_next(struct ip_set_hash *h,
591 const struct hash_netiface6_elem *d)
592{
593}
594 483
595static int 484static int
596hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, 485hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
597 const struct xt_action_param *par, 486 const struct xt_action_param *par,
598 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 487 enum ipset_adt adt, struct ip_set_adt_opt *opt)
599{ 488{
600 struct ip_set_hash *h = set->data; 489 struct hash_netiface *h = set->data;
601 ipset_adtfn adtfn = set->variant->adt[adt]; 490 ipset_adtfn adtfn = set->variant->adt[adt];
602 struct hash_netiface6_elem data = { 491 struct hash_netiface6_elem e = {
603 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK, 492 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK,
604 .elem = 1, 493 .elem = 1,
605 }; 494 };
495 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
606 int ret; 496 int ret;
607 497
608 if (data.cidr == 0) 498 if (e.cidr == 0)
609 return -EINVAL; 499 return -EINVAL;
610 if (adt == IPSET_TEST) 500 if (adt == IPSET_TEST)
611 data.cidr = HOST_MASK; 501 e.cidr = HOST_MASK;
612 502
613 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 503 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
614 ip6_netmask(&data.ip, data.cidr); 504 ip6_netmask(&e.ip, e.cidr);
615 505
616 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 506 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
617#ifdef CONFIG_BRIDGE_NETFILTER 507#ifdef CONFIG_BRIDGE_NETFILTER
@@ -619,37 +509,37 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
619 509
620 if (!nf_bridge) 510 if (!nf_bridge)
621 return -EINVAL; 511 return -EINVAL;
622 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev); 512 e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
623 data.physdev = 1; 513 e.physdev = 1;
624#else 514#else
625 data.iface = NULL; 515 e.iface = NULL;
626#endif 516#endif
627 } else 517 } else
628 data.iface = SRCDIR ? IFACE(in) : IFACE(out); 518 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
629 519
630 if (!data.iface) 520 if (!e.iface)
631 return -EINVAL; 521 return -EINVAL;
632 ret = iface_test(&h->rbtree, &data.iface); 522 ret = iface_test(&h->rbtree, &e.iface);
633 if (adt == IPSET_ADD) { 523 if (adt == IPSET_ADD) {
634 if (!ret) { 524 if (!ret) {
635 ret = iface_add(&h->rbtree, &data.iface); 525 ret = iface_add(&h->rbtree, &e.iface);
636 if (ret) 526 if (ret)
637 return ret; 527 return ret;
638 } 528 }
639 } else if (!ret) 529 } else if (!ret)
640 return ret; 530 return ret;
641 531
642 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 532 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
643} 533}
644 534
645static int 535static int
646hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], 536hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
647 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 537 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
648{ 538{
649 struct ip_set_hash *h = set->data; 539 struct hash_netiface *h = set->data;
650 ipset_adtfn adtfn = set->variant->adt[adt]; 540 ipset_adtfn adtfn = set->variant->adt[adt];
651 struct hash_netiface6_elem data = { .cidr = HOST_MASK, .elem = 1 }; 541 struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
652 u32 timeout = h->timeout; 542 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
653 char iface[IFNAMSIZ]; 543 char iface[IFNAMSIZ];
654 int ret; 544 int ret;
655 545
@@ -664,28 +554,23 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
664 if (tb[IPSET_ATTR_LINENO]) 554 if (tb[IPSET_ATTR_LINENO])
665 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 555 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
666 556
667 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 557 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
558 ip_set_get_extensions(set, tb, &ext);
668 if (ret) 559 if (ret)
669 return ret; 560 return ret;
670 561
671 if (tb[IPSET_ATTR_CIDR]) 562 if (tb[IPSET_ATTR_CIDR])
672 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 563 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
673 if (data.cidr > HOST_MASK) 564 if (e.cidr > HOST_MASK)
674 return -IPSET_ERR_INVALID_CIDR; 565 return -IPSET_ERR_INVALID_CIDR;
675 ip6_netmask(&data.ip, data.cidr); 566 ip6_netmask(&e.ip, e.cidr);
676
677 if (tb[IPSET_ATTR_TIMEOUT]) {
678 if (!with_timeout(h->timeout))
679 return -IPSET_ERR_TIMEOUT;
680 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
681 }
682 567
683 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE])); 568 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
684 data.iface = iface; 569 e.iface = iface;
685 ret = iface_test(&h->rbtree, &data.iface); 570 ret = iface_test(&h->rbtree, &e.iface);
686 if (adt == IPSET_ADD) { 571 if (adt == IPSET_ADD) {
687 if (!ret) { 572 if (!ret) {
688 ret = iface_add(&h->rbtree, &data.iface); 573 ret = iface_add(&h->rbtree, &e.iface);
689 if (ret) 574 if (ret)
690 return ret; 575 return ret;
691 } 576 }
@@ -695,93 +580,17 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
695 if (tb[IPSET_ATTR_CADT_FLAGS]) { 580 if (tb[IPSET_ATTR_CADT_FLAGS]) {
696 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 581 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
697 if (cadt_flags & IPSET_FLAG_PHYSDEV) 582 if (cadt_flags & IPSET_FLAG_PHYSDEV)
698 data.physdev = 1; 583 e.physdev = 1;
699 if (cadt_flags & IPSET_FLAG_NOMATCH) 584 if (cadt_flags & IPSET_FLAG_NOMATCH)
700 flags |= (IPSET_FLAG_NOMATCH << 16); 585 flags |= (IPSET_FLAG_NOMATCH << 16);
701 } 586 }
702 587
703 ret = adtfn(set, &data, timeout, flags); 588 ret = adtfn(set, &e, &ext, &ext, flags);
704 589
705 return ip_set_enomatch(ret, flags, adt) ? 1 : 590 return ip_set_enomatch(ret, flags, adt) ? 1 :
706 ip_set_eexist(ret, flags) ? 0 : ret; 591 ip_set_eexist(ret, flags) ? 0 : ret;
707} 592}
708 593
709/* Create hash:ip type of sets */
710
711static int
712hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
713{
714 struct ip_set_hash *h;
715 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
716 u8 hbits;
717 size_t hsize;
718
719 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
720 return -IPSET_ERR_INVALID_FAMILY;
721
722 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
723 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
724 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
725 return -IPSET_ERR_PROTOCOL;
726
727 if (tb[IPSET_ATTR_HASHSIZE]) {
728 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
729 if (hashsize < IPSET_MIMINAL_HASHSIZE)
730 hashsize = IPSET_MIMINAL_HASHSIZE;
731 }
732
733 if (tb[IPSET_ATTR_MAXELEM])
734 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
735
736 h = kzalloc(sizeof(*h)
737 + sizeof(struct ip_set_hash_nets)
738 * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
739 if (!h)
740 return -ENOMEM;
741
742 h->maxelem = maxelem;
743 get_random_bytes(&h->initval, sizeof(h->initval));
744 h->timeout = IPSET_NO_TIMEOUT;
745 h->ahash_max = AHASH_MAX_SIZE;
746
747 hbits = htable_bits(hashsize);
748 hsize = htable_size(hbits);
749 if (hsize == 0) {
750 kfree(h);
751 return -ENOMEM;
752 }
753 h->table = ip_set_alloc(hsize);
754 if (!h->table) {
755 kfree(h);
756 return -ENOMEM;
757 }
758 h->table->htable_bits = hbits;
759 h->rbtree = RB_ROOT;
760
761 set->data = h;
762
763 if (tb[IPSET_ATTR_TIMEOUT]) {
764 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
765
766 set->variant = set->family == NFPROTO_IPV4
767 ? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
768
769 if (set->family == NFPROTO_IPV4)
770 hash_netiface4_gc_init(set);
771 else
772 hash_netiface6_gc_init(set);
773 } else {
774 set->variant = set->family == NFPROTO_IPV4
775 ? &hash_netiface4_variant : &hash_netiface6_variant;
776 }
777
778 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
779 set->name, jhash_size(h->table->htable_bits),
780 h->table->htable_bits, h->maxelem, set->data, h->table);
781
782 return 0;
783}
784
785static struct ip_set_type hash_netiface_type __read_mostly = { 594static struct ip_set_type hash_netiface_type __read_mostly = {
786 .name = "hash:net,iface", 595 .name = "hash:net,iface",
787 .protocol = IPSET_PROTOCOL, 596 .protocol = IPSET_PROTOCOL,
@@ -799,6 +608,7 @@ static struct ip_set_type hash_netiface_type __read_mostly = {
799 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 608 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
800 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 609 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
801 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 610 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
611 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
802 }, 612 },
803 .adt_policy = { 613 .adt_policy = {
804 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 614 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index cd1d3c1df72a..43b1f1e8727f 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -1,4 +1,4 @@
1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 1/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 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 4 * it under the terms of the GNU General Public License version 2 as
@@ -20,7 +20,6 @@
20#include <linux/netfilter.h> 20#include <linux/netfilter.h>
21#include <linux/netfilter/ipset/pfxlen.h> 21#include <linux/netfilter/ipset/pfxlen.h>
22#include <linux/netfilter/ipset/ip_set.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> 23#include <linux/netfilter/ipset/ip_set_getport.h>
25#include <linux/netfilter/ipset/ip_set_hash.h> 24#include <linux/netfilter/ipset/ip_set_hash.h>
26 25
@@ -35,15 +34,9 @@ IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX);
35MODULE_ALIAS("ip_set_hash:net,port"); 34MODULE_ALIAS("ip_set_hash:net,port");
36 35
37/* Type specific function prefix */ 36/* Type specific function prefix */
38#define TYPE hash_netport 37#define HTYPE hash_netport
39 38#define IP_SET_HASH_WITH_PROTO
40static bool 39#define IP_SET_HASH_WITH_NETS
41hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
42
43#define hash_netport4_same_set hash_netport_same_set
44#define hash_netport6_same_set hash_netport_same_set
45
46/* The type variant functions: IPv4 */
47 40
48/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0 41/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0
49 * However this way we have to store internally cidr - 1, 42 * However this way we have to store internally cidr - 1,
@@ -51,7 +44,9 @@ hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
51 */ 44 */
52#define IP_SET_HASH_WITH_NETS_PACKED 45#define IP_SET_HASH_WITH_NETS_PACKED
53 46
54/* Member elements without timeout */ 47/* IPv4 variants */
48
49/* Member elements */
55struct hash_netport4_elem { 50struct hash_netport4_elem {
56 __be32 ip; 51 __be32 ip;
57 __be16 port; 52 __be16 port;
@@ -60,8 +55,7 @@ struct hash_netport4_elem {
60 u8 nomatch:1; 55 u8 nomatch:1;
61}; 56};
62 57
63/* Member elements with timeout support */ 58struct hash_netport4t_elem {
64struct hash_netport4_telem {
65 __be32 ip; 59 __be32 ip;
66 __be16 port; 60 __be16 port;
67 u8 proto; 61 u8 proto;
@@ -70,6 +64,8 @@ struct hash_netport4_telem {
70 unsigned long timeout; 64 unsigned long timeout;
71}; 65};
72 66
67/* Common functions */
68
73static inline bool 69static inline bool
74hash_netport4_data_equal(const struct hash_netport4_elem *ip1, 70hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
75 const struct hash_netport4_elem *ip2, 71 const struct hash_netport4_elem *ip2,
@@ -81,42 +77,22 @@ hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
81 ip1->cidr == ip2->cidr; 77 ip1->cidr == ip2->cidr;
82} 78}
83 79
84static inline bool 80static inline int
85hash_netport4_data_isnull(const struct hash_netport4_elem *elem) 81hash_netport4_do_data_match(const struct hash_netport4_elem *elem)
86{ 82{
87 return elem->proto == 0; 83 return elem->nomatch ? -ENOTEMPTY : 1;
88} 84}
89 85
90static inline void 86static inline void
91hash_netport4_data_copy(struct hash_netport4_elem *dst, 87hash_netport4_data_set_flags(struct hash_netport4_elem *elem, u32 flags)
92 const struct hash_netport4_elem *src)
93{ 88{
94 dst->ip = src->ip; 89 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
95 dst->port = src->port;
96 dst->proto = src->proto;
97 dst->cidr = src->cidr;
98 dst->nomatch = src->nomatch;
99} 90}
100 91
101static inline void 92static inline void
102hash_netport4_data_flags(struct hash_netport4_elem *dst, u32 flags) 93hash_netport4_data_reset_flags(struct hash_netport4_elem *elem, u8 *flags)
103{ 94{
104 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 95 swap(*flags, elem->nomatch);
105}
106
107static inline void
108hash_netport4_data_reset_flags(struct hash_netport4_elem *dst, u32 *flags)
109{
110 if (dst->nomatch) {
111 *flags = IPSET_FLAG_NOMATCH;
112 dst->nomatch = 0;
113 }
114}
115
116static inline int
117hash_netport4_data_match(const struct hash_netport4_elem *elem)
118{
119 return elem->nomatch ? -ENOTEMPTY : 1;
120} 96}
121 97
122static inline void 98static inline void
@@ -126,12 +102,6 @@ hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
126 elem->cidr = cidr - 1; 102 elem->cidr = cidr - 1;
127} 103}
128 104
129static inline void
130hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
131{
132 elem->proto = 0;
133}
134
135static bool 105static bool
136hash_netport4_data_list(struct sk_buff *skb, 106hash_netport4_data_list(struct sk_buff *skb,
137 const struct hash_netport4_elem *data) 107 const struct hash_netport4_elem *data)
@@ -151,77 +121,53 @@ nla_put_failure:
151 return 1; 121 return 1;
152} 122}
153 123
154static bool 124static inline void
155hash_netport4_data_tlist(struct sk_buff *skb, 125hash_netport4_data_next(struct hash_netport4_elem *next,
156 const struct hash_netport4_elem *data) 126 const struct hash_netport4_elem *d)
157{ 127{
158 const struct hash_netport4_telem *tdata = 128 next->ip = d->ip;
159 (const struct hash_netport4_telem *)data; 129 next->port = d->port;
160 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
161
162 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
163 nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) ||
164 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) ||
165 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
166 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
167 htonl(ip_set_timeout_get(tdata->timeout))) ||
168 (flags &&
169 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
170 goto nla_put_failure;
171 return 0;
172
173nla_put_failure:
174 return 1;
175} 130}
176 131
177#define IP_SET_HASH_WITH_PROTO 132#define MTYPE hash_netport4
178#define IP_SET_HASH_WITH_NETS
179
180#define PF 4 133#define PF 4
181#define HOST_MASK 32 134#define HOST_MASK 32
182#include <linux/netfilter/ipset/ip_set_ahash.h> 135#include "ip_set_hash_gen.h"
183
184static inline void
185hash_netport4_data_next(struct ip_set_hash *h,
186 const struct hash_netport4_elem *d)
187{
188 h->next.ip = d->ip;
189 h->next.port = d->port;
190}
191 136
192static int 137static int
193hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, 138hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
194 const struct xt_action_param *par, 139 const struct xt_action_param *par,
195 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 140 enum ipset_adt adt, struct ip_set_adt_opt *opt)
196{ 141{
197 const struct ip_set_hash *h = set->data; 142 const struct hash_netport *h = set->data;
198 ipset_adtfn adtfn = set->variant->adt[adt]; 143 ipset_adtfn adtfn = set->variant->adt[adt];
199 struct hash_netport4_elem data = { 144 struct hash_netport4_elem e = {
200 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 145 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
201 }; 146 };
147 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
202 148
203 if (adt == IPSET_TEST) 149 if (adt == IPSET_TEST)
204 data.cidr = HOST_MASK - 1; 150 e.cidr = HOST_MASK - 1;
205 151
206 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 152 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
207 &data.port, &data.proto)) 153 &e.port, &e.proto))
208 return -EINVAL; 154 return -EINVAL;
209 155
210 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip); 156 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
211 data.ip &= ip_set_netmask(data.cidr + 1); 157 e.ip &= ip_set_netmask(e.cidr + 1);
212 158
213 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 159 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
214} 160}
215 161
216static int 162static int
217hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], 163hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
218 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 164 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
219{ 165{
220 const struct ip_set_hash *h = set->data; 166 const struct hash_netport *h = set->data;
221 ipset_adtfn adtfn = set->variant->adt[adt]; 167 ipset_adtfn adtfn = set->variant->adt[adt];
222 struct hash_netport4_elem data = { .cidr = HOST_MASK - 1 }; 168 struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
169 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
223 u32 port, port_to, p = 0, ip = 0, ip_to, last; 170 u32 port, port_to, p = 0, ip = 0, ip_to, last;
224 u32 timeout = h->timeout;
225 bool with_ports = false; 171 bool with_ports = false;
226 u8 cidr; 172 u8 cidr;
227 int ret; 173 int ret;
@@ -236,7 +182,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
236 if (tb[IPSET_ATTR_LINENO]) 182 if (tb[IPSET_ATTR_LINENO])
237 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 183 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
238 184
239 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 185 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
186 ip_set_get_extensions(set, tb, &ext);
240 if (ret) 187 if (ret)
241 return ret; 188 return ret;
242 189
@@ -244,31 +191,25 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
244 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 191 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
245 if (!cidr || cidr > HOST_MASK) 192 if (!cidr || cidr > HOST_MASK)
246 return -IPSET_ERR_INVALID_CIDR; 193 return -IPSET_ERR_INVALID_CIDR;
247 data.cidr = cidr - 1; 194 e.cidr = cidr - 1;
248 } 195 }
249 196
250 if (tb[IPSET_ATTR_PORT]) 197 if (tb[IPSET_ATTR_PORT])
251 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 198 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
252 else 199 else
253 return -IPSET_ERR_PROTOCOL; 200 return -IPSET_ERR_PROTOCOL;
254 201
255 if (tb[IPSET_ATTR_PROTO]) { 202 if (tb[IPSET_ATTR_PROTO]) {
256 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 203 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
257 with_ports = ip_set_proto_with_ports(data.proto); 204 with_ports = ip_set_proto_with_ports(e.proto);
258 205
259 if (data.proto == 0) 206 if (e.proto == 0)
260 return -IPSET_ERR_INVALID_PROTO; 207 return -IPSET_ERR_INVALID_PROTO;
261 } else 208 } else
262 return -IPSET_ERR_MISSING_PROTO; 209 return -IPSET_ERR_MISSING_PROTO;
263 210
264 if (!(with_ports || data.proto == IPPROTO_ICMP)) 211 if (!(with_ports || e.proto == IPPROTO_ICMP))
265 data.port = 0; 212 e.port = 0;
266
267 if (tb[IPSET_ATTR_TIMEOUT]) {
268 if (!with_timeout(h->timeout))
269 return -IPSET_ERR_TIMEOUT;
270 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
271 }
272 213
273 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 214 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
274 215
@@ -279,13 +220,13 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
279 } 220 }
280 221
281 if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) { 222 if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
282 data.ip = htonl(ip & ip_set_hostmask(data.cidr + 1)); 223 e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1));
283 ret = adtfn(set, &data, timeout, flags); 224 ret = adtfn(set, &e, &ext, &ext, flags);
284 return ip_set_enomatch(ret, flags, adt) ? 1 : 225 return ip_set_enomatch(ret, flags, adt) ? 1 :
285 ip_set_eexist(ret, flags) ? 0 : ret; 226 ip_set_eexist(ret, flags) ? 0 : ret;
286 } 227 }
287 228
288 port = port_to = ntohs(data.port); 229 port = port_to = ntohs(e.port);
289 if (tb[IPSET_ATTR_PORT_TO]) { 230 if (tb[IPSET_ATTR_PORT_TO]) {
290 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 231 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
291 if (port_to < port) 232 if (port_to < port)
@@ -299,21 +240,20 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
299 swap(ip, ip_to); 240 swap(ip, ip_to);
300 if (ip + UINT_MAX == ip_to) 241 if (ip + UINT_MAX == ip_to)
301 return -IPSET_ERR_HASH_RANGE; 242 return -IPSET_ERR_HASH_RANGE;
302 } else { 243 } else
303 ip_set_mask_from_to(ip, ip_to, data.cidr + 1); 244 ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
304 }
305 245
306 if (retried) 246 if (retried)
307 ip = ntohl(h->next.ip); 247 ip = ntohl(h->next.ip);
308 while (!after(ip, ip_to)) { 248 while (!after(ip, ip_to)) {
309 data.ip = htonl(ip); 249 e.ip = htonl(ip);
310 last = ip_set_range_to_cidr(ip, ip_to, &cidr); 250 last = ip_set_range_to_cidr(ip, ip_to, &cidr);
311 data.cidr = cidr - 1; 251 e.cidr = cidr - 1;
312 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 252 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
313 : port; 253 : port;
314 for (; p <= port_to; p++) { 254 for (; p <= port_to; p++) {
315 data.port = htons(p); 255 e.port = htons(p);
316 ret = adtfn(set, &data, timeout, flags); 256 ret = adtfn(set, &e, &ext, &ext, flags);
317 257
318 if (ret && !ip_set_eexist(ret, flags)) 258 if (ret && !ip_set_eexist(ret, flags))
319 return ret; 259 return ret;
@@ -325,18 +265,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
325 return ret; 265 return ret;
326} 266}
327 267
328static bool 268/* IPv6 variants */
329hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
330{
331 const struct ip_set_hash *x = a->data;
332 const struct ip_set_hash *y = b->data;
333
334 /* Resizing changes htable_bits, so we ignore it */
335 return x->maxelem == y->maxelem &&
336 x->timeout == y->timeout;
337}
338
339/* The type variant functions: IPv6 */
340 269
341struct hash_netport6_elem { 270struct hash_netport6_elem {
342 union nf_inet_addr ip; 271 union nf_inet_addr ip;
@@ -346,7 +275,7 @@ struct hash_netport6_elem {
346 u8 nomatch:1; 275 u8 nomatch:1;
347}; 276};
348 277
349struct hash_netport6_telem { 278struct hash_netport6t_elem {
350 union nf_inet_addr ip; 279 union nf_inet_addr ip;
351 __be16 port; 280 __be16 port;
352 u8 proto; 281 u8 proto;
@@ -355,6 +284,8 @@ struct hash_netport6_telem {
355 unsigned long timeout; 284 unsigned long timeout;
356}; 285};
357 286
287/* Common functions */
288
358static inline bool 289static inline bool
359hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 290hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
360 const struct hash_netport6_elem *ip2, 291 const struct hash_netport6_elem *ip2,
@@ -366,44 +297,22 @@ hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
366 ip1->cidr == ip2->cidr; 297 ip1->cidr == ip2->cidr;
367} 298}
368 299
369static inline bool 300static inline int
370hash_netport6_data_isnull(const struct hash_netport6_elem *elem) 301hash_netport6_do_data_match(const struct hash_netport6_elem *elem)
371{
372 return elem->proto == 0;
373}
374
375static inline void
376hash_netport6_data_copy(struct hash_netport6_elem *dst,
377 const struct hash_netport6_elem *src)
378{
379 memcpy(dst, src, sizeof(*dst));
380}
381
382static inline void
383hash_netport6_data_flags(struct hash_netport6_elem *dst, u32 flags)
384{ 302{
385 dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH); 303 return elem->nomatch ? -ENOTEMPTY : 1;
386} 304}
387 305
388static inline void 306static inline void
389hash_netport6_data_reset_flags(struct hash_netport6_elem *dst, u32 *flags) 307hash_netport6_data_set_flags(struct hash_netport6_elem *elem, u32 flags)
390{
391 if (dst->nomatch) {
392 *flags = IPSET_FLAG_NOMATCH;
393 dst->nomatch = 0;
394 }
395}
396
397static inline int
398hash_netport6_data_match(const struct hash_netport6_elem *elem)
399{ 308{
400 return elem->nomatch ? -ENOTEMPTY : 1; 309 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
401} 310}
402 311
403static inline void 312static inline void
404hash_netport6_data_zero_out(struct hash_netport6_elem *elem) 313hash_netport6_data_reset_flags(struct hash_netport6_elem *elem, u8 *flags)
405{ 314{
406 elem->proto = 0; 315 swap(*flags, elem->nomatch);
407} 316}
408 317
409static inline void 318static inline void
@@ -432,76 +341,57 @@ nla_put_failure:
432 return 1; 341 return 1;
433} 342}
434 343
435static bool 344static inline void
436hash_netport6_data_tlist(struct sk_buff *skb, 345hash_netport6_data_next(struct hash_netport4_elem *next,
437 const struct hash_netport6_elem *data) 346 const struct hash_netport6_elem *d)
438{ 347{
439 const struct hash_netport6_telem *e = 348 next->port = d->port;
440 (const struct hash_netport6_telem *)data;
441 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
442
443 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
444 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
445 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) ||
446 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
447 nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
448 htonl(ip_set_timeout_get(e->timeout))) ||
449 (flags &&
450 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
451 goto nla_put_failure;
452 return 0;
453
454nla_put_failure:
455 return 1;
456} 349}
457 350
351#undef MTYPE
458#undef PF 352#undef PF
459#undef HOST_MASK 353#undef HOST_MASK
460 354
355#define MTYPE hash_netport6
461#define PF 6 356#define PF 6
462#define HOST_MASK 128 357#define HOST_MASK 128
463#include <linux/netfilter/ipset/ip_set_ahash.h> 358#define IP_SET_EMIT_CREATE
464 359#include "ip_set_hash_gen.h"
465static inline void
466hash_netport6_data_next(struct ip_set_hash *h,
467 const struct hash_netport6_elem *d)
468{
469 h->next.port = d->port;
470}
471 360
472static int 361static int
473hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, 362hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
474 const struct xt_action_param *par, 363 const struct xt_action_param *par,
475 enum ipset_adt adt, const struct ip_set_adt_opt *opt) 364 enum ipset_adt adt, struct ip_set_adt_opt *opt)
476{ 365{
477 const struct ip_set_hash *h = set->data; 366 const struct hash_netport *h = set->data;
478 ipset_adtfn adtfn = set->variant->adt[adt]; 367 ipset_adtfn adtfn = set->variant->adt[adt];
479 struct hash_netport6_elem data = { 368 struct hash_netport6_elem e = {
480 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1, 369 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1,
481 }; 370 };
371 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
482 372
483 if (adt == IPSET_TEST) 373 if (adt == IPSET_TEST)
484 data.cidr = HOST_MASK - 1; 374 e.cidr = HOST_MASK - 1;
485 375
486 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 376 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
487 &data.port, &data.proto)) 377 &e.port, &e.proto))
488 return -EINVAL; 378 return -EINVAL;
489 379
490 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 380 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
491 ip6_netmask(&data.ip, data.cidr + 1); 381 ip6_netmask(&e.ip, e.cidr + 1);
492 382
493 return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags); 383 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
494} 384}
495 385
496static int 386static int
497hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], 387hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
498 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 388 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
499{ 389{
500 const struct ip_set_hash *h = set->data; 390 const struct hash_netport *h = set->data;
501 ipset_adtfn adtfn = set->variant->adt[adt]; 391 ipset_adtfn adtfn = set->variant->adt[adt];
502 struct hash_netport6_elem data = { .cidr = HOST_MASK - 1 }; 392 struct hash_netport6_elem e = { .cidr = HOST_MASK - 1 };
393 struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
503 u32 port, port_to; 394 u32 port, port_to;
504 u32 timeout = h->timeout;
505 bool with_ports = false; 395 bool with_ports = false;
506 u8 cidr; 396 u8 cidr;
507 int ret; 397 int ret;
@@ -518,7 +408,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
518 if (tb[IPSET_ATTR_LINENO]) 408 if (tb[IPSET_ATTR_LINENO])
519 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 409 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
520 410
521 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 411 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
412 ip_set_get_extensions(set, tb, &ext);
522 if (ret) 413 if (ret)
523 return ret; 414 return ret;
524 415
@@ -526,32 +417,26 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
526 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 417 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
527 if (!cidr || cidr > HOST_MASK) 418 if (!cidr || cidr > HOST_MASK)
528 return -IPSET_ERR_INVALID_CIDR; 419 return -IPSET_ERR_INVALID_CIDR;
529 data.cidr = cidr - 1; 420 e.cidr = cidr - 1;
530 } 421 }
531 ip6_netmask(&data.ip, data.cidr + 1); 422 ip6_netmask(&e.ip, e.cidr + 1);
532 423
533 if (tb[IPSET_ATTR_PORT]) 424 if (tb[IPSET_ATTR_PORT])
534 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 425 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
535 else 426 else
536 return -IPSET_ERR_PROTOCOL; 427 return -IPSET_ERR_PROTOCOL;
537 428
538 if (tb[IPSET_ATTR_PROTO]) { 429 if (tb[IPSET_ATTR_PROTO]) {
539 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 430 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
540 with_ports = ip_set_proto_with_ports(data.proto); 431 with_ports = ip_set_proto_with_ports(e.proto);
541 432
542 if (data.proto == 0) 433 if (e.proto == 0)
543 return -IPSET_ERR_INVALID_PROTO; 434 return -IPSET_ERR_INVALID_PROTO;
544 } else 435 } else
545 return -IPSET_ERR_MISSING_PROTO; 436 return -IPSET_ERR_MISSING_PROTO;
546 437
547 if (!(with_ports || data.proto == IPPROTO_ICMPV6)) 438 if (!(with_ports || e.proto == IPPROTO_ICMPV6))
548 data.port = 0; 439 e.port = 0;
549
550 if (tb[IPSET_ATTR_TIMEOUT]) {
551 if (!with_timeout(h->timeout))
552 return -IPSET_ERR_TIMEOUT;
553 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
554 }
555 440
556 if (tb[IPSET_ATTR_CADT_FLAGS]) { 441 if (tb[IPSET_ATTR_CADT_FLAGS]) {
557 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 442 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
@@ -560,12 +445,12 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
560 } 445 }
561 446
562 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 447 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
563 ret = adtfn(set, &data, timeout, flags); 448 ret = adtfn(set, &e, &ext, &ext, flags);
564 return ip_set_enomatch(ret, flags, adt) ? 1 : 449 return ip_set_enomatch(ret, flags, adt) ? 1 :
565 ip_set_eexist(ret, flags) ? 0 : ret; 450 ip_set_eexist(ret, flags) ? 0 : ret;
566 } 451 }
567 452
568 port = ntohs(data.port); 453 port = ntohs(e.port);
569 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 454 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
570 if (port > port_to) 455 if (port > port_to)
571 swap(port, port_to); 456 swap(port, port_to);
@@ -573,8 +458,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
573 if (retried) 458 if (retried)
574 port = ntohs(h->next.port); 459 port = ntohs(h->next.port);
575 for (; port <= port_to; port++) { 460 for (; port <= port_to; port++) {
576 data.port = htons(port); 461 e.port = htons(port);
577 ret = adtfn(set, &data, timeout, flags); 462 ret = adtfn(set, &e, &ext, &ext, flags);
578 463
579 if (ret && !ip_set_eexist(ret, flags)) 464 if (ret && !ip_set_eexist(ret, flags))
580 return ret; 465 return ret;
@@ -584,80 +469,6 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
584 return ret; 469 return ret;
585} 470}
586 471
587/* Create hash:ip type of sets */
588
589static int
590hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
591{
592 struct ip_set_hash *h;
593 u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
594 u8 hbits;
595 size_t hsize;
596
597 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
598 return -IPSET_ERR_INVALID_FAMILY;
599
600 if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
601 !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
602 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
603 return -IPSET_ERR_PROTOCOL;
604
605 if (tb[IPSET_ATTR_HASHSIZE]) {
606 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
607 if (hashsize < IPSET_MIMINAL_HASHSIZE)
608 hashsize = IPSET_MIMINAL_HASHSIZE;
609 }
610
611 if (tb[IPSET_ATTR_MAXELEM])
612 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
613
614 h = kzalloc(sizeof(*h)
615 + sizeof(struct ip_set_hash_nets)
616 * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
617 if (!h)
618 return -ENOMEM;
619
620 h->maxelem = maxelem;
621 get_random_bytes(&h->initval, sizeof(h->initval));
622 h->timeout = IPSET_NO_TIMEOUT;
623
624 hbits = htable_bits(hashsize);
625 hsize = htable_size(hbits);
626 if (hsize == 0) {
627 kfree(h);
628 return -ENOMEM;
629 }
630 h->table = ip_set_alloc(hsize);
631 if (!h->table) {
632 kfree(h);
633 return -ENOMEM;
634 }
635 h->table->htable_bits = hbits;
636
637 set->data = h;
638
639 if (tb[IPSET_ATTR_TIMEOUT]) {
640 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
641
642 set->variant = set->family == NFPROTO_IPV4
643 ? &hash_netport4_tvariant : &hash_netport6_tvariant;
644
645 if (set->family == NFPROTO_IPV4)
646 hash_netport4_gc_init(set);
647 else
648 hash_netport6_gc_init(set);
649 } else {
650 set->variant = set->family == NFPROTO_IPV4
651 ? &hash_netport4_variant : &hash_netport6_variant;
652 }
653
654 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
655 set->name, jhash_size(h->table->htable_bits),
656 h->table->htable_bits, h->maxelem, set->data, h->table);
657
658 return 0;
659}
660
661static struct ip_set_type hash_netport_type __read_mostly = { 472static struct ip_set_type hash_netport_type __read_mostly = {
662 .name = "hash:net,port", 473 .name = "hash:net,port",
663 .protocol = IPSET_PROTOCOL, 474 .protocol = IPSET_PROTOCOL,
@@ -674,6 +485,7 @@ static struct ip_set_type hash_netport_type __read_mostly = {
674 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 485 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
675 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 486 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
676 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 487 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
488 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
677 }, 489 },
678 .adt_policy = { 490 .adt_policy = {
679 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 491 [IPSET_ATTR_IP] = { .type = NLA_NESTED },