]> Pileus Git - ~andy/linux/blob - net/netfilter/ipset/ip_set_hash_netiface.c
Merge branch 'next' into for-linus
[~andy/linux] / net / netfilter / ipset / ip_set_hash_netiface.c
1 /* Copyright (C) 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: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/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>
26
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");
31
32 /* Interface name rbtree */
33
34 struct iface_node {
35         struct rb_node node;
36         char iface[IFNAMSIZ];
37 };
38
39 #define iface_data(n)   (rb_entry(n, struct iface_node, node)->iface)
40
41 static inline long
42 ifname_compare(const char *_a, const char *_b)
43 {
44         const long *a = (const long *)_a;
45         const long *b = (const long *)_b;
46
47         BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
48         if (a[0] != b[0])
49                 return a[0] - b[0];
50         if (IFNAMSIZ > sizeof(long)) {
51                 if (a[1] != b[1])
52                         return a[1] - b[1];
53         }
54         if (IFNAMSIZ > 2 * sizeof(long)) {
55                 if (a[2] != b[2])
56                         return a[2] - b[2];
57         }
58         if (IFNAMSIZ > 3 * sizeof(long)) {
59                 if (a[3] != b[3])
60                         return a[3] - b[3];
61         }
62         return 0;
63 }
64
65 static void
66 rbtree_destroy(struct rb_root *root)
67 {
68         struct rb_node *p, *n = root->rb_node;
69         struct iface_node *node;
70
71         /* Non-recursive destroy, like in ext3 */
72         while (n) {
73                 if (n->rb_left) {
74                         n = n->rb_left;
75                         continue;
76                 }
77                 if (n->rb_right) {
78                         n = n->rb_right;
79                         continue;
80                 }
81                 p = rb_parent(n);
82                 node = rb_entry(n, struct iface_node, node);
83                 if (!p)
84                         *root = RB_ROOT;
85                 else if (p->rb_left == n)
86                         p->rb_left = NULL;
87                 else if (p->rb_right == n)
88                         p->rb_right = NULL;
89
90                 kfree(node);
91                 n = p;
92         }
93 }
94
95 static int
96 iface_test(struct rb_root *root, const char **iface)
97 {
98         struct rb_node *n = root->rb_node;
99
100         while (n) {
101                 const char *d = iface_data(n);
102                 long res = ifname_compare(*iface, d);
103
104                 if (res < 0)
105                         n = n->rb_left;
106                 else if (res > 0)
107                         n = n->rb_right;
108                 else {
109                         *iface = d;
110                         return 1;
111                 }
112         }
113         return 0;
114 }
115
116 static int
117 iface_add(struct rb_root *root, const char **iface)
118 {
119         struct rb_node **n = &(root->rb_node), *p = NULL;
120         struct iface_node *d;
121
122         while (*n) {
123                 char *ifname = iface_data(*n);
124                 long res = ifname_compare(*iface, ifname);
125
126                 p = *n;
127                 if (res < 0)
128                         n = &((*n)->rb_left);
129                 else if (res > 0)
130                         n = &((*n)->rb_right);
131                 else {
132                         *iface = ifname;
133                         return 0;
134                 }
135         }
136
137         d = kzalloc(sizeof(*d), GFP_ATOMIC);
138         if (!d)
139                 return -ENOMEM;
140         strcpy(d->iface, *iface);
141
142         rb_link_node(&d->node, p, n);
143         rb_insert_color(&d->node, root);
144
145         *iface = d->iface;
146         return 0;
147 }
148
149 /* Type specific function prefix */
150 #define TYPE            hash_netiface
151
152 static bool
153 hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
154
155 #define hash_netiface4_same_set hash_netiface_same_set
156 #define hash_netiface6_same_set hash_netiface_same_set
157
158 #define STREQ(a, b)     (strcmp(a, b) == 0)
159
160 /* The type variant functions: IPv4 */
161
162 struct hash_netiface4_elem_hashed {
163         __be32 ip;
164         u8 physdev;
165         u8 cidr;
166         u16 padding;
167 };
168
169 #define HKEY_DATALEN    sizeof(struct hash_netiface4_elem_hashed)
170
171 /* Member elements without timeout */
172 struct hash_netiface4_elem {
173         __be32 ip;
174         u8 physdev;
175         u8 cidr;
176         u16 padding;
177         const char *iface;
178 };
179
180 /* Member elements with timeout support */
181 struct hash_netiface4_telem {
182         __be32 ip;
183         u8 physdev;
184         u8 cidr;
185         u16 padding;
186         const char *iface;
187         unsigned long timeout;
188 };
189
190 static inline bool
191 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
192                           const struct hash_netiface4_elem *ip2,
193                           u32 *multi)
194 {
195         return ip1->ip == ip2->ip &&
196                ip1->cidr == ip2->cidr &&
197                (++*multi) &&
198                ip1->physdev == ip2->physdev &&
199                ip1->iface == ip2->iface;
200 }
201
202 static inline bool
203 hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
204 {
205         return elem->cidr == 0;
206 }
207
208 static inline void
209 hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
210                          const struct hash_netiface4_elem *src) {
211         dst->ip = src->ip;
212         dst->cidr = src->cidr;
213         dst->physdev = src->physdev;
214         dst->iface = src->iface;
215 }
216
217 static inline void
218 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
219 {
220         elem->ip &= ip_set_netmask(cidr);
221         elem->cidr = cidr;
222 }
223
224 static inline void
225 hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
226 {
227         elem->cidr = 0;
228 }
229
230 static bool
231 hash_netiface4_data_list(struct sk_buff *skb,
232                          const struct hash_netiface4_elem *data)
233 {
234         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
235
236         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
237         NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
238         NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
239         if (flags)
240                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
241         return 0;
242
243 nla_put_failure:
244         return 1;
245 }
246
247 static bool
248 hash_netiface4_data_tlist(struct sk_buff *skb,
249                           const struct hash_netiface4_elem *data)
250 {
251         const struct hash_netiface4_telem *tdata =
252                 (const struct hash_netiface4_telem *)data;
253         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
254
255         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);
258         if (flags)
259                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
260         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
261                       htonl(ip_set_timeout_get(tdata->timeout)));
262
263         return 0;
264
265 nla_put_failure:
266         return 1;
267 }
268
269 #define IP_SET_HASH_WITH_NETS
270 #define IP_SET_HASH_WITH_RBTREE
271 #define IP_SET_HASH_WITH_MULTI
272
273 #define PF              4
274 #define HOST_MASK       32
275 #include <linux/netfilter/ipset/ip_set_ahash.h>
276
277 static inline void
278 hash_netiface4_data_next(struct ip_set_hash *h,
279                          const struct hash_netiface4_elem *d)
280 {
281         h->next.ip = ntohl(d->ip);
282 }
283
284 static int
285 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
286                     const struct xt_action_param *par,
287                     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
288 {
289         struct ip_set_hash *h = set->data;
290         ipset_adtfn adtfn = set->variant->adt[adt];
291         struct hash_netiface4_elem data = {
292                 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
293         };
294         int ret;
295
296         if (data.cidr == 0)
297                 return -EINVAL;
298         if (adt == IPSET_TEST)
299                 data.cidr = HOST_MASK;
300
301         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
302         data.ip &= ip_set_netmask(data.cidr);
303
304 #define IFACE(dir)      (par->dir ? par->dir->name : NULL)
305 #define PHYSDEV(dir)    (nf_bridge->dir ? nf_bridge->dir->name : NULL)
306 #define SRCDIR          (opt->flags & IPSET_DIM_TWO_SRC)
307
308         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
309 #ifdef CONFIG_BRIDGE_NETFILTER
310                 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
311
312                 if (!nf_bridge)
313                         return -EINVAL;
314                 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
315                 data.physdev = 1;
316 #else
317                 data.iface = NULL;
318 #endif
319         } else
320                 data.iface = SRCDIR ? IFACE(in) : IFACE(out);
321
322         if (!data.iface)
323                 return -EINVAL;
324         ret = iface_test(&h->rbtree, &data.iface);
325         if (adt == IPSET_ADD) {
326                 if (!ret) {
327                         ret = iface_add(&h->rbtree, &data.iface);
328                         if (ret)
329                                 return ret;
330                 }
331         } else if (!ret)
332                 return ret;
333
334         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
335 }
336
337 static int
338 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
339                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
340 {
341         struct ip_set_hash *h = set->data;
342         ipset_adtfn adtfn = set->variant->adt[adt];
343         struct hash_netiface4_elem data = { .cidr = HOST_MASK };
344         u32 ip = 0, ip_to, last;
345         u32 timeout = h->timeout;
346         char iface[IFNAMSIZ] = {};
347         int ret;
348
349         if (unlikely(!tb[IPSET_ATTR_IP] ||
350                      !tb[IPSET_ATTR_IFACE] ||
351                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
352                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
353                 return -IPSET_ERR_PROTOCOL;
354
355         if (tb[IPSET_ATTR_LINENO])
356                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
357
358         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
359         if (ret)
360                 return ret;
361
362         if (tb[IPSET_ATTR_CIDR]) {
363                 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
364                 if (!data.cidr)
365                         return -IPSET_ERR_INVALID_CIDR;
366         }
367
368         if (tb[IPSET_ATTR_TIMEOUT]) {
369                 if (!with_timeout(h->timeout))
370                         return -IPSET_ERR_TIMEOUT;
371                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
372         }
373
374         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
375         data.iface = iface;
376         ret = iface_test(&h->rbtree, &data.iface);
377         if (adt == IPSET_ADD) {
378                 if (!ret) {
379                         ret = iface_add(&h->rbtree, &data.iface);
380                         if (ret)
381                                 return ret;
382                 }
383         } else if (!ret)
384                 return ret;
385
386         if (tb[IPSET_ATTR_CADT_FLAGS]) {
387                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
388                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
389                         data.physdev = 1;
390         }
391
392         if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
393                 data.ip = htonl(ip & ip_set_hostmask(data.cidr));
394                 ret = adtfn(set, &data, timeout, flags);
395                 return ip_set_eexist(ret, flags) ? 0 : ret;
396         }
397
398         if (tb[IPSET_ATTR_IP_TO]) {
399                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
400                 if (ret)
401                         return ret;
402                 if (ip_to < ip)
403                         swap(ip, ip_to);
404                 if (ip + UINT_MAX == ip_to)
405                         return -IPSET_ERR_HASH_RANGE;
406         } else {
407                 ip_set_mask_from_to(ip, ip_to, data.cidr);
408         }
409
410         if (retried)
411                 ip = h->next.ip;
412         while (!after(ip, ip_to)) {
413                 data.ip = htonl(ip);
414                 last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
415                 ret = adtfn(set, &data, timeout, flags);
416
417                 if (ret && !ip_set_eexist(ret, flags))
418                         return ret;
419                 else
420                         ret = 0;
421                 ip = last + 1;
422         }
423         return ret;
424 }
425
426 static bool
427 hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
428 {
429         const struct ip_set_hash *x = a->data;
430         const struct ip_set_hash *y = b->data;
431
432         /* Resizing changes htable_bits, so we ignore it */
433         return x->maxelem == y->maxelem &&
434                x->timeout == y->timeout;
435 }
436
437 /* The type variant functions: IPv6 */
438
439 struct hash_netiface6_elem_hashed {
440         union nf_inet_addr ip;
441         u8 physdev;
442         u8 cidr;
443         u16 padding;
444 };
445
446 #define HKEY_DATALEN    sizeof(struct hash_netiface6_elem_hashed)
447
448 struct hash_netiface6_elem {
449         union nf_inet_addr ip;
450         u8 physdev;
451         u8 cidr;
452         u16 padding;
453         const char *iface;
454 };
455
456 struct hash_netiface6_telem {
457         union nf_inet_addr ip;
458         u8 physdev;
459         u8 cidr;
460         u16 padding;
461         const char *iface;
462         unsigned long timeout;
463 };
464
465 static inline bool
466 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
467                           const struct hash_netiface6_elem *ip2,
468                           u32 *multi)
469 {
470         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
471                ip1->cidr == ip2->cidr &&
472                (++*multi) &&
473                ip1->physdev == ip2->physdev &&
474                ip1->iface == ip2->iface;
475 }
476
477 static inline bool
478 hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
479 {
480         return elem->cidr == 0;
481 }
482
483 static inline void
484 hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
485                          const struct hash_netiface6_elem *src)
486 {
487         memcpy(dst, src, sizeof(*dst));
488 }
489
490 static inline void
491 hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
492 {
493 }
494
495 static inline void
496 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
497 {
498         ip->ip6[0] &= ip_set_netmask6(prefix)[0];
499         ip->ip6[1] &= ip_set_netmask6(prefix)[1];
500         ip->ip6[2] &= ip_set_netmask6(prefix)[2];
501         ip->ip6[3] &= ip_set_netmask6(prefix)[3];
502 }
503
504 static inline void
505 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
506 {
507         ip6_netmask(&elem->ip, cidr);
508         elem->cidr = cidr;
509 }
510
511 static bool
512 hash_netiface6_data_list(struct sk_buff *skb,
513                          const struct hash_netiface6_elem *data)
514 {
515         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
516
517         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
518         NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
519         NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
520         if (flags)
521                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
522         return 0;
523
524 nla_put_failure:
525         return 1;
526 }
527
528 static bool
529 hash_netiface6_data_tlist(struct sk_buff *skb,
530                           const struct hash_netiface6_elem *data)
531 {
532         const struct hash_netiface6_telem *e =
533                 (const struct hash_netiface6_telem *)data;
534         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
535
536         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
537         NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
538         NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
539         if (flags)
540                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
541         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
542                       htonl(ip_set_timeout_get(e->timeout)));
543         return 0;
544
545 nla_put_failure:
546         return 1;
547 }
548
549 #undef PF
550 #undef HOST_MASK
551
552 #define PF              6
553 #define HOST_MASK       128
554 #include <linux/netfilter/ipset/ip_set_ahash.h>
555
556 static inline void
557 hash_netiface6_data_next(struct ip_set_hash *h,
558                          const struct hash_netiface6_elem *d)
559 {
560 }
561
562 static int
563 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
564                     const struct xt_action_param *par,
565                     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
566 {
567         struct ip_set_hash *h = set->data;
568         ipset_adtfn adtfn = set->variant->adt[adt];
569         struct hash_netiface6_elem data = {
570                 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
571         };
572         int ret;
573
574         if (data.cidr == 0)
575                 return -EINVAL;
576         if (adt == IPSET_TEST)
577                 data.cidr = HOST_MASK;
578
579         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
580         ip6_netmask(&data.ip, data.cidr);
581
582         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
583 #ifdef CONFIG_BRIDGE_NETFILTER
584                 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
585
586                 if (!nf_bridge)
587                         return -EINVAL;
588                 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
589                 data.physdev = 1;
590 #else
591                 data.iface = NULL;
592 #endif
593         } else
594                 data.iface = SRCDIR ? IFACE(in) : IFACE(out);
595
596         if (!data.iface)
597                 return -EINVAL;
598         ret = iface_test(&h->rbtree, &data.iface);
599         if (adt == IPSET_ADD) {
600                 if (!ret) {
601                         ret = iface_add(&h->rbtree, &data.iface);
602                         if (ret)
603                                 return ret;
604                 }
605         } else if (!ret)
606                 return ret;
607
608         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
609 }
610
611 static int
612 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
613                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
614 {
615         struct ip_set_hash *h = set->data;
616         ipset_adtfn adtfn = set->variant->adt[adt];
617         struct hash_netiface6_elem data = { .cidr = HOST_MASK };
618         u32 timeout = h->timeout;
619         char iface[IFNAMSIZ] = {};
620         int ret;
621
622         if (unlikely(!tb[IPSET_ATTR_IP] ||
623                      !tb[IPSET_ATTR_IFACE] ||
624                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
625                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
626                 return -IPSET_ERR_PROTOCOL;
627         if (unlikely(tb[IPSET_ATTR_IP_TO]))
628                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
629
630         if (tb[IPSET_ATTR_LINENO])
631                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
632
633         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
634         if (ret)
635                 return ret;
636
637         if (tb[IPSET_ATTR_CIDR])
638                 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
639         if (!data.cidr)
640                 return -IPSET_ERR_INVALID_CIDR;
641         ip6_netmask(&data.ip, data.cidr);
642
643         if (tb[IPSET_ATTR_TIMEOUT]) {
644                 if (!with_timeout(h->timeout))
645                         return -IPSET_ERR_TIMEOUT;
646                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
647         }
648
649         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
650         data.iface = iface;
651         ret = iface_test(&h->rbtree, &data.iface);
652         if (adt == IPSET_ADD) {
653                 if (!ret) {
654                         ret = iface_add(&h->rbtree, &data.iface);
655                         if (ret)
656                                 return ret;
657                 }
658         } else if (!ret)
659                 return ret;
660
661         if (tb[IPSET_ATTR_CADT_FLAGS]) {
662                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
663                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
664                         data.physdev = 1;
665         }
666
667         ret = adtfn(set, &data, timeout, flags);
668
669         return ip_set_eexist(ret, flags) ? 0 : ret;
670 }
671
672 /* Create hash:ip type of sets */
673
674 static int
675 hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
676 {
677         struct ip_set_hash *h;
678         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
679         u8 hbits;
680
681         if (!(set->family == AF_INET || set->family == AF_INET6))
682                 return -IPSET_ERR_INVALID_FAMILY;
683
684         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
685                      !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
686                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
687                 return -IPSET_ERR_PROTOCOL;
688
689         if (tb[IPSET_ATTR_HASHSIZE]) {
690                 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
691                 if (hashsize < IPSET_MIMINAL_HASHSIZE)
692                         hashsize = IPSET_MIMINAL_HASHSIZE;
693         }
694
695         if (tb[IPSET_ATTR_MAXELEM])
696                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
697
698         h = kzalloc(sizeof(*h)
699                     + sizeof(struct ip_set_hash_nets)
700                       * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
701         if (!h)
702                 return -ENOMEM;
703
704         h->maxelem = maxelem;
705         get_random_bytes(&h->initval, sizeof(h->initval));
706         h->timeout = IPSET_NO_TIMEOUT;
707         h->ahash_max = AHASH_MAX_SIZE;
708
709         hbits = htable_bits(hashsize);
710         h->table = ip_set_alloc(
711                         sizeof(struct htable)
712                         + jhash_size(hbits) * sizeof(struct hbucket));
713         if (!h->table) {
714                 kfree(h);
715                 return -ENOMEM;
716         }
717         h->table->htable_bits = hbits;
718         h->rbtree = RB_ROOT;
719
720         set->data = h;
721
722         if (tb[IPSET_ATTR_TIMEOUT]) {
723                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
724
725                 set->variant = set->family == AF_INET
726                         ? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
727
728                 if (set->family == AF_INET)
729                         hash_netiface4_gc_init(set);
730                 else
731                         hash_netiface6_gc_init(set);
732         } else {
733                 set->variant = set->family == AF_INET
734                         ? &hash_netiface4_variant : &hash_netiface6_variant;
735         }
736
737         pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
738                  set->name, jhash_size(h->table->htable_bits),
739                  h->table->htable_bits, h->maxelem, set->data, h->table);
740
741         return 0;
742 }
743
744 static struct ip_set_type hash_netiface_type __read_mostly = {
745         .name           = "hash:net,iface",
746         .protocol       = IPSET_PROTOCOL,
747         .features       = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
748         .dimension      = IPSET_DIM_TWO,
749         .family         = AF_UNSPEC,
750         .revision_min   = 0,
751         .create         = hash_netiface_create,
752         .create_policy  = {
753                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
754                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
755                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
756                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
757                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
758                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
759         },
760         .adt_policy     = {
761                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
762                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
763                 [IPSET_ATTR_IFACE]      = { .type = NLA_NUL_STRING,
764                                             .len = IPSET_MAXNAMELEN - 1 },
765                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
766                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
767                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
768                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
769         },
770         .me             = THIS_MODULE,
771 };
772
773 static int __init
774 hash_netiface_init(void)
775 {
776         return ip_set_type_register(&hash_netiface_type);
777 }
778
779 static void __exit
780 hash_netiface_fini(void)
781 {
782         ip_set_type_unregister(&hash_netiface_type);
783 }
784
785 module_init(hash_netiface_init);
786 module_exit(hash_netiface_fini);