aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-08-02 19:49:47 +0200
committerHarald Welte <laforge@gnumonks.org>2017-08-09 22:08:57 +0200
commitd12eab9c4e375e1669637dd34674c8b8208cf867 (patch)
tree2a105db1821f3b1db6a12b1ab8f3c1ef9d301648 /lib
parentd9d8862a58702ba71b5194faa01ecf1eb234519c (diff)
ippool: Add IPv6 support to IP pool implementation
Extend the IP pool implementation to be able to manage both pools of 32bit addresses (IPv4) as well as pools of 128bit addresses (IPv6) Change-Id: Ib98cc4bf634d6be9a7bf8c03a24e629455fcafc8
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/in46_addr.c148
-rw-r--r--lib/in46_addr.h19
-rw-r--r--lib/ippool.c238
-rw-r--r--lib/ippool.h32
5 files changed, 317 insertions, 124 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 756d566..632990c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,7 +1,7 @@
noinst_LIBRARIES = libmisc.a
-noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h
+noinst_HEADERS = gnugetopt.h ippool.h lookup.h syserr.h tun.h in46_addr.h
AM_CFLAGS = -O2 -fno-builtin -Wall -DSBINDIR='"$(sbindir)"' -ggdb $(LIBOSMOCORE_CFLAGS)
-libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c
+libmisc_a_SOURCES = getopt1.c getopt.c ippool.c lookup.c tun.c debug.c in46_addr.c
diff --git a/lib/in46_addr.c b/lib/in46_addr.c
new file mode 100644
index 0000000..903ceec
--- /dev/null
+++ b/lib/in46_addr.c
@@ -0,0 +1,148 @@
+/*
+ * IPv4/v6 address functions.
+ * Copyright (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ *
+ * The contents of this file may be used under the terms of the GNU
+ * General Public License Version 2, provided that the above copyright
+ * notice and this permission notice is included in all copies or
+ * substantial portions of the software.
+ *
+ */
+
+#include "../lib/in46_addr.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*! Return the address family of given \reff in46_addr argument */
+int in46a_to_af(const struct in46_addr *in)
+{
+ switch (in->len) {
+ case 4:
+ return AF_INET;
+ case 16:
+ return AF_INET6;
+ default:
+ return -1;
+ }
+}
+
+/*! Convert \ref in46_addr to sockaddr_storage */
+int in46a_to_sas(struct sockaddr_storage *out, const struct in46_addr *in)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)out;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)out;
+
+ switch (in->len) {
+ case 4:
+ sin->sin_family = AF_INET;
+ sin->sin_addr = in->v4;
+ break;
+ case 16:
+ sin6->sin6_family = AF_INET;
+ sin6->sin6_addr = in->v6;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+/*! Convenience wrapper around inet_ntop() for \ref in46_addr */
+const char *in46a_ntop(const struct in46_addr *in, char *dst, socklen_t dst_size)
+{
+ int af = in46a_to_af(in);
+ if (af < 0)
+ return NULL;
+
+ return inet_ntop(af, (const void *) &in->v4, dst, dst_size);
+}
+
+/*! Determine if two in46_addr are equal or not
+ * \returns 1 in case they are equal; 0 otherwise */
+int in46a_equal(const struct in46_addr *a, const struct in46_addr *b)
+{
+ if (a->len == b->len && !memcmp(&a->v6, &b->v6, a->len))
+ return 1;
+ else
+ return 0;
+}
+
+/*! Match if IPv6 addr1 + addr2 are within same \a mask */
+static int ipv6_within_mask(const struct in6_addr *addr1, const struct in6_addr *addr2,
+ const struct in6_addr *mask)
+{
+ struct in6_addr masked = *addr2;
+#if defined(__linux__)
+ masked.s6_addr32[0] &= mask->s6_addr32[0];
+ masked.s6_addr32[1] &= mask->s6_addr32[1];
+ masked.s6_addr32[2] &= mask->s6_addr32[2];
+ masked.s6_addr32[3] &= mask->s6_addr32[3];
+#else
+ masked.__u6_addr.__u6_addr32[0] &= mask->__u6_addr.__u6_addr32[0];
+ masked.__u6_addr.__u6_addr32[1] &= mask->__u6_addr.__u6_addr32[1];
+ masked.__u6_addr.__u6_addr32[2] &= mask->__u6_addr.__u6_addr32[2];
+ masked.__u6_addr.__u6_addr32[3] &= mask->__u6_addr.__u6_addr32[3];
+#endif
+ if (!memcmp(addr1, &masked, sizeof(struct in6_addr)))
+ return 1;
+ else
+ return 0;
+}
+
+/*! Create an IPv6 netmask from the given prefix length */
+static void create_ipv6_netmask(struct in6_addr *netmask, int prefixlen)
+{
+ uint32_t *p_netmask;
+ memset(netmask, 0, sizeof(struct in6_addr));
+ if (prefixlen < 0)
+ prefixlen = 0;
+ else if (128 < prefixlen)
+ prefixlen = 128;
+
+#if defined(__linux__)
+ p_netmask = &netmask->s6_addr32[0];
+#else
+ p_netmask = &netmask->__u6_addr.__u6_addr32[0];
+#endif
+ while (32 < prefixlen) {
+ *p_netmask = 0xffffffff;
+ p_netmask++;
+ prefixlen -= 32;
+ }
+ if (prefixlen != 0) {
+ *p_netmask = htonl(0xFFFFFFFF << (32 - prefixlen));
+ }
+}
+
+/*! Determine if given \a addr is within given \a net + \a prefixlen
+ * Builds the netmask from \a net + \a prefixlen and matches it to \a addr
+ * \returns 1 in case of a match, 0 otherwise */
+int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net, size_t prefixlen)
+{
+ struct in_addr netmask;
+ struct in6_addr netmask6;
+
+ if (addr->len != net->len)
+ return 0;
+
+ switch (addr->len) {
+ case 4:
+ netmask.s_addr = htonl(0xFFFFFFFF << (32 - prefixlen));
+ if ((addr->v4.s_addr & netmask.s_addr) == net->v4.s_addr)
+ return 1;
+ else
+ return 0;
+ case 16:
+ create_ipv6_netmask(&netmask6, prefixlen);
+ return ipv6_within_mask(&addr->v6, &net->v6, &netmask6);
+ default:
+ return 0;
+ }
+}
diff --git a/lib/in46_addr.h b/lib/in46_addr.h
new file mode 100644
index 0000000..f28fd8e
--- /dev/null
+++ b/lib/in46_addr.h
@@ -0,0 +1,19 @@
+#pragma once
+#include <stdint.h>
+#include <netinet/in.h>
+
+/* a simple wrapper around an in6_addr to also contain the length of the address,
+ * thereby implicitly indicating the address family of the address */
+struct in46_addr {
+ uint8_t len;
+ union {
+ struct in_addr v4;
+ struct in6_addr v6;
+ };
+};
+
+extern int in46a_to_af(const struct in46_addr *in);
+extern int in46a_to_sas(struct sockaddr_storage *out, const struct in46_addr *in);
+extern const char *in46a_ntop(const struct in46_addr *in, char *dst, socklen_t dst_size);
+extern int in46a_equal(const struct in46_addr *a, const struct in46_addr *b);
+extern int in46a_within_mask(const struct in46_addr *addr, const struct in46_addr *net, size_t prefixlen);
diff --git a/lib/ippool.c b/lib/ippool.c
index 1f79a77..c3eb267 100644
--- a/lib/ippool.c
+++ b/lib/ippool.c
@@ -1,6 +1,7 @@
/*
* IP address pool functions.
* Copyright (C) 2003, 2004 Mondru AB.
+ * Copyright (C) 2017 by Harald Welte <laforge@gnumonks.org>
*
* The contents of this file may be used under the terms of the GNU
* General Public License Version 2, provided that the above copyright
@@ -16,6 +17,7 @@
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
+#include <netdb.h>
#include "syserr.h"
#include "ippool.h"
#include "lookup.h"
@@ -31,13 +33,14 @@ int ippool_printaddr(struct ippool_t *this)
printf("Listsize %d\n", this->listsize);
for (n = 0; n < this->listsize; n++) {
- printf("Unit %d inuse %d prev %d next %d addr %s %x\n",
+ char s[256];
+ in46a_ntop(&this->member[n].addr, s, sizeof(s));
+ printf("Unit %d inuse %d prev %d next %d addr %s\n",
n,
this->member[n].inuse,
this->member[n].prev - this->member,
this->member[n].next - this->member,
- inet_ntoa(this->member[n].addr),
- this->member[n].addr.s_addr);
+ s);
}
return 0;
}
@@ -49,7 +52,7 @@ int ippool_hashadd(struct ippool_t *this, struct ippoolm_t *member)
struct ippoolm_t *p_prev = NULL;
/* Insert into hash table */
- hash = ippool_hash4(&member->addr) & this->hashmask;
+ hash = ippool_hash(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash)
p_prev = p;
if (!p_prev)
@@ -66,7 +69,7 @@ int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
struct ippoolm_t *p_prev = NULL;
/* Find in hash table */
- hash = ippool_hash4(&member->addr) & this->hashmask;
+ hash = ippool_hash(&member->addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
if (p == member) {
break;
@@ -88,75 +91,100 @@ int ippool_hashdel(struct ippool_t *this, struct ippoolm_t *member)
return 0;
}
-unsigned long int ippool_hash4(struct in_addr *addr)
+static unsigned long int ippool_hash4(struct in_addr *addr)
{
return lookup((unsigned char *)&addr->s_addr, sizeof(addr->s_addr), 0);
}
-#ifndef IPPOOL_NOIP6
-unsigned long int ippool_hash6(struct in6_addr *addr)
+static unsigned long int ippool_hash6(struct in6_addr *addr)
{
- return lookup((unsigned char *)addr->u6_addr8, sizeof(addr->u6_addr8),
+ /* TODO: Review hash spread for IPv6 */
+ return lookup((unsigned char *)addr->s6_addr, sizeof(addr->s6_addr),
0);
}
-#endif
-/* Get IP address and mask */
-int ippool_aton(struct in_addr *addr, struct in_addr *mask,
- char *pool, int number)
+unsigned long int ippool_hash(struct in46_addr *addr)
{
+ if (addr->len == 4)
+ return ippool_hash4(&addr->v4);
+ else
+ return ippool_hash6(&addr->v6);
+}
- /* Parse only first instance of network for now */
- /* Eventually "number" will indicate the token which we want to parse */
-
- unsigned int a1, a2, a3, a4;
- unsigned int m1, m2, m3, m4;
- int c;
- int m;
- int masklog;
-
- c = sscanf(pool, "%u.%u.%u.%u/%u.%u.%u.%u",
- &a1, &a2, &a3, &a4, &m1, &m2, &m3, &m4);
- switch (c) {
- case 4:
- mask->s_addr = 0xffffffff;
- break;
- case 5:
- if (m1 > 32) {
- SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
- return -1; /* Invalid mask */
- }
- mask->s_addr = htonl(0xffffffff << (32 - m1));
- break;
- case 8:
- if (m1 >= 256 || m2 >= 256 || m3 >= 256 || m4 >= 256) {
- SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
- return -1; /* Wrong mask format */
+/* Get IP address and mask */
+int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool_in, int number)
+{
+ struct addrinfo *ai;
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = 0,
+ .ai_protocol = 0
+ };
+ char pool[strlen(pool_in)+1];
+
+ strcpy(pool, pool_in);
+
+ int err;
+
+ /* Find '/' and point to first char after it */
+ char *prefixlen_str = strchr(pool, '/');
+ if (prefixlen_str) {
+ *prefixlen_str = '\0';
+ prefixlen_str++;
+ if (*prefixlen_str == '\0') {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "Empty prefix length specified");
+ return -1;
}
- m = m1 * 0x1000000 + m2 * 0x10000 + m3 * 0x100 + m4;
- for (masklog = 0; ((1 << masklog) < ((~m) + 1)); masklog++) ;
- if (((~m) + 1) != (1 << masklog)) {
- SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
- return -1; /* Wrong mask format (not all ones followed by all zeros) */
+ }
+
+ /* convert address */
+ if ((err = getaddrinfo(pool, NULL, &hints, &ai))) {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "Bad address");
+ return -1;
+ }
+
+ /* Copy address, set lengths */
+ if (ai->ai_family == AF_INET) {
+ *prefixlen = 32;
+ addr->len = sizeof(struct in_addr);
+ addr->v4 = ((struct sockaddr_in*)ai->ai_addr)->sin_addr;
+ } else {
+ *prefixlen = 128;
+ addr->len = sizeof(struct in6_addr);
+ addr->v6 = ((struct sockaddr_in6*)ai->ai_addr)->sin6_addr;
+ }
+ freeaddrinfo(ai);
+
+ /* parse prefixlen */
+ if (prefixlen_str) {
+ char *e;
+ *prefixlen = strtol(prefixlen_str, &e, 10);
+ if (*e != '\0') {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "Prefixlen is not an int");
+ return -1;
}
- mask->s_addr = htonl(m);
- break;
- default:
- SYS_ERR(DIP, LOGL_ERROR, 0, "Invalid mask");
- return -1; /* Invalid mask */
}
- if (a1 >= 256 || a2 >= 256 || a3 >= 256 || a4 >= 256) {
- SYS_ERR(DIP, LOGL_ERROR, 0,
- "Wrong IP address format");
+ if (*prefixlen > (addr->len * 8)) {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "Perfixlen too big");
return -1;
- } else
- addr->s_addr =
- htonl(a1 * 0x1000000 + a2 * 0x10000 + a3 * 0x100 + a4);
+ }
return 0;
}
+/* Increase IPv4/IPv6 address by 1 */
+void in46a_inc(struct in46_addr *addr)
+{
+ size_t addrlen;
+ uint8_t *a = (uint8_t *)&addr->v6;
+ for (addrlen = addr->len; addrlen > 0; addrlen--) {
+ if (++a[addrlen-1])
+ break;
+ }
+}
+
/* Create new address pool */
int ippool_new(struct ippool_t **this, char *dyn, char *stat,
int allowdyn, int allowstat, int flags)
@@ -165,11 +193,10 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
/* Parse only first instance of pool for now */
int i;
- struct in_addr addr;
- struct in_addr mask;
- struct in_addr stataddr;
- struct in_addr statmask;
- unsigned int m;
+ struct in46_addr addr;
+ size_t addrprefixlen;
+ struct in46_addr stataddr;
+ size_t stataddrprefixlen;
int listsize;
int dynsize;
unsigned int statsize;
@@ -177,7 +204,7 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
if (!allowdyn) {
dynsize = 0;
} else {
- if (ippool_aton(&addr, &mask, dyn, 0)) {
+ if (ippool_aton(&addr, &addrprefixlen, dyn, 0)) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Failed to parse dynamic pool");
return -1;
@@ -188,8 +215,7 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
flags |= IPPOOL_NONETWORK;
}
- m = ntohl(mask.s_addr);
- dynsize = ((~m) + 1);
+ dynsize = (1 << (addr.len*8 - addrprefixlen)) -1;
if (flags & IPPOOL_NONETWORK) /* Exclude network address from pool */
dynsize--;
if (flags & IPPOOL_NOGATEWAY) /* Exclude gateway address from pool */
@@ -200,17 +226,16 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
if (!allowstat) {
statsize = 0;
- stataddr.s_addr = 0;
- statmask.s_addr = 0;
+ stataddr.len = 0;
+ stataddrprefixlen = 0;
} else {
- if (ippool_aton(&stataddr, &statmask, stat, 0)) {
+ if (ippool_aton(&stataddr, &stataddrprefixlen, stat, 0)) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Failed to parse static range");
return -1;
}
- m = ntohl(statmask.s_addr);
- statsize = ((~m) + 1);
+ statsize = (1 << (addr.len - addrprefixlen + 1)) -1;
if (statsize > IPPOOL_STATSIZE)
statsize = IPPOOL_STATSIZE;
}
@@ -225,8 +250,9 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
(*this)->allowdyn = allowdyn;
(*this)->allowstat = allowstat;
- (*this)->stataddr = stataddr;
- (*this)->statmask = statmask;
+ if (stataddr.len > 0)
+ (*this)->stataddr = stataddr;
+ (*this)->stataddrprefixlen = stataddrprefixlen;
(*this)->listsize += listsize;
if (!((*this)->member = calloc(sizeof(struct ippoolm_t), listsize))) {
@@ -255,17 +281,15 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
(*this)->firstdyn = NULL;
(*this)->lastdyn = NULL;
+ if (flags & IPPOOL_NOGATEWAY) {
+ in46a_inc(&addr);
+ in46a_inc(&addr);
+ } else if (flags & IPPOOL_NONETWORK) {
+ in46a_inc(&addr);
+ }
for (i = 0; i < dynsize; i++) {
-
- if (flags & IPPOOL_NOGATEWAY)
- (*this)->member[i].addr.s_addr =
- htonl(ntohl(addr.s_addr) + i + 2);
- else if (flags & IPPOOL_NONETWORK)
- (*this)->member[i].addr.s_addr =
- htonl(ntohl(addr.s_addr) + i + 1);
- else
- (*this)->member[i].addr.s_addr =
- htonl(ntohl(addr.s_addr) + i);
+ (*this)->member[i].addr = addr;
+ in46a_inc(&addr);
(*this)->member[i].inuse = 0;
@@ -285,8 +309,8 @@ int ippool_new(struct ippool_t **this, char *dyn, char *stat,
(*this)->firststat = NULL;
(*this)->laststat = NULL;
for (i = dynsize; i < listsize; i++) {
-
- (*this)->member[i].addr.s_addr = 0;
+ struct in46_addr *i6al = &(*this)->member[i].addr;
+ memset(i6al, 0, sizeof(*i6al));
(*this)->member[i].inuse = 0;
/* Insert into list of unused */
@@ -316,15 +340,15 @@ int ippool_free(struct ippool_t *this)
/* Find an IP address in the pool */
int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr)
+ struct in46_addr *addr)
{
struct ippoolm_t *p;
uint32_t hash;
/* Find in hash table */
- hash = ippool_hash4(addr) & this->hashmask;
+ hash = ippool_hash(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
- if ((p->addr.s_addr == addr->s_addr) && (p->inuse)) {
+ if (in46a_equal(&p->addr, addr)) {
if (member)
*member = p;
return 0;
@@ -344,7 +368,7 @@ int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
* address space.
**/
int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr, int statip)
+ struct in46_addr *addr, int statip)
{
struct ippoolm_t *p;
struct ippoolm_t *p2 = NULL;
@@ -365,17 +389,23 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
if (0)
(void)ippool_printaddr(this);
+ int specified = 0;
+ if (addr) {
+ if (addr->len == 4 && addr->v4.s_addr)
+ specified = 1;
+ if (addr->len == 16 && !IN6_IS_ADDR_UNSPECIFIED(&addr->v6))
+ specified = 1;
+ }
+
/* First check to see if this type of address is allowed */
- if ((addr) && (addr->s_addr) && statip) { /* IP address given */
+ if (specified && statip) { /* IP address given */
if (!this->allowstat) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"Static IP address not allowed");
return -1;
}
- if ((addr->s_addr & this->statmask.s_addr) !=
- this->stataddr.s_addr) {
- SYS_ERR(DIP, LOGL_ERROR, 0,
- "Static out of range");
+ if (!in46a_within_mask(addr, &this->stataddr, this->stataddrprefixlen)) {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "Static out of range");
return -1;
}
} else {
@@ -387,11 +417,11 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
}
/* If IP address given try to find it in dynamic address pool */
- if ((addr) && (addr->s_addr)) { /* IP address given */
+ if (specified) { /* IP address given */
/* Find in hash table */
- hash = ippool_hash4(addr) & this->hashmask;
+ hash = ippool_hash(addr) & this->hashmask;
for (p = this->hash[hash]; p; p = p->nexthash) {
- if ((p->addr.s_addr == addr->s_addr)) {
+ if (in46a_equal(&p->addr, addr)) {
p2 = p;
break;
}
@@ -420,6 +450,11 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
return -1; /* Allready in use / Should not happen */
}
+ if (p2->addr.len != addr->len) {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
+ return -1;
+ }
+
/* Remove from linked list of free dynamic addresses */
if (p2->prev)
p2->prev->next = p2->next;
@@ -442,7 +477,7 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
/* It was not possible to allocate from dynamic address pool */
/* Try to allocate from static address space */
- if ((addr) && (addr->s_addr) && (statip)) { /* IP address given */
+ if (specified && (statip)) { /* IP address given */
if (!this->firststat) {
SYS_ERR(DIP, LOGL_ERROR, 0,
"No more IP addresses available");
@@ -450,6 +485,11 @@ int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
} else
p2 = this->firststat;
+ if (p2->addr.len != addr->len) {
+ SYS_ERR(DIP, LOGL_ERROR, 0, "MS requested unsupported PDP context type");
+ return -1;
+ }
+
/* Remove from linked list of free static addresses */
if (p2->prev)
p2->prev->next = p2->next;
@@ -518,7 +558,7 @@ int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
this->laststat = member;
member->inuse = 0;
- member->addr.s_addr = 0;
+ memset(&member->addr, 0, sizeof(member->addr));
member->peer = NULL;
member->nexthash = NULL;
if (0)
@@ -530,9 +570,3 @@ int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member)
return -1;
}
}
-
-#ifndef IPPOOL_NOIP6
-extern unsigned long int ippool_hash6(struct in6_addr *addr);
-extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
-extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
-#endif
diff --git a/lib/ippool.h b/lib/ippool.h
index 534140d..53154f2 100644
--- a/lib/ippool.h
+++ b/lib/ippool.h
@@ -12,6 +12,8 @@
#ifndef _IPPOOL_H
#define _IPPOOL_H
+#include "../lib/in46_addr.h"
+
/* Assuming that the address space is fragmented we need a hash table
in order to return the addresses.
@@ -26,8 +28,6 @@
in RFC2373.
*/
-#define IPPOOL_NOIP6
-
#define IPPOOL_NONETWORK 0x01
#define IPPOOL_NOBROADCAST 0x02
#define IPPOOL_NOGATEWAY 0x04
@@ -40,8 +40,8 @@ struct ippool_t {
unsigned int listsize; /* Total number of addresses */
int allowdyn; /* Allow dynamic IP address allocation */
int allowstat; /* Allow static IP address allocation */
- struct in_addr stataddr; /* Static address range network address */
- struct in_addr statmask; /* Static address range network mask */
+ struct in46_addr stataddr; /* Static address range network address */
+ size_t stataddrprefixlen; /* IPv6 prefix length of stataddr */
struct ippoolm_t *member; /* Listsize array of members */
unsigned int hashsize; /* Size of hash table */
int hashlog; /* Log2 size of hash table */
@@ -54,11 +54,7 @@ struct ippool_t {
};
struct ippoolm_t {
-#ifndef IPPOOL_NOIP6
- struct in6_addr addr; /* IP address of this member */
-#else
- struct in_addr addr; /* IP address of this member */
-#endif
+ struct in46_addr addr; /* IP address of this member */
int inuse; /* 0=available; 1= dynamic; 2 = static */
struct ippoolm_t *nexthash; /* Linked list part of hash table */
struct ippoolm_t *prev, *next; /* Linked list of free dynamic or static */
@@ -70,7 +66,7 @@ struct ippoolm_t {
bytes for each address. */
/* Hash an IP address using code based on Bob Jenkins lookupa */
-extern unsigned long int ippool_hash4(struct in_addr *addr);
+extern unsigned long int ippool_hash(struct in46_addr *addr);
/* Create new address pool */
extern int ippool_new(struct ippool_t **this, char *dyn, char *stat,
@@ -81,24 +77,20 @@ extern int ippool_free(struct ippool_t *this);
/* Find an IP address in the pool */
extern int ippool_getip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr);
+ struct in46_addr *addr);
/* Get an IP address. If addr = 0.0.0.0 get a dynamic IP address. Otherwise
check to see if the given address is available */
extern int ippool_newip(struct ippool_t *this, struct ippoolm_t **member,
- struct in_addr *addr, int statip);
+ struct in46_addr *addr, int statip);
/* Return a previously allocated IP address */
extern int ippool_freeip(struct ippool_t *this, struct ippoolm_t *member);
/* Get net and mask based on ascii string */
-extern int ippool_aton(struct in_addr *addr, struct in_addr *mask,
- char *pool, int number);
-
-#ifndef IPPOOL_NOIP6
-extern unsigned long int ippool_hash6(struct in6_addr *addr);
-extern int ippool_getip6(struct ippool_t *this, struct in6_addr *addr);
-extern int ippool_returnip6(struct ippool_t *this, struct in6_addr *addr);
-#endif
+int ippool_aton(struct in46_addr *addr, size_t *prefixlen, const char *pool, int number);
+
+/* Increase IPv4/IPv6 address by 1 */
+extern void in46a_inc(struct in46_addr *addr);
#endif /* !_IPPOOL_H */