linux/net/netfilter/ipset/ip_set_bitmap_port.c
<<
>>
Prefs
   1/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
   2 *
   3 * This program is free software; you can redistribute it and/or modify
   4 * it under the terms of the GNU General Public License version 2 as
   5 * published by the Free Software Foundation.
   6 */
   7
   8/* Kernel module implementing an IP set type: the bitmap:port type */
   9
  10#include <linux/module.h>
  11#include <linux/ip.h>
  12#include <linux/skbuff.h>
  13#include <linux/errno.h>
  14#include <linux/netlink.h>
  15#include <linux/jiffies.h>
  16#include <linux/timer.h>
  17#include <net/netlink.h>
  18
  19#include <linux/netfilter/ipset/ip_set.h>
  20#include <linux/netfilter/ipset/ip_set_bitmap.h>
  21#include <linux/netfilter/ipset/ip_set_getport.h>
  22#define IP_SET_BITMAP_TIMEOUT
  23#include <linux/netfilter/ipset/ip_set_timeout.h>
  24
  25#define REVISION_MIN    0
  26#define REVISION_MAX    0
  27
  28MODULE_LICENSE("GPL");
  29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
  30IP_SET_MODULE_DESC("bitmap:port", REVISION_MIN, REVISION_MAX);
  31MODULE_ALIAS("ip_set_bitmap:port");
  32
  33/* Type structure */
  34struct bitmap_port {
  35        void *members;          /* the set members */
  36        u16 first_port;         /* host byte order, included in range */
  37        u16 last_port;          /* host byte order, included in range */
  38        size_t memsize;         /* members size */
  39        u32 timeout;            /* timeout parameter */
  40        struct timer_list gc;   /* garbage collection */
  41};
  42
  43/* Base variant */
  44
  45static int
  46bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
  47{
  48        const struct bitmap_port *map = set->data;
  49        u16 id = *(u16 *)value;
  50
  51        return !!test_bit(id, map->members);
  52}
  53
  54static int
  55bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
  56{
  57        struct bitmap_port *map = set->data;
  58        u16 id = *(u16 *)value;
  59
  60        if (test_and_set_bit(id, map->members))
  61                return -IPSET_ERR_EXIST;
  62
  63        return 0;
  64}
  65
  66static int
  67bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
  68{
  69        struct bitmap_port *map = set->data;
  70        u16 id = *(u16 *)value;
  71
  72        if (!test_and_clear_bit(id, map->members))
  73                return -IPSET_ERR_EXIST;
  74
  75        return 0;
  76}
  77
  78static int
  79bitmap_port_list(const struct ip_set *set,
  80                 struct sk_buff *skb, struct netlink_callback *cb)
  81{
  82        const struct bitmap_port *map = set->data;
  83        struct nlattr *atd, *nested;
  84        u16 id, first = cb->args[2];
  85        u16 last = map->last_port - map->first_port;
  86
  87        atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
  88        if (!atd)
  89                return -EMSGSIZE;
  90        for (; cb->args[2] <= last; cb->args[2]++) {
  91                id = cb->args[2];
  92                if (!test_bit(id, map->members))
  93                        continue;
  94                nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
  95                if (!nested) {
  96                        if (id == first) {
  97                                nla_nest_cancel(skb, atd);
  98                                return -EMSGSIZE;
  99                        } else
 100                                goto nla_put_failure;
 101                }
 102                if (nla_put_net16(skb, IPSET_ATTR_PORT,
 103                                  htons(map->first_port + id)))
 104                        goto nla_put_failure;
 105                ipset_nest_end(skb, nested);
 106        }
 107        ipset_nest_end(skb, atd);
 108        /* Set listing finished */
 109        cb->args[2] = 0;
 110
 111        return 0;
 112
 113nla_put_failure:
 114        nla_nest_cancel(skb, nested);
 115        ipset_nest_end(skb, atd);
 116        if (unlikely(id == first)) {
 117                cb->args[2] = 0;
 118                return -EMSGSIZE;
 119        }
 120        return 0;
 121}
 122
 123/* Timeout variant */
 124
 125static int
 126bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
 127{
 128        const struct bitmap_port *map = set->data;
 129        const unsigned long *members = map->members;
 130        u16 id = *(u16 *)value;
 131
 132        return ip_set_timeout_test(members[id]);
 133}
 134
 135static int
 136bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
 137{
 138        struct bitmap_port *map = set->data;
 139        unsigned long *members = map->members;
 140        u16 id = *(u16 *)value;
 141
 142        if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
 143                return -IPSET_ERR_EXIST;
 144
 145        members[id] = ip_set_timeout_set(timeout);
 146
 147        return 0;
 148}
 149
 150static int
 151bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
 152{
 153        struct bitmap_port *map = set->data;
 154        unsigned long *members = map->members;
 155        u16 id = *(u16 *)value;
 156        int ret = -IPSET_ERR_EXIST;
 157
 158        if (ip_set_timeout_test(members[id]))
 159                ret = 0;
 160
 161        members[id] = IPSET_ELEM_UNSET;
 162        return ret;
 163}
 164
 165static int
 166bitmap_port_tlist(const struct ip_set *set,
 167                  struct sk_buff *skb, struct netlink_callback *cb)
 168{
 169        const struct bitmap_port *map = set->data;
 170        struct nlattr *adt, *nested;
 171        u16 id, first = cb->args[2];
 172        u16 last = map->last_port - map->first_port;
 173        const unsigned long *members = map->members;
 174
 175        adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
 176        if (!adt)
 177                return -EMSGSIZE;
 178        for (; cb->args[2] <= last; cb->args[2]++) {
 179                id = cb->args[2];
 180                if (!ip_set_timeout_test(members[id]))
 181                        continue;
 182                nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
 183                if (!nested) {
 184                        if (id == first) {
 185                                nla_nest_cancel(skb, adt);
 186                                return -EMSGSIZE;
 187                        } else
 188                                goto nla_put_failure;
 189                }
 190                if (nla_put_net16(skb, IPSET_ATTR_PORT,
 191                                  htons(map->first_port + id)) ||
 192                    nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
 193                                  htonl(ip_set_timeout_get(members[id]))))
 194                        goto nla_put_failure;
 195                ipset_nest_end(skb, nested);
 196        }
 197        ipset_nest_end(skb, adt);
 198
 199        /* Set listing finished */
 200        cb->args[2] = 0;
 201
 202        return 0;
 203
 204nla_put_failure:
 205        nla_nest_cancel(skb, nested);
 206        ipset_nest_end(skb, adt);
 207        if (unlikely(id == first)) {
 208                cb->args[2] = 0;
 209                return -EMSGSIZE;
 210        }
 211        return 0;
 212}
 213
 214static int
 215bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
 216                 const struct xt_action_param *par,
 217                 enum ipset_adt adt, const struct ip_set_adt_opt *opt)
 218{
 219        struct bitmap_port *map = set->data;
 220        ipset_adtfn adtfn = set->variant->adt[adt];
 221        __be16 __port;
 222        u16 port = 0;
 223
 224        if (!ip_set_get_ip_port(skb, opt->family,
 225                                opt->flags & IPSET_DIM_ONE_SRC, &__port))
 226                return -EINVAL;
 227
 228        port = ntohs(__port);
 229
 230        if (port < map->first_port || port > map->last_port)
 231                return -IPSET_ERR_BITMAP_RANGE;
 232
 233        port -= map->first_port;
 234
 235        return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
 236}
 237
 238static int
 239bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
 240                 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 241{
 242        struct bitmap_port *map = set->data;
 243        ipset_adtfn adtfn = set->variant->adt[adt];
 244        u32 timeout = map->timeout;
 245        u32 port;       /* wraparound */
 246        u16 id, port_to;
 247        int ret = 0;
 248
 249        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 250                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 251                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
 252                return -IPSET_ERR_PROTOCOL;
 253
 254        if (tb[IPSET_ATTR_LINENO])
 255                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 256
 257        port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
 258        if (port < map->first_port || port > map->last_port)
 259                return -IPSET_ERR_BITMAP_RANGE;
 260
 261        if (tb[IPSET_ATTR_TIMEOUT]) {
 262                if (!with_timeout(map->timeout))
 263                        return -IPSET_ERR_TIMEOUT;
 264                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 265        }
 266
 267        if (adt == IPSET_TEST) {
 268                id = port - map->first_port;
 269                return adtfn(set, &id, timeout, flags);
 270        }
 271
 272        if (tb[IPSET_ATTR_PORT_TO]) {
 273                port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 274                if (port > port_to) {
 275                        swap(port, port_to);
 276                        if (port < map->first_port)
 277                                return -IPSET_ERR_BITMAP_RANGE;
 278                }
 279        } else
 280                port_to = port;
 281
 282        if (port_to > map->last_port)
 283                return -IPSET_ERR_BITMAP_RANGE;
 284
 285        for (; port <= port_to; port++) {
 286                id = port - map->first_port;
 287                ret = adtfn(set, &id, timeout, flags);
 288
 289                if (ret && !ip_set_eexist(ret, flags))
 290                        return ret;
 291                else
 292                        ret = 0;
 293        }
 294        return ret;
 295}
 296
 297static void
 298bitmap_port_destroy(struct ip_set *set)
 299{
 300        struct bitmap_port *map = set->data;
 301
 302        if (with_timeout(map->timeout))
 303                del_timer_sync(&map->gc);
 304
 305        ip_set_free(map->members);
 306        kfree(map);
 307
 308        set->data = NULL;
 309}
 310
 311static void
 312bitmap_port_flush(struct ip_set *set)
 313{
 314        struct bitmap_port *map = set->data;
 315
 316        memset(map->members, 0, map->memsize);
 317}
 318
 319static int
 320bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
 321{
 322        const struct bitmap_port *map = set->data;
 323        struct nlattr *nested;
 324
 325        nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
 326        if (!nested)
 327                goto nla_put_failure;
 328        if (nla_put_net16(skb, IPSET_ATTR_PORT, htons(map->first_port)) ||
 329            nla_put_net16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)) ||
 330            nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
 331            nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
 332                          htonl(sizeof(*map) + map->memsize)) ||
 333            (with_timeout(map->timeout) &&
 334             nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))))
 335                goto nla_put_failure;
 336        ipset_nest_end(skb, nested);
 337
 338        return 0;
 339nla_put_failure:
 340        return -EMSGSIZE;
 341}
 342
 343static bool
 344bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
 345{
 346        const struct bitmap_port *x = a->data;
 347        const struct bitmap_port *y = b->data;
 348
 349        return x->first_port == y->first_port &&
 350               x->last_port == y->last_port &&
 351               x->timeout == y->timeout;
 352}
 353
 354static const struct ip_set_type_variant bitmap_port = {
 355        .kadt   = bitmap_port_kadt,
 356        .uadt   = bitmap_port_uadt,
 357        .adt    = {
 358                [IPSET_ADD] = bitmap_port_add,
 359                [IPSET_DEL] = bitmap_port_del,
 360                [IPSET_TEST] = bitmap_port_test,
 361        },
 362        .destroy = bitmap_port_destroy,
 363        .flush  = bitmap_port_flush,
 364        .head   = bitmap_port_head,
 365        .list   = bitmap_port_list,
 366        .same_set = bitmap_port_same_set,
 367};
 368
 369static const struct ip_set_type_variant bitmap_tport = {
 370        .kadt   = bitmap_port_kadt,
 371        .uadt   = bitmap_port_uadt,
 372        .adt    = {
 373                [IPSET_ADD] = bitmap_port_tadd,
 374                [IPSET_DEL] = bitmap_port_tdel,
 375                [IPSET_TEST] = bitmap_port_ttest,
 376        },
 377        .destroy = bitmap_port_destroy,
 378        .flush  = bitmap_port_flush,
 379        .head   = bitmap_port_head,
 380        .list   = bitmap_port_tlist,
 381        .same_set = bitmap_port_same_set,
 382};
 383
 384static void
 385bitmap_port_gc(unsigned long ul_set)
 386{
 387        struct ip_set *set = (struct ip_set *) ul_set;
 388        struct bitmap_port *map = set->data;
 389        unsigned long *table = map->members;
 390        u32 id; /* wraparound */
 391        u16 last = map->last_port - map->first_port;
 392
 393        /* We run parallel with other readers (test element)
 394         * but adding/deleting new entries is locked out */
 395        read_lock_bh(&set->lock);
 396        for (id = 0; id <= last; id++)
 397                if (ip_set_timeout_expired(table[id]))
 398                        table[id] = IPSET_ELEM_UNSET;
 399        read_unlock_bh(&set->lock);
 400
 401        map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
 402        add_timer(&map->gc);
 403}
 404
 405static void
 406bitmap_port_gc_init(struct ip_set *set)
 407{
 408        struct bitmap_port *map = set->data;
 409
 410        init_timer(&map->gc);
 411        map->gc.data = (unsigned long) set;
 412        map->gc.function = bitmap_port_gc;
 413        map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
 414        add_timer(&map->gc);
 415}
 416
 417/* Create bitmap:ip type of sets */
 418
 419static bool
 420init_map_port(struct ip_set *set, struct bitmap_port *map,
 421              u16 first_port, u16 last_port)
 422{
 423        map->members = ip_set_alloc(map->memsize);
 424        if (!map->members)
 425                return false;
 426        map->first_port = first_port;
 427        map->last_port = last_port;
 428        map->timeout = IPSET_NO_TIMEOUT;
 429
 430        set->data = map;
 431        set->family = NFPROTO_UNSPEC;
 432
 433        return true;
 434}
 435
 436static int
 437bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
 438                 u32 flags)
 439{
 440        struct bitmap_port *map;
 441        u16 first_port, last_port;
 442
 443        if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 444                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 445                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
 446                return -IPSET_ERR_PROTOCOL;
 447
 448        first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
 449        last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 450        if (first_port > last_port) {
 451                u16 tmp = first_port;
 452
 453                first_port = last_port;
 454                last_port = tmp;
 455        }
 456
 457        map = kzalloc(sizeof(*map), GFP_KERNEL);
 458        if (!map)
 459                return -ENOMEM;
 460
 461        if (tb[IPSET_ATTR_TIMEOUT]) {
 462                map->memsize = (last_port - first_port + 1)
 463                               * sizeof(unsigned long);
 464
 465                if (!init_map_port(set, map, first_port, last_port)) {
 466                        kfree(map);
 467                        return -ENOMEM;
 468                }
 469
 470                map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 471                set->variant = &bitmap_tport;
 472
 473                bitmap_port_gc_init(set);
 474        } else {
 475                map->memsize = bitmap_bytes(0, last_port - first_port);
 476                pr_debug("memsize: %zu\n", map->memsize);
 477                if (!init_map_port(set, map, first_port, last_port)) {
 478                        kfree(map);
 479                        return -ENOMEM;
 480                }
 481
 482                set->variant = &bitmap_port;
 483        }
 484        return 0;
 485}
 486
 487static struct ip_set_type bitmap_port_type = {
 488        .name           = "bitmap:port",
 489        .protocol       = IPSET_PROTOCOL,
 490        .features       = IPSET_TYPE_PORT,
 491        .dimension      = IPSET_DIM_ONE,
 492        .family         = NFPROTO_UNSPEC,
 493        .revision_min   = REVISION_MIN,
 494        .revision_max   = REVISION_MAX,
 495        .create         = bitmap_port_create,
 496        .create_policy  = {
 497                [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 498                [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 499                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 500        },
 501        .adt_policy     = {
 502                [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 503                [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 504                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 505                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 506        },
 507        .me             = THIS_MODULE,
 508};
 509
 510static int __init
 511bitmap_port_init(void)
 512{
 513        return ip_set_type_register(&bitmap_port_type);
 514}
 515
 516static void __exit
 517bitmap_port_fini(void)
 518{
 519        ip_set_type_unregister(&bitmap_port_type);
 520}
 521
 522module_init(bitmap_port_init);
 523module_exit(bitmap_port_fini);
 524