netfilter: ipset: Move extension data to set structure

Default timeout and extension offsets are moved to struct set, because
all set types supports all extensions and it makes possible to generalize
extension support.

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
This commit is contained in:
Jozsef Kadlecsik 2013-09-07 00:10:07 +02:00
parent f925f70569
commit ca134ce864
15 changed files with 266 additions and 289 deletions

View File

@ -72,6 +72,16 @@ struct ip_set_ext {
u32 timeout; u32 timeout;
}; };
struct ip_set_counter {
atomic64_t bytes;
atomic64_t packets;
};
#define ext_timeout(e, s) \
(unsigned long *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_TIMEOUT])
#define ext_counter(e, s) \
(struct ip_set_counter *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COUNTER])
struct ip_set; struct ip_set;
typedef int (*ipset_adtfn)(struct ip_set *set, void *value, typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
@ -179,15 +189,16 @@ struct ip_set {
u8 revision; u8 revision;
/* Extensions */ /* Extensions */
u8 extensions; u8 extensions;
/* Default timeout value, if enabled */
u32 timeout;
/* Element data size */
size_t dsize;
/* Offsets to extensions in elements */
size_t offset[IPSET_EXT_ID_MAX];
/* The type specific data */ /* The type specific data */
void *data; void *data;
}; };
struct ip_set_counter {
atomic64_t bytes;
atomic64_t packets;
};
static inline void static inline void
ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter) ip_set_add_bytes(u64 bytes, struct ip_set_counter *counter)
{ {
@ -390,13 +401,13 @@ bitmap_bytes(u32 a, u32 b)
#include <linux/netfilter/ipset/ip_set_timeout.h> #include <linux/netfilter/ipset/ip_set_timeout.h>
#define IP_SET_INIT_KEXT(skb, opt, map) \ #define IP_SET_INIT_KEXT(skb, opt, set) \
{ .bytes = (skb)->len, .packets = 1, \ { .bytes = (skb)->len, .packets = 1, \
.timeout = ip_set_adt_opt_timeout(opt, map) } .timeout = ip_set_adt_opt_timeout(opt, set) }
#define IP_SET_INIT_UEXT(map) \ #define IP_SET_INIT_UEXT(set) \
{ .bytes = ULLONG_MAX, .packets = ULLONG_MAX, \ { .bytes = ULLONG_MAX, .packets = ULLONG_MAX, \
.timeout = (map)->timeout } .timeout = (set)->timeout }
#define IP_SET_INIT_CIDR(a, b) ((a) ? (a) : (b)) #define IP_SET_INIT_CIDR(a, b) ((a) ? (a) : (b))

View File

@ -23,8 +23,8 @@
/* Set is defined with timeout support: timeout value may be 0 */ /* Set is defined with timeout support: timeout value may be 0 */
#define IPSET_NO_TIMEOUT UINT_MAX #define IPSET_NO_TIMEOUT UINT_MAX
#define ip_set_adt_opt_timeout(opt, map) \ #define ip_set_adt_opt_timeout(opt, set) \
((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (map)->timeout) ((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout)
static inline unsigned int static inline unsigned int
ip_set_timeout_uget(struct nlattr *tb) ip_set_timeout_uget(struct nlattr *tb)

View File

@ -32,11 +32,7 @@
#define mtype_gc IPSET_TOKEN(MTYPE, _gc) #define mtype_gc IPSET_TOKEN(MTYPE, _gc)
#define mtype MTYPE #define mtype MTYPE
#define ext_timeout(e, m) \ #define get_ext(set, map, id) ((map)->extensions + (set)->dsize * (id))
(unsigned long *)((e) + (m)->offset[IPSET_EXT_ID_TIMEOUT])
#define ext_counter(e, m) \
(struct ip_set_counter *)((e) + (m)->offset[IPSET_EXT_ID_COUNTER])
#define get_ext(map, id) ((map)->extensions + (map)->dsize * (id))
static void static void
mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set)) mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
@ -46,7 +42,7 @@ mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
init_timer(&map->gc); init_timer(&map->gc);
map->gc.data = (unsigned long) set; map->gc.data = (unsigned long) set;
map->gc.function = gc; map->gc.function = gc;
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
add_timer(&map->gc); add_timer(&map->gc);
} }
@ -59,7 +55,7 @@ mtype_destroy(struct ip_set *set)
del_timer_sync(&map->gc); del_timer_sync(&map->gc);
ip_set_free(map->members); ip_set_free(map->members);
if (map->dsize) if (set->dsize)
ip_set_free(map->extensions); ip_set_free(map->extensions);
kfree(map); kfree(map);
@ -88,9 +84,9 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
nla_put_net32(skb, IPSET_ATTR_MEMSIZE, nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
htonl(sizeof(*map) + htonl(sizeof(*map) +
map->memsize + map->memsize +
map->dsize * map->elements)) || set->dsize * map->elements)) ||
(SET_WITH_TIMEOUT(set) && (SET_WITH_TIMEOUT(set) &&
nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) || nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(set->timeout))) ||
(SET_WITH_COUNTER(set) && (SET_WITH_COUNTER(set) &&
nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS,
htonl(IPSET_FLAG_WITH_COUNTERS)))) htonl(IPSET_FLAG_WITH_COUNTERS))))
@ -108,16 +104,16 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
{ {
struct mtype *map = set->data; struct mtype *map = set->data;
const struct mtype_adt_elem *e = value; const struct mtype_adt_elem *e = value;
void *x = get_ext(map, e->id); void *x = get_ext(set, map, e->id);
int ret = mtype_do_test(e, map); int ret = mtype_do_test(e, map, set->dsize);
if (ret <= 0) if (ret <= 0)
return ret; return ret;
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(x, map))) ip_set_timeout_expired(ext_timeout(x, set)))
return 0; return 0;
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_update_counter(ext_counter(x, map), ext, mext, flags); ip_set_update_counter(ext_counter(x, set), ext, mext, flags);
return 1; return 1;
} }
@ -127,12 +123,12 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
{ {
struct mtype *map = set->data; struct mtype *map = set->data;
const struct mtype_adt_elem *e = value; const struct mtype_adt_elem *e = value;
void *x = get_ext(map, e->id); void *x = get_ext(set, map, e->id);
int ret = mtype_do_add(e, map, flags); int ret = mtype_do_add(e, map, flags, set->dsize);
if (ret == IPSET_ADD_FAILED) { if (ret == IPSET_ADD_FAILED) {
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(x, map))) ip_set_timeout_expired(ext_timeout(x, set)))
ret = 0; ret = 0;
else if (!(flags & IPSET_FLAG_EXIST)) else if (!(flags & IPSET_FLAG_EXIST))
return -IPSET_ERR_EXIST; return -IPSET_ERR_EXIST;
@ -140,13 +136,13 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
if (SET_WITH_TIMEOUT(set)) if (SET_WITH_TIMEOUT(set))
#ifdef IP_SET_BITMAP_STORED_TIMEOUT #ifdef IP_SET_BITMAP_STORED_TIMEOUT
mtype_add_timeout(ext_timeout(x, map), e, ext, map, ret); mtype_add_timeout(ext_timeout(x, set), e, ext, set, map, ret);
#else #else
ip_set_timeout_set(ext_timeout(x, map), ext->timeout); ip_set_timeout_set(ext_timeout(x, set), ext->timeout);
#endif #endif
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(x, map), ext); ip_set_init_counter(ext_counter(x, set), ext);
return 0; return 0;
} }
@ -156,11 +152,11 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
{ {
struct mtype *map = set->data; struct mtype *map = set->data;
const struct mtype_adt_elem *e = value; const struct mtype_adt_elem *e = value;
const void *x = get_ext(map, e->id); const void *x = get_ext(set, map, e->id);
if (mtype_do_del(e, map) || if (mtype_do_del(e, map) ||
(SET_WITH_TIMEOUT(set) && (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(x, map)))) ip_set_timeout_expired(ext_timeout(x, set))))
return -IPSET_ERR_EXIST; return -IPSET_ERR_EXIST;
return 0; return 0;
@ -180,13 +176,13 @@ mtype_list(const struct ip_set *set,
return -EMSGSIZE; return -EMSGSIZE;
for (; cb->args[2] < map->elements; cb->args[2]++) { for (; cb->args[2] < map->elements; cb->args[2]++) {
id = cb->args[2]; id = cb->args[2];
x = get_ext(map, id); x = get_ext(set, map, id);
if (!test_bit(id, map->members) || if (!test_bit(id, map->members) ||
(SET_WITH_TIMEOUT(set) && (SET_WITH_TIMEOUT(set) &&
#ifdef IP_SET_BITMAP_STORED_TIMEOUT #ifdef IP_SET_BITMAP_STORED_TIMEOUT
mtype_is_filled((const struct mtype_elem *) x) && mtype_is_filled((const struct mtype_elem *) x) &&
#endif #endif
ip_set_timeout_expired(ext_timeout(x, map)))) ip_set_timeout_expired(ext_timeout(x, set))))
continue; continue;
nested = ipset_nest_start(skb, IPSET_ATTR_DATA); nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) { if (!nested) {
@ -196,23 +192,24 @@ mtype_list(const struct ip_set *set,
} else } else
goto nla_put_failure; goto nla_put_failure;
} }
if (mtype_do_list(skb, map, id)) if (mtype_do_list(skb, map, id, set->dsize))
goto nla_put_failure; goto nla_put_failure;
if (SET_WITH_TIMEOUT(set)) { if (SET_WITH_TIMEOUT(set)) {
#ifdef IP_SET_BITMAP_STORED_TIMEOUT #ifdef IP_SET_BITMAP_STORED_TIMEOUT
if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
htonl(ip_set_timeout_stored(map, id, htonl(ip_set_timeout_stored(map, id,
ext_timeout(x, map))))) ext_timeout(x, set),
set->dsize))))
goto nla_put_failure; goto nla_put_failure;
#else #else
if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
htonl(ip_set_timeout_get( htonl(ip_set_timeout_get(
ext_timeout(x, map))))) ext_timeout(x, set)))))
goto nla_put_failure; goto nla_put_failure;
#endif #endif
} }
if (SET_WITH_COUNTER(set) && if (SET_WITH_COUNTER(set) &&
ip_set_put_counter(skb, ext_counter(x, map))) ip_set_put_counter(skb, ext_counter(x, set)))
goto nla_put_failure; goto nla_put_failure;
ipset_nest_end(skb, nested); ipset_nest_end(skb, nested);
} }
@ -245,14 +242,14 @@ mtype_gc(unsigned long ul_set)
* but adding/deleting new entries is locked out */ * but adding/deleting new entries is locked out */
read_lock_bh(&set->lock); read_lock_bh(&set->lock);
for (id = 0; id < map->elements; id++) for (id = 0; id < map->elements; id++)
if (mtype_gc_test(id, map)) { if (mtype_gc_test(id, map, set->dsize)) {
x = get_ext(map, id); x = get_ext(set, map, id);
if (ip_set_timeout_expired(ext_timeout(x, map))) if (ip_set_timeout_expired(ext_timeout(x, set)))
clear_bit(id, map->members); clear_bit(id, map->members);
} }
read_unlock_bh(&set->lock); read_unlock_bh(&set->lock);
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
add_timer(&map->gc); add_timer(&map->gc);
} }

