mem-pool: Adjust the base address if it's the network ID

Instead of just adding the offset internally, this way the reported
base address is always the first assignable address (e.g. for
192.168.0.0/24 vs. 192.168.0.1/24).

Closes strongswan/strongswan#2264
This commit is contained in:
Tobias Brunner 2024-05-28 09:41:29 +02:00
parent 1cbcf198ab
commit 2b11764b70
2 changed files with 54 additions and 22 deletions

View File

@ -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

View File

@ -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);