Merge branch 'mem-pool-range'
Adds support to configure address pools as ranges (from-to) in ipsec.conf and swanctl.conf. The first and last addresses in subnet based pools are now skipped properly and the pools' sizes are adjusted accordingly. Which is also the case if pools are configured with an offset, e.g. 192.168.0.100/24, which reduces the number of available addresses from 254 to 155, and assignment now starts at .100 not .101, i.e. .100-.254 are assignable to clients. References #744.
This commit is contained in:
commit
406f3af1ed
16 files changed
+590
-42
No files matched your search
@@ -1650,6 +1650,7 @@ AC_CONFIG_FILES([
|
||||
src/libhydra/plugins/kernel_pfkey/Makefile
|
||||
src/libhydra/plugins/kernel_pfroute/Makefile
|
||||
src/libhydra/plugins/resolve/Makefile
|
||||
src/libhydra/tests/Makefile
|
||||
src/libipsec/Makefile
|
||||
src/libsimaka/Makefile
|
||||
src/libtls/Makefile
|
||||
|
||||
+3
-1
@@ -853,13 +853,15 @@ an address of the given address family will be requested explicitly.
|
||||
If an IP address is configured, it will be requested from the responder,
|
||||
which is free to respond with a different address.
|
||||
.TP
|
||||
.BR rightsourceip " = %config | <network>/<netmask> | %poolname"
|
||||
.BR rightsourceip " = %config | <network>/<netmask> | <from>-<to> | %poolname"
|
||||
Comma separated list of internal source IPs to use in a tunnel for the remote
|
||||
peer. If the value is
|
||||
.B %config
|
||||
on the responder side, the initiator must propose an address which is then
|
||||
echoed back. Also supported are address pools expressed as
|
||||
\fInetwork\fB/\fInetmask\fR
|
||||
and
|
||||
\fIfrom\fB-\fIto\fR
|
||||
or the use of an external IP address pool using %\fIpoolname\fR,
|
||||
where \fIpoolname\fR is the name of the IP address pool used for the lookup.
|
||||
.TP
|
||||
|
||||
@@ -459,27 +459,12 @@ static traffic_selector_t* make_range(char *str)
|
||||
{
|
||||
traffic_selector_t *ts;
|
||||
ts_type_t type;
|
||||
char *pos;
|
||||
host_t *from, *to;
|
||||
|
||||
pos = strchr(str, '-');
|
||||
if (!pos)
|
||||
if (!host_create_from_range(str, &from, &to))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
to = host_create_from_string(pos + 1, 0);
|
||||
if (!to)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
str = strndup(str, pos - str);
|
||||
from = host_create_from_string_and_family(str, to->get_family(to), 0);
|
||||
free(str);
|
||||
if (!from)
|
||||
{
|
||||
to->destroy(to);
|
||||
return NULL;
|
||||
}
|
||||
if (to->get_family(to) == AF_INET)
|
||||
{
|
||||
type = TS_IPV4_ADDR_RANGE;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Tobias Brunner
|
||||
* Copyright (C) 2012-2014 Tobias Brunner
|
||||
* Copyright (C) 2008 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
@@ -666,6 +666,24 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this,
|
||||
return cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* build a mem_pool_t from an address range
|
||||
*/
|
||||
static mem_pool_t *create_pool_range(char *str)
|
||||
{
|
||||
mem_pool_t *pool;
|
||||
host_t *from, *to;
|
||||
|
||||
if (!host_create_from_range(str, &from, &to))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pool = mem_pool_create_range(str, from, to);
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* build a peer_cfg from a stroke msg
|
||||
*/
|
||||
@@ -789,17 +807,25 @@ static peer_cfg_t *build_peer_cfg(private_stroke_config_t *this,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* in-memory pool, named using CIDR notation */
|
||||
/* in-memory pool, using range or CIDR notation */
|
||||
mem_pool_t *pool;
|
||||
host_t *base;
|
||||
int bits;
|
||||
|
||||
base = host_create_from_subnet(token, &bits);
|
||||
if (base)
|
||||
pool = create_pool_range(token);
|
||||
if (!pool)
|
||||
{
|
||||
this->attributes->add_pool(this->attributes,
|
||||
mem_pool_create(token, base, bits));
|
||||
base = host_create_from_subnet(token, &bits);
|
||||
if (base)
|
||||
{
|
||||
pool = mem_pool_create(token, base, bits);
|
||||
base->destroy(base);
|
||||
}
|
||||
}
|
||||
if (pool)
|
||||
{
|
||||
this->attributes->add_pool(this->attributes, pool);
|
||||
peer_cfg->add_pool(peer_cfg, token);
|
||||
base->destroy(base);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* Copyright (C) 2014 Martin Willi
|
||||
* Copyright (C) 2014 revosec AG
|
||||
*
|
||||
@@ -354,6 +357,24 @@ static vici_message_t* create_reply(char *fmt, ...)
|
||||
return builder->finalize(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a range definition of an address pool
|
||||
*/
|
||||
static mem_pool_t *create_pool_range(char *name, char *buf)
|
||||
{
|
||||
mem_pool_t *pool;
|
||||
host_t *from, *to;
|
||||
|
||||
if (!host_create_from_range(buf, &from, &to))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
pool = mem_pool_create_range(name, from, to);
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse callback data, passed to each callback
|
||||
*/
|
||||
@@ -490,7 +511,8 @@ CALLBACK(pool_kv, bool,
|
||||
if (streq(name, "addrs"))
|
||||
{
|
||||
char buf[128];
|
||||
host_t *base;
|
||||
mem_pool_t *pool;
|
||||
host_t *base = NULL;
|
||||
int bits;
|
||||
|
||||
if (data->pool->vips)
|
||||
@@ -503,14 +525,22 @@ CALLBACK(pool_kv, bool,
|
||||
data->request->reply = create_reply("invalid addrs value");
|
||||
return FALSE;
|
||||
}
|
||||
base = host_create_from_subnet(buf, &bits);
|
||||
if (!base)
|
||||
pool = create_pool_range(data->name, buf);
|
||||
if (!pool)
|
||||
{
|
||||
base = host_create_from_subnet(buf, &bits);
|
||||
if (base)
|
||||
{
|
||||
pool = mem_pool_create(data->name, base, bits);
|
||||
base->destroy(base);
|
||||
}
|
||||
}
|
||||
if (!pool)
|
||||
{
|
||||
data->request->reply = create_reply("invalid addrs value: %s", buf);
|
||||
return FALSE;
|
||||
}
|
||||
data->pool->vips = mem_pool_create(data->name, base, bits);
|
||||
base->destroy(base);
|
||||
data->pool->vips = pool;
|
||||
return TRUE;
|
||||
}
|
||||
data->request->reply = create_reply("invalid attribute: %s", name);
|
||||
|
||||
@@ -78,3 +78,8 @@ if MONOLITHIC
|
||||
libhydra_la_LIBADD += plugins/resolve/libstrongswan-resolve.la
|
||||
endif
|
||||
endif
|
||||
|
||||
if MONOLITHIC
|
||||
SUBDIRS += .
|
||||
endif
|
||||
SUBDIRS += tests
|
||||
@@ -46,6 +46,11 @@ 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
|
||||
*/
|
||||
@@ -306,7 +311,7 @@ static int get_new(private_mem_pool_t *this, identification_t *id)
|
||||
this->leases->put(this->leases, entry->id, entry);
|
||||
}
|
||||
/* assigning offset, starting by 1 */
|
||||
offset = ++this->unused;
|
||||
offset = ++this->unused + (this->base_is_network_id ? 1 : 0);
|
||||
array_insert(entry->online, ARRAY_TAIL, &offset);
|
||||
DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
|
||||
}
|
||||
@@ -579,19 +584,40 @@ static private_mem_pool_t *create_generic(char *name)
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given host is the network ID of a subnet, that is, if hostbits
|
||||
* are zero. Since we limit pools to 2^31 addresses we only have to check the
|
||||
* last 4 bytes.
|
||||
*/
|
||||
static u_int network_id_diff(host_t *host, int hostbits)
|
||||
{
|
||||
u_int32_t last;
|
||||
chunk_t addr;
|
||||
|
||||
if (!hostbits)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
addr = host->get_address(host);
|
||||
last = untoh32(addr.ptr + addr.len - sizeof(last));
|
||||
hostbits = sizeof(last) * 8 - hostbits;
|
||||
return (last << hostbits) >> hostbits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header
|
||||
*/
|
||||
mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
|
||||
{
|
||||
private_mem_pool_t *this;
|
||||
u_int diff;
|
||||
int addr_bits;
|
||||
|
||||
this = create_generic(name);
|
||||
if (base)
|
||||
{
|
||||
addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
|
||||
bits = max(0, min(bits, base->get_family(base) == AF_INET ? 32 : 128));
|
||||
bits = max(0, min(bits, addr_bits));
|
||||
/* net bits -> host bits */
|
||||
bits = addr_bits - bits;
|
||||
if (bits > POOL_LIMIT)
|
||||
@@ -601,15 +627,31 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
|
||||
base, addr_bits - bits);
|
||||
}
|
||||
this->size = 1 << bits;
|
||||
this->base = base->clone(base);
|
||||
|
||||
if (this->size > 2)
|
||||
{ /* do not use first and last addresses of a block */
|
||||
this->unused++;
|
||||
this->size -= 2;
|
||||
{
|
||||
/* if base is the network id we later 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->size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->size -= diff;
|
||||
}
|
||||
/* skip the last address (broadcast) of the subnet */
|
||||
this->size--;
|
||||
}
|
||||
else if (network_id_diff(base, bits))
|
||||
{ /* only serve the second address of the subnet */
|
||||
this->size--;
|
||||
}
|
||||
this->base = base->clone(base);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hydra_tests
|
||||
@@ -0,0 +1,19 @@
|
||||
TESTS = hydra_tests
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
hydra_tests_SOURCES = \
|
||||
suites/test_mem_pool.c \
|
||||
hydra_tests.h hydra_tests.c
|
||||
|
||||
hydra_tests_CFLAGS = \
|
||||
-I$(top_srcdir)/src/libhydra \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libstrongswan/tests \
|
||||
@COVERAGE_CFLAGS@
|
||||
|
||||
hydra_tests_LDFLAGS = @COVERAGE_LDFLAGS@
|
||||
hydra_tests_LDADD = \
|
||||
$(top_builddir)/src/libhydra/libhydra.la \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la \
|
||||
$(top_builddir)/src/libstrongswan/tests/libtest.la
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include <test_runner.h>
|
||||
#include <hydra.h>
|
||||
|
||||
/* declare test suite constructors */
|
||||
#define TEST_SUITE(x) test_suite_t* x();
|
||||
#define TEST_SUITE_DEPEND(x, ...) TEST_SUITE(x)
|
||||
#include "hydra_tests.h"
|
||||
#undef TEST_SUITE
|
||||
#undef TEST_SUITE_DEPEND
|
||||
|
||||
static test_configuration_t tests[] = {
|
||||
#define TEST_SUITE(x) \
|
||||
{ .suite = x, },
|
||||
#define TEST_SUITE_DEPEND(x, type, args) \
|
||||
{ .suite = x, .feature = PLUGIN_DEPENDS(type, args) },
|
||||
#include "hydra_tests.h"
|
||||
{ .suite = NULL, }
|
||||
};
|
||||
|
||||
static bool test_runner_init(bool init)
|
||||
{
|
||||
if (init)
|
||||
{
|
||||
libhydra_init();
|
||||
}
|
||||
else
|
||||
{
|
||||
lib->processor->set_threads(lib->processor, 0);
|
||||
lib->processor->cancel(lib->processor);
|
||||
libhydra_deinit();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return test_runner_run("libhydra", tests, test_runner_init);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
TEST_SUITE(mem_pool_suite_create)
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Tobias Brunner
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "test_suite.h"
|
||||
|
||||
#include <attributes/mem_pool.h>
|
||||
|
||||
static void assert_host(char *expected, host_t *host)
|
||||
{
|
||||
if (!expected)
|
||||
{
|
||||
ck_assert_msg(!host, "not epxecting IP != %+H", host);
|
||||
}
|
||||
else
|
||||
{
|
||||
host_t *verifier;
|
||||
verifier = host_create_from_string(expected, 0);
|
||||
ck_assert_msg(host, "expected IP %+H != NULL", verifier);
|
||||
ck_assert_msg(verifier->ip_equals(verifier, host), "expected IP %+H != "
|
||||
"%+H", verifier, host);;
|
||||
verifier->destroy(verifier);
|
||||
}
|
||||
}
|
||||
|
||||
static void assert_acquire(mem_pool_t *pool, char *requested, char *expected,
|
||||
mem_pool_op_t operation)
|
||||
{
|
||||
identification_t *id;
|
||||
host_t *req, *acquired;
|
||||
|
||||
id = identification_create_from_string("tester");
|
||||
req = host_create_from_string(requested, 0);
|
||||
|
||||
acquired = pool->acquire_address(pool, id, req, operation);
|
||||
assert_host(expected, acquired);
|
||||
DESTROY_IF(acquired);
|
||||
|
||||
req->destroy(req);
|
||||
id->destroy(id);
|
||||
}
|
||||
|
||||
static void assert_acquires_new(mem_pool_t *pool, char *pattern, int first)
|
||||
{
|
||||
char expected[16];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pool->get_size(pool); i++)
|
||||
{
|
||||
snprintf(expected, sizeof(expected), pattern, first + i);
|
||||
assert_acquire(pool, "0.0.0.0", expected, MEM_POOL_NEW);
|
||||
ck_assert_int_eq(i + 1, pool->get_online(pool));
|
||||
}
|
||||
assert_acquire(pool, "0.0.0.0", NULL, MEM_POOL_NEW);
|
||||
}
|
||||
|
||||
START_TEST(test_config)
|
||||
{
|
||||
mem_pool_t *pool;
|
||||
|
||||
pool = mem_pool_create("test", NULL, 0);
|
||||
ck_assert_int_eq(0, pool->get_size(pool));
|
||||
assert_acquire(pool, "192.168.0.1", "192.168.0.1", MEM_POOL_NEW);
|
||||
assert_acquire(pool, "10.0.1.1", "10.0.1.1", MEM_POOL_NEW);
|
||||
assert_acquire(pool, "0.0.0.0", "0.0.0.0", MEM_POOL_NEW);
|
||||
assert_acquire(pool, "255.255.255.255", "255.255.255.255", MEM_POOL_NEW);
|
||||
ck_assert_int_eq(0, pool->get_online(pool));
|
||||
pool->destroy(pool);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_cidr)
|
||||
{
|
||||
mem_pool_t *pool;
|
||||
host_t *base;
|
||||
|
||||
base = host_create_from_string("192.168.0.0", 0);
|
||||
|
||||
pool = mem_pool_create("test", base, 32);
|
||||
ck_assert_int_eq(1, pool->get_size(pool));
|
||||
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_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_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_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_acquires_new(pool, "192.168.0.%d", 1);
|
||||
pool->destroy(pool);
|
||||
|
||||
base->destroy(base);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_cidr_offset)
|
||||
{
|
||||
mem_pool_t *pool;
|
||||
host_t *base;
|
||||
|
||||
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_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_acquires_new(pool, "192.168.0.%d", 1);
|
||||
pool->destroy(pool);
|
||||
base->destroy(base);
|
||||
|
||||
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_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_acquires_new(pool, "192.168.0.%d", 2);
|
||||
pool->destroy(pool);
|
||||
base->destroy(base);
|
||||
|
||||
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_acquires_new(pool, "192.168.0.%d", 254);
|
||||
pool->destroy(pool);
|
||||
base->destroy(base);
|
||||
|
||||
/* due to size == 0 we get the requested IP back */
|
||||
base = host_create_from_string("192.168.0.255", 0);
|
||||
pool = mem_pool_create("test", base, 24);
|
||||
ck_assert_int_eq(0, pool->get_size(pool));
|
||||
assert_acquire(pool, "192.168.0.1", "192.168.0.1", MEM_POOL_NEW);
|
||||
pool->destroy(pool);
|
||||
|
||||
base->destroy(base);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_range)
|
||||
{
|
||||
mem_pool_t *pool;
|
||||
host_t *from, *to;
|
||||
|
||||
from = host_create_from_string("192.168.0.0", 0);
|
||||
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_acquires_new(pool, "192.168.0.%d", 0);
|
||||
pool->destroy(pool);
|
||||
|
||||
to->destroy(to);
|
||||
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_acquires_new(pool, "192.168.0.%d", 0);
|
||||
pool->destroy(pool);
|
||||
|
||||
from->destroy(from);
|
||||
from = host_create_from_string("192.168.0.10", 0);
|
||||
pool = mem_pool_create_range("test", from, to);
|
||||
ck_assert(!pool);
|
||||
|
||||
to->destroy(to);
|
||||
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_acquires_new(pool, "192.168.0.%d", 10);
|
||||
pool->destroy(pool);
|
||||
|
||||
from->destroy(from);
|
||||
from = host_create_from_string("fec::1", 0);
|
||||
to->destroy(to);
|
||||
to = host_create_from_string("fed::1", 0);
|
||||
pool = mem_pool_create_range("test", from, to);
|
||||
ck_assert(!pool);
|
||||
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *mem_pool_suite_create()
|
||||
{
|
||||
Suite *s;
|
||||
TCase *tc;
|
||||
|
||||
s = suite_create("mem_pool");
|
||||
|
||||
tc = tcase_create("%config-like pool");
|
||||
tcase_add_test(tc, test_config);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("cidr constructor");
|
||||
tcase_add_test(tc, test_cidr);
|
||||
tcase_add_test(tc, test_cidr_offset);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("range constructor");
|
||||
tcase_add_test(tc, test_range);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2012 Tobias Brunner
|
||||
* Copyright (C) 2006-2014 Tobias Brunner
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005-2006 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
@@ -525,6 +525,42 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
bool host_create_from_range(char *string, host_t **from, host_t **to)
|
||||
{
|
||||
char *sep, *pos;
|
||||
|
||||
sep = strchr(string, '-');
|
||||
if (!sep)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
for (pos = sep+1; *pos && *pos == ' '; pos++)
|
||||
{
|
||||
/* trim spaces before to address*/
|
||||
}
|
||||
*to = host_create_from_string(pos, 0);
|
||||
if (!*to)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
for (pos = sep-1; pos > string && *pos == ' '; pos--)
|
||||
{
|
||||
/* trim spaces behind from address */
|
||||
}
|
||||
pos = strndup(string, pos - string + 1);
|
||||
*from = host_create_from_string_and_family(pos, (*to)->get_family(*to), 0);
|
||||
free(pos);
|
||||
if (!*from)
|
||||
{
|
||||
(*to)->destroy(*to);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2009 Tobias Brunner
|
||||
* Copyright (C) 2006-2014 Tobias Brunner
|
||||
* Copyright (C) 2006 Daniel Roethlisberger
|
||||
* Copyright (C) 2005-2008 Martin Willi
|
||||
* Copyright (C) 2005 Jan Hutter
|
||||
@@ -180,6 +180,19 @@ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port);
|
||||
*/
|
||||
host_t *host_create_from_sockaddr(sockaddr_t *sockaddr);
|
||||
|
||||
/**
|
||||
* Parse a range definition (1.2.3.0-1.2.3.5), return the two hosts.
|
||||
*
|
||||
* The two hosts are not ordered, from is simply the first, to is the second,
|
||||
* from is not necessarily smaller.
|
||||
*
|
||||
* @param string string to parse
|
||||
* @param from returns the first address (out)
|
||||
* @param to returns the second address (out)
|
||||
* @return TRUE if parsed successfully, FALSE otherwise
|
||||
*/
|
||||
bool host_create_from_range(char *string, host_t **from, host_t **to);
|
||||
|
||||
/**
|
||||
* Create a host from a CIDR subnet definition (1.2.3.0/24), return bits.
|
||||
*
|
||||
|
||||
@@ -399,6 +399,90 @@ START_TEST(test_create_from_subnet_v6)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*******************************************************************************
|
||||
* host_create_from_range
|
||||
*/
|
||||
|
||||
static const chunk_t addr_v4_to = chunk_from_chars(0xc0, 0xa8, 0x00, 0x05);
|
||||
static const chunk_t addr_v6_to = chunk_from_chars(0xfe, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05);
|
||||
|
||||
static void verify_range(char *str, int family, chunk_t from_addr,
|
||||
chunk_t to_addr)
|
||||
{
|
||||
host_t *from, *to;
|
||||
|
||||
if (!family)
|
||||
{
|
||||
ck_assert(!host_create_from_range(str, &from, &to));
|
||||
}
|
||||
else
|
||||
{
|
||||
ck_assert(host_create_from_range(str, &from, &to));
|
||||
verify_address(from, from_addr, family, 0);
|
||||
verify_address(to, to_addr, family, 0);
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(test_create_from_range_v4)
|
||||
{
|
||||
host_t *from, *to;
|
||||
|
||||
ck_assert(host_create_from_range("0.0.0.0-0.0.0.0", &from, &to));
|
||||
verify_any(from, AF_INET, 0);
|
||||
verify_any(to, AF_INET, 0);
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
|
||||
verify_range("192.168.0.1-192.168.0.1", AF_INET, addr_v4, addr_v4);
|
||||
verify_range("192.168.0.1-192.168.0.5", AF_INET, addr_v4, addr_v4_to);
|
||||
verify_range("192.168.0.1- 192.168.0.5", AF_INET, addr_v4, addr_v4_to);
|
||||
verify_range("192.168.0.1 -192.168.0.5", AF_INET, addr_v4, addr_v4_to);
|
||||
verify_range("192.168.0.1 - 192.168.0.5", AF_INET, addr_v4, addr_v4_to);
|
||||
verify_range("192.168.0.5-192.168.0.1", AF_INET, addr_v4_to, addr_v4);
|
||||
|
||||
verify_range("192.168.0.1", 0, chunk_empty, chunk_empty);
|
||||
verify_range("192.168.0.1-", 0, chunk_empty, chunk_empty);
|
||||
verify_range("-192.168.0.1", 0, chunk_empty, chunk_empty);
|
||||
verify_range("192.168.0.1-192", 0, chunk_empty, chunk_empty);
|
||||
verify_range("192.168.0.1-192.168", 0, chunk_empty, chunk_empty);
|
||||
verify_range("192.168.0.1-192.168.0", 0, chunk_empty, chunk_empty);
|
||||
verify_range("foo.b.a.r", 0, chunk_empty, chunk_empty);
|
||||
verify_range("foo.b.a.r-b.a.r.f", 0, chunk_empty, chunk_empty);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_create_from_range_v6)
|
||||
{
|
||||
host_t *from, *to;
|
||||
|
||||
ck_assert(host_create_from_range("::-::", &from, &to));
|
||||
verify_any(from, AF_INET6, 0);
|
||||
verify_any(to, AF_INET6, 0);
|
||||
from->destroy(from);
|
||||
to->destroy(to);
|
||||
|
||||
verify_range("fec1::1-fec1::1", AF_INET6, addr_v6, addr_v6);
|
||||
verify_range("fec1::1-fec1::5", AF_INET6, addr_v6, addr_v6_to);
|
||||
verify_range("fec1::1- fec1::5", AF_INET6, addr_v6, addr_v6_to);
|
||||
verify_range("fec1::1 -fec1::5", AF_INET6, addr_v6, addr_v6_to);
|
||||
verify_range("fec1::1 - fec1::5", AF_INET6, addr_v6, addr_v6_to);
|
||||
verify_range("fec1::5-fec1::1", AF_INET6, addr_v6_to, addr_v6);
|
||||
|
||||
verify_range("fec1::1", 0, chunk_empty, chunk_empty);
|
||||
verify_range("fec1::1-", 0, chunk_empty, chunk_empty);
|
||||
verify_range("-fec1::1", 0, chunk_empty, chunk_empty);
|
||||
verify_range("fec1::1-fec1", 0, chunk_empty, chunk_empty);
|
||||
verify_range("foo::bar", 0, chunk_empty, chunk_empty);
|
||||
verify_range("foo::bar-bar::foo", 0, chunk_empty, chunk_empty);
|
||||
|
||||
verify_range("fec1::1-192.168.0.1", 0, chunk_empty, chunk_empty);
|
||||
verify_range("192.168.0.1-fec1::1", 0, chunk_empty, chunk_empty);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/*******************************************************************************
|
||||
* host_create_netmask
|
||||
*/
|
||||
@@ -627,6 +711,11 @@ Suite *host_suite_create()
|
||||
tcase_add_test(tc, test_create_from_subnet_v6);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("host_create_from_range");
|
||||
tcase_add_test(tc, test_create_from_range_v4);
|
||||
tcase_add_test(tc, test_create_from_range_v6);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("host_create_netmask");
|
||||
tcase_add_test(tc, test_create_netmask_v4);
|
||||
tcase_add_test(tc, test_create_netmask_v6);
|
||||
|
||||
@@ -782,11 +782,11 @@ pools.<name> { # }
|
||||
Section defining a single pool with a unique name.
|
||||
|
||||
pools.<name>.addrs =
|
||||
Subnet defining addresses allocated in pool.
|
||||
Addresses allocated in pool.
|
||||
|
||||
Subnet defining addresses allocated in pool. Accepts a single CIDR subnet
|
||||
defining the pool to allocate addresses from. Pools must be unique and
|
||||
non-overlapping.
|
||||
Subnet or range defining addresses allocated in pool. Accepts a single CIDR
|
||||
subnet defining the pool to allocate addresses from, or an address range
|
||||
(<from>-<to>). Pools must be unique and non-overlapping.
|
||||
|
||||
pools.<name>.<attr> =
|
||||
Comma separated list of additional attributes from type <attr>.
|
||||
|
||||
Reference in new issue
Block a user