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