Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ipset: Unified bitmap type generation

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Jozsef Kadlecsik and committed by
Pablo Neira Ayuso
4d73de38 075e64c0

+271
+6
include/linux/netfilter/ipset/ip_set_bitmap.h
··· 5 5 6 6 #define IPSET_BITMAP_MAX_RANGE 0x0000FFFF 7 7 8 + enum { 9 + IPSET_ADD_FAILED = 1, 10 + IPSET_ADD_STORE_PLAIN_TIMEOUT, 11 + IPSET_ADD_START_STORED_TIMEOUT, 12 + }; 13 + 8 14 /* Common functions */ 9 15 10 16 static inline u32
+265
net/netfilter/ipset/ip_set_bitmap_gen.h
··· 1 + /* Copyright (C) 2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 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. 6 + */ 7 + 8 + #ifndef __IP_SET_BITMAP_IP_GEN_H 9 + #define __IP_SET_BITMAP_IP_GEN_H 10 + 11 + #define CONCAT(a, b) a##b 12 + #define TOKEN(a,b) CONCAT(a, b) 13 + 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) 36 + #define mtype MTYPE 37 + 38 + #define ext_timeout(e, m) \ 39 + (unsigned long *)((e) + (m)->offset[IPSET_OFFSET_TIMEOUT]) 40 + #define get_ext(map, id) ((map)->extensions + (map)->dsize * (id)) 41 + 42 + static void 43 + mtype_gc_init(struct ip_set *set, void (*gc)(unsigned long ul_set)) 44 + { 45 + struct mtype *map = set->data; 46 + 47 + init_timer(&map->gc); 48 + map->gc.data = (unsigned long) set; 49 + map->gc.function = gc; 50 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 51 + add_timer(&map->gc); 52 + } 53 + 54 + static void 55 + mtype_destroy(struct ip_set *set) 56 + { 57 + struct mtype *map = set->data; 58 + 59 + if (SET_WITH_TIMEOUT(set)) 60 + del_timer_sync(&map->gc); 61 + 62 + ip_set_free(map->members); 63 + if (map->dsize) 64 + ip_set_free(map->extensions); 65 + kfree(map); 66 + 67 + set->data = NULL; 68 + } 69 + 70 + static void 71 + mtype_flush(struct ip_set *set) 72 + { 73 + struct mtype *map = set->data; 74 + 75 + memset(map->members, 0, map->memsize); 76 + } 77 + 78 + static int 79 + mtype_head(struct ip_set *set, struct sk_buff *skb) 80 + { 81 + const struct mtype *map = set->data; 82 + struct nlattr *nested; 83 + 84 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 85 + if (!nested) 86 + goto nla_put_failure; 87 + if (mtype_do_head(skb, map) || 88 + nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || 89 + nla_put_net32(skb, IPSET_ATTR_MEMSIZE, 90 + htonl(sizeof(*map) + 91 + map->memsize + 92 + map->dsize * map->elements)) || 93 + (SET_WITH_TIMEOUT(set) && 94 + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)))) 95 + goto nla_put_failure; 96 + ipset_nest_end(skb, nested); 97 + 98 + return 0; 99 + nla_put_failure: 100 + return -EMSGSIZE; 101 + } 102 + 103 + static int 104 + mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, 105 + struct ip_set_ext *mext, u32 flags) 106 + { 107 + struct mtype *map = set->data; 108 + const struct mtype_adt_elem *e = value; 109 + void *x = get_ext(map, e->id); 110 + int ret = mtype_do_test(e, map); 111 + 112 + if (ret <= 0) 113 + return ret; 114 + if (SET_WITH_TIMEOUT(set) && 115 + ip_set_timeout_expired(ext_timeout(x, map))) 116 + return 0; 117 + return 1; 118 + } 119 + 120 + static int 121 + mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, 122 + struct ip_set_ext *mext, u32 flags) 123 + { 124 + struct mtype *map = set->data; 125 + const struct mtype_adt_elem *e = value; 126 + void *x = get_ext(map, e->id); 127 + int ret = mtype_do_add(e, map, flags); 128 + 129 + if (ret == IPSET_ADD_FAILED) { 130 + if (SET_WITH_TIMEOUT(set) && 131 + ip_set_timeout_expired(ext_timeout(x, map))) 132 + ret = 0; 133 + else if (!(flags & IPSET_FLAG_EXIST)) 134 + return -IPSET_ERR_EXIST; 135 + } 136 + 137 + if (SET_WITH_TIMEOUT(set)) 138 + #ifdef IP_SET_BITMAP_STORED_TIMEOUT 139 + mtype_add_timeout(ext_timeout(x, map), e, ext, map, ret); 140 + #else 141 + ip_set_timeout_set(ext_timeout(x, map), ext->timeout); 142 + #endif 143 + 144 + return 0; 145 + } 146 + 147 + static int 148 + mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, 149 + struct ip_set_ext *mext, u32 flags) 150 + { 151 + struct mtype *map = set->data; 152 + const struct mtype_adt_elem *e = value; 153 + const void *x = get_ext(map, e->id); 154 + 155 + if (mtype_do_del(e, map) || 156 + (SET_WITH_TIMEOUT(set) && 157 + ip_set_timeout_expired(ext_timeout(x, map)))) 158 + return -IPSET_ERR_EXIST; 159 + 160 + return 0; 161 + } 162 + 163 + static int 164 + mtype_list(const struct ip_set *set, 165 + struct sk_buff *skb, struct netlink_callback *cb) 166 + { 167 + struct mtype *map = set->data; 168 + struct nlattr *adt, *nested; 169 + void *x; 170 + u32 id, first = cb->args[2]; 171 + 172 + adt = ipset_nest_start(skb, IPSET_ATTR_ADT); 173 + if (!adt) 174 + return -EMSGSIZE; 175 + for (; cb->args[2] < map->elements; cb->args[2]++) { 176 + id = cb->args[2]; 177 + x = get_ext(map, id); 178 + if (!test_bit(id, map->members) || 179 + (SET_WITH_TIMEOUT(set) && 180 + #ifdef IP_SET_BITMAP_STORED_TIMEOUT 181 + mtype_is_filled((const struct mtype_elem *) x) && 182 + #endif 183 + ip_set_timeout_expired(ext_timeout(x, map)))) 184 + continue; 185 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 186 + if (!nested) { 187 + if (id == first) { 188 + nla_nest_cancel(skb, adt); 189 + return -EMSGSIZE; 190 + } else 191 + goto nla_put_failure; 192 + } 193 + if (mtype_do_list(skb, map, id)) 194 + goto nla_put_failure; 195 + if (SET_WITH_TIMEOUT(set)) { 196 + #ifdef IP_SET_BITMAP_STORED_TIMEOUT 197 + if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, 198 + htonl(ip_set_timeout_stored(map, id, 199 + ext_timeout(x, map))))) 200 + goto nla_put_failure; 201 + #else 202 + if (nla_put_net32(skb, IPSET_ATTR_TIMEOUT, 203 + htonl(ip_set_timeout_get( 204 + ext_timeout(x, map))))) 205 + goto nla_put_failure; 206 + #endif 207 + } 208 + ipset_nest_end(skb, nested); 209 + } 210 + ipset_nest_end(skb, adt); 211 + 212 + /* Set listing finished */ 213 + cb->args[2] = 0; 214 + 215 + return 0; 216 + 217 + nla_put_failure: 218 + nla_nest_cancel(skb, nested); 219 + ipset_nest_end(skb, adt); 220 + if (unlikely(id == first)) { 221 + cb->args[2] = 0; 222 + return -EMSGSIZE; 223 + } 224 + return 0; 225 + } 226 + 227 + static void 228 + mtype_gc(unsigned long ul_set) 229 + { 230 + struct ip_set *set = (struct ip_set *) ul_set; 231 + struct mtype *map = set->data; 232 + const void *x; 233 + u32 id; 234 + 235 + /* We run parallel with other readers (test element) 236 + * but adding/deleting new entries is locked out */ 237 + read_lock_bh(&set->lock); 238 + for (id = 0; id < map->elements; id++) 239 + if (mtype_gc_test(id, map)) { 240 + x = get_ext(map, id); 241 + if (ip_set_timeout_expired(ext_timeout(x, map))) 242 + clear_bit(id, map->members); 243 + } 244 + read_unlock_bh(&set->lock); 245 + 246 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 247 + add_timer(&map->gc); 248 + } 249 + 250 + static const struct ip_set_type_variant mtype = { 251 + .kadt = mtype_kadt, 252 + .uadt = mtype_uadt, 253 + .adt = { 254 + [IPSET_ADD] = mtype_add, 255 + [IPSET_DEL] = mtype_del, 256 + [IPSET_TEST] = mtype_test, 257 + }, 258 + .destroy = mtype_destroy, 259 + .flush = mtype_flush, 260 + .head = mtype_head, 261 + .list = mtype_list, 262 + .same_set = mtype_same_set, 263 + }; 264 + 265 + #endif /* __IP_SET_BITMAP_IP_GEN_H */