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