View File

@ -44,10 +44,7 @@ struct bitmap_ip {
u32 elements; /* number of max elements in the set */ u32 elements; /* number of max elements in the set */
u32 hosts; /* number of hosts in a subnet */ u32 hosts; /* number of hosts in a subnet */
size_t memsize; /* members size */ size_t memsize; /* members size */
size_t dsize; /* extensions struct size */
size_t offset[IPSET_EXT_ID_MAX]; /* Offsets to extensions */
u8 netmask; /* subnet netmask */ u8 netmask; /* subnet netmask */
u32 timeout; /* timeout parameter */
struct timer_list gc; /* garbage collection */ struct timer_list gc; /* garbage collection */
}; };
@ -65,20 +62,21 @@ ip_to_id(const struct bitmap_ip *m, u32 ip)
/* Common functions */ /* Common functions */
static inline int static inline int
bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map) bitmap_ip_do_test(const struct bitmap_ip_adt_elem *e,
struct bitmap_ip *map, size_t dsize)
{ {
return !!test_bit(e->id, map->members); return !!test_bit(e->id, map->members);
} }
static inline int static inline int
bitmap_ip_gc_test(u16 id, const struct bitmap_ip *map) bitmap_ip_gc_test(u16 id, const struct bitmap_ip *map, size_t dsize)
{ {
return !!test_bit(id, map->members); return !!test_bit(id, map->members);
} }
static inline int static inline int
bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map, bitmap_ip_do_add(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map,
u32 flags) u32 flags, size_t dsize)
{ {
return !!test_and_set_bit(e->id, map->members); return !!test_and_set_bit(e->id, map->members);
} }
@ -90,7 +88,8 @@ bitmap_ip_do_del(const struct bitmap_ip_adt_elem *e, struct bitmap_ip *map)
} }
static inline int static inline int
bitmap_ip_do_list(struct sk_buff *skb, const struct bitmap_ip *map, u32 id) bitmap_ip_do_list(struct sk_buff *skb, const struct bitmap_ip *map, u32 id,
size_t dsize)
{ {
return nla_put_ipaddr4(skb, IPSET_ATTR_IP, return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
htonl(map->first_ip + id * map->hosts)); htonl(map->first_ip + id * map->hosts));
@ -113,7 +112,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
struct bitmap_ip *map = set->data; struct bitmap_ip *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct bitmap_ip_adt_elem e = { }; struct bitmap_ip_adt_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
u32 ip; u32 ip;
ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC)); ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
@ -133,7 +132,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
u32 ip = 0, ip_to = 0; u32 ip = 0, ip_to = 0;
struct bitmap_ip_adt_elem e = { }; struct bitmap_ip_adt_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(map); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
int ret = 0; int ret = 0;
if (unlikely(!tb[IPSET_ATTR_IP] || if (unlikely(!tb[IPSET_ATTR_IP] ||
@ -200,7 +199,7 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
return x->first_ip == y->first_ip && return x->first_ip == y->first_ip &&
x->last_ip == y->last_ip && x->last_ip == y->last_ip &&
x->netmask == y->netmask && x->netmask == y->netmask &&
x->timeout == y->timeout && a->timeout == b->timeout &&
a->extensions == b->extensions; a->extensions == b->extensions;
} }
@ -240,8 +239,8 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
map->members = ip_set_alloc(map->memsize); map->members = ip_set_alloc(map->memsize);
if (!map->members) if (!map->members)
return false; return false;
if (map->dsize) { if (set->dsize) {
map->extensions = ip_set_alloc(map->dsize * elements); map->extensions = ip_set_alloc(set->dsize * elements);
if (!map->extensions) { if (!map->extensions) {
kfree(map->members); kfree(map->members);
return false; return false;
@ -252,7 +251,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
map->elements = elements; map->elements = elements;
map->hosts = hosts; map->hosts = hosts;
map->netmask = netmask; map->netmask = netmask;
map->timeout = IPSET_NO_TIMEOUT; set->timeout = IPSET_NO_TIMEOUT;
set->data = map; set->data = map;
set->family = NFPROTO_IPV4; set->family = NFPROTO_IPV4;
@ -341,10 +340,10 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
set->extensions |= IPSET_EXT_COUNTER; set->extensions |= IPSET_EXT_COUNTER;
if (tb[IPSET_ATTR_TIMEOUT]) { if (tb[IPSET_ATTR_TIMEOUT]) {
map->dsize = sizeof(struct bitmap_ipct_elem); set->dsize = sizeof(struct bitmap_ipct_elem);
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct bitmap_ipct_elem, timeout); offsetof(struct bitmap_ipct_elem, timeout);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct bitmap_ipct_elem, counter); offsetof(struct bitmap_ipct_elem, counter);
if (!init_map_ip(set, map, first_ip, last_ip, if (!init_map_ip(set, map, first_ip, last_ip,
@ -353,14 +352,14 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
return -ENOMEM; return -ENOMEM;
} }
map->timeout = ip_set_timeout_uget( set->timeout = ip_set_timeout_uget(
tb[IPSET_ATTR_TIMEOUT]); tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
bitmap_ip_gc_init(set, bitmap_ip_gc); bitmap_ip_gc_init(set, bitmap_ip_gc);
} else { } else {
map->dsize = sizeof(struct bitmap_ipc_elem); set->dsize = sizeof(struct bitmap_ipc_elem);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct bitmap_ipc_elem, counter); offsetof(struct bitmap_ipc_elem, counter);
if (!init_map_ip(set, map, first_ip, last_ip, if (!init_map_ip(set, map, first_ip, last_ip,
@ -370,8 +369,8 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
} }
} }
} else if (tb[IPSET_ATTR_TIMEOUT]) { } else if (tb[IPSET_ATTR_TIMEOUT]) {
map->dsize = sizeof(struct bitmap_ipt_elem); set->dsize = sizeof(struct bitmap_ipt_elem);
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct bitmap_ipt_elem, timeout); offsetof(struct bitmap_ipt_elem, timeout);
if (!init_map_ip(set, map, first_ip, last_ip, if (!init_map_ip(set, map, first_ip, last_ip,
@ -380,12 +379,12 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
return -ENOMEM; return -ENOMEM;
} }
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
bitmap_ip_gc_init(set, bitmap_ip_gc); bitmap_ip_gc_init(set, bitmap_ip_gc);
} else { } else {
map->dsize = 0; set->dsize = 0;
if (!init_map_ip(set, map, first_ip, last_ip, if (!init_map_ip(set, map, first_ip, last_ip,
elements, hosts, netmask)) { elements, hosts, netmask)) {
kfree(map); kfree(map);

View File

@ -48,11 +48,8 @@ struct bitmap_ipmac {
u32 first_ip; /* host byte order, included in range */ u32 first_ip; /* host byte order, included in range */
u32 last_ip; /* host byte order, included in range */ u32 last_ip; /* host byte order, included in range */
u32 elements; /* number of max elements in the set */ u32 elements; /* number of max elements in the set */
u32 timeout; /* timeout value */
struct timer_list gc; /* garbage collector */
size_t memsize; /* members size */ size_t memsize; /* members size */
size_t dsize; /* size of element */ struct timer_list gc; /* garbage collector */
size_t offset[IPSET_EXT_ID_MAX]; /* Offsets to extensions */
}; };
/* ADT structure for generic function args */ /* ADT structure for generic function args */
@ -82,13 +79,13 @@ get_elem(void *extensions, u16 id, size_t dsize)
static inline int static inline int
bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e, bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
const struct bitmap_ipmac *map) const struct bitmap_ipmac *map, size_t dsize)
{ {
const struct bitmap_ipmac_elem *elem; const struct bitmap_ipmac_elem *elem;
if (!test_bit(e->id, map->members)) if (!test_bit(e->id, map->members))
return 0; return 0;
elem = get_elem(map->extensions, e->id, map->dsize); elem = get_elem(map->extensions, e->id, dsize);
if (elem->filled == MAC_FILLED) if (elem->filled == MAC_FILLED)
return e->ether == NULL || return e->ether == NULL ||
ether_addr_equal(e->ether, elem->ether); ether_addr_equal(e->ether, elem->ether);
@ -97,13 +94,13 @@ bitmap_ipmac_do_test(const struct bitmap_ipmac_adt_elem *e,
} }
static inline int static inline int
bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map) bitmap_ipmac_gc_test(u16 id, const struct bitmap_ipmac *map, size_t dsize)
{ {
const struct bitmap_ipmac_elem *elem; const struct bitmap_ipmac_elem *elem;
if (!test_bit(id, map->members)) if (!test_bit(id, map->members))
return 0; return 0;
elem = get_elem(map->extensions, id, map->dsize); elem = get_elem(map->extensions, id, dsize);
/* Timer not started for the incomplete elements */ /* Timer not started for the incomplete elements */
return elem->filled == MAC_FILLED; return elem->filled == MAC_FILLED;
} }
@ -117,13 +114,13 @@ bitmap_ipmac_is_filled(const struct bitmap_ipmac_elem *elem)
static inline int static inline int
bitmap_ipmac_add_timeout(unsigned long *timeout, bitmap_ipmac_add_timeout(unsigned long *timeout,
const struct bitmap_ipmac_adt_elem *e, const struct bitmap_ipmac_adt_elem *e,
const struct ip_set_ext *ext, const struct ip_set_ext *ext, struct ip_set *set,
struct bitmap_ipmac *map, int mode) struct bitmap_ipmac *map, int mode)
{ {
u32 t = ext->timeout; u32 t = ext->timeout;
if (mode == IPSET_ADD_START_STORED_TIMEOUT) { if (mode == IPSET_ADD_START_STORED_TIMEOUT) {
if (t == map->timeout) if (t == set->timeout)
/* Timeout was not specified, get stored one */ /* Timeout was not specified, get stored one */
t = *timeout; t = *timeout;
ip_set_timeout_set(timeout, t); ip_set_timeout_set(timeout, t);
@ -142,11 +139,11 @@ bitmap_ipmac_add_timeout(unsigned long *timeout,
static inline int static inline int
bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e, bitmap_ipmac_do_add(const struct bitmap_ipmac_adt_elem *e,
struct bitmap_ipmac *map, u32 flags) struct bitmap_ipmac *map, u32 flags, size_t dsize)
{ {
struct bitmap_ipmac_elem *elem; struct bitmap_ipmac_elem *elem;
elem = get_elem(map->extensions, e->id, map->dsize); elem = get_elem(map->extensions, e->id, dsize);
if (test_and_set_bit(e->id, map->members)) { if (test_and_set_bit(e->id, map->members)) {
if (elem->filled == MAC_FILLED) { if (elem->filled == MAC_FILLED) {
if (e->ether && (flags & IPSET_FLAG_EXIST)) if (e->ether && (flags & IPSET_FLAG_EXIST))
@ -179,10 +176,11 @@ bitmap_ipmac_do_del(const struct bitmap_ipmac_adt_elem *e,
} }
static inline unsigned long static inline unsigned long
ip_set_timeout_stored(struct bitmap_ipmac *map, u32 id, unsigned long *timeout) ip_set_timeout_stored(struct bitmap_ipmac *map, u32 id, unsigned long *timeout,
size_t dsize)
{ {
const struct bitmap_ipmac_elem *elem = const struct bitmap_ipmac_elem *elem =
get_elem(map->extensions, id, map->dsize); get_elem(map->extensions, id, dsize);
return elem->filled == MAC_FILLED ? ip_set_timeout_get(timeout) : return elem->filled == MAC_FILLED ? ip_set_timeout_get(timeout) :
*timeout; *timeout;
@ -190,10 +188,10 @@ ip_set_timeout_stored(struct bitmap_ipmac *map, u32 id, unsigned long *timeout)
static inline int static inline int
bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map, bitmap_ipmac_do_list(struct sk_buff *skb, const struct bitmap_ipmac *map,
u32 id) u32 id, size_t dsize)
{ {
const struct bitmap_ipmac_elem *elem = const struct bitmap_ipmac_elem *elem =
get_elem(map->extensions, id, map->dsize); get_elem(map->extensions, id, dsize);
return nla_put_ipaddr4(skb, IPSET_ATTR_IP, return nla_put_ipaddr4(skb, IPSET_ATTR_IP,
htonl(map->first_ip + id)) || htonl(map->first_ip + id)) ||
@ -216,7 +214,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
struct bitmap_ipmac *map = set->data; struct bitmap_ipmac *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct bitmap_ipmac_adt_elem e = {}; struct bitmap_ipmac_adt_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
u32 ip; u32 ip;
/* MAC can be src only */ /* MAC can be src only */
@ -245,7 +243,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
const struct bitmap_ipmac *map = set->data; const struct bitmap_ipmac *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct bitmap_ipmac_adt_elem e = {}; struct bitmap_ipmac_adt_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_UEXT(map); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0; u32 ip = 0;
int ret = 0; int ret = 0;
@ -285,7 +283,7 @@ bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
return x->first_ip == y->first_ip && return x->first_ip == y->first_ip &&
x->last_ip == y->last_ip && x->last_ip == y->last_ip &&
x->timeout == y->timeout && a->timeout == b->timeout &&
a->extensions == b->extensions; a->extensions == b->extensions;
} }
@ -330,11 +328,11 @@ static bool
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
u32 first_ip, u32 last_ip, u32 elements) u32 first_ip, u32 last_ip, u32 elements)
{ {
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize); map->members = ip_set_alloc((last_ip - first_ip + 1) * set->dsize);
if (!map->members) if (!map->members)
return false; return false;
if (map->dsize) { if (set->dsize) {
map->extensions = ip_set_alloc(map->dsize * elements); map->extensions = ip_set_alloc(set->dsize * elements);
if (!map->extensions) { if (!map->extensions) {
kfree(map->members); kfree(map->members);
return false; return false;
@ -343,7 +341,7 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
map->first_ip = first_ip; map->first_ip = first_ip;
map->last_ip = last_ip; map->last_ip = last_ip;
map->elements = elements; map->elements = elements;
map->timeout = IPSET_NO_TIMEOUT; set->timeout = IPSET_NO_TIMEOUT;
set->data = map; set->data = map;
set->family = NFPROTO_IPV4; set->family = NFPROTO_IPV4;
@ -404,10 +402,10 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
set->extensions |= IPSET_EXT_COUNTER; set->extensions |= IPSET_EXT_COUNTER;
if (tb[IPSET_ATTR_TIMEOUT]) { if (tb[IPSET_ATTR_TIMEOUT]) {
map->dsize = sizeof(struct bitmap_ipmacct_elem); set->dsize = sizeof(struct bitmap_ipmacct_elem);
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct bitmap_ipmacct_elem, timeout); offsetof(struct bitmap_ipmacct_elem, timeout);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct bitmap_ipmacct_elem, counter); offsetof(struct bitmap_ipmacct_elem, counter);
if (!init_map_ipmac(set, map, first_ip, last_ip, if (!init_map_ipmac(set, map, first_ip, last_ip,
@ -415,13 +413,13 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
kfree(map); kfree(map);
return -ENOMEM; return -ENOMEM;
} }
map->timeout = ip_set_timeout_uget( set->timeout = ip_set_timeout_uget(
tb[IPSET_ATTR_TIMEOUT]); tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
bitmap_ipmac_gc_init(set, bitmap_ipmac_gc); bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
} else { } else {
map->dsize = sizeof(struct bitmap_ipmacc_elem); set->dsize = sizeof(struct bitmap_ipmacc_elem);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct bitmap_ipmacc_elem, counter); offsetof(struct bitmap_ipmacc_elem, counter);
if (!init_map_ipmac(set, map, first_ip, last_ip, if (!init_map_ipmac(set, map, first_ip, last_ip,
@ -431,19 +429,19 @@ bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
} }
} }
} else if (tb[IPSET_ATTR_TIMEOUT]) { } else if (tb[IPSET_ATTR_TIMEOUT]) {
map->dsize = sizeof(struct bitmap_ipmact_elem); set->dsize = sizeof(struct bitmap_ipmact_elem);
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct bitmap_ipmact_elem, timeout); offsetof(struct bitmap_ipmact_elem, timeout);
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
kfree(map); kfree(map);
return -ENOMEM; return -ENOMEM;
} }
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
bitmap_ipmac_gc_init(set, bitmap_ipmac_gc); bitmap_ipmac_gc_init(set, bitmap_ipmac_gc);
} else { } else {
map->dsize = sizeof(struct bitmap_ipmac_elem); set->dsize = sizeof(struct bitmap_ipmac_elem);
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
kfree(map); kfree(map);

View File

@ -38,9 +38,6 @@ struct bitmap_port {
u16 last_port; /* host byte order, included in range */ u16 last_port; /* host byte order, included in range */
u32 elements; /* number of max elements in the set */ u32 elements; /* number of max elements in the set */
size_t memsize; /* members size */ size_t memsize; /* members size */
size_t dsize; /* extensions struct size */
size_t offset[IPSET_EXT_ID_MAX]; /* Offsets to extensions */
u32 timeout; /* timeout parameter */
struct timer_list gc; /* garbage collection */ struct timer_list gc; /* garbage collection */
}; };
@ -59,20 +56,20 @@ port_to_id(const struct bitmap_port *m, u16 port)
static inline int static inline int
bitmap_port_do_test(const struct bitmap_port_adt_elem *e, bitmap_port_do_test(const struct bitmap_port_adt_elem *e,
const struct bitmap_port *map) const struct bitmap_port *map, size_t dsize)
{ {
return !!test_bit(e->id, map->members); return !!test_bit(e->id, map->members);
} }
static inline int static inline int
bitmap_port_gc_test(u16 id, const struct bitmap_port *map) bitmap_port_gc_test(u16 id, const struct bitmap_port *map, size_t dsize)
{ {
return !!test_bit(id, map->members); return !!test_bit(id, map->members);
} }
static inline int static inline int
bitmap_port_do_add(const struct bitmap_port_adt_elem *e, bitmap_port_do_add(const struct bitmap_port_adt_elem *e,
struct bitmap_port *map, u32 flags) struct bitmap_port *map, u32 flags, size_t dsize)
{ {
return !!test_and_set_bit(e->id, map->members); return !!test_and_set_bit(e->id, map->members);
} }
@ -85,7 +82,8 @@ bitmap_port_do_del(const struct bitmap_port_adt_elem *e,
} }
static inline int static inline int
bitmap_port_do_list(struct sk_buff *skb, const struct bitmap_port *map, u32 id) bitmap_port_do_list(struct sk_buff *skb, const struct bitmap_port *map, u32 id,
size_t dsize)
{ {
return nla_put_net16(skb, IPSET_ATTR_PORT, return nla_put_net16(skb, IPSET_ATTR_PORT,
htons(map->first_port + id)); htons(map->first_port + id));
@ -106,7 +104,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
struct bitmap_port *map = set->data; struct bitmap_port *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct bitmap_port_adt_elem e = {}; struct bitmap_port_adt_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
__be16 __port; __be16 __port;
u16 port = 0; u16 port = 0;
@ -131,7 +129,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
struct bitmap_port *map = set->data; struct bitmap_port *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct bitmap_port_adt_elem e = {}; struct bitmap_port_adt_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_UEXT(map); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port; /* wraparound */ u32 port; /* wraparound */
u16 port_to; u16 port_to;
int ret = 0; int ret = 0;
@ -191,7 +189,7 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
return x->first_port == y->first_port && return x->first_port == y->first_port &&
x->last_port == y->last_port && x->last_port == y->last_port &&
x->timeout == y->timeout && a->timeout == b->timeout &&
a->extensions == b->extensions; a->extensions == b->extensions;
} }
@ -230,8 +228,8 @@ init_map_port(struct ip_set *set, struct bitmap_port *map,
map->members = ip_set_alloc(map->memsize); map->members = ip_set_alloc(map->memsize);
if (!map->members) if (!map->members)
return false; return false;
if (map->dsize) { if (set->dsize) {
map->extensions = ip_set_alloc(map->dsize * map->elements); map->extensions = ip_set_alloc(set->dsize * map->elements);
if (!map->extensions) { if (!map->extensions) {
kfree(map->members); kfree(map->members);
return false; return false;
@ -239,7 +237,7 @@ init_map_port(struct ip_set *set, struct bitmap_port *map,
} }
map->first_port = first_port; map->first_port = first_port;
map->last_port = last_port; map->last_port = last_port;
map->timeout = IPSET_NO_TIMEOUT; set->timeout = IPSET_NO_TIMEOUT;
set->data = map; set->data = map;
set->family = NFPROTO_UNSPEC; set->family = NFPROTO_UNSPEC;
@ -281,23 +279,23 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
set->extensions |= IPSET_EXT_COUNTER; set->extensions |= IPSET_EXT_COUNTER;
if (tb[IPSET_ATTR_TIMEOUT]) { if (tb[IPSET_ATTR_TIMEOUT]) {
map->dsize = sizeof(struct bitmap_portct_elem); set->dsize = sizeof(struct bitmap_portct_elem);
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct bitmap_portct_elem, timeout); offsetof(struct bitmap_portct_elem, timeout);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct bitmap_portct_elem, counter); offsetof(struct bitmap_portct_elem, counter);
if (!init_map_port(set, map, first_port, last_port)) { if (!init_map_port(set, map, first_port, last_port)) {
kfree(map); kfree(map);
return -ENOMEM; return -ENOMEM;
} }
map->timeout = set->timeout =
ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
bitmap_port_gc_init(set, bitmap_port_gc); bitmap_port_gc_init(set, bitmap_port_gc);
} else { } else {
map->dsize = sizeof(struct bitmap_portc_elem); set->dsize = sizeof(struct bitmap_portc_elem);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct bitmap_portc_elem, counter); offsetof(struct bitmap_portc_elem, counter);
if (!init_map_port(set, map, first_port, last_port)) { if (!init_map_port(set, map, first_port, last_port)) {
kfree(map); kfree(map);
@ -305,19 +303,19 @@ bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
} }
} }
} else if (tb[IPSET_ATTR_TIMEOUT]) { } else if (tb[IPSET_ATTR_TIMEOUT]) {
map->dsize = sizeof(struct bitmap_portt_elem); set->dsize = sizeof(struct bitmap_portt_elem);
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct bitmap_portt_elem, timeout); offsetof(struct bitmap_portt_elem, timeout);
if (!init_map_port(set, map, first_port, last_port)) { if (!init_map_port(set, map, first_port, last_port)) {
kfree(map); kfree(map);
return -ENOMEM; return -ENOMEM;
} }
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
bitmap_port_gc_init(set, bitmap_port_gc); bitmap_port_gc_init(set, bitmap_port_gc);
} else { } else {
map->dsize = 0; set->dsize = 0;
if (!init_map_port(set, map, first_port, last_port)) { if (!init_map_port(set, map, first_port, last_port)) {
kfree(map); kfree(map);
return -ENOMEM; return -ENOMEM;

View File

@ -178,11 +178,6 @@ hbucket_elem_add(struct hbucket *n, u8 ahash_max, size_t dsize)
#define NLEN(family) 0 #define NLEN(family) 0
#endif /* IP_SET_HASH_WITH_NETS */ #endif /* IP_SET_HASH_WITH_NETS */
#define ext_timeout(e, h) \
(unsigned long *)(((void *)(e)) + (h)->offset[IPSET_EXT_ID_TIMEOUT])
#define ext_counter(e, h) \
(struct ip_set_counter *)(((void *)(e)) + (h)->offset[IPSET_EXT_ID_COUNTER])
#endif /* _IP_SET_HASH_GEN_H */ #endif /* _IP_SET_HASH_GEN_H */
/* Family dependent templates */ /* Family dependent templates */
@ -276,9 +271,6 @@ struct htype {
u32 maxelem; /* max elements in the hash */ u32 maxelem; /* max elements in the hash */
u32 elements; /* current element (vs timeout) */ u32 elements; /* current element (vs timeout) */
u32 initval; /* random jhash init value */ u32 initval; /* random jhash init value */
u32 timeout; /* timeout value, if enabled */
size_t dsize; /* data struct size */
size_t offset[IPSET_EXT_ID_MAX]; /* Offsets to extensions */
struct timer_list gc; /* garbage collection when timeout enabled */ struct timer_list gc; /* garbage collection when timeout enabled */
struct mtype_elem next; /* temporary storage for uadd */ struct mtype_elem next; /* temporary storage for uadd */
#ifdef IP_SET_HASH_WITH_MULTI #ifdef IP_SET_HASH_WITH_MULTI
@ -351,7 +343,7 @@ mtype_del_cidr(struct htype *h, u8 cidr, u8 nets_length, u8 n)
/* Calculate the actual memory size of the set data */ /* Calculate the actual memory size of the set data */
static size_t static size_t
mtype_ahash_memsize(const struct htype *h, const struct htable *t, mtype_ahash_memsize(const struct htype *h, const struct htable *t,
u8 nets_length) u8 nets_length, size_t dsize)
{ {
u32 i; u32 i;
size_t memsize = sizeof(*h) size_t memsize = sizeof(*h)
@ -362,7 +354,7 @@ mtype_ahash_memsize(const struct htype *h, const struct htable *t,
+ jhash_size(t->htable_bits) * sizeof(struct hbucket); + jhash_size(t->htable_bits) * sizeof(struct hbucket);
for (i = 0; i < jhash_size(t->htable_bits); i++) for (i = 0; i < jhash_size(t->htable_bits); i++)
memsize += t->bucket[i].size * h->dsize; memsize += t->bucket[i].size * dsize;
return memsize; return memsize;
} }
@ -417,10 +409,10 @@ mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
init_timer(&h->gc); init_timer(&h->gc);
h->gc.data = (unsigned long) set; h->gc.data = (unsigned long) set;
h->gc.function = gc; h->gc.function = gc;
h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
add_timer(&h->gc); add_timer(&h->gc);
pr_debug("gc initialized, run in every %u\n", pr_debug("gc initialized, run in every %u\n",
IPSET_GC_PERIOD(h->timeout)); IPSET_GC_PERIOD(set->timeout));
} }
static bool static bool
@ -431,7 +423,7 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
/* Resizing changes htable_bits, so we ignore it */ /* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem && return x->maxelem == y->maxelem &&
x->timeout == y->timeout && a->timeout == b->timeout &&
#ifdef IP_SET_HASH_WITH_NETMASK #ifdef IP_SET_HASH_WITH_NETMASK
x->netmask == y->netmask && x->netmask == y->netmask &&
#endif #endif
@ -444,7 +436,7 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b)
/* Delete expired elements from the hashtable */ /* Delete expired elements from the hashtable */
static void static void
mtype_expire(struct htype *h, u8 nets_length, size_t dsize) mtype_expire(struct ip_set *set, struct htype *h, u8 nets_length, size_t dsize)
{ {
struct htable *t; struct htable *t;
struct hbucket *n; struct hbucket *n;
@ -458,7 +450,7 @@ mtype_expire(struct htype *h, u8 nets_length, size_t dsize)
n = hbucket(t, i); n = hbucket(t, i);
for (j = 0; j < n->pos; j++) { for (j = 0; j < n->pos; j++) {
data = ahash_data(n, j, dsize); data = ahash_data(n, j, dsize);
if (ip_set_timeout_expired(ext_timeout(data, h))) { if (ip_set_timeout_expired(ext_timeout(data, set))) {
pr_debug("expired %u/%u\n", i, j); pr_debug("expired %u/%u\n", i, j);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
mtype_del_cidr(h, CIDR(data->cidr), mtype_del_cidr(h, CIDR(data->cidr),
@ -497,10 +489,10 @@ mtype_gc(unsigned long ul_set)
pr_debug("called\n"); pr_debug("called\n");
write_lock_bh(&set->lock); write_lock_bh(&set->lock);
mtype_expire(h, NLEN(set->family), h->dsize); mtype_expire(set, h, NLEN(set->family), set->dsize);
write_unlock_bh(&set->lock); write_unlock_bh(&set->lock);
h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; h->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
add_timer(&h->gc); add_timer(&h->gc);
} }
@ -526,7 +518,7 @@ mtype_resize(struct ip_set *set, bool retried)
if (SET_WITH_TIMEOUT(set) && !retried) { if (SET_WITH_TIMEOUT(set) && !retried) {
i = h->elements; i = h->elements;
write_lock_bh(&set->lock); write_lock_bh(&set->lock);
mtype_expire(set->data, NLEN(set->family), h->dsize); mtype_expire(set, set->data, NLEN(set->family), set->dsize);
write_unlock_bh(&set->lock); write_unlock_bh(&set->lock);
if (h->elements < i) if (h->elements < i)
return 0; return 0;
@ -553,13 +545,13 @@ retry:
for (i = 0; i < jhash_size(orig->htable_bits); i++) { for (i = 0; i < jhash_size(orig->htable_bits); i++) {
n = hbucket(orig, i); n = hbucket(orig, i);
for (j = 0; j < n->pos; j++) { for (j = 0; j < n->pos; j++) {
data = ahash_data(n, j, h->dsize); data = ahash_data(n, j, set->dsize);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
flags = 0; flags = 0;
mtype_data_reset_flags(data, &flags); mtype_data_reset_flags(data, &flags);
#endif #endif
m = hbucket(t, HKEY(data, h->initval, htable_bits)); m = hbucket(t, HKEY(data, h->initval, htable_bits));
ret = hbucket_elem_add(m, AHASH_MAX(h), h->dsize); ret = hbucket_elem_add(m, AHASH_MAX(h), set->dsize);
if (ret < 0) { if (ret < 0) {
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
mtype_data_reset_flags(data, &flags); mtype_data_reset_flags(data, &flags);
@ -570,8 +562,8 @@ retry:
goto retry; goto retry;
return ret; return ret;
} }
d = ahash_data(m, m->pos++, h->dsize); d = ahash_data(m, m->pos++, set->dsize);
memcpy(d, data, h->dsize); memcpy(d, data, set->dsize);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
mtype_data_reset_flags(d, &flags); mtype_data_reset_flags(d, &flags);
#endif #endif
@ -609,7 +601,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem) if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem)
/* FIXME: when set is full, we slow down here */ /* FIXME: when set is full, we slow down here */
mtype_expire(h, NLEN(set->family), h->dsize); mtype_expire(set, h, NLEN(set->family), set->dsize);
if (h->elements >= h->maxelem) { if (h->elements >= h->maxelem) {
if (net_ratelimit()) if (net_ratelimit())
@ -623,11 +615,11 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
key = HKEY(value, h->initval, t->htable_bits); key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i, h->dsize); data = ahash_data(n, i, set->dsize);
if (mtype_data_equal(data, d, &multi)) { if (mtype_data_equal(data, d, &multi)) {
if (flag_exist || if (flag_exist ||
(SET_WITH_TIMEOUT(set) && (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(data, h)))) { ip_set_timeout_expired(ext_timeout(data, set)))) {
/* Just the extensions could be overwritten */ /* Just the extensions could be overwritten */
j = i; j = i;
goto reuse_slot; goto reuse_slot;
@ -638,14 +630,14 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
} }
/* Reuse first timed out entry */ /* Reuse first timed out entry */
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(data, h)) && ip_set_timeout_expired(ext_timeout(data, set)) &&
j != AHASH_MAX(h) + 1) j != AHASH_MAX(h) + 1)
j = i; j = i;
} }
reuse_slot: reuse_slot:
if (j != AHASH_MAX(h) + 1) { if (j != AHASH_MAX(h) + 1) {
/* Fill out reused slot */ /* Fill out reused slot */
data = ahash_data(n, j, h->dsize); data = ahash_data(n, j, set->dsize);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
mtype_del_cidr(h, CIDR(data->cidr), NLEN(set->family), 0); mtype_del_cidr(h, CIDR(data->cidr), NLEN(set->family), 0);
mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0);
@ -653,13 +645,13 @@ reuse_slot:
} else { } else {
/* Use/create a new slot */ /* Use/create a new slot */
TUNE_AHASH_MAX(h, multi); TUNE_AHASH_MAX(h, multi);
ret = hbucket_elem_add(n, AHASH_MAX(h), h->dsize); ret = hbucket_elem_add(n, AHASH_MAX(h), set->dsize);
if (ret != 0) { if (ret != 0) {
if (ret == -EAGAIN) if (ret == -EAGAIN)
mtype_data_next(&h->next, d); mtype_data_next(&h->next, d);
goto out; goto out;
} }
data = ahash_data(n, n->pos++, h->dsize); data = ahash_data(n, n->pos++, set->dsize);
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0); mtype_add_cidr(h, CIDR(d->cidr), NLEN(set->family), 0);
#endif #endif
@ -670,9 +662,9 @@ reuse_slot:
mtype_data_set_flags(data, flags); mtype_data_set_flags(data, flags);
#endif #endif
if (SET_WITH_TIMEOUT(set)) if (SET_WITH_TIMEOUT(set))
ip_set_timeout_set(ext_timeout(data, h), ext->timeout); ip_set_timeout_set(ext_timeout(data, set), ext->timeout);
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(data, h), ext); ip_set_init_counter(ext_counter(data, set), ext);
out: out:
rcu_read_unlock_bh(); rcu_read_unlock_bh();
@ -699,16 +691,16 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
key = HKEY(value, h->initval, t->htable_bits); key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i, h->dsize); data = ahash_data(n, i, set->dsize);
if (!mtype_data_equal(data, d, &multi)) if (!mtype_data_equal(data, d, &multi))
continue; continue;
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(data, h))) ip_set_timeout_expired(ext_timeout(data, set)))
goto out; goto out;
if (i != n->pos - 1) if (i != n->pos - 1)
/* Not last one */ /* Not last one */
memcpy(data, ahash_data(n, n->pos - 1, h->dsize), memcpy(data, ahash_data(n, n->pos - 1, set->dsize),
h->dsize); set->dsize);
n->pos--; n->pos--;
h->elements--; h->elements--;
@ -717,14 +709,14 @@ mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
#endif #endif
if (n->pos + AHASH_INIT_SIZE < n->size) { if (n->pos + AHASH_INIT_SIZE < n->size) {
void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
* h->dsize, * set->dsize,
GFP_ATOMIC); GFP_ATOMIC);
if (!tmp) { if (!tmp) {
ret = 0; ret = 0;
goto out; goto out;
} }
n->size -= AHASH_INIT_SIZE; n->size -= AHASH_INIT_SIZE;
memcpy(tmp, n->value, n->size * h->dsize); memcpy(tmp, n->value, n->size * set->dsize);
kfree(n->value); kfree(n->value);
n->value = tmp; n->value = tmp;
} }
@ -742,8 +734,7 @@ mtype_data_match(struct mtype_elem *data, const struct ip_set_ext *ext,
struct ip_set_ext *mext, struct ip_set *set, u32 flags) struct ip_set_ext *mext, struct ip_set *set, u32 flags)
{ {
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_update_counter(ext_counter(data, ip_set_update_counter(ext_counter(data, set),
(struct htype *)(set->data)),
ext, mext, flags); ext, mext, flags);
return mtype_do_data_match(data); return mtype_do_data_match(data);
} }
@ -770,12 +761,12 @@ mtype_test_cidrs(struct ip_set *set, struct mtype_elem *d,
key = HKEY(d, h->initval, t->htable_bits); key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i, h->dsize); data = ahash_data(n, i, set->dsize);
if (!mtype_data_equal(data, d, &multi)) if (!mtype_data_equal(data, d, &multi))
continue; continue;
if (SET_WITH_TIMEOUT(set)) { if (SET_WITH_TIMEOUT(set)) {
if (!ip_set_timeout_expired( if (!ip_set_timeout_expired(
ext_timeout(data, h))) ext_timeout(data, set)))
return mtype_data_match(data, ext, return mtype_data_match(data, ext,
mext, set, mext, set,
flags); flags);
@ -818,10 +809,10 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
key = HKEY(d, h->initval, t->htable_bits); key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key); n = hbucket(t, key);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i, h->dsize); data = ahash_data(n, i, set->dsize);
if (mtype_data_equal(data, d, &multi) && if (mtype_data_equal(data, d, &multi) &&
!(SET_WITH_TIMEOUT(set) && !(SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(data, h)))) { ip_set_timeout_expired(ext_timeout(data, set)))) {
ret = mtype_data_match(data, ext, mext, set, flags); ret = mtype_data_match(data, ext, mext, set, flags);
goto out; goto out;
} }
@ -841,7 +832,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
size_t memsize; size_t memsize;
t = rcu_dereference_bh_nfnl(h->table); t = rcu_dereference_bh_nfnl(h->table);
memsize = mtype_ahash_memsize(h, t, NLEN(set->family)); memsize = mtype_ahash_memsize(h, t, NLEN(set->family), set->dsize);
nested = ipset_nest_start(skb, IPSET_ATTR_DATA); nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) if (!nested)
@ -858,7 +849,7 @@ mtype_head(struct ip_set *set, struct sk_buff *skb)
if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) || nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) ||
((set->extensions & IPSET_EXT_TIMEOUT) && ((set->extensions & IPSET_EXT_TIMEOUT) &&
nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout))) || nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(set->timeout))) ||
((set->extensions & IPSET_EXT_COUNTER) && ((set->extensions & IPSET_EXT_COUNTER) &&
nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS,
htonl(IPSET_FLAG_WITH_COUNTERS)))) htonl(IPSET_FLAG_WITH_COUNTERS))))
@ -894,9 +885,9 @@ mtype_list(const struct ip_set *set,
n = hbucket(t, cb->args[2]); n = hbucket(t, cb->args[2]);
pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n); pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
e = ahash_data(n, i, h->dsize); e = ahash_data(n, i, set->dsize);
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, h))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
pr_debug("list hash %lu hbucket %p i %u, data %p\n", pr_debug("list hash %lu hbucket %p i %u, data %p\n",
cb->args[2], n, i, e); cb->args[2], n, i, e);
@ -913,10 +904,10 @@ mtype_list(const struct ip_set *set,
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
nla_put_net32(skb, IPSET_ATTR_TIMEOUT, nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
htonl(ip_set_timeout_get( htonl(ip_set_timeout_get(
ext_timeout(e, h))))) ext_timeout(e, set)))))
goto nla_put_failure; goto nla_put_failure;
if (SET_WITH_COUNTER(set) && if (SET_WITH_COUNTER(set) &&
ip_set_put_counter(skb, ext_counter(e, h))) ip_set_put_counter(skb, ext_counter(e, set)))
goto nla_put_failure; goto nla_put_failure;
ipset_nest_end(skb, nested); ipset_nest_end(skb, nested);
} }
@ -1026,7 +1017,7 @@ IPSET_TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->netmask = netmask; h->netmask = netmask;
#endif #endif
get_random_bytes(&h->initval, sizeof(h->initval)); get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT; set->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize); hbits = htable_bits(hashsize);
hsize = htable_size(hbits); hsize = htable_size(hbits);
@ -1053,30 +1044,30 @@ IPSET_TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) {
set->extensions |= IPSET_EXT_COUNTER; set->extensions |= IPSET_EXT_COUNTER;
if (tb[IPSET_ATTR_TIMEOUT]) { if (tb[IPSET_ATTR_TIMEOUT]) {
h->timeout = set->timeout =
ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
if (set->family == NFPROTO_IPV4) { if (set->family == NFPROTO_IPV4) {
h->dsize = sizeof(struct set->dsize = sizeof(struct
IPSET_TOKEN(HTYPE, 4ct_elem)); IPSET_TOKEN(HTYPE, 4ct_elem));
h->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct offsetof(struct
IPSET_TOKEN(HTYPE, 4ct_elem), IPSET_TOKEN(HTYPE, 4ct_elem),
timeout); timeout);
h->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct offsetof(struct
IPSET_TOKEN(HTYPE, 4ct_elem), IPSET_TOKEN(HTYPE, 4ct_elem),
counter); counter);
IPSET_TOKEN(HTYPE, 4_gc_init)(set, IPSET_TOKEN(HTYPE, 4_gc_init)(set,
IPSET_TOKEN(HTYPE, 4_gc)); IPSET_TOKEN(HTYPE, 4_gc));
} else { } else {
h->dsize = sizeof(struct set->dsize = sizeof(struct
IPSET_TOKEN(HTYPE, 6ct_elem)); IPSET_TOKEN(HTYPE, 6ct_elem));
h->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct offsetof(struct
IPSET_TOKEN(HTYPE, 6ct_elem), IPSET_TOKEN(HTYPE, 6ct_elem),
timeout); timeout);
h->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct offsetof(struct
IPSET_TOKEN(HTYPE, 6ct_elem), IPSET_TOKEN(HTYPE, 6ct_elem),
counter); counter);
@ -1085,36 +1076,36 @@ IPSET_TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
} }
} else { } else {
if (set->family == NFPROTO_IPV4) { if (set->family == NFPROTO_IPV4) {
h->dsize = set->dsize =
sizeof(struct sizeof(struct
IPSET_TOKEN(HTYPE, 4c_elem)); IPSET_TOKEN(HTYPE, 4c_elem));
h->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct offsetof(struct
IPSET_TOKEN(HTYPE, 4c_elem), IPSET_TOKEN(HTYPE, 4c_elem),
counter); counter);
} else { } else {
h->dsize = set->dsize =
sizeof(struct sizeof(struct
IPSET_TOKEN(HTYPE, 6c_elem)); IPSET_TOKEN(HTYPE, 6c_elem));
h->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct offsetof(struct
IPSET_TOKEN(HTYPE, 6c_elem), IPSET_TOKEN(HTYPE, 6c_elem),
counter); counter);
} }
} }
} else if (tb[IPSET_ATTR_TIMEOUT]) { } else if (tb[IPSET_ATTR_TIMEOUT]) {
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
if (set->family == NFPROTO_IPV4) { if (set->family == NFPROTO_IPV4) {
h->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 4t_elem)); set->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 4t_elem));
h->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct IPSET_TOKEN(HTYPE, 4t_elem), offsetof(struct IPSET_TOKEN(HTYPE, 4t_elem),
timeout); timeout);
IPSET_TOKEN(HTYPE, 4_gc_init)(set, IPSET_TOKEN(HTYPE, 4_gc_init)(set,
IPSET_TOKEN(HTYPE, 4_gc)); IPSET_TOKEN(HTYPE, 4_gc));
} else { } else {
h->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 6t_elem)); set->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 6t_elem));
h->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct IPSET_TOKEN(HTYPE, 6t_elem), offsetof(struct IPSET_TOKEN(HTYPE, 6t_elem),
timeout); timeout);
IPSET_TOKEN(HTYPE, 6_gc_init)(set, IPSET_TOKEN(HTYPE, 6_gc_init)(set,
@ -1122,9 +1113,9 @@ IPSET_TOKEN(HTYPE, _create)(struct ip_set *set, struct nlattr *tb[], u32 flags)
} }
} else { } else {
if (set->family == NFPROTO_IPV4) if (set->family == NFPROTO_IPV4)
h->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 4_elem)); set->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 4_elem));
else else
h->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 6_elem)); set->dsize = sizeof(struct IPSET_TOKEN(HTYPE, 6_elem));
} }
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",

