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