]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/netfilter/ipset/ip_set_hash_ipportnet.c
Merge tag 'remoteproc-for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/ohad...
[karo-tx-linux.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         if (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             (flags &&
133              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
134                 goto nla_put_failure;
135         return 0;
136
137 nla_put_failure:
138         return 1;
139 }
140
141 static bool
142 hash_ipportnet4_data_tlist(struct sk_buff *skb,
143                            const struct hash_ipportnet4_elem *data)
144 {
145         const struct hash_ipportnet4_telem *tdata =
146                 (const struct hash_ipportnet4_telem *)data;
147         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
148
149         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
150             nla_put_ipaddr4(skb, IPSET_ATTR_IP2, tdata->ip2) ||
151             nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) ||
152             nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
153             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
154             nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
155                           htonl(ip_set_timeout_get(tdata->timeout))) ||
156             (flags &&
157              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
158                 goto nla_put_failure;
159         return 0;
160
161 nla_put_failure:
162         return 1;
163 }
164
165 #define IP_SET_HASH_WITH_PROTO
166 #define IP_SET_HASH_WITH_NETS
167
168 #define PF              4
169 #define HOST_MASK       32
170 #include <linux/netfilter/ipset/ip_set_ahash.h>
171
172 static inline void
173 hash_ipportnet4_data_next(struct ip_set_hash *h,
174                           const struct hash_ipportnet4_elem *d)
175 {
176         h->next.ip = ntohl(d->ip);
177         h->next.port = ntohs(d->port);
178         h->next.ip2 = ntohl(d->ip2);
179 }
180
181 static int
182 hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
183                      const struct xt_action_param *par,
184                      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
185 {
186         const struct ip_set_hash *h = set->data;
187         ipset_adtfn adtfn = set->variant->adt[adt];
188         struct hash_ipportnet4_elem data = {
189                 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
190         };
191
192         if (adt == IPSET_TEST)
193                 data.cidr = HOST_MASK - 1;
194
195         if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
196                                  &data.port, &data.proto))
197                 return -EINVAL;
198
199         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
200         ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
201         data.ip2 &= ip_set_netmask(data.cidr + 1);
202
203         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
204 }
205
206 static int
207 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
208                      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
209 {
210         const struct ip_set_hash *h = set->data;
211         ipset_adtfn adtfn = set->variant->adt[adt];
212         struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
213         u32 ip, ip_to = 0, p = 0, port, port_to;
214         u32 ip2_from = 0, ip2_to, ip2_last, ip2;
215         u32 timeout = h->timeout;
216         bool with_ports = false;
217         u8 cidr;
218         int ret;
219
220         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
221                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
222                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
223                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
224                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
225                 return -IPSET_ERR_PROTOCOL;
226
227         if (tb[IPSET_ATTR_LINENO])
228                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
229
230         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
231         if (ret)
232                 return ret;
233
234         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
235         if (ret)
236                 return ret;
237
238         if (tb[IPSET_ATTR_CIDR2]) {
239                 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
240                 if (!cidr || cidr > HOST_MASK)
241                         return -IPSET_ERR_INVALID_CIDR;
242                 data.cidr = cidr - 1;
243         }
244
245         if (tb[IPSET_ATTR_PORT])
246                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
247         else
248                 return -IPSET_ERR_PROTOCOL;
249
250         if (tb[IPSET_ATTR_PROTO]) {
251                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
252                 with_ports = ip_set_proto_with_ports(data.proto);
253
254                 if (data.proto == 0)
255                         return -IPSET_ERR_INVALID_PROTO;
256         } else
257                 return -IPSET_ERR_MISSING_PROTO;
258
259         if (!(with_ports || data.proto == IPPROTO_ICMP))
260                 data.port = 0;
261
262         if (tb[IPSET_ATTR_TIMEOUT]) {
263                 if (!with_timeout(h->timeout))
264                         return -IPSET_ERR_TIMEOUT;
265                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
266         }
267
268         if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) {
269                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
270                 if (cadt_flags & IPSET_FLAG_NOMATCH)
271                         flags |= (cadt_flags << 16);
272         }
273
274         with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
275         if (adt == IPSET_TEST ||
276             !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
277               tb[IPSET_ATTR_IP2_TO])) {
278                 data.ip = htonl(ip);
279                 data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1));
280                 ret = adtfn(set, &data, timeout, flags);
281                 return ip_set_eexist(ret, flags) ? 0 : ret;
282         }
283
284         if (tb[IPSET_ATTR_IP_TO]) {
285                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
286                 if (ret)
287                         return ret;
288                 if (ip > ip_to)
289                         swap(ip, ip_to);
290         } else if (tb[IPSET_ATTR_CIDR]) {
291                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
292
293                 if (cidr > 32)
294                         return -IPSET_ERR_INVALID_CIDR;
295                 ip_set_mask_from_to(ip, ip_to, cidr);
296         }
297
298         port_to = port = ntohs(data.port);
299         if (tb[IPSET_ATTR_PORT_TO]) {
300                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
301                 if (port > port_to)
302                         swap(port, port_to);
303         }
304         if (tb[IPSET_ATTR_IP2_TO]) {
305                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
306                 if (ret)
307                         return ret;
308                 if (ip2_from > ip2_to)
309                         swap(ip2_from, ip2_to);
310                 if (ip2_from + UINT_MAX == ip2_to)
311                         return -IPSET_ERR_HASH_RANGE;
312         } else {
313                 ip_set_mask_from_to(ip2_from, ip2_to, data.cidr + 1);
314         }
315
316         if (retried)
317                 ip = h->next.ip;
318         for (; !before(ip_to, ip); ip++) {
319                 data.ip = htonl(ip);
320                 p = retried && ip == h->next.ip ? h->next.port : port;
321                 for (; p <= port_to; p++) {
322                         data.port = htons(p);
323                         ip2 = retried && ip == h->next.ip && p == h->next.port
324                                 ? h->next.ip2 : ip2_from;
325                         while (!after(ip2, ip2_to)) {
326                                 data.ip2 = htonl(ip2);
327                                 ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
328                                                                 &cidr);
329                                 data.cidr = cidr - 1;
330                                 ret = adtfn(set, &data, timeout, flags);
331
332                                 if (ret && !ip_set_eexist(ret, flags))
333                                         return ret;
334                                 else
335                                         ret = 0;
336                                 ip2 = ip2_last + 1;
337                         }
338                 }
339         }
340         return ret;
341 }
342
343 static bool
344 hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
345 {
346         const struct ip_set_hash *x = a->data;
347         const struct ip_set_hash *y = b->data;
348
349         /* Resizing changes htable_bits, so we ignore it */
350         return x->maxelem == y->maxelem &&
351                x->timeout == y->timeout;
352 }
353
354 /* The type variant functions: IPv6 */
355
356 struct hash_ipportnet6_elem {
357         union nf_inet_addr ip;
358         union nf_inet_addr ip2;
359         __be16 port;
360         u8 cidr:7;
361         u8 nomatch:1;
362         u8 proto;
363 };
364
365 struct hash_ipportnet6_telem {
366         union nf_inet_addr ip;
367         union nf_inet_addr ip2;
368         __be16 port;
369         u8 cidr:7;
370         u8 nomatch:1;
371         u8 proto;
372         unsigned long timeout;
373 };
374
375 static inline bool
376 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
377                            const struct hash_ipportnet6_elem *ip2,
378                            u32 *multi)
379 {
380         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
381                ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
382                ip1->cidr == ip2->cidr &&
383                ip1->port == ip2->port &&
384                ip1->proto == ip2->proto;
385 }
386
387 static inline bool
388 hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
389 {
390         return elem->proto == 0;
391 }
392
393 static inline void
394 hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
395                           const struct hash_ipportnet6_elem *src)
396 {
397         memcpy(dst, src, sizeof(*dst));
398 }
399
400 static inline void
401 hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
402 {
403         dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
404 }
405
406 static inline bool
407 hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
408 {
409         return !elem->nomatch;
410 }
411
412 static inline void
413 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
414 {
415         elem->proto = 0;
416 }
417
418 static inline void
419 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
420 {
421         ip->ip6[0] &= ip_set_netmask6(prefix)[0];
422         ip->ip6[1] &= ip_set_netmask6(prefix)[1];
423         ip->ip6[2] &= ip_set_netmask6(prefix)[2];
424         ip->ip6[3] &= ip_set_netmask6(prefix)[3];
425 }
426
427 static inline void
428 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
429 {
430         ip6_netmask(&elem->ip2, cidr);
431         elem->cidr = cidr - 1;
432 }
433
434 static bool
435 hash_ipportnet6_data_list(struct sk_buff *skb,
436                           const struct hash_ipportnet6_elem *data)
437 {
438         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
439
440         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
441             nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
442             nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
443             nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
444             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
445             (flags &&
446              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
447                 goto nla_put_failure;
448         return 0;
449
450 nla_put_failure:
451         return 1;
452 }
453
454 static bool
455 hash_ipportnet6_data_tlist(struct sk_buff *skb,
456                            const struct hash_ipportnet6_elem *data)
457 {
458         const struct hash_ipportnet6_telem *e =
459                 (const struct hash_ipportnet6_telem *)data;
460         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
461
462         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
463             nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
464             nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
465             nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
466             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
467             nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
468                           htonl(ip_set_timeout_get(e->timeout))) ||
469             (flags &&
470              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
471                 goto nla_put_failure;
472         return 0;
473
474 nla_put_failure:
475         return 1;
476 }
477
478 #undef PF
479 #undef HOST_MASK
480
481 #define PF              6
482 #define HOST_MASK       128
483 #include <linux/netfilter/ipset/ip_set_ahash.h>
484
485 static inline void
486 hash_ipportnet6_data_next(struct ip_set_hash *h,
487                           const struct hash_ipportnet6_elem *d)
488 {
489         h->next.port = ntohs(d->port);
490 }
491
492 static int
493 hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
494                      const struct xt_action_param *par,
495                      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
496 {
497         const struct ip_set_hash *h = set->data;
498         ipset_adtfn adtfn = set->variant->adt[adt];
499         struct hash_ipportnet6_elem data = {
500                 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
501         };
502
503         if (adt == IPSET_TEST)
504                 data.cidr = HOST_MASK - 1;
505
506         if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
507                                  &data.port, &data.proto))
508                 return -EINVAL;
509
510         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
511         ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
512         ip6_netmask(&data.ip2, data.cidr + 1);
513
514         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
515 }
516
517 static int
518 hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
519                      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
520 {
521         const struct ip_set_hash *h = set->data;
522         ipset_adtfn adtfn = set->variant->adt[adt];
523         struct hash_ipportnet6_elem data = { .cidr = HOST_MASK - 1 };
524         u32 port, port_to;
525         u32 timeout = h->timeout;
526         bool with_ports = false;
527         u8 cidr;
528         int ret;
529
530         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
531                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
532                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
533                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
534                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
535                      tb[IPSET_ATTR_IP_TO] ||
536                      tb[IPSET_ATTR_CIDR]))
537                 return -IPSET_ERR_PROTOCOL;
538         if (unlikely(tb[IPSET_ATTR_IP_TO]))
539                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
540
541         if (tb[IPSET_ATTR_LINENO])
542                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
543
544         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
545         if (ret)
546                 return ret;
547
548         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
549         if (ret)
550                 return ret;
551
552         if (tb[IPSET_ATTR_CIDR2]) {
553                 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
554                 if (!cidr || cidr > HOST_MASK)
555                         return -IPSET_ERR_INVALID_CIDR;
556                 data.cidr = cidr - 1;
557         }
558
559         ip6_netmask(&data.ip2, data.cidr + 1);
560
561         if (tb[IPSET_ATTR_PORT])
562                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
563         else
564                 return -IPSET_ERR_PROTOCOL;
565
566         if (tb[IPSET_ATTR_PROTO]) {
567                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
568                 with_ports = ip_set_proto_with_ports(data.proto);
569
570                 if (data.proto == 0)
571                         return -IPSET_ERR_INVALID_PROTO;
572         } else
573                 return -IPSET_ERR_MISSING_PROTO;
574
575         if (!(with_ports || data.proto == IPPROTO_ICMPV6))
576                 data.port = 0;
577
578         if (tb[IPSET_ATTR_TIMEOUT]) {
579                 if (!with_timeout(h->timeout))
580                         return -IPSET_ERR_TIMEOUT;
581                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
582         }
583
584         if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) {
585                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
586                 if (cadt_flags & IPSET_FLAG_NOMATCH)
587                         flags |= (cadt_flags << 16);
588         }
589
590         if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
591                 ret = adtfn(set, &data, timeout, flags);
592                 return ip_set_eexist(ret, flags) ? 0 : ret;
593         }
594
595         port = ntohs(data.port);
596         port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
597         if (port > port_to)
598                 swap(port, port_to);
599
600         if (retried)
601                 port = h->next.port;
602         for (; port <= port_to; port++) {
603                 data.port = htons(port);
604                 ret = adtfn(set, &data, timeout, flags);
605
606                 if (ret && !ip_set_eexist(ret, flags))
607                         return ret;
608                 else
609                         ret = 0;
610         }
611         return ret;
612 }
613
614 /* Create hash:ip type of sets */
615
616 static int
617 hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
618 {
619         struct ip_set_hash *h;
620         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
621         u8 hbits;
622         size_t hsize;
623
624         if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
625                 return -IPSET_ERR_INVALID_FAMILY;
626
627         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
628                      !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
629                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
630                 return -IPSET_ERR_PROTOCOL;
631
632         if (tb[IPSET_ATTR_HASHSIZE]) {
633                 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
634                 if (hashsize < IPSET_MIMINAL_HASHSIZE)
635                         hashsize = IPSET_MIMINAL_HASHSIZE;
636         }
637
638         if (tb[IPSET_ATTR_MAXELEM])
639                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
640
641         h = kzalloc(sizeof(*h)
642                     + sizeof(struct ip_set_hash_nets)
643                       * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
644         if (!h)
645                 return -ENOMEM;
646
647         h->maxelem = maxelem;
648         get_random_bytes(&h->initval, sizeof(h->initval));
649         h->timeout = IPSET_NO_TIMEOUT;
650
651         hbits = htable_bits(hashsize);
652         hsize = htable_size(hbits);
653         if (hsize == 0) {
654                 kfree(h);
655                 return -ENOMEM;
656         }
657         h->table = ip_set_alloc(hsize);
658         if (!h->table) {
659                 kfree(h);
660                 return -ENOMEM;
661         }
662         h->table->htable_bits = hbits;
663
664         set->data = h;
665
666         if (tb[IPSET_ATTR_TIMEOUT]) {
667                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
668
669                 set->variant = set->family == NFPROTO_IPV4
670                         ? &hash_ipportnet4_tvariant
671                         : &hash_ipportnet6_tvariant;
672
673                 if (set->family == NFPROTO_IPV4)
674                         hash_ipportnet4_gc_init(set);
675                 else
676                         hash_ipportnet6_gc_init(set);
677         } else {
678                 set->variant = set->family == NFPROTO_IPV4
679                         ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
680         }
681
682         pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
683                  set->name, jhash_size(h->table->htable_bits),
684                  h->table->htable_bits, h->maxelem, set->data, h->table);
685
686         return 0;
687 }
688
689 static struct ip_set_type hash_ipportnet_type __read_mostly = {
690         .name           = "hash:ip,port,net",
691         .protocol       = IPSET_PROTOCOL,
692         .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
693         .dimension      = IPSET_DIM_THREE,
694         .family         = NFPROTO_UNSPEC,
695         .revision_min   = 0,
696         /*                1        SCTP and UDPLITE support added */
697         /*                2        Range as input support for IPv4 added */
698         .revision_max   = 3,    /* nomatch flag support added */
699         .create         = hash_ipportnet_create,
700         .create_policy  = {
701                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
702                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
703                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
704                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
705                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
706         },
707         .adt_policy     = {
708                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
709                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
710                 [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
711                 [IPSET_ATTR_IP2_TO]     = { .type = NLA_NESTED },
712                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
713                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
714                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
715                 [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
716                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
717                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
718                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
719                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
720         },
721         .me             = THIS_MODULE,
722 };
723
724 static int __init
725 hash_ipportnet_init(void)
726 {
727         return ip_set_type_register(&hash_ipportnet_type);
728 }
729
730 static void __exit
731 hash_ipportnet_fini(void)
732 {
733         ip_set_type_unregister(&hash_ipportnet_type);
734 }
735
736 module_init(hash_ipportnet_init);
737 module_exit(hash_ipportnet_fini);