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:
Tobias Brunner committed 2014-10-30 15:08:05 +01:00
commit 406f3af1ed
16 files changed
+590 -42

No files matched your search

+1
View File
@@ -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
View File
@@ -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
+1 -16
View File
@@ -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;
+33 -7
View File
@@ -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
{
+35 -5
View File
@@ -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);
+5
View File
@@ -78,3 +78,8 @@ if MONOLITHIC
libhydra_la_LIBADD += plugins/resolve/libstrongswan-resolve.la
endif
endif
if MONOLITHIC
SUBDIRS += .
endif
SUBDIRS += tests
+49 -7
View File
@@ -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;
}
+1
View File
@@ -0,0 +1 @@
hydra_tests
+19
View File
@@ -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
+53
View File
@@ -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);
}
+16
View File
@@ -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)
+230
View File
@@ -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;
}
+37 -1
View File
@@ -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.
*/
+14 -1
View File
@@ -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);
+4 -4
View File
@@ -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>.