root/net/netfilter/ipset/ip_set_hash_netnet.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hash_netnet4_data_equal
  2. hash_netnet4_do_data_match
  3. hash_netnet4_data_set_flags
  4. hash_netnet4_data_reset_flags
  5. hash_netnet4_data_reset_elem
  6. hash_netnet4_data_netmask
  7. hash_netnet4_data_list
  8. hash_netnet4_data_next
  9. hash_netnet4_init
  10. hash_netnet4_kadt
  11. hash_netnet4_uadt
  12. hash_netnet6_data_equal
  13. hash_netnet6_do_data_match
  14. hash_netnet6_data_set_flags
  15. hash_netnet6_data_reset_flags
  16. hash_netnet6_data_reset_elem
  17. hash_netnet6_data_netmask
  18. hash_netnet6_data_list
  19. hash_netnet6_data_next
  20. hash_netnet6_init
  21. hash_netnet6_kadt
  22. hash_netnet6_uadt
  23. hash_netnet_init
  24. hash_netnet_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@netfilter.org>
   3  * Copyright (C) 2013 Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>
   4  */
   5 
   6 /* Kernel module implementing an IP set type: the hash:net type */
   7 
   8 #include <linux/jhash.h>
   9 #include <linux/module.h>
  10 #include <linux/ip.h>
  11 #include <linux/skbuff.h>
  12 #include <linux/errno.h>
  13 #include <linux/random.h>
  14 #include <net/ip.h>
  15 #include <net/ipv6.h>
  16 #include <net/netlink.h>
  17 
  18 #include <linux/netfilter.h>
  19 #include <linux/netfilter/ipset/pfxlen.h>
  20 #include <linux/netfilter/ipset/ip_set.h>
  21 #include <linux/netfilter/ipset/ip_set_hash.h>
  22 
  23 #define IPSET_TYPE_REV_MIN      0
  24 /*                              1          Forceadd support added */
  25 #define IPSET_TYPE_REV_MAX      2       /* skbinfo support added */
  26 
  27 MODULE_LICENSE("GPL");
  28 MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
  29 IP_SET_MODULE_DESC("hash:net,net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  30 MODULE_ALIAS("ip_set_hash:net,net");
  31 
  32 /* Type specific function prefix */
  33 #define HTYPE           hash_netnet
  34 #define IP_SET_HASH_WITH_NETS
  35 #define IPSET_NET_COUNT 2
  36 
  37 /* IPv4 variants */
  38 
  39 /* Member elements  */
  40 struct hash_netnet4_elem {
  41         union {
  42                 __be32 ip[2];
  43                 __be64 ipcmp;
  44         };
  45         u8 nomatch;
  46         u8 padding;
  47         union {
  48                 u8 cidr[2];
  49                 u16 ccmp;
  50         };
  51 };
  52 
  53 /* Common functions */
  54 
  55 static inline bool
  56 hash_netnet4_data_equal(const struct hash_netnet4_elem *ip1,
  57                         const struct hash_netnet4_elem *ip2,
  58                         u32 *multi)
  59 {
  60         return ip1->ipcmp == ip2->ipcmp &&
  61                ip1->ccmp == ip2->ccmp;
  62 }
  63 
  64 static inline int
  65 hash_netnet4_do_data_match(const struct hash_netnet4_elem *elem)
  66 {
  67         return elem->nomatch ? -ENOTEMPTY : 1;
  68 }
  69 
  70 static inline void
  71 hash_netnet4_data_set_flags(struct hash_netnet4_elem *elem, u32 flags)
  72 {
  73         elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
  74 }
  75 
  76 static inline void
  77 hash_netnet4_data_reset_flags(struct hash_netnet4_elem *elem, u8 *flags)
  78 {
  79         swap(*flags, elem->nomatch);
  80 }
  81 
  82 static inline void
  83 hash_netnet4_data_reset_elem(struct hash_netnet4_elem *elem,
  84                              struct hash_netnet4_elem *orig)
  85 {
  86         elem->ip[1] = orig->ip[1];
  87 }
  88 
  89 static inline void
  90 hash_netnet4_data_netmask(struct hash_netnet4_elem *elem, u8 cidr, bool inner)
  91 {
  92         if (inner) {
  93                 elem->ip[1] &= ip_set_netmask(cidr);
  94                 elem->cidr[1] = cidr;
  95         } else {
  96                 elem->ip[0] &= ip_set_netmask(cidr);
  97                 elem->cidr[0] = cidr;
  98         }
  99 }
 100 
 101 static bool
 102 hash_netnet4_data_list(struct sk_buff *skb,
 103                        const struct hash_netnet4_elem *data)
 104 {
 105         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
 106 
 107         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip[0]) ||
 108             nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip[1]) ||
 109             nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) ||
 110             nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) ||
 111             (flags &&
 112              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
 113                 goto nla_put_failure;
 114         return false;
 115 
 116 nla_put_failure:
 117         return true;
 118 }
 119 
 120 static inline void
 121 hash_netnet4_data_next(struct hash_netnet4_elem *next,
 122                        const struct hash_netnet4_elem *d)
 123 {
 124         next->ipcmp = d->ipcmp;
 125 }
 126 
 127 #define MTYPE           hash_netnet4
 128 #define HOST_MASK       32
 129 #include "ip_set_hash_gen.h"
 130 
 131 static void
 132 hash_netnet4_init(struct hash_netnet4_elem *e)
 133 {
 134         e->cidr[0] = HOST_MASK;
 135         e->cidr[1] = HOST_MASK;
 136 }
 137 
 138 static int
 139 hash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
 140                   const struct xt_action_param *par,
 141                   enum ipset_adt adt, struct ip_set_adt_opt *opt)
 142 {
 143         const struct hash_netnet4 *h = set->data;
 144         ipset_adtfn adtfn = set->variant->adt[adt];
 145         struct hash_netnet4_elem e = { };
 146         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 147 
 148         e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK);
 149         e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK);
 150         if (adt == IPSET_TEST)
 151                 e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK;
 152 
 153         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]);
 154         ip4addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1]);
 155         e.ip[0] &= ip_set_netmask(e.cidr[0]);
 156         e.ip[1] &= ip_set_netmask(e.cidr[1]);
 157 
 158         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 159 }
 160 
 161 static int
 162 hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 163                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 164 {
 165         const struct hash_netnet4 *h = set->data;
 166         ipset_adtfn adtfn = set->variant->adt[adt];
 167         struct hash_netnet4_elem e = { };
 168         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 169         u32 ip = 0, ip_to = 0;
 170         u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
 171         int ret;
 172 
 173         if (tb[IPSET_ATTR_LINENO])
 174                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 175 
 176         hash_netnet4_init(&e);
 177         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
 178                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
 179                 return -IPSET_ERR_PROTOCOL;
 180 
 181         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
 182         if (ret)
 183                 return ret;
 184 
 185         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
 186         if (ret)
 187                 return ret;
 188 
 189         ret = ip_set_get_extensions(set, tb, &ext);
 190         if (ret)
 191                 return ret;
 192 
 193         if (tb[IPSET_ATTR_CIDR]) {
 194                 e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 195                 if (!e.cidr[0] || e.cidr[0] > HOST_MASK)
 196                         return -IPSET_ERR_INVALID_CIDR;
 197         }
 198 
 199         if (tb[IPSET_ATTR_CIDR2]) {
 200                 e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
 201                 if (!e.cidr[1] || e.cidr[1] > HOST_MASK)
 202                         return -IPSET_ERR_INVALID_CIDR;
 203         }
 204 
 205         if (tb[IPSET_ATTR_CADT_FLAGS]) {
 206                 u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
 207 
 208                 if (cadt_flags & IPSET_FLAG_NOMATCH)
 209                         flags |= (IPSET_FLAG_NOMATCH << 16);
 210         }
 211 
 212         if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] ||
 213                                    tb[IPSET_ATTR_IP2_TO])) {
 214                 e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0]));
 215                 e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1]));
 216                 ret = adtfn(set, &e, &ext, &ext, flags);
 217                 return ip_set_enomatch(ret, flags, adt, set) ? -ret :
 218                        ip_set_eexist(ret, flags) ? 0 : ret;
 219         }
 220 
 221         ip_to = ip;
 222         if (tb[IPSET_ATTR_IP_TO]) {
 223                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
 224                 if (ret)
 225                         return ret;
 226                 if (ip_to < ip)
 227                         swap(ip, ip_to);
 228                 if (unlikely(ip + UINT_MAX == ip_to))
 229                         return -IPSET_ERR_HASH_RANGE;
 230         } else {
 231                 ip_set_mask_from_to(ip, ip_to, e.cidr[0]);
 232         }
 233 
 234         ip2_to = ip2_from;
 235         if (tb[IPSET_ATTR_IP2_TO]) {
 236                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
 237                 if (ret)
 238                         return ret;
 239                 if (ip2_to < ip2_from)
 240                         swap(ip2_from, ip2_to);
 241                 if (unlikely(ip2_from + UINT_MAX == ip2_to))
 242                         return -IPSET_ERR_HASH_RANGE;
 243         } else {
 244                 ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
 245         }
 246 
 247         if (retried) {
 248                 ip = ntohl(h->next.ip[0]);
 249                 ip2 = ntohl(h->next.ip[1]);
 250         } else {
 251                 ip2 = ip2_from;
 252         }
 253 
 254         do {
 255                 e.ip[0] = htonl(ip);
 256                 ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
 257                 do {
 258                         e.ip[1] = htonl(ip2);
 259                         ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
 260                         ret = adtfn(set, &e, &ext, &ext, flags);
 261                         if (ret && !ip_set_eexist(ret, flags))
 262                                 return ret;
 263 
 264                         ret = 0;
 265                 } while (ip2++ < ip2_to);
 266                 ip2 = ip2_from;
 267         } while (ip++ < ip_to);
 268         return ret;
 269 }
 270 
 271 /* IPv6 variants */
 272 
 273 struct hash_netnet6_elem {
 274         union nf_inet_addr ip[2];
 275         u8 nomatch;
 276         u8 padding;
 277         union {
 278                 u8 cidr[2];
 279                 u16 ccmp;
 280         };
 281 };
 282 
 283 /* Common functions */
 284 
 285 static inline bool
 286 hash_netnet6_data_equal(const struct hash_netnet6_elem *ip1,
 287                         const struct hash_netnet6_elem *ip2,
 288                         u32 *multi)
 289 {
 290         return ipv6_addr_equal(&ip1->ip[0].in6, &ip2->ip[0].in6) &&
 291                ipv6_addr_equal(&ip1->ip[1].in6, &ip2->ip[1].in6) &&
 292                ip1->ccmp == ip2->ccmp;
 293 }
 294 
 295 static inline int
 296 hash_netnet6_do_data_match(const struct hash_netnet6_elem *elem)
 297 {
 298         return elem->nomatch ? -ENOTEMPTY : 1;
 299 }
 300 
 301 static inline void
 302 hash_netnet6_data_set_flags(struct hash_netnet6_elem *elem, u32 flags)
 303 {
 304         elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH;
 305 }
 306 
 307 static inline void
 308 hash_netnet6_data_reset_flags(struct hash_netnet6_elem *elem, u8 *flags)
 309 {
 310         swap(*flags, elem->nomatch);
 311 }
 312 
 313 static inline void
 314 hash_netnet6_data_reset_elem(struct hash_netnet6_elem *elem,
 315                              struct hash_netnet6_elem *orig)
 316 {
 317         elem->ip[1] = orig->ip[1];
 318 }
 319 
 320 static inline void
 321 hash_netnet6_data_netmask(struct hash_netnet6_elem *elem, u8 cidr, bool inner)
 322 {
 323         if (inner) {
 324                 ip6_netmask(&elem->ip[1], cidr);
 325                 elem->cidr[1] = cidr;
 326         } else {
 327                 ip6_netmask(&elem->ip[0], cidr);
 328                 elem->cidr[0] = cidr;
 329         }
 330 }
 331 
 332 static bool
 333 hash_netnet6_data_list(struct sk_buff *skb,
 334                        const struct hash_netnet6_elem *data)
 335 {
 336         u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
 337 
 338         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip[0].in6) ||
 339             nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip[1].in6) ||
 340             nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) ||
 341             nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) ||
 342             (flags &&
 343              nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
 344                 goto nla_put_failure;
 345         return false;
 346 
 347 nla_put_failure:
 348         return true;
 349 }
 350 
 351 static inline void
 352 hash_netnet6_data_next(struct hash_netnet6_elem *next,
 353                        const struct hash_netnet6_elem *d)
 354 {
 355 }
 356 
 357 #undef MTYPE
 358 #undef HOST_MASK
 359 
 360 #define MTYPE           hash_netnet6
 361 #define HOST_MASK       128
 362 #define IP_SET_EMIT_CREATE
 363 #include "ip_set_hash_gen.h"
 364 
 365 static void
 366 hash_netnet6_init(struct hash_netnet6_elem *e)
 367 {
 368         e->cidr[0] = HOST_MASK;
 369         e->cidr[1] = HOST_MASK;
 370 }
 371 
 372 static int
 373 hash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
 374                   const struct xt_action_param *par,
 375                   enum ipset_adt adt, struct ip_set_adt_opt *opt)
 376 {
 377         const struct hash_netnet6 *h = set->data;
 378         ipset_adtfn adtfn = set->variant->adt[adt];
 379         struct hash_netnet6_elem e = { };
 380         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 381 
 382         e.cidr[0] = INIT_CIDR(h->nets[0].cidr[0], HOST_MASK);
 383         e.cidr[1] = INIT_CIDR(h->nets[0].cidr[1], HOST_MASK);
 384         if (adt == IPSET_TEST)
 385                 e.ccmp = (HOST_MASK << (sizeof(u8) * 8)) | HOST_MASK;
 386 
 387         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0].in6);
 388         ip6addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1].in6);
 389         ip6_netmask(&e.ip[0], e.cidr[0]);
 390         ip6_netmask(&e.ip[1], e.cidr[1]);
 391 
 392         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 393 }
 394 
 395 static int
 396 hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 397                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 398 {
 399         ipset_adtfn adtfn = set->variant->adt[adt];
 400         struct hash_netnet6_elem e = { };
 401         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 402         int ret;
 403 
 404         if (tb[IPSET_ATTR_LINENO])
 405                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 406 
 407         hash_netnet6_init(&e);
 408         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
 409                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
 410                 return -IPSET_ERR_PROTOCOL;
 411         if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO]))
 412                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
 413 
 414         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip[0]);
 415         if (ret)
 416                 return ret;
 417 
 418         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip[1]);
 419         if (ret)
 420                 return ret;
 421 
 422         ret = ip_set_get_extensions(set, tb, &ext);
 423         if (ret)
 424                 return ret;
 425 
 426         if (tb[IPSET_ATTR_CIDR]) {
 427                 e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 428                 if (!e.cidr[0] || e.cidr[0] > HOST_MASK)
 429                         return -IPSET_ERR_INVALID_CIDR;
 430         }
 431 
 432         if (tb[IPSET_ATTR_CIDR2]) {
 433                 e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
 434                 if (!e.cidr[1] || e.cidr[1] > HOST_MASK)
 435                         return -IPSET_ERR_INVALID_CIDR;
 436         }
 437 
 438         ip6_netmask(&e.ip[0], e.cidr[0]);
 439         ip6_netmask(&e.ip[1], e.cidr[1]);
 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_NOMATCH)
 445                         flags |= (IPSET_FLAG_NOMATCH << 16);
 446         }
 447 
 448         ret = adtfn(set, &e, &ext, &ext, flags);
 449 
 450         return ip_set_enomatch(ret, flags, adt, set) ? -ret :
 451                ip_set_eexist(ret, flags) ? 0 : ret;
 452 }
 453 
 454 static struct ip_set_type hash_netnet_type __read_mostly = {
 455         .name           = "hash:net,net",
 456         .protocol       = IPSET_PROTOCOL,
 457         .features       = IPSET_TYPE_IP | IPSET_TYPE_IP2 | IPSET_TYPE_NOMATCH,
 458         .dimension      = IPSET_DIM_TWO,
 459         .family         = NFPROTO_UNSPEC,
 460         .revision_min   = IPSET_TYPE_REV_MIN,
 461         .revision_max   = IPSET_TYPE_REV_MAX,
 462         .create         = hash_netnet_create,
 463         .create_policy  = {
 464                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
 465                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
 466                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
 467                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
 468                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 469                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 470         },
 471         .adt_policy     = {
 472                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 473                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 474                 [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
 475                 [IPSET_ATTR_IP2_TO]     = { .type = NLA_NESTED },
 476                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 477                 [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
 478                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 479                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 480                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 481                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 482                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 483                 [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING,
 484                                             .len  = IPSET_MAX_COMMENT_SIZE },
 485                 [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
 486                 [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
 487                 [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
 488         },
 489         .me             = THIS_MODULE,
 490 };
 491 
 492 static int __init
 493 hash_netnet_init(void)
 494 {
 495         return ip_set_type_register(&hash_netnet_type);
 496 }
 497 
 498 static void __exit
 499 hash_netnet_fini(void)
 500 {
 501         rcu_barrier();
 502         ip_set_type_unregister(&hash_netnet_type);
 503 }
 504 
 505 module_init(hash_netnet_init);
 506 module_exit(hash_netnet_fini);

/* [<][>][^][v][top][bottom][index][help] */