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