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_netiface *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 (e.cidr == 0) 168 return -EINVAL; 169 if (adt == IPSET_TEST) 170 e.cidr = HOST_MASK; 171 172 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); 173 e.ip &= ip_set_netmask(e.cidr); 174 175 #define IFACE(dir) (par->dir ? par->dir->name : "") 176 #define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC) 177 178 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 179 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 180 const char *eiface = SRCDIR ? get_physindev_name(skb) : 181 get_physoutdev_name(skb); 182 183 if (!eiface) 184 return -EINVAL; 185 STRLCPY(e.iface, eiface); 186 e.physdev = 1; 187 #endif 188 } else { 189 STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); 190 } 191 192 if (strlen(e.iface) == 0) 193 return -EINVAL; 194 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 195 } 196 197 static int 198 hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], 199 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 200 { 201 struct hash_netiface *h = set->data; 202 ipset_adtfn adtfn = set->variant->adt[adt]; 203 struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; 204 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 205 u32 ip = 0, ip_to = 0, last; 206 int ret; 207 208 if (tb[IPSET_ATTR_LINENO]) 209 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 210 211 if (unlikely(!tb[IPSET_ATTR_IP] || 212 !tb[IPSET_ATTR_IFACE] || 213 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 214 return -IPSET_ERR_PROTOCOL; 215 216 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 217 if (ret) 218 return ret; 219 220 ret = ip_set_get_extensions(set, tb, &ext); 221 if (ret) 222 return ret; 223 224 if (tb[IPSET_ATTR_CIDR]) { 225 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 226 if (e.cidr > HOST_MASK) 227 return -IPSET_ERR_INVALID_CIDR; 228 } 229 nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); 230 231 if (tb[IPSET_ATTR_CADT_FLAGS]) { 232 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 233 234 if (cadt_flags & IPSET_FLAG_PHYSDEV) 235 e.physdev = 1; 236 if (cadt_flags & IPSET_FLAG_NOMATCH) 237 flags |= (IPSET_FLAG_NOMATCH << 16); 238 } 239 if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) { 240 e.ip = htonl(ip & ip_set_hostmask(e.cidr)); 241 ret = adtfn(set, &e, &ext, &ext, flags); 242 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 243 ip_set_eexist(ret, flags) ? 0 : ret; 244 } 245 246 if (tb[IPSET_ATTR_IP_TO]) { 247 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 248 if (ret) 249 return ret; 250 if (ip_to < ip) 251 swap(ip, ip_to); 252 if (ip + UINT_MAX == ip_to) 253 return -IPSET_ERR_HASH_RANGE; 254 } else { 255 ip_set_mask_from_to(ip, ip_to, e.cidr); 256 } 257 258 if (retried) 259 ip = ntohl(h->next.ip); 260 while (!after(ip, ip_to)) { 261 e.ip = htonl(ip); 262 last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); 263 ret = adtfn(set, &e, &ext, &ext, flags); 264 265 if (ret && !ip_set_eexist(ret, flags)) 266 return ret; 267 268 ret = 0; 269 ip = last + 1; 270 } 271 return ret; 272 } 273 274 /* IPv6 variant */ 275 276 struct hash_netiface6_elem_hashed { 277 union nf_inet_addr ip; 278 u8 physdev; 279 u8 cidr; 280 u8 nomatch; 281 u8 elem; 282 }; 283 284 struct hash_netiface6_elem { 285 union nf_inet_addr ip; 286 u8 physdev; 287 u8 cidr; 288 u8 nomatch; 289 u8 elem; 290 char iface[IFNAMSIZ]; 291 }; 292 293 /* Common functions */ 294 295 static inline bool 296 hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1, 297 const struct hash_netiface6_elem *ip2, 298 u32 *multi) 299 { 300 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && 301 ip1->cidr == ip2->cidr && 302 (++*multi) && 303 ip1->physdev == ip2->physdev && 304 strcmp(ip1->iface, ip2->iface) == 0; 305 } 306 307 static inline int 308 hash_netiface6_do_data_match(const struct hash_netiface6_elem *elem) 309 { 310 return elem->nomatch ? -ENOTEMPTY : 1; 311 } 312 313 static inline void 314 hash_netiface6_data_set_flags(struct hash_netiface6_elem *elem, u32 flags) 315 { 316 elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 317 } 318 319 static inline void 320 hash_netiface6_data_reset_flags(struct hash_netiface6_elem *elem, u8 *flags) 321 { 322 swap(*flags, elem->nomatch); 323 } 324 325 static inline void 326 hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr) 327 { 328 ip6_netmask(&elem->ip, cidr); 329 elem->cidr = cidr; 330 } 331 332 static bool 333 hash_netiface6_data_list(struct sk_buff *skb, 334 const struct hash_netiface6_elem *data) 335 { 336 u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0; 337 338 if (data->nomatch) 339 flags |= IPSET_FLAG_NOMATCH; 340 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || 341 nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr) || 342 nla_put_string(skb, IPSET_ATTR_IFACE, data->iface) || 343 (flags && 344 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 345 goto nla_put_failure; 346 return false; 347 348 nla_put_failure: 349 return true; 350 } 351 352 static inline void 353 hash_netiface6_data_next(struct hash_netiface4_elem *next, 354 const struct hash_netiface6_elem *d) 355 { 356 } 357 358 #undef MTYPE 359 #undef HOST_MASK 360 361 #define MTYPE hash_netiface6 362 #define HOST_MASK 128 363 #define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed) 364 #define IP_SET_EMIT_CREATE 365 #include "ip_set_hash_gen.h" 366 367 static int 368 hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb, 369 const struct xt_action_param *par, 370 enum ipset_adt adt, struct ip_set_adt_opt *opt) 371 { 372 struct hash_netiface *h = set->data; 373 ipset_adtfn adtfn = set->variant->adt[adt]; 374 struct hash_netiface6_elem e = { 375 .cidr = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), 376 .elem = 1, 377 }; 378 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 379 380 if (e.cidr == 0) 381 return -EINVAL; 382 if (adt == IPSET_TEST) 383 e.cidr = HOST_MASK; 384 385 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 386 ip6_netmask(&e.ip, e.cidr); 387 388 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 389 #if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 390 const char *eiface = SRCDIR ? get_physindev_name(skb) : 391 get_physoutdev_name(skb); 392 393 if (!eiface) 394 return -EINVAL; 395 STRLCPY(e.iface, eiface); 396 e.physdev = 1; 397 #endif 398 } else { 399 STRLCPY(e.iface, SRCDIR ? IFACE(in) : IFACE(out)); 400 } 401 402 if (strlen(e.iface) == 0) 403 return -EINVAL; 404 405 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 406 } 407 408 static int 409 hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], 410 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 411 { 412 ipset_adtfn adtfn = set->variant->adt[adt]; 413 struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 }; 414 struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 415 int ret; 416 417 if (tb[IPSET_ATTR_LINENO]) 418 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 419 420 if (unlikely(!tb[IPSET_ATTR_IP] || 421 !tb[IPSET_ATTR_IFACE] || 422 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 423 return -IPSET_ERR_PROTOCOL; 424 if (unlikely(tb[IPSET_ATTR_IP_TO])) 425 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 426 427 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip); 428 if (ret) 429 return ret; 430 431 ret = ip_set_get_extensions(set, tb, &ext); 432 if (ret) 433 return ret; 434 435 if (tb[IPSET_ATTR_CIDR]) { 436 e.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 437 if (e.cidr > HOST_MASK) 438 return -IPSET_ERR_INVALID_CIDR; 439 } 440 441 ip6_netmask(&e.ip, e.cidr); 442 443 nla_strlcpy(e.iface, tb[IPSET_ATTR_IFACE], IFNAMSIZ); 444 445 if (tb[IPSET_ATTR_CADT_FLAGS]) { 446 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 447 448 if (cadt_flags & IPSET_FLAG_PHYSDEV) 449 e.physdev = 1; 450 if (cadt_flags & IPSET_FLAG_NOMATCH) 451 flags |= (IPSET_FLAG_NOMATCH << 16); 452 } 453 454 ret = adtfn(set, &e, &ext, &ext, flags); 455 456 return ip_set_enomatch(ret, flags, adt, set) ? -ret : 457 ip_set_eexist(ret, flags) ? 0 : ret; 458 } 459 460 static struct ip_set_type hash_netiface_type __read_mostly = { 461 .name = "hash:net,iface", 462 .protocol = IPSET_PROTOCOL, 463 .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE | 464 IPSET_TYPE_NOMATCH, 465 .dimension = IPSET_DIM_TWO, 466 .family = NFPROTO_UNSPEC, 467 .revision_min = IPSET_TYPE_REV_MIN, 468 .revision_max = IPSET_TYPE_REV_MAX, 469 .create = hash_netiface_create, 470 .create_policy = { 471 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 472 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 473 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 474 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 475 [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 476 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 477 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 478 }, 479 .adt_policy = { 480 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 481 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 482 [IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING, 483 .len = IFNAMSIZ - 1 }, 484 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 485 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 486 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 487 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 488 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 489 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 490 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING, 491 .len = IPSET_MAX_COMMENT_SIZE }, 492 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 493 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 494 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 495 }, 496 .me = THIS_MODULE, 497 }; 498 499 static int __init 500 hash_netiface_init(void) 501 { 502 return ip_set_type_register(&hash_netiface_type); 503 } 504 505 static void __exit 506 hash_netiface_fini(void) 507 { 508 rcu_barrier(); 509 ip_set_type_unregister(&hash_netiface_type); 510 } 511 512 module_init(hash_netiface_init); 513 module_exit(hash_netiface_fini); 514