aboutsummaryrefslogtreecommitdiff
path: root/dhcp6s.c
diff options
context:
space:
mode:
authorSUZUKI, Shinsuke <suz@kame.net>2006-01-26 06:21:37 +0000
committerSUZUKI, Shinsuke <suz@kame.net>2006-01-26 06:21:37 +0000
commitd859b0a9117ccd0c5b42e6ba56da47d955516026 (patch)
treede087126d87a42118b0b0d1f2ec460c9eb6fa133 /dhcp6s.c
parente137e82e0a14b4b60f165b2621a25fbc8c040c2c (diff)
supported IA-NA address-pool
ToDo: IA-PD prefix-pool, write a manual
Diffstat (limited to 'dhcp6s.c')
-rw-r--r--dhcp6s.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/dhcp6s.c b/dhcp6s.c
index 6a448e1..7d626dd 100644
--- a/dhcp6s.c
+++ b/dhcp6s.c
@@ -74,6 +74,10 @@
#include <base64.h>
#include <control.h>
#include <dhcp6_ctl.h>
+#ifdef USE_POOL
+#include <signal.h>
+#include <lease.h>
+#endif
#define DUID_FILE LOCALDBDIR "/dhcp6s_duid"
#define DHCP6S_CONF SYSCONFDIR "/dhcp6s.conf"
@@ -185,6 +189,10 @@ static int make_ia __P((struct dhcp6_listval *, struct dhcp6_list *,
struct dhcp6_list *, struct host_conf *, int));
static int make_match_ia __P((struct dhcp6_listval *, struct dhcp6_list *,
struct dhcp6_list *));
+#ifdef USE_POOL
+static int make_iana_from_pool __P((struct dhcp6_poolspec *,
+ struct dhcp6_listval *, struct dhcp6_list *));
+#endif
static void calc_ia_timo __P((struct dhcp6_ia *, struct dhcp6_list *,
struct host_conf *));
static void update_binding_duration __P((struct dhcp6_binding *));
@@ -332,6 +340,12 @@ server6_init()
static struct sockaddr_in6 sa6_any_relay_storage;
TAILQ_INIT(&dhcp6_binding_head);
+#ifdef USE_POOL
+ if (lease_init() != 0) {
+ dprintf(LOG_ERR, FNAME, "failed to initialize the lease table");
+ exit(1);
+ }
+#endif
ifidx = if_nametoindex(device);
if (ifidx == 0) {
@@ -1239,6 +1253,14 @@ react_solicit(ifp, dh6, len, optinfo, from, fromlen, relayinfohead)
struct dhcp6_list conflist;
struct dhcp6_listval *iana;
+#ifdef USE_POOL
+ if (client_conf == NULL && ifp->pool.name) {
+ if ((client_conf = create_dynamic_hostconf(&optinfo->clientID,
+ &ifp->pool)) == NULL)
+ dprintf(LOG_NOTICE, FNAME,
+ "failed to make host configuration");
+ }
+#endif
TAILQ_INIT(&conflist);
/* make a local copy of the configured addresses */
@@ -1448,6 +1470,14 @@ react_request(ifp, pi, dh6, len, optinfo, from, fromlen, relayinfohead)
struct dhcp6_list conflist;
struct dhcp6_listval *iana;
+#ifdef USE_POOL
+ if (client_conf == NULL && ifp->pool.name) {
+ if ((client_conf = create_dynamic_hostconf(&optinfo->clientID,
+ &ifp->pool)) == NULL)
+ dprintf(LOG_NOTICE, FNAME,
+ "failed to make host configuration");
+ }
+#endif
TAILQ_INIT(&conflist);
/* make a local copy of the configured prefixes */
@@ -2163,6 +2193,9 @@ release_binding_ia(iap, retlist, optinfo)
lvia->val_prefix6.plen);
break;
case DHCP6_LISTVAL_IANA:
+#ifdef USE_POOL
+ release_address(&lvia->val_prefix6.addr);
+#endif
dprintf(LOG_DEBUG, FNAME,
"bound address %s "
"has been released",
@@ -2397,8 +2430,17 @@ make_ia(spec, conflist, retlist, client_conf, do_binding)
* trivial case:
* if the configuration is empty, we cannot make any IA.
*/
+#ifdef USE_POOL
+ if (TAILQ_EMPTY(conflist)) {
+ if (spec->type != DHCP6_LISTVAL_IANA ||
+ client_conf->pool.name == NULL) {
+ return (0);
+ }
+ }
+#else
if (TAILQ_EMPTY(conflist))
return (0);
+#endif /* USE_POOL */
TAILQ_INIT(&ialist);
@@ -2406,10 +2448,43 @@ make_ia(spec, conflist, retlist, client_conf, do_binding)
for (specia = TAILQ_FIRST(&spec->sublist); specia;
specia = TAILQ_NEXT(specia, link)) {
/* try to find an IA that matches the spec best. */
+#ifdef USE_POOL
+ if (!TAILQ_EMPTY(conflist)) {
+ if (make_match_ia(specia, conflist, &ialist))
+ found++;
+ } else if (spec->type == DHCP6_LISTVAL_IANA &&
+ client_conf->pool.name != NULL) {
+ if (make_iana_from_pool(&client_conf->pool, specia, &ialist))
+ found++;
+ }
+#else
if (make_match_ia(specia, conflist, &ialist))
found++;
+#endif /* USE_POOL */
}
if (found == 0) {
+#ifdef USE_POOL
+ if (!TAILQ_EMPTY(conflist)) {
+ struct dhcp6_listval *v;
+
+ /* use the first IA in the configuration list */
+ for (v = TAILQ_FIRST(conflist); v; v = TAILQ_NEXT(v, link)) {
+ if (spec->type != DHCP6_LISTVAL_IANA)
+ break; /* always use the first IA for non-IANA */
+ if (!is_leased(&v->val_statefuladdr6.addr))
+ break;
+ }
+ if (v && dhcp6_add_listval(&ialist, v->type, &v->uv, NULL)) {
+ found = 1;
+ TAILQ_REMOVE(conflist, v, link);
+ dhcp6_clear_listval(v);
+ }
+ } else if (spec->type == DHCP6_LISTVAL_IANA &&
+ client_conf->pool.name != NULL) {
+ if (make_iana_from_pool(&client_conf->pool, NULL, &ialist))
+ found = 1;
+ }
+#else
struct dhcp6_listval *v;
/* use the first IA in the configuration list */
@@ -2419,6 +2494,7 @@ make_ia(spec, conflist, retlist, client_conf, do_binding)
TAILQ_REMOVE(conflist, v, link);
dhcp6_clear_listval(v);
}
+#endif /* USE_POOL */
}
if (found) {
memset(&ia, 0, sizeof(ia));
@@ -2467,6 +2543,10 @@ make_match_ia(spec, conflist, retlist)
break;
case DHCP6_LISTVAL_STATEFULADDR6:
/* No "partial match" for addresses */
+#ifdef USE_POOL
+ if (is_leased(&spec->val_statefuladdr6.addr))
+ match = 0;
+#endif
break;
default:
dprintf(LOG_ERR, FNAME, "unsupported IA type");
@@ -2490,6 +2570,52 @@ make_match_ia(spec, conflist, retlist)
return (matched);
}
+#ifdef USE_POOL
+/* making sublist of iana */
+static int
+make_iana_from_pool(poolspec, spec, retlist)
+ struct dhcp6_poolspec *poolspec;
+ struct dhcp6_listval *spec;
+ struct dhcp6_list *retlist;
+{
+ struct dhcp6_statefuladdr saddr;
+ struct pool_conf *pool;
+ int found = 0;
+
+ dprintf(LOG_DEBUG, FNAME, "called");
+
+ if ((pool = find_pool(poolspec->name)) == NULL) {
+ dprintf(LOG_ERR, FNAME, "pool '%s' not found", poolspec->name);
+ return (0);
+ }
+
+ if (spec) {
+ memcpy(&saddr.addr, &spec->val_statefuladdr6.addr, sizeof(saddr.addr));
+ if (is_available_in_pool(pool, &saddr.addr)) {
+ found = 1;
+ }
+ } else {
+ if (get_free_address_from_pool(pool, &saddr.addr)) {
+ found = 1;
+ }
+ }
+
+ if (found) {
+ saddr.pltime = poolspec->pltime;
+ saddr.vltime = poolspec->vltime;
+
+ if (!dhcp6_add_listval(retlist, DHCP6_LISTVAL_STATEFULADDR6,
+ &saddr, NULL)) {
+ return (0);
+ }
+ }
+
+ dprintf(LOG_DEBUG, FNAME, "returns (found=%d)", found);
+
+ return (found);
+}
+#endif /* USE_POOL */
+
static void
calc_ia_timo(ia, ialist, client_conf)
struct dhcp6_ia *ia;
@@ -2629,6 +2755,35 @@ add_binding(clientid, btype, iatype, iaid, val0)
"failed to copy binding data");
goto fail;
}
+#ifdef USE_POOL
+ /* lease address */
+ if (iatype == DHCP6_LISTVAL_IANA) {
+ struct dhcp6_list *ia_list = &binding->val_list;
+ struct dhcp6_listval *lv, *lv_next;
+
+ for (lv = TAILQ_FIRST(ia_list); lv; lv = lv_next) {
+ lv_next = TAILQ_NEXT(lv, link);
+
+ if (lv->type != DHCP6_LISTVAL_STATEFULADDR6) {
+ dprintf(LOG_ERR, FNAME,
+ "unexpected binding value type(%d)", lv->type);
+ continue;
+ }
+
+ if (!lease_address(&lv->val_statefuladdr6.addr)) {
+ dprintf(LOG_NOTICE, FNAME,
+ "cannot lease address %s",
+ in6addr2str(&lv->val_statefuladdr6.addr, 0));
+ TAILQ_REMOVE(ia_list, lv, link);
+ dhcp6_clear_listval(lv);
+ }
+ }
+ if (TAILQ_EMPTY(ia_list)) {
+ dprintf(LOG_NOTICE, FNAME, "cannot lease any address");
+ goto fail;
+ }
+ }
+#endif /* USE_POOL */
break;
default:
dprintf(LOG_ERR, FNAME, "unexpected binding type(%d)", btype);
@@ -2734,6 +2889,22 @@ free_binding(binding)
/* free configuration info in a type dependent manner. */
switch (binding->type) {
case DHCP6_BINDING_IA:
+#ifdef USE_POOL
+ /* releaes address */
+ if (binding->iatype == DHCP6_LISTVAL_IANA) {
+ struct dhcp6_list *ia_list = &binding->val_list;
+ struct dhcp6_listval *lv;
+
+ for (lv = TAILQ_FIRST(ia_list); lv; lv = TAILQ_NEXT(lv, link)) {
+ if (lv->type != DHCP6_LISTVAL_STATEFULADDR6) {
+ dprintf(LOG_ERR, FNAME,
+ "unexpected binding value type(%d)", lv->type);
+ continue;
+ }
+ release_address(&lv->val_statefuladdr6.addr);
+ }
+ }
+#endif /* USE_POOL */
dhcp6_clear_list(&binding->val_list);
break;
default:
@@ -2783,6 +2954,10 @@ binding_timo(arg)
in6addr2str(&iav->val_prefix6.addr, 0),
iav->val_prefix6.plen,
bindingstr(binding));
+#ifdef USE_POOL
+ if (binding->iatype == DHCP6_LISTVAL_IANA)
+ release_address(&iav->val_prefix6.addr);
+#endif
TAILQ_REMOVE(ia_list, iav, link);
dhcp6_clear_listval(iav);
}