netfilter: ipset: fix hash size checking in kernel
[linux-flexiantxendom0-3.2.10.git] / 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         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, htonl(flags));
260         return 0;
261
262 nla_put_failure:
263         return 1;
264 }
265
266 static bool
267 hash_netiface4_data_tlist(struct sk_buff *skb,
268                           const struct hash_netiface4_elem *data)
269 {
270         const struct hash_netiface4_telem *tdata =
271                 (const struct hash_netiface4_telem *)data;
272         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
273
274         if (data->nomatch)
275                 flags |= IPSET_FLAG_NOMATCH;
276         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
277         NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
278         NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
279         if (flags)
280                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
281         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
282                       htonl(ip_set_timeout_get(tdata->timeout)));
283
284         return 0;
285
286 nla_put_failure:
287         return 1;
288 }
289
290 #define IP_SET_HASH_WITH_NETS
291 #define IP_SET_HASH_WITH_RBTREE
292 #define IP_SET_HASH_WITH_MULTI
293
294 #define PF              4
295 #define HOST_MASK       32
296 #include <linux/netfilter/ipset/ip_set_ahash.h>
297
298 static inline void
299 hash_netiface4_data_next(struct ip_set_hash *h,
300                          const struct hash_netiface4_elem *d)
301 {
302         h->next.ip = ntohl(d->ip);
303 }
304
305 static int
306 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
307                     const struct xt_action_param *par,
308                     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
309 {
310         struct ip_set_hash *h = set->data;
311         ipset_adtfn adtfn = set->variant->adt[adt];
312         struct hash_netiface4_elem data = {
313                 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
314         };
315         int ret;
316
317         if (data.cidr == 0)
318                 return -EINVAL;
319         if (adt == IPSET_TEST)
320                 data.cidr = HOST_MASK;
321
322         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
323         data.ip &= ip_set_netmask(data.cidr);
324
325 #define IFACE(dir)      (par->dir ? par->dir->name : NULL)
326 #define PHYSDEV(dir)    (nf_bridge->dir ? nf_bridge->dir->name : NULL)
327 #define SRCDIR          (opt->flags & IPSET_DIM_TWO_SRC)
328
329         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
330 #ifdef CONFIG_BRIDGE_NETFILTER
331                 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
332
333                 if (!nf_bridge)
334                         return -EINVAL;
335                 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
336                 data.physdev = 1;
337 #else
338                 data.iface = NULL;
339 #endif
340         } else
341                 data.iface = SRCDIR ? IFACE(in) : IFACE(out);
342
343         if (!data.iface)
344                 return -EINVAL;
345         ret = iface_test(&h->rbtree, &data.iface);
346         if (adt == IPSET_ADD) {
347                 if (!ret) {
348                         ret = iface_add(&h->rbtree, &data.iface);
349                         if (ret)
350                                 return ret;
351                 }
352         } else if (!ret)
353                 return ret;
354
355         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
356 }
357
358 static int
359 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
360                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
361 {
362         struct ip_set_hash *h = set->data;
363         ipset_adtfn adtfn = set->variant->adt[adt];
364         struct hash_netiface4_elem data = { .cidr = HOST_MASK };
365         u32 ip = 0, ip_to, last;
366         u32 timeout = h->timeout;
367         char iface[IFNAMSIZ] = {};
368         int ret;
369
370         if (unlikely(!tb[IPSET_ATTR_IP] ||
371                      !tb[IPSET_ATTR_IFACE] ||
372                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
373                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
374                 return -IPSET_ERR_PROTOCOL;
375
376         if (tb[IPSET_ATTR_LINENO])
377                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
378
379         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
380         if (ret)
381                 return ret;
382
383         if (tb[IPSET_ATTR_CIDR]) {
384                 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
385                 if (!data.cidr || data.cidr > HOST_MASK)
386                         return -IPSET_ERR_INVALID_CIDR;
387         }
388
389         if (tb[IPSET_ATTR_TIMEOUT]) {
390                 if (!with_timeout(h->timeout))
391                         return -IPSET_ERR_TIMEOUT;
392                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
393         }
394
395         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
396         data.iface = iface;
397         ret = iface_test(&h->rbtree, &data.iface);
398         if (adt == IPSET_ADD) {
399                 if (!ret) {
400                         ret = iface_add(&h->rbtree, &data.iface);
401                         if (ret)
402                                 return ret;
403                 }
404         } else if (!ret)
405                 return ret;
406
407         if (tb[IPSET_ATTR_CADT_FLAGS]) {
408                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
409                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
410                         data.physdev = 1;
411                 if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH))
412                         flags |= (cadt_flags << 16);
413         }
414
415         if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
416                 data.ip = htonl(ip & ip_set_hostmask(data.cidr));
417                 ret = adtfn(set, &data, timeout, flags);
418                 return ip_set_eexist(ret, flags) ? 0 : ret;
419         }
420
421         if (tb[IPSET_ATTR_IP_TO]) {
422                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
423                 if (ret)
424                         return ret;
425                 if (ip_to < ip)
426                         swap(ip, ip_to);
427                 if (ip + UINT_MAX == ip_to)
428                         return -IPSET_ERR_HASH_RANGE;
429         } else {
430                 ip_set_mask_from_to(ip, ip_to, data.cidr);
431         }
432
433         if (retried)
434                 ip = h->next.ip;
435         while (!after(ip, ip_to)) {
436                 data.ip = htonl(ip);
437                 last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
438                 ret = adtfn(set, &data, timeout, flags);
439
440                 if (ret && !ip_set_eexist(ret, flags))
441                         return ret;
442                 else
443                         ret = 0;
444                 ip = last + 1;
445         }
446         return ret;
447 }
448
449 static bool
450 hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
451 {
452         const struct ip_set_hash *x = a->data;
453         const struct ip_set_hash *y = b->data;
454
455         /* Resizing changes htable_bits, so we ignore it */
456         return x->maxelem == y->maxelem &&
457                x->timeout == y->timeout;
458 }
459
460 /* The type variant functions: IPv6 */
461
462 struct hash_netiface6_elem_hashed {
463         union nf_inet_addr ip;
464         u8 physdev;
465         u8 cidr;
466         u8 nomatch;
467         u8 padding;
468 };
469
470 #define HKEY_DATALEN    sizeof(struct hash_netiface6_elem_hashed)
471
472 struct hash_netiface6_elem {
473         union nf_inet_addr ip;
474         u8 physdev;
475         u8 cidr;
476         u8 nomatch;
477         u8 padding;
478         const char *iface;
479 };
480
481 struct hash_netiface6_telem {
482         union nf_inet_addr ip;
483         u8 physdev;
484         u8 cidr;
485         u8 nomatch;
486         u8 padding;
487         const char *iface;
488         unsigned long timeout;
489 };
490
491 static inline bool
492 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
493                           const struct hash_netiface6_elem *ip2,
494                           u32 *multi)
495 {
496         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
497                ip1->cidr == ip2->cidr &&
498                (++*multi) &&
499                ip1->physdev == ip2->physdev &&
500                ip1->iface == ip2->iface;
501 }
502
503 static inline bool
504 hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
505 {
506         return elem->cidr == 0;
507 }
508
509 static inline void
510 hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
511                          const struct hash_netiface6_elem *src)
512 {
513         memcpy(dst, src, sizeof(*dst));
514 }
515
516 static inline void
517 hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
518 {
519         dst->nomatch = flags & IPSET_FLAG_NOMATCH;
520 }
521
522 static inline bool
523 hash_netiface6_data_match(const struct hash_netiface6_elem *elem)
524 {
525         return !elem->nomatch;
526 }
527
528 static inline void
529 hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
530 {
531         elem->cidr = 0;
532 }
533
534 static inline void
535 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
536 {
537         ip->ip6[0] &= ip_set_netmask6(prefix)[0];
538         ip->ip6[1] &= ip_set_netmask6(prefix)[1];
539         ip->ip6[2] &= ip_set_netmask6(prefix)[2];
540         ip->ip6[3] &= ip_set_netmask6(prefix)[3];
541 }
542
543 static inline void
544 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
545 {
546         ip6_netmask(&elem->ip, cidr);
547         elem->cidr = cidr;
548 }
549
550 static bool
551 hash_netiface6_data_list(struct sk_buff *skb,
552                          const struct hash_netiface6_elem *data)
553 {
554         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
555
556         if (data->nomatch)
557                 flags |= IPSET_FLAG_NOMATCH;
558         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
559         NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
560         NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
561         if (flags)
562                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
563         return 0;
564
565 nla_put_failure:
566         return 1;
567 }
568
569 static bool
570 hash_netiface6_data_tlist(struct sk_buff *skb,
571                           const struct hash_netiface6_elem *data)
572 {
573         const struct hash_netiface6_telem *e =
574                 (const struct hash_netiface6_telem *)data;
575         u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
576
577         if (data->nomatch)
578                 flags |= IPSET_FLAG_NOMATCH;
579         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
580         NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
581         NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
582         if (flags)
583                 NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags));
584         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
585                       htonl(ip_set_timeout_get(e->timeout)));
586         return 0;
587
588 nla_put_failure:
589         return 1;
590 }
591
592 #undef PF
593 #undef HOST_MASK
594
595 #define PF              6
596 #define HOST_MASK       128
597 #include <linux/netfilter/ipset/ip_set_ahash.h>
598
599 static inline void
600 hash_netiface6_data_next(struct ip_set_hash *h,
601                          const struct hash_netiface6_elem *d)
602 {
603 }
604
605 static int
606 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
607                     const struct xt_action_param *par,
608                     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
609 {
610         struct ip_set_hash *h = set->data;
611         ipset_adtfn adtfn = set->variant->adt[adt];
612         struct hash_netiface6_elem data = {
613                 .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
614         };
615         int ret;
616
617         if (data.cidr == 0)
618                 return -EINVAL;
619         if (adt == IPSET_TEST)
620                 data.cidr = HOST_MASK;
621
622         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
623         ip6_netmask(&data.ip, data.cidr);
624
625         if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
626 #ifdef CONFIG_BRIDGE_NETFILTER
627                 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
628
629                 if (!nf_bridge)
630                         return -EINVAL;
631                 data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
632                 data.physdev = 1;
633 #else
634                 data.iface = NULL;
635 #endif
636         } else
637                 data.iface = SRCDIR ? IFACE(in) : IFACE(out);
638
639         if (!data.iface)
640                 return -EINVAL;
641         ret = iface_test(&h->rbtree, &data.iface);
642         if (adt == IPSET_ADD) {
643                 if (!ret) {
644                         ret = iface_add(&h->rbtree, &data.iface);
645                         if (ret)
646                                 return ret;
647                 }
648         } else if (!ret)
649                 return ret;
650
651         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
652 }
653
654 static int
655 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
656                    enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
657 {
658         struct ip_set_hash *h = set->data;
659         ipset_adtfn adtfn = set->variant->adt[adt];
660         struct hash_netiface6_elem data = { .cidr = HOST_MASK };
661         u32 timeout = h->timeout;
662         char iface[IFNAMSIZ] = {};
663         int ret;
664
665         if (unlikely(!tb[IPSET_ATTR_IP] ||
666                      !tb[IPSET_ATTR_IFACE] ||
667                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
668                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
669                 return -IPSET_ERR_PROTOCOL;
670         if (unlikely(tb[IPSET_ATTR_IP_TO]))
671                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
672
673         if (tb[IPSET_ATTR_LINENO])
674                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
675
676         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
677         if (ret)
678                 return ret;
679
680         if (tb[IPSET_ATTR_CIDR])
681                 data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
682         if (!data.cidr || data.cidr > HOST_MASK)
683                 return -IPSET_ERR_INVALID_CIDR;
684         ip6_netmask(&data.ip, data.cidr);
685
686         if (tb[IPSET_ATTR_TIMEOUT]) {
687                 if (!with_timeout(h->timeout))
688                         return -IPSET_ERR_TIMEOUT;
689                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
690         }
691
692         strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
693         data.iface = iface;
694         ret = iface_test(&h->rbtree, &data.iface);
695         if (adt == IPSET_ADD) {
696                 if (!ret) {
697                         ret = iface_add(&h->rbtree, &data.iface);
698                         if (ret)
699                                 return ret;
700                 }
701         } else if (!ret)
702                 return ret;
703
704         if (tb[IPSET_ATTR_CADT_FLAGS]) {
705                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
706                 if (cadt_flags & IPSET_FLAG_PHYSDEV)
707                         data.physdev = 1;
708                 if (adt == IPSET_ADD && (cadt_flags & IPSET_FLAG_NOMATCH))
709                         flags |= (cadt_flags << 16);
710         }
711
712         ret = adtfn(set, &data, timeout, flags);
713
714         return ip_set_eexist(ret, flags) ? 0 : ret;
715 }
716
717 /* Create hash:ip type of sets */
718
719 static int
720 hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
721 {
722         struct ip_set_hash *h;
723         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
724         u8 hbits;
725         size_t hsize;
726
727         if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
728                 return -IPSET_ERR_INVALID_FAMILY;
729
730         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
731                      !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
732                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
733                 return -IPSET_ERR_PROTOCOL;
734
735         if (tb[IPSET_ATTR_HASHSIZE]) {
736                 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
737                 if (hashsize < IPSET_MIMINAL_HASHSIZE)
738                         hashsize = IPSET_MIMINAL_HASHSIZE;
739         }
740
741         if (tb[IPSET_ATTR_MAXELEM])
742                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
743
744         h = kzalloc(sizeof(*h)
745                     + sizeof(struct ip_set_hash_nets)
746                       * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
747         if (!h)
748                 return -ENOMEM;
749
750         h->maxelem = maxelem;
751         get_random_bytes(&h->initval, sizeof(h->initval));
752         h->timeout = IPSET_NO_TIMEOUT;
753         h->ahash_max = AHASH_MAX_SIZE;
754
755         hbits = htable_bits(hashsize);
756         hsize = htable_size(hbits);
757         if (hsize == 0) {
758                 kfree(h);
759                 return -ENOMEM;
760         }
761         h->table = ip_set_alloc(hsize);
762         if (!h->table) {
763                 kfree(h);
764                 return -ENOMEM;
765         }
766         h->table->htable_bits = hbits;
767         h->rbtree = RB_ROOT;
768
769         set->data = h;
770
771         if (tb[IPSET_ATTR_TIMEOUT]) {
772                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
773
774                 set->variant = set->family == NFPROTO_IPV4
775                         ? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
776
777                 if (set->family == NFPROTO_IPV4)
778                         hash_netiface4_gc_init(set);
779                 else
780                         hash_netiface6_gc_init(set);
781         } else {
782                 set->variant = set->family == NFPROTO_IPV4
783                         ? &hash_netiface4_variant : &hash_netiface6_variant;
784         }
785
786         pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
787                  set->name, jhash_size(h->table->htable_bits),
788                  h->table->htable_bits, h->maxelem, set->data, h->table);
789
790         return 0;
791 }
792
793 static struct ip_set_type hash_netiface_type __read_mostly = {
794         .name           = "hash:net,iface",
795         .protocol       = IPSET_PROTOCOL,
796         .features       = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
797         .dimension      = IPSET_DIM_TWO,
798         .family         = NFPROTO_UNSPEC,
799         .revision_min   = 0,
800         .revision_max   = 1,    /* nomatch flag support added */
801         .create         = hash_netiface_create,
802         .create_policy  = {
803                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
804                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
805                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
806                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
807                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
808                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
809         },
810         .adt_policy     = {
811                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
812                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
813                 [IPSET_ATTR_IFACE]      = { .type = NLA_NUL_STRING,
814                                             .len = IPSET_MAXNAMELEN - 1 },
815                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
816                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
817                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
818                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
819         },
820         .me             = THIS_MODULE,
821 };
822
823 static int __init
824 hash_netiface_init(void)
825 {
826         return ip_set_type_register(&hash_netiface_type);
827 }
828
829 static void __exit
830 hash_netiface_fini(void)
831 {
832         ip_set_type_unregister(&hash_netiface_type);
833 }
834
835 module_init(hash_netiface_init);
836 module_exit(hash_netiface_fini);