1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* Copyright (C) 2013 Jozsef Kadlecsik <kadlec@netfilter.org> */ 3 4 #ifndef __IP_SET_BITMAP_IP_GEN_H 5 #define __IP_SET_BITMAP_IP_GEN_H 6 7 #include <linux/rcupdate_wait.h> 8 9 #define mtype_do_test IPSET_TOKEN(MTYPE, _do_test) 10 #define mtype_gc_test IPSET_TOKEN(MTYPE, _gc_test) 11 #define mtype_is_filled IPSET_TOKEN(MTYPE, _is_filled) 12 #define mtype_do_add IPSET_TOKEN(MTYPE, _do_add) 13 #define mtype_ext_cleanup IPSET_TOKEN(MTYPE, _ext_cleanup) 14 #define mtype_do_del IPSET_TOKEN(MTYPE, _do_del) 15 #define mtype_do_list IPSET_TOKEN(MTYPE, _do_list) 16 #define mtype_do_head IPSET_TOKEN(MTYPE, _do_head) 17 #define mtype_adt_elem IPSET_TOKEN(MTYPE, _adt_elem) 18 #define mtype_add_timeout IPSET_TOKEN(MTYPE, _add_timeout) 19 #define mtype_gc_init IPSET_TOKEN(MTYPE, _gc_init) 20 #define mtype_kadt IPSET_TOKEN(MTYPE, _kadt) 21 #define mtype_uadt IPSET_TOKEN(MTYPE, _uadt) 22 #define mtype_destroy IPSET_TOKEN(MTYPE, _destroy) 23 #define mtype_memsize IPSET_TOKEN(MTYPE, _memsize) 24 #define mtype_flush IPSET_TOKEN(MTYPE, _flush) 25 #define mtype_head IPSET_TOKEN(MTYPE, _head) 26 #define mtype_same_set IPSET_TOKEN(MTYPE, _same_set) 27 #define mtype_elem IPSET_TOKEN(MTYPE, _elem) 28 #define mtype_test IPSET_TOKEN(MTYPE, _test) 29 #define mtype_add IPSET_TOKEN(MTYPE, _add) 30 #define mtype_del IPSET_TOKEN(MTYPE, _del) 31 #define mtype_list IPSET_TOKEN(MTYPE, _list) 32 #define mtype_gc IPSET_TOKEN(MTYPE, _gc) 33 #define mtype_cancel_gc IPSET_TOKEN(MTYPE, _cancel_gc) 34 #define mtype MTYPE 35 36 #define get_ext(set, map, id) ((map)->extensions + ((set)->dsize * (id))) 37 38 static void 39 mtype_gc_init(struct ip_set *set, void (*gc)(struct timer_list *t)) 40 { 41 struct mtype *map = set->data; 42 43 timer_setup(&map->gc, gc, 0); 44 mod_timer(&map->gc, jiffies + IPSET_GC_PERIOD(set->timeout) * HZ); 45 } 46 47 static void 48 mtype_ext_cleanup(struct ip_set *set) 49 { 50 struct mtype *map = set->data; 51 u32 id; 52 53 for (id = 0; id < map->elements; id++) 54 if (test_bit(id, map->members)) 55 ip_set_ext_destroy(set, get_ext(set, map, id)); 56 } 57 58 static void 59 mtype_destroy(struct ip_set *set) 60 { 61 struct mtype *map = set->data; 62 63 if (set->dsize && set->extensions & IPSET_EXT_DESTROY) 64 mtype_ext_cleanup(set); 65 ip_set_free(map->members); 66 ip_set_free(map); 67 68 set->data = NULL; 69 } 70 71 static void 72 mtype_flush(struct ip_set *set) 73 { 74 struct mtype *map = set->data; 75 76 if (set->extensions & IPSET_EXT_DESTROY) 77 mtype_ext_cleanup(set); 78 bitmap_zero(map->members, map->elements); 79 set->elements = 0; 80 DEBUG_NET_WARN_ON_ONCE(atomic64_read(&set->ext_size) > 0); 81 } 82 83 /* Calculate the actual memory size of the set data */ 84 static size_t 85 mtype_memsize(const struct mtype *map, size_t dsize) 86 { 87 return sizeof(*map) + map->memsize + 88 map->elements * dsize; 89 } 90 91 static int 92 mtype_head(struct ip_set *set, struct sk_buff *skb) 93 { 94 const struct mtype *map = set->data; 95 struct nlattr *nested; 96 size_t memsize = mtype_memsize(map, set->dsize) + atomic64_read(&set->ext_size); 97 98 nested = nla_nest_start(skb, IPSET_ATTR_DATA); 99 if (!nested) 100 goto nla_put_failure; 101 if (mtype_do_head(skb, map) || 102 nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref)) || 103 nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)) || 104 nla_put_net32(skb, IPSET_ATTR_ELEMENTS, htonl(set->elements))) 105 goto nla_put_failure; 106 if (unlikely(ip_set_put_flags(skb, set))) 107 goto nla_put_failure; 108 nla_nest_end(skb, nested); 109 110 return 0; 111 nla_put_failure: 112 return -EMSGSIZE; 113 } 114 115 static int 116 mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext, 117 struct ip_set_ext *mext, u32 flags) 118 { 119 struct mtype *map = set->data; 120 const struct mtype_adt_elem *e = value; 121 void *x = get_ext(set, map, e->id); 122 int ret = mtype_do_test(e, map, set->dsize); 123 124 if (ret <= 0) 125 return ret; 126 return ip_set_match_extensions(set, ext, mext, flags, x); 127 } 128 129 static int 130 mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, 131 struct ip_set_ext *mext, u32 flags) 132 { 133 struct mtype *map = set->data; 134 const struct mtype_adt_elem *e = value; 135 void *x = get_ext(set, map, e->id); 136 int ret = mtype_do_add(e, map, flags, set->dsize); 137 138 if (ret == IPSET_ADD_FAILED) { 139 if (SET_WITH_TIMEOUT(set) && 140 ip_set_timeout_expired(ext_timeout(x, set))) { 141 set->elements--; 142 ret = 0; 143 } else if (!(flags & IPSET_FLAG_EXIST)) { 144 set_bit(e->id, map->members); 145 return -IPSET_ERR_EXIST; 146 } 147 /* Element is re-added, cleanup extensions */ 148 ip_set_ext_destroy(set, x); 149 } 150 if (ret > 0) 151 set->elements--; 152 153 if (SET_WITH_TIMEOUT(set)) 154 #ifdef IP_SET_BITMAP_STORED_TIMEOUT 155 mtype_add_timeout(ext_timeout(x, set), e, ext, set, map, ret); 156 #else 157 ip_set_timeout_set(ext_timeout(x, set), ext->timeout); 158 #endif 159 160 if (SET_WITH_COUNTER(set)) 161 ip_set_init_counter(ext_counter(x, set), ext); 162 if (SET_WITH_COMMENT(set) && !ext->target) 163 ip_set_init_comment(set, ext_comment(x, set), ext); 164 if (SET_WITH_SKBINFO(set)) 165 ip_set_init_skbinfo(ext_skbinfo(x, set), ext); 166 167 /* Activate element */ 168 smp_mb__before_atomic(); 169 set_bit(e->id, map->members); 170 set->elements++; 171 172 return 0; 173 } 174 175 static int 176 mtype_del(struct ip_set *set, void *value, const struct ip_set_ext *ext, 177 struct ip_set_ext *mext, u32 flags) 178 { 179 struct mtype *map = set->data; 180 const struct mtype_adt_elem *e = value; 181 void *x = get_ext(set, map, e->id); 182 183 if (mtype_do_del(e, map)) 184 return -IPSET_ERR_EXIST; 185 186 ip_set_ext_destroy(set, x); 187 set->elements--; 188 if (SET_WITH_TIMEOUT(set) && 189 ip_set_timeout_expired(ext_timeout(x, set))) 190 return -IPSET_ERR_EXIST; 191 192 return 0; 193 } 194 195 #ifndef IP_SET_BITMAP_STORED_TIMEOUT 196 static bool 197 mtype_is_filled(const struct mtype_elem *x) 198 { 199 return true; 200 } 201 #endif 202 203 static int 204 mtype_list(const struct ip_set *set, 205 struct sk_buff *skb, struct netlink_callback *cb) 206 { 207 struct mtype *map = set->data; 208 struct nlattr *adt, *nested; 209 void *x; 210 u32 id, first = cb->args[IPSET_CB_ARG0]; 211 int ret = 0; 212 213 adt = nla_nest_start(skb, IPSET_ATTR_ADT); 214 if (!adt) 215 return -EMSGSIZE; 216 /* Extensions may be replaced */ 217 rcu_read_lock(); 218 for (; cb->args[IPSET_CB_ARG0] < map->elements; 219 cb->args[IPSET_CB_ARG0]++) { 220 cond_resched_rcu(); 221 id = cb->args[IPSET_CB_ARG0]; 222 x = get_ext(set, map, id); 223 if (!test_bit_acquire(id, map->members) || 224 (SET_WITH_TIMEOUT(set) && 225 #ifdef IP_SET_BITMAP_STORED_TIMEOUT 226 mtype_is_filled(x) && 227 #endif 228 ip_set_timeout_expired(ext_timeout(x, set)))) 229 continue; 230 nested = nla_nest_start(skb, IPSET_ATTR_DATA); 231 if (!nested) { 232 if (id == first) { 233 nla_nest_cancel(skb, adt); 234 ret = -EMSGSIZE; 235 goto out; 236 } 237 238 goto nla_put_failure; 239 } 240 if (mtype_do_list(skb, map, id, set->dsize)) 241 goto nla_put_failure; 242 if (ip_set_put_extensions(skb, set, x, mtype_is_filled(x))) 243 goto nla_put_failure; 244 nla_nest_end(skb, nested); 245 } 246 nla_nest_end(skb, adt); 247 248 /* Set listing finished */ 249 cb->args[IPSET_CB_ARG0] = 0; 250 251 goto out; 252 253 nla_put_failure: 254 nla_nest_cancel(skb, nested); 255 if (unlikely(id == first)) { 256 cb->args[IPSET_CB_ARG0] = 0; 257 ret = -EMSGSIZE; 258 } 259 nla_nest_end(skb, adt); 260 out: 261 rcu_read_unlock(); 262 return ret; 263 } 264 265 static void 266 mtype_gc(struct timer_list *t) 267 { 268 struct mtype *map = timer_container_of(map, t, gc); 269 struct ip_set *set = map->set; 270 void *x; 271 u32 id; 272 273 /* We run parallel with other readers (test element) 274 * but adding/deleting new entries is locked out 275 */ 276 spin_lock_bh(&set->lock); 277 for (id = 0; id < map->elements; id++) 278 if (mtype_gc_test(id, map, set->dsize)) { 279 x = get_ext(set, map, id); 280 if (ip_set_timeout_expired(ext_timeout(x, set))) { 281 clear_bit(id, map->members); 282 smp_mb__after_atomic(); 283 ip_set_ext_destroy(set, x); 284 set->elements--; 285 } 286 } 287 spin_unlock_bh(&set->lock); 288 289 map->gc.expires = jiffies + IPSET_GC_PERIOD(set->timeout) * HZ; 290 add_timer(&map->gc); 291 } 292 293 static void 294 mtype_cancel_gc(struct ip_set *set) 295 { 296 struct mtype *map = set->data; 297 298 if (SET_WITH_TIMEOUT(set)) 299 timer_delete_sync(&map->gc); 300 } 301 302 static const struct ip_set_type_variant mtype = { 303 .kadt = mtype_kadt, 304 .uadt = mtype_uadt, 305 .adt = { 306 [IPSET_ADD] = mtype_add, 307 [IPSET_DEL] = mtype_del, 308 [IPSET_TEST] = mtype_test, 309 }, 310 .destroy = mtype_destroy, 311 .flush = mtype_flush, 312 .head = mtype_head, 313 .list = mtype_list, 314 .same_set = mtype_same_set, 315 .cancel_gc = mtype_cancel_gc, 316 }; 317 318 #endif /* __IP_SET_BITMAP_IP_GEN_H */ 319