diff options
author | SUZUKI, Shinsuke <suz@kame.net> | 2006-01-26 06:21:37 +0000 |
---|---|---|
committer | SUZUKI, Shinsuke <suz@kame.net> | 2006-01-26 06:21:37 +0000 |
commit | d859b0a9117ccd0c5b42e6ba56da47d955516026 (patch) | |
tree | de087126d87a42118b0b0d1f2ec460c9eb6fa133 /dhcp6s.c | |
parent | e137e82e0a14b4b60f165b2621a25fbc8c040c2c (diff) |
supported IA-NA address-pool
ToDo: IA-PD prefix-pool, write a manual
Diffstat (limited to 'dhcp6s.c')
-rw-r--r-- | dhcp6s.c | 175 |
1 files changed, 175 insertions, 0 deletions
@@ -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); } |