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