linux/net/netfilter/ipset/ip_set_bitmap_ip.c
<<
>>
Prefs
   1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
   2 *                         Patrick Schaaf <bof@bof.de>
   3 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License version 2 as
   7 * published by the Free Software Foundation.
   8 */
   9
  10/* Kernel module implementing an IP set type: the bitmap:ip type */
  11
  12#include <linux/module.h>
  13#include <linux/ip.h>
  14#include <linux/skbuff.h>
  15#include <linux/errno.h>
  16#include <linux/bitops.h>
  17#include <linux/spinlock.h>
  18#include <linux/netlink.h>
  19#include <linux/jiffies.h>
  20#include <linux/timer.h>
  21#include <net/netlink.h>
  22#include <net/tcp.h>
  23
  24#include <linux/netfilter/ipset/pfxlen.h>
  25#include <linux/netfilter/ipset/ip_set.h>
  26#include <linux/netfilter/ipset/ip_set_bitmap.h>
  27
  28#define REVISION_MIN    0
  29#define REVISION_MAX    1       /* Counter support added */
  30
  31MODULE_LICENSE("GPL");
  32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
  33IP_SET_MODULE_DESC("bitmap:ip", REVISION_MIN, REVISION_MAX);
  34MODULE_ALIAS("ip_set_bitmap:ip");
  35
  36#define MTYPE           bitmap_ip
  37
  38/* Type structure */
  39struct bitmap_ip {
  40        void *members;          /* the set members */
  41        void *extensions;       /* data extensions */
  42        u32 first_ip;           /* host byte order, included in range */
  43        u32 last_ip;            /* host byte order, included in range */
  44        u32 elements;           /* number of max elements in the set */
  45        u32 hosts;              /* number of hosts in a subnet */
  46        size_t memsize;         /* members size */
  47        size_t dsize;           /* extensions struct size */
  48        size_t offset[IPSET_OFFSET_MAX]; /* Offsets to extensions */
  49        u8 netmask;             /* subnet netmask */
  50        u32 timeout;            /* timeout parameter */
  51        struct timer_list gc;   /* garbage collection */
  52};
  53
  54/* ADT structure for generic function args */
  55struct bitmap_ip_adt_elem {
  56        u16 id;
  57};
  58
  59static inline u32
  60ip_to_id(const struct bitmap_ip *m, u32 ip)
  61{
  62        return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
  63}
  64
  65/* Common functions */
  66
  67static inline int
  68bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map)
  69{
  70        return !!test_bit(e->id, map->members);
  71}
  72
  73static inline int
  74bitmap_ip_gc_test(u16 id, const struct bitmap_ip *map)
  75{
  76        return !!test_bit(id, map->members);
  77}
  78
  79static inline int
  80bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map,
  81                 u32 flags)
  82{
  83        return !!test_and_set_bit(e->id, map->members);
  84}
  85
  86static inline int
  87bitmap_ip_do_del(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map)
  88{
  89        return !test_and_clear_bit(e->id, map->members);
  90}
  91
  92static inline int
  93bitmap_ip_do_list(struct sk_buff *skb, const struct bitmap_ip *map, u32 id)
  94{
  95        return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
  96                        htonl(map->first_ip + id * map->hosts));
  97}
  98
  99static inline int
 100bitmap_ip_do_head(struct sk_buff *skb, const struct bitmap_ip *map)
 101{
 102        return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
 103               nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
 104               (map->netmask != 32 &&
 105                nla_put_u8(skb, IPSET_ATTR_NETMASK, map->netmask));
 106}
 107
 108static int
 109bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
 110               const struct xt_action_param *par,
 111               enum ipset_adt adt, struct ip_set_adt_opt *opt)
 112{
 113        struct bitmap_ip *map = set->data;
 114        ipset_adtfn adtfn = set->variant->adt[adt];
 115        struct bitmap_ip_adt_elem e = { };
 116        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
 117        u32 ip;
 118
 119        ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
 120        if (ip < map->first_ip || ip > map->last_ip)
 121                return -IPSET_ERR_BITMAP_RANGE;
 122
 123        e.id = ip_to_id(map, ip);
 124
 125        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 126}
 127
 128static int
 129bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 130               enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 131{
 132        struct bitmap_ip *map = set->data;
 133        ipset_adtfn adtfn = set->variant->adt[adt];
 134        u32 ip, ip_to;
 135        struct bitmap_ip_adt_elem e = { };
 136        struct ip_set_ext ext = IP_SET_INIT_UEXT(map);
 137        int ret = 0;
 138
 139        if (unlikely(!tb[IPSET_ATTR_IP] ||
 140                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 141                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
 142                     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
 143                return -IPSET_ERR_PROTOCOL;
 144
 145        if (tb[IPSET_ATTR_LINENO])
 146                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 147
 148        ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
 149              ip_set_get_extensions(set, tb, &ext);
 150        if (ret)
 151                return ret;
 152
 153        if (ip < map->first_ip || ip > map->last_ip)
 154                return -IPSET_ERR_BITMAP_RANGE;
 155
 156        if (adt == IPSET_TEST) {
 157                e.id = ip_to_id(map, ip);
 158                return adtfn(set, &e, &ext, &ext, flags);
 159        }
 160
 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                        if (ip < map->first_ip)
 168                                return -IPSET_ERR_BITMAP_RANGE;
 169                }
 170        } else if (tb[IPSET_ATTR_CIDR]) {
 171                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 172
 173                if (!cidr || cidr > 32)
 174                        return -IPSET_ERR_INVALID_CIDR;
 175                ip_set_mask_from_to(ip, ip_to, cidr);
 176        } else
 177                ip_to = ip;
 178
 179        if (ip_to > map->last_ip)
 180                return -IPSET_ERR_BITMAP_RANGE;
 181
 182        for (; !before(ip_to, ip); ip += map->hosts) {
 183                e.id = ip_to_id(map, ip);
 184                ret = adtfn(set, &e, &ext, &ext, flags);
 185
 186                if (ret && !ip_set_eexist(ret, flags))
 187                        return ret;
 188                else
 189                        ret = 0;
 190        }
 191        return ret;
 192}
 193
 194static bool
 195bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
 196{
 197        const struct bitmap_ip *x = a->data;
 198        const struct bitmap_ip *y = b->data;
 199
 200        return x->first_ip == y->first_ip &&
 201               x->last_ip == y->last_ip &&
 202               x->netmask == y->netmask &&
 203               x->timeout == y->timeout &&
 204               a->extensions == b->extensions;
 205}
 206
 207/* Plain variant */
 208
 209struct bitmap_ip_elem {
 210};
 211
 212/* Timeout variant */
 213
 214struct bitmap_ipt_elem {
 215        unsigned long timeout;
 216};
 217
 218/* Plain variant with counter */
 219
 220struct bitmap_ipc_elem {
 221        struct ip_set_counter counter;
 222};
 223
 224/* Timeout variant with counter */
 225
 226struct bitmap_ipct_elem {
 227        unsigned long timeout;
 228        struct ip_set_counter counter;
 229};
 230
 231#include "ip_set_bitmap_gen.h"
 232
 233/* Create bitmap:ip type of sets */
 234
 235static bool
 236init_map_ip(struct ip_set *set, struct bitmap_ip *map,
 237            u32 first_ip, u32 last_ip,
 238            u32 elements, u32 hosts, u8 netmask)
 239{
 240        map->members = ip_set_alloc(map->memsize);
 241        if (!map->members)
 242                return false;
 243        if (map->dsize) {
 244                map->extensions = ip_set_alloc(map->dsize * elements);
 245                if (!map->extensions) {
 246                        kfree(map->members);
 247                        return false;
 248                }
 249        }
 250        map->first_ip = first_ip;
 251        map->last_ip = last_ip;
 252        map->elements = elements;
 253        map->hosts = hosts;
 254        map->netmask = netmask;
 255        map->timeout = IPSET_NO_TIMEOUT;
 256
 257        set->data = map;
 258        set->family = NFPROTO_IPV4;
 259
 260        return true;
 261}
 262
 263static int
 264bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
 265{
 266        struct bitmap_ip *map;
 267        u32 first_ip, last_ip, hosts, cadt_flags = 0;
 268        u64 elements;
 269        u8 netmask = 32;
 270        int ret;
 271
 272        if (unlikely(!tb[IPSET_ATTR_IP] ||
 273                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 274                     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
 275                return -IPSET_ERR_PROTOCOL;
 276
 277        ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
 278        if (ret)
 279                return ret;
 280
 281        if (tb[IPSET_ATTR_IP_TO]) {
 282                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
 283                if (ret)
 284                        return ret;
 285                if (first_ip > last_ip) {
 286                        u32 tmp = first_ip;
 287
 288                        first_ip = last_ip;
 289                        last_ip = tmp;
 290                }
 291        } else if (tb[IPSET_ATTR_CIDR]) {
 292                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 293
 294                if (cidr >= 32)
 295                        return -IPSET_ERR_INVALID_CIDR;
 296                ip_set_mask_from_to(first_ip, last_ip, cidr);
 297        } else
 298                return -IPSET_ERR_PROTOCOL;
 299
 300        if (tb[IPSET_ATTR_NETMASK]) {
 301                netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
 302
 303                if (netmask > 32)
 304                        return -IPSET_ERR_INVALID_NETMASK;
 305
 306                first_ip &= ip_set_hostmask(netmask);
 307                last_ip |= ~ip_set_hostmask(netmask);
 308        }
 309
 310        if (netmask == 32) {
 311                hosts = 1;
 312                elements = (u64)last_ip - first_ip + 1;
 313        } else {
 314                u8 mask_bits;
 315                u32 mask;
 316
 317                mask = range_to_mask(first_ip, last_ip, &mask_bits);
 318
 319                if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
 320                    netmask <= mask_bits)
 321                        return -IPSET_ERR_BITMAP_RANGE;
 322
 323                pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
 324                hosts = 2 << (32 - netmask - 1);
 325                elements = 2 << (netmask - mask_bits - 1);
 326        }
 327        if (elements > IPSET_BITMAP_MAX_RANGE + 1)
 328                return -IPSET_ERR_BITMAP_RANGE_SIZE;
 329
 330        pr_debug("hosts %u, elements %llu\n",
 331                 hosts, (unsigned long long)elements);
 332
 333        map = kzalloc(sizeof(*map), GFP_KERNEL);
 334        if (!map)
 335                return -ENOMEM;
 336
 337        map->memsize = bitmap_bytes(0, elements - 1);
 338        set->variant = &bitmap_ip;
 339        if (tb[IPSET_ATTR_CADT_FLAGS])
 340                cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
 341        if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
 342                set->extensions |= IPSET_EXT_COUNTER;
 343                if (tb[IPSET_ATTR_TIMEOUT]) {
 344                        map->dsize = sizeof(struct bitmap_ipct_elem);
 345                        map->offset[IPSET_OFFSET_TIMEOUT] =
 346                                offsetof(struct bitmap_ipct_elem, timeout);
 347                        map->offset[IPSET_OFFSET_COUNTER] =
 348                                offsetof(struct bitmap_ipct_elem, counter);
 349
 350                        if (!init_map_ip(set, map, first_ip, last_ip,
 351                                         elements, hosts, netmask)) {
 352                                kfree(map);
 353                                return -ENOMEM;
 354                        }
 355
 356                        map->timeout = ip_set_timeout_uget(
 357                                tb[IPSET_ATTR_TIMEOUT]);
 358                        set->extensions |= IPSET_EXT_TIMEOUT;
 359
 360                        bitmap_ip_gc_init(set, bitmap_ip_gc);
 361                } else {
 362                        map->dsize = sizeof(struct bitmap_ipc_elem);
 363                        map->offset[IPSET_OFFSET_COUNTER] =
 364                                offsetof(struct bitmap_ipc_elem, counter);
 365
 366                        if (!init_map_ip(set, map, first_ip, last_ip,
 367                                         elements, hosts, netmask)) {
 368                                kfree(map);
 369                                return -ENOMEM;
 370                        }
 371                }
 372        } else if (tb[IPSET_ATTR_TIMEOUT]) {
 373                map->dsize = sizeof(struct bitmap_ipt_elem);
 374                map->offset[IPSET_OFFSET_TIMEOUT] =
 375                        offsetof(struct bitmap_ipt_elem, timeout);
 376
 377                if (!init_map_ip(set, map, first_ip, last_ip,
 378                                 elements, hosts, netmask)) {
 379                        kfree(map);
 380                        return -ENOMEM;
 381                }
 382
 383                map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 384                set->extensions |= IPSET_EXT_TIMEOUT;
 385
 386                bitmap_ip_gc_init(set, bitmap_ip_gc);
 387        } else {
 388                map->dsize = 0;
 389                if (!init_map_ip(set, map, first_ip, last_ip,
 390                                 elements, hosts, netmask)) {
 391                        kfree(map);
 392                        return -ENOMEM;
 393                }
 394        }
 395        return 0;
 396}
 397
 398static struct ip_set_type bitmap_ip_type __read_mostly = {
 399        .name           = "bitmap:ip",
 400        .protocol       = IPSET_PROTOCOL,
 401        .features       = IPSET_TYPE_IP,
 402        .dimension      = IPSET_DIM_ONE,
 403        .family         = NFPROTO_IPV4,
 404        .revision_min   = REVISION_MIN,
 405        .revision_max   = REVISION_MAX,
 406        .create         = bitmap_ip_create,
 407        .create_policy  = {
 408                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 409                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 410                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 411                [IPSET_ATTR_NETMASK]    = { .type = NLA_U8  },
 412                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 413                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 414        },
 415        .adt_policy     = {
 416                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 417                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 418                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 419                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 420                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 421                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 422                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 423        },
 424        .me             = THIS_MODULE,
 425};
 426
 427static int __init
 428bitmap_ip_init(void)
 429{
 430        return ip_set_type_register(&bitmap_ip_type);
 431}
 432
 433static void __exit
 434bitmap_ip_fini(void)
 435{
 436        ip_set_type_unregister(&bitmap_ip_type);
 437}
 438
 439module_init(bitmap_ip_init);
 440module_exit(bitmap_ip_fini);
 441