1 /* $KAME: config.c,v 1.53 2005/09/16 11:30:14 suz Exp $ */
4 * Copyright (C) 2002 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/queue.h>
34 #include <sys/ioctl.h>
37 #include <netinet/in.h>
39 #include <net/if_dl.h>
42 #include <linux/if_packet.h>
67 struct prefix_ifconf
*prefix_ifconflist
;
68 struct dhcp6_list siplist
, sipnamelist
, dnslist
, dnsnamelist
, ntplist
;
69 struct dhcp6_list nislist
, nisnamelist
;
70 struct dhcp6_list nisplist
, nispnamelist
;
71 struct dhcp6_list bcmcslist
, bcmcsnamelist
;
72 long long optrefreshtime
;
74 static struct dhcp6_ifconf
*dhcp6_ifconflist
;
75 struct ia_conflist ia_conflist0
;
76 static struct host_conf
*host_conflist0
, *host_conflist
;
77 static struct keyinfo
*key_list
, *key_list0
;
78 static struct authinfo
*auth_list
, *auth_list0
;
79 static struct dhcp6_list siplist0
, sipnamelist0
, dnslist0
, dnsnamelist0
, ntplist0
;
80 static struct dhcp6_list nislist0
, nisnamelist0
;
81 static struct dhcp6_list nisplist0
, nispnamelist0
;
82 static struct dhcp6_list bcmcslist0
, bcmcsnamelist0
;
83 static long long optrefreshtime0
= -1;
84 #ifndef DHCP6_DYNAMIC_HOSTCONF_MAX
85 #define DHCP6_DYNAMIC_HOSTCONF_MAX 1024
87 struct dynamic_hostconf
{
88 TAILQ_ENTRY(dynamic_hostconf
) link
;
89 struct host_conf
*host
;
91 static TAILQ_HEAD(dynamic_hostconf_listhead
, dynamic_hostconf
)
92 dynamic_hostconf_head
;
93 static unsigned int dynamic_hostconf_count
;
94 static struct pool_conf
*pool_conflist
, *pool_conflist0
;
96 enum { DHCPOPTCODE_SEND
, DHCPOPTCODE_REQUEST
, DHCPOPTCODE_ALLOW
};
98 /* temporary configuration structure for DHCP interface */
100 struct dhcp6_ifconf
*next
;
104 /* configuration flags */
108 int server_pref
; /* server preference (server only) */
110 char *scriptpath
; /* path to config script (client only) */
112 struct dhcp6_list reqopt_list
;
113 struct ia_conflist iaconf_list
;
115 struct authinfo
*authinfo
; /* authentication information
116 * (no need to clear) */
117 struct dhcp6_poolspec pool
;
120 extern struct cf_list
*cf_dns_list
, *cf_dns_name_list
, *cf_ntp_list
;
121 extern struct cf_list
*cf_sip_list
, *cf_sip_name_list
;
122 extern struct cf_list
*cf_nis_list
, *cf_nis_name_list
;
123 extern struct cf_list
*cf_nisp_list
, *cf_nisp_name_list
;
124 extern struct cf_list
*cf_bcmcs_list
, *cf_bcmcs_name_list
;
125 extern long long cf_refreshtime
;
126 extern char *configfilename
;
128 static struct keyinfo
*find_keybyname
__P((struct keyinfo
*, char *));
129 static int add_pd_pif
__P((struct iapd_conf
*, struct cf_list
*));
130 static int add_options
__P((int, struct dhcp6_ifconf
*, struct cf_list
*));
131 static int add_prefix
__P((struct dhcp6_list
*, char *, int,
132 struct dhcp6_prefix
*));
133 static void clear_pd_pif
__P((struct iapd_conf
*));
134 static void clear_ifconf
__P((struct dhcp6_ifconf
*));
135 static void clear_iaconf
__P((struct ia_conflist
*));
136 static void clear_hostconf
__P((struct host_conf
*));
137 static void clear_keys
__P((struct keyinfo
*));
138 static void clear_authinfo
__P((struct authinfo
*));
139 static int configure_duid
__P((char *, struct duid
*));
140 static int configure_addr
__P((struct cf_list
*, struct dhcp6_list
*, char *));
141 static int configure_domain
__P((struct cf_list
*, struct dhcp6_list
*, char *));
142 static int get_default_ifid
__P((struct prefix_ifconf
*));
143 static void clear_poolconf
__P((struct pool_conf
*));
144 static struct pool_conf
*create_pool
__P((char *, struct dhcp6_range
*));
145 struct host_conf
*find_dynamic_hostconf
__P((struct duid
*));
146 static int in6_addr_cmp
__P((struct in6_addr
*, struct in6_addr
*));
148 static void in6_addr_inc
__P((struct in6_addr
*));
152 configure_interface(iflist
)
153 struct cf_namelist
*iflist
;
155 struct cf_namelist
*ifp
;
156 struct dhcp6_ifconf
*ifc
;
159 for (ifp
= iflist
; ifp
; ifp
= ifp
->next
) {
162 if (if_nametoindex(ifp
->name
) == 0) {
163 dprintf(LOG_ERR
, FNAME
, "invalid interface(%s): %s",
164 ifp
->name
, strerror(errno
));
168 if ((ifc
= malloc(sizeof(*ifc
))) == NULL
) {
169 dprintf(LOG_ERR
, FNAME
,
170 "memory allocation for %s failed", ifp
->name
);
173 memset(ifc
, 0, sizeof(*ifc
));
174 ifc
->next
= dhcp6_ifconflist
;
175 dhcp6_ifconflist
= ifc
;
177 if ((ifc
->ifname
= strdup(ifp
->name
)) == NULL
) {
178 dprintf(LOG_ERR
, FNAME
, "failed to copy ifname");
182 ifc
->server_pref
= DH6OPT_PREF_UNDEF
;
183 TAILQ_INIT(&ifc
->reqopt_list
);
184 TAILQ_INIT(&ifc
->iaconf_list
);
186 for (cfl
= ifp
->params
; cfl
; cfl
= cfl
->next
) {
189 if (dhcp6_mode
!= DHCP6_MODE_CLIENT
) {
190 dprintf(LOG_INFO
, FNAME
, "%s:%d "
191 "client-only configuration",
196 if (add_options(DHCPOPTCODE_REQUEST
,
202 if (add_options(DHCPOPTCODE_SEND
,
208 if (add_options(DHCPOPTCODE_ALLOW
,
214 if (dhcp6_mode
!= DHCP6_MODE_CLIENT
) {
215 dprintf(LOG_INFO
, FNAME
, "%s:%d "
216 "client-only configuration",
217 configfilename
, cfl
->line
);
220 ifc
->send_flags
|= DHCIFF_INFO_ONLY
;
222 case DECL_PREFERENCE
:
223 if (dhcp6_mode
!= DHCP6_MODE_SERVER
) {
224 dprintf(LOG_INFO
, FNAME
, "%s:%d "
225 "server-only configuration",
226 configfilename
, cfl
->line
);
229 ifc
->server_pref
= (int)cfl
->num
;
230 if (ifc
->server_pref
< 0 ||
231 ifc
->server_pref
> 255) {
232 dprintf(LOG_INFO
, FNAME
, "%s:%d "
234 configfilename
, cfl
->line
,
240 if (dhcp6_mode
!= DHCP6_MODE_CLIENT
) {
241 dprintf(LOG_INFO
, FNAME
, "%s:%d "
242 "client-only configuration",
243 configfilename
, cfl
->line
);
246 if (ifc
->scriptpath
) {
247 dprintf(LOG_INFO
, FNAME
,
248 "%s:%d duplicated configuration",
249 configfilename
, cfl
->line
);
253 ifc
->scriptpath
= strdup(cp
+ 1);
254 if (ifc
->scriptpath
== NULL
) {
255 dprintf(LOG_NOTICE
, FNAME
,
256 "failed to copy script path");
259 cp
= ifc
->scriptpath
;
261 dprintf(LOG_INFO
, FNAME
,
262 "script must be an absolute path");
265 cp
+= strlen(ifc
->scriptpath
) - 1;
266 *cp
= '\0'; /* clear the terminating quote */
268 case DECL_ADDRESSPOOL
:
270 struct dhcp6_poolspec
* spec
;
271 struct pool_conf
* pool
;
273 spec
= (struct dhcp6_poolspec
*)cfl
->ptr
;
275 for (pool
= pool_conflist0
; pool
; pool
= pool
->next
)
276 if (strcmp(spec
->name
, pool
->name
) == 0)
279 dprintf(LOG_ERR
, FNAME
, "%s:%d "
280 "pool '%s' not found",
281 configfilename
, cfl
->line
,
285 if (spec
->vltime
!= DHCP6_DURATION_INFINITE
&&
286 (spec
->pltime
== DHCP6_DURATION_INFINITE
||
287 spec
->pltime
> spec
->vltime
)) {
288 dprintf(LOG_ERR
, FNAME
, "%s:%d ",
289 configfilename
, cfl
->line
,
290 "specified a larger preferred lifetime "
291 "than valid lifetime");
295 if ((ifc
->pool
.name
= strdup(spec
->name
)) == NULL
) {
296 dprintf(LOG_ERR
, FNAME
,
297 "memory allocation failed");
300 dprintf(LOG_DEBUG
, FNAME
,
301 "pool '%s' is specified to the interface '%s'",
302 ifc
->pool
.name
, ifc
->ifname
);
306 dprintf(LOG_ERR
, FNAME
, "%s:%d "
307 "invalid interface configuration",
308 configfilename
, cfl
->line
);
317 clear_ifconf(dhcp6_ifconflist
);
318 dhcp6_ifconflist
= NULL
;
323 configure_ia(ialist
, iatype
)
324 struct cf_namelist
*ialist
;
327 struct cf_namelist
*iap
;
328 struct ia_conf
*iac
= NULL
;
333 TAILQ_INIT(&ia_conflist0
);
339 confsize
= sizeof(struct iapd_conf
);
342 confsize
= sizeof(struct iana_conf
);
345 dprintf(LOG_ERR
, FNAME
, "internal error");
349 for (iap
= ialist
; iap
; iap
= iap
->next
) {
352 if ((iac
= malloc(confsize
)) == NULL
) {
353 dprintf(LOG_ERR
, FNAME
,
354 "memory allocation for IA %s failed",
358 memset(iac
, 0, confsize
);
360 /* common initialization */
362 iac
->iaid
= (u_int32_t
)atoi(iap
->name
);
363 TAILQ_INIT(&iac
->iadata
);
364 TAILQ_INSERT_TAIL(&ia_conflist0
, iac
, link
);
366 /* IA-type specific initialization */
369 TAILQ_INIT(&((struct iapd_conf
*)iac
)->iapd_prefix_list
);
370 TAILQ_INIT(&((struct iapd_conf
*)iac
)->iapd_pif_list
);
373 TAILQ_INIT(&((struct iana_conf
*)iac
)->iana_address_list
);
377 /* set up parameters for the IA */
378 for (cfl
= iap
->params
; cfl
; cfl
= cfl
->next
) {
379 struct iapd_conf
*pdp
= (struct iapd_conf
*) iac
;
380 struct iana_conf
*nap
= (struct iana_conf
*) iac
;
386 if (add_pd_pif(pdp
, cfl
))
390 if (add_prefix(&pdp
->iapd_prefix_list
,
391 "IAPD", DHCP6_LISTVAL_PREFIX6
,
393 dprintf(LOG_NOTICE
, FNAME
, "failed "
394 "to configure prefix");
399 dprintf(LOG_ERR
, FNAME
, "%s:%d "
400 "invalid configuration",
401 configfilename
, cfl
->line
);
408 if (add_prefix(&nap
->iana_address_list
,
409 "IANA", DHCP6_LISTVAL_STATEFULADDR6
,
411 dprintf(LOG_NOTICE
, FNAME
, "failed "
412 "to configure address");
417 dprintf(LOG_ERR
, FNAME
, "%s:%d "
418 "invalid configuration",
419 configfilename
, cfl
->line
);
424 dprintf(LOG_ERR
, FNAME
, "%s:%d "
426 configfilename
, cfl
->line
, iatype
);
439 add_pd_pif(iapdc
, cfl0
)
440 struct iapd_conf
*iapdc
;
441 struct cf_list
*cfl0
;
444 struct prefix_ifconf
*pif
;
446 /* duplication check */
447 for (pif
= TAILQ_FIRST(&iapdc
->iapd_pif_list
); pif
;
448 pif
= TAILQ_NEXT(pif
, link
)) {
449 if (strcmp(pif
->ifname
, cfl0
->ptr
) == 0) {
450 dprintf(LOG_NOTICE
, FNAME
, "%s:%d "
451 "duplicated prefix interface: %s",
452 configfilename
, cfl0
->line
, cfl0
->ptr
);
453 return (0); /* ignore it */
457 if ((pif
= malloc(sizeof(*pif
))) == NULL
) {
458 dprintf(LOG_ERR
, FNAME
,
459 "memory allocation for %s failed", cfl0
->ptr
);
462 memset(pif
, 0, sizeof(*pif
));
464 /* validate and copy ifname */
465 if (if_nametoindex(cfl0
->ptr
) == 0) {
466 dprintf(LOG_ERR
, FNAME
, "%s:%d invalid interface (%s): %s",
467 configfilename
, cfl0
->line
,
468 cfl0
->ptr
, strerror(errno
));
471 if ((pif
->ifname
= strdup(cfl0
->ptr
)) == NULL
) {
472 dprintf(LOG_ERR
, FNAME
, "failed to copy ifname");
476 pif
->ifid_len
= IFID_LEN_DEFAULT
;
477 pif
->sla_len
= SLA_LEN_DEFAULT
;
478 if (get_default_ifid(pif
)) {
479 dprintf(LOG_NOTICE
, FNAME
,
480 "failed to get default IF ID for %s", pif
->ifname
);
484 for (cfl
= cfl0
->list
; cfl
; cfl
= cfl
->next
) {
487 pif
->sla_id
= (u_int32_t
)cfl
->num
;
489 case IFPARAM_SLA_LEN
:
490 pif
->sla_len
= (int)cfl
->num
;
491 if (pif
->sla_len
< 0 || pif
->sla_len
> 128) {
492 dprintf(LOG_ERR
, FNAME
, "%s:%d "
493 "invalid SLA length: %d",
494 configfilename
, cfl
->line
, pif
->sla_len
);
499 dprintf(LOG_ERR
, FNAME
, "%s:%d internal error: "
500 "invalid configuration",
501 configfilename
, cfl
->line
);
506 TAILQ_INSERT_TAIL(&iapdc
->iapd_pif_list
, pif
, link
);
517 configure_host(hostlist
)
518 struct cf_namelist
*hostlist
;
520 struct cf_namelist
*host
;
521 struct host_conf
*hconf
;
523 for (host
= hostlist
; host
; host
= host
->next
) {
526 if ((hconf
= malloc(sizeof(*hconf
))) == NULL
) {
527 dprintf(LOG_ERR
, FNAME
, "memory allocation failed "
528 "for host %s", host
->name
);
531 memset(hconf
, 0, sizeof(*hconf
));
532 TAILQ_INIT(&hconf
->prefix_list
);
533 TAILQ_INIT(&hconf
->addr_list
);
534 hconf
->next
= host_conflist0
;
535 host_conflist0
= hconf
;
537 if ((hconf
->name
= strdup(host
->name
)) == NULL
) {
538 dprintf(LOG_ERR
, FNAME
, "failed to copy host name: %s",
543 for (cfl
= host
->params
; cfl
; cfl
= cfl
->next
) {
546 if (hconf
->duid
.duid_id
) {
547 dprintf(LOG_ERR
, FNAME
, "%s:%d "
548 "duplicated DUID for %s",
550 cfl
->line
, host
->name
);
553 if ((configure_duid((char *)cfl
->ptr
,
554 &hconf
->duid
)) != 0) {
555 dprintf(LOG_ERR
, FNAME
, "%s:%d "
556 "failed to configure "
558 configfilename
, cfl
->line
,
562 dprintf(LOG_DEBUG
, FNAME
,
563 "configure DUID for %s: %s",
564 host
->name
, duidstr(&hconf
->duid
));
567 if (add_prefix(&hconf
->prefix_list
,
568 hconf
->name
, DHCP6_LISTVAL_PREFIX6
,
570 dprintf(LOG_ERR
, FNAME
, "failed "
571 "to configure prefix for %s",
577 if (add_prefix(&hconf
->addr_list
,
578 hconf
->name
, DHCP6_LISTVAL_STATEFULADDR6
,
580 dprintf(LOG_ERR
, FNAME
, "failed "
581 "to configure address for %s",
586 case DECL_DELAYEDKEY
:
587 if (hconf
->delayedkey
!= NULL
) {
588 dprintf(LOG_WARNING
, FNAME
,
589 "%s:%d: duplicate key %s for %s"
590 " (ignored)", configfilename
,
591 cfl
->line
, cfl
->ptr
, host
->name
);
594 if ((hconf
->delayedkey
=
595 find_keybyname(key_list0
, cfl
->ptr
))
597 dprintf(LOG_ERR
, FNAME
, "failed to "
598 "find key information for %s",
602 dprintf(LOG_DEBUG
, FNAME
, "configure key for "
603 "delayed auth with %s (keyid=%08x)",
604 host
->name
, hconf
->delayedkey
->keyid
);
606 case DECL_ADDRESSPOOL
:
608 struct dhcp6_poolspec
* spec
;
609 struct pool_conf
*pool
;
611 spec
= (struct dhcp6_poolspec
*)cfl
->ptr
;
613 for (pool
= pool_conflist0
; pool
; pool
= pool
->next
)
614 if (strcmp(spec
->name
, pool
->name
) == 0)
617 dprintf(LOG_ERR
, FNAME
, "%s:%d "
618 "pool '%s' not found",
619 configfilename
, cfl
->line
,
623 if (spec
->vltime
!= DHCP6_DURATION_INFINITE
&&
624 (spec
->pltime
== DHCP6_DURATION_INFINITE
||
625 spec
->pltime
> spec
->vltime
)) {
626 dprintf(LOG_ERR
, FNAME
, "%s:%d ",
627 configfilename
, cfl
->line
,
628 "specified a larger preferred lifetime "
629 "than valid lifetime");
633 if ((hconf
->pool
.name
= strdup(spec
->name
)) == NULL
) {
634 dprintf(LOG_ERR
, FNAME
,
635 "memory allocation failed");
638 dprintf(LOG_DEBUG
, FNAME
,
639 "pool '%s' is specified to the host '%s'",
640 hconf
->pool
.name
, hconf
->name
);
644 dprintf(LOG_ERR
, FNAME
, "%s:%d "
645 "invalid host configuration for %s",
646 configfilename
, cfl
->line
,
656 /* there is currently nothing special to recover the error */
661 configure_keys(keylist
)
662 struct cf_namelist
*keylist
;
664 struct cf_namelist
*key
;
668 struct keyinfo
*kinfo
;
672 for (key
= keylist
; key
; key
= key
->next
) {
675 if ((kinfo
= malloc(sizeof(*kinfo
))) == NULL
) {
676 dprintf(LOG_ERR
, FNAME
, "memory allocation failed "
677 "for key %s", key
->name
);
680 memset(kinfo
, 0, sizeof(*kinfo
));
681 kinfo
->next
= key_list0
;
684 if ((kinfo
->name
= strdup(key
->name
)) == NULL
) {
685 dprintf(LOG_ERR
, FNAME
, "failed to copy key name: %s",
692 for (cfl
= key
->params
; cfl
; cfl
= cfl
->next
) {
695 if (kinfo
->realm
!= NULL
) {
696 dprintf(LOG_WARNING
, FNAME
,
697 "%s:%d duplicate realm for key %s "
698 "(ignored)", configfilename
,
699 cfl
->line
, key
->name
);
702 kinfo
->realm
= qstrdup(cfl
->ptr
);
703 if (kinfo
->realm
== NULL
) {
704 dprintf(LOG_WARNING
, FNAME
,
705 "failed to allocate memory for "
709 kinfo
->realmlen
= strlen(kinfo
->realm
);
713 dprintf(LOG_WARNING
, FNAME
,
714 "%s:%d duplicate realm for key %s "
716 configfilename
, cfl
->line
);
720 if (keyid
< 0 || keyid
> 0xffffffff) {
721 dprintf(LOG_WARNING
, FNAME
,
722 "%s:%d key ID overflow",
723 configfilename
, cfl
->line
);
727 case KEYPARAM_SECRET
:
728 /* duplicate check */
729 if (kinfo
->secret
!= NULL
) {
730 dprintf(LOG_WARNING
, FNAME
,
731 "%s:%d duplicate secret "
732 "for key %s (ignored)",
733 configfilename
, cfl
->line
,
735 continue; /* ignored */
738 /* convert base64 string to binary secret */
739 if ((secretstr
= qstrdup(cfl
->ptr
)) == NULL
) {
740 dprintf(LOG_WARNING
, FNAME
,
741 "failed to make a copy of secret");
744 memset(secret
, 0, sizeof(secret
));
745 secretlen
= base64_decodestring(secretstr
,
746 secret
, sizeof(secret
));
748 dprintf(LOG_ERR
, FNAME
,
749 "%s:%d failed to parse base64 key",
750 configfilename
, cfl
->line
);
756 /* set the binary secret */
757 kinfo
->secret
= malloc(secretlen
);
758 if (kinfo
->secret
== NULL
) {
759 dprintf(LOG_WARNING
, FNAME
,
760 "failed to allocate memory "
764 memcpy(kinfo
->secret
, secret
, secretlen
);
765 kinfo
->secretlen
= secretlen
;
767 case KEYPARAM_EXPIRE
:
768 if (expire
!= NULL
) {
769 dprintf(LOG_WARNING
, FNAME
,
770 "%s:%d duplicate expire for key "
771 "%s (ignored)", configfilename
,
772 cfl
->line
, key
->name
);
775 expire
= qstrdup(cfl
->ptr
);
778 dprintf(LOG_ERR
, FNAME
,
779 "%s:%d invalid key parameter for %s",
780 configfilename
, cfl
->line
, key
->name
);
785 /* check for mandatory parameters or use default */
786 if (kinfo
->realm
== NULL
) {
787 dprintf(LOG_ERR
, FNAME
,
788 "realm not specified for key %s", key
->name
);
792 dprintf(LOG_ERR
, FNAME
,
793 "key ID not specified for key %s", key
->name
);
796 kinfo
->keyid
= keyid
;
797 if (kinfo
->secret
== NULL
) {
798 dprintf(LOG_ERR
, FNAME
,
799 "secret not specified for key %s", key
->name
);
803 if (expire
!= NULL
) {
804 if (strcmp(expire
, "forever") != 0) {
805 time_t now
, expire_time
;
808 if (time(&now
) == -1) {
809 dprintf(LOG_ERR
, FNAME
, "cannot get "
814 lt
= localtime(&now
);
817 if (strptime(expire
, "%Y-%m-%d %H:%M", lt
)
819 strptime(expire
, "%m-%d %H:%M", lt
)
821 strptime(expire
, "%H:%M", lt
) == NULL
) {
822 dprintf(LOG_ERR
, FNAME
, "invalid "
823 "expiration time: %s");
827 expire_time
= mktime(lt
);
828 if (expire_time
< now
) {
829 dprintf(LOG_ERR
, FNAME
, "past "
830 "expiration time specified: %s",
835 kinfo
->expire
= expire_time
;
848 static struct keyinfo
*
849 find_keybyname(head
, kname
)
850 struct keyinfo
*head
;
853 struct keyinfo
*kinfo
;
855 for (kinfo
= head
; kinfo
!= NULL
; kinfo
= kinfo
->next
) {
856 if (strcmp(kname
, kinfo
->name
) == 0)
864 configure_authinfo(authlist
)
865 struct cf_namelist
*authlist
;
867 struct cf_namelist
*auth
;
868 struct authinfo
*ainfo
;
870 for (auth
= authlist
; auth
; auth
= auth
->next
) {
873 if ((ainfo
= malloc(sizeof(*ainfo
))) == NULL
) {
874 dprintf(LOG_ERR
, FNAME
, "memory allocation failed "
875 "for auth info %s", auth
->name
);
878 memset(ainfo
, 0, sizeof(*ainfo
));
879 ainfo
->next
= auth_list0
;
881 ainfo
->protocol
= DHCP6_AUTHPROTO_UNDEF
;
882 ainfo
->algorithm
= DHCP6_AUTHALG_UNDEF
;
883 ainfo
->rdm
= DHCP6_AUTHRDM_UNDEF
;
885 if ((ainfo
->name
= strdup(auth
->name
)) == NULL
) {
886 dprintf(LOG_ERR
, FNAME
,
887 "failed to copy auth info name: %s", auth
->name
);
891 for (cfl
= auth
->params
; cfl
; cfl
= cfl
->next
) {
893 case AUTHPARAM_PROTO
:
894 if (ainfo
->protocol
!= DHCP6_AUTHPROTO_UNDEF
) {
895 dprintf(LOG_WARNING
, FNAME
,
896 "%s:%d duplicate protocol "
899 configfilename
, cfl
->line
,
901 continue; /* ignored */
903 ainfo
->protocol
= (int)cfl
->num
;
906 if (ainfo
->algorithm
!= DHCP6_AUTHALG_UNDEF
) {
907 dprintf(LOG_WARNING
, FNAME
,
908 "%s:%d duplicate algorithm "
911 configfilename
, cfl
->line
,
913 continue; /* ignored */
915 ainfo
->algorithm
= (int)cfl
->num
;
918 if (ainfo
->rdm
!= DHCP6_AUTHRDM_UNDEF
) {
919 dprintf(LOG_WARNING
, FNAME
,
920 "%s:%d duplicate RDM "
923 configfilename
, cfl
->line
,
925 continue; /* ignored */
927 ainfo
->rdm
= (int)cfl
->num
;
930 dprintf(LOG_WARNING
, FNAME
,
931 "%s:%d auth info specific keys "
933 configfilename
, cfl
->line
);
936 dprintf(LOG_ERR
, FNAME
,
937 "%s:%d invalid auth info parameter for %s",
938 configfilename
, cfl
->line
, auth
->name
);
943 /* check for mandatory parameters and consistency */
944 switch (ainfo
->protocol
) {
945 case DHCP6_AUTHPROTO_UNDEF
:
946 dprintf(LOG_ERR
, FNAME
,
947 "auth protocol is not specified for %s",
950 case DHCP6_AUTHPROTO_DELAYED
:
951 if (dhcp6_mode
!= DHCP6_MODE_CLIENT
) {
952 dprintf(LOG_ERR
, FNAME
,
953 "client-only auth protocol is specified");
957 case DHCP6_AUTHPROTO_RECONFIG
:
958 if (dhcp6_mode
!= DHCP6_MODE_SERVER
) {
959 dprintf(LOG_ERR
, FNAME
,
960 "server-only auth protocol is specified");
965 if (ainfo
->algorithm
== DHCP6_AUTHALG_UNDEF
)
966 ainfo
->algorithm
= DHCP6_AUTHALG_HMACMD5
;
967 if (ainfo
->rdm
== DHCP6_AUTHRDM_UNDEF
)
968 ainfo
->rdm
= DHCP6_AUTHRDM_MONOCOUNTER
;
974 /* there is currently nothing special to recover the error */
979 configure_global_option()
981 /* SIP Server address */
982 if (configure_addr(cf_sip_list
, &siplist0
, "SIP") < 0)
985 /* SIP domain name */
986 if (configure_domain(cf_sip_name_list
, &sipnamelist0
, "SIP") < 0)
990 if (configure_addr(cf_dns_list
, &dnslist0
, "DNS") < 0)
994 if (configure_domain(cf_dns_name_list
, &dnsnamelist0
, "DNS") < 0)
998 if (configure_addr(cf_ntp_list
, &ntplist0
, "NTP") < 0)
1001 /* NIS Server address */
1002 if (configure_addr(cf_nis_list
, &nislist0
, "NIS") < 0)
1005 /* NIS domain name */
1006 if (configure_domain(cf_nis_name_list
, &nisnamelist0
, "NIS") < 0)
1009 /* NIS+ Server address */
1010 if (configure_addr(cf_nisp_list
, &nisplist0
, "NISP") < 0)
1013 /* NIS+ domain name */
1014 if (configure_domain(cf_nisp_name_list
, &nispnamelist0
, "NISP") < 0)
1017 /* BCMCS Server address */
1018 if (configure_addr(cf_bcmcs_list
, &bcmcslist0
, "BCMCS") < 0)
1021 /* BCMCS domain name */
1022 if (configure_domain(cf_bcmcs_name_list
, &bcmcsnamelist0
, "BCMCS") < 0)
1025 /* Lifetime for stateless options */
1026 if (cf_refreshtime
>= 0) {
1027 optrefreshtime0
= cf_refreshtime
;
1033 return (-1); /* no need to free intermediate list */
1037 configure_addr(cf_addr_list
, list0
, optname
)
1038 struct cf_list
*cf_addr_list
;
1039 struct dhcp6_list
*list0
;
1044 /* check against configuration restriction */
1045 if (cf_addr_list
!= NULL
&& dhcp6_mode
!= DHCP6_MODE_SERVER
) {
1046 dprintf(LOG_INFO
, FNAME
, "%s:%d server-only configuration",
1047 configfilename
, cf_addr_list
->line
);
1052 for (cl
= cf_addr_list
; cl
; cl
= cl
->next
) {
1053 /* duplication check */
1054 if (dhcp6_find_listval(list0
, DHCP6_LISTVAL_ADDR6
,
1056 dprintf(LOG_INFO
, FNAME
,
1057 "%s:%d duplicated %s server: %s",
1058 configfilename
, cl
->line
,
1060 in6addr2str((struct in6_addr
*)cl
->ptr
, 0));
1063 if (dhcp6_add_listval(list0
, DHCP6_LISTVAL_ADDR6
,
1064 cl
->ptr
, NULL
) == NULL
) {
1065 dprintf(LOG_ERR
, FNAME
, "failed to add a %s server",
1075 configure_domain(cf_name_list
, list0
, optname
)
1076 struct cf_list
*cf_name_list
;
1077 struct dhcp6_list
*list0
;
1082 /* check against configuration restriction */
1083 if (cf_name_list
!= NULL
&& dhcp6_mode
!= DHCP6_MODE_SERVER
) {
1084 dprintf(LOG_INFO
, FNAME
, "%s:%d server-only configuration",
1085 configfilename
, cf_name_list
->line
);
1090 for (cl
= cf_name_list
; cl
; cl
= cl
->next
) {
1092 struct dhcp6_vbuf name_vbuf
;
1094 name
= strdup(cl
->ptr
+ 1);
1096 dprintf(LOG_ERR
, FNAME
,
1097 "failed to copy a %s domain name",
1101 cp
= name
+ strlen(name
) - 1;
1102 *cp
= '\0'; /* clear the terminating quote */
1104 name_vbuf
.dv_buf
= name
;
1105 name_vbuf
.dv_len
= strlen(name
) + 1;
1107 /* duplication check */
1108 if (dhcp6_find_listval(list0
, DHCP6_LISTVAL_VBUF
,
1110 dprintf(LOG_INFO
, FNAME
,
1111 "%s:%d duplicated %s name: %s",
1112 configfilename
, cl
->line
, optname
,
1114 dhcp6_vbuf_free(&name_vbuf
);
1119 if (dhcp6_add_listval(list0
, DHCP6_LISTVAL_VBUF
,
1120 &name_vbuf
, NULL
) == NULL
) {
1121 dprintf(LOG_ERR
, FNAME
, "failed to add a %s name",
1123 dhcp6_vbuf_free(&name_vbuf
);
1126 dhcp6_vbuf_free(&name_vbuf
);
1133 configure_duid(str
, duid
)
1134 char *str
; /* this is a valid DUID string */
1142 /* calculate DUID len */
1148 if ((slen
% 3) != 0)
1150 duidlen
+= (slen
/ 3);
1151 if (duidlen
> 128) {
1152 dprintf(LOG_ERR
, FNAME
, "too long DUID (%d)", duidlen
);
1156 if ((idbuf
= malloc(duidlen
)) == NULL
) {
1157 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
1161 for (cp
= str
, bp
= idbuf
; *cp
;) {
1167 if (sscanf(cp
, "%02x", &x
) != 1)
1174 duid
->duid_len
= duidlen
;
1175 duid
->duid_id
= idbuf
;
1182 dprintf(LOG_ERR
, FNAME
, "assumption failure (bad string)");
1186 /* we currently only construct EUI-64 based interface ID */
1188 get_default_ifid(pif
)
1189 struct prefix_ifconf
*pif
;
1191 struct ifaddrs
*ifa
, *ifap
;
1193 struct sockaddr_dl
*sdl
;
1196 struct sockaddr_ll
*sll
;
1199 if (pif
->ifid_len
< 64) {
1200 dprintf(LOG_NOTICE
, FNAME
, "ID length too short");
1204 if (getifaddrs(&ifap
) < 0) {
1205 dprintf(LOG_ERR
, FNAME
, "getifaddrs failed: %s",
1210 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
1213 if (strcmp(ifa
->ifa_name
, pif
->ifname
) != 0)
1216 if (ifa
->ifa_addr
== NULL
)
1220 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
1223 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
1224 if (sdl
->sdl_alen
< 6) {
1225 dprintf(LOG_NOTICE
, FNAME
,
1226 "link layer address is too short (%s)",
1231 memset(pif
->ifid
, 0, sizeof(pif
->ifid
));
1232 cp
= (char *)(sdl
->sdl_data
+ sdl
->sdl_nlen
);
1235 if (ifa
->ifa_addr
->sa_family
!= AF_PACKET
)
1238 sll
= (struct sockaddr_ll
*)ifa
->ifa_addr
;
1239 if (sll
->sll_halen
< 6) {
1240 dprintf(LOG_NOTICE
, FNAME
,
1241 "link layer address is too short (%s)",
1246 memset(pif
->ifid
, 0, sizeof(pif
->ifid
));
1247 cp
= (char *)(sll
->sll_addr
);
1249 pif
->ifid
[8] = cp
[0];
1250 pif
->ifid
[8] ^= 0x02; /* reverse the u/l bit*/
1251 pif
->ifid
[9] = cp
[1];
1252 pif
->ifid
[10] = cp
[2];
1253 pif
->ifid
[11] = 0xff;
1254 pif
->ifid
[12] = 0xfe;
1255 pif
->ifid
[13] = cp
[3];
1256 pif
->ifid
[14] = cp
[4];
1257 pif
->ifid
[15] = cp
[5];
1263 dprintf(LOG_INFO
, FNAME
,
1264 "cannot find interface information for %s", pif
->ifname
);
1279 clear_iaconf(&ia_conflist0
);
1280 clear_ifconf(dhcp6_ifconflist
);
1281 dhcp6_ifconflist
= NULL
;
1282 clear_hostconf(host_conflist0
);
1283 host_conflist0
= NULL
;
1284 clear_keys(key_list0
);
1286 clear_authinfo(auth_list0
);
1289 dhcp6_clear_list(&siplist0
);
1290 TAILQ_INIT(&siplist0
);
1291 dhcp6_clear_list(&sipnamelist0
);
1292 TAILQ_INIT(&sipnamelist0
);
1293 dhcp6_clear_list(&dnslist0
);
1294 TAILQ_INIT(&dnslist0
);
1295 dhcp6_clear_list(&dnsnamelist0
);
1296 TAILQ_INIT(&dnsnamelist0
);
1297 dhcp6_clear_list(&ntplist0
);
1298 TAILQ_INIT(&ntplist0
);
1299 optrefreshtime0
= -1;
1300 clear_poolconf(pool_conflist0
);
1306 struct dhcp6_ifconf
*ifc
;
1307 struct dhcp6_if
*ifp
;
1308 struct ia_conf
*iac
;
1310 /* commit interface configuration */
1311 for (ifp
= dhcp6_if
; ifp
; ifp
= ifp
->next
) {
1312 /* re-initialization */
1313 ifp
->send_flags
= 0;
1314 ifp
->allow_flags
= 0;
1315 dhcp6_clear_list(&ifp
->reqopt_list
);
1316 clear_iaconf(&ifp
->iaconf_list
);
1317 ifp
->server_pref
= DH6OPT_PREF_UNDEF
;
1318 if (ifp
->scriptpath
!= NULL
)
1319 free(ifp
->scriptpath
);
1320 ifp
->scriptpath
= NULL
;
1321 ifp
->authproto
= DHCP6_AUTHPROTO_UNDEF
;
1322 ifp
->authalgorithm
= DHCP6_AUTHALG_UNDEF
;
1323 ifp
->authrdm
= DHCP6_AUTHRDM_UNDEF
;
1325 for (ifc
= dhcp6_ifconflist
; ifc
; ifc
= ifc
->next
) {
1326 if (strcmp(ifp
->ifname
, ifc
->ifname
) == 0)
1332 /* copy new configuration */
1333 ifp
->send_flags
= ifc
->send_flags
;
1334 ifp
->allow_flags
= ifc
->allow_flags
;
1335 dhcp6_copy_list(&ifp
->reqopt_list
, &ifc
->reqopt_list
);
1336 while ((iac
= TAILQ_FIRST(&ifc
->iaconf_list
)) != NULL
) {
1337 TAILQ_REMOVE(&ifc
->iaconf_list
, iac
, link
);
1338 TAILQ_INSERT_TAIL(&ifp
->iaconf_list
,
1341 ifp
->server_pref
= ifc
->server_pref
;
1342 ifp
->scriptpath
= ifc
->scriptpath
;
1343 ifc
->scriptpath
= NULL
;
1345 if (ifc
->authinfo
!= NULL
) {
1346 ifp
->authproto
= ifc
->authinfo
->protocol
;
1347 ifp
->authalgorithm
= ifc
->authinfo
->algorithm
;
1348 ifp
->authrdm
= ifc
->authinfo
->rdm
;
1350 ifp
->pool
= ifc
->pool
;
1351 ifc
->pool
.name
= NULL
;
1354 clear_ifconf(dhcp6_ifconflist
);
1355 dhcp6_ifconflist
= NULL
;
1357 /* clear unused IA configuration */
1358 if (!TAILQ_EMPTY(&ia_conflist0
)) {
1359 dprintf(LOG_INFO
, FNAME
,
1360 "some IA configuration defined but not used");
1362 clear_iaconf(&ia_conflist0
);
1364 /* commit per-host configuration */
1365 clear_hostconf(host_conflist
);
1366 host_conflist
= host_conflist0
;
1367 host_conflist0
= NULL
;
1369 /* commit secret key information */
1370 clear_keys(key_list
);
1371 key_list
= key_list0
;
1374 /* commit authentication information */
1375 clear_authinfo(auth_list
);
1376 auth_list
= auth_list0
;
1379 /* commit SIP server addresses */
1380 dhcp6_clear_list(&siplist
);
1381 dhcp6_move_list(&siplist
, &siplist0
);
1383 /* commit SIP domain names */
1384 dhcp6_clear_list(&sipnamelist
);
1385 dhcp6_move_list(&sipnamelist
, &sipnamelist0
);
1387 /* commit DNS addresses */
1388 dhcp6_clear_list(&dnslist
);
1389 dhcp6_move_list(&dnslist
, &dnslist0
);
1391 /* commit DNS names */
1392 dhcp6_clear_list(&dnsnamelist
);
1393 dhcp6_move_list(&dnsnamelist
, &dnsnamelist0
);
1395 /* commit NTP addresses */
1396 dhcp6_clear_list(&ntplist
);
1397 dhcp6_move_list(&ntplist
, &ntplist0
);
1399 /* commit NIS server addresses */
1400 dhcp6_clear_list(&nislist
);
1401 dhcp6_move_list(&nislist
, &nislist0
);
1403 /* commit NIS domain names */
1404 dhcp6_clear_list(&nisnamelist
);
1405 dhcp6_move_list(&nisnamelist
, &nisnamelist0
);
1407 /* commit NIS+ server addresses */
1408 dhcp6_clear_list(&nisplist
);
1409 dhcp6_move_list(&nisplist
, &nisplist0
);
1411 /* commit NIS+ domain names */
1412 dhcp6_clear_list(&nispnamelist
);
1413 dhcp6_move_list(&nispnamelist
, &nispnamelist0
);
1415 /* commit BCMCS server addresses */
1416 dhcp6_clear_list(&bcmcslist
);
1417 dhcp6_move_list(&bcmcslist
, &bcmcslist0
);
1419 /* commit BCMCS domain names */
1420 dhcp6_clear_list(&bcmcsnamelist
);
1421 dhcp6_move_list(&bcmcsnamelist
, &bcmcsnamelist0
);
1423 /* commit information refresh time */
1424 optrefreshtime
= optrefreshtime0
;
1425 /* commit pool configuration */
1426 clear_poolconf(pool_conflist
);
1427 pool_conflist
= pool_conflist0
;
1428 pool_conflist0
= NULL
;
1432 clear_ifconf(iflist
)
1433 struct dhcp6_ifconf
*iflist
;
1435 struct dhcp6_ifconf
*ifc
, *ifc_next
;
1437 for (ifc
= iflist
; ifc
; ifc
= ifc_next
) {
1438 ifc_next
= ifc
->next
;
1441 dhcp6_clear_list(&ifc
->reqopt_list
);
1443 clear_iaconf(&ifc
->iaconf_list
);
1445 if (ifc
->scriptpath
)
1446 free(ifc
->scriptpath
);
1449 free(ifc
->pool
.name
);
1456 struct iapd_conf
*iapdc
;
1458 struct prefix_ifconf
*pif
, *pif_next
;
1460 for (pif
= TAILQ_FIRST(&iapdc
->iapd_pif_list
); pif
; pif
= pif_next
) {
1461 pif_next
= TAILQ_NEXT(pif
, link
);
1467 dhcp6_clear_list(&iapdc
->iapd_prefix_list
);
1471 clear_iaconf(ialist
)
1472 struct ia_conflist
*ialist
;
1474 struct ia_conf
*iac
;
1476 while ((iac
= TAILQ_FIRST(ialist
)) != NULL
) {
1477 TAILQ_REMOVE(ialist
, iac
, link
);
1481 if (!TAILQ_EMPTY(&iac
->iadata
)) {
1482 dprintf(LOG_ERR
, FNAME
, "assumption failure");
1485 clear_pd_pif((struct iapd_conf
*)iac
);
1495 clear_hostconf(hlist
)
1496 struct host_conf
*hlist
;
1498 struct host_conf
*host
, *host_next
;
1500 for (host
= hlist
; host
; host
= host_next
) {
1501 host_next
= host
->next
;
1504 dhcp6_clear_list(&host
->prefix_list
);
1505 dhcp6_clear_list(&host
->addr_list
);
1506 if (host
->duid
.duid_id
)
1507 free(host
->duid
.duid_id
);
1508 if (host
->pool
.name
)
1509 free(host
->pool
.name
);
1516 struct keyinfo
*klist
;
1518 struct keyinfo
*key
, *key_next
;
1520 for (key
= klist
; key
; key
= key_next
) {
1521 key_next
= key
->next
;
1531 clear_authinfo(alist
)
1532 struct authinfo
*alist
;
1534 struct authinfo
*auth
, *auth_next
;
1536 for (auth
= alist
; auth
; auth
= auth_next
) {
1537 auth_next
= auth
->next
;
1543 add_options(opcode
, ifc
, cfl0
)
1545 struct dhcp6_ifconf
*ifc
;
1546 struct cf_list
*cfl0
;
1548 struct cf_list
*cfl
;
1550 struct authinfo
*ainfo
;
1551 struct ia_conf
*iac
;
1553 for (cfl
= cfl0
; cfl
; cfl
= cfl
->next
) {
1555 case DHCPOPT_RAPID_COMMIT
:
1557 case DHCPOPTCODE_SEND
:
1558 ifc
->send_flags
|= DHCIFF_RAPID_COMMIT
;
1560 case DHCPOPTCODE_ALLOW
:
1561 ifc
->allow_flags
|= DHCIFF_RAPID_COMMIT
;
1564 dprintf(LOG_ERR
, FNAME
,
1565 "invalid operation (%d) "
1566 "for option type (%d)",
1571 case DHCPOPT_AUTHINFO
:
1572 if (opcode
!= DHCPOPTCODE_SEND
) {
1573 dprintf(LOG_ERR
, FNAME
,
1574 "invalid operation (%d) "
1575 "for option type (%d)",
1579 ainfo
= find_authinfo(auth_list0
, cfl
->ptr
);
1580 if (ainfo
== NULL
) {
1581 dprintf(LOG_ERR
, FNAME
, "%s:%d "
1582 "auth info (%s) is not defined",
1583 configfilename
, cfl
->line
,
1587 if (ifc
->authinfo
!= NULL
) {
1588 dprintf(LOG_ERR
, FNAME
,
1589 "%s:%d authinfo is doubly specified on %s",
1590 configfilename
, cfl
->line
, ifc
->ifname
);
1593 ifc
->authinfo
= ainfo
;
1597 case DHCPOPTCODE_SEND
:
1598 iac
= find_iaconf(&ia_conflist0
, IATYPE_PD
,
1599 (u_int32_t
)cfl
->num
);
1601 dprintf(LOG_ERR
, FNAME
, "%s:%d "
1602 "IA_PD (%lu) is not defined",
1603 configfilename
, cfl
->line
,
1608 TAILQ_REMOVE(&ia_conflist0
, iac
, link
);
1609 TAILQ_INSERT_TAIL(&ifc
->iaconf_list
,
1614 dprintf(LOG_ERR
, FNAME
,
1615 "invalid operation (%d) "
1616 "for option type (%d)", opcode
, cfl
->type
);
1622 case DHCPOPTCODE_SEND
:
1623 iac
= find_iaconf(&ia_conflist0
, IATYPE_NA
,
1624 (u_int32_t
)cfl
->num
);
1626 dprintf(LOG_ERR
, FNAME
, "%s:%d "
1627 "IA_NA (%lu) is not defined",
1628 configfilename
, cfl
->line
,
1633 TAILQ_REMOVE(&ia_conflist0
, iac
, link
);
1634 TAILQ_INSERT_TAIL(&ifc
->iaconf_list
,
1639 dprintf(LOG_ERR
, FNAME
,
1640 "invalid operation (%d) "
1641 "for option type (%d)", opcode
, cfl
->type
);
1646 case DHCPOPT_SIPNAME
:
1648 case DHCPOPT_DNSNAME
:
1651 case DHCPOPT_NISNAME
:
1653 case DHCPOPT_NISPNAME
:
1655 case DHCPOPT_BCMCSNAME
:
1656 case DHCPOPT_REFRESHTIME
:
1657 switch (cfl
->type
) {
1659 opttype
= DH6OPT_SIP_SERVER_A
;
1661 case DHCPOPT_SIPNAME
:
1662 opttype
= DH6OPT_SIP_SERVER_D
;
1665 opttype
= DH6OPT_DNS
;
1667 case DHCPOPT_DNSNAME
:
1668 opttype
= DH6OPT_DNSNAME
;
1671 opttype
= DH6OPT_NTP
;
1674 opttype
= DH6OPT_NIS_SERVERS
;
1676 case DHCPOPT_NISNAME
:
1677 opttype
= DH6OPT_NIS_DOMAIN_NAME
;
1680 opttype
= DH6OPT_NISP_SERVERS
;
1682 case DHCPOPT_NISPNAME
:
1683 opttype
= DH6OPT_NISP_DOMAIN_NAME
;
1686 opttype
= DH6OPT_BCMCS_SERVER_A
;
1688 case DHCPOPT_BCMCSNAME
:
1689 opttype
= DH6OPT_BCMCS_SERVER_D
;
1691 case DHCPOPT_REFRESHTIME
:
1692 opttype
= DH6OPT_REFRESHTIME
;
1696 case DHCPOPTCODE_REQUEST
:
1697 if (dhcp6_find_listval(&ifc
->reqopt_list
,
1698 DHCP6_LISTVAL_NUM
, &opttype
, 0)
1700 dprintf(LOG_INFO
, FNAME
,
1701 "duplicated requested option: %s",
1702 dhcp6optstr(opttype
));
1703 goto next
; /* ignore it */
1705 if (dhcp6_add_listval(&ifc
->reqopt_list
,
1706 DHCP6_LISTVAL_NUM
, &opttype
, NULL
)
1708 dprintf(LOG_ERR
, FNAME
, "failed to "
1709 "configure an option");
1714 dprintf(LOG_ERR
, FNAME
,
1715 "invalid operation (%d) "
1716 "for option type (%d)", opcode
, cfl
->type
);
1721 dprintf(LOG_ERR
, FNAME
,
1722 "%s:%d unsupported option type: %d",
1723 configfilename
, cfl
->line
, cfl
->type
);
1735 add_prefix(head
, name
, type
, prefix0
)
1736 struct dhcp6_list
*head
;
1739 struct dhcp6_prefix
*prefix0
;
1741 struct dhcp6_prefix oprefix
;
1745 /* additional validation of parameters */
1746 if (oprefix
.plen
< 4 || oprefix
.plen
> 128) {
1747 dprintf(LOG_ERR
, FNAME
, "invalid prefix: %d", oprefix
.plen
);
1750 /* clear trailing bits */
1751 prefix6_mask(&oprefix
.addr
, oprefix
.plen
);
1752 if (!IN6_ARE_ADDR_EQUAL(&prefix0
->addr
, &oprefix
.addr
)) {
1753 dprintf(LOG_WARNING
, FNAME
, "prefix %s/%d for %s "
1754 "has a trailing garbage. It should be %s/%d",
1755 in6addr2str(&prefix0
->addr
, 0), prefix0
->plen
,
1756 name
, in6addr2str(&oprefix
.addr
, 0), oprefix
.plen
);
1757 /* ignore the error */
1760 /* avoid invalid prefix addresses */
1761 if (IN6_IS_ADDR_MULTICAST(&oprefix
.addr
) ||
1762 IN6_IS_ADDR_LINKLOCAL(&oprefix
.addr
) ||
1763 IN6_IS_ADDR_SITELOCAL(&oprefix
.addr
)) {
1764 dprintf(LOG_ERR
, FNAME
, "invalid prefix address: %s",
1765 in6addr2str(&oprefix
.addr
, 0));
1769 /* prefix duplication check */
1770 if (dhcp6_find_listval(head
, type
, &oprefix
, 0)) {
1771 if (type
== DHCP6_LISTVAL_PREFIX6
) {
1772 dprintf(LOG_NOTICE
, FNAME
,
1773 "duplicated prefix: %s/%d for %s",
1774 in6addr2str(&oprefix
.addr
, 0), oprefix
.plen
, name
);
1776 dprintf(LOG_NOTICE
, FNAME
,
1777 "duplicated address: %s for %s",
1778 in6addr2str(&oprefix
.addr
, 0), name
);
1783 /* validation about relationship of pltime and vltime */
1784 if (oprefix
.vltime
!= DHCP6_DURATION_INFINITE
&&
1785 (oprefix
.pltime
== DHCP6_DURATION_INFINITE
||
1786 oprefix
.pltime
> oprefix
.vltime
)) {
1787 if (type
== DHCP6_LISTVAL_PREFIX6
) {
1788 dprintf(LOG_NOTICE
, FNAME
,
1789 "%s/%d has larger preferred lifetime "
1790 "than valid lifetime",
1791 in6addr2str(&oprefix
.addr
, 0), oprefix
.plen
);
1793 dprintf(LOG_NOTICE
, FNAME
,
1794 "%s has larger preferred lifetime "
1795 "than valid lifetime",
1796 in6addr2str(&oprefix
.addr
, 0));
1801 /* insert the new prefix to the chain */
1802 if (dhcp6_add_listval(head
, type
, &oprefix
, NULL
) == NULL
) {
1810 find_iaconf(head
, type
, iaid
)
1811 struct ia_conflist
*head
;
1815 struct ia_conf
*iac
;
1817 for (iac
= TAILQ_FIRST(head
); iac
; iac
= TAILQ_NEXT(iac
, link
)) {
1818 if (iac
->type
== type
&& iac
->iaid
== iaid
)
1829 struct host_conf
*host
;
1831 if ((host
= find_dynamic_hostconf(duid
)) != NULL
) {
1835 for (host
= host_conflist
; host
; host
= host
->next
) {
1836 if (host
->duid
.duid_len
== duid
->duid_len
&&
1837 memcmp(host
->duid
.duid_id
, duid
->duid_id
,
1838 host
->duid
.duid_len
) == 0) {
1847 find_authinfo(head
, name
)
1848 struct authinfo
*head
;
1851 struct authinfo
*ainfo
;
1853 for (ainfo
= head
; ainfo
; ainfo
= ainfo
->next
) {
1854 if (strcmp(ainfo
->name
, name
) == 0)
1861 struct dhcp6_prefix
*
1862 find_prefix6(list
, prefix
)
1863 struct dhcp6_list
*list
;
1864 struct dhcp6_prefix
*prefix
;
1866 struct dhcp6_listval
*v
;
1868 for (v
= TAILQ_FIRST(list
); v
; v
= TAILQ_NEXT(v
, link
)) {
1869 if (v
->val_prefix6
.plen
== prefix
->plen
&&
1870 IN6_ARE_ADDR_EQUAL(&v
->val_prefix6
.addr
, &prefix
->addr
)) {
1871 return (&v
->val_prefix6
);
1878 find_key(realm
, realmlen
, id
)
1883 struct keyinfo
*key
;
1885 for (key
= key_list
; key
; key
= key
->next
) {
1886 if (key
->realmlen
== realmlen
&&
1887 memcmp(key
->realm
, realm
, realmlen
) == 0 &&
1904 if (qstr
[0] != '"' || len
< 2 || qstr
[len
- 1] != '"')
1907 if ((dup
= malloc(len
)) == NULL
)
1910 memcpy(dup
, qstr
+ 1, len
- 1);
1911 dup
[len
- 2] = '\0';
1917 configure_pool(poollist
)
1918 struct cf_namelist
*poollist
;
1920 struct cf_namelist
*plp
;
1922 dprintf(LOG_DEBUG
, FNAME
, "called");
1924 if (poollist
&& dhcp6_mode
!= DHCP6_MODE_SERVER
) {
1925 dprintf(LOG_ERR
, FNAME
, "%s:%d "
1926 "pool statement is server-only",
1927 configfilename
, poollist
->line
);
1931 for (plp
= poollist
; plp
; plp
= plp
->next
) {
1932 struct pool_conf
*pool
= NULL
;
1933 struct dhcp6_range
*range
= NULL
;
1934 struct cf_list
*cfl
;
1936 for (cfl
= plp
->params
; cfl
; cfl
= cfl
->next
) {
1942 dprintf(LOG_ERR
, FNAME
, "%s:%d "
1943 "invalid pool configuration",
1944 configfilename
, cfl
->line
);
1950 dprintf(LOG_ERR
, FNAME
, "%s:%d "
1951 "pool '%s' has no range declaration",
1952 configfilename
, plp
->line
,
1956 if ((pool
= create_pool(plp
->name
, range
)) == NULL
) {
1957 dprintf(LOG_ERR
, FNAME
,
1958 "faled to craete pool '%s'", plp
->name
);
1961 pool
->next
= pool_conflist0
;
1962 pool_conflist0
= pool
;
1968 /* there is currently nothing special to recover the error */
1973 clear_poolconf(plist
)
1974 struct pool_conf
*plist
;
1976 struct pool_conf
*pool
, *pool_next
;
1978 dprintf(LOG_DEBUG
, FNAME
, "called");
1980 for (pool
= plist
; pool
; pool
= pool_next
) {
1981 pool_next
= pool
->next
;
1988 create_dynamic_hostconf(duid
, pool
)
1990 struct dhcp6_poolspec
*pool
;
1992 struct dynamic_hostconf
*dynconf
= NULL
;
1993 struct host_conf
*host
;
1995 static int init
= 1;
1998 TAILQ_INIT(&dynamic_hostconf_head
);
1999 dynamic_hostconf_count
= 0;
2003 if (dynamic_hostconf_count
>= DHCP6_DYNAMIC_HOSTCONF_MAX
) {
2004 struct dynamic_hostconf_listhead
*head
= &dynamic_hostconf_head
;
2006 dprintf(LOG_DEBUG
, FNAME
, "reached to the max count (count=%lu)",
2007 dynamic_hostconf_count
);
2009 /* Find the last entry that doesn't need authentication */
2010 TAILQ_FOREACH_REVERSE(dynconf
, head
, dynamic_hostconf_listhead
, link
)
2011 if (dynconf
->host
->delayedkey
== NULL
)
2013 if (dynconf
== NULL
)
2014 dynconf
= TAILQ_LAST(head
, dynamic_hostconf_listhead
);
2015 TAILQ_REMOVE(head
, dynconf
, link
);
2016 dynamic_hostconf_count
--;
2017 clear_hostconf(dynconf
->host
);
2019 if ((dynconf
= malloc(sizeof(*dynconf
))) == NULL
) {
2020 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
2024 memset(dynconf
, 0, sizeof(*dynconf
));
2026 if ((host
= malloc(sizeof(*host
))) == NULL
) {
2027 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
2030 memset(host
, 0, sizeof(*host
));
2031 TAILQ_INIT(&host
->prefix_list
);
2032 TAILQ_INIT(&host
->addr_list
);
2034 if ((strid
= duidstr(duid
)) == NULL
)
2036 if ((host
->name
= strdup(strid
)) == NULL
) {
2037 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
2040 if (duidcpy(&host
->duid
, duid
) != 0) {
2044 if ((host
->pool
.name
= strdup(pool
->name
)) == NULL
) {
2045 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
2049 host
->pool
.pltime
= pool
->pltime
;
2050 host
->pool
.vltime
= pool
->vltime
;
2052 dynconf
->host
= host
;
2053 TAILQ_INSERT_HEAD(&dynamic_hostconf_head
, dynconf
, link
);
2054 dynamic_hostconf_count
++;
2056 dprintf(LOG_DEBUG
, FNAME
, "created host_conf (name=%s)", host
->name
);
2062 clear_hostconf(host
); /* host->next must be NULL */
2070 find_dynamic_hostconf(duid
)
2073 struct dynamic_hostconf
*dynconf
= NULL
;
2075 TAILQ_FOREACH(dynconf
, &dynamic_hostconf_head
, link
) {
2076 if (dynconf
->host
->duid
.duid_len
== duid
->duid_len
&&
2077 memcmp(dynconf
->host
->duid
.duid_id
, duid
->duid_id
,
2078 duid
->duid_len
) == 0)
2084 TAILQ_REMOVE(&dynamic_hostconf_head
, dynconf
, link
);
2085 TAILQ_INSERT_HEAD(&dynamic_hostconf_head
, dynconf
, link
);
2087 return (dynconf
->host
);
2094 create_pool(name
, range
)
2096 struct dhcp6_range
*range
;
2098 struct pool_conf
*pool
= NULL
;
2100 if (!name
|| !range
) {
2104 dprintf(LOG_DEBUG
, FNAME
, "name=%s, range=%s->%s", name
,
2105 in6addr2str(&range
->min
, 0), in6addr2str(&range
->max
, 0));
2107 if (in6_addr_cmp(&range
->min
, &range
->max
) > 0) {
2108 dprintf(LOG_ERR
, FNAME
, "invalid address range %s->%s",
2109 in6addr2str(&range
->min
, 0),
2110 in6addr2str(&range
->max
, 0));
2114 if ((pool
= malloc(sizeof(struct pool_conf
))) == NULL
) {
2115 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
2118 if ((pool
->name
= strdup(name
)) == NULL
) {
2119 dprintf(LOG_ERR
, FNAME
, "memory allocation failed");
2123 pool
->min
= range
->min
;
2124 pool
->max
= range
->max
;
2133 struct pool_conf
*pool
= NULL
;
2138 dprintf(LOG_DEBUG
, FNAME
, "name=%s", name
);
2140 for (pool
= pool_conflist
; pool
; pool
= pool
->next
) {
2141 if (strcmp(name
, pool
->name
) == 0) {
2142 dprintf(LOG_DEBUG
, FNAME
, "found (name=%s)", name
);
2147 dprintf(LOG_DEBUG
, FNAME
, "not found (name=%s)", name
);
2154 get_free_address_from_pool(pool
, addr
)
2155 struct pool_conf
*pool
;
2156 struct in6_addr
*addr
;
2158 struct in6_addr cur
;
2162 dprintf(LOG_DEBUG
, FNAME
, "called (pool=%s)", pool
->name
);
2164 for (cur
= pool
->min
; in6_addr_cmp(&cur
, &pool
->max
) <= 0;
2165 in6_addr_inc(&cur
)) {
2166 if (!is_leased(&cur
) &&
2167 !IN6_IS_ADDR_MULTICAST(&cur
) &&
2168 !IN6_IS_ADDR_LINKLOCAL(&cur
) &&
2169 !IN6_IS_ADDR_SITELOCAL(&cur
)) {
2170 dprintf(LOG_DEBUG
, FNAME
, "found %s",
2171 in6addr2str(&cur
, 0));
2176 dprintf(LOG_DEBUG
, FNAME
, "next address %s",
2177 in6addr2str(&cur
, 0));
2180 dprintf(LOG_NOTICE
, FNAME
, "no available address");
2185 is_available_in_pool(pool
, addr
)
2186 struct pool_conf
*pool
;
2187 struct in6_addr
*addr
;
2192 dprintf(LOG_DEBUG
, FNAME
, "pool=%s, addr=%s",
2193 pool
->name
, in6addr2str(addr
, 0));
2195 if (in6_addr_cmp(addr
, &pool
->min
) >= 0 &&
2196 in6_addr_cmp(addr
, &pool
->max
) <= 0 &&
2198 !IN6_IS_ADDR_MULTICAST(addr
) &&
2199 !IN6_IS_ADDR_LINKLOCAL(addr
) &&
2200 !IN6_IS_ADDR_SITELOCAL(addr
)) {
2204 dprintf(LOG_DEBUG
, FNAME
, "unavailable address (pool=%s, addr=%s)",
2205 pool
->name
, in6addr2str(addr
, 0));
2212 in6_addr_cmp(addr1
, addr2
)
2213 struct in6_addr
*addr1
, *addr2
;
2217 for (i
= 0; i
< 16; i
++) {
2218 if (addr1
->s6_addr
[i
] != addr2
->s6_addr
[i
]) {
2219 if (addr1
->s6_addr
[i
] > addr2
->s6_addr
[i
])
2232 struct in6_addr
*addr
;
2236 for (i
= 15; i
>= 0; i
--) {
2237 if (++(addr
->s6_addr
[i
]) != 0x00)