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 <net/ip.h> 17 #include <net/ipv6.h> 18 #include <net/netlink.h> 19 20 #include <linux/netfilter.h> 21 #include <linux/netfilter_bridge.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 34 MODULE_LICENSE("GPL"); 35 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 36 IP_SET_MODULE_DESC("hash:net,iface", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 37 MODULE_ALIAS("ip_set_hash:net,iface"); 38 39 /* Type specific function prefix */ 40 #define HTYPE hash_netiface 41 #define IP_SET_HASH_WITH_NETS 42 #define IP_SET_HASH_WITH_MULTI 43 #define IP_SET_HASH_WITH_NET0 44 45 #define STRLCPY(a, b) strlcpy(a, b, IFNAMSIZ) 46 47 /* IPv4 variant */ 48 49 struct hash_netiface4_elem_hashed { 50 __be32 ip; 51 u8 physdev; 52 u8 cidr; 53 u8 nomatch; 54 u8 elem; 55 }; 56 57 /* Member elements */ 58 struct hash_netiface4_elem { 59 __be32 ip; 60 u8 physdev; 61 u8 cidr; 62 u8 nomatch; 63 u8 elem; 64 char iface[IFNAMSIZ]; 65 }; 66 67 /* Common functions */ 68 69 static inline bool 70 hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1, 71 const struct hash_netiface4_elem *ip2, 72 u32 *multi) 73 { 74 return ip1->ip == ip2->ip && 75 ip1->cidr == ip2->cidr && 76 (++*multi) && 77 ip1->physdev == ip2->physdev && 78 strcmp(ip1->iface, ip2->iface) == 0; 79 } 80 81 static inline int 82 hash_netiface4_do_data_match(const struct hash_netiface4_elem *elem) 83 { 84 return elem->nomatch ? -ENOTEMPTY : 1; 85 } 86 87 static inline void 88 hash_netiface4_data_set_flags(struct hash_netiface4_elem *elem, u32 flags) 89 { 90 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 91 } 92 93 static inline void 94 hash_netiface4_data_reset_flags(struct hash_netiface4_elem *elem, u8 *flags) 95 { 96 swap(*flags, elem->nomatch); 97 } 98 99 static inline void 100 hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr) 101 { 102 elem->ip &= ip_set_netmask(cidr); 103 elem->cidr = cidr; 104 } 105 106 static bool 107 hash_netiface4_data_list(struct sk_buff *skb, 108 const struct hash_netiface4_elem *data) 109 { 110 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 111 112 if (data->nomatch) 113 flags |= IPSET_FLAG_NOMATCH; 114 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || 115 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || 116 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || 117 (flags && 118 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 119 goto nla_put_failure; 120 return false; 121 122 nla_put_failure: 123 return true; 124 } 125 126 static inline void 127 hash_netiface4_data_next(struct hash_netiface4_elem *next, 128 const struct hash_netiface4_elem *d) 129 { 130 next->ip = d->ip; 131 } 132 133 #define MTYPE hash_netiface4 134 #define HOST_MASK 32 135 #define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed) 136 #include "ip_set_hash_gen.h" 137 138 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 139 static const char *get_physindev_name(const struct sk_buff *skb) 140 { 141 struct net_device *dev = nf_bridge_get_physindev(skb); 142 143 return dev ? dev->name : NULL; 144 } 145 146 static const char *get_physoutdev_name(const struct sk_buff *skb) 147 { 148 struct net_device *dev = nf_bridge_get_physoutdev(skb); 149 150 return dev ? dev->name : NULL; 151 } 152 #endif 153 154 static int 155 hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb, 156 const struct xt_action_param *par, 157 enum ipset_adt adt, struct ip_set_adt_opt *opt) 158 { 159 struct hash_netiface4 *h = set->data; 160 ipset_adtfn adtfn = set->variant->adt[adt]; 161 struct hash_netiface4_elem e = { 162 .cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 163 .elem = 1, 164 }; 165 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 166 167 if (adt == IPSET_TEST) 168 e.cidr = HOST_MASK; 169 170 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 171 e.ip &= ip_set_netmask(e.cidr); 172 173 #define IFACE(dir) (par->state->dir ? par->state->dir->name : "") 174 #define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC) 175 176 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 177 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 178 const char *eiface = SRCDIR ? get_physindev_name(skb) : 179 get_physoutdev_name(skb); 180 181 if (!eiface) 182 return -EINVAL; 183 STRLCPY(e.iface, eiface); 184 e.physdev = 1; 185 #endif 186 } else { 187 STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); 188 } 189 190 if (strlen(e.iface) == 0) 191 return -EINVAL; 192 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 193 } 194 195 static int 196 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], 197 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 198 { 199 struct hash_netiface4 *h = set->data; 200 ipset_adtfn adtfn = set->variant->adt[adt]; 201 struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; 202 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 203 u32 ip = 0, ip_to = 0; 204 int ret; 205 206 if (tb[IPSET_ATTR_LINENO]) 207 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 208 209 if (unlikely(!tb[IPSET_ATTR_IP] || 210 !tb[IPSET_ATTR_IFACE] || 211 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 212 return -IPSET_ERR_PROTOCOL; 213 214 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 215 if (ret) 216 return ret; 217 218 ret = ip_set_get_extensions(set, tb, &ext); 219 if (ret) 220 return ret; 221 222 if (tb[IPSET_ATTR_CIDR]) { 223 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 224 if (e.cidr > HOST_MASK) 225 return -IPSET_ERR_INVALID_CIDR; 226 } 227 nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); 228 229 if (tb[IPSET_ATTR_CADT_FLAGS]) { 230 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 231 232 if (cadt_flags & IPSET_FLAG_PHYSDEV) 233 e.physdev = 1; 234 if (cadt_flags & IPSET_FLAG_NOMATCH) 235 flags |= (IPSET_FLAG_NOMATCH << 16); 236 } 237 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { 238 e.ip = htonl(ip & ip_set_hostmask(e.cidr)); 239 ret = adtfn(set, &e, &ext, &ext, flags); 240 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 241 ip_set_eexist(ret, flags) ? 0 : ret; 242 } 243 244 if (tb[IPSET_ATTR_IP_TO]) { 245 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 246 if (ret) 247 return ret; 248 if (ip_to < ip) 249 swap(ip, ip_to); 250 if (ip + UINT_MAX == ip_to) 251 return -IPSET_ERR_HASH_RANGE; 252 } else { 253 ip_set_mask_from_to(ip, ip_to, e.cidr); 254 } 255 256 if (retried) 257 ip = ntohl(h->next.ip); 258 do { 259 e.ip = htonl(ip); 260 ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); 261 ret = adtfn(set, &e, &ext, &ext, flags); 262 263 if (ret && !ip_set_eexist(ret, flags)) 264 return ret; 265 266 ret = 0; 267 } while (ip++ < ip_to); 268 return ret; 269 } 270 271 /* IPv6 variant */ 272 273 struct hash_netiface6_elem_hashed { 274 union nf_inet_addr ip; 275 u8 physdev; 276 u8 cidr; 277 u8 nomatch; 278 u8 elem; 279 }; 280 281 struct hash_netiface6_elem { 282 union nf_inet_addr ip; 283 u8 physdev; 284 u8 cidr; 285 u8 nomatch; 286 u8 elem; 287 char iface[IFNAMSIZ]; 288 }; 289 290 /* Common functions */ 291 292 static inline bool 293 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 294 const struct hash_netiface6_elem *ip2, 295 u32 *multi) 296 { 297 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 298 ip1->cidr == ip2->cidr && 299 (++*multi) && 300 ip1->physdev == ip2->physdev && 301 strcmp(ip1->iface, ip2->iface) == 0; 302 } 303 304 static inline int 305 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem) 306 { 307 return elem->nomatch ? -ENOTEMPTY : 1; 308 } 309 310 static inline void 311 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags) 312 { 313 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 314 } 315 316 static inline void 317 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags) 318 { 319 swap(*flags, elem->nomatch); 320 } 321 322 static inline void 323 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr) 324 { 325 ip6_netmask(&elem->ip, cidr); 326 elem->cidr = cidr; 327 } 328 329 static bool 330 hash_netiface6_data_list(struct sk_buff *skb, 331 const struct hash_netiface6_elem *data) 332 { 333 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 334 335 if (data->nomatch) 336 flags |= IPSET_FLAG_NOMATCH; 337 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 338 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || 339 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || 340 (flags && 341 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 342 goto nla_put_failure; 343 return false; 344 345 nla_put_failure: 346 return true; 347 } 348 349 static inline void 350 hash_netiface6_data_next(struct hash_netiface6_elem *next, 351 const struct hash_netiface6_elem *d) 352 { 353 } 354 355 #undef MTYPE 356 #undef HOST_MASK 357 358 #define MTYPE hash_netiface6 359 #define HOST_MASK 128 360 #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) 361 #define IP_SET_EMIT_CREATE 362 #include "ip_set_hash_gen.h" 363 364 static int 365 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, 366 const struct xt_action_param *par, 367 enum ipset_adt adt, struct ip_set_adt_opt *opt) 368 { 369 struct hash_netiface6 *h = set->data; 370 ipset_adtfn adtfn = set->variant->adt[adt]; 371 struct hash_netiface6_elem e = { 372 .cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 373 .elem = 1, 374 }; 375 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 376 377 if (adt == IPSET_TEST) 378 e.cidr = HOST_MASK; 379 380 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 381 ip6_netmask(&e.ip, e.cidr); 382 383 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 384 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 385 const char *eiface = SRCDIR ? get_physindev_name(skb) : 386 get_physoutdev_name(skb); 387 388 if (!eiface) 389 return -EINVAL; 390 STRLCPY(e.iface, eiface); 391 e.physdev = 1; 392 #endif 393 } else { 394 STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); 395 } 396 397 if (strlen(e.iface) == 0) 398 return -EINVAL; 399 400 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 401 } 402 403 static int 404 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], 405 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 406 { 407 ipset_adtfn adtfn = set->variant->adt[adt]; 408 struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 }; 409 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 410 int ret; 411 412 if (tb[IPSET_ATTR_LINENO]) 413 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 414 415 if (unlikely(!tb[IPSET_ATTR_IP] || 416 !tb[IPSET_ATTR_IFACE] || 417 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 418 return -IPSET_ERR_PROTOCOL; 419 if (unlikely(tb[IPSET_ATTR_IP_TO])) 420 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 421 422 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip); 423 if (ret) 424 return ret; 425 426 ret = ip_set_get_extensions(set, tb, &ext); 427 if (ret) 428 return ret; 429 430 if (tb[IPSET_ATTR_CIDR]) { 431 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 432 if (e.cidr > HOST_MASK) 433 return -IPSET_ERR_INVALID_CIDR; 434 } 435 436 ip6_netmask(&e.ip, e.cidr); 437 438 nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); 439 440 if (tb[IPSET_ATTR_CADT_FLAGS]) { 441 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 442 443 if (cadt_flags & IPSET_FLAG_PHYSDEV) 444 e.physdev = 1; 445 if (cadt_flags & IPSET_FLAG_NOMATCH) 446 flags |= (IPSET_FLAG_NOMATCH << 16); 447 } 448 449 ret = adtfn(set, &e, &ext, &ext, flags); 450 451 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 452 ip_set_eexist(ret, flags) ? 0 : ret; 453 } 454 455 static struct ip_set_type hash_netiface_type __read_mostly = { 456 .name = "hash:net,iface", 457 .protocol = IPSET_PROTOCOL, 458 .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE | 459 IPSET_TYPE_NOMATCH, 460 .dimension = IPSET_DIM_TWO, 461 .family = NFPROTO_UNSPEC, 462 .revision_min = IPSET_TYPE_REV_MIN, 463 .revision_max = IPSET_TYPE_REV_MAX, 464 .create = hash_netiface_create, 465 .create_policy = { 466 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 467 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 468 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 469 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 470 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 471 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 472 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 473 }, 474 .adt_policy = { 475 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 476 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 477 [IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING, 478 .len = IFNAMSIZ - 1 }, 479 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 480 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 481 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 482 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 483 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 484 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 485 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, 486 .len = IPSET_MAX_COMMENT_SIZE }, 487 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 488 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 489 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 490 }, 491 .me = THIS_MODULE, 492 }; 493 494 static int __init 495 hash_netiface_init(void) 496 { 497 return ip_set_type_register(&hash_netiface_type); 498 } 499 500 static void __exit 501 hash_netiface_fini(void) 502 { 503 rcu_barrier(); 504 ip_set_type_unregister(&hash_netiface_type); 505 } 506 507 module_init(hash_netiface_init); 508 module_exit(hash_netiface_fini); 509