root/net/netfilter/ipset/ip_set_hash_netport.c

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

DEFINITIONS

This source file includes following definitions.
  1. hash_netport4_data_equal
  2. hash_netport4_do_data_match
  3. hash_netport4_data_set_flags
  4. hash_netport4_data_reset_flags
  5. hash_netport4_data_netmask
  6. hash_netport4_data_list
  7. hash_netport4_data_next
  8. hash_netport4_kadt
  9. hash_netport4_uadt
  10. hash_netport6_data_equal
  11. hash_netport6_do_data_match
  12. hash_netport6_data_set_flags
  13. hash_netport6_data_reset_flags
  14. hash_netport6_data_netmask
  15. hash_netport6_data_list
  16. hash_netport6_data_next
  17. hash_netport6_kadt
  18. hash_netport6_uadt
  19. hash_netport_init
  20. hash_netport_fini

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

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