1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
8 /* Kernel module implementing an IP set type: the hash:ip,port,net type */
10 #include <linux/jhash.h>
11 #include <linux/module.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
15 #include <linux/random.h>
18 #include <net/netlink.h>
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>
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");
33 /* Type specific function prefix */
34 #define TYPE hash_ipportnet
37 hash_ipportnet_same_set(const struct ip_set
*a
, const struct ip_set
*b
);
39 #define hash_ipportnet4_same_set hash_ipportnet_same_set
40 #define hash_ipportnet6_same_set hash_ipportnet_same_set
42 /* The type variant functions: IPv4 */
44 /* Member elements without timeout */
45 struct hash_ipportnet4_elem
{
53 /* Member elements with timeout support */
54 struct hash_ipportnet4_telem
{
60 unsigned long timeout
;
64 hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem
*ip1
,
65 const struct hash_ipportnet4_elem
*ip2
,
68 return ip1
->ip
== ip2
->ip
&&
69 ip1
->ip2
== ip2
->ip2
&&
70 ip1
->cidr
== ip2
->cidr
&&
71 ip1
->port
== ip2
->port
&&
72 ip1
->proto
== ip2
->proto
;
76 hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem
*elem
)
78 return elem
->proto
== 0;
82 hash_ipportnet4_data_copy(struct hash_ipportnet4_elem
*dst
,
83 const struct hash_ipportnet4_elem
*src
)
85 memcpy(dst
, src
, sizeof(*dst
));
89 hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem
*elem
, u8 cidr
)
91 elem
->ip2
&= ip_set_netmask(cidr
);
96 hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem
*elem
)
102 hash_ipportnet4_data_list(struct sk_buff
*skb
,
103 const struct hash_ipportnet4_elem
*data
)
105 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
, data
->ip
);
106 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP2
, data
->ip2
);
107 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
, data
->port
);
108 NLA_PUT_U8(skb
, IPSET_ATTR_CIDR2
, data
->cidr
);
109 NLA_PUT_U8(skb
, IPSET_ATTR_PROTO
, data
->proto
);
117 hash_ipportnet4_data_tlist(struct sk_buff
*skb
,
118 const struct hash_ipportnet4_elem
*data
)
120 const struct hash_ipportnet4_telem
*tdata
=
121 (const struct hash_ipportnet4_telem
*)data
;
123 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP
, tdata
->ip
);
124 NLA_PUT_IPADDR4(skb
, IPSET_ATTR_IP2
, tdata
->ip2
);
125 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
, tdata
->port
);
126 NLA_PUT_U8(skb
, IPSET_ATTR_CIDR2
, data
->cidr
);
127 NLA_PUT_U8(skb
, IPSET_ATTR_PROTO
, data
->proto
);
128 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
,
129 htonl(ip_set_timeout_get(tdata
->timeout
)));
137 #define IP_SET_HASH_WITH_PROTO
138 #define IP_SET_HASH_WITH_NETS
142 #include <linux/netfilter/ipset/ip_set_ahash.h>
145 hash_ipportnet4_data_next(struct ip_set_hash
*h
,
146 const struct hash_ipportnet4_elem
*d
)
148 h
->next
.ip
= ntohl(d
->ip
);
149 h
->next
.port
= ntohs(d
->port
);
150 h
->next
.ip2
= ntohl(d
->ip2
);
154 hash_ipportnet4_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
155 const struct xt_action_param
*par
,
156 enum ipset_adt adt
, const struct ip_set_adt_opt
*opt
)
158 const struct ip_set_hash
*h
= set
->data
;
159 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
160 struct hash_ipportnet4_elem data
= {
161 .cidr
= h
->nets
[0].cidr
? h
->nets
[0].cidr
: HOST_MASK
166 if (adt
== IPSET_TEST
)
167 data
.cidr
= HOST_MASK
;
169 if (!ip_set_get_ip4_port(skb
, opt
->flags
& IPSET_DIM_TWO_SRC
,
170 &data
.port
, &data
.proto
))
173 ip4addrptr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
, &data
.ip
);
174 ip4addrptr(skb
, opt
->flags
& IPSET_DIM_THREE_SRC
, &data
.ip2
);
175 data
.ip2
&= ip_set_netmask(data
.cidr
);
177 return adtfn(set
, &data
, opt_timeout(opt
, h
), opt
->cmdflags
);
181 hash_ipportnet4_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
182 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
184 const struct ip_set_hash
*h
= set
->data
;
185 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
186 struct hash_ipportnet4_elem data
= { .cidr
= HOST_MASK
};
187 u32 ip
, ip_to
, p
= 0, port
, port_to
;
188 u32 ip2_from
= 0, ip2_to
, ip2_last
, ip2
;
189 u32 timeout
= h
->timeout
;
190 bool with_ports
= false;
193 if (unlikely(!tb
[IPSET_ATTR_IP
] || !tb
[IPSET_ATTR_IP2
] ||
194 !ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
195 !ip_set_optattr_netorder(tb
, IPSET_ATTR_PORT_TO
) ||
196 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
197 return -IPSET_ERR_PROTOCOL
;
199 if (tb
[IPSET_ATTR_LINENO
])
200 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
202 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &ip
);
206 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP2
], &ip2_from
);
210 if (tb
[IPSET_ATTR_CIDR2
]) {
211 data
.cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR2
]);
213 return -IPSET_ERR_INVALID_CIDR
;
216 if (tb
[IPSET_ATTR_PORT
])
217 data
.port
= nla_get_be16(tb
[IPSET_ATTR_PORT
]);
219 return -IPSET_ERR_PROTOCOL
;
221 if (tb
[IPSET_ATTR_PROTO
]) {
222 data
.proto
= nla_get_u8(tb
[IPSET_ATTR_PROTO
]);
223 with_ports
= ip_set_proto_with_ports(data
.proto
);
226 return -IPSET_ERR_INVALID_PROTO
;
228 return -IPSET_ERR_MISSING_PROTO
;
230 if (!(with_ports
|| data
.proto
== IPPROTO_ICMP
))
233 if (tb
[IPSET_ATTR_TIMEOUT
]) {
234 if (!with_timeout(h
->timeout
))
235 return -IPSET_ERR_TIMEOUT
;
236 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
239 with_ports
= with_ports
&& tb
[IPSET_ATTR_PORT_TO
];
240 if (adt
== IPSET_TEST
||
241 !(tb
[IPSET_ATTR_CIDR
] || tb
[IPSET_ATTR_IP_TO
] || with_ports
||
242 tb
[IPSET_ATTR_IP2_TO
])) {
244 data
.ip2
= htonl(ip2_from
& ip_set_hostmask(data
.cidr
));
245 ret
= adtfn(set
, &data
, timeout
, flags
);
246 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
249 if (tb
[IPSET_ATTR_IP_TO
]) {
250 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &ip_to
);
255 } else if (tb
[IPSET_ATTR_CIDR
]) {
256 u8 cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
259 return -IPSET_ERR_INVALID_CIDR
;
260 ip_set_mask_from_to(ip
, ip_to
, cidr
);
263 port_to
= port
= ntohs(data
.port
);
264 if (tb
[IPSET_ATTR_PORT_TO
]) {
265 port_to
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
269 if (tb
[IPSET_ATTR_IP2_TO
]) {
270 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP2_TO
], &ip2_to
);
273 if (ip2_from
> ip2_to
)
274 swap(ip2_from
, ip2_to
);
275 if (ip2_from
+ UINT_MAX
== ip2_to
)
276 return -IPSET_ERR_HASH_RANGE
;
278 ip_set_mask_from_to(ip2_from
, ip2_to
, data
.cidr
);
283 for (; !before(ip_to
, ip
); ip
++) {
285 p
= retried
&& ip
== h
->next
.ip
? h
->next
.port
: port
;
286 for (; p
<= port_to
; p
++) {
287 data
.port
= htons(p
);
288 ip2
= retried
&& ip
== h
->next
.ip
&& p
== h
->next
.port
289 ? h
->next
.ip2
: ip2_from
;
290 while (!after(ip2
, ip2_to
)) {
291 data
.ip2
= htonl(ip2
);
292 ip2_last
= ip_set_range_to_cidr(ip2
, ip2_to
,
294 ret
= adtfn(set
, &data
, timeout
, flags
);
296 if (ret
&& !ip_set_eexist(ret
, flags
))
308 hash_ipportnet_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
310 const struct ip_set_hash
*x
= a
->data
;
311 const struct ip_set_hash
*y
= b
->data
;
313 /* Resizing changes htable_bits, so we ignore it */
314 return x
->maxelem
== y
->maxelem
&&
315 x
->timeout
== y
->timeout
;
318 /* The type variant functions: IPv6 */
320 struct hash_ipportnet6_elem
{
321 union nf_inet_addr ip
;
322 union nf_inet_addr ip2
;
328 struct hash_ipportnet6_telem
{
329 union nf_inet_addr ip
;
330 union nf_inet_addr ip2
;
334 unsigned long timeout
;
338 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem
*ip1
,
339 const struct hash_ipportnet6_elem
*ip2
,
342 return ipv6_addr_cmp(&ip1
->ip
.in6
, &ip2
->ip
.in6
) == 0 &&
343 ipv6_addr_cmp(&ip1
->ip2
.in6
, &ip2
->ip2
.in6
) == 0 &&
344 ip1
->cidr
== ip2
->cidr
&&
345 ip1
->port
== ip2
->port
&&
346 ip1
->proto
== ip2
->proto
;
350 hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem
*elem
)
352 return elem
->proto
== 0;
356 hash_ipportnet6_data_copy(struct hash_ipportnet6_elem
*dst
,
357 const struct hash_ipportnet6_elem
*src
)
359 memcpy(dst
, src
, sizeof(*dst
));
363 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem
*elem
)
369 ip6_netmask(union nf_inet_addr
*ip
, u8 prefix
)
371 ip
->ip6
[0] &= ip_set_netmask6(prefix
)[0];
372 ip
->ip6
[1] &= ip_set_netmask6(prefix
)[1];
373 ip
->ip6
[2] &= ip_set_netmask6(prefix
)[2];
374 ip
->ip6
[3] &= ip_set_netmask6(prefix
)[3];
378 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem
*elem
, u8 cidr
)
380 ip6_netmask(&elem
->ip2
, cidr
);
385 hash_ipportnet6_data_list(struct sk_buff
*skb
,
386 const struct hash_ipportnet6_elem
*data
)
388 NLA_PUT_IPADDR6(skb
, IPSET_ATTR_IP
, &data
->ip
);
389 NLA_PUT_IPADDR6(skb
, IPSET_ATTR_IP2
, &data
->ip2
);
390 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
, data
->port
);
391 NLA_PUT_U8(skb
, IPSET_ATTR_CIDR2
, data
->cidr
);
392 NLA_PUT_U8(skb
, IPSET_ATTR_PROTO
, data
->proto
);
400 hash_ipportnet6_data_tlist(struct sk_buff
*skb
,
401 const struct hash_ipportnet6_elem
*data
)
403 const struct hash_ipportnet6_telem
*e
=
404 (const struct hash_ipportnet6_telem
*)data
;
406 NLA_PUT_IPADDR6(skb
, IPSET_ATTR_IP
, &e
->ip
);
407 NLA_PUT_IPADDR6(skb
, IPSET_ATTR_IP2
, &data
->ip2
);
408 NLA_PUT_NET16(skb
, IPSET_ATTR_PORT
, data
->port
);
409 NLA_PUT_U8(skb
, IPSET_ATTR_CIDR2
, data
->cidr
);
410 NLA_PUT_U8(skb
, IPSET_ATTR_PROTO
, data
->proto
);
411 NLA_PUT_NET32(skb
, IPSET_ATTR_TIMEOUT
,
412 htonl(ip_set_timeout_get(e
->timeout
)));
423 #define HOST_MASK 128
424 #include <linux/netfilter/ipset/ip_set_ahash.h>
427 hash_ipportnet6_data_next(struct ip_set_hash
*h
,
428 const struct hash_ipportnet6_elem
*d
)
430 h
->next
.port
= ntohs(d
->port
);
434 hash_ipportnet6_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
435 const struct xt_action_param
*par
,
436 enum ipset_adt adt
, const struct ip_set_adt_opt
*opt
)
438 const struct ip_set_hash
*h
= set
->data
;
439 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
440 struct hash_ipportnet6_elem data
= {
441 .cidr
= h
->nets
[0].cidr
? h
->nets
[0].cidr
: HOST_MASK
446 if (adt
== IPSET_TEST
)
447 data
.cidr
= HOST_MASK
;
449 if (!ip_set_get_ip6_port(skb
, opt
->flags
& IPSET_DIM_TWO_SRC
,
450 &data
.port
, &data
.proto
))
453 ip6addrptr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
, &data
.ip
.in6
);
454 ip6addrptr(skb
, opt
->flags
& IPSET_DIM_THREE_SRC
, &data
.ip2
.in6
);
455 ip6_netmask(&data
.ip2
, data
.cidr
);
457 return adtfn(set
, &data
, opt_timeout(opt
, h
), opt
->cmdflags
);
461 hash_ipportnet6_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
462 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
464 const struct ip_set_hash
*h
= set
->data
;
465 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
466 struct hash_ipportnet6_elem data
= { .cidr
= HOST_MASK
};
468 u32 timeout
= h
->timeout
;
469 bool with_ports
= false;
472 if (unlikely(!tb
[IPSET_ATTR_IP
] || !tb
[IPSET_ATTR_IP2
] ||
473 !ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
474 !ip_set_optattr_netorder(tb
, IPSET_ATTR_PORT_TO
) ||
475 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
476 tb
[IPSET_ATTR_IP_TO
] ||
477 tb
[IPSET_ATTR_CIDR
]))
478 return -IPSET_ERR_PROTOCOL
;
479 if (unlikely(tb
[IPSET_ATTR_IP_TO
]))
480 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED
;
482 if (tb
[IPSET_ATTR_LINENO
])
483 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
485 ret
= ip_set_get_ipaddr6(tb
[IPSET_ATTR_IP
], &data
.ip
);
489 ret
= ip_set_get_ipaddr6(tb
[IPSET_ATTR_IP2
], &data
.ip2
);
493 if (tb
[IPSET_ATTR_CIDR2
])
494 data
.cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR2
]);
497 return -IPSET_ERR_INVALID_CIDR
;
499 ip6_netmask(&data
.ip2
, data
.cidr
);
501 if (tb
[IPSET_ATTR_PORT
])
502 data
.port
= nla_get_be16(tb
[IPSET_ATTR_PORT
]);
504 return -IPSET_ERR_PROTOCOL
;
506 if (tb
[IPSET_ATTR_PROTO
]) {
507 data
.proto
= nla_get_u8(tb
[IPSET_ATTR_PROTO
]);
508 with_ports
= ip_set_proto_with_ports(data
.proto
);
511 return -IPSET_ERR_INVALID_PROTO
;
513 return -IPSET_ERR_MISSING_PROTO
;
515 if (!(with_ports
|| data
.proto
== IPPROTO_ICMPV6
))
518 if (tb
[IPSET_ATTR_TIMEOUT
]) {
519 if (!with_timeout(h
->timeout
))
520 return -IPSET_ERR_TIMEOUT
;
521 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
524 if (adt
== IPSET_TEST
|| !with_ports
|| !tb
[IPSET_ATTR_PORT_TO
]) {
525 ret
= adtfn(set
, &data
, timeout
, flags
);
526 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
529 port
= ntohs(data
.port
);
530 port_to
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
536 for (; port
<= port_to
; port
++) {
537 data
.port
= htons(port
);
538 ret
= adtfn(set
, &data
, timeout
, flags
);
540 if (ret
&& !ip_set_eexist(ret
, flags
))
548 /* Create hash:ip type of sets */
551 hash_ipportnet_create(struct ip_set
*set
, struct nlattr
*tb
[], u32 flags
)
553 struct ip_set_hash
*h
;
554 u32 hashsize
= IPSET_DEFAULT_HASHSIZE
, maxelem
= IPSET_DEFAULT_MAXELEM
;
557 if (!(set
->family
== AF_INET
|| set
->family
== AF_INET6
))
558 return -IPSET_ERR_INVALID_FAMILY
;
560 if (unlikely(!ip_set_optattr_netorder(tb
, IPSET_ATTR_HASHSIZE
) ||
561 !ip_set_optattr_netorder(tb
, IPSET_ATTR_MAXELEM
) ||
562 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
563 return -IPSET_ERR_PROTOCOL
;
565 if (tb
[IPSET_ATTR_HASHSIZE
]) {
566 hashsize
= ip_set_get_h32(tb
[IPSET_ATTR_HASHSIZE
]);
567 if (hashsize
< IPSET_MIMINAL_HASHSIZE
)
568 hashsize
= IPSET_MIMINAL_HASHSIZE
;
571 if (tb
[IPSET_ATTR_MAXELEM
])
572 maxelem
= ip_set_get_h32(tb
[IPSET_ATTR_MAXELEM
]);
574 h
= kzalloc(sizeof(*h
)
575 + sizeof(struct ip_set_hash_nets
)
576 * (set
->family
== AF_INET
? 32 : 128), GFP_KERNEL
);
580 h
->maxelem
= maxelem
;
581 get_random_bytes(&h
->initval
, sizeof(h
->initval
));
582 h
->timeout
= IPSET_NO_TIMEOUT
;
584 hbits
= htable_bits(hashsize
);
585 h
->table
= ip_set_alloc(
586 sizeof(struct htable
)
587 + jhash_size(hbits
) * sizeof(struct hbucket
));
592 h
->table
->htable_bits
= hbits
;
596 if (tb
[IPSET_ATTR_TIMEOUT
]) {
597 h
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
599 set
->variant
= set
->family
== AF_INET
600 ? &hash_ipportnet4_tvariant
601 : &hash_ipportnet6_tvariant
;
603 if (set
->family
== AF_INET
)
604 hash_ipportnet4_gc_init(set
);
606 hash_ipportnet6_gc_init(set
);
608 set
->variant
= set
->family
== AF_INET
609 ? &hash_ipportnet4_variant
: &hash_ipportnet6_variant
;
612 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
613 set
->name
, jhash_size(h
->table
->htable_bits
),
614 h
->table
->htable_bits
, h
->maxelem
, set
->data
, h
->table
);
619 static struct ip_set_type hash_ipportnet_type __read_mostly
= {
620 .name
= "hash:ip,port,net",
621 .protocol
= IPSET_PROTOCOL
,
622 .features
= IPSET_TYPE_IP
| IPSET_TYPE_PORT
| IPSET_TYPE_IP2
,
623 .dimension
= IPSET_DIM_THREE
,
626 /* 1 SCTP and UDPLITE support added */
627 .revision_max
= 2, /* Range as input support for IPv4 added */
628 .create
= hash_ipportnet_create
,
630 [IPSET_ATTR_HASHSIZE
] = { .type
= NLA_U32
},
631 [IPSET_ATTR_MAXELEM
] = { .type
= NLA_U32
},
632 [IPSET_ATTR_PROBES
] = { .type
= NLA_U8
},
633 [IPSET_ATTR_RESIZE
] = { .type
= NLA_U8
},
634 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
637 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
638 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
639 [IPSET_ATTR_IP2
] = { .type
= NLA_NESTED
},
640 [IPSET_ATTR_IP2_TO
] = { .type
= NLA_NESTED
},
641 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
642 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
643 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
644 [IPSET_ATTR_CIDR2
] = { .type
= NLA_U8
},
645 [IPSET_ATTR_PROTO
] = { .type
= NLA_U8
},
646 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
647 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
653 hash_ipportnet_init(void)
655 return ip_set_type_register(&hash_ipportnet_type
);
659 hash_ipportnet_fini(void)
661 ip_set_type_unregister(&hash_ipportnet_type
);
664 module_init(hash_ipportnet_init
);
665 module_exit(hash_ipportnet_fini
);