root/net/netfilter/ipset/ip_set_bitmap_ipmac.c

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

DEFINITIONS

This source file includes following definitions.
  1. ip_to_id
  2. bitmap_ipmac_do_test
  3. bitmap_ipmac_gc_test
  4. bitmap_ipmac_is_filled
  5. bitmap_ipmac_add_timeout
  6. bitmap_ipmac_do_add
  7. bitmap_ipmac_do_del
  8. bitmap_ipmac_do_list
  9. bitmap_ipmac_do_head
  10. bitmap_ipmac_kadt
  11. bitmap_ipmac_uadt
  12. bitmap_ipmac_same_set
  13. init_map_ipmac
  14. bitmap_ipmac_create
  15. bitmap_ipmac_init
  16. bitmap_ipmac_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
   3  *                         Patrick Schaaf <bof@bof.de>
   4  *                         Martin Josefsson <gandalf@wlug.westbo.se>
   5  */
   6 
   7 /* Kernel module implementing an IP set type: the bitmap:ip,mac type */
   8 
   9 #include <linux/module.h>
  10 #include <linux/ip.h>
  11 #include <linux/etherdevice.h>
  12 #include <linux/skbuff.h>
  13 #include <linux/errno.h>
  14 #include <linux/if_ether.h>
  15 #include <linux/netlink.h>
  16 #include <linux/jiffies.h>
  17 #include <linux/timer.h>
  18 #include <net/netlink.h>
  19 
  20 #include <linux/netfilter/ipset/pfxlen.h>
  21 #include <linux/netfilter/ipset/ip_set.h>
  22 #include <linux/netfilter/ipset/ip_set_bitmap.h>
  23 
  24 #define IPSET_TYPE_REV_MIN      0
  25 /*                              1          Counter support added */
  26 /*                              2          Comment support added */
  27 #define IPSET_TYPE_REV_MAX      3       /* skbinfo support added */
  28 
  29 MODULE_LICENSE("GPL");
  30 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  31 IP_SET_MODULE_DESC("bitmap:ip,mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  32 MODULE_ALIAS("ip_set_bitmap:ip,mac");
  33 
  34 #define MTYPE           bitmap_ipmac
  35 #define HOST_MASK       32
  36 #define IP_SET_BITMAP_STORED_TIMEOUT
  37 
  38 enum {
  39         MAC_UNSET,              /* element is set, without MAC */
  40         MAC_FILLED,             /* element is set with MAC */
  41 };
  42 
  43 /* Type structure */
  44 struct bitmap_ipmac {
  45         unsigned long *members; /* the set members */
  46         u32 first_ip;           /* host byte order, included in range */
  47         u32 last_ip;            /* host byte order, included in range */
  48         u32 elements;           /* number of max elements in the set */
  49         size_t memsize;         /* members size */
  50         struct timer_list gc;   /* garbage collector */
  51         struct ip_set *set;     /* attached to this ip_set */
  52         unsigned char extensions[0]     /* MAC + data extensions */
  53                 __aligned(__alignof__(u64));
  54 };
  55 
  56 /* ADT structure for generic function args */
  57 struct bitmap_ipmac_adt_elem {
  58         unsigned char ether[ETH_ALEN] __aligned(2);
  59         u16 id;
  60         u16 add_mac;
  61 };
  62 
  63 struct bitmap_ipmac_elem {
  64         unsigned char ether[ETH_ALEN];
  65         unsigned char filled;
  66 } __aligned(__alignof__(u64));
  67 
  68 static inline u32
  69 ip_to_id(const struct bitmap_ipmac *m, u32 ip)
  70 {
  71         return ip - m->first_ip;
  72 }
  73 
  74 #define get_elem(extensions, id, dsize)         \
  75         (struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
  76 
  77 #define get_const_elem(extensions, id, dsize)   \
  78         (const struct bitmap_ipmac_elem *)(extensions + (id) * (dsize))
  79 
  80 /* Common functions */
  81 
  82 static inline int
  83 bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
  84                      const struct bitmap_ipmac *map, size_t dsize)
  85 {
  86         const struct bitmap_ipmac_elem *elem;
  87 
  88         if (!test_bit(e->id, map->members))
  89                 return 0;
  90         elem = get_const_elem(map->extensions, e->id, dsize);
  91         if (e->add_mac && elem->filled == MAC_FILLED)
  92                 return ether_addr_equal(e->ether, elem->ether);
  93         /* Trigger kernel to fill out the ethernet address */
  94         return -EAGAIN;
  95 }
  96 
  97 static inline int
  98 bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
  99 {
 100         const struct bitmap_ipmac_elem *elem;
 101 
 102         if (!test_bit(id, map->members))
 103                 return 0;
 104         elem = get_const_elem(map->extensions, id, dsize);
 105         /* Timer not started for the incomplete elements */
 106         return elem->filled == MAC_FILLED;
 107 }
 108 
 109 static inline int
 110 bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
 111 {
 112         return elem->filled == MAC_FILLED;
 113 }
 114 
 115 static inline int
 116 bitmap_ipmac_add_timeout(unsigned long *timeout,
 117                          const struct bitmap_ipmac_adt_elem *e,
 118                          const struct ip_set_ext *ext, struct ip_set *set,
 119                          struct bitmap_ipmac *map, int mode)
 120 {
 121         u32 t = ext->timeout;
 122 
 123         if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
 124                 if (t == set->timeout)
 125                         /* Timeout was not specified, get stored one */
 126                         t = *timeout;
 127                 ip_set_timeout_set(timeout, t);
 128         } else {
 129                 /* If MAC is unset yet, we store plain timeout value
 130                  * because the timer is not activated yet
 131                  * and we can reuse it later when MAC is filled out,
 132                  * possibly by the kernel
 133                  */
 134                 if (e->add_mac)
 135                         ip_set_timeout_set(timeout, t);
 136                 else
 137                         *timeout = t;
 138         }
 139         return 0;
 140 }
 141 
 142 static inline int
 143 bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
 144                     struct bitmap_ipmac *map, u32 flags, size_t dsize)
 145 {
 146         struct bitmap_ipmac_elem *elem;
 147 
 148         elem = get_elem(map->extensions, e->id, dsize);
 149         if (test_bit(e->id, map->members)) {
 150                 if (elem->filled == MAC_FILLED) {
 151                         if (e->add_mac &&
 152                             (flags & IPSET_FLAG_EXIST) &&
 153                             !ether_addr_equal(e->ether, elem->ether)) {
 154                                 /* memcpy isn't atomic */
 155                                 clear_bit(e->id, map->members);
 156                                 smp_mb__after_atomic();
 157                                 ether_addr_copy(elem->ether, e->ether);
 158                         }
 159                         return IPSET_ADD_FAILED;
 160                 } else if (!e->add_mac)
 161                         /* Already added without ethernet address */
 162                         return IPSET_ADD_FAILED;
 163                 /* Fill the MAC address and trigger the timer activation */
 164                 clear_bit(e->id, map->members);
 165                 smp_mb__after_atomic();
 166                 ether_addr_copy(elem->ether, e->ether);
 167                 elem->filled = MAC_FILLED;
 168                 return IPSET_ADD_START_STORED_TIMEOUT;
 169         } else if (e->add_mac) {
 170                 /* We can store MAC too */
 171                 ether_addr_copy(elem->ether, e->ether);
 172                 elem->filled = MAC_FILLED;
 173                 return 0;
 174         }
 175         elem->filled = MAC_UNSET;
 176         /* MAC is not stored yet, don't start timer */
 177         return IPSET_ADD_STORE_PLAIN_TIMEOUT;
 178 }
 179 
 180 static inline int
 181 bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e,
 182                     struct bitmap_ipmac *map)
 183 {
 184         return !test_and_clear_bit(e->id, map->members);
 185 }
 186 
 187 static inline int
 188 bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
 189                      u32 id, size_t dsize)
 190 {
 191         const struct bitmap_ipmac_elem *elem =
 192                 get_const_elem(map->extensions, id, dsize);
 193 
 194         return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
 195                                htonl(map->first_ip + id)) ||
 196                (elem->filled == MAC_FILLED &&
 197                 nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, elem->ether));
 198 }
 199 
 200 static inline int
 201 bitmap_ipmac_do_head(struct sk_buff *skb, const struct bitmap_ipmac *map)
 202 {
 203         return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
 204                nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
 205 }
 206 
 207 static int
 208 bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
 209                   const struct xt_action_param *par,
 210                   enum ipset_adt adt, struct ip_set_adt_opt *opt)
 211 {
 212         struct bitmap_ipmac *map = set->data;
 213         ipset_adtfn adtfn = set->variant->adt[adt];
 214         struct bitmap_ipmac_adt_elem e = { .id = 0, .add_mac = 1 };
 215         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 216         u32 ip;
 217 
 218         ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
 219         if (ip < map->first_ip || ip > map->last_ip)
 220                 return -IPSET_ERR_BITMAP_RANGE;
 221 
 222         /* Backward compatibility: we don't check the second flag */
 223         if (skb_mac_header(skb) < skb->head ||
 224             (skb_mac_header(skb) + ETH_HLEN) > skb->data)
 225                 return -EINVAL;
 226 
 227         e.id = ip_to_id(map, ip);
 228 
 229         if (opt->flags & IPSET_DIM_TWO_SRC)
 230                 ether_addr_copy(e.ether, eth_hdr(skb)->h_source);
 231         else
 232                 ether_addr_copy(e.ether, eth_hdr(skb)->h_dest);
 233 
 234         if (is_zero_ether_addr(e.ether))
 235                 return -EINVAL;
 236 
 237         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 238 }
 239 
 240 static int
 241 bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
 242                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 243 {
 244         const struct bitmap_ipmac *map = set->data;
 245         ipset_adtfn adtfn = set->variant->adt[adt];
 246         struct bitmap_ipmac_adt_elem e = { .id = 0 };
 247         struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 248         u32 ip = 0;
 249         int ret = 0;
 250 
 251         if (tb[IPSET_ATTR_LINENO])
 252                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 253 
 254         if (unlikely(!tb[IPSET_ATTR_IP]))
 255                 return -IPSET_ERR_PROTOCOL;
 256 
 257         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
 258         if (ret)
 259                 return ret;
 260 
 261         ret = ip_set_get_extensions(set, tb, &ext);
 262         if (ret)
 263                 return ret;
 264 
 265         if (ip < map->first_ip || ip > map->last_ip)
 266                 return -IPSET_ERR_BITMAP_RANGE;
 267 
 268         e.id = ip_to_id(map, ip);
 269         if (tb[IPSET_ATTR_ETHER]) {
 270                 if (nla_len(tb[IPSET_ATTR_ETHER]) != ETH_ALEN)
 271                         return -IPSET_ERR_PROTOCOL;
 272                 memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
 273                 e.add_mac = 1;
 274         }
 275         ret = adtfn(set, &e, &ext, &ext, flags);
 276 
 277         return ip_set_eexist(ret, flags) ? 0 : ret;
 278 }
 279 
 280 static bool
 281 bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
 282 {
 283         const struct bitmap_ipmac *x = a->data;
 284         const struct bitmap_ipmac *y = b->data;
 285 
 286         return x->first_ip == y->first_ip &&
 287                x->last_ip == y->last_ip &&
 288                a->timeout == b->timeout &&
 289                a->extensions == b->extensions;
 290 }
 291 
 292 /* Plain variant */
 293 
 294 #include "ip_set_bitmap_gen.h"
 295 
 296 /* Create bitmap:ip,mac type of sets */
 297 
 298 static bool
 299 init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
 300                u32 first_ip, u32 last_ip, u32 elements)
 301 {
 302         map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN);
 303         if (!map->members)
 304                 return false;
 305         map->first_ip = first_ip;
 306         map->last_ip = last_ip;
 307         map->elements = elements;
 308         set->timeout = IPSET_NO_TIMEOUT;
 309 
 310         map->set = set;
 311         set->data = map;
 312         set->family = NFPROTO_IPV4;
 313 
 314         return true;
 315 }
 316 
 317 static int
 318 bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
 319                     u32 flags)
 320 {
 321         u32 first_ip = 0, last_ip = 0;
 322         u64 elements;
 323         struct bitmap_ipmac *map;
 324         int ret;
 325 
 326         if (unlikely(!tb[IPSET_ATTR_IP] ||
 327                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 328                      !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
 329                 return -IPSET_ERR_PROTOCOL;
 330 
 331         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
 332         if (ret)
 333                 return ret;
 334 
 335         if (tb[IPSET_ATTR_IP_TO]) {
 336                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
 337                 if (ret)
 338                         return ret;
 339                 if (first_ip > last_ip)
 340                         swap(first_ip, last_ip);
 341         } else if (tb[IPSET_ATTR_CIDR]) {
 342                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 343 
 344                 if (cidr >= HOST_MASK)
 345                         return -IPSET_ERR_INVALID_CIDR;
 346                 ip_set_mask_from_to(first_ip, last_ip, cidr);
 347         } else {
 348                 return -IPSET_ERR_PROTOCOL;
 349         }
 350 
 351         elements = (u64)last_ip - first_ip + 1;
 352 
 353         if (elements > IPSET_BITMAP_MAX_RANGE + 1)
 354                 return -IPSET_ERR_BITMAP_RANGE_SIZE;
 355 
 356         set->dsize = ip_set_elem_len(set, tb,
 357                                      sizeof(struct bitmap_ipmac_elem),
 358                                      __alignof__(struct bitmap_ipmac_elem));
 359         map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
 360         if (!map)
 361                 return -ENOMEM;
 362 
 363         map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
 364         set->variant = &bitmap_ipmac;
 365         if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
 366                 kfree(map);
 367                 return -ENOMEM;
 368         }
 369         if (tb[IPSET_ATTR_TIMEOUT]) {
 370                 set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 371                 bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
 372         }
 373         return 0;
 374 }
 375 
 376 static struct ip_set_type bitmap_ipmac_type = {
 377         .name           = "bitmap:ip,mac",
 378         .protocol       = IPSET_PROTOCOL,
 379         .features       = IPSET_TYPE_IP | IPSET_TYPE_MAC,
 380         .dimension      = IPSET_DIM_TWO,
 381         .family         = NFPROTO_IPV4,
 382         .revision_min   = IPSET_TYPE_REV_MIN,
 383         .revision_max   = IPSET_TYPE_REV_MAX,
 384         .create         = bitmap_ipmac_create,
 385         .create_policy  = {
 386                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 387                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 388                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 389                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 390                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 391         },
 392         .adt_policy     = {
 393                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 394                 [IPSET_ATTR_ETHER]      = { .type = NLA_BINARY,
 395                                             .len  = ETH_ALEN },
 396                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 397                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 398                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 399                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 400                 [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING,
 401                                             .len  = IPSET_MAX_COMMENT_SIZE },
 402                 [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
 403                 [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
 404                 [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
 405         },
 406         .me             = THIS_MODULE,
 407 };
 408 
 409 static int __init
 410 bitmap_ipmac_init(void)
 411 {
 412         return ip_set_type_register(&bitmap_ipmac_type);
 413 }
 414 
 415 static void __exit
 416 bitmap_ipmac_fini(void)
 417 {
 418         rcu_barrier();
 419         ip_set_type_unregister(&bitmap_ipmac_type);
 420 }
 421 
 422 module_init(bitmap_ipmac_init);
 423 module_exit(bitmap_ipmac_fini);

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