summaryrefslogtreecommitdiffstats
path: root/kernel/ip_set_ipportiphash.c
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2009-02-10 15:38:32 +0100
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2009-02-10 15:38:32 +0100
commit08b3df85d107b2ae58a7a264bcdb1480b29acf98 (patch)
tree9ba7dda8f66309203eceb6bf8910c821ba1d5315 /kernel/ip_set_ipportiphash.c
parentaa9317d60a4cf887fe0086742412169178073806 (diff)
Fix possible duplicates in hashesh.
Bug fixed: after elements are added and deleted from a hash, an element can successfully be added in spite it's already in the hash and thus duplicates can occur. Bug spotted by Shih-Yi Chen.
Diffstat (limited to 'kernel/ip_set_ipportiphash.c')
-rw-r--r--kernel/ip_set_ipportiphash.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/kernel/ip_set_ipportiphash.c b/kernel/ip_set_ipportiphash.c
index 2130508..e0725d9 100644
--- a/kernel/ip_set_ipportiphash.c
+++ b/kernel/ip_set_ipportiphash.c
@@ -51,8 +51,7 @@ ipportiphash_id(struct ip_set *set, ip_set_ip_t *hash_ip,
elem = HARRAY_ELEM(map->members, struct ipportip *, id);
if (elem->ip == *hash_ip && elem->ip1 == ip1)
return id;
- /* No shortcut at testing - there can be deleted
- * entries. */
+ /* No shortcut - there can be deleted entries. */
}
return UINT_MAX;
}
@@ -90,19 +89,22 @@ __ipportip_add(struct ip_set_ipportiphash *map,
{
__u32 probe;
u_int16_t i;
- struct ipportip *elem;
+ struct ipportip *elem, *slot = NULL;
for (i = 0; i < map->probes; i++) {
probe = jhash_ip2(map, i, hash_ip, ip1) % map->hashsize;
elem = HARRAY_ELEM(map->members, struct ipportip *, probe);
if (elem->ip == hash_ip && elem->ip1 == ip1)
return -EEXIST;
- if (!(elem->ip || elem->ip1)) {
- elem->ip = hash_ip;
- elem->ip1 = ip1;
- map->elements++;
- return 0;
- }
+ if (!(slot || elem->ip || elem->ip1))
+ slot = elem;
+ /* There can be deleted entries, must check all slots */
+ }
+ if (slot) {
+ slot->ip = hash_ip;
+ slot->ip1 = ip1;
+ map->elements++;
+ return 0;
}
/* Trigger rehashing */
return -EAGAIN;