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