1 /* Copyright (C) 2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
8 #ifndef __IP_SET_BITMAP_IP_GEN_H
9 #define __IP_SET_BITMAP_IP_GEN_H
11 #define CONCAT(a, b) a##b
12 #define TOKEN(a,b) CONCAT(a, b)
14 #define mtype_do_test TOKEN(MTYPE, _do_test)
15 #define mtype_gc_test TOKEN(MTYPE, _gc_test)
16 #define mtype_is_filled TOKEN(MTYPE, _is_filled)
17 #define mtype_do_add TOKEN(MTYPE, _do_add)
18 #define mtype_do_del TOKEN(MTYPE, _do_del)
19 #define mtype_do_list TOKEN(MTYPE, _do_list)
20 #define mtype_do_head TOKEN(MTYPE, _do_head)
21 #define mtype_adt_elem TOKEN(MTYPE, _adt_elem)
22 #define mtype_add_timeout TOKEN(MTYPE, _add_timeout)
23 #define mtype_gc_init TOKEN(MTYPE, _gc_init)
24 #define mtype_kadt TOKEN(MTYPE, _kadt)
25 #define mtype_uadt TOKEN(MTYPE, _uadt)
26 #define mtype_destroy TOKEN(MTYPE, _destroy)
27 #define mtype_flush TOKEN(MTYPE, _flush)
28 #define mtype_head TOKEN(MTYPE, _head)
29 #define mtype_same_set TOKEN(MTYPE, _same_set)
30 #define mtype_elem TOKEN(MTYPE, _elem)
31 #define mtype_test TOKEN(MTYPE, _test)
32 #define mtype_add TOKEN(MTYPE, _add)
33 #define mtype_del TOKEN(MTYPE, _del)
34 #define mtype_list TOKEN(MTYPE, _list)
35 #define mtype_gc TOKEN(MTYPE, _gc)
38 #define ext_timeout(e, m) \
39 (unsigned long *)((e) + (m)->offset[IPSET_OFFSET_TIMEOUT])
40 #define ext_counter(e, m) \
41 (struct ip_set_counter *)((e) + (m)->offset[IPSET_OFFSET_COUNTER])
42 #define get_ext(map, id) ((map)->extensions + (map)->dsize * (id))
45 mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set))
47 struct mtype *map = set->data;
50 map->gc.data = (unsigned long) set;
51 map->gc.function = gc;
52 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
57 mtype_destroy(struct ip_set *set)
59 struct mtype *map = set->data;
61 if (SET_WITH_TIMEOUT(set))
62 del_timer_sync(&map->gc);
64 ip_set_free(map->members);
66 ip_set_free(map->extensions);
73 mtype_flush(struct ip_set *set)
75 struct mtype *map = set->data;
77 memset(map->members, 0, map->memsize);
81 mtype_head(struct ip_set *set, struct sk_buff *skb)
83 const struct mtype *map = set->data;
84 struct nlattr *nested;
86 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
89 if (mtype_do_head(skb, map) ||
90 nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) ||
91 nla_put_net32(skb, IPSET_ATTR_MEMSIZE,
94 map->dsize * map->elements)) ||
95 (SET_WITH_TIMEOUT(set) &&
96 nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) ||
97 (SET_WITH_COUNTER(set) &&
98 nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS,
99 htonl(IPSET_FLAG_WITH_COUNTERS))))
100 goto nla_put_failure;
101 ipset_nest_end(skb, nested);
109 mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
110 struct ip_set_ext *mext, u32 flags)
112 struct mtype *map = set->data;
113 const struct mtype_adt_elem *e = value;
114 void *x = get_ext(map, e->id);
115 int ret = mtype_do_test(e, map);
119 if (SET_WITH_TIMEOUT(set) &&
120 ip_set_timeout_expired(ext_timeout(x, map)))
122 if (SET_WITH_COUNTER(set))
123 ip_set_update_counter(ext_counter(x, map), ext, mext, flags);
128 mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
129 struct ip_set_ext *mext, u32 flags)
131 struct mtype *map = set->data;
132 const struct mtype_adt_elem *e = value;
133 void *x = get_ext(map, e->id);
134 int ret = mtype_do_add(e, map, flags);
136 if (ret == IPSET_ADD_FAILED) {
137 if (SET_WITH_TIMEOUT(set) &&
138 ip_set_timeout_expired(ext_timeout(x, map)))
140 else if (!(flags & IPSET_FLAG_EXIST))
141 return -IPSET_ERR_EXIST;
144 if (SET_WITH_TIMEOUT(set))
145 #ifdef IP_SET_BITMAP_STORED_TIMEOUT
146 mtype_add_timeout(ext_timeout(x, map), e, ext, map, ret);
148 ip_set_timeout_set(ext_timeout(x, map), ext->timeout);
151 if (SET_WITH_COUNTER(set))
152 ip_set_init_counter(ext_counter(x, map), ext);
157 mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext,
158 struct ip_set_ext *mext, u32 flags)
160 struct mtype *map = set->data;
161 const struct mtype_adt_elem *e = value;
162 const void *x = get_ext(map, e->id);
164 if (mtype_do_del(e, map) ||
165 (SET_WITH_TIMEOUT(set) &&
166 ip_set_timeout_expired(ext_timeout(x, map))))
167 return -IPSET_ERR_EXIST;
173 mtype_list(const struct ip_set *set,
174 struct sk_buff *skb, struct netlink_callback *cb)
176 struct mtype *map = set->data;
177 struct nlattr *adt, *nested;
179 u32 id, first = cb->args[2];
181 adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
184 for (; cb->args[2] < map->elements; cb->args[2]++) {
186 x = get_ext(map, id);
187 if (!test_bit(id, map->members) ||
188 (SET_WITH_TIMEOUT(set) &&
189 #ifdef IP_SET_BITMAP_STORED_TIMEOUT
190 mtype_is_filled((const struct mtype_elem *) x) &&
192 ip_set_timeout_expired(ext_timeout(x, map))))
194 nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
197 nla_nest_cancel(skb, adt);
200 goto nla_put_failure;
202 if (mtype_do_list(skb, map, id))
203 goto nla_put_failure;
204 if (SET_WITH_TIMEOUT(set)) {
205 #ifdef IP_SET_BITMAP_STORED_TIMEOUT
206 if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
207 htonl(ip_set_timeout_stored(map, id,
208 ext_timeout(x, map)))))
209 goto nla_put_failure;
211 if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
212 htonl(ip_set_timeout_get(
213 ext_timeout(x, map)))))
214 goto nla_put_failure;
217 if (SET_WITH_COUNTER(set) &&
218 ip_set_put_counter(skb, ext_counter(x, map)))
219 goto nla_put_failure;
220 ipset_nest_end(skb, nested);
222 ipset_nest_end(skb, adt);
224 /* Set listing finished */
230 nla_nest_cancel(skb, nested);
231 ipset_nest_end(skb, adt);
232 if (unlikely(id == first)) {
240 mtype_gc(unsigned long ul_set)
242 struct ip_set *set = (struct ip_set *) ul_set;
243 struct mtype *map = set->data;
247 /* We run parallel with other readers (test element)
248 * but adding/deleting new entries is locked out */
249 read_lock_bh(&set->lock);
250 for (id = 0; id < map->elements; id++)
251 if (mtype_gc_test(id, map)) {
252 x = get_ext(map, id);
253 if (ip_set_timeout_expired(ext_timeout(x, map)))
254 clear_bit(id, map->members);
256 read_unlock_bh(&set->lock);
258 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
262 static const struct ip_set_type_variant mtype = {
266 [IPSET_ADD] = mtype_add,
267 [IPSET_DEL] = mtype_del,
268 [IPSET_TEST] = mtype_test,
270 .destroy = mtype_destroy,
271 .flush = mtype_flush,
274 .same_set = mtype_same_set,
277 #endif /* __IP_SET_BITMAP_IP_GEN_H */