netfilter: ipset: fix hash size checking in kernel
[linux-flexiantxendom0-3.2.10.git] / net / netfilter / ipset / ip_set_hash_ipportnet.c
1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation.
6  */
7
8 /* Kernel module implementing an IP set type: the hash:ip,port,net type */
9
10 #include <linux/jhash.h>
11 #include <linux/module.h>
12 #include <linux/ip.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
15 #include <linux/random.h>
16 #include <net/ip.h>
17 #include <net/ipv6.h>
18 #include <net/netlink.h>
19 #include <net/tcp.h>
20
21 #include <linux/netfilter.h>
22 #include <linux/netfilter/ipset/pfxlen.h>
23 #include <linux/netfilter/ipset/ip_set.h>
24 #include <linux/netfilter/ipset/ip_set_timeout.h>
25 #include <linux/netfilter/ipset/ip_set_getport.h>
26 #include <linux/netfilter/ipset/ip_set_hash.h>
27
28 MODULE_LICENSE("GPL");
29 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30 MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
31 MODULE_ALIAS("ip_set_hash:ip,port,net");
32
33 /* Type specific function prefix */
34 #define TYPE            hash_ipportnet
35
36 static bool
37 hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
38
39 #define hash_ipportnet4_same_set        hash_ipportnet_same_set
40 #define hash_ipportnet6_same_set        hash_ipportnet_same_set
41
42 /* The type variant functions: IPv4 */
43
44 /* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0
45  * However this way we have to store internally cidr - 1,
46  * dancing back and forth.
47  */
48 #define IP_SET_HASH_WITH_NETS_PACKED
49
50 /* Member elements without timeout */
51 struct hash_ipportnet4_elem {
52         __be32 ip;
53         __be32 ip2;
54         __be16 port;
55         u8 cidr:7;
56         u8 nomatch:1;
57         u8 proto;
58 };
59
60 /* Member elements with timeout support */
61 struct hash_ipportnet4_telem {
62         __be32 ip;
63         __be32 ip2;
64         __be16 port;
65         u8 cidr:7;
66         u8 nomatch:1;
67         u8 proto;
68         unsigned long timeout;
69 };
70
71 static inline bool
72 hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
73                            const struct hash_ipportnet4_elem *ip2,
74                            u32 *multi)
75 {
76         return ip1->ip == ip2->ip &&
77                ip1->ip2 == ip2->ip2 &&
78                ip1->cidr == ip2->cidr &&
79                ip1->port == ip2->port &&
80                ip1->proto == ip2->proto;
81 }
82
83 static inline bool
84 hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
85 {
86         return elem->proto == 0;
87 }
88
89 static inline void
90 hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
91                           const struct hash_ipportnet4_elem *src)
92 {
93         memcpy(dst, src, sizeof(*dst));
94 }
95
96 static inline void
97 hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
98 {
99         dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
100 }
101
102 static inline bool
103 hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
104 {
105         return !elem->nomatch;
106 }
107
108 static inline void
109 hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
110 {
111         elem->ip2 &= ip_set_netmask(cidr);
112         elem->cidr = cidr - 1;
113 }
114
115 static inline void
116 hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
117 {
118         elem->proto = 0;
119 }
120
121 static bool
122 hash_ipportnet4_data_list(struct sk_buff *skb,
123                           const struct hash_ipportnet4_elem *data)
124 {
125         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
126
127         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
128         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
129         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
130         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1);
131         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
132         if (flags)
133                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
134         return 0;
135
136 nla_put_failure:
137         return 1;
138 }
139
140 static bool
141 hash_ipportnet4_data_tlist(struct sk_buff *skb,
142                            const struct hash_ipportnet4_elem *data)
143 {
144         const struct hash_ipportnet4_telem *tdata =
145                 (const struct hash_ipportnet4_telem *)data;
146         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
147
148         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
149         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
150         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
151         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1);
152         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
153         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
154                       htonl(ip_set_timeout_get(tdata->timeout)));
155         if (flags)
156                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
157
158         return 0;
159
160 nla_put_failure:
161         return 1;
162 }
163
164 #define IP_SET_HASH_WITH_PROTO
165 #define IP_SET_HASH_WITH_NETS
166
167 #define PF              4
168 #define HOST_MASK       32
169 #include <linux/netfilter/ipset/ip_set_ahash.h>
170
171 static inline void
172 hash_ipportnet4_data_next(struct ip_set_hash *h,
173                           const struct hash_ipportnet4_elem *d)
174 {
175         h->next.ip = ntohl(d->ip);
176         h->next.port = ntohs(d->port);
177         h->next.ip2 = ntohl(d->ip2);
178 }
179
180 static int
181 hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
182                      const struct xt_action_param *par,
183                      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
184 {
185         const struct ip_set_hash *h = set->data;
186         ipset_adtfn adtfn = set->variant->adt[adt];
187         struct hash_ipportnet4_elem data = {
188                 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
189         };
190
191         if (adt == IPSET_TEST)
192                 data.cidr = HOST_MASK - 1;
193
194         if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
195                                  &data.port, &data.proto))
196                 return -EINVAL;
197
198         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
199         ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
200         data.ip2 &= ip_set_netmask(data.cidr + 1);
201
202         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
203 }
204
205 static int
206 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
207                      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
208 {
209         const struct ip_set_hash *h = set->data;
210         ipset_adtfn adtfn = set->variant->adt[adt];
211         struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
212         u32 ip, ip_to = 0, p = 0, port, port_to;
213         u32 ip2_from = 0, ip2_to, ip2_last, ip2;
214         u32 timeout = h->timeout;
215         bool with_ports = false;
216         u8 cidr;
217         int ret;
218
219         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
220                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
221                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
222                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
223                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
224                 return -IPSET_ERR_PROTOCOL;
225
226         if (tb[IPSET_ATTR_LINENO])
227                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
228
229         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
230         if (ret)
231                 return ret;
232
233         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
234         if (ret)
235                 return ret;
236
237         if (tb[IPSET_ATTR_CIDR2]) {
238                 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
239                 if (!cidr || cidr > HOST_MASK)
240                         return -IPSET_ERR_INVALID_CIDR;
241                 data.cidr = cidr - 1;
242         }
243
244         if (tb[IPSET_ATTR_PORT])
245                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
246         else
247                 return -IPSET_ERR_PROTOCOL;
248
249         if (tb[IPSET_ATTR_PROTO]) {
250                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
251                 with_ports = ip_set_proto_with_ports(data.proto);
252
253                 if (data.proto == 0)
254                         return -IPSET_ERR_INVALID_PROTO;
255         } else
256                 return -IPSET_ERR_MISSING_PROTO;
257
258         if (!(with_ports || data.proto == IPPROTO_ICMP))
259                 data.port = 0;
260
261         if (tb[IPSET_ATTR_TIMEOUT]) {
262                 if (!with_timeout(h->timeout))
263                         return -IPSET_ERR_TIMEOUT;
264                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
265         }
266
267         if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) {
268                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
269                 if (cadt_flags & IPSET_FLAG_NOMATCH)
270                         flags |= (cadt_flags << 16);
271         }
272
273         with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
274         if (adt == IPSET_TEST ||
275             !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
276               tb[IPSET_ATTR_IP2_TO])) {
277                 data.ip = htonl(ip);
278                 data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1));
279                 ret = adtfn(set, &data, timeout, flags);
280                 return ip_set_eexist(ret, flags) ? 0 : ret;
281         }
282
283         if (tb[IPSET_ATTR_IP_TO]) {
284                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
285                 if (ret)
286                         return ret;
287                 if (ip > ip_to)
288                         swap(ip, ip_to);
289         } else if (tb[IPSET_ATTR_CIDR]) {
290                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
291
292                 if (cidr > 32)
293                         return -IPSET_ERR_INVALID_CIDR;
294                 ip_set_mask_from_to(ip, ip_to, cidr);
295         }
296
297         port_to = port = ntohs(data.port);
298         if (tb[IPSET_ATTR_PORT_TO]) {
299                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
300                 if (port > port_to)
301                         swap(port, port_to);
302         }
303         if (tb[IPSET_ATTR_IP2_TO]) {
304                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
305                 if (ret)
306                         return ret;
307                 if (ip2_from > ip2_to)
308                         swap(ip2_from, ip2_to);
309                 if (ip2_from + UINT_MAX == ip2_to)
310                         return -IPSET_ERR_HASH_RANGE;
311         } else {
312                 ip_set_mask_from_to(ip2_from, ip2_to, data.cidr + 1);
313         }
314
315         if (retried)
316                 ip = h->next.ip;
317         for (; !before(ip_to, ip); ip++) {
318                 data.ip = htonl(ip);
319                 p = retried && ip == h->next.ip ? h->next.port : port;
320                 for (; p <= port_to; p++) {
321                         data.port = htons(p);
322                         ip2 = retried && ip == h->next.ip && p == h->next.port
323                                 ? h->next.ip2 : ip2_from;
324                         while (!after(ip2, ip2_to)) {
325                                 data.ip2 = htonl(ip2);
326                                 ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
327                                                                 &cidr);
328                                 data.cidr = cidr - 1;
329                                 ret = adtfn(set, &data, timeout, flags);
330
331                                 if (ret && !ip_set_eexist(ret, flags))
332                                         return ret;
333                                 else
334                                         ret = 0;
335                                 ip2 = ip2_last + 1;
336                         }
337                 }
338         }
339         return ret;
340 }
341
342 static bool
343 hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
344 {
345         const struct ip_set_hash *x = a->data;
346         const struct ip_set_hash *y = b->data;
347
348         /* Resizing changes htable_bits, so we ignore it */
349         return x->maxelem == y->maxelem &&
350                x->timeout == y->timeout;
351 }
352
353 /* The type variant functions: IPv6 */
354
355 struct hash_ipportnet6_elem {
356         union nf_inet_addr ip;
357         union nf_inet_addr ip2;
358         __be16 port;
359         u8 cidr:7;
360         u8 nomatch:1;
361         u8 proto;
362 };
363
364 struct hash_ipportnet6_telem {
365         union nf_inet_addr ip;
366         union nf_inet_addr ip2;
367         __be16 port;
368         u8 cidr:7;
369         u8 nomatch:1;
370         u8 proto;
371         unsigned long timeout;
372 };
373
374 static inline bool
375 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
376                            const struct hash_ipportnet6_elem *ip2,
377                            u32 *multi)
378 {
379         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
380                ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
381                ip1->cidr == ip2->cidr &&
382                ip1->port == ip2->port &&
383                ip1->proto == ip2->proto;
384 }
385
386 static inline bool
387 hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
388 {
389         return elem->proto == 0;
390 }
391
392 static inline void
393 hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
394                           const struct hash_ipportnet6_elem *src)
395 {
396         memcpy(dst, src, sizeof(*dst));
397 }
398
399 static inline void
400 hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
401 {
402         dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
403 }
404
405 static inline bool
406 hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
407 {
408         return !elem->nomatch;
409 }
410
411 static inline void
412 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
413 {
414         elem->proto = 0;
415 }
416
417 static inline void
418 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
419 {
420         ip->ip6[0] &= ip_set_netmask6(prefix)[0];
421         ip->ip6[1] &= ip_set_netmask6(prefix)[1];
422         ip->ip6[2] &= ip_set_netmask6(prefix)[2];
423         ip->ip6[3] &= ip_set_netmask6(prefix)[3];
424 }
425
426 static inline void
427 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
428 {
429         ip6_netmask(&elem->ip2, cidr);
430         elem->cidr = cidr - 1;
431 }
432
433 static bool
434 hash_ipportnet6_data_list(struct sk_buff *skb,
435                           const struct hash_ipportnet6_elem *data)
436 {
437         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
438
439         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
440         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
441         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
442         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1);
443         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
444         if (flags)
445                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
446         return 0;
447
448 nla_put_failure:
449         return 1;
450 }
451
452 static bool
453 hash_ipportnet6_data_tlist(struct sk_buff *skb,
454                            const struct hash_ipportnet6_elem *data)
455 {
456         const struct hash_ipportnet6_telem *e =
457                 (const struct hash_ipportnet6_telem *)data;
458         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
459
460         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
461         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
462         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
463         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr + 1);
464         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
465         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
466                       htonl(ip_set_timeout_get(e->timeout)));
467         if (flags)
468                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
469         return 0;
470
471 nla_put_failure:
472         return 1;
473 }
474
475 #undef PF
476 #undef HOST_MASK
477
478 #define PF              6
479 #define HOST_MASK       128
480 #include <linux/netfilter/ipset/ip_set_ahash.h>
481
482 static inline void
483 hash_ipportnet6_data_next(struct ip_set_hash *h,
484                           const struct hash_ipportnet6_elem *d)
485 {
486         h->next.port = ntohs(d->port);
487 }
488
489 static int
490 hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
491                      const struct xt_action_param *par,
492                      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
493 {
494         const struct ip_set_hash *h = set->data;
495         ipset_adtfn adtfn = set->variant->adt[adt];
496         struct hash_ipportnet6_elem data = {
497                 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
498         };
499
500         if (adt == IPSET_TEST)
501                 data.cidr = HOST_MASK - 1;
502
503         if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
504                                  &data.port, &data.proto))
505                 return -EINVAL;
506
507         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
508         ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
509         ip6_netmask(&data.ip2, data.cidr + 1);
510
511         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
512 }
513
514 static int
515 hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
516                      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
517 {
518         const struct ip_set_hash *h = set->data;
519         ipset_adtfn adtfn = set->variant->adt[adt];
520         struct hash_ipportnet6_elem data = { .cidr = HOST_MASK - 1 };
521         u32 port, port_to;
522         u32 timeout = h->timeout;
523         bool with_ports = false;
524         u8 cidr;
525         int ret;
526
527         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
528                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
529                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
530                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
531                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
532                      tb[IPSET_ATTR_IP_TO] ||
533                      tb[IPSET_ATTR_CIDR]))
534                 return -IPSET_ERR_PROTOCOL;
535         if (unlikely(tb[IPSET_ATTR_IP_TO]))
536                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
537
538         if (tb[IPSET_ATTR_LINENO])
539                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
540
541         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
542         if (ret)
543                 return ret;
544
545         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
546         if (ret)
547                 return ret;
548
549         if (tb[IPSET_ATTR_CIDR2]) {
550                 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
551                 if (!cidr || cidr > HOST_MASK)
552                         return -IPSET_ERR_INVALID_CIDR;
553                 data.cidr = cidr - 1;
554         }
555
556         ip6_netmask(&data.ip2, data.cidr + 1);
557
558         if (tb[IPSET_ATTR_PORT])
559                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
560         else
561                 return -IPSET_ERR_PROTOCOL;
562
563         if (tb[IPSET_ATTR_PROTO]) {
564                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
565                 with_ports = ip_set_proto_with_ports(data.proto);
566
567                 if (data.proto == 0)
568                         return -IPSET_ERR_INVALID_PROTO;
569         } else
570                 return -IPSET_ERR_MISSING_PROTO;
571
572         if (!(with_ports || data.proto == IPPROTO_ICMPV6))
573                 data.port = 0;
574
575         if (tb[IPSET_ATTR_TIMEOUT]) {
576                 if (!with_timeout(h->timeout))
577                         return -IPSET_ERR_TIMEOUT;
578                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
579         }
580
581         if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) {
582                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
583                 if (cadt_flags & IPSET_FLAG_NOMATCH)
584                         flags |= (cadt_flags << 16);
585         }
586
587         if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
588                 ret = adtfn(set, &data, timeout, flags);
589                 return ip_set_eexist(ret, flags) ? 0 : ret;
590         }
591
592         port = ntohs(data.port);
593         port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
594         if (port > port_to)
595                 swap(port, port_to);
596
597         if (retried)
598                 port = h->next.port;
599         for (; port <= port_to; port++) {
600                 data.port = htons(port);
601                 ret = adtfn(set, &data, timeout, flags);
602
603                 if (ret && !ip_set_eexist(ret, flags))
604                         return ret;
605                 else
606                         ret = 0;
607         }
608         return ret;
609 }
610
611 /* Create hash:ip type of sets */
612
613 static int
614 hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
615 {
616         struct ip_set_hash *h;
617         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
618         u8 hbits;
619         size_t hsize;
620
621         if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
622                 return -IPSET_ERR_INVALID_FAMILY;
623
624         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
625                      !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
626                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
627                 return -IPSET_ERR_PROTOCOL;
628
629         if (tb[IPSET_ATTR_HASHSIZE]) {
630                 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
631                 if (hashsize < IPSET_MIMINAL_HASHSIZE)
632                         hashsize = IPSET_MIMINAL_HASHSIZE;
633         }
634
635         if (tb[IPSET_ATTR_MAXELEM])
636                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
637
638         h = kzalloc(sizeof(*h)
639                     + sizeof(struct ip_set_hash_nets)
640                       * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
641         if (!h)
642                 return -ENOMEM;
643
644         h->maxelem = maxelem;
645         get_random_bytes(&h->initval, sizeof(h->initval));
646         h->timeout = IPSET_NO_TIMEOUT;
647
648         hbits = htable_bits(hashsize);
649         hsize = htable_size(hbits);
650         if (hsize == 0) {
651                 kfree(h);
652                 return -ENOMEM;
653         }
654         h->table = ip_set_alloc(hsize);
655         if (!h->table) {
656                 kfree(h);
657                 return -ENOMEM;
658         }
659         h->table->htable_bits = hbits;
660
661         set->data = h;
662
663         if (tb[IPSET_ATTR_TIMEOUT]) {
664                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
665
666                 set->variant = set->family == NFPROTO_IPV4
667                         ? &hash_ipportnet4_tvariant
668                         : &hash_ipportnet6_tvariant;
669
670                 if (set->family == NFPROTO_IPV4)
671                         hash_ipportnet4_gc_init(set);
672                 else
673                         hash_ipportnet6_gc_init(set);
674         } else {
675                 set->variant = set->family == NFPROTO_IPV4
676                         ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
677         }
678
679         pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
680                  set->name, jhash_size(h->table->htable_bits),
681                  h->table->htable_bits, h->maxelem, set->data, h->table);
682
683         return 0;
684 }
685
686 static struct ip_set_type hash_ipportnet_type __read_mostly = {
687         .name           = "hash:ip,port,net",
688         .protocol       = IPSET_PROTOCOL,
689         .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
690         .dimension      = IPSET_DIM_THREE,
691         .family         = NFPROTO_UNSPEC,
692         .revision_min   = 0,
693         /*                1        SCTP and UDPLITE support added */
694         /*                2        Range as input support for IPv4 added */
695         .revision_max   = 3,    /* nomatch flag support added */
696         .create         = hash_ipportnet_create,
697         .create_policy  = {
698                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
699                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
700                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
701                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
702                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
703         },
704         .adt_policy     = {
705                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
706                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
707                 [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
708                 [IPSET_ATTR_IP2_TO]     = { .type = NLA_NESTED },
709                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
710                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
711                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
712                 [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
713                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
714                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
715                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
716                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
717         },
718         .me             = THIS_MODULE,
719 };
720
721 static int __init
722 hash_ipportnet_init(void)
723 {
724         return ip_set_type_register(&hash_ipportnet_type);
725 }
726
727 static void __exit
728 hash_ipportnet_fini(void)
729 {
730         ip_set_type_unregister(&hash_ipportnet_type);
731 }
732
733 module_init(hash_ipportnet_init);
734 module_exit(hash_ipportnet_fini);