1 /* Copyright (C) 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:net,iface 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>
16 #include <linux/rbtree.h>
19 #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_hash.h>
27 MODULE_LICENSE("GPL");
28 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29 MODULE_DESCRIPTION("hash:net,iface type of IP sets");
30 MODULE_ALIAS("ip_set_hash:net,iface");
32 /* Interface name rbtree */
39 #define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
42 ifname_compare(const char *_a
, const char *_b
)
44 const long *a
= (const long *)_a
;
45 const long *b
= (const long *)_b
;
47 BUILD_BUG_ON(IFNAMSIZ
> 4 * sizeof(unsigned long));
50 if (IFNAMSIZ
> sizeof(long)) {
54 if (IFNAMSIZ
> 2 * sizeof(long)) {
58 if (IFNAMSIZ
> 3 * sizeof(long)) {
66 rbtree_destroy(struct rb_root
*root
)
68 struct rb_node
*p
, *n
= root
->rb_node
;
69 struct iface_node
*node
;
71 /* Non-recursive destroy, like in ext3 */
82 node
= rb_entry(n
, struct iface_node
, node
);
85 else if (p
->rb_left
== n
)
87 else if (p
->rb_right
== n
)
96 iface_test(struct rb_root
*root
, const char **iface
)
98 struct rb_node
*n
= root
->rb_node
;
101 const char *d
= iface_data(n
);
102 long res
= ifname_compare(*iface
, d
);
117 iface_add(struct rb_root
*root
, const char **iface
)
119 struct rb_node
**n
= &(root
->rb_node
), *p
= NULL
;
120 struct iface_node
*d
;
123 char *ifname
= iface_data(*n
);
124 long res
= ifname_compare(*iface
, ifname
);
128 n
= &((*n
)->rb_left
);
130 n
= &((*n
)->rb_right
);
137 d
= kzalloc(sizeof(*d
), GFP_ATOMIC
);
140 strcpy(d
->iface
, *iface
);
142 rb_link_node(&d
->node
, p
, n
);
143 rb_insert_color(&d
->node
, root
);
149 /* Type specific function prefix */
150 #define TYPE hash_netiface
153 hash_netiface_same_set(const struct ip_set
*a
, const struct ip_set
*b
);
155 #define hash_netiface4_same_set hash_netiface_same_set
156 #define hash_netiface6_same_set hash_netiface_same_set
158 #define STREQ(a, b) (strcmp(a, b) == 0)
160 /* The type variant functions: IPv4 */
162 struct hash_netiface4_elem_hashed
{
170 #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
172 /* Member elements without timeout */
173 struct hash_netiface4_elem
{
182 /* Member elements with timeout support */
183 struct hash_netiface4_telem
{
190 unsigned long timeout
;
194 hash_netiface4_data_equal(const struct hash_netiface4_elem
*ip1
,
195 const struct hash_netiface4_elem
*ip2
,
198 return ip1
->ip
== ip2
->ip
&&
199 ip1
->cidr
== ip2
->cidr
&&
201 ip1
->physdev
== ip2
->physdev
&&
202 ip1
->iface
== ip2
->iface
;
206 hash_netiface4_data_isnull(const struct hash_netiface4_elem
*elem
)
208 return elem
->cidr
== 0;
212 hash_netiface4_data_copy(struct hash_netiface4_elem
*dst
,
213 const struct hash_netiface4_elem
*src
)
216 dst
->cidr
= src
->cidr
;
217 dst
->physdev
= src
->physdev
;
218 dst
->iface
= src
->iface
;
219 dst
->nomatch
= src
->nomatch
;
223 hash_netiface4_data_flags(struct hash_netiface4_elem
*dst
, u32 flags
)
225 dst
->nomatch
= flags
& IPSET_FLAG_NOMATCH
;
229 hash_netiface4_data_match(const struct hash_netiface4_elem
*elem
)
231 return !elem
->nomatch
;
235 hash_netiface4_data_netmask(struct hash_netiface4_elem
*elem
, u8 cidr
)
237 elem
->ip
&= ip_set_netmask(cidr
);
242 hash_netiface4_data_zero_out(struct hash_netiface4_elem
*elem
)
248 hash_netiface4_data_list(struct sk_buff
*skb
,
249 const struct hash_netiface4_elem
*data
)
251 u32 flags
= data
->physdev
? IPSET_FLAG_PHYSDEV
: 0;
254 flags
|= IPSET_FLAG_NOMATCH
;
255 if (nla_put_ipaddr4(skb
, IPSET_ATTR_IP
, data
->ip
) ||
256 nla_put_u8(skb
, IPSET_ATTR_CIDR
, data
->cidr
) ||
257 nla_put_string(skb
, IPSET_ATTR_IFACE
, data
->iface
) ||
259 nla_put_net32(skb
, IPSET_ATTR_CADT_FLAGS
, htonl(flags
))))
260 goto nla_put_failure
;
268 hash_netiface4_data_tlist(struct sk_buff
*skb
,
269 const struct hash_netiface4_elem
*data
)
271 const struct hash_netiface4_telem
*tdata
=
272 (const struct hash_netiface4_telem
*)data
;
273 u32 flags
= data
->physdev
? IPSET_FLAG_PHYSDEV
: 0;
276 flags
|= IPSET_FLAG_NOMATCH
;
277 if (nla_put_ipaddr4(skb
, IPSET_ATTR_IP
, data
->ip
) ||
278 nla_put_u8(skb
, IPSET_ATTR_CIDR
, data
->cidr
) ||
279 nla_put_string(skb
, IPSET_ATTR_IFACE
, data
->iface
) ||
281 nla_put_net32(skb
, IPSET_ATTR_CADT_FLAGS
, htonl(flags
))) ||
282 nla_put_net32(skb
, IPSET_ATTR_TIMEOUT
,
283 htonl(ip_set_timeout_get(tdata
->timeout
))))
284 goto nla_put_failure
;
292 #define IP_SET_HASH_WITH_NETS
293 #define IP_SET_HASH_WITH_RBTREE
294 #define IP_SET_HASH_WITH_MULTI
298 #include <linux/netfilter/ipset/ip_set_ahash.h>
301 hash_netiface4_data_next(struct ip_set_hash
*h
,
302 const struct hash_netiface4_elem
*d
)
304 h
->next
.ip
= ntohl(d
->ip
);
308 hash_netiface4_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
309 const struct xt_action_param
*par
,
310 enum ipset_adt adt
, const struct ip_set_adt_opt
*opt
)
312 struct ip_set_hash
*h
= set
->data
;
313 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
314 struct hash_netiface4_elem data
= {
315 .cidr
= h
->nets
[0].cidr
? h
->nets
[0].cidr
: HOST_MASK
321 if (adt
== IPSET_TEST
)
322 data
.cidr
= HOST_MASK
;
324 ip4addrptr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
, &data
.ip
);
325 data
.ip
&= ip_set_netmask(data
.cidr
);
327 #define IFACE(dir) (par->dir ? par->dir->name : NULL)
328 #define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
329 #define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
331 if (opt
->cmdflags
& IPSET_FLAG_PHYSDEV
) {
332 #ifdef CONFIG_BRIDGE_NETFILTER
333 const struct nf_bridge_info
*nf_bridge
= skb
->nf_bridge
;
337 data
.iface
= SRCDIR
? PHYSDEV(physindev
) : PHYSDEV(physoutdev
);
343 data
.iface
= SRCDIR
? IFACE(in
) : IFACE(out
);
347 ret
= iface_test(&h
->rbtree
, &data
.iface
);
348 if (adt
== IPSET_ADD
) {
350 ret
= iface_add(&h
->rbtree
, &data
.iface
);
357 return adtfn(set
, &data
, opt_timeout(opt
, h
), opt
->cmdflags
);
361 hash_netiface4_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
362 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
364 struct ip_set_hash
*h
= set
->data
;
365 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
366 struct hash_netiface4_elem data
= { .cidr
= HOST_MASK
};
367 u32 ip
= 0, ip_to
, last
;
368 u32 timeout
= h
->timeout
;
369 char iface
[IFNAMSIZ
] = {};
372 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
373 !tb
[IPSET_ATTR_IFACE
] ||
374 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
375 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
376 return -IPSET_ERR_PROTOCOL
;
378 if (tb
[IPSET_ATTR_LINENO
])
379 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
381 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP
], &ip
);
385 if (tb
[IPSET_ATTR_CIDR
]) {
386 data
.cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
387 if (!data
.cidr
|| data
.cidr
> HOST_MASK
)
388 return -IPSET_ERR_INVALID_CIDR
;
391 if (tb
[IPSET_ATTR_TIMEOUT
]) {
392 if (!with_timeout(h
->timeout
))
393 return -IPSET_ERR_TIMEOUT
;
394 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
397 strcpy(iface
, nla_data(tb
[IPSET_ATTR_IFACE
]));
399 ret
= iface_test(&h
->rbtree
, &data
.iface
);
400 if (adt
== IPSET_ADD
) {
402 ret
= iface_add(&h
->rbtree
, &data
.iface
);
409 if (tb
[IPSET_ATTR_CADT_FLAGS
]) {
410 u32 cadt_flags
= ip_set_get_h32(tb
[IPSET_ATTR_CADT_FLAGS
]);
411 if (cadt_flags
& IPSET_FLAG_PHYSDEV
)
413 if (adt
== IPSET_ADD
&& (cadt_flags
& IPSET_FLAG_NOMATCH
))
414 flags
|= (cadt_flags
<< 16);
417 if (adt
== IPSET_TEST
|| !tb
[IPSET_ATTR_IP_TO
]) {
418 data
.ip
= htonl(ip
& ip_set_hostmask(data
.cidr
));
419 ret
= adtfn(set
, &data
, timeout
, flags
);
420 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
423 if (tb
[IPSET_ATTR_IP_TO
]) {
424 ret
= ip_set_get_hostipaddr4(tb
[IPSET_ATTR_IP_TO
], &ip_to
);
429 if (ip
+ UINT_MAX
== ip_to
)
430 return -IPSET_ERR_HASH_RANGE
;
432 ip_set_mask_from_to(ip
, ip_to
, data
.cidr
);
437 while (!after(ip
, ip_to
)) {
439 last
= ip_set_range_to_cidr(ip
, ip_to
, &data
.cidr
);
440 ret
= adtfn(set
, &data
, timeout
, flags
);
442 if (ret
&& !ip_set_eexist(ret
, flags
))
452 hash_netiface_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
454 const struct ip_set_hash
*x
= a
->data
;
455 const struct ip_set_hash
*y
= b
->data
;
457 /* Resizing changes htable_bits, so we ignore it */
458 return x
->maxelem
== y
->maxelem
&&
459 x
->timeout
== y
->timeout
;
462 /* The type variant functions: IPv6 */
464 struct hash_netiface6_elem_hashed
{
465 union nf_inet_addr ip
;
472 #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
474 struct hash_netiface6_elem
{
475 union nf_inet_addr ip
;
483 struct hash_netiface6_telem
{
484 union nf_inet_addr ip
;
490 unsigned long timeout
;
494 hash_netiface6_data_equal(const struct hash_netiface6_elem
*ip1
,
495 const struct hash_netiface6_elem
*ip2
,
498 return ipv6_addr_cmp(&ip1
->ip
.in6
, &ip2
->ip
.in6
) == 0 &&
499 ip1
->cidr
== ip2
->cidr
&&
501 ip1
->physdev
== ip2
->physdev
&&
502 ip1
->iface
== ip2
->iface
;
506 hash_netiface6_data_isnull(const struct hash_netiface6_elem
*elem
)
508 return elem
->cidr
== 0;
512 hash_netiface6_data_copy(struct hash_netiface6_elem
*dst
,
513 const struct hash_netiface6_elem
*src
)
515 memcpy(dst
, src
, sizeof(*dst
));
519 hash_netiface6_data_flags(struct hash_netiface6_elem
*dst
, u32 flags
)
521 dst
->nomatch
= flags
& IPSET_FLAG_NOMATCH
;
525 hash_netiface6_data_match(const struct hash_netiface6_elem
*elem
)
527 return !elem
->nomatch
;
531 hash_netiface6_data_zero_out(struct hash_netiface6_elem
*elem
)
537 ip6_netmask(union nf_inet_addr
*ip
, u8 prefix
)
539 ip
->ip6
[0] &= ip_set_netmask6(prefix
)[0];
540 ip
->ip6
[1] &= ip_set_netmask6(prefix
)[1];
541 ip
->ip6
[2] &= ip_set_netmask6(prefix
)[2];
542 ip
->ip6
[3] &= ip_set_netmask6(prefix
)[3];
546 hash_netiface6_data_netmask(struct hash_netiface6_elem
*elem
, u8 cidr
)
548 ip6_netmask(&elem
->ip
, cidr
);
553 hash_netiface6_data_list(struct sk_buff
*skb
,
554 const struct hash_netiface6_elem
*data
)
556 u32 flags
= data
->physdev
? IPSET_FLAG_PHYSDEV
: 0;
559 flags
|= IPSET_FLAG_NOMATCH
;
560 if (nla_put_ipaddr6(skb
, IPSET_ATTR_IP
, &data
->ip
.in6
) ||
561 nla_put_u8(skb
, IPSET_ATTR_CIDR
, data
->cidr
) ||
562 nla_put_string(skb
, IPSET_ATTR_IFACE
, data
->iface
) ||
564 nla_put_net32(skb
, IPSET_ATTR_CADT_FLAGS
, htonl(flags
))))
565 goto nla_put_failure
;
573 hash_netiface6_data_tlist(struct sk_buff
*skb
,
574 const struct hash_netiface6_elem
*data
)
576 const struct hash_netiface6_telem
*e
=
577 (const struct hash_netiface6_telem
*)data
;
578 u32 flags
= data
->physdev
? IPSET_FLAG_PHYSDEV
: 0;
581 flags
|= IPSET_FLAG_NOMATCH
;
582 if (nla_put_ipaddr6(skb
, IPSET_ATTR_IP
, &e
->ip
.in6
) ||
583 nla_put_u8(skb
, IPSET_ATTR_CIDR
, data
->cidr
) ||
584 nla_put_string(skb
, IPSET_ATTR_IFACE
, data
->iface
) ||
586 nla_put_net32(skb
, IPSET_ATTR_CADT_FLAGS
, htonl(flags
))) ||
587 nla_put_net32(skb
, IPSET_ATTR_TIMEOUT
,
588 htonl(ip_set_timeout_get(e
->timeout
))))
589 goto nla_put_failure
;
600 #define HOST_MASK 128
601 #include <linux/netfilter/ipset/ip_set_ahash.h>
604 hash_netiface6_data_next(struct ip_set_hash
*h
,
605 const struct hash_netiface6_elem
*d
)
610 hash_netiface6_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
611 const struct xt_action_param
*par
,
612 enum ipset_adt adt
, const struct ip_set_adt_opt
*opt
)
614 struct ip_set_hash
*h
= set
->data
;
615 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
616 struct hash_netiface6_elem data
= {
617 .cidr
= h
->nets
[0].cidr
? h
->nets
[0].cidr
: HOST_MASK
623 if (adt
== IPSET_TEST
)
624 data
.cidr
= HOST_MASK
;
626 ip6addrptr(skb
, opt
->flags
& IPSET_DIM_ONE_SRC
, &data
.ip
.in6
);
627 ip6_netmask(&data
.ip
, data
.cidr
);
629 if (opt
->cmdflags
& IPSET_FLAG_PHYSDEV
) {
630 #ifdef CONFIG_BRIDGE_NETFILTER
631 const struct nf_bridge_info
*nf_bridge
= skb
->nf_bridge
;
635 data
.iface
= SRCDIR
? PHYSDEV(physindev
) : PHYSDEV(physoutdev
);
641 data
.iface
= SRCDIR
? IFACE(in
) : IFACE(out
);
645 ret
= iface_test(&h
->rbtree
, &data
.iface
);
646 if (adt
== IPSET_ADD
) {
648 ret
= iface_add(&h
->rbtree
, &data
.iface
);
655 return adtfn(set
, &data
, opt_timeout(opt
, h
), opt
->cmdflags
);
659 hash_netiface6_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
660 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
662 struct ip_set_hash
*h
= set
->data
;
663 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
664 struct hash_netiface6_elem data
= { .cidr
= HOST_MASK
};
665 u32 timeout
= h
->timeout
;
666 char iface
[IFNAMSIZ
] = {};
669 if (unlikely(!tb
[IPSET_ATTR_IP
] ||
670 !tb
[IPSET_ATTR_IFACE
] ||
671 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
672 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
673 return -IPSET_ERR_PROTOCOL
;
674 if (unlikely(tb
[IPSET_ATTR_IP_TO
]))
675 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED
;
677 if (tb
[IPSET_ATTR_LINENO
])
678 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
680 ret
= ip_set_get_ipaddr6(tb
[IPSET_ATTR_IP
], &data
.ip
);
684 if (tb
[IPSET_ATTR_CIDR
])
685 data
.cidr
= nla_get_u8(tb
[IPSET_ATTR_CIDR
]);
686 if (!data
.cidr
|| data
.cidr
> HOST_MASK
)
687 return -IPSET_ERR_INVALID_CIDR
;
688 ip6_netmask(&data
.ip
, data
.cidr
);
690 if (tb
[IPSET_ATTR_TIMEOUT
]) {
691 if (!with_timeout(h
->timeout
))
692 return -IPSET_ERR_TIMEOUT
;
693 timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
696 strcpy(iface
, nla_data(tb
[IPSET_ATTR_IFACE
]));
698 ret
= iface_test(&h
->rbtree
, &data
.iface
);
699 if (adt
== IPSET_ADD
) {
701 ret
= iface_add(&h
->rbtree
, &data
.iface
);
708 if (tb
[IPSET_ATTR_CADT_FLAGS
]) {
709 u32 cadt_flags
= ip_set_get_h32(tb
[IPSET_ATTR_CADT_FLAGS
]);
710 if (cadt_flags
& IPSET_FLAG_PHYSDEV
)
712 if (adt
== IPSET_ADD
&& (cadt_flags
& IPSET_FLAG_NOMATCH
))
713 flags
|= (cadt_flags
<< 16);
716 ret
= adtfn(set
, &data
, timeout
, flags
);
718 return ip_set_eexist(ret
, flags
) ? 0 : ret
;
721 /* Create hash:ip type of sets */
724 hash_netiface_create(struct ip_set
*set
, struct nlattr
*tb
[], u32 flags
)
726 struct ip_set_hash
*h
;
727 u32 hashsize
= IPSET_DEFAULT_HASHSIZE
, maxelem
= IPSET_DEFAULT_MAXELEM
;
731 if (!(set
->family
== NFPROTO_IPV4
|| set
->family
== NFPROTO_IPV6
))
732 return -IPSET_ERR_INVALID_FAMILY
;
734 if (unlikely(!ip_set_optattr_netorder(tb
, IPSET_ATTR_HASHSIZE
) ||
735 !ip_set_optattr_netorder(tb
, IPSET_ATTR_MAXELEM
) ||
736 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
)))
737 return -IPSET_ERR_PROTOCOL
;
739 if (tb
[IPSET_ATTR_HASHSIZE
]) {
740 hashsize
= ip_set_get_h32(tb
[IPSET_ATTR_HASHSIZE
]);
741 if (hashsize
< IPSET_MIMINAL_HASHSIZE
)
742 hashsize
= IPSET_MIMINAL_HASHSIZE
;
745 if (tb
[IPSET_ATTR_MAXELEM
])
746 maxelem
= ip_set_get_h32(tb
[IPSET_ATTR_MAXELEM
]);
748 h
= kzalloc(sizeof(*h
)
749 + sizeof(struct ip_set_hash_nets
)
750 * (set
->family
== NFPROTO_IPV4
? 32 : 128), GFP_KERNEL
);
754 h
->maxelem
= maxelem
;
755 get_random_bytes(&h
->initval
, sizeof(h
->initval
));
756 h
->timeout
= IPSET_NO_TIMEOUT
;
757 h
->ahash_max
= AHASH_MAX_SIZE
;
759 hbits
= htable_bits(hashsize
);
760 hsize
= htable_size(hbits
);
765 h
->table
= ip_set_alloc(hsize
);
770 h
->table
->htable_bits
= hbits
;
775 if (tb
[IPSET_ATTR_TIMEOUT
]) {
776 h
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
778 set
->variant
= set
->family
== NFPROTO_IPV4
779 ? &hash_netiface4_tvariant
: &hash_netiface6_tvariant
;
781 if (set
->family
== NFPROTO_IPV4
)
782 hash_netiface4_gc_init(set
);
784 hash_netiface6_gc_init(set
);
786 set
->variant
= set
->family
== NFPROTO_IPV4
787 ? &hash_netiface4_variant
: &hash_netiface6_variant
;
790 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
791 set
->name
, jhash_size(h
->table
->htable_bits
),
792 h
->table
->htable_bits
, h
->maxelem
, set
->data
, h
->table
);
797 static struct ip_set_type hash_netiface_type __read_mostly
= {
798 .name
= "hash:net,iface",
799 .protocol
= IPSET_PROTOCOL
,
800 .features
= IPSET_TYPE_IP
| IPSET_TYPE_IFACE
,
801 .dimension
= IPSET_DIM_TWO
,
802 .family
= NFPROTO_UNSPEC
,
804 .revision_max
= 1, /* nomatch flag support added */
805 .create
= hash_netiface_create
,
807 [IPSET_ATTR_HASHSIZE
] = { .type
= NLA_U32
},
808 [IPSET_ATTR_MAXELEM
] = { .type
= NLA_U32
},
809 [IPSET_ATTR_PROBES
] = { .type
= NLA_U8
},
810 [IPSET_ATTR_RESIZE
] = { .type
= NLA_U8
},
811 [IPSET_ATTR_PROTO
] = { .type
= NLA_U8
},
812 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
815 [IPSET_ATTR_IP
] = { .type
= NLA_NESTED
},
816 [IPSET_ATTR_IP_TO
] = { .type
= NLA_NESTED
},
817 [IPSET_ATTR_IFACE
] = { .type
= NLA_NUL_STRING
,
818 .len
= IPSET_MAXNAMELEN
- 1 },
819 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
820 [IPSET_ATTR_CIDR
] = { .type
= NLA_U8
},
821 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
822 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
828 hash_netiface_init(void)
830 return ip_set_type_register(&hash_netiface_type
);
834 hash_netiface_fini(void)
836 ip_set_type_unregister(&hash_netiface_type
);
839 module_init(hash_netiface_init
);
840 module_exit(hash_netiface_fini
);