]> Pileus Git - ~andy/linux/blob - net/netfilter/ipset/ip_set_hash_netiface.c
x86-64, reboot: Be more paranoid in 64-bit reboot=bios
[~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         u8 nomatch;
167         u8 padding;
168 };
169
170 #define HKEY_DATALEN    sizeof(struct hash_netiface4_elem_hashed)
171
172 /* Member elements without timeout */
173 struct hash_netiface4_elem {
174         __be32 ip;
175         u8 physdev;
176         u8 cidr;
177         u8 nomatch;
178         u8 padding;
179         const char *iface;
180 };
181
182 /* Member elements with timeout support */
183 struct hash_netiface4_telem {
184         __be32 ip;
185         u8 physdev;
186         u8 cidr;
187         u8 nomatch;
188         u8 padding;
189         const char *iface;
190         unsigned long timeout;
191 };
192
193 static inline bool
194 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
195                           const struct hash_netiface4_elem *ip2,
196                           u32 *multi)
197 {
198         return ip1->ip == ip2->ip &&
199                ip1->cidr == ip2->cidr &&
200                (++*multi) &&
201                ip1->physdev == ip2->physdev &&
202                ip1->iface == ip2->iface;
203 }
204
205 static inline bool
206 hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
207 {
208         return elem->cidr == 0;
209 }
210
211 static inline void
212 hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
213                          const struct hash_netiface4_elem *src)
214 {
215         dst->ip = src->ip;
216         dst->cidr = src->cidr;
217         dst->physdev = src->physdev;
218         dst->iface = src->iface;
219         dst->nomatch = src->nomatch;
220 }
221
222 static inline void
223 hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
224 {
225         dst->nomatch = flags & IPSET_FLAG_NOMATCH;
226 }
227
228 static inline bool
229 hash_netiface4_data_match(const struct hash_netiface4_elem *elem)
230 {
231         return !elem->nomatch;
232 }
233
234 static inline void
235 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
236 {
237         elem->ip &= ip_set_netmask(cidr);
238         elem->cidr = cidr;
239 }
240
241 static inline void
242 hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
243 {
244         elem->cidr = 0;
245 }
246
247 static bool
248 hash_netiface4_data_list(struct sk_buff *skb,
249                          const struct hash_netiface4_elem *data)
250 {
251         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
252
253         if (data->nomatch)
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) ||
258             (flags &&
259              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
260                 goto nla_put_failure;
261         return 0;
262
263 nla_put_failure:
264         return 1;
265 }
266
267 static bool
268 hash_netiface4_data_tlist(struct sk_buff *skb,
269                           const struct hash_netiface4_elem *data)
270 {
271         const struct hash_netiface4_telem *tdata =
272                 (const struct hash_netiface4_telem *)data;
273         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
274
275         if (data->nomatch)
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) ||
280             (flags &&
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;
285
286         return 0;
287
288 nla_put_failure:
289         return 1;
290 }
291
292 #define IP_SET_HASH_WITH_NETS
293 #define IP_SET_HASH_WITH_RBTREE
294 #define IP_SET_HASH_WITH_MULTI
295
296 #define PF              4
297 #define HOST_MASK       32
298 #include <linux/netfilter/ipset/ip_set_ahash.h>
299
300 static inline void
301 hash_netiface4_data_next(struct ip_set_hash *h,
302                          const struct hash_netiface4_elem *d)
303 {
304         h->next.ip = ntohl(d->ip);
305 }
306
307 static int
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)
311 {
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
316         };
317         int ret;
318
319         if (data.cidr == 0)
320                 return -EINVAL;
321         if (adt == IPSET_TEST)
322                 data.cidr = HOST_MASK;
323
324         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
325         data.ip &= ip_set_netmask(data.cidr);
326
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)
330
331         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
332 #ifdef CONFIG_BRIDGE_NETFILTER
333                 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
334
335                 if (!nf_bridge)
336                         return -EINVAL;
337                 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
338                 data.physdev = 1;
339 #else
340                 data.iface = NULL;
341 #endif
342         } else
343                 data.iface = SRCDIR ? IFACE(in) : IFACE(out);
344
345         if (!data.iface)
346                 return -EINVAL;
347         ret = iface_test(&h->rbtree, &data.iface);
348         if (adt == IPSET_ADD) {
349                 if (!ret) {
350                         ret = iface_add(&h->rbtree, &data.iface);
351                         if (ret)
352                                 return ret;
353                 }
354         } else if (!ret)
355                 return ret;
356
357         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
358 }
359
360 static int
361 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
362                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
363 {
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] = {};
370         int ret;
371
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;
377
378         if (tb[IPSET_ATTR_LINENO])
379                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
380
381         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
382         if (ret)
383                 return ret;
384
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;
389         }
390
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]);
395         }
396
397         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
398         data.iface = iface;
399         ret = iface_test(&h->rbtree, &data.iface);
400         if (adt == IPSET_ADD) {
401                 if (!ret) {
402                         ret = iface_add(&h->rbtree, &data.iface);
403                         if (ret)
404                                 return ret;
405                 }
406         } else if (!ret)
407                 return ret;
408
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)
412                         data.physdev = 1;
413                 if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH))
414                         flags |= (cadt_flags << 16);
415         }
416
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;
421         }
422
423         if (tb[IPSET_ATTR_IP_TO]) {
424                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
425                 if (ret)
426                         return ret;
427                 if (ip_to < ip)
428                         swap(ip, ip_to);
429                 if (ip + UINT_MAX == ip_to)
430                         return -IPSET_ERR_HASH_RANGE;
431         } else {
432                 ip_set_mask_from_to(ip, ip_to, data.cidr);
433         }
434
435         if (retried)
436                 ip = h->next.ip;
437         while (!after(ip, ip_to)) {
438                 data.ip = htonl(ip);
439                 last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
440                 ret = adtfn(set, &data, timeout, flags);
441
442                 if (ret && !ip_set_eexist(ret, flags))
443                         return ret;
444                 else
445                         ret = 0;
446                 ip = last + 1;
447         }
448         return ret;
449 }
450
451 static bool
452 hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
453 {
454         const struct ip_set_hash *x = a->data;
455         const struct ip_set_hash *y = b->data;
456
457         /* Resizing changes htable_bits, so we ignore it */
458         return x->maxelem == y->maxelem &&
459                x->timeout == y->timeout;
460 }
461
462 /* The type variant functions: IPv6 */
463
464 struct hash_netiface6_elem_hashed {
465         union nf_inet_addr ip;
466         u8 physdev;
467         u8 cidr;
468         u8 nomatch;
469         u8 padding;
470 };
471
472 #define HKEY_DATALEN    sizeof(struct hash_netiface6_elem_hashed)
473
474 struct hash_netiface6_elem {
475         union nf_inet_addr ip;
476         u8 physdev;
477         u8 cidr;
478         u8 nomatch;
479         u8 padding;
480         const char *iface;
481 };
482
483 struct hash_netiface6_telem {
484         union nf_inet_addr ip;
485         u8 physdev;
486         u8 cidr;
487         u8 nomatch;
488         u8 padding;
489         const char *iface;
490         unsigned long timeout;
491 };
492
493 static inline bool
494 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
495                           const struct hash_netiface6_elem *ip2,
496                           u32 *multi)
497 {
498         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
499                ip1->cidr == ip2->cidr &&
500                (++*multi) &&
501                ip1->physdev == ip2->physdev &&
502                ip1->iface == ip2->iface;
503 }
504
505 static inline bool
506 hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
507 {
508         return elem->cidr == 0;
509 }
510
511 static inline void
512 hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
513                          const struct hash_netiface6_elem *src)
514 {
515         memcpy(dst, src, sizeof(*dst));
516 }
517
518 static inline void
519 hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
520 {
521         dst->nomatch = flags & IPSET_FLAG_NOMATCH;
522 }
523
524 static inline bool
525 hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
526 {
527         return !elem->nomatch;
528 }
529
530 static inline void
531 hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
532 {
533         elem->cidr = 0;
534 }
535
536 static inline void
537 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
538 {
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];
543 }
544
545 static inline void
546 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
547 {
548         ip6_netmask(&elem->ip, cidr);
549         elem->cidr = cidr;
550 }
551
552 static bool
553 hash_netiface6_data_list(struct sk_buff *skb,
554                          const struct hash_netiface6_elem *data)
555 {
556         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
557
558         if (data->nomatch)
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) ||
563             (flags &&
564              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
565                 goto nla_put_failure;
566         return 0;
567
568 nla_put_failure:
569         return 1;
570 }
571
572 static bool
573 hash_netiface6_data_tlist(struct sk_buff *skb,
574                           const struct hash_netiface6_elem *data)
575 {
576         const struct hash_netiface6_telem *e =
577                 (const struct hash_netiface6_telem *)data;
578         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
579
580         if (data->nomatch)
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) ||
585             (flags &&
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;
590         return 0;
591
592 nla_put_failure:
593         return 1;
594 }
595
596 #undef PF
597 #undef HOST_MASK
598
599 #define PF              6
600 #define HOST_MASK       128
601 #include <linux/netfilter/ipset/ip_set_ahash.h>
602
603 static inline void
604 hash_netiface6_data_next(struct ip_set_hash *h,
605                          const struct hash_netiface6_elem *d)
606 {
607 }
608
609 static int
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)
613 {
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
618         };
619         int ret;
620
621         if (data.cidr == 0)
622                 return -EINVAL;
623         if (adt == IPSET_TEST)
624                 data.cidr = HOST_MASK;
625
626         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
627         ip6_netmask(&data.ip, data.cidr);
628
629         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
630 #ifdef CONFIG_BRIDGE_NETFILTER
631                 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
632
633                 if (!nf_bridge)
634                         return -EINVAL;
635                 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
636                 data.physdev = 1;
637 #else
638                 data.iface = NULL;
639 #endif
640         } else
641                 data.iface = SRCDIR ? IFACE(in) : IFACE(out);
642
643         if (!data.iface)
644                 return -EINVAL;
645         ret = iface_test(&h->rbtree, &data.iface);
646         if (adt == IPSET_ADD) {
647                 if (!ret) {
648                         ret = iface_add(&h->rbtree, &data.iface);
649                         if (ret)
650                                 return ret;
651                 }
652         } else if (!ret)
653                 return ret;
654
655         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
656 }
657
658 static int
659 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
660                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
661 {
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] = {};
667         int ret;
668
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;
676
677         if (tb[IPSET_ATTR_LINENO])
678                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
679
680         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
681         if (ret)
682                 return ret;
683
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);
689
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]);
694         }
695
696         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
697         data.iface = iface;
698         ret = iface_test(&h->rbtree, &data.iface);
699         if (adt == IPSET_ADD) {
700                 if (!ret) {
701                         ret = iface_add(&h->rbtree, &data.iface);
702                         if (ret)
703                                 return ret;
704                 }
705         } else if (!ret)
706                 return ret;
707
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)
711                         data.physdev = 1;
712                 if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH))
713                         flags |= (cadt_flags << 16);
714         }
715
716         ret = adtfn(set, &data, timeout, flags);
717
718         return ip_set_eexist(ret, flags) ? 0 : ret;
719 }
720
721 /* Create hash:ip type of sets */
722
723 static int
724 hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
725 {
726         struct ip_set_hash *h;
727         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
728         u8 hbits;
729         size_t hsize;
730
731         if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
732                 return -IPSET_ERR_INVALID_FAMILY;
733
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;
738
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;
743         }
744
745         if (tb[IPSET_ATTR_MAXELEM])
746                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
747
748         h = kzalloc(sizeof(*h)
749                     + sizeof(struct ip_set_hash_nets)
750                       * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
751         if (!h)
752                 return -ENOMEM;
753
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;
758
759         hbits = htable_bits(hashsize);
760         hsize = htable_size(hbits);
761         if (hsize == 0) {
762                 kfree(h);
763                 return -ENOMEM;
764         }
765         h->table = ip_set_alloc(hsize);
766         if (!h->table) {
767                 kfree(h);
768                 return -ENOMEM;
769         }
770         h->table->htable_bits = hbits;
771         h->rbtree = RB_ROOT;
772
773         set->data = h;
774
775         if (tb[IPSET_ATTR_TIMEOUT]) {
776                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
777
778                 set->variant = set->family == NFPROTO_IPV4
779                         ? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
780
781                 if (set->family == NFPROTO_IPV4)
782                         hash_netiface4_gc_init(set);
783                 else
784                         hash_netiface6_gc_init(set);
785         } else {
786                 set->variant = set->family == NFPROTO_IPV4
787                         ? &hash_netiface4_variant : &hash_netiface6_variant;
788         }
789
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);
793
794         return 0;
795 }
796
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,
803         .revision_min   = 0,
804         .revision_max   = 1,    /* nomatch flag support added */
805         .create         = hash_netiface_create,
806         .create_policy  = {
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 },
813         },
814         .adt_policy     = {
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 },
823         },
824         .me             = THIS_MODULE,
825 };
826
827 static int __init
828 hash_netiface_init(void)
829 {
830         return ip_set_type_register(&hash_netiface_type);
831 }
832
833 static void __exit
834 hash_netiface_fini(void)
835 {
836         ip_set_type_unregister(&hash_netiface_type);
837 }
838
839 module_init(hash_netiface_init);
840 module_exit(hash_netiface_fini);