1/* Copyright (C) 2003-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,port 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 <net/ip.h> 17#include <net/ipv6.h> 18#include <net/netlink.h> 19 20#include <linux/netfilter.h> 21#include <linux/netfilter/ipset/pfxlen.h> 22#include <linux/netfilter/ipset/ip_set.h> 23#include <linux/netfilter/ipset/ip_set_getport.h> 24#include <linux/netfilter/ipset/ip_set_hash.h> 25 26#define REVISION_MIN 0 27/* 1 SCTP and UDPLITE support added */ 28/* 2 Range as input support for IPv4 added */ 29/* 3 nomatch flag support added */ 30#define REVISION_MAX 4 /* Counters support added */ 31 32MODULE_LICENSE("GPL"); 33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 34IP_SET_MODULE_DESC("hash:net,port", REVISION_MIN, REVISION_MAX); 35MODULE_ALIAS("ip_set_hash:net,port"); 36 37/* Type specific function prefix */ 38#define HTYPE hash_netport 39#define IP_SET_HASH_WITH_PROTO 40#define IP_SET_HASH_WITH_NETS 41 42/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0 43 * However this way we have to store internally cidr - 1, 44 * dancing back and forth. 45 */ 46#define IP_SET_HASH_WITH_NETS_PACKED 47 48/* IPv4 variants */ 49 50/* Member elements */ 51struct hash_netport4_elem { 52 __be32 ip; 53 __be16 port; 54 u8 proto; 55 u8 cidr:7; 56 u8 nomatch:1; 57}; 58 59struct hash_netport4t_elem { 60 __be32 ip; 61 __be16 port; 62 u8 proto; 63 u8 cidr:7; 64 u8 nomatch:1; 65 unsigned long timeout; 66}; 67 68struct hash_netport4c_elem { 69 __be32 ip; 70 __be16 port; 71 u8 proto; 72 u8 cidr:7; 73 u8 nomatch:1; 74 struct ip_set_counter counter; 75}; 76 77struct hash_netport4ct_elem { 78 __be32 ip; 79 __be16 port; 80 u8 proto; 81 u8 cidr:7; 82 u8 nomatch:1; 83 struct ip_set_counter counter; 84 unsigned long timeout; 85}; 86 87/* Common functions */ 88 89static inline bool 90hash_netport4_data_equal(const struct hash_netport4_elem *ip1, 91 const struct hash_netport4_elem *ip2, 92 u32 *multi) 93{ 94 return ip1->ip == ip2->ip && 95 ip1->port == ip2->port && 96 ip1->proto == ip2->proto && 97 ip1->cidr == ip2->cidr; 98} 99 100static inline int 101hash_netport4_do_data_match(const struct hash_netport4_elem *elem) 102{ 103 return elem->nomatch ? -ENOTEMPTY : 1; 104} 105 106static inline void 107hash_netport4_data_set_flags(struct hash_netport4_elem *elem, u32 flags) 108{ 109 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 110} 111 112static inline void 113hash_netport4_data_reset_flags(struct hash_netport4_elem *elem, u8 *flags) 114{ 115 swap(*flags, elem->nomatch); 116} 117 118static inline void 119hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr) 120{ 121 elem->ip &= ip_set_netmask(cidr); 122 elem->cidr = cidr - 1; 123} 124 125static bool 126hash_netport4_data_list(struct sk_buff *skb, 127 const struct hash_netport4_elem *data) 128{ 129 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 130 131 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || 132 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 133 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) || 134 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 135 (flags && 136 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 137 goto nla_put_failure; 138 return 0; 139 140nla_put_failure: 141 return 1; 142} 143 144static inline void 145hash_netport4_data_next(struct hash_netport4_elem *next, 146 const struct hash_netport4_elem *d) 147{ 148 next->ip = d->ip; 149 next->port = d->port; 150} 151 152#define MTYPE hash_netport4 153#define PF 4 154#define HOST_MASK 32 155#include "ip_set_hash_gen.h" 156 157static int 158hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, 159 const struct xt_action_param *par, 160 enum ipset_adt adt, struct ip_set_adt_opt *opt) 161{ 162 const struct hash_netport *h = set->data; 163 ipset_adtfn adtfn = set->variant->adt[adt]; 164 struct hash_netport4_elem e = { 165 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1 166 }; 167 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 168 169 if (adt == IPSET_TEST) 170 e.cidr = HOST_MASK - 1; 171 172 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 173 &e.port, &e.proto)) 174 return -EINVAL; 175 176 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 177 e.ip &= ip_set_netmask(e.cidr + 1); 178 179 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 180} 181 182static int 183hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], 184 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 185{ 186 const struct hash_netport *h = set->data; 187 ipset_adtfn adtfn = set->variant->adt[adt]; 188 struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 }; 189 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 190 u32 port, port_to, p = 0, ip = 0, ip_to, last; 191 bool with_ports = false; 192 u8 cidr; 193 int ret; 194 195 if (unlikely(!tb[IPSET_ATTR_IP] || 196 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 197 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 198 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 199 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 200 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 201 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 202 return -IPSET_ERR_PROTOCOL; 203 204 if (tb[IPSET_ATTR_LINENO]) 205 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 206 207 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) || 208 ip_set_get_extensions(set, tb, &ext); 209 if (ret) 210 return ret; 211 212 if (tb[IPSET_ATTR_CIDR]) { 213 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 214 if (!cidr || cidr > HOST_MASK) 215 return -IPSET_ERR_INVALID_CIDR; 216 e.cidr = cidr - 1; 217 } 218 219 if (tb[IPSET_ATTR_PORT]) 220 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 221 else 222 return -IPSET_ERR_PROTOCOL; 223 224 if (tb[IPSET_ATTR_PROTO]) { 225 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 226 with_ports = ip_set_proto_with_ports(e.proto); 227 228 if (e.proto == 0) 229 return -IPSET_ERR_INVALID_PROTO; 230 } else 231 return -IPSET_ERR_MISSING_PROTO; 232 233 if (!(with_ports || e.proto == IPPROTO_ICMP)) 234 e.port = 0; 235 236 with_ports = with_ports && tb[IPSET_ATTR_PORT_TO]; 237 238 if (tb[IPSET_ATTR_CADT_FLAGS]) { 239 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 240 if (cadt_flags & IPSET_FLAG_NOMATCH) 241 flags |= (IPSET_FLAG_NOMATCH << 16); 242 } 243 244 if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) { 245 e.ip = htonl(ip & ip_set_hostmask(e.cidr + 1)); 246 ret = adtfn(set, &e, &ext, &ext, flags); 247 return ip_set_enomatch(ret, flags, adt) ? 1 : 248 ip_set_eexist(ret, flags) ? 0 : ret; 249 } 250 251 port = port_to = ntohs(e.port); 252 if (tb[IPSET_ATTR_PORT_TO]) { 253 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 254 if (port_to < port) 255 swap(port, port_to); 256 } 257 if (tb[IPSET_ATTR_IP_TO]) { 258 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 259 if (ret) 260 return ret; 261 if (ip_to < ip) 262 swap(ip, ip_to); 263 if (ip + UINT_MAX == ip_to) 264 return -IPSET_ERR_HASH_RANGE; 265 } else 266 ip_set_mask_from_to(ip, ip_to, e.cidr + 1); 267 268 if (retried) 269 ip = ntohl(h->next.ip); 270 while (!after(ip, ip_to)) { 271 e.ip = htonl(ip); 272 last = ip_set_range_to_cidr(ip, ip_to, &cidr); 273 e.cidr = cidr - 1; 274 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 275 : port; 276 for (; p <= port_to; p++) { 277 e.port = htons(p); 278 ret = adtfn(set, &e, &ext, &ext, flags); 279 280 if (ret && !ip_set_eexist(ret, flags)) 281 return ret; 282 else 283 ret = 0; 284 } 285 ip = last + 1; 286 } 287 return ret; 288} 289 290/* IPv6 variants */ 291 292struct hash_netport6_elem { 293 union nf_inet_addr ip; 294 __be16 port; 295 u8 proto; 296 u8 cidr:7; 297 u8 nomatch:1; 298}; 299 300struct hash_netport6t_elem { 301 union nf_inet_addr ip; 302 __be16 port; 303 u8 proto; 304 u8 cidr:7; 305 u8 nomatch:1; 306 unsigned long timeout; 307}; 308 309struct hash_netport6c_elem { 310 union nf_inet_addr ip; 311 __be16 port; 312 u8 proto; 313 u8 cidr:7; 314 u8 nomatch:1; 315 struct ip_set_counter counter; 316}; 317 318struct hash_netport6ct_elem { 319 union nf_inet_addr ip; 320 __be16 port; 321 u8 proto; 322 u8 cidr:7; 323 u8 nomatch:1; 324 struct ip_set_counter counter; 325 unsigned long timeout; 326}; 327 328/* Common functions */ 329 330static inline bool 331hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 332 const struct hash_netport6_elem *ip2, 333 u32 *multi) 334{ 335 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 336 ip1->port == ip2->port && 337 ip1->proto == ip2->proto && 338 ip1->cidr == ip2->cidr; 339} 340 341static inline int 342hash_netport6_do_data_match(const struct hash_netport6_elem *elem) 343{ 344 return elem->nomatch ? -ENOTEMPTY : 1; 345} 346 347static inline void 348hash_netport6_data_set_flags(struct hash_netport6_elem *elem, u32 flags) 349{ 350 elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH); 351} 352 353static inline void 354hash_netport6_data_reset_flags(struct hash_netport6_elem *elem, u8 *flags) 355{ 356 swap(*flags, elem->nomatch); 357} 358 359static inline void 360hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr) 361{ 362 ip6_netmask(&elem->ip, cidr); 363 elem->cidr = cidr - 1; 364} 365 366static bool 367hash_netport6_data_list(struct sk_buff *skb, 368 const struct hash_netport6_elem *data) 369{ 370 u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 371 372 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 373 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 374 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr + 1) || 375 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) || 376 (flags && 377 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 378 goto nla_put_failure; 379 return 0; 380 381nla_put_failure: 382 return 1; 383} 384 385static inline void 386hash_netport6_data_next(struct hash_netport4_elem *next, 387 const struct hash_netport6_elem *d) 388{ 389 next->port = d->port; 390} 391 392#undef MTYPE 393#undef PF 394#undef HOST_MASK 395 396#define MTYPE hash_netport6 397#define PF 6 398#define HOST_MASK 128 399#define IP_SET_EMIT_CREATE 400#include "ip_set_hash_gen.h" 401 402static int 403hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, 404 const struct xt_action_param *par, 405 enum ipset_adt adt, struct ip_set_adt_opt *opt) 406{ 407 const struct hash_netport *h = set->data; 408 ipset_adtfn adtfn = set->variant->adt[adt]; 409 struct hash_netport6_elem e = { 410 .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1, 411 }; 412 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 413 414 if (adt == IPSET_TEST) 415 e.cidr = HOST_MASK - 1; 416 417 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 418 &e.port, &e.proto)) 419 return -EINVAL; 420 421 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 422 ip6_netmask(&e.ip, e.cidr + 1); 423 424 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 425} 426 427static int 428hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], 429 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 430{ 431 const struct hash_netport *h = set->data; 432 ipset_adtfn adtfn = set->variant->adt[adt]; 433 struct hash_netport6_elem e = { .cidr = HOST_MASK - 1 }; 434 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 435 u32 port, port_to; 436 bool with_ports = false; 437 u8 cidr; 438 int ret; 439 440 if (unlikely(!tb[IPSET_ATTR_IP] || 441 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 442 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 443 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 444 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 445 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 446 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 447 return -IPSET_ERR_PROTOCOL; 448 if (unlikely(tb[IPSET_ATTR_IP_TO])) 449 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 450 451 if (tb[IPSET_ATTR_LINENO]) 452 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 453 454 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) || 455 ip_set_get_extensions(set, tb, &ext); 456 if (ret) 457 return ret; 458 459 if (tb[IPSET_ATTR_CIDR]) { 460 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 461 if (!cidr || cidr > HOST_MASK) 462 return -IPSET_ERR_INVALID_CIDR; 463 e.cidr = cidr - 1; 464 } 465 ip6_netmask(&e.ip, e.cidr + 1); 466 467 if (tb[IPSET_ATTR_PORT]) 468 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 469 else 470 return -IPSET_ERR_PROTOCOL; 471 472 if (tb[IPSET_ATTR_PROTO]) { 473 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 474 with_ports = ip_set_proto_with_ports(e.proto); 475 476 if (e.proto == 0) 477 return -IPSET_ERR_INVALID_PROTO; 478 } else 479 return -IPSET_ERR_MISSING_PROTO; 480 481 if (!(with_ports || e.proto == IPPROTO_ICMPV6)) 482 e.port = 0; 483 484 if (tb[IPSET_ATTR_CADT_FLAGS]) { 485 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 486 if (cadt_flags & IPSET_FLAG_NOMATCH) 487 flags |= (IPSET_FLAG_NOMATCH << 16); 488 } 489 490 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 491 ret = adtfn(set, &e, &ext, &ext, flags); 492 return ip_set_enomatch(ret, flags, adt) ? 1 : 493 ip_set_eexist(ret, flags) ? 0 : ret; 494 } 495 496 port = ntohs(e.port); 497 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 498 if (port > port_to) 499 swap(port, port_to); 500 501 if (retried) 502 port = ntohs(h->next.port); 503 for (; port <= port_to; port++) { 504 e.port = htons(port); 505 ret = adtfn(set, &e, &ext, &ext, flags); 506 507 if (ret && !ip_set_eexist(ret, flags)) 508 return ret; 509 else 510 ret = 0; 511 } 512 return ret; 513} 514 515static struct ip_set_type hash_netport_type __read_mostly = { 516 .name = "hash:net,port", 517 .protocol = IPSET_PROTOCOL, 518 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_NOMATCH, 519 .dimension = IPSET_DIM_TWO, 520 .family = NFPROTO_UNSPEC, 521 .revision_min = REVISION_MIN, 522 .revision_max = REVISION_MAX, 523 .create = hash_netport_create, 524 .create_policy = { 525 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 526 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 527 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 528 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 529 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 530 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 531 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 532 }, 533 .adt_policy = { 534 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 535 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 536 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 537 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 538 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 539 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 540 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 541 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 542 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 543 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 544 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 545 }, 546 .me = THIS_MODULE, 547}; 548 549static int __init 550hash_netport_init(void) 551{ 552 return ip_set_type_register(&hash_netport_type); 553} 554 555static void __exit 556hash_netport_fini(void) 557{ 558 ip_set_type_unregister(&hash_netport_type); 559} 560 561module_init(hash_netport_init); 562module_exit(hash_netport_fini); 563