Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

upgraded base spec of DHCPv6 and dhcpv6-pd according to the latest dr…

…afts.

backward compatibility was (basically) not provided.
  • Loading branch information...
commit 5042e9e46ae522496da297937910d8597aa4850b 1 parent cb9ecde
jinmei authored
7 kame/kame/dhcp6/Makefile.in
View
@@ -1,5 +1,5 @@
#
-# $Id: Makefile.in,v 1.17 2002/12/29 01:08:05 jinmei Exp $
+# $Id: Makefile.in,v 1.18 2003/01/05 17:12:12 jinmei Exp $
#
srcdir= @srcdir@
@@ -24,10 +24,11 @@ CFLAGS+= -DCONF_DH6OPT_DNS=@dhcpopt_dns@ \
-DCONF_DH6OPT_PREFIX_INFORMATION=@dhcpopt_pinfo@ \
-DCONF_DH6OPT_PREFIX_REQUEST=@dhcpopt_preq@ \
-DCONF_DH6OPT_IA_PD=@dhcpopt_ia_pd@ \
- -DCONF_DH6OPT_IA_PD_PREFIX=@dhcpopt_ia_pd_prefix@
+ -DCONF_DH6OPT_IA_PD_PREFIX=@dhcpopt_ia_pd_prefix@ \
+ -DCONF_DH6OPT_STCODE_NOPREFIXAVAIL=@dhcpstcode_no_prefix@
GENSRCS=cfparse.c cftoken.c
-CLIENTOBJS= dhcp6c.o common.o config.o prefixconf.o timer.o \
+CLIENTOBJS= dhcp6c.o common.o config.o prefixconf.o dhcp6c_ia.o timer.o \
$(GENSRCS:%.c=%.o)
SERVOBJS= dhcp6s.o common.o config.o timer.o $(GENSRCS:%.c=%.o)
RELAYOBJS = dhcp6relay.o common.o
220 kame/kame/dhcp6/cfparse.y
View
@@ -1,4 +1,4 @@
-/* $KAME: cfparse.y,v 1.16 2002/09/24 14:20:49 itojun Exp $ */
+/* $KAME: cfparse.y,v 1.17 2003/01/05 17:12:12 jinmei Exp $ */
/*
* Copyright (C) 2002 WIDE Project.
@@ -37,6 +37,8 @@
#include <arpa/inet.h>
+#include <string.h>
+
#include "dhcp6.h"
#include "config.h"
#include "common.h"
@@ -77,7 +79,8 @@ extern void yyerror __P((char *, ...))
l->list = (pl); \
} while (0)
-static struct cf_namelist *iflist_head, *piflist_head, *hostlist_head;
+static struct cf_namelist *iflist_head, *piflist_head, *hostlist_head,
+ *iapdlist_head;
struct cf_list *cf_dns_list;
extern int yylex __P((void));
@@ -88,9 +91,10 @@ static void cleanup_cflist __P((struct cf_list *));
%token INTERFACE IFNAME
%token PREFIX_INTERFACE SLA_ID SLA_LEN DUID_ID
+%token ID_ASSOC IA_PD IAID
%token REQUEST SEND ALLOW PREFERENCE
%token HOST HOSTNAME DUID
-%token OPTION RAPID_COMMIT PREFIX_DELEGATION DNS_SERVERS
+%token OPTION RAPID_COMMIT PREFIX_DELEGATION IA_PD DNS_SERVERS
%token INFO_ONLY
%token NUMBER SLASH EOS BCL ECL STRING PREFIX INFINITY
%token COMMA
@@ -102,10 +106,11 @@ static void cleanup_cflist __P((struct cf_list *));
struct dhcp6_prefix *prefix;
}
-%type <str> IFNAME HOSTNAME DUID_ID STRING
+%type <str> IFNAME HOSTNAME DUID_ID STRING IAID
%type <num> NUMBER duration
%type <list> declaration declarations dhcpoption ifparam ifparams
%type <list> address_list address_list_ent
+%type <list> iaconf_list iaconf prefix_interface
%type <prefix> prefixparam
%%
@@ -116,9 +121,9 @@ statements:
statement:
interface_statement
- | prefix_interface_statement
| host_statement
| option_statement
+ | ia_statement
;
interface_statement:
@@ -133,18 +138,6 @@ interface_statement:
}
;
-prefix_interface_statement:
- PREFIX_INTERFACE IFNAME BCL ifparams ECL EOS
- {
- struct cf_namelist *ifl;
-
- MAKE_NAMELIST(ifl, $2, $4);
-
- if (add_namelist(ifl, &piflist_head))
- return (-1);
- }
- ;
-
host_statement:
HOST HOSTNAME BCL declarations ECL EOS
{
@@ -169,6 +162,32 @@ option_statement:
}
;
+ia_statement:
+ ID_ASSOC IA_PD IAID BCL iaconf_list ECL EOS
+ {
+ struct cf_namelist *iapd;
+
+ MAKE_NAMELIST(iapd, $3, $5);
+
+ if (add_namelist(iapd, &iapdlist_head))
+ return (-1);
+ }
+ | ID_ASSOC IA_PD BCL iaconf_list ECL EOS
+ {
+ struct cf_namelist *iapd;
+ char *zero;
+
+ if ((zero = strdup("0")) == NULL) {
+ yywarn("can't allocate memory");
+ return (-1);
+ }
+ MAKE_NAMELIST(iapd, zero, $4);
+
+ if (add_namelist(iapd, &iapdlist_head))
+ return (-1);
+ }
+ ;
+
address_list:
{ $$ = NULL; }
| address_list address_list_ent
@@ -306,6 +325,14 @@ dhcpoption:
/* currently no value */
$$ = l;
}
+ | IA_PD NUMBER
+ {
+ struct cf_list *l;
+
+ MAKE_CFLIST(l, DHCPOPT_IA_PD, NULL, NULL);
+ l->num = $2;
+ $$ = l;
+ }
| DNS_SERVERS
{
struct cf_list *l;
@@ -316,6 +343,110 @@ dhcpoption:
}
;
+prefixparam:
+ STRING SLASH NUMBER duration
+ {
+ struct dhcp6_prefix pconf0, *pconf;
+
+ memset(&pconf0, 0, sizeof(pconf0));
+ if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
+ yywarn("invalid IPv6 address: %s", $1);
+ free($1);
+ return (-1);
+ }
+ free($1);
+ /* validate other parameters later */
+ pconf0.plen = $3;
+ if ($4 < 0)
+ pconf0.pltime = DHCP6_DURATITION_INFINITE;
+ else
+ pconf0.pltime = (u_int32_t)$4;
+ pconf0.vltime = pconf0.pltime;
+
+ if ((pconf = malloc(sizeof(*pconf))) == NULL) {
+ yywarn("can't allocate memory");
+ return (-1);
+ }
+ *pconf = pconf0;
+
+ $$ = pconf;
+ }
+ | STRING SLASH NUMBER duration duration
+ {
+ struct dhcp6_prefix pconf0, *pconf;
+
+ memset(&pconf0, 0, sizeof(pconf0));
+ if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
+ yywarn("invalid IPv6 address: %s", $1);
+ free($1);
+ return (-1);
+ }
+ free($1);
+ /* validate other parameters later */
+ pconf0.plen = $3;
+ if ($4 < 0)
+ pconf0.pltime = DHCP6_DURATITION_INFINITE;
+ else
+ pconf0.pltime = (u_int32_t)$4;
+ if ($5 < 0)
+ pconf0.vltime = DHCP6_DURATITION_INFINITE;
+ else
+ pconf0.vltime = (u_int32_t)$5;
+
+ if ((pconf = malloc(sizeof(*pconf))) == NULL) {
+ yywarn("can't allocate memory");
+ return (-1);
+ }
+ *pconf = pconf0;
+
+ $$ = pconf;
+ }
+
+
+duration:
+ INFINITY
+ {
+ $$ = -1;
+ }
+ | NUMBER
+ {
+ $$ = $1;
+ }
+ ;
+
+iaconf_list:
+ { $$ = NULL; }
+ | iaconf_list iaconf
+ {
+ struct cf_list *head;
+
+ if ((head = $1) == NULL) {
+ $2->next = NULL;
+ $2->tail = $2;
+ head = $2;
+ } else {
+ head->tail->next = $2;
+ head->tail = $2;
+ }
+
+ $$ = head;
+ }
+ ;
+
+iaconf:
+ prefix_interface { $$ = $1; }
+ ;
+
+prefix_interface:
+ PREFIX_INTERFACE IFNAME BCL ifparams ECL EOS
+ {
+ struct cf_list *ifl;
+
+ MAKE_CFLIST(ifl, IACONF_PIF, $2, $4);
+ $$ = ifl;
+ }
+ ;
+
ifparams:
{ $$ = NULL; }
| ifparams ifparam
@@ -354,57 +485,18 @@ ifparam:
}
;
-prefixparam:
- STRING SLASH NUMBER duration
- {
- struct dhcp6_prefix pconf0, *pconf;
-
- memset(&pconf0, 0, sizeof(pconf0));
- if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
- yywarn("invalid IPv6 address: %s", $1);
- free($1);
- return (-1);
- }
- free($1);
- /* validate other parameters later */
- pconf0.plen = $3;
- if ($4 < 0)
- pconf0.duration = DHCP6_DURATITION_INFINITE;
- else
- pconf0.duration = (u_int32_t)$4;
-
- if ((pconf = malloc(sizeof(*pconf))) == NULL) {
- yywarn("can't allocate memory");
- return (-1);
- }
- *pconf = pconf0;
-
- $$ = pconf;
- }
-
-duration:
- INFINITY
- {
- $$ = -1;
- }
- | NUMBER
- {
- $$ = $1;
- }
- ;
-
%%
/* supplement routines for configuration */
static int
add_namelist(new, headp)
struct cf_namelist *new, **headp;
{
- struct cf_namelist *ifp;
-
+ struct cf_namelist *n;
+
/* check for duplicated configuration */
- for (ifp = *headp; ifp; ifp = ifp->next) {
- if (strcmp(ifp->name, new->name) == 0) {
- yywarn("duplicated interface: %s (ignored)",
+ for (n = *headp; n; n = n->next) {
+ if (strcmp(n->name, new->name) == 0) {
+ yywarn("duplicated name: %s (ignored)",
new->name);
cleanup_namelist(new);
return (0);
@@ -422,8 +514,8 @@ static void
cleanup()
{
cleanup_namelist(iflist_head);
- cleanup_namelist(piflist_head);
cleanup_namelist(hostlist_head);
+ cleanup_namelist(iapdlist_head);
cleanup_cflist(cf_dns_list);
}
@@ -467,10 +559,10 @@ cleanup_cflist(p)
int
cf_post_config()
{
- if (configure_interface(iflist_head))
+ if (configure_ia(iapdlist_head, IATYPE_PD))
config_fail();
- if (configure_prefix_interface(piflist_head))
+ if (configure_interface(iflist_head))
config_fail();
if (configure_host(hostlist_head))
16 kame/kame/dhcp6/cftoken.l
View
@@ -1,4 +1,4 @@
-/* $KAME: cftoken.l,v 1.15 2002/09/24 14:20:49 itojun Exp $ */
+/* $KAME: cftoken.l,v 1.16 2003/01/05 17:12:12 jinmei Exp $ */
%{
/*
@@ -93,6 +93,7 @@ ecl \}
%s S_PREF
%s S_HOST
%s S_DUID
+%s S_IA
%%
%{
@@ -142,6 +143,7 @@ ecl \}
<S_CNF>rapid-commit { DECHO; return (RAPID_COMMIT); }
<S_CNF>prefix-delegation { DECHO; return (PREFIX_DELEGATION); }
+<S_CNF>ia-pd { DECHO; return (IA_PD); }
<S_CNF>domain-name-servers { DECHO; return (DNS_SERVERS); }
/* generic options */
@@ -149,7 +151,17 @@ ecl \}
<S_CNF>allow { DECHO; return (ALLOW); }
- /* interface parameters for delegated prefix configuration */
+ /* identity association */
+<S_CNF>id-assoc { DECHO; BEGIN S_IA; return(ID_ASSOC); }
+<S_IA>pd { DECHO; return(IA_PD); }
+<S_IA>{number} { DECHO; yylval.str = strdup(yytext); return(IAID); }
+<S_IA>{bcl} { DP("begin of closure"); BEGIN S_CNF; return (BCL); }
+
+ /*
+ * interface parameters for delegated prefix configuration.
+ * when lex reads an interface name, the state will be back to
+ * S_CNF.
+ */
<S_CNF>prefix-interface { DECHO; BEGIN S_IFACE; return (PREFIX_INTERFACE); }
<S_CNF>sla-id { DECHO; return (SLA_ID); }
<S_CNF>sla-len { DECHO; return (SLA_LEN); }
502 kame/kame/dhcp6/common.c
View
@@ -1,4 +1,4 @@
-/* $KAME: common.c,v 1.68 2002/12/29 00:54:48 jinmei Exp $ */
+/* $KAME: common.c,v 1.69 2003/01/05 17:12:12 jinmei Exp $ */
/*
* Copyright (C) 1998 and 1999 WIDE Project.
* All rights reserved.
@@ -82,7 +82,11 @@ int debug_thresh;
#if 0
static unsigned int if_maxindex __P((void));
#endif
+static int dhcp6_count_list __P((struct dhcp6_list *));
static int in6_matchflags __P((struct sockaddr *, char *, int));
+static int copyout_option __P((char *, char *, struct dhcp6_listval *));
+static int copyin_option __P((int, struct dhcp6opt *, struct dhcp6opt *,
+ struct dhcp6_list *));
static ssize_t gethwid __P((char *, int, const char *, u_int16_t *));
static int get_delegated_prefixes __P((char *, char *,
struct dhcp6_optinfo *));
@@ -91,16 +95,12 @@ int
dhcp6_copy_list(dst, src)
struct dhcp6_list *dst, *src;
{
- struct dhcp6_listval *ent, *dent;
+ struct dhcp6_listval *ent;
for (ent = TAILQ_FIRST(src); ent; ent = TAILQ_NEXT(ent, link)) {
- if ((dent = malloc(sizeof(*dent))) == NULL)
+ if (dhcp6_add_listval(dst, ent->type,
+ &ent->uv, &ent->sublist) == NULL)
goto fail;
-
- memset(dent, 0, sizeof(*dent));
- memcpy(&dent->uv, &ent->uv, sizeof(ent->uv));
-
- TAILQ_INSERT_TAIL(dst, dent, link);
}
return (0);
@@ -118,13 +118,13 @@ dhcp6_clear_list(head)
while ((v = TAILQ_FIRST(head)) != NULL) {
TAILQ_REMOVE(head, v, link);
- free(v);
+ dhcp6_clear_listval(v);
}
return;
}
-int
+static int
dhcp6_count_list(head)
struct dhcp6_list *head;
{
@@ -137,20 +137,40 @@ dhcp6_count_list(head)
return (i);
}
+void
+dhcp6_clear_listval(lv)
+ struct dhcp6_listval *lv;
+{
+ dhcp6_clear_list(&lv->sublist);
+ free(lv);
+}
+
+/*
+ * Note: this function only searches for the first entry that matches
+ * VAL. It also does not care about sublists.
+ */
struct dhcp6_listval *
-dhcp6_find_listval(head, val, type)
+dhcp6_find_listval(head, type, val, option)
struct dhcp6_list *head;
- void *val;
dhcp6_listval_type_t type;
+ void *val;
+ int option;
{
struct dhcp6_listval *lv;
for (lv = TAILQ_FIRST(head); lv; lv = TAILQ_NEXT(lv, link)) {
+ if (lv->type != type)
+ continue;
+
switch(type) {
case DHCP6_LISTVAL_NUM:
if (lv->val_num == *(int *)val)
return (lv);
break;
+ case DHCP6_LISTVAL_STCODE:
+ if (lv->val_num16 == *(u_int16_t *)val)
+ return (lv);
+ break;
case DHCP6_LISTVAL_ADDR6:
if (IN6_ARE_ADDR_EQUAL(&lv->val_addr6,
(struct in6_addr *)val)) {
@@ -158,13 +178,23 @@ dhcp6_find_listval(head, val, type)
}
break;
case DHCP6_LISTVAL_PREFIX6:
- if (IN6_ARE_ADDR_EQUAL(&lv->val_prefix6.addr,
+ if ((option & MATCHLIST_PREFIXLEN) &&
+ lv->val_prefix6.plen ==
+ ((struct dhcp6_prefix *)val)->plen) {
+ return (lv);
+ } else if (IN6_ARE_ADDR_EQUAL(&lv->val_prefix6.addr,
&((struct dhcp6_prefix *)val)->addr) &&
lv->val_prefix6.plen ==
((struct dhcp6_prefix *)val)->plen) {
return (lv);
}
break;
+ case DHCP6_LISTVAL_IAPD:
+ if (lv->val_ia.iaid ==
+ ((struct dhcp6_ia *)val)->iaid) {
+ return (lv);
+ }
+ break;
}
}
@@ -172,39 +202,56 @@ dhcp6_find_listval(head, val, type)
}
struct dhcp6_listval *
-dhcp6_add_listval(head, val, type)
- struct dhcp6_list *head;
- void *val;
+dhcp6_add_listval(head, type, val, sublist)
+ struct dhcp6_list *head, *sublist;
dhcp6_listval_type_t type;
+ void *val;
{
- struct dhcp6_listval *lv;
+ struct dhcp6_listval *lv = NULL;
if ((lv = malloc(sizeof(*lv))) == NULL) {
dprintf(LOG_ERR, "%s" "failed to allocate memory for list "
"entry", FNAME);
- return (NULL);
+ goto fail;
}
memset(lv, 0, sizeof(*lv));
+ lv->type = type;
+ TAILQ_INIT(&lv->sublist);
switch(type) {
case DHCP6_LISTVAL_NUM:
lv->val_num = *(int *)val;
break;
+ case DHCP6_LISTVAL_STCODE:
+ lv->val_num16 = *(u_int16_t *)val;
+ break;
case DHCP6_LISTVAL_ADDR6:
lv->val_addr6 = *(struct in6_addr *)val;
break;
case DHCP6_LISTVAL_PREFIX6:
lv->val_prefix6 = *(struct dhcp6_prefix *)val;
break;
+ case DHCP6_LISTVAL_IAPD:
+ lv->val_ia = *(struct dhcp6_ia *)val;
+ break;
default:
dprintf(LOG_ERR, "%s" "unexpected list value type (%d)",
FNAME, type);
- exit(1);
+ goto fail;
}
+ if (sublist && dhcp6_copy_list(&lv->sublist, sublist))
+ goto fail;
+
TAILQ_INSERT_TAIL(head, lv, link);
return (lv);
+
+ fail:
+ if (lv)
+ free(lv);
+
+ return (NULL);
}
struct dhcp6_event *
@@ -219,6 +266,7 @@ dhcp6_create_event(ifp, state)
FNAME);
return (NULL);
}
+ memset(ev, 0, sizeof(*ev));
ev->ifp = ifp;
ev->state = state;
TAILQ_INIT(&ev->data_list);
@@ -230,13 +278,18 @@ void
dhcp6_remove_event(ev)
struct dhcp6_event *ev;
{
+ struct dhcp6_eventdata *evd, *evd_next;
+
dprintf(LOG_DEBUG, "%s" "removing an event on %s, state=%d", FNAME,
ev->ifp->ifname, ev->state);
- if (!TAILQ_EMPTY(&ev->data_list)) {
- dprintf(LOG_ERR, "%s" "assumption failure: "
- "event data list is not empty", FNAME);
- exit(1);
+ for (evd = TAILQ_FIRST(&ev->data_list); evd; evd = evd_next) {
+ evd_next = TAILQ_NEXT(evd, link);
+ TAILQ_REMOVE(&ev->data_list, evd, link);
+ if (evd->destructor)
+ (*evd->destructor)(evd);
+ else
+ free(evd);
}
duidfree(&ev->serverid);
@@ -567,7 +620,7 @@ get_duid(idfile, duid)
{
FILE *fp = NULL;
u_int16_t len = 0, hwtype;
- struct dhcp6_duid_type1 *dp; /* we only support the type1 DUID */
+ struct dhcp6opt_duid_type1 *dp; /* we only support the type1 DUID */
char tmpbuf[256]; /* DUID should be no more than 256 bytes */
if ((fp = fopen(idfile, "r")) == NULL && errno != ENOENT)
@@ -588,7 +641,7 @@ get_duid(idfile, duid)
"failed to get a hardware address", FNAME);
goto fail;
}
- len = l + sizeof(struct dhcp6_duid_type1);
+ len = l + sizeof(struct dhcp6opt_duid_type1);
}
memset(duid, 0, sizeof(*duid));
@@ -611,12 +664,12 @@ get_duid(idfile, duid)
} else {
u_int64_t t64;
- dp = (struct dhcp6_duid_type1 *)duid->duid_id;
- dp->dh6duid1_type = htons(1); /* type 1 */
- dp->dh6duid1_hwtype = htons(hwtype);
+ dp = (struct dhcp6opt_duid_type1 *)duid->duid_id;
+ dp->dh6_duid1_type = htons(1); /* type 1 */
+ dp->dh6_duid1_hwtype = htons(hwtype);
/* time is Jan 1, 2000 (UTC), modulo 2^32 */
t64 = (u_int64_t)(time(NULL) - 946684800);
- dp->dh6duid1_time = htonl((u_long)(t64 & 0xffffffff));
+ dp->dh6_duid1_time = htonl((u_long)(t64 & 0xffffffff));
memcpy((void *)(dp + 1), tmpbuf, (len - sizeof(*dp)));
dprintf(LOG_DEBUG, "%s" "generated a new DUID: %s", FNAME,
@@ -715,6 +768,7 @@ dhcp6_init_options(optinfo)
optinfo->pref = DH6OPT_PREF_UNDEF;
+ TAILQ_INIT(&optinfo->iapd_list);
TAILQ_INIT(&optinfo->reqopt_list);
TAILQ_INIT(&optinfo->stcode_list);
TAILQ_INIT(&optinfo->dns_list);
@@ -729,6 +783,7 @@ dhcp6_clear_options(optinfo)
duidfree(&optinfo->clientID);
duidfree(&optinfo->serverID);
+ dhcp6_clear_list(&optinfo->iapd_list);
dhcp6_clear_list(&optinfo->reqopt_list);
dhcp6_clear_list(&optinfo->stcode_list);
dhcp6_clear_list(&optinfo->dns_list);
@@ -747,6 +802,8 @@ dhcp6_copy_options(dst, src)
goto fail;
dst->rapidcommit = src->rapidcommit;
+ if (dhcp6_copy_list(&dst->iapd_list, &src->iapd_list))
+ goto fail;
if (dhcp6_copy_list(&dst->reqopt_list, &src->reqopt_list))
goto fail;
if (dhcp6_copy_list(&dst->stcode_list, &src->stcode_list))
@@ -771,9 +828,13 @@ dhcp6_get_options(p, ep, optinfo)
struct dhcp6_optinfo *optinfo;
{
struct dhcp6opt *np, opth;
- int i, opt, optlen, reqopts, num;
+ int i, opt, optlen, reqopts;
+ u_int16_t num;
char *cp, *val;
u_int16_t val16;
+ struct dhcp6opt_ia optia;
+ struct dhcp6_ia ia;
+ struct dhcp6_list sublist;
for (; p + 1 <= ep; p = np) {
struct duid duid0;
@@ -835,7 +896,7 @@ dhcp6_get_options(p, ep, optinfo)
/* need to check duplication? */
if (dhcp6_add_listval(&optinfo->stcode_list,
- &num, DHCP6_LISTVAL_NUM) == NULL) {
+ DHCP6_LISTVAL_STCODE, &num, NULL) == NULL) {
dprintf(LOG_ERR, "%s" "failed to copy "
"status code", FNAME);
goto fail;
@@ -857,7 +918,7 @@ dhcp6_get_options(p, ep, optinfo)
dhcp6optstr(num));
if (dhcp6_find_listval(&optinfo->reqopt_list,
- &num, DHCP6_LISTVAL_NUM)) {
+ DHCP6_LISTVAL_NUM, &num, 0)) {
dprintf(LOG_INFO, "%s" "duplicated "
"option type (%s)", FNAME,
dhcp6optstr(opttype));
@@ -865,7 +926,7 @@ dhcp6_get_options(p, ep, optinfo)
}
if (dhcp6_add_listval(&optinfo->reqopt_list,
- &num, DHCP6_LISTVAL_NUM) == NULL) {
+ DHCP6_LISTVAL_NUM, &num, NULL) == NULL) {
dprintf(LOG_ERR, "%s" "failed to copy "
"requested option", FNAME);
goto fail;
@@ -889,7 +950,7 @@ dhcp6_get_options(p, ep, optinfo)
for (val = cp; val < cp + optlen;
val += sizeof(struct in6_addr)) {
if (dhcp6_find_listval(&optinfo->dns_list,
- &num, DHCP6_LISTVAL_ADDR6)) {
+ DHCP6_LISTVAL_ADDR6, &num, 0)) {
dprintf(LOG_INFO, "%s" "duplicated "
"DNS address (%s)", FNAME,
in6addr2str((struct in6_addr *)val,
@@ -898,7 +959,7 @@ dhcp6_get_options(p, ep, optinfo)
}
if (dhcp6_add_listval(&optinfo->dns_list,
- val, DHCP6_LISTVAL_ADDR6) == NULL) {
+ DHCP6_LISTVAL_ADDR6, val, NULL) == NULL) {
dprintf(LOG_ERR, "%s" "failed to copy "
"DNS address", FNAME);
goto fail;
@@ -906,6 +967,43 @@ dhcp6_get_options(p, ep, optinfo)
nextdns:
}
break;
+ case DH6OPT_IA_PD:
+ if (optlen + sizeof(struct dhcp6opt) <
+ sizeof(optia))
+ goto malformed;
+ memcpy(&optia, p, sizeof(optia));
+ ia.iaid = ntohl(optia.dh6_ia_iaid);
+ ia.t1 = ntohl(optia.dh6_ia_t1);
+ ia.t2 = ntohl(optia.dh6_ia_t2);
+
+ dprintf(LOG_DEBUG, " IA_PD: ID=%lu, T1=%lu, T2=%lu",
+ ia.iaid, ia.t1, ia.t2);
+
+ /* duplication check */
+ if (dhcp6_find_listval(&optinfo->iapd_list,
+ DHCP6_LISTVAL_IAPD, &ia, 0)) {
+ dprintf(LOG_INFO, "%s" "duplicated IA_PD %lu",
+ FNAME, ia.iaid);
+ break; /* ignore this IA_PD */
+ }
+
+ /* take care of sub-options */
+ TAILQ_INIT(&sublist);
+ if (copyin_option(opt,
+ (struct dhcp6opt *)((char *)p + sizeof(optia)),
+ (struct dhcp6opt *)(cp + optlen), &sublist)) {
+ goto fail;
+ }
+
+ /* link this option set */
+ if (dhcp6_add_listval(&optinfo->iapd_list,
+ DHCP6_LISTVAL_IAPD, &ia, &sublist) == NULL) {
+ dhcp6_clear_list(&sublist);
+ goto fail;
+ }
+ dhcp6_clear_list(&sublist);
+
+ break;
case DH6OPT_PREFIX_DELEGATION:
if (get_delegated_prefixes(cp, cp + optlen, optinfo))
goto fail;
@@ -930,13 +1028,156 @@ dhcp6_get_options(p, ep, optinfo)
}
static int
+copyin_option(type, p, ep, list)
+ int type;
+ struct dhcp6opt *p, *ep;
+ struct dhcp6_list *list;
+{
+ int opt, optlen;
+ char *cp;
+ struct dhcp6opt *np, opth;
+ struct dhcp6opt_stcode opt_stcode;
+ struct dhcp6opt_ia_pd_prefix opt_iapd_prefix;
+ struct dhcp6_prefix iapd_prefix;
+ struct dhcp6_list sublist;
+
+ TAILQ_INIT(&sublist);
+
+ for (; p + 1 <= ep; p = np) {
+ memcpy(&opth, p, sizeof(opth));
+ optlen = ntohs(opth.dh6opt_len);
+ opt = ntohs(opth.dh6opt_type);
+
+ cp = (char *)(p + 1);
+ np = (struct dhcp6opt *)(cp + optlen);
+
+ dprintf(LOG_DEBUG, "%s" "get DHCP option %s, len %d",
+ FNAME, dhcp6optstr(opt), optlen);
+
+ if (np > ep) {
+ dprintf(LOG_INFO, "%s" "malformed DHCP option", FNAME);
+ goto fail;
+ }
+
+ switch (opt) {
+ case DH6OPT_IA_PD_PREFIX:
+ /* check option context */
+ if (type != DH6OPT_IA_PD) {
+ dprintf(LOG_INFO, "%s"
+ "%s is an invalid position for %s", FNAME,
+ dhcp6optstr(type), dhcp6optstr(opt));
+ goto nextoption; /* or discard the message? */
+ }
+ /* check option length */
+ if (optlen + sizeof(opth) < sizeof(opt_iapd_prefix))
+ goto malformed;
+
+ /* copy and convert option values */
+ memcpy(&opt_iapd_prefix, p, sizeof(opt_iapd_prefix));
+ if (opt_iapd_prefix.dh6_iapd_prefix_prefix_len > 128) {
+ dprintf(LOG_INFO, "%s" "invalid prefix length "
+ "(%d)", FNAME,
+ opt_iapd_prefix.dh6_iapd_prefix_prefix_len);
+ goto malformed;
+ }
+ iapd_prefix.pltime = ntohl(opt_iapd_prefix.dh6_iapd_prefix_preferred_time);
+ iapd_prefix.vltime = ntohl(opt_iapd_prefix.dh6_iapd_prefix_valid_time);
+ iapd_prefix.plen =
+ opt_iapd_prefix.dh6_iapd_prefix_prefix_len;
+ memcpy(&iapd_prefix.addr,
+ &opt_iapd_prefix.dh6_iapd_prefix_prefix_addr,
+ sizeof(iapd_prefix.addr));
+ /* clear padding bits in the prefix address */
+ prefix6_mask(&iapd_prefix.addr, iapd_prefix.plen);
+
+ dprintf(LOG_DEBUG, " IA_PD prefix: "
+ "%s/%d pltime=%lu vltime=%lu",
+ in6addr2str(&iapd_prefix.addr, 0),
+ iapd_prefix.plen,
+ iapd_prefix.pltime, iapd_prefix.vltime);
+
+ if (dhcp6_find_listval(list, DHCP6_LISTVAL_PREFIX6,
+ &iapd_prefix, 0)) {
+ dprintf(LOG_INFO, "%s" "duplicated IA_PD "
+ "prefix %s/%d", FNAME,
+ iapd_prefix.pltime, iapd_prefix.vltime);
+ goto nextoption;
+ }
+
+ /* take care of sub-options */
+ TAILQ_INIT(&sublist);
+ if (copyin_option(opt,
+ (struct dhcp6opt *)(char *)p +
+ sizeof(opt_iapd_prefix),
+ ep, &sublist)) {
+ goto fail;
+ }
+
+ if (dhcp6_add_listval(list, DHCP6_LISTVAL_PREFIX6,
+ &iapd_prefix, &sublist) == NULL) {
+ dhcp6_clear_list(&sublist);
+ goto fail;
+ }
+ dhcp6_clear_list(&sublist);
+ break;
+ case DH6OPT_STATUS_CODE:
+ /* check option context */
+ if (type != DH6OPT_IA_PD &&
+ type != DH6OPT_IA_PD_PREFIX) {
+ dprintf(LOG_INFO, "%s"
+ "%s is an invalid position for %s", FNAME,
+ dhcp6optstr(type), dhcp6optstr(opt));
+ goto nextoption; /* or discard the message? */
+ }
+ /* check option length */
+ if (optlen + sizeof(opth) < sizeof(opt_stcode))
+ goto malformed;
+
+ /* copy and convert option values */
+ memcpy(&opt_stcode, p, sizeof(opt_stcode));
+ opt_stcode.dh6_stcode_code =
+ ntohs(opt_stcode.dh6_stcode_code);
+
+ dprintf(LOG_DEBUG, " status code: %s",
+ dhcp6_stcodestr(opt_stcode.dh6_stcode_code));
+
+ /* duplication check */
+ if (dhcp6_find_listval(list, DHCP6_LISTVAL_STCODE,
+ &opt_stcode.dh6_stcode_code, 0)) {
+ dprintf(LOG_INFO, "%s"
+ "duplicated status code (%d)", FNAME,
+ opt_stcode.dh6_stcode_code);
+ goto nextoption;
+ }
+
+ /* copy-in the code value */
+ if (dhcp6_add_listval(list, DHCP6_LISTVAL_STCODE,
+ &opt_stcode.dh6_stcode_code, NULL) == NULL)
+ goto fail;
+
+ break;
+ }
+ nextoption:
+ }
+
+ return (0);
+
+ malformed:
+ dprintf(LOG_INFO, " malformed DHCP option: type %d", opt);
+
+ fail:
+ dhcp6_clear_list(&sublist);
+ return (-1);
+}
+
+static int
get_delegated_prefixes(p, ep, optinfo)
char *p, *ep;
struct dhcp6_optinfo *optinfo;
{
char *np, *cp;
struct dhcp6opt opth;
- struct dhcp6_prefix_info pi;
+ struct dhcp6opt_prefix_info pi;
struct dhcp6_prefix prefix;
int optlen, opt;
@@ -977,13 +1218,15 @@ get_delegated_prefixes(p, ep, optinfo)
memset(&prefix, 0, sizeof(prefix));
prefix.addr = pi.dh6_pi_paddr;
prefix.plen = pi.dh6_pi_plen;
- prefix.duration = ntohl(pi.dh6_pi_duration);
+ /* XXX */
+ prefix.vltime = ntohl(pi.dh6_pi_duration);
+ prefix.pltime = ntohl(pi.dh6_pi_duration);
- if (prefix.duration != DHCP6_DURATITION_INFINITE) {
+ if (prefix.vltime != DHCP6_DURATITION_INFINITE) {
dprintf(LOG_DEBUG, " prefix information: "
- "%s/%d duration %ld",
+ "%s/%d duration %lu",
in6addr2str(&prefix.addr, 0),
- prefix.plen, prefix.duration);
+ prefix.plen, prefix.vltime);
} else {
dprintf(LOG_DEBUG, " prefix information: "
"%s/%d duration infinity",
@@ -992,7 +1235,7 @@ get_delegated_prefixes(p, ep, optinfo)
}
if (dhcp6_find_listval(&optinfo->prefix_list,
- &prefix, DHCP6_LISTVAL_PREFIX6)) {
+ DHCP6_LISTVAL_PREFIX6, &prefix, 0)) {
dprintf(LOG_INFO, "%s" "duplicated "
"prefix (%s/%d)", FNAME,
in6addr2str(&prefix.addr, 0),
@@ -1000,8 +1243,8 @@ get_delegated_prefixes(p, ep, optinfo)
goto nextoption;
}
- if (dhcp6_add_listval(&optinfo->prefix_list, &prefix,
- DHCP6_LISTVAL_PREFIX6) == NULL) {
+ if (dhcp6_add_listval(&optinfo->prefix_list,
+ DHCP6_LISTVAL_PREFIX6, &prefix, NULL) == NULL) {
dprintf(LOG_ERR, "%s" "failed to copy a "
"prefix", FNAME);
goto fail;
@@ -1042,7 +1285,7 @@ dhcp6_set_options(bp, ep, optinfo)
struct dhcp6_optinfo *optinfo;
{
struct dhcp6opt *p = bp, opth;
- struct dhcp6_listval *stcode;
+ struct dhcp6_listval *stcode, *op;
int len = 0, optlen;
char *tmpbuf = NULL;
@@ -1115,14 +1358,44 @@ dhcp6_set_options(bp, ep, optinfo)
free(tmpbuf);
}
+ for (op = TAILQ_FIRST(&optinfo->iapd_list); op;
+ op = TAILQ_NEXT(op, link)) {
+ int optlen;
+
+ tmpbuf = NULL;
+ if ((optlen = copyout_option(NULL, NULL, op)) < 0) {
+ dprintf(LOG_INFO, "%s" "failed to count option length",
+ FNAME);
+ goto fail;
+ }
+ if ((void *)ep - (void *)p < optlen) {
+ dprintf(LOG_INFO, "%s" "short buffer", FNAME);
+ goto fail;
+ }
+ if ((tmpbuf = malloc(optlen)) == NULL) {
+ dprintf(LOG_NOTICE, "%s"
+ "memory allocation failed for DNS options", FNAME);
+ goto fail;
+ }
+ if (copyout_option(tmpbuf, tmpbuf + optlen, op) < 0) {
+ dprintf(LOG_ERR, "%s"
+ "failed to construct an option", FNAME);
+ goto fail;
+ }
+ memcpy(p, tmpbuf, optlen);
+ free(tmpbuf);
+ p = (struct dhcp6opt *)((char *)p + optlen);
+ len += optlen;
+ }
+
if (!TAILQ_EMPTY(&optinfo->prefix_list)) {
char *tp;
struct dhcp6_listval *dp;
- struct dhcp6_prefix_info pi;
+ struct dhcp6opt_prefix_info pi;
tmpbuf = NULL;
optlen = dhcp6_count_list(&optinfo->prefix_list) *
- sizeof(struct dhcp6_prefix_info);
+ sizeof(struct dhcp6opt_prefix_info);
if ((tmpbuf = malloc(optlen)) == NULL) {
dprintf(LOG_ERR, "%s"
"memory allocation failed for options", FNAME);
@@ -1137,7 +1410,7 @@ dhcp6_set_options(bp, ep, optinfo)
memset(&pi, 0, sizeof(pi));
pi.dh6_pi_type = htons(DH6OPT_PREFIX_INFORMATION);
pi.dh6_pi_len = htons(sizeof(pi) - 4);
- pi.dh6_pi_duration = htonl(dp->val_prefix6.duration);
+ pi.dh6_pi_duration = htonl(dp->val_prefix6.vltime);
pi.dh6_pi_plen = dp->val_prefix6.plen;
memcpy(&pi.dh6_pi_paddr, &dp->val_prefix6.addr,
sizeof(struct in6_addr));
@@ -1156,6 +1429,122 @@ dhcp6_set_options(bp, ep, optinfo)
}
#undef COPY_OPTION
+/*
+ * Construct a DHCPv6 option along with sub-options in the wire format.
+ * If the packet buffer is NULL, just calculate the length of the option
+ * (and sub-options) so that the caller can allocate a buffer to store the
+ * option(s).
+ * This function basically assumes that the caller prepares enough buffer to
+ * store all the options. However, it also takes the buffer end and checks
+ * the possibility of overrun for safety.
+ */
+static int
+copyout_option(p, ep, optval)
+ char *p, *ep;
+ struct dhcp6_listval *optval;
+{
+ struct dhcp6opt *opt;
+ struct dhcp6opt_stcode stcodeopt;
+ struct dhcp6opt_ia ia;
+ struct dhcp6opt_ia_pd_prefix pd_prefix;
+ char *subp;
+ struct dhcp6_listval *subov;
+ int optlen, headlen, sublen, opttype;
+
+ /* check invariant for safety */
+ if (p && ep <= p)
+ return (-1);
+
+ /* first, detect the length of the option head */
+ switch(optval->type) {
+ case DHCP6_LISTVAL_IAPD:
+ memset(&ia, 0, sizeof(ia));
+ headlen = sizeof(ia);
+ opttype = DH6OPT_IA_PD;
+ opt = (struct dhcp6opt *)&ia;
+ break;
+ case DHCP6_LISTVAL_PREFIX6:
+ memset(&pd_prefix, 0, sizeof(pd_prefix));
+ headlen = sizeof(pd_prefix);
+ opttype = DH6OPT_IA_PD_PREFIX;
+ opt = (struct dhcp6opt *)&pd_prefix;
+ break;
+ case DHCP6_LISTVAL_STCODE:
+ memset(&stcodeopt, 0, sizeof(stcodeopt));
+ headlen = sizeof(stcodeopt);
+ opttype = DH6OPT_STATUS_CODE;
+ opt = (struct dhcp6opt *)&stcodeopt;
+ break;
+ default:
+ /*
+ * we encounter an unknown option. this should be an internal
+ * error.
+ */
+ dprintf(LOG_ERR, "%s" "unknown option: code %d", FNAME,
+ optval->type);
+ return (-1);
+ }
+
+ /* then, calculate the length of and/or fill in the sub-options */
+ subp = NULL;
+ sublen = 0;
+ if (p)
+ subp = p + headlen;
+ for (subov = TAILQ_FIRST(&optval->sublist); subov;
+ subov = TAILQ_NEXT(subov, link)) {
+ int s;
+
+ if ((s = copyout_option(subp, ep, subov)) < 0)
+ return (-1);
+ sublen += s;
+ }
+
+ /* finally, deal with the head part again */
+ optlen = headlen + sublen;
+ if (!p)
+ return(optlen);
+
+ dprintf(LOG_DEBUG, "%s" "set %s", FNAME, dhcp6optstr(opttype));
+ if (ep - p < headlen) /* check it just in case */
+ return (-1);
+
+ /* fill in the common part */
+ opt->dh6opt_type = htons(opttype);
+ opt->dh6opt_len = htons(optlen - sizeof(struct dhcp6opt));
+
+ /* fill in type specific fields */
+ switch(optval->type) {
+ case DHCP6_LISTVAL_IAPD:
+ ia.dh6_ia_iaid = htonl(optval->val_ia.iaid);
+ ia.dh6_ia_t1 = htonl(optval->val_ia.t1);
+ ia.dh6_ia_t2 = htonl(optval->val_ia.t2);
+ break;
+ case DHCP6_LISTVAL_PREFIX6:
+ pd_prefix.dh6_iapd_prefix_preferred_time =
+ htonl(optval->val_prefix6.pltime);
+ pd_prefix.dh6_iapd_prefix_valid_time =
+ htonl(optval->val_prefix6.vltime);
+ pd_prefix.dh6_iapd_prefix_prefix_len =
+ optval->val_prefix6.plen;
+ pd_prefix.dh6_iapd_prefix_prefix_addr =
+ optval->val_prefix6.addr;
+ break;
+ case DHCP6_LISTVAL_STCODE:
+ stcodeopt.dh6_stcode_code = htons(optval->val_num16);
+ break;
+ default:
+ /*
+ * XXX: this case should be rejected at the beginning of this
+ * function.
+ */
+ return (-1);
+ }
+
+ /* copyout the data (p must be non NULL at this point) */
+ memcpy(p, opt, headlen);
+ return (optlen);
+}
+
void
dhcp6_set_timeoparam(ev)
struct dhcp6_event *ev;
@@ -1209,7 +1598,7 @@ dhcp6_reset_timer(ev)
* The first Solicit message from the client on the interface
* MUST be delayed by a random amount of time between
* MIN_SOL_DELAY and MAX_SOL_DELAY.
- * [dhcpv6-24 17.1.2]
+ * [dhcpv6-28 17.1.2]
*/
ev->retrans = (random() % (MAX_SOL_DELAY - MIN_SOL_DELAY)) +
MIN_SOL_DELAY;
@@ -1220,7 +1609,7 @@ dhcp6_reset_timer(ev)
* The first RT MUST be selected to be strictly
* greater than IRT by choosing RAND to be strictly
* greater than 0.
- * [dhcpv6-24 17.1.2]
+ * [dhcpv6-28 17.1.2]
*/
r = (double)((random() % 1000) + 1) / 10000;
n = ev->init_retrans + r * ev->init_retrans;
@@ -1304,6 +1693,7 @@ duidfree(duid)
{
if (duid->duid_id)
free(duid->duid_id);
+ duid->duid_id = NULL;
duid->duid_len = 0;
}
@@ -1335,6 +1725,10 @@ dhcp6optstr(type)
return ("prefix delegation");
case DH6OPT_PREFIX_INFORMATION:
return ("prefix information");
+ case DH6OPT_IA_PD:
+ return ("IA_PD");
+ case DH6OPT_IA_PD_PREFIX:
+ return ("IA_PD prefix");
default:
sprintf(genstr, "opt_%d", type);
return (genstr);
@@ -1375,7 +1769,7 @@ dhcp6msgstr(type)
char *
dhcp6_stcodestr(code)
- int code;
+ u_int16_t code;
{
static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */
@@ -1387,20 +1781,16 @@ dhcp6_stcodestr(code)
return ("success");
case DH6OPT_STCODE_UNSPECFAIL:
return ("unspec failure");
- case DH6OPT_STCODE_AUTHFAILED:
- return ("auth fail");
- case DH6OPT_STCODE_ADDRUNAVAIL:
- return ("address unavailable");
case DH6OPT_STCODE_NOADDRAVAIL:
return ("no addresses");
case DH6OPT_STCODE_NOBINDING:
return ("no binding");
- case DH6OPT_STCODE_CONFNOMATCH:
- return ("confirm no match");
case DH6OPT_STCODE_NOTONLINK:
return ("not on-link");
case DH6OPT_STCODE_USEMULTICAST:
return ("use multicast");
+ case DH6OPT_STCODE_NOPREFIXAVAIL:
+ return ("no prefixes");
default:
sprintf(genstr, "code%d", code);
return (genstr);
15 kame/kame/dhcp6/common.h
View
@@ -1,4 +1,4 @@
-/* $KAME: common.h,v 1.29 2002/06/11 08:24:34 jinmei Exp $ */
+/* $KAME: common.h,v 1.30 2003/01/05 17:12:12 jinmei Exp $ */
/*
* Copyright (C) 1998 and 1999 WIDE Project.
* All rights reserved.
@@ -43,16 +43,17 @@ extern int foreground;
extern int debug_thresh;
extern char *device;
+/* search option for dhcp6_find_listval() */
+#define MATCHLIST_PREFIXLEN 0x1
+
/* common.c */
extern int dhcp6_copy_list __P((struct dhcp6_list *, struct dhcp6_list *));
extern void dhcp6_clear_list __P((struct dhcp6_list *));
-extern int dhcp6_count_list __P((struct dhcp6_list *));
+extern void dhcp6_clear_listval __P((struct dhcp6_listval *));
extern struct dhcp6_listval *dhcp6_find_listval __P((struct dhcp6_list *,
- void *,
- dhcp6_listval_type_t));
+ dhcp6_listval_type_t, void *, int));
extern struct dhcp6_listval *dhcp6_add_listval __P((struct dhcp6_list *,
- void *,
- dhcp6_listval_type_t));
+ dhcp6_listval_type_t, void *, struct dhcp6_list *));
extern struct dhcp6_event *dhcp6_create_event __P((struct dhcp6_if *, int));
extern void dhcp6_remove_event __P((struct dhcp6_event *));
extern int getifaddr __P((struct in6_addr *, char *, struct in6_addr *,
@@ -81,7 +82,7 @@ extern void dhcp6_set_timeoparam __P((struct dhcp6_event *));
extern void dhcp6_reset_timer __P((struct dhcp6_event *));
extern char *dhcp6optstr __P((int));
extern char *dhcp6msgstr __P((int));
-extern char *dhcp6_stcodestr __P((int));
+extern char *dhcp6_stcodestr __P((u_int16_t));
extern char *duidstr __P((struct duid *));
extern int duidcpy __P((struct duid *, struct duid *));
extern int duidcmp __P((struct duid *, struct duid *));
392 kame/kame/dhcp6/config.c
View
@@ -1,4 +1,4 @@
-/* $KAME: config.c,v 1.23 2002/12/29 00:36:31 jinmei Exp $ */
+/* $KAME: config.c,v 1.24 2003/01/05 17:12:12 jinmei Exp $ */
/*
* Copyright (C) 2002 WIDE Project.
@@ -51,26 +51,45 @@ extern int errno;
struct dhcp6_if *dhcp6_if;
struct prefix_ifconf *prefix_ifconflist;
+struct iapd_conf *iapd_conflist;
struct dhcp6_list dnslist;
static struct dhcp6_ifconf *dhcp6_ifconflist;
-static struct prefix_ifconf *prefix_ifconflist0;
+static struct iapd_conf *iapd_conflist0;
static struct host_conf *host_conflist0, *host_conflist;
static struct dhcp6_list dnslist0;
enum { DHCPOPTCODE_SEND, DHCPOPTCODE_REQUEST, DHCPOPTCODE_ALLOW };
+/* temporary configuration structure for DHCP interface */
+struct dhcp6_ifconf {
+ struct dhcp6_ifconf *next;
+
+ char *ifname;
+
+ /* configuration flags */
+ u_long send_flags;
+ u_long allow_flags;
+
+ int server_pref; /* server preference (server only) */
+
+ struct dhcp6_list iapd_list;
+ struct dhcp6_list reqopt_list;
+};
+
extern struct cf_list *cf_dns_list;
extern char *configfilename;
+static int add_pd_pif __P((struct iapd_conf *, struct cf_list *));
static int add_options __P((int, struct dhcp6_ifconf *, struct cf_list *));
static int add_prefix __P((struct host_conf *, struct dhcp6_prefix *));
+static void clear_pd_pif __P((struct iapd_conf *));
static void clear_ifconf __P((struct dhcp6_ifconf *));
-static void clear_prefixifconf __P((struct prefix_ifconf *));
+static void clear_iaconf __P((struct ia_conf *));
static void clear_hostconf __P((struct host_conf *));
-static void clear_options __P((struct dhcp6_optconf *));
static int configure_duid __P((char *, struct duid *));
static int get_default_ifid __P((struct prefix_ifconf *));
+static struct ia_conf *find_iaconf_fromhead __P((struct ia_conf *, u_int32_t));
void
ifinit(ifname)
@@ -146,6 +165,7 @@ configure_interface(iflist)
}
ifc->server_pref = DH6OPT_PREF_UNDEF;
+ TAILQ_INIT(&ifc->iapd_list);
TAILQ_INIT(&ifc->reqopt_list);
for (cfl = ifp->params; cfl; cfl = cfl->next) {
@@ -221,72 +241,152 @@ configure_interface(iflist)
}
int
-configure_prefix_interface(iflist)
- struct cf_namelist *iflist;
+configure_ia(ialist, iatype)
+ struct cf_namelist *ialist;
+ iatype_t iatype;
{
- struct cf_namelist *ifp;
- struct prefix_ifconf *pif;
+ struct cf_namelist *iap;
+ struct ia_conf *iac = NULL, **iac_head;
+ size_t confsize;
+
+ switch(iatype) {
+ case IATYPE_PD:
+ confsize = sizeof(struct iapd_conf);
+ iac_head = (struct ia_conf **)&iapd_conflist0;
+ break;
+ default:
+ dprintf(LOG_ERR, "%s" "internal error", FNAME);
+ goto bad;
+ }
- for (ifp = iflist; ifp; ifp = ifp->next) {
+ for (iap = ialist; iap; iap = iap->next) {
struct cf_list *cfl;
- if ((pif = malloc(sizeof(*pif))) == NULL) {
+ if ((iac = malloc(confsize)) == NULL) {
dprintf(LOG_ERR, "%s"
- "memory allocation for %s failed", FNAME,
- ifp->name);
- goto bad;
- }
- memset(pif, 0, sizeof(*pif));
- pif->next = prefix_ifconflist0;
- prefix_ifconflist0 = pif;
-
- /* validate and copy ifname */
- if (if_nametoindex(ifp->name) == 0) {
- dprintf(LOG_ERR, "%s" "invalid interface (%s): %s",
- FNAME, ifp->name, strerror(errno));
- goto bad;
- }
- if ((pif->ifname = strdup(ifp->name)) == NULL) {
- dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME);
+ "memory allocation for IA %s failed", FNAME,
+ iap->name);
goto bad;
}
-
- pif->ifid_len = IFID_LEN_DEFAULT;
- pif->sla_len = SLA_LEN_DEFAULT;
- if (get_default_ifid(pif)) {
- dprintf(LOG_NOTICE, "%s"
- "failed to get default IF ID for %s",
- FNAME, pif->ifname);
- goto bad;
+ memset(iac, 0, confsize);
+
+ /* common initialization */
+ iac->next = *iac_head;
+ *iac_head = iac;
+ iac->type = iatype;
+ iac->iaid = (u_int32_t)atoi(iap->name);
+
+ /* IA-type specific initialization */
+ switch(iatype) {
+ case IATYPE_PD:
+ TAILQ_INIT(&((struct iapd_conf *)iac)->iapd_pif_list);
+ break;
}
- for (cfl = ifp->params; cfl; cfl = cfl->next) {
+ /* set up parameters for the IA */
+ for (cfl = iap->params; cfl; cfl = cfl->next) {
switch(cfl->type) {
- case IFPARAM_SLA_ID:
- pif->sla_id = (u_int32_t)cfl->num;
- break;
- case IFPARAM_SLA_LEN:
- pif->sla_len = (int)cfl->num;
- if (pif->sla_len < 0 || pif->sla_len > 128) {
- dprintf(LOG_ERR, "%s"
- "invalid SLA length: %d", FNAME,
- pif->sla_len);
- goto bad;
+ case IACONF_PIF:
+ /* sanity check */
+ if (iatype != IATYPE_PD) {
+ dprintf(LOG_ERR, "%s" "%s:%d "
+ "internal error "
+ "(IA type mismatch)",
+ FNAME, configfilename, cfl->line);
}
+ if (add_pd_pif((struct iapd_conf *)iac, cfl))
+ goto bad;
break;
default:
dprintf(LOG_ERR, "%s" "%s:%d "
- "invalid configuration", FNAME,
- configfilename, cfl->line);
+ "invalid configuration", FNAME,
+ configfilename, cfl->line);
goto bad;
}
}
}
-
+
return (0);
bad:
- /* there is currently nothing special to recover the error */
+ return (-1);
+}
+
+static int
+add_pd_pif(iapdc, cfl0)
+ struct iapd_conf *iapdc;
+ struct cf_list *cfl0;
+{
+ struct cf_list *cfl;
+ struct prefix_ifconf *pif;
+
+ /* duplication check */
+ for (pif = TAILQ_FIRST(&iapdc->iapd_pif_list); pif;
+ pif = TAILQ_NEXT(pif, link)) {
+ if (strcmp(pif->ifname, cfl0->ptr) == 0) {
+ dprintf(LOG_NOTICE, "%s" "%s:%d "
+ "duplicated prefix interface: %s",
+ FNAME, configfilename, cfl0->line, cfl0->ptr);
+ return (0); /* ignore it */
+ }
+ }
+
+ if ((pif = malloc(sizeof(*pif))) == NULL) {
+ dprintf(LOG_ERR, "%s"
+ "memory allocation for %s failed", FNAME, cfl0->ptr);
+ goto bad;
+ }
+ memset(pif, 0, sizeof(*pif));
+
+ /* validate and copy ifname */
+ if (if_nametoindex(cfl0->ptr) == 0) {
+ dprintf(LOG_ERR, "%s" "%s:%d invalid interface (%s): %s",
+ FNAME, configfilename, cfl0->line,
+ cfl0->ptr, strerror(errno));
+ goto bad;
+ }
+ if ((pif->ifname = strdup(cfl0->ptr)) == NULL) {
+ dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME);
+ goto bad;
+ }
+
+ pif->ifid_len = IFID_LEN_DEFAULT;
+ pif->sla_len = SLA_LEN_DEFAULT;
+ if (get_default_ifid(pif)) {
+ dprintf(LOG_NOTICE, "%s" "failed to get default IF ID for %s",
+ FNAME, pif->ifname);
+ goto bad;
+ }
+
+ for (cfl = cfl0->list; cfl; cfl = cfl->next) {
+ switch(cfl->type) {
+ case IFPARAM_SLA_ID:
+ pif->sla_id = (u_int32_t)cfl->num;
+ break;
+ case IFPARAM_SLA_LEN:
+ pif->sla_len = (int)cfl->num;
+ if (pif->sla_len < 0 || pif->sla_len > 128) {
+ dprintf(LOG_ERR, "%s" "%s:%d "
+ "invalid SLA length: %d", FNAME,
+ configfilename, cfl->line, pif->sla_len);
+ goto bad;
+ }
+ break;
+ default:
+ dprintf(LOG_ERR, "%s" "%s:%d internal error: "
+ "invalid configuration", FNAME,
+ configfilename, cfl->line);
+ goto bad;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(&iapdc->iapd_pif_list, pif, link);
+ return (0);
+
+ bad:
+ if (pif->ifname)
+ free(pif->ifname);
+ free(pif);
return (-1);
}
@@ -379,16 +479,16 @@ configure_global_option()
TAILQ_INIT(&dnslist0);
for (cl = cf_dns_list; cl; cl = cl->next) {
/* duplication check */
- if (dhcp6_find_listval(&dnslist0, cl->ptr,
- DHCP6_LISTVAL_ADDR6)) {
+ if (dhcp6_find_listval(&dnslist0, DHCP6_LISTVAL_ADDR6,
+ cl->ptr, 0)) {
dprintf(LOG_INFO, "%s"
"%s:%d duplicated DNS server: %s", FNAME,
configfilename, cl->line,
in6addr2str((struct in6_addr *)cl->ptr, 0));
goto bad;
}
- if (dhcp6_add_listval(&dnslist0, cl->ptr,
- DHCP6_LISTVAL_ADDR6) == NULL) {
+ if (dhcp6_add_listval(&dnslist0, DHCP6_LISTVAL_ADDR6,
+ cl->ptr, NULL) == NULL) {
dprintf(LOG_ERR, "%s" "failed to add a DNS server");
goto bad;
}
@@ -523,10 +623,10 @@ get_default_ifid(pif)
void
configure_cleanup()
{
+ clear_iaconf((struct ia_conf *)iapd_conflist0);
+ iapd_conflist0 = NULL;
clear_ifconf(dhcp6_ifconflist);
dhcp6_ifconflist = NULL;
- clear_prefixifconf(prefix_ifconflist0);
- prefix_ifconflist0 = NULL;
clear_hostconf(host_conflist0);
host_conflist0 = NULL;
dhcp6_clear_list(&dnslist0);
@@ -546,10 +646,9 @@ configure_commit()
ifp->allow_flags = ifc->allow_flags;
- clear_options(ifp->send_options);
-
- ifp->send_options = ifc->send_options;
- ifc->send_options = NULL;
+ dhcp6_clear_list(&ifp->iapd_list);
+ ifp->iapd_list = ifc->iapd_list;
+ TAILQ_INIT(&ifc->iapd_list);
dhcp6_clear_list(&ifp->reqopt_list);
ifp->reqopt_list = ifc->reqopt_list;
@@ -560,13 +659,13 @@ configure_commit()
}
clear_ifconf(dhcp6_ifconflist);
- /* commit prefix configuration */
- if (prefix_ifconflist) {
+ /* commit IA_PD configuration */
+ if (iapd_conflist) {
/* clear previous configuration. (need more work?) */
- clear_prefixifconf(prefix_ifconflist);
+ clear_pd_pif(iapd_conflist);
}
- prefix_ifconflist = prefix_ifconflist0;
- prefix_ifconflist0 = NULL;
+ iapd_conflist = iapd_conflist0;
+ iapd_conflist0 = NULL;
/* commit prefix configuration */
if (host_conflist) {
@@ -594,7 +693,7 @@ clear_ifconf(iflist)
ifc_next = ifc->next;
free(ifc->ifname);
- clear_options(ifc->send_options);
+ dhcp6_clear_list(&ifc->iapd_list);
dhcp6_clear_list(&ifc->reqopt_list);
free(ifc);
@@ -602,13 +701,13 @@ clear_ifconf(iflist)
}
static void
-clear_prefixifconf(iflist)
- struct prefix_ifconf *iflist;
+clear_pd_pif(iapdc)
+ struct iapd_conf *iapdc;
{
struct prefix_ifconf *pif, *pif_next;
- for (pif = iflist; pif; pif = pif_next) {
- pif_next = pif->next;
+ for (pif = TAILQ_FIRST(&iapdc->iapd_pif_list); pif; pif = pif_next) {
+ pif_next = TAILQ_NEXT(pif, link);
free(pif->ifname);
free(pif);
@@ -616,6 +715,24 @@ clear_prefixifconf(iflist)
}
static void
+clear_iaconf(ialist)
+ struct ia_conf *ialist;
+{
+ struct ia_conf *iac, *iac_next;
+
+ for (iac = ialist; iac; iac = iac_next) {
+ iac_next = iac->next;
+
+ switch(iac->type) {
+ case IATYPE_PD:
+ clear_pd_pif((struct iapd_conf *)iac);
+ break;
+ }
+ free(iac);
+ }
+}
+
+static void
clear_hostconf(hlist)
struct host_conf *hlist;
{
@@ -636,20 +753,6 @@ clear_hostconf(hlist)
}
}
-static void
-clear_options(opt0)
- struct dhcp6_optconf *opt0;
-{
- struct dhcp6_optconf *opt, *opt_next;
-
- for (opt = opt0; opt; opt = opt_next) {
- opt_next = opt->next;
-
- free(opt->val);
- free(opt);
- }
-}
-
static int
add_options(opcode, ifc, cfl0)
int opcode;
@@ -659,6 +762,7 @@ add_options(opcode, ifc, cfl0)
struct dhcp6_listval *opt;
struct cf_list *cfl;
int opttype;
+ struct dhcp6_ia ia;
for (cfl = cfl0; cfl; cfl = cfl->next) {
if (opcode == DHCPOPTCODE_REQUEST) {
@@ -690,12 +794,51 @@ add_options(opcode, ifc, cfl0)
return (-1);
}
break;
+ case DHCPOPT_IA_PD:
+ switch(opcode) {
+ case DHCPOPTCODE_SEND:
+ if (find_iaconf_fromhead(
+ (struct ia_conf *)iapd_conflist0,
+ (u_int32_t)cfl->num) == NULL) {
+ dprintf(LOG_ERR, "%s" "%s:%d "
+ "IA_PD (%lu) is not defined",
+ FNAME, configfilename, cfl->line,
+ (u_long)cfl->num);
+ return (-1);
+ }
+
+ /*
+ * Set up IA parameters. Currently only
+ * IAID is configurable.
+ */
+ memset(&ia, 0, sizeof(ia));
+ ia.iaid = (u_int32_t)cfl->num;
+
+ /*
+ * add the option information to the local
+ * configuration.
+ */
+ if (dhcp6_add_listval(&ifc->iapd_list,
+ DHCP6_LISTVAL_IAPD, &ia, NULL) == NULL) {
+ dprintf(LOG_ERR, "%s" "failed to "
+ "configure an option", FNAME);
+ return (-1);
+ }
+ break;
+ default:
+ dprintf(LOG_ERR, "%s" "invalid operation (%d) "
+ "for option type (%d)",
+ FNAME, opcode, cfl->type);
+ break;
+ }
+ break;
case DHCPOPT_PREFIX_DELEGATION:
switch(opcode) {
case DHCPOPTCODE_REQUEST:
opttype = DH6OPT_PREFIX_DELEGATION;
if (dhcp6_add_listval(&ifc->reqopt_list,
- &opttype, DHCP6_LISTVAL_NUM) == NULL) {
+ DHCP6_LISTVAL_NUM, &opttype, NULL)
+ == NULL) {
dprintf(LOG_ERR, "%s" "failed to "
"configure an option", FNAME);
return (-1);
@@ -713,7 +856,8 @@ add_options(opcode, ifc, cfl0)
case DHCPOPTCODE_REQUEST:
opttype = DH6OPT_DNS;
if (dhcp6_add_listval(&ifc->reqopt_list,
- &opttype, DHCP6_LISTVAL_NUM) == NULL) {
+ DHCP6_LISTVAL_NUM, &opttype, NULL)
+ == NULL) {
dprintf(LOG_ERR, "%s" "failed to "
"configure an option", FNAME);
return (-1);
@@ -727,9 +871,10 @@ add_options(opcode, ifc, cfl0)
}
break;
default:
- dprintf(LOG_ERR, "%s"
- "unknown option type: %d", FNAME, cfl->type);
- return (-1);
+ dprintf(LOG_ERR, "%s" "%s:%d "
+ "unsupported option type: %d",
+ FNAME, configfilename, cfl->line, cfl->type);
+ return (-1);
}
next:
@@ -744,7 +889,6 @@ add_prefix(hconf, prefix0)
struct dhcp6_prefix *prefix0;
{
struct dhcp6_prefix oprefix;
- struct dhcp6_listval *p, *pent;
oprefix = *prefix0;
@@ -775,27 +919,30 @@ add_prefix(hconf, prefix0)
}
/* prefix duplication check */
- for (p = TAILQ_FIRST(&hconf->prefix_list); p;
- p = TAILQ_NEXT(p, link)) {
- if (IN6_ARE_ADDR_EQUAL(&p->val_prefix6.addr, &oprefix.addr) &&
- p->val_prefix6.plen == oprefix.plen) {
- dprintf(LOG_ERR, "%s"
- "duplicated prefix: %s/%d for %s", FNAME,
- in6addr2str(&oprefix.addr, 0), oprefix.plen,
- hconf->name);
- return (-1);
- }
+ if (dhcp6_find_listval(&hconf->prefix_list, DHCP6_LISTVAL_PREFIX6,
+ &oprefix, 0)) {
+ dprintf(LOG_NOTICE, "%s"
+ "duplicated prefix: %s/%d for %s", FNAME,
+ in6addr2str(&oprefix.addr, 0), oprefix.plen,
+ hconf->name);
+ return (-1);
+ }
+
+ /* validation about relationship of pltime and vltime */
+ if (oprefix.vltime != DHCP6_DURATITION_INFINITE &&
+ (oprefix.pltime == DHCP6_DURATITION_INFINITE ||
+ oprefix.pltime > oprefix.vltime)) {
+ dprintf(LOG_NOTICE, "%s" "%s/%d has larger preferred lifetime "
+ "than valid lifetime", FNAME,
+ in6addr2str(&oprefix.addr, 0), oprefix.plen);
+ return (-1);
}
- /* allocate memory for the new prefix and insert it to the chain */
- if ((pent = malloc(sizeof(*pent))) == NULL) {
- dprintf(LOG_ERR, "%s" "memory allocation failed for %s",
- FNAME, hconf->name);
+ /* insert the new prefix to the chain */
+ if (dhcp6_add_listval(&hconf->prefix_list, DHCP6_LISTVAL_PREFIX6,
+ &oprefix, NULL) == NULL) {
return (-1);
}
- memset(pent, 0, sizeof(*pent));
- pent->val_prefix6 = oprefix;
- TAILQ_INSERT_TAIL(&hconf->prefix_list, pent, link);
return (0);
}
@@ -828,20 +975,39 @@ find_ifconfbyid(id)
return (NULL);
}
-struct prefix_ifconf *
-find_prefixifconf(ifname)
- char *ifname;
+static struct ia_conf *
+find_iaconf_fromhead(head, iaid)
+ struct ia_conf *head;
+ u_int32_t iaid;
{
- struct prefix_ifconf *ifp;
+ struct ia_conf *iac;
- for (ifp = prefix_ifconflist; ifp; ifp = ifp->next) {
- if (strcmp(ifp->ifname, ifname) == NULL)
- return (ifp);
+ for (iac = head; iac; iac = iac->next) {
+ if (iac->iaid == iaid)
+ return (iac);
}
return (NULL);
}
+struct ia_conf *
+find_iaconf(type, iaid)
+ int type;
+ u_int32_t iaid;
+{
+ struct ia_conf *iac_head;
+
+ switch(type) {
+ case IATYPE_PD:
+ iac_head = (struct ia_conf *)iapd_conflist;
+ break;
+ default:
+ return (NULL);
+ }
+
+ return (find_iaconf_fromhead(iac_head, iaid));
+}
+
struct host_conf *
find_hostconf(duid)
struct duid *duid;
66 kame/kame/dhcp6/config.h
View
@@ -1,4 +1,4 @@
-/* $KAME: config.h,v 1.18 2002/06/14 15:32:55 jinmei Exp $ */
+/* $KAME: config.h,v 1.19 2003/01/05 17:12:12 jinmei Exp $ */
/*
* Copyright (C) 2002 WIDE Project.
@@ -54,7 +54,7 @@ struct dhcp6_if {
int server_pref; /* server preference (server only) */
- struct dhcp6_optconf *send_options;
+ struct dhcp6_list iapd_list;
struct dhcp6_list reqopt_list;
struct dhcp6_serverinfo *current_server;
@@ -83,7 +83,7 @@ struct dhcp6_event {
TAILQ_HEAD(, dhcp6_eventdata) data_list;
};
-typedef enum { DHCP6_DATA_PREFIX } dhcp6_eventdata_t;
+typedef enum { DHCP6_EVDATA_IAPD } dhcp6_eventdata_t;
struct dhcp6_eventdata {
TAILQ_ENTRY(dhcp6_eventdata) link;
@@ -91,6 +91,9 @@ struct dhcp6_eventdata {
struct dhcp6_event *event;
dhcp6_eventdata_t type;
void *data;
+
+ void (*destructor) __P((struct dhcp6_eventdata *));
+ void *privdata;
};
struct dhcp6_serverinfo {
@@ -107,26 +110,9 @@ struct dhcp6_serverinfo {
/* client status code */
enum {DHCP6S_INIT, DHCP6S_SOLICIT, DHCP6S_INFOREQ, DHCP6S_REQUEST,
DHCP6S_RENEW, DHCP6S_REBIND, DHCP6S_IDLE};
-
-struct dhcp6_ifconf {
- struct dhcp6_ifconf *next;
-
- char *ifname;
-
- /* configuration flags */
- u_long send_flags;
- u_long allow_flags;
-
- int server_pref; /* server preference (server only) */
-
- struct dhcp6_optconf *send_options;
- struct dhcp6_optconf *allow_options;
-
- struct dhcp6_list reqopt_list;
-};
struct prefix_ifconf {
- struct prefix_ifconf *next;
+ TAILQ_ENTRY(prefix_ifconf) link;
char *ifname; /* interface name such as ne0 */
int sla_len; /* SLA ID length in bits */
@@ -138,27 +124,40 @@ struct prefix_ifconf {
#define IFID_LEN_DEFAULT 64
#define SLA_LEN_DEFAULT 16
+struct ia_conf {
+ struct ia_conf *next;
+ int type;
+ u_int32_t iaid;
+
+ /* type dependent values follow */
+};
+typedef enum {IATYPE_PD} iatype_t;
+
+TAILQ_HEAD(pifc_list, prefix_ifconf);
+struct iapd_conf {
+ struct ia_conf iapd_ia;
+
+ /* type dependent values follow */
+ struct pifc_list iapd_pif_list;
+};
+#define iapd_next iapd_ia.next
+#define iapd_type iapd_ia.type
+#define iapd_id iapd_ia.iaid
+
/* per-host configuration */
struct host_conf {
struct host_conf *next;
char *name; /* host name to identify the host */
struct duid duid; /* DUID for the host */
- /* delegated prefixes for the host: */
+ /* delegated prefixes for the host */
+ /* struct dhcp6_list prefix_list; */
struct dhcp6_list prefix_list;
/* bindings of delegated prefixes */
struct dhcp6_list prefix_binding_list;
};
-/* DHCP option information */
-struct dhcp6_optconf {
- struct dhcp6_optconf *next;
- int type;
- int len;
- char *val;
-};
-
/* structures and definitions used in the config file parser */
struct cf_namelist {
struct cf_namelist *next;
@@ -183,7 +182,9 @@ enum {DECL_SEND, DECL_ALLOW, DECL_INFO_ONLY, DECL_REQUEST, DECL_DUID,
DECL_PREFIX, DECL_PREFERENCE,
IFPARAM_SLA_ID, IFPARAM_SLA_LEN,
DHCPOPT_RAPID_COMMIT, DHCPOPT_PREFIX_DELEGATION, DHCPOPT_DNS,
- ADDRESS_LIST_ENT };
+ DHCPOPT_IA_PD,
+ ADDRESS_LIST_ENT,
+ IACONF_PIF };
typedef enum {DHCP6_MODE_SERVER, DHCP6_MODE_CLIENT, DHCP6_MODE_RELAY }
dhcp6_mode_t;
@@ -197,8 +198,8 @@ extern struct dhcp6_list dnslist;
extern void ifinit __P((char *));
extern int configure_interface __P((struct cf_namelist *));
-extern int configure_prefix_interface __P((struct cf_namelist *));
extern int configure_host __P((struct cf_namelist *));
+extern int configure_ia __P((struct cf_namelist *, iatype_t));
extern int configure_global_option __P((void));
extern void configure_cleanup __P((void));
extern void configure_commit __P((void));
@@ -209,3 +210,4 @@ extern struct prefix_ifconf *find_prefixifconf __P((char *));
extern struct host_conf *find_hostconf __P((struct duid *));
extern struct dhcp6_prefix *find_prefix6 __P((struct dhcp6_list *,
struct dhcp6_prefix *));
+extern struct ia_conf *find_iaconf __P((int, u_int32_t));
26 kame/kame/dhcp6/configure
View
@@ -832,8 +832,9 @@ Optional Packages:
--with-opt-pdel=VALUE specify DHCP option value for prefix delegation
--with-opt-pinfo=VALUE specify DHCP option value for prefix information
--with-opt-preq=VALUE specify DHCP option value for prefix request
- --with-opt-pa-pd=VALUE specify DHCP option value for IA_PD
- --with-opt-preq=VALUE specify DHCP option value for IA_PD prefix
+ --with-opt-ia-pd=VALUE specify DHCP option value for IA_PD
+ --with-opt-ia-pd-prefix=VALUE specify DHCP option value for IA_PD prefix
+ --with-stcode-no-prefix=VALUE specify DHCP status code for NoPrefixAvail
Some influential environment variables:
CC C compiler command
@@ -4321,6 +4322,26 @@ echo "${ECHO_T}using $dhcpopt_ia_pd_prefix" >&6
fi
+echo "$as_me:$LINENO: checking for DHCP NoPrefixAvail status code" >&5
+echo $ECHO_N "checking for DHCP NoPrefixAvail status code... $ECHO_C" >&6
+
+# Check whether --with-stcode-no-prefix or --without-stcode-no-prefix was given.
+if test "${with_stcode_no_prefix+set}" = set; then
+ withval="$with_stcode_no_prefix"
+ dhcpstcode_no_prefix="$withval"
+else
+ dhcpstcode_no_prefix=0
+fi;
+if test $dhcpstcode_no_prefix = 0 ; then
+ dhcpstcode_no_prefix=6
+ echo "$as_me:$LINENO: result: unspecified and using $dhcpstcode_no_prefix" >&5
+echo "${ECHO_T}unspecified and using $dhcpstcode_no_prefix" >&6
+else
+ echo "$as_me:$LINENO: result: using $dhcpstcode_no_prefix" >&5
+echo "${ECHO_T}using $dhcpstcode_no_prefix" >&6
+fi
+
+
for ac_header in stdarg.h
do
@@ -5034,6 +5055,7 @@ s,@dhcpopt_pinfo@,$dhcpopt_pinfo,;t t
s,@dhcpopt_preq@,$dhcpopt_preq,;t t
s,@dhcpopt_ia_pd@,$dhcpopt_ia_pd,;t t
s,@dhcpopt_ia_pd_prefix@,$dhcpopt_ia_pd_prefix,;t t
+s,@dhcpstcode_no_prefix@,$dhcpstcode_no_prefix,;t t
CEOF
_ACEOF
16 kame/kame/dhcp6/configure.in
View
@@ -191,7 +191,7 @@ AC_SUBST(dhcpopt_preq)
AC_MSG_CHECKING(for DHCP IA_PD option)
AC_ARG_WITH(opt-ia-pd,
-[ --with-opt-pa-pd=VALUE specify DHCP option value for IA_PD],
+[ --with-opt-ia-pd=VALUE specify DHCP option value for IA_PD],
dhcpopt_ia_pd="$withval", dhcpopt_ia_pd=0)
if test $dhcpopt_ia_pd = 0 ; then
dhcpopt_ia_pd=33
@@ -203,7 +203,7 @@ AC_SUBST(dhcpopt_ia_pd)
AC_MSG_CHECKING(for DHCP IA_PD_PREFIX option)
AC_ARG_WITH(opt-ia-pd-prefix,
-[ --with-opt-preq=VALUE specify DHCP option value for IA_PD prefix],
+[ --with-opt-ia-pd-prefix=VALUE specify DHCP option value for IA_PD prefix],
dhcpopt_ia_pd_prefix="$withval", dhcpopt_ia_pd_prefix=0)
if test $dhcpopt_ia_pd_prefix = 0 ; then
dhcpopt_ia_pd_prefix=34
@@ -213,6 +213,18 @@ else
fi
AC_SUBST(dhcpopt_ia_pd_prefix)
+AC_MSG_CHECKING(for DHCP NoPrefixAvail status code)
+AC_ARG_WITH(stcode-no-prefix,
+[ --with-stcode-no-prefix=VALUE specify DHCP status code for NoPrefixAvail],
+ dhcpstcode_no_prefix="$withval", dhcpstcode_no_prefix=0)
+if test $dhcpstcode_no_prefix = 0 ; then
+ dhcpstcode_no_prefix=6
+ AC_MSG_RESULT(unspecified and using $dhcpstcode_no_prefix)
+else
+ AC_MSG_RESULT(using $dhcpstcode_no_prefix)
+fi
+AC_SUBST(dhcpstcode_no_prefix)
+
AC_CHECK_HEADERS(stdarg.h)
AC_OUTPUT(Makefile)
100 kame/kame/dhcp6/dhcp6.h
View
@@ -1,4 +1,4 @@
-/* $KAME: dhcp6.h,v 1.33 2002/12/29 00:54:48 jinmei Exp $ */
+/* $KAME: dhcp6.h,v 1.34 2003/01/05 17:12:13 jinmei Exp $ */
/*
* Copyright (C) 1998 and 1999 WIDE Project.
* All rights reserved.
@@ -27,9 +27,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/*
- * draft-ietf-dhc-dhcpv6-26
- */
#ifndef __DHCP6_H_DEFINED
#define __DHCP6_H_DEFINED
@@ -76,8 +73,6 @@
#define DHCP6_DURATITION_INFINITE 0xffffffff
-/* Internal data structure */
-
/* DUID: DHCP unique Identifier */
struct duid {
int duid_len; /* length */
@@ -85,28 +80,45 @@ struct duid {
};
/* option information */
-struct dhcp6_prefix { /* delegated prefix information */
- struct in6_addr addr;
+struct dhcp6_ia { /* identity association */
+ u_int32_t iaid;
+ u_int32_t t1;
+ u_int32_t t2;
+};
+
+struct dhcp6_prefix {
+ u_int32_t pltime;
+ u_int32_t vltime;
int plen;
- u_int32_t duration;
+ struct in6_addr addr;
};
+/* Internal data structure */
+typedef enum { DHCP6_LISTVAL_NUM = 1,
+ DHCP6_LISTVAL_STCODE, DHCP6_LISTVAL_ADDR6,
+ DHCP6_LISTVAL_IAPD, DHCP6_LISTVAL_PREFIX6
+} dhcp6_listval_type_t;
+TAILQ_HEAD(dhcp6_list, dhcp6_listval);
struct dhcp6_listval {
TAILQ_ENTRY(dhcp6_listval) link;
+ dhcp6_listval_type_t type;
+
union {
int uv_num;
+ u_int16_t uv_num16;
struct in6_addr uv_addr6;
struct dhcp6_prefix uv_prefix6;
+ struct dhcp6_ia uv_ia;
} uv;
+
+ struct dhcp6_list sublist;
};
#define val_num uv.uv_num
+#define val_num16 uv.uv_num16
#define val_addr6 uv.uv_addr6
+#define val_ia uv.uv_ia
#define val_prefix6 uv.uv_prefix6
-TAILQ_HEAD(dhcp6_list, dhcp6_listval);
-
-typedef enum { DHCP6_LISTVAL_NUM, DHCP6_LISTVAL_ADDR6,
- DHCP6_LISTVAL_PREFIX6 } dhcp6_listval_type_t;
struct dhcp6_optinfo {
struct duid clientID; /* DUID */
@@ -115,7 +127,8 @@ struct dhcp6_optinfo {
int rapidcommit; /* bool */
int pref; /* server preference */
- struct dhcp6_list reqopt_list; /* options in option request */
+ struct dhcp6_list iapd_list; /* list of IA_PD */
+ struct dhcp6_list reqopt_list; /* options in option request */
struct dhcp6_list stcode_list; /* status code */
struct dhcp6_list dns_list; /* DNS server list */
struct dhcp6_list prefix_list; /* prefix list */
@@ -151,13 +164,13 @@ struct dhcp6 {
#define DH6OPT_STATUS_CODE 13
# define DH6OPT_STCODE_SUCCESS 0
# define DH6OPT_STCODE_UNSPECFAIL 1
-# define DH6OPT_STCODE_AUTHFAILED 2
-# define DH6OPT_STCODE_ADDRUNAVAIL 3
-# define DH6OPT_STCODE_NOADDRAVAIL 4
-# define DH6OPT_STCODE_NOBINDING 5
-# define DH6OPT_STCODE_CONFNOMATCH 6
-# define DH6OPT_STCODE_NOTONLINK 7
-# define DH6OPT_STCODE_USEMULTICAST 8
+# define DH6OPT_STCODE_NOADDRAVAIL 2
+# define DH6OPT_STCODE_NOBINDING 3
+# define DH6OPT_STCODE_NOTONLINK 4
+# define DH6OPT_STCODE_USEMULTICAST 5
+/* The following code is not yet defined and is currently KAME specific. */
+# define DH6OPT_STCODE_NOPREFIXAVAIL CONF_DH6OPT_STCODE_NOPREFIXAVAIL
+
#define DH6OPT_RAPID_COMMIT 14
#define DH6OPT_USER_CLASS 15
#define DH6OPT_VENDOR_CLASS 16
@@ -177,6 +190,10 @@ struct dhcp6 {
#define DH6OPT_PREFIX_INFORMATION CONF_DH6OPT_PREFIX_INFORMATION
#define DH6OPT_PREFIX_REQUEST CONF_DH6OPT_PREFIX_REQUEST
+/* The following two are KAME specific. */
+#define DH6OPT_IA_PD CONF_DH6OPT_IA_PD
+#define DH6OPT_IA_PD_PREFIX CONF_DH6OPT_IA_PD_PREFIX
+
struct dhcp6opt {
u_int16_t dh6opt_type;
u_int16_t dh6opt_len;
@@ -184,15 +201,22 @@ struct dhcp6opt {
} __attribute__ ((__packed__));
/* DUID type 1 */
-struct dhcp6_duid_type1 {
- u_int16_t dh6duid1_type;
- u_int16_t dh6duid1_hwtype;
- u_int32_t dh6duid1_time;
+struct dhcp6opt_duid_type1 {
+ u_int16_t dh6_duid1_type;
+ u_int16_t dh6_duid1_hwtype;
+ u_int32_t dh6_duid1_time;
/* link-layer address follows */
} __attribute__ ((__packed__));
+/* Status Code */
+struct dhcp6opt_stcode {
+ u_int16_t dh6_stcode_type;
+ u_int16_t dh6_stcode_len;
+ u_int16_t dh6_stcode_code;
+} __attribute__ ((__packed__));
+
/* Prefix Information */
-struct dhcp6_prefix_info {
+struct dhcp6opt_prefix_info {
u_int16_t dh6_pi_type;
u_int16_t dh6_pi_len;
u_int32_t dh6_pi_duration;
@@ -200,4 +224,28 @@ struct dhcp6_prefix_info {
struct in6_addr dh6_pi_paddr;
} __attribute__ ((__packed__));
+/*
+ * General format of Identity Association.
+ * This format applies to Prefix Delegation (IA_PD) and Non-temporary Addresses
+ * (IA_NA), while our implementation only supports the former.
+ */
+struct dhcp6opt_ia {
+ u_int16_t dh6_ia_type;
+ u_int16_t dh6_ia_len;
+ u_int32_t dh6_ia_iaid;
+ u_int32_t dh6_ia_t1;
+ u_int32_t dh6_ia_t2;
+ /* sub options follow */
+} __attribute__ ((__packed__));
+
+/* IA_PD Prefix */
+struct dhcp6opt_ia_pd_prefix {
+ u_int16_t dh6_iapd_prefix_type;
+ u_int16_t dh6_iapd_prefix_len;
+ u_int32_t dh6_iapd_prefix_preferred_time;
+ u_int32_t dh6_iapd_prefix_valid_time;
+ u_int8_t dh6_iapd_prefix_prefix_len;
+ struct in6_addr dh6_iapd_prefix_prefix_addr;
+} __attribute__ ((__packed__));
+
#endif /*__DHCP6_H_DEFINED*/
193 kame/kame/dhcp6/dhcp6c.c
View
@@ -1,4 +1,4 @@
-/* $KAME: dhcp6c.c,v 1.98 2002/12/29 00:36:31 jinmei Exp $ */
+/* $KAME: dhcp6c.c,v 1.99 2003/01/05 17:12:13 jinmei Exp $ */
/*
* Copyright (C) 1998 and 1999 WIDE Project.
* All rights reserved.
@@ -66,11 +66,12 @@
#include <err.h>
#include <ifaddrs.h>
-#include <dhcp6.h>
-#include <config.h>
-#include <common.h>
-#include <timer.h>
-#include <prefixconf.h>
+#include "dhcp6.h"
+#include "config.h"
+#include "common.h"
+#include "timer.h"
+#include "dhcp6c_ia.h"
+#include "prefixconf.h"
static int debug = 0;
static u_long sig_flags = 0;
@@ -373,7 +374,7 @@ client6_init()
}
ifp->outsock = outsock;
- prefix6_init();
+ init_ia();
if (signal(SIGHUP, client6_signal) == SIG_ERR) {
dprintf(LOG_WARNING, "%s" "failed to set signal: %s",
@@ -415,8 +416,8 @@ free_resources()
{
struct dhcp6_if *ifp;
- /* release delegated prefixes (should send DHCPv6 release?) */
- prefix6_remove_all();
+ /* release all IAs (should send DHCPv6 release accordingly?) */
+ remove_all_ia();
for (ifp = dhcp6_if; ifp; ifp = ifp->next) {
struct dhcp6_event *ev, *ev_next;
@@ -518,6 +519,7 @@ client6_timo(arg)
ev->state = DHCP6S_SOLICIT;
dhcp6_set_timeoparam(ev); /* XXX */
/* fall through */
+ case DHCP6S_REQUEST:
case DHCP6S_INFOREQ:
client6_send(ev);
break;
@@ -530,7 +532,7 @@ client6_timo(arg)
client6_send_rebind(ev);
} else {
dprintf(LOG_INFO, "%s"
- "all information to be updated were canceled",
+ "all information to be updated was canceled",
FNAME);
dhcp6_remove_event(ev);
return (NULL);
@@ -565,7 +567,7 @@ select_server(ifp)
struct dhcp6_serverinfo *s;
/*
- * pick the best server according to dhcpv6-26 Section 17.1.3
+ * pick the best server according to dhcpv6-28 Section 17.1.3
* XXX: we currently just choose the one that is active and has the
* highest preference.
*/
@@ -654,6 +656,7 @@ client6_send(ev)
struct dhcp6 *dh6;
struct dhcp6_optinfo optinfo;
ssize_t optlen, len;
+ struct dhcp6_listval *iapd;
ifp = ev->ifp;
@@ -685,7 +688,7 @@ client6_send(ev)
* each new message it sends.
*
* A client MUST leave the transaction-ID unchanged in
- * retransmissions of a message. [dhcpv6-26 15.1]
+ * retransmissions of a message. [dhcpv6-28 15.1]
*/
#ifdef HAVE_ARC4RANDOM
ev->xid = arc4random() & DH6_XIDMASK;
@@ -726,6 +729,44 @@ client6_send(ev)
optinfo.rapidcommit = 1;
}
+ /* IA_PD */
+ switch (ev->state) {
+ case DHCP6S_SOLICIT:
+ if (dhcp6_copy_list(&optinfo.iapd_list, &ifp->iapd_list)) {
+ dprintf(LOG_NOTICE, "%s"
+ "failed to copy options to be sent",
+ FNAME);
+ goto end;
+ }
+ break;
+ case DHCP6S_REQUEST:
+ /*
+ * First check the IA_PD given in the advertise.
+ * If the server has given an IA_PD for a local IA, include
+ * the given IA. Otherwise, include locally configured IA
+ * anyway.
+ * (Specification is not clear on this policy.)
+ */
+ for (iapd = TAILQ_FIRST(&ifp->iapd_list); iapd;
+ iapd = TAILQ_NEXT(iapd, link)) {
+ struct dhcp6_listval *v;
+
+ if ((v = dhcp6_find_listval(
+ &ifp->current_server->optinfo.iapd_list,
+ DHCP6_LISTVAL_IAPD, &iapd->uv, 0)) == NULL)
+ v = iapd;
+
+ if (dhcp6_add_listval(&optinfo.iapd_list,
+ DHCP6_LISTVAL_IAPD, &v->uv, &v->sublist) == NULL) {
+ dprintf(LOG_NOTICE, "%s"
+ "failed to construct IA_PD for request",
+ FNAME);
+ goto end;
+ }
+ }
+ break;
+ }
+
/* option request options */
if (dhcp6_copy_list(&optinfo.reqopt_list, &ifp->reqopt_list)) {
dprintf(LOG_ERR, "%s" "failed to copy requested options",
@@ -746,18 +787,18 @@ client6_send(ev)
/* set options in the message */
if ((optlen = dhcp6_set_options((struct dhcp6opt *)(dh6 + 1),
- (struct dhcp6opt *)(buf + sizeof(buf)),
- &optinfo)) < 0) {
+ (struct dhcp6opt *)(buf + sizeof(buf)), &optinfo)) < 0) {
dprintf(LOG_INFO, "%s" "failed to construct options", FNAME);
goto end;
}
len += optlen;
/*
- * Unless otherwise specified, a client sends DHCP messages to the
- * All_DHCP_Relay_Agents_and_Servers or the DHCP_Anycast address.
- * [dhcpv6-26 Section 13.]
- * Our current implementation always follows the case.
+ * Unless otherwise specified in this document or in a document that
+ * describes how IPv6 is carried over a specific type of link (for link
+ * types that do not support multicast), a client sends DHCP messages
+ * to the All_DHCP_Relay_Agents_and_Servers.
+ * [dhcpv6-28 Section 13.]
*/
dst = *sa6_allagent;
dst.sin6_scope_id = ifp->linkid;
@@ -790,7 +831,7 @@ client6_send_renew(ev)
struct sockaddr_in6 dst;
ifp = ev->ifp;