View File

@ -99,7 +99,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct hash_ip *h = set->data; const struct hash_ip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip4_elem e = {}; struct hash_ip4_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
__be32 ip; __be32 ip;
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip); ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
@ -118,7 +118,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ip *h = set->data; const struct hash_ip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip4_elem e = {}; struct hash_ip4_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, hosts; u32 ip = 0, ip_to = 0, hosts;
int ret = 0; int ret = 0;
@ -253,7 +253,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct hash_ip *h = set->data; const struct hash_ip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip6_elem e = {}; struct hash_ip6_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
hash_ip6_netmask(&e.ip, h->netmask); hash_ip6_netmask(&e.ip, h->netmask);
@ -270,7 +270,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ip *h = set->data; const struct hash_ip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ip6_elem e = {}; struct hash_ip6_elem e = {};
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
int ret; int ret;
if (unlikely(!tb[IPSET_ATTR_IP] || if (unlikely(!tb[IPSET_ATTR_IP] ||

View File

@ -116,10 +116,9 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt) enum ipset_adt adt, struct ip_set_adt_opt *opt)
{ {
const struct hash_ipport *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem e = { }; struct hash_ipport4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&e.port, &e.proto)) &e.port, &e.proto))
@ -136,7 +135,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ipport *h = set->data; const struct hash_ipport *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport4_elem e = { }; struct hash_ipport4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip, ip_to = 0, p = 0, port, port_to; u32 ip, ip_to = 0, p = 0, port, port_to;
bool with_ports = false; bool with_ports = false;
int ret; int ret;
@ -306,10 +305,9 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt) enum ipset_adt adt, struct ip_set_adt_opt *opt)
{ {
const struct hash_ipport *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem e = { }; struct hash_ipport6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&e.port, &e.proto)) &e.port, &e.proto))
@ -326,7 +324,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ipport *h = set->data; const struct hash_ipport *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipport6_elem e = { }; struct hash_ipport6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port, port_to; u32 port, port_to;
bool with_ports = false; bool with_ports = false;
int ret; int ret;

