aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/ipset/ip_set_list_set.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter/ipset/ip_set_list_set.c')
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c53
1 files changed, 23 insertions, 30 deletions
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index a47c32982f0..e9159e99fc4 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -43,14 +43,19 @@ struct list_set {
43static inline struct set_elem * 43static inline struct set_elem *
44list_set_elem(const struct list_set *map, u32 id) 44list_set_elem(const struct list_set *map, u32 id)
45{ 45{
46 return (struct set_elem *)((char *)map->members + id * map->dsize); 46 return (struct set_elem *)((void *)map->members + id * map->dsize);
47}
48
49static inline struct set_telem *
50list_set_telem(const struct list_set *map, u32 id)
51{
52 return (struct set_telem *)((void *)map->members + id * map->dsize);
47} 53}
48 54
49static inline bool 55static inline bool
50list_set_timeout(const struct list_set *map, u32 id) 56list_set_timeout(const struct list_set *map, u32 id)
51{ 57{
52 const struct set_telem *elem = 58 const struct set_telem *elem = list_set_telem(map, id);
53 (const struct set_telem *) list_set_elem(map, id);
54 59
55 return ip_set_timeout_test(elem->timeout); 60 return ip_set_timeout_test(elem->timeout);
56} 61}
@@ -58,19 +63,11 @@ list_set_timeout(const struct list_set *map, u32 id)
58static inline bool 63static inline bool
59list_set_expired(const struct list_set *map, u32 id) 64list_set_expired(const struct list_set *map, u32 id)
60{ 65{
61 const struct set_telem *elem = 66 const struct set_telem *elem = list_set_telem(map, id);
62 (const struct set_telem *) list_set_elem(map, id);
63 67
64 return ip_set_timeout_expired(elem->timeout); 68 return ip_set_timeout_expired(elem->timeout);
65} 69}
66 70
67static inline int
68list_set_exist(const struct set_telem *elem)
69{
70 return elem->id != IPSET_INVALID_ID &&
71 !ip_set_timeout_expired(elem->timeout);
72}
73
74/* Set list without and with timeout */ 71/* Set list without and with timeout */
75 72
76static int 73static int
@@ -146,11 +143,11 @@ list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
146 struct set_telem *e; 143 struct set_telem *e;
147 144
148 for (; i < map->size; i++) { 145 for (; i < map->size; i++) {
149 e = (struct set_telem *)list_set_elem(map, i); 146 e = list_set_telem(map, i);
150 swap(e->id, id); 147 swap(e->id, id);
148 swap(e->timeout, timeout);
151 if (e->id == IPSET_INVALID_ID) 149 if (e->id == IPSET_INVALID_ID)
152 break; 150 break;
153 swap(e->timeout, timeout);
154 } 151 }
155} 152}
156 153
@@ -164,7 +161,7 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
164 /* Last element replaced: e.g. add new,before,last */ 161 /* Last element replaced: e.g. add new,before,last */
165 ip_set_put_byindex(e->id); 162 ip_set_put_byindex(e->id);
166 if (with_timeout(map->timeout)) 163 if (with_timeout(map->timeout))
167 list_elem_tadd(map, i, id, timeout); 164 list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
168 else 165 else
169 list_elem_add(map, i, id); 166 list_elem_add(map, i, id);
170 167
@@ -172,11 +169,11 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
172} 169}
173 170
174static int 171static int
175list_set_del(struct list_set *map, ip_set_id_t id, u32 i) 172list_set_del(struct list_set *map, u32 i)
176{ 173{
177 struct set_elem *a = list_set_elem(map, i), *b; 174 struct set_elem *a = list_set_elem(map, i), *b;
178 175
179 ip_set_put_byindex(id); 176 ip_set_put_byindex(a->id);
180 177
181 for (; i < map->size - 1; i++) { 178 for (; i < map->size - 1; i++) {
182 b = list_set_elem(map, i + 1); 179 b = list_set_elem(map, i + 1);
@@ -308,11 +305,11 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
308 (before == 0 || 305 (before == 0 ||
309 (before > 0 && 306 (before > 0 &&
310 next_id_eq(map, i, refid)))) 307 next_id_eq(map, i, refid))))
311 ret = list_set_del(map, id, i); 308 ret = list_set_del(map, i);
312 else if (before < 0 && 309 else if (before < 0 &&
313 elem->id == refid && 310 elem->id == refid &&
314 next_id_eq(map, i, id)) 311 next_id_eq(map, i, id))
315 ret = list_set_del(map, id, i + 1); 312 ret = list_set_del(map, i + 1);
316 } 313 }
317 break; 314 break;
318 default: 315 default:
@@ -369,8 +366,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
369 NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); 366 NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
370 if (with_timeout(map->timeout)) 367 if (with_timeout(map->timeout))
371 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); 368 NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
372 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, 369 NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
373 htonl(atomic_read(&set->ref) - 1));
374 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, 370 NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
375 htonl(sizeof(*map) + map->size * map->dsize)); 371 htonl(sizeof(*map) + map->size * map->dsize));
376 ipset_nest_end(skb, nested); 372 ipset_nest_end(skb, nested);
@@ -461,16 +457,13 @@ list_set_gc(unsigned long ul_set)
461 struct set_telem *e; 457 struct set_telem *e;
462 u32 i; 458 u32 i;
463 459
464 /* We run parallel with other readers (test element) 460 write_lock_bh(&set->lock);
465 * but adding/deleting new entries is locked out */ 461 for (i = 0; i < map->size; i++) {
466 read_lock_bh(&set->lock); 462 e = list_set_telem(map, i);
467 for (i = map->size - 1; i >= 0; i--) { 463 if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
468 e = (struct set_telem *) list_set_elem(map, i); 464 list_set_del(map, i);
469 if (e->id != IPSET_INVALID_ID &&
470 list_set_expired(map, i))
471 list_set_del(map, e->id, i);
472 } 465 }
473 read_unlock_bh(&set->lock); 466 write_unlock_bh(&set->lock);
474 467
475 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 468 map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
476 add_timer(&map->gc); 469 add_timer(&map->gc);