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:ip,port,ip 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#include <net/tcp.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_getport.h> 25#include <linux/netfilter/ipset/ip_set_hash.h> 26 27#define REVISION_MIN 0 28/* 1 SCTP and UDPLITE support added */ 29#define REVISION_MAX 2 /* Counters support added */ 30 31MODULE_LICENSE("GPL"); 32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 33IP_SET_MODULE_DESC("hash:ip,port,ip", REVISION_MIN, REVISION_MAX); 34MODULE_ALIAS("ip_set_hash:ip,port,ip"); 35 36/* Type specific function prefix */ 37#define HTYPE hash_ipportip 38 39/* IPv4 variants */ 40 41/* Member elements */ 42struct hash_ipportip4_elem { 43 __be32 ip; 44 __be32 ip2; 45 __be16 port; 46 u8 proto; 47 u8 padding; 48}; 49 50struct hash_ipportip4t_elem { 51 __be32 ip; 52 __be32 ip2; 53 __be16 port; 54 u8 proto; 55 u8 padding; 56 unsigned long timeout; 57}; 58 59struct hash_ipportip4c_elem { 60 __be32 ip; 61 __be32 ip2; 62 __be16 port; 63 u8 proto; 64 u8 padding; 65 struct ip_set_counter counter; 66}; 67 68struct hash_ipportip4ct_elem { 69 __be32 ip; 70 __be32 ip2; 71 __be16 port; 72 u8 proto; 73 u8 padding; 74 struct ip_set_counter counter; 75 unsigned long timeout; 76}; 77 78static inline bool 79hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, 80 const struct hash_ipportip4_elem *ip2, 81 u32 *multi) 82{ 83 return ip1->ip == ip2->ip && 84 ip1->ip2 == ip2->ip2 && 85 ip1->port == ip2->port && 86 ip1->proto == ip2->proto; 87} 88 89static bool 90hash_ipportip4_data_list(struct sk_buff *skb, 91 const struct hash_ipportip4_elem *data) 92{ 93 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || 94 nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) || 95 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 96 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto)) 97 goto nla_put_failure; 98 return 0; 99 100nla_put_failure: 101 return 1; 102} 103 104static inline void 105hash_ipportip4_data_next(struct hash_ipportip4_elem *next, 106 const struct hash_ipportip4_elem *d) 107{ 108 next->ip = d->ip; 109 next->port = d->port; 110} 111 112/* Common functions */ 113#define MTYPE hash_ipportip4 114#define PF 4 115#define HOST_MASK 32 116#include "ip_set_hash_gen.h" 117 118static int 119hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, 120 const struct xt_action_param *par, 121 enum ipset_adt adt, struct ip_set_adt_opt *opt) 122{ 123 const struct hash_ipportip *h = set->data; 124 ipset_adtfn adtfn = set->variant->adt[adt]; 125 struct hash_ipportip4_elem e = { }; 126 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 127 128 if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 129 &e.port, &e.proto)) 130 return -EINVAL; 131 132 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 133 ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2); 134 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 135} 136 137static int 138hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], 139 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 140{ 141 const struct hash_ipportip *h = set->data; 142 ipset_adtfn adtfn = set->variant->adt[adt]; 143 struct hash_ipportip4_elem e = { }; 144 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 145 u32 ip, ip_to, p = 0, port, port_to; 146 bool with_ports = false; 147 int ret; 148 149 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 150 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 151 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 152 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 153 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 154 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 155 return -IPSET_ERR_PROTOCOL; 156 157 if (tb[IPSET_ATTR_LINENO]) 158 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 159 160 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip) || 161 ip_set_get_extensions(set, tb, &ext); 162 if (ret) 163 return ret; 164 165 ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &e.ip2); 166 if (ret) 167 return ret; 168 169 if (tb[IPSET_ATTR_PORT]) 170 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 171 else 172 return -IPSET_ERR_PROTOCOL; 173 174 if (tb[IPSET_ATTR_PROTO]) { 175 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 176 with_ports = ip_set_proto_with_ports(e.proto); 177 178 if (e.proto == 0) 179 return -IPSET_ERR_INVALID_PROTO; 180 } else 181 return -IPSET_ERR_MISSING_PROTO; 182 183 if (!(with_ports || e.proto == IPPROTO_ICMP)) 184 e.port = 0; 185 186 if (adt == IPSET_TEST || 187 !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 188 tb[IPSET_ATTR_PORT_TO])) { 189 ret = adtfn(set, &e, &ext, &ext, flags); 190 return ip_set_eexist(ret, flags) ? 0 : ret; 191 } 192 193 ip_to = ip = ntohl(e.ip); 194 if (tb[IPSET_ATTR_IP_TO]) { 195 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 196 if (ret) 197 return ret; 198 if (ip > ip_to) 199 swap(ip, ip_to); 200 } else if (tb[IPSET_ATTR_CIDR]) { 201 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 202 203 if (!cidr || cidr > 32) 204 return -IPSET_ERR_INVALID_CIDR; 205 ip_set_mask_from_to(ip, ip_to, cidr); 206 } 207 208 port_to = port = ntohs(e.port); 209 if (with_ports && tb[IPSET_ATTR_PORT_TO]) { 210 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 211 if (port > port_to) 212 swap(port, port_to); 213 } 214 215 if (retried) 216 ip = ntohl(h->next.ip); 217 for (; !before(ip_to, ip); ip++) { 218 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) 219 : port; 220 for (; p <= port_to; p++) { 221 e.ip = htonl(ip); 222 e.port = htons(p); 223 ret = adtfn(set, &e, &ext, &ext, flags); 224 225 if (ret && !ip_set_eexist(ret, flags)) 226 return ret; 227 else 228 ret = 0; 229 } 230 } 231 return ret; 232} 233 234/* IPv6 variants */ 235 236struct hash_ipportip6_elem { 237 union nf_inet_addr ip; 238 union nf_inet_addr ip2; 239 __be16 port; 240 u8 proto; 241 u8 padding; 242}; 243 244struct hash_ipportip6t_elem { 245 union nf_inet_addr ip; 246 union nf_inet_addr ip2; 247 __be16 port; 248 u8 proto; 249 u8 padding; 250 unsigned long timeout; 251}; 252 253struct hash_ipportip6c_elem { 254 union nf_inet_addr ip; 255 union nf_inet_addr ip2; 256 __be16 port; 257 u8 proto; 258 u8 padding; 259 struct ip_set_counter counter; 260}; 261 262struct hash_ipportip6ct_elem { 263 union nf_inet_addr ip; 264 union nf_inet_addr ip2; 265 __be16 port; 266 u8 proto; 267 u8 padding; 268 struct ip_set_counter counter; 269 unsigned long timeout; 270}; 271 272/* Common functions */ 273 274static inline bool 275hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 276 const struct hash_ipportip6_elem *ip2, 277 u32 *multi) 278{ 279 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 280 ipv6_addr_equal(&ip1->ip2.in6, &ip2->ip2.in6) && 281 ip1->port == ip2->port && 282 ip1->proto == ip2->proto; 283} 284 285static bool 286hash_ipportip6_data_list(struct sk_buff *skb, 287 const struct hash_ipportip6_elem *data) 288{ 289 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 290 nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) || 291 nla_put_net16(skb, IPSET_ATTR_PORT, data->port) || 292 nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto)) 293 goto nla_put_failure; 294 return 0; 295 296nla_put_failure: 297 return 1; 298} 299 300static inline void 301hash_ipportip6_data_next(struct hash_ipportip4_elem *next, 302 const struct hash_ipportip6_elem *d) 303{ 304 next->port = d->port; 305} 306 307#undef MTYPE 308#undef PF 309#undef HOST_MASK 310 311#define MTYPE hash_ipportip6 312#define PF 6 313#define HOST_MASK 128 314#define IP_SET_EMIT_CREATE 315#include "ip_set_hash_gen.h" 316 317static int 318hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, 319 const struct xt_action_param *par, 320 enum ipset_adt adt, struct ip_set_adt_opt *opt) 321{ 322 const struct hash_ipportip *h = set->data; 323 ipset_adtfn adtfn = set->variant->adt[adt]; 324 struct hash_ipportip6_elem e = { }; 325 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 326 327 if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, 328 &e.port, &e.proto)) 329 return -EINVAL; 330 331 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 332 ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6); 333 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 334} 335 336static int 337hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], 338 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 339{ 340 const struct hash_ipportip *h = set->data; 341 ipset_adtfn adtfn = set->variant->adt[adt]; 342 struct hash_ipportip6_elem e = { }; 343 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 344 u32 port, port_to; 345 bool with_ports = false; 346 int ret; 347 348 if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 349 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 350 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 351 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 352 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 353 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 354 tb[IPSET_ATTR_IP_TO] || 355 tb[IPSET_ATTR_CIDR])) 356 return -IPSET_ERR_PROTOCOL; 357 358 if (tb[IPSET_ATTR_LINENO]) 359 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 360 361 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) || 362 ip_set_get_extensions(set, tb, &ext); 363 if (ret) 364 return ret; 365 366 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2); 367 if (ret) 368 return ret; 369 370 if (tb[IPSET_ATTR_PORT]) 371 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 372 else 373 return -IPSET_ERR_PROTOCOL; 374 375 if (tb[IPSET_ATTR_PROTO]) { 376 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 377 with_ports = ip_set_proto_with_ports(e.proto); 378 379 if (e.proto == 0) 380 return -IPSET_ERR_INVALID_PROTO; 381 } else 382 return -IPSET_ERR_MISSING_PROTO; 383 384 if (!(with_ports || e.proto == IPPROTO_ICMPV6)) 385 e.port = 0; 386 387 if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { 388 ret = adtfn(set, &e, &ext, &ext, flags); 389 return ip_set_eexist(ret, flags) ? 0 : ret; 390 } 391 392 port = ntohs(e.port); 393 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 394 if (port > port_to) 395 swap(port, port_to); 396 397 if (retried) 398 port = ntohs(h->next.port); 399 for (; port <= port_to; port++) { 400 e.port = htons(port); 401 ret = adtfn(set, &e, &ext, &ext, flags); 402 403 if (ret && !ip_set_eexist(ret, flags)) 404 return ret; 405 else 406 ret = 0; 407 } 408 return ret; 409} 410 411static struct ip_set_type hash_ipportip_type __read_mostly = { 412 .name = "hash:ip,port,ip", 413 .protocol = IPSET_PROTOCOL, 414 .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, 415 .dimension = IPSET_DIM_THREE, 416 .family = NFPROTO_UNSPEC, 417 .revision_min = REVISION_MIN, 418 .revision_max = REVISION_MAX, 419 .create = hash_ipportip_create, 420 .create_policy = { 421 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 422 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 423 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 424 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 425 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 426 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 427 }, 428 .adt_policy = { 429 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 430 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 431 [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 432 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 433 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 434 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 435 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 436 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 437 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 438 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 439 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 440 }, 441 .me = THIS_MODULE, 442}; 443 444static int __init 445hash_ipportip_init(void) 446{ 447 return ip_set_type_register(&hash_ipportip_type); 448} 449 450static void __exit 451hash_ipportip_fini(void) 452{ 453 ip_set_type_unregister(&hash_ipportip_type); 454} 455 456module_init(hash_ipportip_init); 457module_exit(hash_ipportip_fini); 458