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 IPSET_TYPE_REV_MIN      0
  29/*                              1          Counter support added */
  30/*                              2          Comment support added */
  31#define IPSET_TYPE_REV_MAX      3       /* skbinfo support added */
  32
  33MODULE_LICENSE("GPL");
  34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
  35IP_SET_MODULE_DESC("bitmap:ip", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
  36MODULE_ALIAS("ip_set_bitmap:ip");
  37
  38#define MTYPE           bitmap_ip
  39
  40/* Type structure */
  41struct bitmap_ip {
  42        void *members;          /* the set members */
  43        void *extensions;       /* data extensions */
  44        u32 first_ip;           /* host byte order, included in range */
  45        u32 last_ip;            /* host byte order, included in range */
  46        u32 elements;           /* number of max elements in the set */
  47        u32 hosts;              /* number of hosts in a subnet */
  48        size_t memsize;         /* members size */
  49        u8 netmask;             /* subnet netmask */
  50        struct timer_list gc;   /* garbage collection */
  51};
  52
  53/* ADT structure for generic function args */
  54struct bitmap_ip_adt_elem {
  55        u16 id;
  56};
  57
  58static inline u32
  59ip_to_id(const struct bitmap_ip *m, u32 ip)
  60{
  61        return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
  62}
  63
  64/* Common functions */
  65
  66static inline int
  67bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e,
  68                  struct bitmap_ip *map, size_t dsize)
  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, size_t dsize)
  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, size_t dsize)
  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                  size_t dsize)
  95{
  96        return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
  97                        htonl(map->first_ip + id * map->hosts));
  98}
  99
 100static inline int
 101bitmap_ip_do_head(struct sk_buff *skb, const struct bitmap_ip *map)
 102{
 103        return nla_put_ipaddr4(skb, IPSET_ATTR_IP, htonl(map->first_ip)) ||
 104               nla_put_ipaddr4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)) ||
 105               (map->netmask != 32 &&
 106                nla_put_u8(skb, IPSET_ATTR_NETMASK, map->netmask));
 107}
 108
 109static int
 110bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
 111               const struct xt_action_param *par,
 112               enum ipset_adt adt, struct ip_set_adt_opt *opt)
 113{
 114        struct bitmap_ip *map = set->data;
 115        ipset_adtfn adtfn = set->variant->adt[adt];
 116        struct bitmap_ip_adt_elem e = { .id = 0 };
 117        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
 118        u32 ip;
 119
 120        ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
 121        if (ip < map->first_ip || ip > map->last_ip)
 122                return -IPSET_ERR_BITMAP_RANGE;
 123
 124        e.id = ip_to_id(map, ip);
 125
 126        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 127}
 128
 129static int
 130bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
 131               enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 132{
 133        struct bitmap_ip *map = set->data;
 134        ipset_adtfn adtfn = set->variant->adt[adt];
 135        u32 ip = 0, ip_to = 0;
 136        struct bitmap_ip_adt_elem e = { .id = 0 };
 137        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
 138        int ret = 0;
 139
 140        if (unlikely(!tb[IPSET_ATTR_IP] ||
 141                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 142                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
 143                     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)   ||
 144                     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
 145                     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
 146                     !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
 147                return -IPSET_ERR_PROTOCOL;
 148
 149        if (tb[IPSET_ATTR_LINENO])
 150                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 151
 152        ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
 153              ip_set_get_extensions(set, tb, &ext);
 154        if (ret)
 155                return ret;
 156
 157        if (ip < map->first_ip || ip > map->last_ip)
 158                return -IPSET_ERR_BITMAP_RANGE;
 159
 160        if (adt == IPSET_TEST) {
 161                e.id = ip_to_id(map, ip);
 162                return adtfn(set, &e, &ext, &ext, flags);
 163        }
 164
 165        if (tb[IPSET_ATTR_IP_TO]) {
 166                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
 167                if (ret)
 168                        return ret;
 169                if (ip > ip_to) {
 170                        swap(ip, ip_to);
 171                        if (ip < map->first_ip)
 172                                return -IPSET_ERR_BITMAP_RANGE;
 173                }
 174        } else if (tb[IPSET_ATTR_CIDR]) {
 175                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 176
 177                if (!cidr || cidr > 32)
 178                        return -IPSET_ERR_INVALID_CIDR;
 179                ip_set_mask_from_to(ip, ip_to, cidr);
 180        } else
 181                ip_to = ip;
 182
 183        if (ip_to > map->last_ip)
 184                return -IPSET_ERR_BITMAP_RANGE;
 185
 186        for (; !before(ip_to, ip); ip += map->hosts) {
 187                e.id = ip_to_id(map, ip);
 188                ret = adtfn(set, &e, &ext, &ext, flags);
 189
 190                if (ret && !ip_set_eexist(ret, flags))
 191                        return ret;
 192                else
 193                        ret = 0;
 194        }
 195        return ret;
 196}
 197
 198static bool
 199bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
 200{
 201        const struct bitmap_ip *x = a->data;
 202        const struct bitmap_ip *y = b->data;
 203
 204        return x->first_ip == y->first_ip &&
 205               x->last_ip == y->last_ip &&
 206               x->netmask == y->netmask &&
 207               a->timeout == b->timeout &&
 208               a->extensions == b->extensions;
 209}
 210
 211/* Plain variant */
 212
 213struct bitmap_ip_elem {
 214};
 215
 216#include "ip_set_bitmap_gen.h"
 217
 218/* Create bitmap:ip type of sets */
 219
 220static bool
 221init_map_ip(struct ip_set *set, struct bitmap_ip *map,
 222            u32 first_ip, u32 last_ip,
 223            u32 elements, u32 hosts, u8 netmask)
 224{
 225        map->members = ip_set_alloc(map->memsize);
 226        if (!map->members)
 227                return false;
 228        if (set->dsize) {
 229                map->extensions = ip_set_alloc(set->dsize * elements);
 230                if (!map->extensions) {
 231                        kfree(map->members);
 232                        return false;
 233                }
 234        }
 235        map->first_ip = first_ip;
 236        map->last_ip = last_ip;
 237        map->elements = elements;
 238        map->hosts = hosts;
 239        map->netmask = netmask;
 240        set->timeout = IPSET_NO_TIMEOUT;
 241
 242        set->data = map;
 243        set->family = NFPROTO_IPV4;
 244
 245        return true;
 246}
 247
 248static int
 249bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
 250                 u32 flags)
 251{
 252        struct bitmap_ip *map;
 253        u32 first_ip = 0, last_ip = 0, hosts;
 254        u64 elements;
 255        u8 netmask = 32;
 256        int ret;
 257
 258        if (unlikely(!tb[IPSET_ATTR_IP] ||
 259                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 260                     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
 261                return -IPSET_ERR_PROTOCOL;
 262
 263        ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
 264        if (ret)
 265                return ret;
 266
 267        if (tb[IPSET_ATTR_IP_TO]) {
 268                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
 269                if (ret)
 270                        return ret;
 271                if (first_ip > last_ip) {
 272                        u32 tmp = first_ip;
 273
 274                        first_ip = last_ip;
 275                        last_ip = tmp;
 276                }
 277        } else if (tb[IPSET_ATTR_CIDR]) {
 278                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 279
 280                if (cidr >= 32)
 281                        return -IPSET_ERR_INVALID_CIDR;
 282                ip_set_mask_from_to(first_ip, last_ip, cidr);
 283        } else
 284                return -IPSET_ERR_PROTOCOL;
 285
 286        if (tb[IPSET_ATTR_NETMASK]) {
 287                netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
 288
 289                if (netmask > 32)
 290                        return -IPSET_ERR_INVALID_NETMASK;
 291
 292                first_ip &= ip_set_hostmask(netmask);
 293                last_ip |= ~ip_set_hostmask(netmask);
 294        }
 295
 296        if (netmask == 32) {
 297                hosts = 1;
 298                elements = (u64)last_ip - first_ip + 1;
 299        } else {
 300                u8 mask_bits;
 301                u32 mask;
 302
 303                mask = range_to_mask(first_ip, last_ip, &mask_bits);
 304
 305                if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
 306                    netmask <= mask_bits)
 307                        return -IPSET_ERR_BITMAP_RANGE;
 308
 309                pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
 310                hosts = 2 << (32 - netmask - 1);
 311                elements = 2 << (netmask - mask_bits - 1);
 312        }
 313        if (elements > IPSET_BITMAP_MAX_RANGE + 1)
 314                return -IPSET_ERR_BITMAP_RANGE_SIZE;
 315
 316        pr_debug("hosts %u, elements %llu\n",
 317                 hosts, (unsigned long long)elements);
 318
 319        map = kzalloc(sizeof(*map), GFP_KERNEL);
 320        if (!map)
 321                return -ENOMEM;
 322
 323        map->memsize = bitmap_bytes(0, elements - 1);
 324        set->variant = &bitmap_ip;
 325        set->dsize = ip_set_elem_len(set, tb, 0);
 326        if (!init_map_ip(set, map, first_ip, last_ip,
 327                         elements, hosts, netmask)) {
 328                kfree(map);
 329                return -ENOMEM;
 330        }
 331        if (tb[IPSET_ATTR_TIMEOUT]) {
 332                set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 333                bitmap_ip_gc_init(set, bitmap_ip_gc);
 334        }
 335        return 0;
 336}
 337
 338static struct ip_set_type bitmap_ip_type __read_mostly = {
 339        .name           = "bitmap:ip",
 340        .protocol       = IPSET_PROTOCOL,
 341        .features       = IPSET_TYPE_IP,
 342        .dimension      = IPSET_DIM_ONE,
 343        .family         = NFPROTO_IPV4,
 344        .revision_min   = IPSET_TYPE_REV_MIN,
 345        .revision_max   = IPSET_TYPE_REV_MAX,
 346        .create         = bitmap_ip_create,
 347        .create_policy  = {
 348                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 349                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 350                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 351                [IPSET_ATTR_NETMASK]    = { .type = NLA_U8  },
 352                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 353                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 354        },
 355        .adt_policy     = {
 356                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 357                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 358                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 359                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 360                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 361                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 362                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 363                [IPSET_ATTR_COMMENT]    = { .type = NLA_NUL_STRING },
 364                [IPSET_ATTR_SKBMARK]    = { .type = NLA_U64 },
 365                [IPSET_ATTR_SKBPRIO]    = { .type = NLA_U32 },
 366                [IPSET_ATTR_SKBQUEUE]   = { .type = NLA_U16 },
 367        },
 368        .me             = THIS_MODULE,
 369};
 370
 371static int __init
 372bitmap_ip_init(void)
 373{
 374        return ip_set_type_register(&bitmap_ip_type);
 375}
 376
 377static void __exit
 378bitmap_ip_fini(void)
 379{
 380        ip_set_type_unregister(&bitmap_ip_type);
 381}
 382
 383module_init(bitmap_ip_init);
 384module_exit(bitmap_ip_fini);
 385