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/ipset/pfxlen.h>
23 #include <linux/netfilter/ipset/ip_set.h>
24 #include <linux/netfilter/ipset/ip_set_hash.h>
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 */
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");
37 /* Interface name rbtree */
44 #define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
47 rbtree_destroy(struct rb_root *root)
49 struct iface_node *node, *next;
51 rbtree_postorder_for_each_entry_safe(node, next, root, node)
58 iface_test(struct rb_root *root, const char **iface)
60 struct rb_node *n = root->rb_node;
63 const char *d = iface_data(n);
64 int res = strcmp(*iface, d);
79 iface_add(struct rb_root *root, const char **iface)
81 struct rb_node **n = &(root->rb_node), *p = NULL;
85 char *ifname = iface_data(*n);
86 int res = strcmp(*iface, ifname);
92 n = &((*n)->rb_right);
99 d = kzalloc(sizeof(*d), GFP_ATOMIC);
102 strcpy(d->iface, *iface);
104 rb_link_node(&d->node, p, n);
105 rb_insert_color(&d->node, root);
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
117 #define STREQ(a, b) (strcmp(a, b) == 0)
121 struct hash_netiface4_elem_hashed {
129 /* Member elements */
130 struct hash_netiface4_elem {
139 /* Common functions */
142 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
143 const struct hash_netiface4_elem *ip2,
146 return ip1->ip == ip2->ip &&
147 ip1->cidr == ip2->cidr &&
149 ip1->physdev == ip2->physdev &&
150 ip1->iface == ip2->iface;
154 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem)
156 return elem->nomatch ? -ENOTEMPTY : 1;
160 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags)
162 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
166 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags)
168 swap(*flags, elem->nomatch);
172 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
174 elem->ip &= ip_set_netmask(cidr);
179 hash_netiface4_data_list(struct sk_buff *skb,
180 const struct hash_netiface4_elem *data)
182 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
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) ||
190 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
191 goto nla_put_failure;
199 hash_netiface4_data_next(struct hash_netiface4_elem *next,
200 const struct hash_netiface4_elem *d)
205 #define MTYPE hash_netiface4
208 #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
209 #include "ip_set_hash_gen.h"
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)
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),
222 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
227 if (adt == IPSET_TEST)
230 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
231 e.ip &= ip_set_netmask(e.cidr);
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)
237 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
238 #ifdef CONFIG_BRIDGE_NETFILTER
239 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
243 e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
249 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
253 ret = iface_test(&h->rbtree, &e.iface);
254 if (adt == IPSET_ADD) {
256 ret = iface_add(&h->rbtree, &e.iface);
263 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
267 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
268 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
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];
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;
286 if (tb[IPSET_ATTR_LINENO])
287 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
289 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
290 ip_set_get_extensions(set, tb, &ext);
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;
300 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
302 ret = iface_test(&h->rbtree, &e.iface);
303 if (adt == IPSET_ADD) {
305 ret = iface_add(&h->rbtree, &e.iface);
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)
316 if (cadt_flags & IPSET_FLAG_NOMATCH)
317 flags |= (IPSET_FLAG_NOMATCH << 16);
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;
326 if (tb[IPSET_ATTR_IP_TO]) {
327 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
332 if (ip + UINT_MAX == ip_to)
333 return -IPSET_ERR_HASH_RANGE;
335 ip_set_mask_from_to(ip, ip_to, e.cidr);
338 ip = ntohl(h->next.ip);
339 while (!after(ip, ip_to)) {
341 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
342 ret = adtfn(set, &e, &ext, &ext, flags);
344 if (ret && !ip_set_eexist(ret, flags))
355 struct hash_netiface6_elem_hashed {
356 union nf_inet_addr ip;
363 struct hash_netiface6_elem {
364 union nf_inet_addr ip;
372 /* Common functions */
375 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
376 const struct hash_netiface6_elem *ip2,
379 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
380 ip1->cidr == ip2->cidr &&
382 ip1->physdev == ip2->physdev &&
383 ip1->iface == ip2->iface;
387 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem)
389 return elem->nomatch ? -ENOTEMPTY : 1;
393 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags)
395 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
399 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags)
401 swap(*flags, elem->nomatch);
405 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
407 ip6_netmask(&elem->ip, cidr);
412 hash_netiface6_data_list(struct sk_buff *skb,
413 const struct hash_netiface6_elem *data)
415 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
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) ||
423 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
424 goto nla_put_failure;
432 hash_netiface6_data_next(struct hash_netiface4_elem *next,
433 const struct hash_netiface6_elem *d)
442 #define MTYPE hash_netiface6
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"
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)
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),
460 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
465 if (adt == IPSET_TEST)
468 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
469 ip6_netmask(&e.ip, e.cidr);
471 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
472 #ifdef CONFIG_BRIDGE_NETFILTER
473 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
477 e.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
483 e.iface = SRCDIR ? IFACE(in) : IFACE(out);
487 ret = iface_test(&h->rbtree, &e.iface);
488 if (adt == IPSET_ADD) {
490 ret = iface_add(&h->rbtree, &e.iface);
497 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
501 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
502 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
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];
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;
521 if (tb[IPSET_ATTR_LINENO])
522 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
524 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
525 ip_set_get_extensions(set, tb, &ext);
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);
535 strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
537 ret = iface_test(&h->rbtree, &e.iface);
538 if (adt == IPSET_ADD) {
540 ret = iface_add(&h->rbtree, &e.iface);
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)
551 if (cadt_flags & IPSET_FLAG_NOMATCH)
552 flags |= (IPSET_FLAG_NOMATCH << 16);
555 ret = adtfn(set, &e, &ext, &ext, flags);
557 return ip_set_enomatch(ret, flags, adt, set) ? -ret :
558 ip_set_eexist(ret, flags) ? 0 : ret;
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 |
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,
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 },
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 },
597 hash_netiface_init(void)
599 return ip_set_type_register(&hash_netiface_type);
603 hash_netiface_fini(void)
605 ip_set_type_unregister(&hash_netiface_type);
608 module_init(hash_netiface_init);
609 module_exit(hash_netiface_fini);