Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / net / netfilter / ipset / ip_set_hash_netiface.c
1 /* Copyright (C) 2011-2013 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,iface 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 <linux/rbtree.h>
17 #include <net/ip.h>
18 #include <net/ipv6.h>
19 #include <net/netlink.h>
20
21 #include <linux/netfilter.h>
22 #include <linux/netfilter_bridge.h>
23 #include <linux/netfilter/ipset/pfxlen.h>
24 #include <linux/netfilter/ipset/ip_set.h>
25 #include <linux/netfilter/ipset/ip_set_hash.h>
26
27 #define IPSET_TYPE_REV_MIN      0
28 /*                              1    nomatch flag support added */
29 /*                              2    /0 support added */
30 /*                              3    Counters support added */
31 /*                              4    Comments support added */
32 /*                              5    Forceadd support added */
33 #define IPSET_TYPE_REV_MAX      6 /* skbinfo support added */
34
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
37 IP_SET_MODULE_DESC("hash:net,iface", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
38 MODULE_ALIAS("ip_set_hash:net,iface");
39
40 /* Interface name rbtree */
41
42 struct iface_node {
43         struct rb_node node;
44         char iface[IFNAMSIZ];
45 };
46
47 #define iface_data(n)   (rb_entry(n, struct iface_node, node)->iface)
48
49 static void
50 rbtree_destroy(struct rb_root *root)
51 {
52         struct iface_node *node, *next;
53
54         rbtree_postorder_for_each_entry_safe(node, next, root, node)
55                 kfree(node);
56
57         *root = RB_ROOT;
58 }
59
60 static int
61 iface_test(struct rb_root *root, const char **iface)
62 {
63         struct rb_node *n = root->rb_node;
64
65         while (n) {
66                 const char *d = iface_data(n);
67                 int res = strcmp(*iface, d);
68
69                 if (res < 0)
70                         n = n->rb_left;
71                 else if (res > 0)
72                         n = n->rb_right;
73                 else {
74                         *iface = d;
75                         return 1;
76                 }
77         }
78         return 0;
79 }
80
81 static int
82 iface_add(struct rb_root *root, const char **iface)
83 {
84         struct rb_node **n = &(root->rb_node), *p = NULL;
85         struct iface_node *d;
86
87         while (*n) {
88                 char *ifname = iface_data(*n);
89                 int res = strcmp(*iface, ifname);
90
91                 p = *n;
92                 if (res < 0)
93                         n = &((*n)->rb_left);
94                 else if (res > 0)
95                         n = &((*n)->rb_right);
96                 else {
97                         *iface = ifname;
98                         return 0;
99                 }
100         }
101
102         d = kzalloc(sizeof(*d), GFP_ATOMIC);
103         if (!d)
104                 return -ENOMEM;
105         strcpy(d->iface, *iface);
106
107         rb_link_node(&d->node, p, n);
108         rb_insert_color(&d->node, root);
109
110         *iface = d->iface;
111         return 0;
112 }
113
114 /* Type specific function prefix */
115 #define HTYPE           hash_netiface
116 #define IP_SET_HASH_WITH_NETS
117 #define IP_SET_HASH_WITH_RBTREE
118 #define IP_SET_HASH_WITH_MULTI
119 #define IP_SET_HASH_WITH_NET0
120
121 #define STREQ(a, b)     (strcmp(a, b) == 0)
122
123 /* IPv4 variant */
124
125 struct hash_netiface4_elem_hashed {
126         __be32 ip;
127         u8 physdev;
128         u8 cidr;
129         u8 nomatch;
130         u8 elem;
131 };
132
133 /* Member elements */
134 struct hash_netiface4_elem {
135         __be32 ip;
136         u8 physdev;
137         u8 cidr;
138         u8 nomatch;
139         u8 elem;
140         const char *iface;
141 };
142
143 /* Common functions */
144
145 static inline bool
146 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
147                           const struct hash_netiface4_elem *ip2,
148                           u32 *multi)
149 {
150         return ip1->ip == ip2->ip &&
151                ip1->cidr == ip2->cidr &&
152                (++*multi) &&
153                ip1->physdev == ip2->physdev &&
154                ip1->iface == ip2->iface;
155 }
156
157 static inline int
158 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
159 {
160         return elem->nomatch ? -ENOTEMPTY : 1;
161 }
162
163 static inline void
164 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
165 {
166         elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
167 }
168
169 static inline void
170 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
171 {
172         swap(*flags, elem->nomatch);
173 }
174
175 static inline void
176 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
177 {
178         elem->ip &= ip_set_netmask(cidr);
179         elem->cidr = cidr;
180 }
181
182 static bool
183 hash_netiface4_data_list(struct sk_buff *skb,
184                          const struct hash_netiface4_elem *data)
185 {
186         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
187
188         if (data->nomatch)
189                 flags |= IPSET_FLAG_NOMATCH;
190         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
191             nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
192             nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
193             (flags &&
194              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
195                 goto nla_put_failure;
196         return 0;
197
198 nla_put_failure:
199         return 1;
200 }
201
202 static inline void
203 hash_netiface4_data_next(struct hash_netiface4_elem *next,
204                          const struct hash_netiface4_elem *d)
205 {
206         next->ip = d->ip;
207 }
208
209 #define MTYPE           hash_netiface4
210 #define PF              4
211 #define HOST_MASK       32
212 #define HKEY_DATALEN    sizeof(struct hash_netiface4_elem_hashed)
213 #include "ip_set_hash_gen.h"
214
215 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
216 static const char *get_physindev_name(const struct sk_buff *skb)
217 {
218         struct net_device *dev = nf_bridge_get_physindev(skb);
219
220         return dev ? dev->name : NULL;
221 }
222
223 static const char *get_phyoutdev_name(const struct sk_buff *skb)
224 {
225         struct net_device *dev = nf_bridge_get_physoutdev(skb);
226
227         return dev ? dev->name : NULL;
228 }
229 #endif
230
231 static int
232 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
233                     const struct xt_action_param *par,
234                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
235 {
236         struct hash_netiface *h = set->data;
237         ipset_adtfn adtfn = set->variant->adt[adt];
238         struct hash_netiface4_elem e = {
239                 .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
240                 .elem = 1,
241         };
242         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
243         int ret;
244
245         if (e.cidr == 0)
246                 return -EINVAL;
247         if (adt == IPSET_TEST)
248                 e.cidr = HOST_MASK;
249
250         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
251         e.ip &= ip_set_netmask(e.cidr);
252
253 #define IFACE(dir)      (par->dir ? par->dir->name : NULL)
254 #define SRCDIR          (opt->flags & IPSET_DIM_TWO_SRC)
255
256         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
257 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
258                 e.iface = SRCDIR ? get_physindev_name(skb) :
259                                    get_phyoutdev_name(skb);
260
261                 if (!e.iface)
262                         return -EINVAL;
263                 e.physdev = 1;
264 #else
265                 e.iface = NULL;
266 #endif
267         } else
268                 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
269
270         if (!e.iface)
271                 return -EINVAL;
272         ret = iface_test(&h->rbtree, &e.iface);
273         if (adt == IPSET_ADD) {
274                 if (!ret) {
275                         ret = iface_add(&h->rbtree, &e.iface);
276                         if (ret)
277                                 return ret;
278                 }
279         } else if (!ret)
280                 return ret;
281
282         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
283 }
284
285 static int
286 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
287                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
288 {
289         struct hash_netiface *h = set->data;
290         ipset_adtfn adtfn = set->variant->adt[adt];
291         struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
292         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
293         u32 ip = 0, ip_to = 0, last;
294         char iface[IFNAMSIZ];
295         int ret;
296
297         if (unlikely(!tb[IPSET_ATTR_IP] ||
298                      !tb[IPSET_ATTR_IFACE] ||
299                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
300                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
301                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
302                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
303                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
304                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
305                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
306                 return -IPSET_ERR_PROTOCOL;
307
308         if (tb[IPSET_ATTR_LINENO])
309                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
310
311         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
312               ip_set_get_extensions(set, tb, &ext);
313         if (ret)
314                 return ret;
315
316         if (tb[IPSET_ATTR_CIDR]) {
317                 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
318                 if (e.cidr > HOST_MASK)
319                         return -IPSET_ERR_INVALID_CIDR;
320         }
321
322         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
323         e.iface = iface;
324         ret = iface_test(&h->rbtree, &e.iface);
325         if (adt == IPSET_ADD) {
326                 if (!ret) {
327                         ret = iface_add(&h->rbtree, &e.iface);
328                         if (ret)
329                                 return ret;
330                 }
331         } else if (!ret)
332                 return ret;
333
334         if (tb[IPSET_ATTR_CADT_FLAGS]) {
335                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
336                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
337                         e.physdev = 1;
338                 if (cadt_flags & IPSET_FLAG_NOMATCH)
339                         flags |= (IPSET_FLAG_NOMATCH << 16);
340         }
341         if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
342                 e.ip = htonl(ip & ip_set_hostmask(e.cidr));
343                 ret = adtfn(set, &e, &ext, &ext, flags);
344                 return ip_set_enomatch(ret, flags, adt, set) ? -ret :
345                        ip_set_eexist(ret, flags) ? 0 : ret;
346         }
347
348         if (tb[IPSET_ATTR_IP_TO]) {
349                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
350                 if (ret)
351                         return ret;
352                 if (ip_to < ip)
353                         swap(ip, ip_to);
354                 if (ip + UINT_MAX == ip_to)
355                         return -IPSET_ERR_HASH_RANGE;
356         } else
357                 ip_set_mask_from_to(ip, ip_to, e.cidr);
358
359         if (retried)
360                 ip = ntohl(h->next.ip);
361         while (!after(ip, ip_to)) {
362                 e.ip = htonl(ip);
363                 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
364                 ret = adtfn(set, &e, &ext, &ext, flags);
365
366                 if (ret && !ip_set_eexist(ret, flags))
367                         return ret;
368                 else
369                         ret = 0;
370                 ip = last + 1;
371         }
372         return ret;
373 }
374
375 /* IPv6 variant */
376
377 struct hash_netiface6_elem_hashed {
378         union nf_inet_addr ip;
379         u8 physdev;
380         u8 cidr;
381         u8 nomatch;
382         u8 elem;
383 };
384
385 struct hash_netiface6_elem {
386         union nf_inet_addr ip;
387         u8 physdev;
388         u8 cidr;
389         u8 nomatch;
390         u8 elem;
391         const char *iface;
392 };
393
394 /* Common functions */
395
396 static inline bool
397 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
398                           const struct hash_netiface6_elem *ip2,
399                           u32 *multi)
400 {
401         return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
402                ip1->cidr == ip2->cidr &&
403                (++*multi) &&
404                ip1->physdev == ip2->physdev &&
405                ip1->iface == ip2->iface;
406 }
407
408 static inline int
409 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
410 {
411         return elem->nomatch ? -ENOTEMPTY : 1;
412 }
413
414 static inline void
415 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
416 {
417         elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
418 }
419
420 static inline void
421 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
422 {
423         swap(*flags, elem->nomatch);
424 }
425
426 static inline void
427 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
428 {
429         ip6_netmask(&elem->ip, cidr);
430         elem->cidr = cidr;
431 }
432
433 static bool
434 hash_netiface6_data_list(struct sk_buff *skb,
435                          const struct hash_netiface6_elem *data)
436 {
437         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
438
439         if (data->nomatch)
440                 flags |= IPSET_FLAG_NOMATCH;
441         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
442             nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
443             nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
444             (flags &&
445              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
446                 goto nla_put_failure;
447         return 0;
448
449 nla_put_failure:
450         return 1;
451 }
452
453 static inline void
454 hash_netiface6_data_next(struct hash_netiface4_elem *next,
455                          const struct hash_netiface6_elem *d)
456 {
457 }
458
459 #undef MTYPE
460 #undef PF
461 #undef HOST_MASK
462 #undef HKEY_DATALEN
463
464 #define MTYPE           hash_netiface6
465 #define PF              6
466 #define HOST_MASK       128
467 #define HKEY_DATALEN    sizeof(struct hash_netiface6_elem_hashed)
468 #define IP_SET_EMIT_CREATE
469 #include "ip_set_hash_gen.h"
470
471 static int
472 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
473                     const struct xt_action_param *par,
474                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
475 {
476         struct hash_netiface *h = set->data;
477         ipset_adtfn adtfn = set->variant->adt[adt];
478         struct hash_netiface6_elem e = {
479                 .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
480                 .elem = 1,
481         };
482         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
483         int ret;
484
485         if (e.cidr == 0)
486                 return -EINVAL;
487         if (adt == IPSET_TEST)
488                 e.cidr = HOST_MASK;
489
490         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
491         ip6_netmask(&e.ip, e.cidr);
492
493         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
494 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
495                 e.iface = SRCDIR ? get_physindev_name(skb) :
496                                    get_phyoutdev_name(skb);
497                 if (!e.iface)
498                         return -EINVAL;
499
500                 e.physdev = 1;
501 #else
502                 e.iface = NULL;
503 #endif
504         } else
505                 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
506
507         if (!e.iface)
508                 return -EINVAL;
509         ret = iface_test(&h->rbtree, &e.iface);
510         if (adt == IPSET_ADD) {
511                 if (!ret) {
512                         ret = iface_add(&h->rbtree, &e.iface);
513                         if (ret)
514                                 return ret;
515                 }
516         } else if (!ret)
517                 return ret;
518
519         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
520 }
521
522 static int
523 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
524                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
525 {
526         struct hash_netiface *h = set->data;
527         ipset_adtfn adtfn = set->variant->adt[adt];
528         struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
529         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
530         char iface[IFNAMSIZ];
531         int ret;
532
533         if (unlikely(!tb[IPSET_ATTR_IP] ||
534                      !tb[IPSET_ATTR_IFACE] ||
535                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
536                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
537                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
538                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
539                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
540                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
541                      !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
542                 return -IPSET_ERR_PROTOCOL;
543         if (unlikely(tb[IPSET_ATTR_IP_TO]))
544                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
545
546         if (tb[IPSET_ATTR_LINENO])
547                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
548
549         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
550               ip_set_get_extensions(set, tb, &ext);
551         if (ret)
552                 return ret;
553
554         if (tb[IPSET_ATTR_CIDR])
555                 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
556         if (e.cidr > HOST_MASK)
557                 return -IPSET_ERR_INVALID_CIDR;
558         ip6_netmask(&e.ip, e.cidr);
559
560         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
561         e.iface = iface;
562         ret = iface_test(&h->rbtree, &e.iface);
563         if (adt == IPSET_ADD) {
564                 if (!ret) {
565                         ret = iface_add(&h->rbtree, &e.iface);
566                         if (ret)
567                                 return ret;
568                 }
569         } else if (!ret)
570                 return ret;
571
572         if (tb[IPSET_ATTR_CADT_FLAGS]) {
573                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
574                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
575                         e.physdev = 1;
576                 if (cadt_flags & IPSET_FLAG_NOMATCH)
577                         flags |= (IPSET_FLAG_NOMATCH << 16);
578         }
579
580         ret = adtfn(set, &e, &ext, &ext, flags);
581
582         return ip_set_enomatch(ret, flags, adt, set) ? -ret :
583                ip_set_eexist(ret, flags) ? 0 : ret;
584 }
585
586 static struct ip_set_type hash_netiface_type __read_mostly = {
587         .name           = "hash:net,iface",
588         .protocol       = IPSET_PROTOCOL,
589         .features       = IPSET_TYPE_IP | IPSET_TYPE_IFACE |
590                           IPSET_TYPE_NOMATCH,
591         .dimension      = IPSET_DIM_TWO,
592         .family         = NFPROTO_UNSPEC,
593         .revision_min   = IPSET_TYPE_REV_MIN,
594         .revision_max   = IPSET_TYPE_REV_MAX,
595         .create         = hash_netiface_create,
596         .create_policy  = {
597                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
598                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
599                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
600                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
601                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
602                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
603                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
604         },
605         .adt_policy     = {
606                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
607                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
608                 [IPSET_ATTR_IFACE]      = { .type = NLA_NUL_STRING,
609                                             .len  = IFNAMSIZ - 1 },
610                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
611                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
612                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
613                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
614                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
615                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
616                 [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING },
617                 [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
618                 [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
619                 [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
620         },
621         .me             = THIS_MODULE,
622 };
623
624 static int __init
625 hash_netiface_init(void)
626 {
627         return ip_set_type_register(&hash_netiface_type);
628 }
629
630 static void __exit
631 hash_netiface_fini(void)
632 {
633         ip_set_type_unregister(&hash_netiface_type);
634 }
635
636 module_init(hash_netiface_init);
637 module_exit(hash_netiface_fini);