1/* $Id: config.c,v 1.1.1.1 2006/12/04 00:45:20 Exp $ */ 2/* ported from KAME: config.c,v 1.21 2002/09/24 14:20:49 itojun Exp */ 3 4/* 5 * Copyright (C) 2002 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32#include <sys/types.h> 33#include <sys/socket.h> 34 35#include <net/if.h> 36 37#include <netinet/in.h> 38 39#include <syslog.h> 40#include <stdlib.h> 41#include <stdio.h> 42#include <string.h> 43#include <ifaddrs.h> 44 45#include "queue.h" 46#include "dhcp6.h" 47#include "config.h" 48#include "common.h" 49 50extern int errno; 51 52static struct dhcp6_ifconf *dhcp6_ifconflist; 53static struct host_conf *host_conflist0, *host_conflist; 54static struct dhcp6_list dnslist0; 55 56enum { DHCPOPTCODE_SEND, DHCPOPTCODE_REQUEST, DHCPOPTCODE_ALLOW }; 57 58static int add_options __P((int, struct dhcp6_ifconf *, struct cf_list *)); 59static int add_address __P((struct dhcp6_list *, struct dhcp6_addr *)); 60static int add_option __P((struct dhcp6_option_list *, struct cf_list *)); 61static int clear_option_list __P((struct dhcp6_option_list *)); 62 63static void clear_ifconf __P((struct dhcp6_ifconf *)); 64static void clear_hostconf __P((struct host_conf *)); 65 66/* Foxconn added start pling 09/17/2010 */ 67static char user_class[MAX_USER_CLASS_LEN]; 68int set_dhcpc_user_class(char *str) 69{ 70 strcpy(user_class, str); 71 dprintf(LOG_INFO, "Set User-class [%s]", user_class); 72 return 0; 73} 74/* Foxconn added end pling 09/17/2010 */ 75 76/* Foxconn added start pling 10/07/2010 */ 77/* For testing purposes */ 78extern u_int32_t xid_solicit; 79extern u_int32_t xid_request; 80extern u_int32_t duid_time; 81/* Foxconn added end pling 10/07/2010 */ 82 83int 84configure_interface(const struct cf_namelist *iflist) 85{ 86 const struct cf_namelist *ifp; 87 struct dhcp6_ifconf *ifc; 88 89 for (ifp = iflist; ifp; ifp = ifp->next) { 90 struct cf_list *cfl; 91 92 if ((ifc = malloc(sizeof(*ifc))) == NULL) { 93 dprintf(LOG_ERR, "%s" 94 "memory allocation for %s failed", FNAME, 95 ifp->name); 96 goto bad; 97 } 98 memset(ifc, 0, sizeof(*ifc)); 99 ifc->next = dhcp6_ifconflist; 100 dhcp6_ifconflist = ifc; 101 102 if ((ifc->ifname = strdup(ifp->name)) == NULL) { 103 dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME); 104 goto bad; 105 } 106 107 ifc->server_pref = DH6OPT_PREF_UNDEF; 108 TAILQ_INIT(&ifc->reqopt_list); 109 TAILQ_INIT(&ifc->addr_list); 110 TAILQ_INIT(&ifc->option_list); 111 112 for (cfl = ifp->params; cfl; cfl = cfl->next) { 113 switch(cfl->type) { 114 case DECL_REQUEST: 115 if (dhcp6_mode != DHCP6_MODE_CLIENT) { 116 dprintf(LOG_INFO, "%s" "%s:%d " 117 "client-only configuration", 118 FNAME, configfilename, 119 cfl->line); 120 goto bad; 121 } 122 if (add_options(DHCPOPTCODE_REQUEST, 123 ifc, cfl->list)) { 124 goto bad; 125 } 126 break; 127 case DECL_SEND: 128 if (add_options(DHCPOPTCODE_SEND, 129 ifc, cfl->list)) { 130 goto bad; 131 } 132 break; 133 case DECL_ALLOW: 134 if (add_options(DHCPOPTCODE_ALLOW, 135 ifc, cfl->list)) { 136 goto bad; 137 } 138 break; 139 case DECL_INFO_ONLY: 140 if (dhcp6_mode == DHCP6_MODE_CLIENT) 141 { 142 ifc->send_flags |= DHCIFF_INFO_ONLY; 143 /* Foxconn added start pling 09/23/2010 */ 144 set_dhcp6c_flags(DHCIFF_INFO_ONLY); 145 /* Foxconn added end pling 09/23/2010 */ 146 } 147 break; 148 case DECL_TEMP_ADDR: 149 if (dhcp6_mode == DHCP6_MODE_CLIENT) 150 ifc->send_flags |= DHCIFF_TEMP_ADDRS; 151 break; 152 case DECL_PREFERENCE: 153 if (dhcp6_mode != DHCP6_MODE_SERVER) { 154 dprintf(LOG_INFO, "%s" "%s:%d " 155 "server-only configuration", 156 FNAME, configfilename, 157 cfl->line); 158 goto bad; 159 } 160 ifc->server_pref = (int)cfl->num; 161 if (ifc->server_pref < 0 || 162 ifc->server_pref > 255) { 163 dprintf(LOG_INFO, "%s" "%s:%d " 164 "bad value: %d", FNAME, 165 configfilename, cfl->line, 166 ifc->server_pref); 167 goto bad; 168 } 169 break; 170 case DECL_IAID: 171 if (ifc->iaidinfo.iaid) { 172 dprintf(LOG_ERR, "%s" "%s:%d " 173 "duplicated IAID for %s", 174 FNAME, configfilename, 175 cfl->line, ifc->ifname); 176 goto bad; 177 } else 178 ifc->iaidinfo.iaid = (u_int32_t)cfl->num; 179 break; 180 case DECL_RENEWTIME: 181 if (ifc->iaidinfo.renewtime) { 182 dprintf(LOG_ERR, "%s" "%s:%d " 183 "duplicated renewtime for %s", 184 FNAME, configfilename, 185 cfl->line, ifc->ifname); 186 goto bad; 187 } else 188 ifc->iaidinfo.renewtime = (u_int32_t)cfl->num; 189 break; 190 case DECL_REBINDTIME: 191 if (ifc->iaidinfo.iaid) { 192 dprintf(LOG_ERR, "%s" "%s:%d " 193 "duplicated rebindtime for %s", 194 FNAME, configfilename, 195 cfl->line, ifc->ifname); 196 goto bad; 197 } else 198 ifc->iaidinfo.rebindtime = (u_int32_t)cfl->num; 199 break; 200 case DECL_ADDRESS: 201 if (add_address(&ifc->addr_list, cfl->ptr)) { 202 dprintf(LOG_ERR, "%s" "failed " 203 "to configure ipv6address for %s", 204 FNAME, ifc->ifname); 205 goto bad; 206 } 207 break; 208 case DECL_PREFIX_REQ: 209 /* XX: ToDo */ 210 break; 211 case DECL_PREFIX_INFO: 212 break; 213 case DECL_PREFIX_DELEGATION_INTERFACE: 214 if (add_option(&ifc->option_list, cfl)){ 215 dprintf(LOG_ERR, "%s failed to configure prefix-delegation-interface for %s", 216 FNAME, ifc->ifname); 217 goto bad; 218 } 219 break; 220 /* Foxconn added start pling 08/26/2009 */ 221 /* Add flag to send dhcpv6 solicit only for DHCP client. 222 * Used by IPv6 auto detection. 223 */ 224 case DECL_SOLICIT_ONLY: 225 if (dhcp6_mode == DHCP6_MODE_CLIENT) 226 { 227 dprintf(LOG_ERR, "Send DHCPC solicit only!"); 228 ifc->send_flags |= DHCIFF_SOLICIT_ONLY; 229 } 230 break; 231 /* Foxconn added end pling 08/26/2009 */ 232 /* Foxconn added start pling 09/07/2010 */ 233 /* Support user-class for DHCP client */ 234 case DECL_USER_CLASS: 235 if (dhcp6_mode == DHCP6_MODE_CLIENT) 236 { 237 dprintf(LOG_ERR, "%s assign user_class='%s'", FNAME, user_class); 238 if (strlen(user_class)) 239 strcpy(ifc->user_class, user_class); 240 else 241 ifc->user_class[0] = '\0'; 242 } 243 break; 244 /* Foxconn added end pling 09/07/2010 */ 245 /* Foxconn added start pling 09/21/2010 */ 246 /* For DHCPv6 readylogo, need to send IANA and IAPD separately. 247 */ 248 case DECL_IANA_ONLY: 249 if (dhcp6_mode == DHCP6_MODE_CLIENT) 250 { 251 dprintf(LOG_ERR, "Accept IANA only!"); 252 set_dhcp6c_flags(DHCIFF_IANA_ONLY); 253 } 254 break; 255 case DECL_IAPD_ONLY: 256 if (dhcp6_mode == DHCP6_MODE_CLIENT) 257 { 258 dprintf(LOG_ERR, "Accept IAPD only!"); 259 set_dhcp6c_flags(DHCIFF_IAPD_ONLY); 260 } 261 break; 262 /* Foxconn added end pling 09/21/2010 */ 263 /* Foxconn added start pling 10/07/2010 */ 264 /* For Testing purposes */ 265 case DECL_XID_SOL: 266 xid_solicit = (u_int32_t)cfl->num; 267 break; 268 case DECL_XID_REQ: 269 xid_request = (u_int32_t)cfl->num; 270 break; 271 case DECL_DUID_TIME: 272 duid_time = (u_int32_t)cfl->num; 273 break; 274 /* Foxconn added end pling 10/07/2010 */ 275 default: 276 dprintf(LOG_ERR, "%s" "%s:%d " 277 "invalid interface configuration", 278 FNAME, configfilename, cfl->line); 279 goto bad; 280 } 281 } 282 } 283 284 return (0); 285 286 bad: 287 clear_ifconf(dhcp6_ifconflist); 288 dhcp6_ifconflist = NULL; 289 return (-1); 290} 291 292int 293configure_host(const struct cf_namelist *hostlist) 294{ 295 const struct cf_namelist *host; 296 struct host_conf *hconf; 297 298 for (host = hostlist; host; host = host->next) { 299 struct cf_list *cfl; 300 301 if ((hconf = malloc(sizeof(*hconf))) == NULL) { 302 dprintf(LOG_ERR, "%s" "memory allocation failed " 303 "for host %s", FNAME, host->name); 304 goto bad; 305 } 306 memset(hconf, 0, sizeof(*hconf)); 307 TAILQ_INIT(&hconf->addr_list); 308 TAILQ_INIT(&hconf->addr_binding_list); 309 TAILQ_INIT(&hconf->prefix_list); 310 TAILQ_INIT(&hconf->prefix_binding_list); 311 hconf->next = host_conflist0; 312 host_conflist0 = hconf; 313 314 if ((hconf->name = strdup(host->name)) == NULL) { 315 dprintf(LOG_ERR, "%s" "failed to copy host name: %s", 316 FNAME, host->name); 317 goto bad; 318 } 319 320 for (cfl = host->params; cfl; cfl = cfl->next) { 321 switch(cfl->type) { 322 case DECL_DUID: 323 if (hconf->duid.duid_id) { 324 dprintf(LOG_ERR, "%s" "%s:%d " 325 "duplicated DUID for %s", 326 FNAME, configfilename, 327 cfl->line, host->name); 328 goto bad; 329 } 330 if ((configure_duid((char *)cfl->ptr, 331 &hconf->duid)) != 0) { 332 dprintf(LOG_ERR, "%s" "%s:%d " 333 "failed to configure " 334 "DUID for %s", FNAME, 335 configfilename, cfl->line, 336 host->name); 337 goto bad; 338 } 339 dprintf(LOG_DEBUG, "%s" 340 "configure DUID for %s: %s", FNAME, 341 host->name, duidstr(&hconf->duid)); 342 break; 343 case DECL_PREFIX: 344 if (add_address(&hconf->prefix_list, cfl->ptr)) { 345 dprintf(LOG_ERR, "%s" "failed " 346 "to configure prefix for %s", 347 FNAME, host->name); 348 goto bad; 349 } 350 break; 351 case DECL_IAID: 352 if (hconf->iaidinfo.iaid) { 353 dprintf(LOG_ERR, "%s" "%s:%d " 354 "duplicated IAID for %s", 355 FNAME, configfilename, 356 cfl->line, host->name); 357 goto bad; 358 } else 359 hconf->iaidinfo.iaid = (u_int32_t)cfl->num; 360 break; 361 case DECL_RENEWTIME: 362 if (hconf->iaidinfo.renewtime) { 363 dprintf(LOG_ERR, "%s" "%s:%d " 364 "duplicated renewtime for %s", 365 FNAME, configfilename, 366 cfl->line, host->name); 367 goto bad; 368 } else 369 hconf->iaidinfo.renewtime = (u_int32_t)cfl->num; 370 break; 371 case DECL_REBINDTIME: 372 if (hconf->iaidinfo.rebindtime) { 373 dprintf(LOG_ERR, "%s" "%s:%d " 374 "duplicated rebindtime for %s", 375 FNAME, configfilename, 376 cfl->line, host->name); 377 goto bad; 378 } else 379 hconf->iaidinfo.rebindtime = (u_int32_t)cfl->num; 380 break; 381 case DECL_ADDRESS: 382 if (add_address(&hconf->addr_list, cfl->ptr)) { 383 dprintf(LOG_ERR, "%s" "failed " 384 "to configure ipv6address for %s", 385 FNAME, host->name); 386 goto bad; 387 } 388 break; 389 case DECL_LINKLOCAL: 390 if (IN6_IS_ADDR_UNSPECIFIED(&hconf->linklocal)) { 391 dprintf(LOG_ERR, "%s" "%s:%d " 392 "duplicated linklocal for %s", 393 FNAME, configfilename, 394 cfl->line, host->name); 395 goto bad; 396 } else 397 memcpy(&hconf->linklocal, cfl->ptr, 398 sizeof(hconf->linklocal) ); 399 break; 400 default: 401 dprintf(LOG_ERR, "%s: %d invalid host configuration for %s", 402 configfilename, cfl->line, host->name); 403 goto bad; 404 } 405 } 406 } 407 408 return (0); 409 410 bad: 411 /* there is currently nothing special to recover the error */ 412 return (-1); 413} 414 415int 416configure_global_option(void) 417{ 418 struct cf_list *cl; 419 420 /* DNS servers */ 421 if (cf_dns_list && dhcp6_mode != DHCP6_MODE_SERVER) { 422 dprintf(LOG_INFO, "%s" "%s:%d server-only configuration", 423 FNAME, configfilename, cf_dns_list->line); 424 goto bad; 425 } 426 TAILQ_INIT(&dnslist0); 427 for (cl = cf_dns_list; cl; cl = cl->next) { 428 /* duplication check */ 429 if (dhcp6_find_listval(&dnslist0, cl->ptr, 430 DHCP6_LISTVAL_ADDR6)) { 431 dprintf(LOG_INFO, "%s" 432 "%s:%d duplicated DNS server: %s", FNAME, 433 configfilename, cl->line, 434 in6addr2str((struct in6_addr *)cl->ptr, 0)); 435 goto bad; 436 } 437 if (dhcp6_add_listval(&dnslist0, cl->ptr, 438 DHCP6_LISTVAL_ADDR6) == NULL) { 439 dprintf(LOG_ERR, "%s" "failed to add a DNS server", 440 FNAME); 441 goto bad; 442 } 443 } 444 445 return 0; 446 447 bad: 448 return -1; 449} 450 451 452void 453configure_cleanup(void) 454{ 455 clear_ifconf(dhcp6_ifconflist); 456 dhcp6_ifconflist = NULL; 457 clear_hostconf(host_conflist0); 458 host_conflist0 = NULL; 459 dhcp6_clear_list(&dnslist0); 460 TAILQ_INIT(&dnslist0); 461} 462 463void 464configure_commit(void) 465{ 466 struct dhcp6_ifconf *ifc; 467 struct dhcp6_if *ifp; 468 469 /* commit interface configuration */ 470 for (ifc = dhcp6_ifconflist; ifc; ifc = ifc->next) { 471 if ((ifp = find_ifconfbyname(ifc->ifname)) != NULL) { 472 ifp->send_flags = ifc->send_flags; 473 474 ifp->allow_flags = ifc->allow_flags; 475 476 dhcp6_clear_list(&ifp->reqopt_list); 477 ifp->reqopt_list = ifc->reqopt_list; 478 TAILQ_INIT(&ifc->reqopt_list); 479 480 dhcp6_clear_list(&ifp->addr_list); 481 ifp->addr_list = ifc->addr_list; 482 TAILQ_INIT(&ifc->addr_list); 483 484 dhcp6_clear_list(&ifp->prefix_list); 485 ifp->prefix_list = ifc->prefix_list; 486 TAILQ_INIT(&ifc->prefix_list); 487 488 clear_option_list(&ifp->option_list); 489 ifp->option_list = ifc->option_list; 490 TAILQ_INIT(&ifc->option_list); 491 492 ifp->server_pref = ifc->server_pref; 493 494 /* Foxconn added start pling 09/07/2010 */ 495 /* configure user-class */ 496 if (dhcp6_mode == DHCP6_MODE_CLIENT) 497 strcpy(ifp->user_class, ifc->user_class); 498 /* Foxconn added end pling 09/07/2010 */ 499 500 memcpy(&ifp->iaidinfo, &ifc->iaidinfo, sizeof(ifp->iaidinfo)); 501 } 502 } 503 clear_ifconf(dhcp6_ifconflist); 504 505 /* commit prefix configuration */ 506 if (host_conflist) { 507 /* clear previous configuration. (need more work?) */ 508 clear_hostconf(host_conflist); 509 } 510 host_conflist = host_conflist0; 511 host_conflist0 = NULL; 512} 513 514static void 515clear_ifconf(struct dhcp6_ifconf *iflist) 516{ 517 struct dhcp6_ifconf *ifc, *ifc_next; 518 519 for (ifc = iflist; ifc; ifc = ifc_next) { 520 ifc_next = ifc->next; 521 522 free(ifc->ifname); 523 524 dhcp6_clear_list(&ifc->reqopt_list); 525 526 free(ifc); 527 } 528} 529 530static void 531clear_hostconf(struct host_conf *hlist) 532{ 533 struct host_conf *host, *host_next; 534 struct dhcp6_listval *p; 535 536 for (host = hlist; host; host = host_next) { 537 host_next = host->next; 538 539 free(host->name); 540 while ((p = TAILQ_FIRST(&host->prefix_list)) != NULL) { 541 TAILQ_REMOVE(&host->prefix_list, p, link); 542 free(p); 543 } 544 if (host->duid.duid_id) 545 free(host->duid.duid_id); 546 free(host); 547 } 548} 549 550static int 551add_options(int opcode, struct dhcp6_ifconf *ifc, 552 struct cf_list *cfl0) 553{ 554 struct dhcp6_listval *opt; 555 struct cf_list *cfl; 556 int opttype; 557 558 for (cfl = cfl0; cfl; cfl = cfl->next) { 559 if (opcode == DHCPOPTCODE_REQUEST) { 560 for (opt = TAILQ_FIRST(&ifc->reqopt_list); opt; 561 opt = TAILQ_NEXT(opt, link)) { 562 if (opt->val_num == cfl->type) { 563 dprintf(LOG_INFO, "%s" 564 "duplicated requested" 565 " option: %s", FNAME, 566 dhcp6optstr(cfl->type)); 567 goto next; /* ignore it */ 568 } 569 } 570 } 571 572 switch(cfl->type) { 573 case DHCPOPT_RAPID_COMMIT: 574 switch(opcode) { 575 case DHCPOPTCODE_SEND: 576 ifc->send_flags |= DHCIFF_RAPID_COMMIT; 577 break; 578 case DHCPOPTCODE_ALLOW: 579 ifc->allow_flags |= DHCIFF_RAPID_COMMIT; 580 break; 581 default: 582 dprintf(LOG_ERR, "%s" "invalid operation (%d) " 583 "for option type (%d)", 584 FNAME, opcode, cfl->type); 585 return (-1); 586 } 587 break; 588 case DHCPOPT_PREFIX_DELEGATION: 589 switch(opcode) { 590 case DHCPOPTCODE_REQUEST: 591 ifc->send_flags |= DHCIFF_PREFIX_DELEGATION; 592 break; 593 default: 594 dprintf(LOG_ERR, "%s" "invalid operation (%d) " 595 "for option type (%d)", 596 FNAME, opcode, cfl->type); 597 return (-1); 598 } 599 break; 600 601 case DHCPOPT_DNS: 602 switch(opcode) { 603 case DHCPOPTCODE_REQUEST: 604 opttype = DH6OPT_DNS_SERVERS; 605 if (dhcp6_add_listval(&ifc->reqopt_list, 606 &opttype, DHCP6_LISTVAL_NUM) == NULL) { 607 dprintf(LOG_ERR, "%s" "failed to " 608 "configure an option", FNAME); 609 return (-1); 610 } 611 break; 612 default: 613 dprintf(LOG_ERR, "%s" "invalid operation (%d) " 614 "for option type (%d)", 615 FNAME, opcode, cfl->type); 616 break; 617 } 618 break; 619 620 /* Foxconn added start pling 09/23/2010 */ 621 /* To support domain search list for DHCPv6 readylogo tests */ 622 case DHCPOPT_DOMAIN_LIST: 623 switch(opcode) { 624 case DHCPOPTCODE_REQUEST: 625 opttype = DH6OPT_DOMAIN_LIST; 626 if (dhcp6_add_listval(&ifc->reqopt_list, 627 &opttype, DHCP6_LISTVAL_NUM) == NULL) { 628 dprintf(LOG_ERR, "%s" "failed to " 629 "configure an option", FNAME); 630 return (-1); 631 } 632 break; 633 default: 634 dprintf(LOG_ERR, "%s" "invalid operation (%d) " 635 "for option type (%d)", 636 FNAME, opcode, cfl->type); 637 break; 638 } 639 break; 640 /* Foxconn added end pling 09/23/2010 */ 641 642 default: 643 dprintf(LOG_ERR, "%s" 644 "unknown option type: %d", FNAME, cfl->type); 645 return (-1); 646 } 647 648 next:; 649 } 650 651 return (0); 652} 653 654static int 655add_address(struct dhcp6_list *addr_list, 656 struct dhcp6_addr *v6addr) 657{ 658 struct dhcp6_listval *lv, *val; 659 660 /* avoid invalid addresses */ 661 if (IN6_IS_ADDR_RESERVED(&v6addr->addr)) { 662 dprintf(LOG_ERR, "%s" "invalid address: %s", 663 FNAME, in6addr2str(&v6addr->addr, 0)); 664 return (-1); 665 } 666 667 /* address duplication check */ 668 for (lv = TAILQ_FIRST(addr_list); lv; 669 lv = TAILQ_NEXT(lv, link)) { 670 if (IN6_ARE_ADDR_EQUAL(&lv->val_dhcp6addr.addr, &v6addr->addr) && 671 lv->val_dhcp6addr.plen == v6addr->plen) { 672 dprintf(LOG_ERR, "%s" 673 "duplicated address: %s/%d ", FNAME, 674 in6addr2str(&v6addr->addr, 0), v6addr->plen); 675 return (-1); 676 } 677 } 678 if ((val = (struct dhcp6_listval *)malloc(sizeof(*val))) == NULL) 679 dprintf(LOG_ERR, "%s" "memory allocation failed", FNAME); 680 memset(val, 0, sizeof(*val)); 681 memcpy(&val->val_dhcp6addr, v6addr, sizeof(val->val_dhcp6addr)); 682 dprintf(LOG_DEBUG, "%s" "add address: %s", 683 FNAME, in6addr2str(&v6addr->addr, 0)); 684 TAILQ_INSERT_TAIL(addr_list, val, link); 685 return (0); 686} 687 688int add_option (struct dhcp6_option_list *opts, struct cf_list *cfl) 689{ 690 struct dhcp6_option *opt ; 691 692 if ( get_if_option( opts, cfl->type ) != 0L ) 693 return (-1); 694 695 switch (cfl->type) 696 { 697 case DECL_PREFIX_DELEGATION_INTERFACE: 698 opt = (struct dhcp6_option*)malloc(sizeof(struct dhcp6_option)); 699 opt->type = cfl->type; 700 if ( cfl->ptr != 0L ) 701 { 702 opt->len = strlen((char*)(cfl->ptr))+1; 703 opt->val = malloc(opt->len); 704 memcpy(opt->val, cfl->ptr, opt->len); 705 }else 706 { 707 opt->val = malloc(1); 708 opt->len = 0; 709 *((char*)(opt->val))='\0'; 710 } 711 TAILQ_INSERT_TAIL(opts, opt, link); 712 break; 713 default: 714 break; 715 } 716 return (0); 717} 718 719int clear_option_list (struct dhcp6_option_list *opts) 720{ 721 struct dhcp6_option *opt; 722 while ((opt = TAILQ_FIRST(opts)) != NULL) { 723 TAILQ_REMOVE(opts, opt, link); 724 free(opt); 725 } 726} 727 728void *get_if_option( struct dhcp6_option_list *opts, int type ) 729{ 730 struct dhcp6_option *opt; 731 TAILQ_FOREACH( opt, opts, link) 732 { 733 if ( opt->type == type ) 734 return opt->val; 735 } 736 return 0L; 737} 738