diff options
Diffstat (limited to 'kernel/ip_set_hash_ip_src.c')
-rw-r--r-- | kernel/ip_set_hash_ip_src.c | 473 |
1 files changed, 0 insertions, 473 deletions
diff --git a/kernel/ip_set_hash_ip_src.c b/kernel/ip_set_hash_ip_src.c deleted file mode 100644 index ef0a8ec..0000000 --- a/kernel/ip_set_hash_ip_src.c +++ /dev/null @@ -1,473 +0,0 @@ -/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define CONCAT(a, b, c) a##b##c -#define TOKEN(a, b, c) CONCAT(a, b, c) - -/* IPv4/IPv6 dependent function prototypes for hash:ip */ - -#if PF == 4 -#define HOST_MASK 32 -#define NLA_PUT_ADDR(skb, ip) \ - NLA_PUT_NET32(skb, IPSET_ATTR_IP, *(ip)); -#else -#define HOST_MASK 128 -#define NLA_PUT_ADDR(skb, ip) \ - NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), ip); -#endif - -#define hash_ip_pf_timeout TOKEN(hash_ip, PF, _timeout) -#define hash_ip_pf_expired TOKEN(hash_ip, PF, _expired) -#define hash_ip_pf_elem_test TOKEN(hash_ip, PF, _elem_test) -#define hash_ip_pf_elem_exist TOKEN(hash_ip, PF, _elem_exist) -#define hash_ip_pf_elem_expired TOKEN(hash_ip, PF, _elem_expired) -#define hash_ip_pf_test TOKEN(hash_ip, PF, _test) -#define hash_ip_pf_add TOKEN(hash_ip, PF, _add) -#define hash_ip_pf_readd TOKEN(hash_ip, PF, _readd) -#define hash_ip_pf_del TOKEN(hash_ip, PF, _del) -#define hash_ip_pf_map_expired TOKEN(hash_ip, PF, _map_expired) -#define hash_ip_pf_set_expired TOKEN(hash_ip, PF, _set_expired) -#define hash_ip_pf_head TOKEN(hash_ip, PF, _head) -#define hash_ip_pf_list TOKEN(hash_ip, PF, _list) -#define hash_ip_pf_resize TOKEN(hash_ip, PF, _resize) -#define hash_ip_pf TOKEN(hash_ip, PF , ) -#define hash_ip_pf_kadt TOKEN(hash_ip, PF, _kadt) -#define hash_ip_pf_uadt TOKEN(hash_ip, PF, _uadt) -#define hash_ip_pf_destroy TOKEN(hash_ip, PF, _destroy) -#define hash_ip_pf_flush TOKEN(hash_ip, PF, _flush) -#define hash_ip_pf_timeout_gc TOKEN(hash_ip, PF, _timeout_gc) -#define hash_ip_pf_gc_init TOKEN(hash_ip, PF, _gc_init) -#define ip_pf_hash TOKEN(ip, PF, _hash) -#define ip_pf_cmp TOKEN(ip, PF, _cmp) -#define ip_pf_null TOKEN(ip, PF, _null) -#define ip_pf_cpy TOKEN(ip, PF, _cpy) -#define ip_pf_zero_out TOKEN(ip, PF, _zero_out) -#define ip_pf_elem TOKEN(ip, PF, _elem) -#define ip_pf_elem_timeout TOKEN(ip, PF, _elem_timeout) -#define ip_pf_get_elem_timeout TOKEN(get_ip, PF, _elem_timeout) - -static inline bool -hash_ip_pf_timeout(const struct hash_ip *map, uint32_t id) -{ - struct ip_pf_elem_timeout *elem = hash_ip_elem(map, id); - - return ip_set_timeout_test(elem->timeout); -} - -static inline bool -hash_ip_pf_expired(const struct hash_ip *map, uint32_t id) -{ - struct ip_pf_elem_timeout *elem = hash_ip_elem(map, id); - - return ip_set_timeout_expired(elem->timeout); -} - -static inline bool -hash_ip_pf_elem_test(const struct hash_ip *map, bool with_timeout, - uint32_t id, struct ip_pf_elem * ip) -{ - struct ip_pf_elem *elem = hash_ip_elem(map, id); - - return ip_pf_cmp(elem, ip) - && (!with_timeout || hash_ip_pf_timeout(map, id)); -} - -static inline bool -hash_ip_pf_elem_exist(const struct hash_ip *map, bool with_timeout, - uint32_t id) -{ - struct ip_pf_elem *elem = hash_ip_elem(map, id); - - return !(ip_pf_null(elem) - || (with_timeout && hash_ip_pf_expired(map, id))); -} - -static inline bool -hash_ip_pf_elem_expired(const struct hash_ip *map, bool with_timeout, - uint32_t id) -{ - struct ip_pf_elem *elem = hash_ip_elem(map, id); - - return ip_pf_null(elem) - || (with_timeout && hash_ip_pf_expired(map, id)); -} - -static inline uint32_t -hash_ip_pf_test(const struct hash_ip *map, bool with_timeout, - struct ip_pf_elem * ip) -{ - uint32_t id; - uint8_t i; - - for (i = 0; i < map->probes; i++) { - id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); - if (hash_ip_pf_elem_test(map, with_timeout, id, ip)) - return id + 1; - /* No shortcut - there can be deleted entries. */ - } - return 0; -} - -static void -hash_ip_pf_map_expired(struct hash_ip *map) -{ - struct ip_pf_elem_timeout *table = map->members; - uint32_t i; - - /* We run parallel with other readers (test element) - * but adding/deleting new entries is locked out */ - for (i = 0; i < map->hashsize; i++) - if (ip_set_timeout_expired(table[i].timeout)) { - ip_pf_zero_out((struct ip_pf_elem *)&table[i]); - table[i].timeout = IPSET_ELEM_UNSET; - map->elements--; - } -} - -static inline void -hash_ip_pf_set_expired(struct ip_set *set) -{ - /* We run parallel with other readers (test element) - * but adding/deleting new entries is locked out */ - read_lock_bh(&set->lock); - hash_ip_pf_map_expired(set->data); - read_unlock_bh(&set->lock); -} - -static int -hash_ip_pf_add(struct hash_ip *map, bool with_timeout, - struct ip_pf_elem *ip, uint32_t timeout) -{ - uint32_t id, empty = 0; - uint8_t i; - - if (map->elements >= map->maxelem) { - if (with_timeout) { - hash_ip_pf_map_expired(map); - if (map->elements < map->maxelem) - goto doit; - } - return -IPSET_ERR_HASH_FULL; - } - -doit: - for (i = 0; i < map->probes; i++) { - id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); - if (hash_ip_pf_elem_test(map, with_timeout, id, ip)) - return -IPSET_ERR_EXIST; - if (empty == 0 - && hash_ip_pf_elem_expired(map, with_timeout, id)) - empty = id + 1; - /* There can be deleted entries, must check all slots */ - } - if (!empty) - /* Trigger rehashing */ - return -EAGAIN; - - if (with_timeout) { - struct ip_pf_elem_timeout *e = hash_ip_elem(map, empty - 1); - e->timeout = ip_set_timeout_set(timeout); - D("add with timeout: %u (%lu)", timeout, e->timeout); - ip_pf_cpy((struct ip_pf_elem *)e, ip); - } else { - struct ip_pf_elem *e = hash_ip_elem(map, empty - 1); - ip_pf_cpy(e, ip); - } - map->elements++; - return 0; -} - -static int -hash_ip_pf_readd(struct hash_ip *map, bool with_timeout, struct ip_pf_elem *ip) -{ - uint32_t id, empty = 0; - uint8_t i; - - for (i = 0; empty == 0 && i < map->probes; i++) { - id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); - if (ip_pf_null(hash_ip_elem(map, id))) - empty = id + 1; - } - if (!empty) - /* Trigger rehashing */ - return -EAGAIN; - - if (with_timeout) { - struct ip_pf_elem_timeout *e = hash_ip_elem(map, empty - 1); - e->timeout = ip_pf_get_elem_timeout(ip); - ip_pf_cpy((struct ip_pf_elem *)e, ip); - } else { - struct ip_pf_elem *e = hash_ip_elem(map, empty - 1); - ip_pf_cpy(e, ip); - } - map->elements++; - return 0; -} - -static int -hash_ip_pf_del(struct hash_ip *map, bool with_timeout, struct ip_pf_elem *ip) -{ - struct ip_pf_elem *e; - uint32_t id, found = 0; - uint8_t i; - - for (i = 0; i < map->probes; i++) { - id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); - if (hash_ip_pf_elem_test(map, with_timeout, id, ip)) { - found = id + 1; - break; - } - } - if (!found) - return -IPSET_ERR_EXIST; - - e = hash_ip_elem(map, found - 1); - ip_pf_zero_out(e); - if (with_timeout) - ((struct ip_pf_elem_timeout *)e)->timeout = IPSET_ELEM_UNSET; - - map->elements--; - - return 0; -} - -static int -hash_ip_pf_head(struct ip_set *set, struct sk_buff *skb) -{ - const struct hash_ip *map = set->data; - struct nlattr *nested; - - if (set->flags & IP_SET_FLAG_TIMEOUT) - hash_ip_pf_set_expired(set); - - nested = ipset_nest_start(skb, IPSET_ATTR_DATA); - if (!nested) - goto nla_put_failure; - NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE, htonl(map->hashsize)); - NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(map->maxelem)); - if (map->netmask != HOST_MASK) - NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); - NLA_PUT_U8(skb, IPSET_ATTR_PROBES, map->probes); - NLA_PUT_U8(skb, IPSET_ATTR_RESIZE, map->resize); - NLA_PUT_NET32(skb, IPSET_ATTR_ELEMENTS, htonl(map->elements)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(map->hashsize * map->elem_size)); - if (set->flags & IP_SET_FLAG_TIMEOUT) - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); - ipset_nest_end(skb, nested); - - return 0; -nla_put_failure: - return -EFAULT; -} - -static int -hash_ip_pf_list(struct ip_set *set, - struct sk_buff *skb, struct netlink_callback *cb) -{ - const struct hash_ip *map = set->data; - struct nlattr *atd, *nested; - struct ip_pf_elem *elem; - uint32_t id, first = cb->args[2]; - bool with_timeout = set->flags & IP_SET_FLAG_TIMEOUT; - - atd = ipset_nest_start(skb, IPSET_ATTR_ADT); - if (!atd) - return -EFAULT; - for (; cb->args[2] < map->hashsize; cb->args[2]++) { - id = cb->args[2]; - if (hash_ip_pf_elem_expired(map, with_timeout, id)) - continue; - nested = ipset_nest_start(skb, IPSET_ATTR_DATA); - if (!nested) { - if (id == first) { - nla_nest_cancel(skb, atd); - return -EFAULT; - } else - goto nla_put_failure; - } - elem = hash_ip_elem(map, id); - NLA_PUT_ADDR(skb, &elem->ip); - if (map->netmask != HOST_MASK) - NLA_PUT_U8(skb, IPSET_ATTR_CIDR, map->netmask); - if (with_timeout) { - unsigned long timeout = ip_pf_get_elem_timeout(elem); - D("list with timeout: %u (%lu)", - ip_set_timeout_get(timeout), timeout); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(timeout))); - } - ipset_nest_end(skb, nested); - } - ipset_nest_end(skb, atd); - /* Set listing finished */ - cb->args[2] = 0; - - return 0; - -nla_put_failure: - nla_nest_cancel(skb, nested); - ipset_nest_end(skb, atd); - return 0; -} - -static int -hash_ip_pf_resize(struct ip_set *set, uint8_t retried) -{ - struct hash_ip *map = set->data, *tmp; - void *members; - uint32_t i, hashsize = map->hashsize; - uint8_t oflags, flags = set->flags; - bool with_timeout = flags & IP_SET_FLAG_TIMEOUT; - int ret; - - if (map->resize == 0) - return -IPSET_ERR_HASH_FULL; - - /* Try to cleanup first */ - if (retried == 0 && with_timeout) { - i = map->elements; - hash_ip_pf_set_expired(set); - if (map->elements < i) - return 0; - } - -again: - ret = 0; - - /* Calculate new hash size */ - hashsize += (hashsize * map->resize)/100; - if (hashsize == map->hashsize) - hashsize++; - if (hashsize >= map->maxelem) - return -IPSET_ERR_HASH_FULL; - - printk("Rehashing of set %s triggered: hash grows from %lu to %lu\n", - set->name, - (long unsigned)map->hashsize, - (long unsigned)hashsize); - - tmp = kmalloc(sizeof(struct hash_ip) - + map->probes * sizeof(initval_t), GFP_ATOMIC); - if (!tmp) - return -ENOMEM; - - memcpy(tmp, map, sizeof(*map) + map->probes * sizeof(initval_t)); - tmp->elements = 0; - tmp->hashsize = hashsize; - tmp->members = ip_set_alloc(hashsize * map->elem_size, - GFP_ATOMIC, &flags); - if (!tmp->members) { - kfree(tmp); - return -ENOMEM; - } - - write_lock_bh(&set->lock); - map = set->data; /* Play safe */ - for (i = 0; i < map->hashsize && ret == 0; i++) { - if (hash_ip_pf_elem_exist(map, with_timeout, i)) - ret = hash_ip_pf_readd(tmp, with_timeout, - hash_ip_elem(map, i)); - } - if (ret) { - /* Failure, try again */ - write_unlock_bh(&set->lock); - ip_set_free(tmp->members, flags); - kfree(tmp); - goto again; - } - - /* Success at resizing! */ - members = map->members; - oflags = set->flags; - - map->hashsize = tmp->hashsize; - map->members = tmp->members; - map->elements = tmp->elements; - set->flags = flags; - write_unlock_bh(&set->lock); - - ip_set_free(members, oflags); - kfree(tmp); - - return 0; -} - -static int -hash_ip_pf_kadt(struct ip_set *set, const struct sk_buff * skb, - enum ipset_adt adt, uint8_t pf, const uint8_t *flags); -static int -hash_ip_pf_uadt(struct ip_set *set, struct nlattr *head, int len, - enum ipset_adt adt, uint32_t *lineno, uint32_t flags); - -static const struct ip_set_type_variant hash_ip_pf __read_mostly = { - .kadt = hash_ip_pf_kadt, - .uadt = hash_ip_pf_uadt, - .destroy = hash_ip_pf_destroy, - .flush = hash_ip_pf_flush, - .head = hash_ip_pf_head, - .list = hash_ip_pf_list, - .resize = hash_ip_pf_resize, -}; - -static void -hash_ip_pf_timeout_gc(unsigned long ul_set) -{ - struct ip_set *set = (struct ip_set *) ul_set; - struct hash_ip *map = set->data; - - hash_ip_pf_set_expired(set); - - map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; - add_timer(&map->gc); -} - -static inline void -hash_ip_pf_gc_init(struct ip_set *set) -{ - struct hash_ip *map = set->data; - - init_timer(&map->gc); - map->gc.data = (unsigned long) set; - map->gc.function = hash_ip_pf_timeout_gc; - map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; - add_timer(&map->gc); -} - -#undef HOST_MASK -#undef NLA_PUT_ADDR -#undef hash_ip_pf_timeout -#undef hash_ip_pf_expired -#undef hash_ip_pf_elem_test -#undef hash_ip_pf_elem_exist -#undef hash_ip_pf_elem_expired -#undef hash_ip_pf_test -#undef hash_ip_pf_add -#undef hash_ip_pf_readd -#undef hash_ip_pf_del -#undef hash_ip_pf_map_expired -#undef hash_ip_pf_set_expired -#undef hash_ip_pf_head -#undef hash_ip_pf_list -#undef hash_ip_pf_resize -#undef hash_ip_pf -#undef hash_ip_pf_kadt -#undef hash_ip_pf_uadt -#undef hash_ip_pf_destroy -#undef hash_ip_pf_flush -#undef hash_ip_pf_timeout_gc -#undef hash_ip_pf_gc_init -#undef ip_pf_hash -#undef ip_pf_cmp -#undef ip_pf_null -#undef ip_pf_cpy -#undef ip_pf_zero_out -#undef ip_pf_elem -#undef ip_pf_elem_timeout -#undef ip_pf_get_elem_timeout |