linux/net/netfilter/ipset/ip_set_bitmap_port.c
<<
>>
Prefs
   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 bitmap:port type */
   5
   6#include <linux/module.h>
   7#include <linux/ip.h>
   8#include <linux/skbuff.h>
   9#include <linux/errno.h>
  10#include <linux/netlink.h>
  11#include <linux/jiffies.h>
  12#include <linux/timer.h>
  13#include <net/netlink.h>
  14
  15#include <linux/netfilter/ipset/ip_set.h>
  16#include <linux/netfilter/ipset/ip_set_bitmap.h>
  17#include <linux/netfilter/ipset/ip_set_getport.h>
  18
  19#define IPSET_TYPE_REV_MIN      0
  20/*                              1          Counter support added */
  21/*                              2          Comment support added */
  22#define IPSET_TYPE_REV_MAX      3       /* skbinfo support added */
  23
  24MODULE_LICENSE("GPL");
  25MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@netfilter.org>");
  26IP_SET_MODULE_DESC("bitmap:port", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  27MODULE_ALIAS("ip_set_bitmap:port");
  28
  29#define MTYPE           bitmap_port
  30
  31/* Type structure */
  32struct bitmap_port {
  33        unsigned long *members; /* the set members */
  34        u16 first_port;         /* host byte order, included in range */
  35        u16 last_port;          /* host byte order, included in range */
  36        u32 elements;           /* number of max elements in the set */
  37        size_t memsize;         /* members size */
  38        struct timer_list gc;   /* garbage collection */
  39        struct ip_set *set;     /* attached to this ip_set */
  40        unsigned char extensions[]      /* data extensions */
  41                __aligned(__alignof__(u64));
  42};
  43
  44/* ADT structure for generic function args */
  45struct bitmap_port_adt_elem {
  46        u16 id;
  47};
  48
  49static u16
  50port_to_id(const struct bitmap_port *m, u16 port)
  51{
  52        return port - m->first_port;
  53}
  54
  55/* Common functions */
  56
  57static int
  58bitmap_port_do_test(const struct bitmap_port_adt_elem *e,
  59                    const struct bitmap_port *map, size_t dsize)
  60{
  61        return !!test_bit(e->id, map->members);
  62}
  63
  64static int
  65bitmap_port_gc_test(u16 id, const struct bitmap_port *map, size_t dsize)
  66{
  67        return !!test_bit(id, map->members);
  68}
  69
  70static int
  71bitmap_port_do_add(const struct bitmap_port_adt_elem *e,
  72                   struct bitmap_port *map, u32 flags, size_t dsize)
  73{
  74        return !!test_bit(e->id, map->members);
  75}
  76
  77static int
  78bitmap_port_do_del(const struct bitmap_port_adt_elem *e,
  79                   struct bitmap_port *map)
  80{
  81        return !test_and_clear_bit(e->id, map->members);
  82}
  83
  84static int
  85bitmap_port_do_list(struct sk_buff *skb, const struct bitmap_port *map, u32 id,
  86                    size_t dsize)
  87{
  88        return nla_put_net16(skb, IPSET_ATTR_PORT,
  89                             htons(map->first_port + id));
  90}
  91
  92static int
  93bitmap_port_do_head(struct sk_buff *skb, const struct bitmap_port *map)
  94{
  95        return nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) ||
  96               nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
  97}
  98
  99static bool
 100ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
 101{
 102        bool ret;
 103        u8 proto;
 104
 105        switch (pf) {
 106        case NFPROTO_IPV4:
 107                ret = ip_set_get_ip4_port(skb, src, port, &proto);
 108                break;
 109        case NFPROTO_IPV6:
 110                ret = ip_set_get_ip6_port(skb, src, port, &proto);
 111                break;
 112        default:
 113                return false;
 114        }
 115        if (!ret)
 116                return ret;
 117        switch (proto) {
 118        case IPPROTO_TCP:
 119        case IPPROTO_UDP:
 120                return true;
 121        default:
 122                return false;
 123        }
 124}
 125
 126static int
 127bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
 128                 const struct xt_action_param *par,
 129                 enum ipset_adt adt, struct ip_set_adt_opt *opt)
 130{
 131        struct bitmap_port *map = set->data;
 132        ipset_adtfn adtfn = set->variant->adt[adt];
 133        struct bitmap_port_adt_elem e = { .id = 0 };
 134        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 135        __be16 __port;
 136        u16 port = 0;
 137
 138        if (!ip_set_get_ip_port(skb, opt->family,
 139                                opt->flags & IPSET_DIM_ONE_SRC, &__port))
 140                return -EINVAL;
 141
 142        port = ntohs(__port);
 143
 144        if (port < map->first_port || port > map->last_port)
 145                return -IPSET_ERR_BITMAP_RANGE;
 146
 147        e.id = port_to_id(map, port);
 148
 149        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 150}
 151
 152static int
 153bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
 154                 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 155{
 156        struct bitmap_port *map = set->data;
 157        ipset_adtfn adtfn = set->variant->adt[adt];
 158        struct bitmap_port_adt_elem e = { .id = 0 };
 159        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 160        u32 port;       /* wraparound */
 161        u16 port_to;
 162        int ret = 0;
 163
 164        if (tb[IPSET_ATTR_LINENO])
 165                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 166
 167        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 168                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO)))
 169                return -IPSET_ERR_PROTOCOL;
 170
 171        port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
 172        if (port < map->first_port || port > map->last_port)
 173                return -IPSET_ERR_BITMAP_RANGE;
 174        ret = ip_set_get_extensions(set, tb, &ext);
 175        if (ret)
 176                return ret;
 177
 178        if (adt == IPSET_TEST) {
 179                e.id = port_to_id(map, port);
 180                return adtfn(set, &e, &ext, &ext, flags);
 181        }
 182
 183        if (tb[IPSET_ATTR_PORT_TO]) {
 184                port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 185                if (port > port_to) {
 186                        swap(port, port_to);
 187                        if (port < map->first_port)
 188                                return -IPSET_ERR_BITMAP_RANGE;
 189                }
 190        } else {
 191                port_to = port;
 192        }
 193
 194        if (port_to > map->last_port)
 195                return -IPSET_ERR_BITMAP_RANGE;
 196
 197        for (; port <= port_to; port++) {
 198                e.id = port_to_id(map, port);
 199                ret = adtfn(set, &e, &ext, &ext, flags);
 200
 201                if (ret && !ip_set_eexist(ret, flags))
 202                        return ret;
 203
 204                ret = 0;
 205        }
 206        return ret;
 207}
 208
 209static bool
 210bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
 211{
 212        const struct bitmap_port *x = a->data;
 213        const struct bitmap_port *y = b->data;
 214
 215        return x->first_port == y->first_port &&
 216               x->last_port == y->last_port &&
 217               a->timeout == b->timeout &&
 218               a->extensions == b->extensions;
 219}
 220
 221/* Plain variant */
 222
 223struct bitmap_port_elem {
 224};
 225
 226#include "ip_set_bitmap_gen.h"
 227
 228/* Create bitmap:ip type of sets */
 229
 230static bool
 231init_map_port(struct ip_set *set, struct bitmap_port *map,
 232              u16 first_port, u16 last_port)
 233{
 234        map->members = bitmap_zalloc(map->elements, GFP_KERNEL | __GFP_NOWARN);
 235        if (!map->members)
 236                return false;
 237        map->first_port = first_port;
 238        map->last_port = last_port;
 239        set->timeout = IPSET_NO_TIMEOUT;
 240
 241        map->set = set;
 242        set->data = map;
 243        set->family = NFPROTO_UNSPEC;
 244
 245        return true;
 246}
 247
 248static int
 249bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
 250                   u32 flags)
 251{
 252        struct bitmap_port *map;
 253        u16 first_port, last_port;
 254        u32 elements;
 255
 256        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 257                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 258                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 259                     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
 260                return -IPSET_ERR_PROTOCOL;
 261
 262        first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
 263        last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 264        if (first_port > last_port)
 265                swap(first_port, last_port);
 266
 267        elements = last_port - first_port + 1;
 268        set->dsize = ip_set_elem_len(set, tb, 0, 0);
 269        map = ip_set_alloc(sizeof(*map) + elements * set->dsize);
 270        if (!map)
 271                return -ENOMEM;
 272
 273        map->elements = elements;
 274        map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
 275        set->variant = &bitmap_port;
 276        if (!init_map_port(set, map, first_port, last_port)) {
 277                ip_set_free(map);
 278                return -ENOMEM;
 279        }
 280        if (tb[IPSET_ATTR_TIMEOUT]) {
 281                set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 282                bitmap_port_gc_init(set, bitmap_port_gc);
 283        }
 284        return 0;
 285}
 286
 287static struct ip_set_type bitmap_port_type = {
 288        .name           = "bitmap:port",
 289        .protocol       = IPSET_PROTOCOL,
 290        .features       = IPSET_TYPE_PORT,
 291        .dimension      = IPSET_DIM_ONE,
 292        .family         = NFPROTO_UNSPEC,
 293        .revision_min   = IPSET_TYPE_REV_MIN,
 294        .revision_max   = IPSET_TYPE_REV_MAX,
 295        .create         = bitmap_port_create,
 296        .create_policy  = {
 297                [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 298                [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 299                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 300                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 301        },
 302        .adt_policy     = {
 303                [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 304                [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 305                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 306                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 307                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 308                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 309                [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING,
 310                                            .len  = IPSET_MAX_COMMENT_SIZE },
 311                [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
 312                [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
 313                [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
 314        },
 315        .me             = THIS_MODULE,
 316};
 317
 318static int __init
 319bitmap_port_init(void)
 320{
 321        return ip_set_type_register(&bitmap_port_type);
 322}
 323
 324static void __exit
 325bitmap_port_fini(void)
 326{
 327        rcu_barrier();
 328        ip_set_type_unregister(&bitmap_port_type);
 329}
 330
 331module_init(bitmap_port_init);
 332module_exit(bitmap_port_fini);
 333