root/net/netfilter/ipset/ip_set_hash_ipportip.c

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

DEFINITIONS

This source file includes following definitions.
  1. hash_ipportip4_data_equal
  2. hash_ipportip4_data_list
  3. hash_ipportip4_data_next
  4. hash_ipportip4_kadt
  5. hash_ipportip4_uadt
  6. hash_ipportip6_data_equal
  7. hash_ipportip6_data_list
  8. hash_ipportip6_data_next
  9. hash_ipportip6_kadt
  10. hash_ipportip6_uadt
  11. hash_ipportip_init
  12. hash_ipportip_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:ip,port,ip 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 #include <net/tcp.h>
  16 
  17 #include <linux/netfilter.h>
  18 #include <linux/netfilter/ipset/pfxlen.h>
  19 #include <linux/netfilter/ipset/ip_set.h>
  20 #include <linux/netfilter/ipset/ip_set_getport.h>
  21 #include <linux/netfilter/ipset/ip_set_hash.h>
  22 
  23 #define IPSET_TYPE_REV_MIN      0
  24 /*                              1    SCTP and UDPLITE support added */
  25 /*                              2    Counters support added */
  26 /*                              3    Comments support added */
  27 /*                              4    Forceadd support added */
  28 #define IPSET_TYPE_REV_MAX      5 /* skbinfo support added */
  29 
  30 MODULE_LICENSE("GPL");
  31 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  32 IP_SET_MODULE_DESC("hash:ip,port,ip", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  33 MODULE_ALIAS("ip_set_hash:ip,port,ip");
  34 
  35 /* Type specific function prefix */
  36 #define HTYPE           hash_ipportip
  37 
  38 /* IPv4 variant */
  39 
  40 /* Member elements  */
  41 struct hash_ipportip4_elem {
  42         __be32 ip;
  43         __be32 ip2;
  44         __be16 port;
  45         u8 proto;
  46         u8 padding;
  47 };
  48 
  49 static inline bool
  50 hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
  51                           const struct hash_ipportip4_elem *ip2,
  52                           u32 *multi)
  53 {
  54         return ip1->ip == ip2->ip &&
  55                ip1->ip2 == ip2->ip2 &&
  56                ip1->port == ip2->port &&
  57                ip1->proto == ip2->proto;
  58 }
  59 
  60 static bool
  61 hash_ipportip4_data_list(struct sk_buff *skb,
  62                          const struct hash_ipportip4_elem *data)
  63 {
  64         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
  65             nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) ||
  66             nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
  67             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto))
  68                 goto nla_put_failure;
  69         return false;
  70 
  71 nla_put_failure:
  72         return true;
  73 }
  74 
  75 static inline void
  76 hash_ipportip4_data_next(struct hash_ipportip4_elem *next,
  77                          const struct hash_ipportip4_elem *d)
  78 {
  79         next->ip = d->ip;
  80         next->port = d->port;
  81 }
  82 
  83 /* Common functions */
  84 #define MTYPE           hash_ipportip4
  85 #define HOST_MASK       32
  86 #include "ip_set_hash_gen.h"
  87 
  88 static int
  89 hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
  90                     const struct xt_action_param *par,
  91                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
  92 {
  93         ipset_adtfn adtfn = set->variant->adt[adt];
  94         struct hash_ipportip4_elem e = { .ip = 0 };
  95         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
  96 
  97         if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
  98                                  &e.port, &e.proto))
  99                 return -EINVAL;
 100 
 101         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
 102         ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2);
 103         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 104 }
 105 
 106 static int
 107 hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
 108                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 109 {
 110         const struct hash_ipportip4 *h = set->data;
 111         ipset_adtfn adtfn = set->variant->adt[adt];
 112         struct hash_ipportip4_elem e = { .ip = 0 };
 113         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 114         u32 ip, ip_to = 0, p = 0, port, port_to;
 115         bool with_ports = false;
 116         int ret;
 117 
 118         if (tb[IPSET_ATTR_LINENO])
 119                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 120 
 121         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
 122                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 123                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
 124                 return -IPSET_ERR_PROTOCOL;
 125 
 126         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip);
 127         if (ret)
 128                 return ret;
 129 
 130         ret = ip_set_get_extensions(set, tb, &ext);
 131         if (ret)
 132                 return ret;
 133 
 134         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &e.ip2);
 135         if (ret)
 136                 return ret;
 137 
 138         e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
 139 
 140         if (tb[IPSET_ATTR_PROTO]) {
 141                 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
 142                 with_ports = ip_set_proto_with_ports(e.proto);
 143 
 144                 if (e.proto == 0)
 145                         return -IPSET_ERR_INVALID_PROTO;
 146         } else {
 147                 return -IPSET_ERR_MISSING_PROTO;
 148         }
 149 
 150         if (!(with_ports || e.proto == IPPROTO_ICMP))
 151                 e.port = 0;
 152 
 153         if (adt == IPSET_TEST ||
 154             !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
 155               tb[IPSET_ATTR_PORT_TO])) {
 156                 ret = adtfn(set, &e, &ext, &ext, flags);
 157                 return ip_set_eexist(ret, flags) ? 0 : ret;
 158         }
 159 
 160         ip_to = ip = ntohl(e.ip);
 161         if (tb[IPSET_ATTR_IP_TO]) {
 162                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
 163                 if (ret)
 164                         return ret;
 165                 if (ip > ip_to)
 166                         swap(ip, ip_to);
 167         } else if (tb[IPSET_ATTR_CIDR]) {
 168                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 169 
 170                 if (!cidr || cidr > HOST_MASK)
 171                         return -IPSET_ERR_INVALID_CIDR;
 172                 ip_set_mask_from_to(ip, ip_to, cidr);
 173         }
 174 
 175         port_to = port = ntohs(e.port);
 176         if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
 177                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 178                 if (port > port_to)
 179                         swap(port, port_to);
 180         }
 181 
 182         if (retried)
 183                 ip = ntohl(h->next.ip);
 184         for (; ip <= ip_to; ip++) {
 185                 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 186                                                        : port;
 187                 for (; p <= port_to; p++) {
 188                         e.ip = htonl(ip);
 189                         e.port = htons(p);
 190                         ret = adtfn(set, &e, &ext, &ext, flags);
 191 
 192                         if (ret && !ip_set_eexist(ret, flags))
 193                                 return ret;
 194 
 195                         ret = 0;
 196                 }
 197         }
 198         return ret;
 199 }
 200 
 201 /* IPv6 variant */
 202 
 203 struct hash_ipportip6_elem {
 204         union nf_inet_addr ip;
 205         union nf_inet_addr ip2;
 206         __be16 port;
 207         u8 proto;
 208         u8 padding;
 209 };
 210 
 211 /* Common functions */
 212 
 213 static inline bool
 214 hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
 215                           const struct hash_ipportip6_elem *ip2,
 216                           u32 *multi)
 217 {
 218         return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
 219                ipv6_addr_equal(&ip1->ip2.in6, &ip2->ip2.in6) &&
 220                ip1->port == ip2->port &&
 221                ip1->proto == ip2->proto;
 222 }
 223 
 224 static bool
 225 hash_ipportip6_data_list(struct sk_buff *skb,
 226                          const struct hash_ipportip6_elem *data)
 227 {
 228         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
 229             nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
 230             nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
 231             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto))
 232                 goto nla_put_failure;
 233         return false;
 234 
 235 nla_put_failure:
 236         return true;
 237 }
 238 
 239 static inline void
 240 hash_ipportip6_data_next(struct hash_ipportip6_elem *next,
 241                          const struct hash_ipportip6_elem *d)
 242 {
 243         next->port = d->port;
 244 }
 245 
 246 #undef MTYPE
 247 #undef HOST_MASK
 248 
 249 #define MTYPE           hash_ipportip6
 250 #define HOST_MASK       128
 251 #define IP_SET_EMIT_CREATE
 252 #include "ip_set_hash_gen.h"
 253 
 254 static int
 255 hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
 256                     const struct xt_action_param *par,
 257                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
 258 {
 259         ipset_adtfn adtfn = set->variant->adt[adt];
 260         struct hash_ipportip6_elem e = { .ip = { .all = { 0 } } };
 261         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 262 
 263         if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 264                                  &e.port, &e.proto))
 265                 return -EINVAL;
 266 
 267         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
 268         ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6);
 269         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 270 }
 271 
 272 static int
 273 hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
 274                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 275 {
 276         const struct hash_ipportip6 *h = set->data;
 277         ipset_adtfn adtfn = set->variant->adt[adt];
 278         struct hash_ipportip6_elem e = {  .ip = { .all = { 0 } } };
 279         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 280         u32 port, port_to;
 281         bool with_ports = false;
 282         int ret;
 283 
 284         if (tb[IPSET_ATTR_LINENO])
 285                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 286 
 287         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
 288                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 289                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
 290                 return -IPSET_ERR_PROTOCOL;
 291         if (unlikely(tb[IPSET_ATTR_IP_TO]))
 292                 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
 293         if (unlikely(tb[IPSET_ATTR_CIDR])) {
 294                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 295 
 296                 if (cidr != HOST_MASK)
 297                         return -IPSET_ERR_INVALID_CIDR;
 298         }
 299 
 300         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip);
 301         if (ret)
 302                 return ret;
 303 
 304         ret = ip_set_get_extensions(set, tb, &ext);
 305         if (ret)
 306                 return ret;
 307 
 308         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2);
 309         if (ret)
 310                 return ret;
 311 
 312         e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
 313 
 314         if (tb[IPSET_ATTR_PROTO]) {
 315                 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
 316                 with_ports = ip_set_proto_with_ports(e.proto);
 317 
 318                 if (e.proto == 0)
 319                         return -IPSET_ERR_INVALID_PROTO;
 320         } else {
 321                 return -IPSET_ERR_MISSING_PROTO;
 322         }
 323 
 324         if (!(with_ports || e.proto == IPPROTO_ICMPV6))
 325                 e.port = 0;
 326 
 327         if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
 328                 ret = adtfn(set, &e, &ext, &ext, flags);
 329                 return ip_set_eexist(ret, flags) ? 0 : ret;
 330         }
 331 
 332         port = ntohs(e.port);
 333         port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 334         if (port > port_to)
 335                 swap(port, port_to);
 336 
 337         if (retried)
 338                 port = ntohs(h->next.port);
 339         for (; port <= port_to; port++) {
 340                 e.port = htons(port);
 341                 ret = adtfn(set, &e, &ext, &ext, flags);
 342 
 343                 if (ret && !ip_set_eexist(ret, flags))
 344                         return ret;
 345 
 346                 ret = 0;
 347         }
 348         return ret;
 349 }
 350 
 351 static struct ip_set_type hash_ipportip_type __read_mostly = {
 352         .name           = "hash:ip,port,ip",
 353         .protocol       = IPSET_PROTOCOL,
 354         .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
 355         .dimension      = IPSET_DIM_THREE,
 356         .family         = NFPROTO_UNSPEC,
 357         .revision_min   = IPSET_TYPE_REV_MIN,
 358         .revision_max   = IPSET_TYPE_REV_MAX,
 359         .create         = hash_ipportip_create,
 360         .create_policy  = {
 361                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
 362                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
 363                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
 364                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
 365                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 366                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 367         },
 368         .adt_policy     = {
 369                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 370                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 371                 [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
 372                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 373                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 374                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 375                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 376                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 377                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 378                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 379                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 380                 [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING,
 381                                             .len  = IPSET_MAX_COMMENT_SIZE },
 382                 [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
 383                 [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
 384                 [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
 385         },
 386         .me             = THIS_MODULE,
 387 };
 388 
 389 static int __init
 390 hash_ipportip_init(void)
 391 {
 392         return ip_set_type_register(&hash_ipportip_type);
 393 }
 394 
 395 static void __exit
 396 hash_ipportip_fini(void)
 397 {
 398         rcu_barrier();
 399         ip_set_type_unregister(&hash_ipportip_type);
 400 }
 401 
 402 module_init(hash_ipportip_init);
 403 module_exit(hash_ipportip_fini);

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