1 /* Copyright (C) 2011-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
8 /* Kernel module implementing an IP set type: the hash:net,iface type */
10 #include <linux/jhash.h>
11 #include <linux/module.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
15 #include <linux/random.h>
16 #include <linux/rbtree.h>
19 #include <net/netlink.h>
21 #include <linux/netfilter.h>
22 #include <linux/netfilter_bridge.h>
23 #include <linux/netfilter/ipset/pfxlen.h>
24 #include <linux/netfilter/ipset/ip_set.h>
25 #include <linux/netfilter/ipset/ip_set_hash.h>
27 #define IPSET_TYPE_REV_MIN 0
28 /* 1 nomatch flag support added */
29 /* 2 /0 support added */
30 /* 3 Counters support added */
31 /* 4 Comments support added */
32 /* 5 Forceadd support added */
33 #define IPSET_TYPE_REV_MAX 6 /* skbinfo support added */
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
37 IP_SET_MODULE_DESC("hash:net,iface", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
38 MODULE_ALIAS("ip_set_hash:net,iface");
40 /* Interface name rbtree */
47 #define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
50 rbtree_destroy(struct rb_root *root)
52 struct iface_node *node, *next;
54 rbtree_postorder_for_each_entry_safe(node, next, root, node)
61 iface_test(struct rb_root *root, const char **iface)
63 struct rb_node *n = root->rb_node;
66 const char *d = iface_data(n);
67 int res = strcmp(*iface, d);
82 iface_add(struct rb_root *root, const char **iface)
84 struct rb_node **n = &(root->rb_node), *p = NULL;
88 char *ifname = iface_data(*n);
89 int res = strcmp(*iface, ifname);
95 n = &((*n)->rb_right);
102 d = kzalloc(sizeof(*d), GFP_ATOMIC);
105 strcpy(d->iface, *iface);
107 rb_link_node(&d->node, p, n);
108 rb_insert_color(&d->node, root);
114 /* Type specific function prefix */
115 #define HTYPE hash_netiface
116 #define IP_SET_HASH_WITH_NETS
117 #define IP_SET_HASH_WITH_RBTREE
118 #define IP_SET_HASH_WITH_MULTI
119 #define IP_SET_HASH_WITH_NET0
121 #define STREQ(a, b) (strcmp(a, b) == 0)
125 struct hash_netiface4_elem_hashed {
133 /* Member elements */
134 struct hash_netiface4_elem {
143 /* Common functions */
146 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
147 const struct hash_netiface4_elem *ip2,
150 return ip1->ip == ip2->ip &&
151 ip1->cidr == ip2->cidr &&
153 ip1->physdev == ip2->physdev &&
154 ip1->iface == ip2->iface;
158 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
160 return elem->nomatch ? -ENOTEMPTY : 1;
164 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
166 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
170 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
172 swap(*flags, elem->nomatch);
176 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
178 elem->ip &= ip_set_netmask(cidr);
183 hash_netiface4_data_list(struct sk_buff *skb,
184 const struct hash_netiface4_elem *data)
186 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
189 flags |= IPSET_FLAG_NOMATCH;
190 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
191 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
192 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
194 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
195 goto nla_put_failure;
203 hash_netiface4_data_next(struct hash_netiface4_elem *next,
204 const struct hash_netiface4_elem *d)
209 #define MTYPE hash_netiface4
212 #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
213 #include "ip_set_hash_gen.h"
215 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
216 static const char *get_physindev_name(const struct sk_buff *skb)
218 struct net_device *dev = nf_bridge_get_physindev(skb);
220 return dev ? dev->name : NULL;
223 static const char *get_phyoutdev_name(const struct sk_buff *skb)
225 struct net_device *dev = nf_bridge_get_physoutdev(skb);
227 return dev ? dev->name : NULL;
232 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
233 const struct xt_action_param *par,
234 enum ipset_adt adt, struct ip_set_adt_opt *opt)
236 struct hash_netiface *h = set->data;
237 ipset_adtfn adtfn = set->variant->adt[adt];
238 struct hash_netiface4_elem e = {
239 .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
242 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
247 if (adt == IPSET_TEST)
250 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
251 e.ip &= ip_set_netmask(e.cidr);
253 #define IFACE(dir) (par->dir ? par->dir->name : NULL)
254 #define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
256 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
257 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
258 e.iface = SRCDIR ? get_physindev_name(skb) :
259 get_phyoutdev_name(skb);
268 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
272 ret = iface_test(&h->rbtree, &e.iface);
273 if (adt == IPSET_ADD) {
275 ret = iface_add(&h->rbtree, &e.iface);
282 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
286 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
287 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
289 struct hash_netiface *h = set->data;
290 ipset_adtfn adtfn = set->variant->adt[adt];
291 struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
292 struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
293 u32 ip = 0, ip_to = 0, last;
294 char iface[IFNAMSIZ];
297 if (unlikely(!tb[IPSET_ATTR_IP] ||
298 !tb[IPSET_ATTR_IFACE] ||
299 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
300 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
301 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
302 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
303 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
304 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
305 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
306 return -IPSET_ERR_PROTOCOL;
308 if (tb[IPSET_ATTR_LINENO])
309 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
311 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
312 ip_set_get_extensions(set, tb, &ext);
316 if (tb[IPSET_ATTR_CIDR]) {
317 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
318 if (e.cidr > HOST_MASK)
319 return -IPSET_ERR_INVALID_CIDR;
322 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
324 ret = iface_test(&h->rbtree, &e.iface);
325 if (adt == IPSET_ADD) {
327 ret = iface_add(&h->rbtree, &e.iface);
334 if (tb[IPSET_ATTR_CADT_FLAGS]) {
335 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
336 if (cadt_flags & IPSET_FLAG_PHYSDEV)
338 if (cadt_flags & IPSET_FLAG_NOMATCH)
339 flags |= (IPSET_FLAG_NOMATCH << 16);
341 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
342 e.ip = htonl(ip & ip_set_hostmask(e.cidr));
343 ret = adtfn(set, &e, &ext, &ext, flags);
344 return ip_set_enomatch(ret, flags, adt, set) ? -ret :
345 ip_set_eexist(ret, flags) ? 0 : ret;
348 if (tb[IPSET_ATTR_IP_TO]) {
349 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
354 if (ip + UINT_MAX == ip_to)
355 return -IPSET_ERR_HASH_RANGE;
357 ip_set_mask_from_to(ip, ip_to, e.cidr);
360 ip = ntohl(h->next.ip);
361 while (!after(ip, ip_to)) {
363 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
364 ret = adtfn(set, &e, &ext, &ext, flags);
366 if (ret && !ip_set_eexist(ret, flags))
377 struct hash_netiface6_elem_hashed {
378 union nf_inet_addr ip;
385 struct hash_netiface6_elem {
386 union nf_inet_addr ip;
394 /* Common functions */
397 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
398 const struct hash_netiface6_elem *ip2,
401 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
402 ip1->cidr == ip2->cidr &&
404 ip1->physdev == ip2->physdev &&
405 ip1->iface == ip2->iface;
409 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
411 return elem->nomatch ? -ENOTEMPTY : 1;
415 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
417 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
421 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
423 swap(*flags, elem->nomatch);
427 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
429 ip6_netmask(&elem->ip, cidr);
434 hash_netiface6_data_list(struct sk_buff *skb,
435 const struct hash_netiface6_elem *data)
437 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
440 flags |= IPSET_FLAG_NOMATCH;
441 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
442 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) ||
443 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) ||
445 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
446 goto nla_put_failure;
454 hash_netiface6_data_next(struct hash_netiface4_elem *next,
455 const struct hash_netiface6_elem *d)
464 #define MTYPE hash_netiface6
466 #define HOST_MASK 128
467 #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
468 #define IP_SET_EMIT_CREATE
469 #include "ip_set_hash_gen.h"
472 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
473 const struct xt_action_param *par,
474 enum ipset_adt adt, struct ip_set_adt_opt *opt)
476 struct hash_netiface *h = set->data;
477 ipset_adtfn adtfn = set->variant->adt[adt];
478 struct hash_netiface6_elem e = {
479 .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
482 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
487 if (adt == IPSET_TEST)
490 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
491 ip6_netmask(&e.ip, e.cidr);
493 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
494 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
495 e.iface = SRCDIR ? get_physindev_name(skb) :
496 get_phyoutdev_name(skb);
505 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
509 ret = iface_test(&h->rbtree, &e.iface);
510 if (adt == IPSET_ADD) {
512 ret = iface_add(&h->rbtree, &e.iface);
519 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
523 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
524 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
526 struct hash_netiface *h = set->data;
527 ipset_adtfn adtfn = set->variant->adt[adt];
528 struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
529 struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
530 char iface[IFNAMSIZ];
533 if (unlikely(!tb[IPSET_ATTR_IP] ||
534 !tb[IPSET_ATTR_IFACE] ||
535 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
536 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
537 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
538 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
539 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
540 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
541 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
542 return -IPSET_ERR_PROTOCOL;
543 if (unlikely(tb[IPSET_ATTR_IP_TO]))
544 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
546 if (tb[IPSET_ATTR_LINENO])
547 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
549 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
550 ip_set_get_extensions(set, tb, &ext);
554 if (tb[IPSET_ATTR_CIDR])
555 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
556 if (e.cidr > HOST_MASK)
557 return -IPSET_ERR_INVALID_CIDR;
558 ip6_netmask(&e.ip, e.cidr);
560 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
562 ret = iface_test(&h->rbtree, &e.iface);
563 if (adt == IPSET_ADD) {
565 ret = iface_add(&h->rbtree, &e.iface);
572 if (tb[IPSET_ATTR_CADT_FLAGS]) {
573 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
574 if (cadt_flags & IPSET_FLAG_PHYSDEV)
576 if (cadt_flags & IPSET_FLAG_NOMATCH)
577 flags |= (IPSET_FLAG_NOMATCH << 16);
580 ret = adtfn(set, &e, &ext, &ext, flags);
582 return ip_set_enomatch(ret, flags, adt, set) ? -ret :
583 ip_set_eexist(ret, flags) ? 0 : ret;
586 static struct ip_set_type hash_netiface_type __read_mostly = {
587 .name = "hash:net,iface",
588 .protocol = IPSET_PROTOCOL,
589 .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE |
591 .dimension = IPSET_DIM_TWO,
592 .family = NFPROTO_UNSPEC,
593 .revision_min = IPSET_TYPE_REV_MIN,
594 .revision_max = IPSET_TYPE_REV_MAX,
595 .create = hash_netiface_create,
597 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
598 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
599 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
600 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
601 [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
602 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
603 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
606 [IPSET_ATTR_IP] = { .type = NLA_NESTED },
607 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
608 [IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING,
609 .len = IFNAMSIZ - 1 },
610 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
611 [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
612 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
613 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
614 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
615 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
616 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
617 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
618 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
619 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
625 hash_netiface_init(void)
627 return ip_set_type_register(&hash_netiface_type);
631 hash_netiface_fini(void)
633 ip_set_type_unregister(&hash_netiface_type);
636 module_init(hash_netiface_init);
637 module_exit(hash_netiface_fini);