Logo Search packages:      
Sourcecode: west-chamber version File versions  Download package

ip_set_hashes.h

#ifndef __IP_SET_HASHES_H
#define __IP_SET_HASHES_H

#define initval_t uint32_t

/* Macros to generate functions */

#ifdef __KERNEL__
#define HASH_RETRY0(type, dtype, cond)                            \
static int                                            \
type##_retry(struct ip_set *set)                            \
{                                                     \
      struct ip_set_##type *map = set->data, *tmp;                \
      dtype *elem;                                          \
      void *members;                                        \
      u_int32_t i, hashsize = map->hashsize;                      \
      int res;                                        \
                                                      \
      if (map->resize == 0)                                 \
            return -ERANGE;                                 \
                                                      \
    again:                                            \
      res = 0;                                        \
                                                      \
      /* Calculate new hash size */                         \
      hashsize += (hashsize * map->resize)/100;             \
      if (hashsize == map->hashsize)                              \
            hashsize++;                               \
                                                      \
      ip_set_printk("rehashing of set %s triggered: "             \
                  "hashsize grows from %lu to %lu",               \
                  set->name,                          \
                  (long unsigned)map->hashsize,             \
                  (long unsigned)hashsize);                       \
                                                            \
      tmp = kmalloc(sizeof(struct ip_set_##type)                  \
                  + map->probes * sizeof(initval_t), GFP_ATOMIC); \
      if (!tmp) {                                     \
            DP("out of memory for %zu bytes",               \
               sizeof(struct ip_set_##type)                       \
               + map->probes * sizeof(initval_t));                \
            return -ENOMEM;                                 \
      }                                               \
      tmp->members = harray_malloc(hashsize, sizeof(dtype), GFP_ATOMIC);\
      if (!tmp->members) {                                  \
            DP("out of memory for %zu bytes", hashsize * sizeof(dtype));\
            kfree(tmp);                               \
            return -ENOMEM;                                 \
      }                                               \
      tmp->hashsize = hashsize;                             \
      tmp->elements = 0;                                    \
      tmp->probes = map->probes;                            \
      tmp->resize = map->resize;                            \
      memcpy(tmp->initval, map->initval, map->probes * sizeof(initval_t));\
      __##type##_retry(tmp, map);                           \
                                                      \
      write_lock_bh(&set->lock);                            \
      map = set->data; /* Play safe */                      \
      for (i = 0; i < map->hashsize && res == 0; i++) {           \
            elem = HARRAY_ELEM(map->members, dtype *, i);         \
            if (cond)                                 \
                  res = __##type##_add(tmp, elem);          \
      }                                               \
      if (res) {                                      \
            /* Failure, try again */                        \
            write_unlock_bh(&set->lock);                    \
            harray_free(tmp->members);                      \
            kfree(tmp);                               \
            goto again;                               \
      }                                               \
                                                      \
      /* Success at resizing! */                            \
      members = map->members;                               \
                                                      \
      map->hashsize = tmp->hashsize;                              \
      map->members = tmp->members;                          \
      write_unlock_bh(&set->lock);                          \
                                                      \
      harray_free(members);                                 \
      kfree(tmp);                                     \
                                                      \
      return 0;                                       \
}

#define HASH_RETRY(type, dtype)                                   \
      HASH_RETRY0(type, dtype, *elem)

#define HASH_RETRY2(type, dtype)                                  \
      HASH_RETRY0(type, dtype, elem->ip || elem->ip1)

#define HASH_CREATE(type, dtype)                            \
static int                                            \
type##_create(struct ip_set *set, const void *data, u_int32_t size)     \
{                                                     \
      const struct ip_set_req_##type##_create *req = data;        \
      struct ip_set_##type *map;                            \
      uint16_t i;                                     \
                                                      \
      if (req->hashsize < 1) {                              \
            ip_set_printk("hashsize too small");                  \
            return -ENOEXEC;                          \
      }                                               \
                                                      \
      if (req->probes < 1) {                                \
            ip_set_printk("probes too small");              \
            return -ENOEXEC;                          \
      }                                               \
                                                      \
      map = kmalloc(sizeof(struct ip_set_##type)                  \
                  + req->probes * sizeof(initval_t), GFP_KERNEL); \
      if (!map) {                                     \
            DP("out of memory for %zu bytes",               \
               sizeof(struct ip_set_##type)                       \
               + req->probes * sizeof(initval_t));                \
            return -ENOMEM;                                 \
      }                                               \
      for (i = 0; i < req->probes; i++)                     \
            get_random_bytes(((initval_t *) map->initval)+i, 4);  \
      map->elements = 0;                                    \
      map->hashsize = req->hashsize;                              \
      map->probes = req->probes;                            \
      map->resize = req->resize;                            \
      if (__##type##_create(req, map)) {                    \
            kfree(map);                               \
            return -ENOEXEC;                          \
      }                                               \
      map->members = harray_malloc(map->hashsize, sizeof(dtype), GFP_KERNEL);\
      if (!map->members) {                                  \
            DP("out of memory for %zu bytes", map->hashsize * sizeof(dtype));\
            kfree(map);                               \
            return -ENOMEM;                                 \
      }                                               \
                                                      \
      set->data = map;                                \
      return 0;                                       \
}

#define HASH_DESTROY(type)                                  \
static void                                           \
type##_destroy(struct ip_set *set)                          \
{                                                     \
      struct ip_set_##type *map = set->data;                      \
                                                      \
      harray_free(map->members);                            \
      kfree(map);                                     \
                                                      \
      set->data = NULL;                               \
}

#define HASH_FLUSH(type, dtype)                                   \
static void                                           \
type##_flush(struct ip_set *set)                            \
{                                                     \
      struct ip_set_##type *map = set->data;                      \
      harray_flush(map->members, map->hashsize, sizeof(dtype));   \
      map->elements = 0;                                    \
}

#define HASH_FLUSH_CIDR(type, dtype)                              \
static void                                           \
type##_flush(struct ip_set *set)                            \
{                                                     \
      struct ip_set_##type *map = set->data;                      \
      harray_flush(map->members, map->hashsize, sizeof(dtype));   \
      memset(map->cidr, 0, sizeof(map->cidr));              \
      memset(map->nets, 0, sizeof(map->nets));              \
      map->elements = 0;                                    \
}

#define HASH_LIST_HEADER(type)                                    \
static void                                           \
type##_list_header(const struct ip_set *set, void *data)          \
{                                                     \
      const struct ip_set_##type *map = set->data;                \
      struct ip_set_req_##type##_create *header = data;           \
                                                      \
      header->hashsize = map->hashsize;                     \
      header->probes = map->probes;                         \
      header->resize = map->resize;                         \
      __##type##_list_header(map, header);                        \
}

#define HASH_LIST_MEMBERS_SIZE(type, dtype)                       \
static int                                            \
type##_list_members_size(const struct ip_set *set, char dont_align)     \
{                                                     \
      const struct ip_set_##type *map = set->data;                \
                                                      \
      return (map->elements * IPSET_VALIGN(sizeof(dtype), dont_align));\
}

#define HASH_LIST_MEMBERS(type, dtype)                            \
static void                                           \
type##_list_members(const struct ip_set *set, void *data, char dont_align)\
{                                                     \
      const struct ip_set_##type *map = set->data;                \
      dtype *elem, *d;                                \
      uint32_t i, n = 0;                                    \
                                                      \
      for (i = 0; i < map->hashsize; i++) {                       \
            elem = HARRAY_ELEM(map->members, dtype *, i);         \
            if (*elem) {                                    \
                  d = data + n * IPSET_VALIGN(sizeof(dtype), dont_align);\
                  *d = *elem;                         \
                  n++;                                \
            }                                         \
      }                                               \
}

#define HASH_LIST_MEMBERS_MEMCPY(type, dtype, nonzero)                  \
static void                                           \
type##_list_members(const struct ip_set *set, void *data, char dont_align)\
{                                                     \
      const struct ip_set_##type *map = set->data;                \
      dtype *elem;                                          \
      uint32_t i, n = 0;                                    \
                                                      \
      for (i = 0; i < map->hashsize; i++) {                       \
            elem = HARRAY_ELEM(map->members, dtype *, i);         \
            if (nonzero) {                                  \
                  memcpy(data + n * IPSET_VALIGN(sizeof(dtype), dont_align),\
                         elem, sizeof(dtype));              \
                  n++;                                \
            }                                         \
      }                                               \
}

#define IP_SET_RTYPE(type, __features)                            \
struct ip_set_type ip_set_##type = {                              \
      .typename         = #type,                      \
      .features         = __features,                       \
      .protocol_version = IP_SET_PROTOCOL_VERSION,          \
      .create                 = &type##_create,             \
      .retry                  = &type##_retry,              \
      .destroy          = &type##_destroy,                  \
      .flush                  = &type##_flush,              \
      .reqsize          = sizeof(struct ip_set_req_##type), \
      .addip                  = &type##_uadd,                     \
      .addip_kernel           = &type##_kadd,                     \
      .delip                  = &type##_udel,                     \
      .delip_kernel           = &type##_kdel,                     \
      .testip                 = &type##_utest,              \
      .testip_kernel          = &type##_ktest,              \
      .header_size            = sizeof(struct ip_set_req_##type##_create),\
      .list_header            = &type##_list_header,              \
      .list_members_size      = &type##_list_members_size,        \
      .list_members           = &type##_list_members,             \
      .me               = THIS_MODULE,                      \
};

/* Helper functions */
static inline void
add_cidr_size(uint8_t *cidr, uint8_t size)
{
      uint8_t next;
      int i;
      
      for (i = 0; i < 30 && cidr[i]; i++) {
            if (cidr[i] < size) {
                  next = cidr[i];
                  cidr[i] = size;
                  size = next;
            }
      }
      if (i < 30)
            cidr[i] = size;
}

static inline void
del_cidr_size(uint8_t *cidr, uint8_t size)
{
      int i;
      
      for (i = 0; i < 29 && cidr[i]; i++) {
            if (cidr[i] == size)
                  cidr[i] = size = cidr[i+1];
      }
      cidr[29] = 0;
}
#else
#include <arpa/inet.h>
#endif /* __KERNEL */

#ifndef UINT16_MAX
#define UINT16_MAX 65535
#endif

static unsigned char shifts[] = {255, 253, 249, 241, 225, 193, 129, 1};

static inline ip_set_ip_t 
pack_ip_cidr(ip_set_ip_t ip, unsigned char cidr)
{
      ip_set_ip_t addr, *paddr = &addr;
      unsigned char n, t, *a;

      addr = htonl(ip & (0xFFFFFFFF << (32 - (cidr))));
#ifdef __KERNEL__
      DP("ip:%u.%u.%u.%u/%u", NIPQUAD(addr), cidr);
#endif
      n = cidr / 8;
      t = cidr % 8;     
      a = &((unsigned char *)paddr)[n];
      *a = *a /(1 << (8 - t)) + shifts[t];
#ifdef __KERNEL__
      DP("n: %u, t: %u, a: %u", n, t, *a);
      DP("ip:%u.%u.%u.%u/%u, %u.%u.%u.%u",
         HIPQUAD(ip), cidr, NIPQUAD(addr));
#endif

      return ntohl(addr);
}


#endif /* __IP_SET_HASHES_H */

Generated by  Doxygen 1.6.0   Back to index