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