root/net/netfilter/ipset/ip_set_hash_net.c

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

DEFINITIONS

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

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