]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/netfilter/ipset/ip_set_hash_ipportnet.c
605ef3bf94ef1ffffe39abd6dcd59fd5d0c9bd2f
[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 /* Member elements without timeout */
45 struct hash_ipportnet4_elem {
46         __be32 ip;
47         __be32 ip2;
48         __be16 port;
49         u8 cidr;
50         u8 proto;
51 };
52
53 /* Member elements with timeout support */
54 struct hash_ipportnet4_telem {
55         __be32 ip;
56         __be32 ip2;
57         __be16 port;
58         u8 cidr;
59         u8 proto;
60         unsigned long timeout;
61 };
62
63 static inline bool
64 hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
65                            const struct hash_ipportnet4_elem *ip2)
66 {
67         return ip1->ip == ip2->ip &&
68                ip1->ip2 == ip2->ip2 &&
69                ip1->cidr == ip2->cidr &&
70                ip1->port == ip2->port &&
71                ip1->proto == ip2->proto;
72 }
73
74 static inline bool
75 hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
76 {
77         return elem->proto == 0;
78 }
79
80 static inline void
81 hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
82                           const struct hash_ipportnet4_elem *src)
83 {
84         memcpy(dst, src, sizeof(*dst));
85 }
86
87 static inline void
88 hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
89 {
90         elem->ip2 &= ip_set_netmask(cidr);
91         elem->cidr = cidr;
92 }
93
94 static inline void
95 hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
96 {
97         elem->proto = 0;
98 }
99
100 static bool
101 hash_ipportnet4_data_list(struct sk_buff *skb,
102                           const struct hash_ipportnet4_elem *data)
103 {
104         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
105         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
106         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
107         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
108         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
109         return 0;
110
111 nla_put_failure:
112         return 1;
113 }
114
115 static bool
116 hash_ipportnet4_data_tlist(struct sk_buff *skb,
117                            const struct hash_ipportnet4_elem *data)
118 {
119         const struct hash_ipportnet4_telem *tdata =
120                 (const struct hash_ipportnet4_telem *)data;
121
122         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
123         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
124         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
125         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
126         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
127         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
128                       htonl(ip_set_timeout_get(tdata->timeout)));
129
130         return 0;
131
132 nla_put_failure:
133         return 1;
134 }
135
136 #define IP_SET_HASH_WITH_PROTO
137 #define IP_SET_HASH_WITH_NETS
138
139 #define PF              4
140 #define HOST_MASK       32
141 #include <linux/netfilter/ipset/ip_set_ahash.h>
142
143 static inline void
144 hash_ipportnet4_data_next(struct ip_set_hash *h,
145                           const struct hash_ipportnet4_elem *d)
146 {
147         h->next.ip = ntohl(d->ip);
148         h->next.port = ntohs(d->port);
149 }
150
151 static int
152 hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
153                      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
154 {
155         const struct ip_set_hash *h = set->data;
156         ipset_adtfn adtfn = set->variant->adt[adt];
157         struct hash_ipportnet4_elem data =
158                 { .cidr = h->nets[0].cidr || HOST_MASK };
159
160         if (data.cidr == 0)
161                 return -EINVAL;
162         if (adt == IPSET_TEST)
163                 data.cidr = HOST_MASK;
164
165         if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
166                                  &data.port, &data.proto))
167                 return -EINVAL;
168
169         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
170         ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
171         data.ip2 &= ip_set_netmask(data.cidr);
172
173         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
174 }
175
176 static int
177 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
178                      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
179 {
180         const struct ip_set_hash *h = set->data;
181         ipset_adtfn adtfn = set->variant->adt[adt];
182         struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
183         u32 ip, ip_to, p = 0, port, port_to;
184         u32 timeout = h->timeout;
185         bool with_ports = false;
186         int ret;
187
188         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
189                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
190                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
191                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
192                 return -IPSET_ERR_PROTOCOL;
193
194         if (tb[IPSET_ATTR_LINENO])
195                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
196
197         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
198         if (ret)
199                 return ret;
200
201         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
202         if (ret)
203                 return ret;
204
205         if (tb[IPSET_ATTR_CIDR2])
206                 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
207
208         if (!data.cidr)
209                 return -IPSET_ERR_INVALID_CIDR;
210
211         data.ip2 &= ip_set_netmask(data.cidr);
212
213         if (tb[IPSET_ATTR_PORT])
214                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
215         else
216                 return -IPSET_ERR_PROTOCOL;
217
218         if (tb[IPSET_ATTR_PROTO]) {
219                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
220                 with_ports = ip_set_proto_with_ports(data.proto);
221
222                 if (data.proto == 0)
223                         return -IPSET_ERR_INVALID_PROTO;
224         } else
225                 return -IPSET_ERR_MISSING_PROTO;
226
227         if (!(with_ports || data.proto == IPPROTO_ICMP))
228                 data.port = 0;
229
230         if (tb[IPSET_ATTR_TIMEOUT]) {
231                 if (!with_timeout(h->timeout))
232                         return -IPSET_ERR_TIMEOUT;
233                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
234         }
235
236         if (adt == IPSET_TEST ||
237             !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
238               tb[IPSET_ATTR_PORT_TO])) {
239                 ret = adtfn(set, &data, timeout, flags);
240                 return ip_set_eexist(ret, flags) ? 0 : ret;
241         }
242
243         ip = ntohl(data.ip);
244         if (tb[IPSET_ATTR_IP_TO]) {
245                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
246                 if (ret)
247                         return ret;
248                 if (ip > ip_to)
249                         swap(ip, ip_to);
250         } else if (tb[IPSET_ATTR_CIDR]) {
251                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
252
253                 if (cidr > 32)
254                         return -IPSET_ERR_INVALID_CIDR;
255                 ip &= ip_set_hostmask(cidr);
256                 ip_to = ip | ~ip_set_hostmask(cidr);
257         } else
258                 ip_to = ip;
259
260         port_to = port = ntohs(data.port);
261         if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
262                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
263                 if (port > port_to)
264                         swap(port, port_to);
265         }
266
267         if (retried)
268                 ip = h->next.ip;
269         for (; !before(ip_to, ip); ip++) {
270                 p = retried && ip == h->next.ip ? h->next.port : port;
271                 for (; p <= port_to; p++) {
272                         data.ip = htonl(ip);
273                         data.port = htons(p);
274                         ret = adtfn(set, &data, timeout, flags);
275
276                         if (ret && !ip_set_eexist(ret, flags))
277                                 return ret;
278                         else
279                                 ret = 0;
280                 }
281         }
282         return ret;
283 }
284
285 static bool
286 hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
287 {
288         const struct ip_set_hash *x = a->data;
289         const struct ip_set_hash *y = b->data;
290
291         /* Resizing changes htable_bits, so we ignore it */
292         return x->maxelem == y->maxelem &&
293                x->timeout == y->timeout;
294 }
295
296 /* The type variant functions: IPv6 */
297
298 struct hash_ipportnet6_elem {
299         union nf_inet_addr ip;
300         union nf_inet_addr ip2;
301         __be16 port;
302         u8 cidr;
303         u8 proto;
304 };
305
306 struct hash_ipportnet6_telem {
307         union nf_inet_addr ip;
308         union nf_inet_addr ip2;
309         __be16 port;
310         u8 cidr;
311         u8 proto;
312         unsigned long timeout;
313 };
314
315 static inline bool
316 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
317                            const struct hash_ipportnet6_elem *ip2)
318 {
319         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
320                ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
321                ip1->cidr == ip2->cidr &&
322                ip1->port == ip2->port &&
323                ip1->proto == ip2->proto;
324 }
325
326 static inline bool
327 hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
328 {
329         return elem->proto == 0;
330 }
331
332 static inline void
333 hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
334                           const struct hash_ipportnet6_elem *src)
335 {
336         memcpy(dst, src, sizeof(*dst));
337 }
338
339 static inline void
340 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
341 {
342         elem->proto = 0;
343 }
344
345 static inline void
346 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
347 {
348         ip->ip6[0] &= ip_set_netmask6(prefix)[0];
349         ip->ip6[1] &= ip_set_netmask6(prefix)[1];
350         ip->ip6[2] &= ip_set_netmask6(prefix)[2];
351         ip->ip6[3] &= ip_set_netmask6(prefix)[3];
352 }
353
354 static inline void
355 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
356 {
357         ip6_netmask(&elem->ip2, cidr);
358         elem->cidr = cidr;
359 }
360
361 static bool
362 hash_ipportnet6_data_list(struct sk_buff *skb,
363                           const struct hash_ipportnet6_elem *data)
364 {
365         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
366         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
367         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
368         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
369         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
370         return 0;
371
372 nla_put_failure:
373         return 1;
374 }
375
376 static bool
377 hash_ipportnet6_data_tlist(struct sk_buff *skb,
378                            const struct hash_ipportnet6_elem *data)
379 {
380         const struct hash_ipportnet6_telem *e =
381                 (const struct hash_ipportnet6_telem *)data;
382
383         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
384         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
385         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
386         NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
387         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
388         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
389                       htonl(ip_set_timeout_get(e->timeout)));
390         return 0;
391
392 nla_put_failure:
393         return 1;
394 }
395
396 #undef PF
397 #undef HOST_MASK
398
399 #define PF              6
400 #define HOST_MASK       128
401 #include <linux/netfilter/ipset/ip_set_ahash.h>
402
403 static inline void
404 hash_ipportnet6_data_next(struct ip_set_hash *h,
405                           const struct hash_ipportnet6_elem *d)
406 {
407         h->next.port = ntohs(d->port);
408 }
409
410 static int
411 hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
412                      enum ipset_adt adt, const struct ip_set_adt_opt *opt)
413 {
414         const struct ip_set_hash *h = set->data;
415         ipset_adtfn adtfn = set->variant->adt[adt];
416         struct hash_ipportnet6_elem data =
417                 { .cidr = h->nets[0].cidr || HOST_MASK };
418
419         if (data.cidr == 0)
420                 return -EINVAL;
421         if (adt == IPSET_TEST)
422                 data.cidr = HOST_MASK;
423
424         if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
425                                  &data.port, &data.proto))
426                 return -EINVAL;
427
428         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
429         ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
430         ip6_netmask(&data.ip2, data.cidr);
431
432         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
433 }
434
435 static int
436 hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
437                      enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
438 {
439         const struct ip_set_hash *h = set->data;
440         ipset_adtfn adtfn = set->variant->adt[adt];
441         struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
442         u32 port, port_to;
443         u32 timeout = h->timeout;
444         bool with_ports = false;
445         int ret;
446
447         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
448                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
449                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
450                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
451                      tb[IPSET_ATTR_IP_TO] ||
452                      tb[IPSET_ATTR_CIDR]))
453                 return -IPSET_ERR_PROTOCOL;
454
455         if (tb[IPSET_ATTR_LINENO])
456                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
457
458         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
459         if (ret)
460                 return ret;
461
462         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
463         if (ret)
464                 return ret;
465
466         if (tb[IPSET_ATTR_CIDR2])
467                 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
468
469         if (!data.cidr)
470                 return -IPSET_ERR_INVALID_CIDR;
471
472         ip6_netmask(&data.ip2, data.cidr);
473
474         if (tb[IPSET_ATTR_PORT])
475                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
476         else
477                 return -IPSET_ERR_PROTOCOL;
478
479         if (tb[IPSET_ATTR_PROTO]) {
480                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
481                 with_ports = ip_set_proto_with_ports(data.proto);
482
483                 if (data.proto == 0)
484                         return -IPSET_ERR_INVALID_PROTO;
485         } else
486                 return -IPSET_ERR_MISSING_PROTO;
487
488         if (!(with_ports || data.proto == IPPROTO_ICMPV6))
489                 data.port = 0;
490
491         if (tb[IPSET_ATTR_TIMEOUT]) {
492                 if (!with_timeout(h->timeout))
493                         return -IPSET_ERR_TIMEOUT;
494                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
495         }
496
497         if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
498                 ret = adtfn(set, &data, timeout, flags);
499                 return ip_set_eexist(ret, flags) ? 0 : ret;
500         }
501
502         port = ntohs(data.port);
503         port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
504         if (port > port_to)
505                 swap(port, port_to);
506
507         if (retried)
508                 port = h->next.port;
509         for (; port <= port_to; port++) {
510                 data.port = htons(port);
511                 ret = adtfn(set, &data, timeout, flags);
512
513                 if (ret && !ip_set_eexist(ret, flags))
514                         return ret;
515                 else
516                         ret = 0;
517         }
518         return ret;
519 }
520
521 /* Create hash:ip type of sets */
522
523 static int
524 hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
525 {
526         struct ip_set_hash *h;
527         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
528         u8 hbits;
529
530         if (!(set->family == AF_INET || set->family == AF_INET6))
531                 return -IPSET_ERR_INVALID_FAMILY;
532
533         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
534                      !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
535                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
536                 return -IPSET_ERR_PROTOCOL;
537
538         if (tb[IPSET_ATTR_HASHSIZE]) {
539                 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
540                 if (hashsize < IPSET_MIMINAL_HASHSIZE)
541                         hashsize = IPSET_MIMINAL_HASHSIZE;
542         }
543
544         if (tb[IPSET_ATTR_MAXELEM])
545                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
546
547         h = kzalloc(sizeof(*h)
548                     + sizeof(struct ip_set_hash_nets)
549                       * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
550         if (!h)
551                 return -ENOMEM;
552
553         h->maxelem = maxelem;
554         get_random_bytes(&h->initval, sizeof(h->initval));
555         h->timeout = IPSET_NO_TIMEOUT;
556
557         hbits = htable_bits(hashsize);
558         h->table = ip_set_alloc(
559                         sizeof(struct htable)
560                         + jhash_size(hbits) * sizeof(struct hbucket));
561         if (!h->table) {
562                 kfree(h);
563                 return -ENOMEM;
564         }
565         h->table->htable_bits = hbits;
566
567         set->data = h;
568
569         if (tb[IPSET_ATTR_TIMEOUT]) {
570                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
571
572                 set->variant = set->family == AF_INET
573                         ? &hash_ipportnet4_tvariant
574                         : &hash_ipportnet6_tvariant;
575
576                 if (set->family == AF_INET)
577                         hash_ipportnet4_gc_init(set);
578                 else
579                         hash_ipportnet6_gc_init(set);
580         } else {
581                 set->variant = set->family == AF_INET
582                         ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
583         }
584
585         pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
586                  set->name, jhash_size(h->table->htable_bits),
587                  h->table->htable_bits, h->maxelem, set->data, h->table);
588
589         return 0;
590 }
591
592 static struct ip_set_type hash_ipportnet_type __read_mostly = {
593         .name           = "hash:ip,port,net",
594         .protocol       = IPSET_PROTOCOL,
595         .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
596         .dimension      = IPSET_DIM_THREE,
597         .family         = AF_UNSPEC,
598         .revision       = 1,
599         .create         = hash_ipportnet_create,
600         .create_policy  = {
601                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
602                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
603                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
604                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
605                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
606         },
607         .adt_policy     = {
608                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
609                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
610                 [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
611                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
612                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
613                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
614                 [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
615                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
616                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
617                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
618         },
619         .me             = THIS_MODULE,
620 };
621
622 static int __init
623 hash_ipportnet_init(void)
624 {
625         return ip_set_type_register(&hash_ipportnet_type);
626 }
627
628 static void __exit
629 hash_ipportnet_fini(void)
630 {
631         ip_set_type_unregister(&hash_ipportnet_type);
632 }
633
634 module_init(hash_ipportnet_init);
635 module_exit(hash_ipportnet_fini);