View File

@ -120,10 +120,9 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt) enum ipset_adt adt, struct ip_set_adt_opt *opt)
{ {
const struct hash_ipportip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem e = { }; struct hash_ipportip4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC, if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&e.port, &e.proto)) &e.port, &e.proto))
@ -141,7 +140,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ipportip *h = set->data; const struct hash_ipportip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip4_elem e = { }; struct hash_ipportip4_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip, ip_to = 0, p = 0, port, port_to; u32 ip, ip_to = 0, p = 0, port, port_to;
bool with_ports = false; bool with_ports = false;
int ret; int ret;
@ -319,10 +318,9 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt) enum ipset_adt adt, struct ip_set_adt_opt *opt)
{ {
const struct hash_ipportip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip6_elem e = { }; struct hash_ipportip6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC, if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
&e.port, &e.proto)) &e.port, &e.proto))
@ -340,7 +338,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ipportip *h = set->data; const struct hash_ipportip *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportip6_elem e = { }; struct hash_ipportip6_elem e = { };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port, port_to; u32 port, port_to;
bool with_ports = false; bool with_ports = false;
int ret; int ret;

View File

@ -172,7 +172,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_ipportnet4_elem e = { struct hash_ipportnet4_elem e = {
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1, .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (adt == IPSET_TEST) if (adt == IPSET_TEST)
e.cidr = HOST_MASK - 1; e.cidr = HOST_MASK - 1;
@ -195,7 +195,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ipportnet *h = set->data; const struct hash_ipportnet *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 }; struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, p = 0, port, port_to; u32 ip = 0, ip_to = 0, p = 0, port, port_to;
u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
bool with_ports = false; bool with_ports = false;
@ -306,9 +306,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
: port; : port;
for (; p <= port_to; p++) { for (; p <= port_to; p++) {
e.port = htons(p); e.port = htons(p);
ip2 = retried ip2 = retried &&
&& ip == ntohl(h->next.ip) ip == ntohl(h->next.ip) &&
&& p == ntohs(h->next.port) p == ntohs(h->next.port)
? ntohl(h->next.ip2) : ip2_from; ? ntohl(h->next.ip2) : ip2_from;
while (!after(ip2, ip2_to)) { while (!after(ip2, ip2_to)) {
e.ip2 = htonl(ip2); e.ip2 = htonl(ip2);
@ -456,7 +456,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_ipportnet6_elem e = { struct hash_ipportnet6_elem e = {
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1, .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (adt == IPSET_TEST) if (adt == IPSET_TEST)
e.cidr = HOST_MASK - 1; e.cidr = HOST_MASK - 1;
@ -479,7 +479,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_ipportnet *h = set->data; const struct hash_ipportnet *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_ipportnet6_elem e = { .cidr = HOST_MASK - 1 }; struct hash_ipportnet6_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port, port_to; u32 port, port_to;
bool with_ports = false; bool with_ports = false;
u8 cidr; u8 cidr;

View File

@ -145,7 +145,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_net4_elem e = { struct hash_net4_elem e = {
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (e.cidr == 0) if (e.cidr == 0)
return -EINVAL; return -EINVAL;
@ -165,7 +165,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_net *h = set->data; const struct hash_net *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net4_elem e = { .cidr = HOST_MASK }; struct hash_net4_elem e = { .cidr = HOST_MASK };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, last; u32 ip = 0, ip_to = 0, last;
int ret; int ret;
@ -340,7 +340,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_net6_elem e = { struct hash_net6_elem e = {
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (e.cidr == 0) if (e.cidr == 0)
return -EINVAL; return -EINVAL;
@ -357,10 +357,9 @@ static int
hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{ {
const struct hash_net *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_net6_elem e = { .cidr = HOST_MASK }; struct hash_net6_elem e = { .cidr = HOST_MASK };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
int ret; int ret;
if (unlikely(!tb[IPSET_ATTR_IP] || if (unlikely(!tb[IPSET_ATTR_IP] ||

View File

@ -268,7 +268,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
.elem = 1, .elem = 1,
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
int ret; int ret;
if (e.cidr == 0) if (e.cidr == 0)
@ -319,7 +319,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
struct hash_netiface *h = set->data; struct hash_netiface *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 ip = 0, ip_to = 0, last; u32 ip = 0, ip_to = 0, last;
char iface[IFNAMSIZ]; char iface[IFNAMSIZ];
int ret; int ret;
@ -537,7 +537,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK), .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK),
.elem = 1, .elem = 1,
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
int ret; int ret;
if (e.cidr == 0) if (e.cidr == 0)
@ -584,7 +584,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
struct hash_netiface *h = set->data; struct hash_netiface *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 }; struct hash_netiface6_elem e = { .cidr = HOST_MASK, .elem = 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
char iface[IFNAMSIZ]; char iface[IFNAMSIZ];
int ret; int ret;

View File

@ -164,7 +164,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_netport4_elem e = { struct hash_netport4_elem e = {
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1, .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (adt == IPSET_TEST) if (adt == IPSET_TEST)
e.cidr = HOST_MASK - 1; e.cidr = HOST_MASK - 1;
@ -186,7 +186,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_netport *h = set->data; const struct hash_netport *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 }; struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port, port_to, p = 0, ip = 0, ip_to = 0, last; u32 port, port_to, p = 0, ip = 0, ip_to = 0, last;
bool with_ports = false; bool with_ports = false;
u8 cidr; u8 cidr;
@ -409,7 +409,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_netport6_elem e = { struct hash_netport6_elem e = {
.cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1, .cidr = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK) - 1,
}; };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (adt == IPSET_TEST) if (adt == IPSET_TEST)
e.cidr = HOST_MASK - 1; e.cidr = HOST_MASK - 1;
@ -431,7 +431,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
const struct hash_netport *h = set->data; const struct hash_netport *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netport6_elem e = { .cidr = HOST_MASK - 1 }; struct hash_netport6_elem e = { .cidr = HOST_MASK - 1 };
struct ip_set_ext ext = IP_SET_INIT_UEXT(h); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
u32 port, port_to; u32 port, port_to;
bool with_ports = false; bool with_ports = false;
u8 cidr; u8 cidr;

View File

@ -58,24 +58,13 @@ struct set_adt_elem {
/* Type structure */ /* Type structure */
struct list_set { struct list_set {
size_t dsize; /* element size */
size_t offset[IPSET_EXT_ID_MAX]; /* Offsets to extensions */
u32 size; /* size of set list array */ u32 size; /* size of set list array */
u32 timeout; /* timeout value */
struct timer_list gc; /* garbage collection */ struct timer_list gc; /* garbage collection */
struct set_elem members[0]; /* the set members */ struct set_elem members[0]; /* the set members */
}; };
static inline struct set_elem * #define list_set_elem(set, map, id) \
list_set_elem(const struct list_set *map, u32 id) (struct set_elem *)((void *)(map)->members + (id) * (set)->dsize)
{
return (struct set_elem *)((void *)map->members + id * map->dsize);
}
#define ext_timeout(e, m) \
(unsigned long *)((void *)(e) + (m)->offset[IPSET_EXT_ID_TIMEOUT])
#define ext_counter(e, m) \
(struct ip_set_counter *)((void *)(e) + (m)->offset[IPSET_EXT_ID_COUNTER])
static int static int
list_set_ktest(struct ip_set *set, const struct sk_buff *skb, list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
@ -92,16 +81,16 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE) if (opt->cmdflags & IPSET_FLAG_SKIP_SUBCOUNTER_UPDATE)
opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE; opt->cmdflags &= ~IPSET_FLAG_SKIP_COUNTER_UPDATE;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
return 0; return 0;
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
ret = ip_set_test(e->id, skb, par, opt); ret = ip_set_test(e->id, skb, par, opt);
if (ret > 0) { if (ret > 0) {
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_update_counter(ext_counter(e, map), ip_set_update_counter(ext_counter(e, set),
ext, &opt->ext, ext, &opt->ext,
cmdflags); cmdflags);
return ret; return ret;
@ -121,11 +110,11 @@ list_set_kadd(struct ip_set *set, const struct sk_buff *skb,
int ret; int ret;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
return 0; return 0;
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
ret = ip_set_add(e->id, skb, par, opt); ret = ip_set_add(e->id, skb, par, opt);
if (ret == 0) if (ret == 0)
@ -145,11 +134,11 @@ list_set_kdel(struct ip_set *set, const struct sk_buff *skb,
int ret; int ret;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
return 0; return 0;
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
ret = ip_set_del(e->id, skb, par, opt); ret = ip_set_del(e->id, skb, par, opt);
if (ret == 0) if (ret == 0)
@ -163,8 +152,7 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par, const struct xt_action_param *par,
enum ipset_adt adt, struct ip_set_adt_opt *opt) enum ipset_adt adt, struct ip_set_adt_opt *opt)
{ {
struct list_set *map = set->data; struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, map);
switch (adt) { switch (adt) {
case IPSET_TEST: case IPSET_TEST:
@ -188,10 +176,10 @@ id_eq(const struct ip_set *set, u32 i, ip_set_id_t id)
if (i >= map->size) if (i >= map->size)
return 0; return 0;
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
return !!(e->id == id && return !!(e->id == id &&
!(SET_WITH_TIMEOUT(set) && !(SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map)))); ip_set_timeout_expired(ext_timeout(e, set))));
} }
static int static int
@ -199,28 +187,29 @@ list_set_add(struct ip_set *set, u32 i, struct set_adt_elem *d,
const struct ip_set_ext *ext) const struct ip_set_ext *ext)
{ {
struct list_set *map = set->data; struct list_set *map = set->data;
struct set_elem *e = list_set_elem(map, i); struct set_elem *e = list_set_elem(set, map, i);
if (e->id != IPSET_INVALID_ID) { if (e->id != IPSET_INVALID_ID) {
if (i == map->size - 1) if (i == map->size - 1)
/* Last element replaced: e.g. add new,before,last */ /* Last element replaced: e.g. add new,before,last */
ip_set_put_byindex(e->id); ip_set_put_byindex(e->id);
else { else {
struct set_elem *x = list_set_elem(map, map->size - 1); struct set_elem *x = list_set_elem(set, map,
map->size - 1);
/* Last element pushed off */ /* Last element pushed off */
if (x->id != IPSET_INVALID_ID) if (x->id != IPSET_INVALID_ID)
ip_set_put_byindex(x->id); ip_set_put_byindex(x->id);
memmove(list_set_elem(map, i + 1), e, memmove(list_set_elem(set, map, i + 1), e,
map->dsize * (map->size - (i + 1))); set->dsize * (map->size - (i + 1)));
} }
} }
e->id = d->id; e->id = d->id;
if (SET_WITH_TIMEOUT(set)) if (SET_WITH_TIMEOUT(set))
ip_set_timeout_set(ext_timeout(e, map), ext->timeout); ip_set_timeout_set(ext_timeout(e, set), ext->timeout);
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(e, map), ext); ip_set_init_counter(ext_counter(e, set), ext);
return 0; return 0;
} }
@ -228,16 +217,16 @@ static int
list_set_del(struct ip_set *set, u32 i) list_set_del(struct ip_set *set, u32 i)
{ {
struct list_set *map = set->data; struct list_set *map = set->data;
struct set_elem *e = list_set_elem(map, i); struct set_elem *e = list_set_elem(set, map, i);
ip_set_put_byindex(e->id); ip_set_put_byindex(e->id);
if (i < map->size - 1) if (i < map->size - 1)
memmove(e, list_set_elem(map, i + 1), memmove(e, list_set_elem(set, map, i + 1),
map->dsize * (map->size - (i + 1))); set->dsize * (map->size - (i + 1)));
/* Last element */ /* Last element */
e = list_set_elem(map, map->size - 1); e = list_set_elem(set, map, map->size - 1);
e->id = IPSET_INVALID_ID; e->id = IPSET_INVALID_ID;
return 0; return 0;
} }
@ -250,9 +239,9 @@ set_cleanup_entries(struct ip_set *set)
u32 i; u32 i;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id != IPSET_INVALID_ID && if (e->id != IPSET_INVALID_ID &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
list_set_del(set, i); list_set_del(set, i);
} }
} }
@ -268,11 +257,11 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext,
int ret; int ret;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
return 0; return 0;
else if (SET_WITH_TIMEOUT(set) && else if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
else if (e->id != d->id) else if (e->id != d->id)
continue; continue;
@ -301,11 +290,11 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
/* Check already added element */ /* Check already added element */
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
goto insert; goto insert;
else if (SET_WITH_TIMEOUT(set) && else if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
else if (e->id != d->id) else if (e->id != d->id)
continue; continue;
@ -320,9 +309,9 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
return -IPSET_ERR_EXIST; return -IPSET_ERR_EXIST;
/* Update extensions */ /* Update extensions */
if (SET_WITH_TIMEOUT(set)) if (SET_WITH_TIMEOUT(set))
ip_set_timeout_set(ext_timeout(e, map), ext->timeout); ip_set_timeout_set(ext_timeout(e, set), ext->timeout);
if (SET_WITH_COUNTER(set)) if (SET_WITH_COUNTER(set))
ip_set_init_counter(ext_counter(e, map), ext); ip_set_init_counter(ext_counter(e, set), ext);
/* Set is already added to the list */ /* Set is already added to the list */
ip_set_put_byindex(d->id); ip_set_put_byindex(d->id);
return 0; return 0;
@ -330,7 +319,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
insert: insert:
ret = -IPSET_ERR_LIST_FULL; ret = -IPSET_ERR_LIST_FULL;
for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) { for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
ret = d->before != 0 ? -IPSET_ERR_REF_EXIST ret = d->before != 0 ? -IPSET_ERR_REF_EXIST
: list_set_add(set, i, d, ext); : list_set_add(set, i, d, ext);
@ -355,12 +344,12 @@ list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext,
u32 i; u32 i;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
return d->before != 0 ? -IPSET_ERR_REF_EXIST return d->before != 0 ? -IPSET_ERR_REF_EXIST
: -IPSET_ERR_EXIST; : -IPSET_ERR_EXIST;
else if (SET_WITH_TIMEOUT(set) && else if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
else if (e->id != d->id) else if (e->id != d->id)
continue; continue;
@ -383,10 +372,9 @@ static int
list_set_uadt(struct ip_set *set, struct nlattr *tb[], list_set_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{ {
struct list_set *map = set->data;
ipset_adtfn adtfn = set->variant->adt[adt]; ipset_adtfn adtfn = set->variant->adt[adt];
struct set_adt_elem e = { .refid = IPSET_INVALID_ID }; struct set_adt_elem e = { .refid = IPSET_INVALID_ID };
struct ip_set_ext ext = IP_SET_INIT_UEXT(map); struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
struct ip_set *s; struct ip_set *s;
int ret = 0; int ret = 0;
@ -454,7 +442,7 @@ list_set_flush(struct ip_set *set)
u32 i; u32 i;
for (i = 0; i < map->size; i++) { for (i = 0; i < map->size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id != IPSET_INVALID_ID) { if (e->id != IPSET_INVALID_ID) {
ip_set_put_byindex(e->id); ip_set_put_byindex(e->id);
e->id = IPSET_INVALID_ID; e->id = IPSET_INVALID_ID;
@ -486,13 +474,13 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
goto nla_put_failure; goto nla_put_failure;
if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) || if (nla_put_net32(skb, IPSET_ATTR_SIZE, htonl(map->size)) ||
(SET_WITH_TIMEOUT(set) && (SET_WITH_TIMEOUT(set) &&
nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) || nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(set->timeout))) ||
(SET_WITH_COUNTER(set) && (SET_WITH_COUNTER(set) &&
nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS,
htonl(IPSET_FLAG_WITH_COUNTERS))) || htonl(IPSET_FLAG_WITH_COUNTERS))) ||
nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
nla_put_net32(skb, IPSET_ATTR_MEMSIZE, nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
htonl(sizeof(*map) + map->size * map->dsize))) htonl(sizeof(*map) + map->size * set->dsize)))
goto nla_put_failure; goto nla_put_failure;
ipset_nest_end(skb, nested); ipset_nest_end(skb, nested);
@ -515,11 +503,11 @@ list_set_list(const struct ip_set *set,
return -EMSGSIZE; return -EMSGSIZE;
for (; cb->args[2] < map->size; cb->args[2]++) { for (; cb->args[2] < map->size; cb->args[2]++) {
i = cb->args[2]; i = cb->args[2];
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
goto finish; goto finish;
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, map))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
nested = ipset_nest_start(skb, IPSET_ATTR_DATA); nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) { if (!nested) {
@ -535,10 +523,10 @@ list_set_list(const struct ip_set *set,
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
nla_put_net32(skb, IPSET_ATTR_TIMEOUT, nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
htonl(ip_set_timeout_get( htonl(ip_set_timeout_get(
ext_timeout(e, map))))) ext_timeout(e, set)))))
goto nla_put_failure; goto nla_put_failure;
if (SET_WITH_COUNTER(set) && if (SET_WITH_COUNTER(set) &&
ip_set_put_counter(skb, ext_counter(e, map))) ip_set_put_counter(skb, ext_counter(e, set)))
goto nla_put_failure; goto nla_put_failure;
ipset_nest_end(skb, nested); ipset_nest_end(skb, nested);
} }
@ -565,7 +553,7 @@ list_set_same_set(const struct ip_set *a, const struct ip_set *b)
const struct list_set *y = b->data; const struct list_set *y = b->data;
return x->size == y->size && return x->size == y->size &&
x->timeout == y->timeout && a->timeout == b->timeout &&
a->extensions == b->extensions; a->extensions == b->extensions;
} }
@ -594,7 +582,7 @@ list_set_gc(unsigned long ul_set)
set_cleanup_entries(set); set_cleanup_entries(set);
write_unlock_bh(&set->lock); write_unlock_bh(&set->lock);
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
add_timer(&map->gc); add_timer(&map->gc);
} }
@ -606,7 +594,7 @@ list_set_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
init_timer(&map->gc); init_timer(&map->gc);
map->gc.data = (unsigned long) set; map->gc.data = (unsigned long) set;
map->gc.function = gc; map->gc.function = gc;
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ;
add_timer(&map->gc); add_timer(&map->gc);
} }
@ -625,12 +613,12 @@ init_list_set(struct ip_set *set, u32 size, size_t dsize,
return NULL; return NULL;
map->size = size; map->size = size;
map->dsize = dsize; set->dsize = dsize;
map->timeout = timeout; set->timeout = timeout;
set->data = map; set->data = map;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
e = list_set_elem(map, i); e = list_set_elem(set, map, i);
e->id = IPSET_INVALID_ID; e->id = IPSET_INVALID_ID;
} }
@ -667,9 +655,9 @@ list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
if (!map) if (!map)
return -ENOMEM; return -ENOMEM;
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct setct_elem, timeout); offsetof(struct setct_elem, timeout);
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct setct_elem, counter); offsetof(struct setct_elem, counter);
list_set_gc_init(set, list_set_gc); list_set_gc_init(set, list_set_gc);
} else { } else {
@ -677,7 +665,7 @@ list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
sizeof(struct setc_elem), 0); sizeof(struct setc_elem), 0);
if (!map) if (!map)
return -ENOMEM; return -ENOMEM;
map->offset[IPSET_EXT_ID_COUNTER] = set->offset[IPSET_EXT_ID_COUNTER] =
offsetof(struct setc_elem, counter); offsetof(struct setc_elem, counter);
} }
} else if (tb[IPSET_ATTR_TIMEOUT]) { } else if (tb[IPSET_ATTR_TIMEOUT]) {
@ -686,7 +674,7 @@ list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
if (!map) if (!map)
return -ENOMEM; return -ENOMEM;
set->extensions |= IPSET_EXT_TIMEOUT; set->extensions |= IPSET_EXT_TIMEOUT;
map->offset[IPSET_EXT_ID_TIMEOUT] = set->offset[IPSET_EXT_ID_TIMEOUT] =
offsetof(struct sett_elem, timeout); offsetof(struct sett_elem, timeout);
list_set_gc_init(set, list_set_gc); list_set_gc_init(set, list_set_gc);
} else { } else {