aboutsummaryrefslogtreecommitdiffstats
path: root/src/libhydra/attributes/mem_pool.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2014-10-30 15:04:31 +0100
committerTobias Brunner <tobias@strongswan.org>2014-10-30 15:08:05 +0100
commit406f3af1ed1c53463b08769b419718161ea3fc94 (patch)
tree82e3608389ee037efecb4159226c61166cb4b5eb /src/libhydra/attributes/mem_pool.c
parent1201ddcbc5dda4849524f08a0923071d1b15b387 (diff)
parentcd67cd70c842fc2dacd253ba8b07a452269526dc (diff)
downloadstrongswan-406f3af1ed1c53463b08769b419718161ea3fc94.tar.bz2
strongswan-406f3af1ed1c53463b08769b419718161ea3fc94.tar.xz
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.
Diffstat (limited to 'src/libhydra/attributes/mem_pool.c')
-rw-r--r--src/libhydra/attributes/mem_pool.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c
index cc45e5629..225abe383 100644
--- a/src/libhydra/attributes/mem_pool.c
+++ b/src/libhydra/attributes/mem_pool.c
@@ -47,6 +47,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
*/
u_int size;
@@ -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);
}
@@ -580,18 +585,39 @@ static private_mem_pool_t *create_generic(char *name)
}
/**
+ * 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;
}