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