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