diff --git a/src/libcharon/attributes/mem_pool.c b/src/libcharon/attributes/mem_pool.c index b2382c46d2..95e400353c 100644 --- a/src/libcharon/attributes/mem_pool.c +++ b/src/libcharon/attributes/mem_pool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Tobias Brunner + * Copyright (C) 2010-2024 Tobias Brunner * Copyright (C) 2008-2010 Martin Willi * * Copyright (C) secunet Security Networks AG @@ -46,11 +46,6 @@ struct private_mem_pool_t { */ host_t *base; - /** - * whether base is the network id of the subnet on which the pool is based - */ - bool base_is_network_id; - /** * size of the pool */ @@ -137,22 +132,16 @@ static bool id_equals(identification_t *a, identification_t *b) } /** - * convert a pool offset to an address + * apply the given offset to a base address */ -static host_t* offset2host(private_mem_pool_t *pool, int offset) +static host_t *apply_offset(host_t *base, int offset) { chunk_t addr; host_t *host; uint32_t *pos; - offset--; - if (offset > pool->size) - { - return NULL; - } - - addr = chunk_clone(pool->base->get_address(pool->base)); - if (pool->base->get_family(pool->base) == AF_INET6) + addr = chunk_clone(base->get_address(base)); + if (base->get_family(base) == AF_INET6) { pos = (uint32_t*)(addr.ptr + 12); } @@ -161,11 +150,24 @@ static host_t* offset2host(private_mem_pool_t *pool, int offset) pos = (uint32_t*)addr.ptr; } *pos = htonl(offset + ntohl(*pos)); - host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0); + host = host_create_from_chunk(base->get_family(base), addr, 0); free(addr.ptr); return host; } +/** + * convert a pool offset to an address + */ +static host_t* offset2host(private_mem_pool_t *pool, int offset) +{ + offset--; + if (offset > pool->size) + { + return NULL; + } + return apply_offset(pool->base, offset); +} + /** * convert a host to a pool offset */ @@ -342,8 +344,7 @@ static int get_new(private_mem_pool_t *this, identification_t *id, host_t *peer) entry = entry_create(id); this->leases->put(this->leases, entry->id, entry); } - /* assigning offset, starting by 1 */ - lease.offset = ++this->unused + (this->base_is_network_id ? 1 : 0); + lease.offset = ++this->unused; lease.hash = hash_addr(peer); array_insert(entry->online, ARRAY_TAIL, &lease); DBG1(DBG_CFG, "assigning new lease to '%Y'", id); @@ -682,13 +683,14 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) if (this->size > 2) { - /* if base is the network id we later skip the first address, + /* if base is the network id we skip the first address, * otherwise adjust the size to represent the actual number * of assignable addresses */ diff = network_id_diff(base, bits); if (!diff) { - this->base_is_network_id = TRUE; + this->base->destroy(this->base); + this->base = apply_offset(base, 1); this->size--; } else diff --git a/src/libcharon/tests/suites/test_mem_pool.c b/src/libcharon/tests/suites/test_mem_pool.c index 8d87b6ad46..ae10e3a36c 100644 --- a/src/libcharon/tests/suites/test_mem_pool.c +++ b/src/libcharon/tests/suites/test_mem_pool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Tobias Brunner + * Copyright (C) 2014-2024 Tobias Brunner * * Copyright (C) secunet Security Networks AG * @@ -35,6 +35,17 @@ static void assert_host(char *expected, host_t *host) } } +static void assert_base(mem_pool_t *pool, char *expected) +{ + host_t *verifier, *base; + + verifier = host_create_from_string(expected, 0); + base = pool->get_base(pool); + ck_assert_msg(verifier->ip_equals(verifier, base), "expected base %+H != " + "%+H", verifier, base); + verifier->destroy(verifier); +} + static void assert_acquire(mem_pool_t *pool, char *requested, char *expected, mem_pool_op_t operation) { @@ -90,26 +101,31 @@ START_TEST(test_cidr) pool = mem_pool_create("test", base, 32); ck_assert_int_eq(1, pool->get_size(pool)); + assert_base(pool, "192.168.0.0"); assert_acquires_new(pool, "192.168.0.%d", 0); pool->destroy(pool); pool = mem_pool_create("test", base, 31); ck_assert_int_eq(2, pool->get_size(pool)); + assert_base(pool, "192.168.0.0"); assert_acquires_new(pool, "192.168.0.%d", 0); pool->destroy(pool); pool = mem_pool_create("test", base, 30); ck_assert_int_eq(2, pool->get_size(pool)); + assert_base(pool, "192.168.0.1"); assert_acquires_new(pool, "192.168.0.%d", 1); pool->destroy(pool); pool = mem_pool_create("test", base, 29); ck_assert_int_eq(6, pool->get_size(pool)); + assert_base(pool, "192.168.0.1"); assert_acquires_new(pool, "192.168.0.%d", 1); pool->destroy(pool); pool = mem_pool_create("test", base, 24); ck_assert_int_eq(254, pool->get_size(pool)); + assert_base(pool, "192.168.0.1"); assert_acquires_new(pool, "192.168.0.%d", 1); pool->destroy(pool); @@ -125,11 +141,19 @@ START_TEST(test_cidr_offset) base = host_create_from_string("192.168.0.1", 0); pool = mem_pool_create("test", base, 31); ck_assert_int_eq(1, pool->get_size(pool)); + assert_base(pool, "192.168.0.1"); assert_acquires_new(pool, "192.168.0.%d", 1); pool->destroy(pool); pool = mem_pool_create("test", base, 30); ck_assert_int_eq(2, pool->get_size(pool)); + assert_base(pool, "192.168.0.1"); + assert_acquires_new(pool, "192.168.0.%d", 1); + pool->destroy(pool); + + pool = mem_pool_create("test", base, 24); + ck_assert_int_eq(254, pool->get_size(pool)); + assert_base(pool, "192.168.0.1"); assert_acquires_new(pool, "192.168.0.%d", 1); pool->destroy(pool); base->destroy(base); @@ -137,11 +161,13 @@ START_TEST(test_cidr_offset) base = host_create_from_string("192.168.0.2", 0); pool = mem_pool_create("test", base, 30); ck_assert_int_eq(1, pool->get_size(pool)); + assert_base(pool, "192.168.0.2"); assert_acquires_new(pool, "192.168.0.%d", 2); pool->destroy(pool); pool = mem_pool_create("test", base, 24); ck_assert_int_eq(253, pool->get_size(pool)); + assert_base(pool, "192.168.0.2"); assert_acquires_new(pool, "192.168.0.%d", 2); pool->destroy(pool); base->destroy(base); @@ -149,6 +175,7 @@ START_TEST(test_cidr_offset) base = host_create_from_string("192.168.0.254", 0); pool = mem_pool_create("test", base, 24); ck_assert_int_eq(1, pool->get_size(pool)); + assert_base(pool, "192.168.0.254"); assert_acquires_new(pool, "192.168.0.%d", 254); pool->destroy(pool); base->destroy(base); @@ -170,6 +197,7 @@ START_TEST(test_range) to = host_create_from_string("192.168.0.0", 0); pool = mem_pool_create_range("test", from, to); ck_assert_int_eq(1, pool->get_size(pool)); + assert_base(pool, "192.168.0.0"); assert_acquires_new(pool, "192.168.0.%d", 0); pool->destroy(pool); @@ -177,6 +205,7 @@ START_TEST(test_range) to = host_create_from_string("192.168.0.1", 0); pool = mem_pool_create_range("test", from, to); ck_assert_int_eq(2, pool->get_size(pool)); + assert_base(pool, "192.168.0.0"); assert_acquires_new(pool, "192.168.0.%d", 0); pool->destroy(pool); @@ -189,6 +218,7 @@ START_TEST(test_range) to = host_create_from_string("192.168.0.20", 0); pool = mem_pool_create_range("test", from, to); ck_assert_int_eq(11, pool->get_size(pool)); + assert_base(pool, "192.168.0.10"); assert_acquires_new(pool, "192.168.0.%d", 10); pool->destroy(pool);