1/* $Id: server6_parse.y,v 1.1.1.1 2006-12-04 00:45:34 pmoutarl Exp $ */ 2 3/* 4 * Copyright (C) International Business Machines Corp., 2003 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 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. 18 * 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 29 * SUCH DAMAGE. 30 */ 31 32/* Author: Shirley Ma, xma@us.ibm.com */ 33 34%{ 35 36#include <stdio.h> 37#include <string.h> 38#include <stdlib.h> 39#include <syslog.h> 40#include <errno.h> 41#include <sys/socket.h> 42#include <net/if.h> 43#include <netinet/in.h> 44#include "queue.h" 45#include "dhcp6.h" 46#include "config.h" 47#include "common.h" 48#include "server6_conf.h" 49#include "hash.h" 50#include "lease.h" 51 52extern int num_lines; 53extern char *sfyytext; 54extern int sock; 55static struct interface *ifnetworklist = NULL; 56static struct link_decl *linklist = NULL; 57static struct host_decl *hostlist = NULL; 58static struct pool_decl *poollist = NULL; 59 60static struct interface *ifnetwork = NULL; 61static struct link_decl *link = NULL; 62static struct host_decl *host = NULL; 63static struct pool_decl *pool = NULL; 64static struct scopelist *currentscope = NULL; 65static struct scopelist *currentgroup = NULL; 66static int allow = 0; 67 68static void cleanup(void); 69void sfyyerror(char *msg); 70 71#define ABORT do { cleanup(); YYABORT; } while (0) 72 73extern int sfyylex __P((void)); 74%} 75%token <str> INTERFACE IFNAME 76%token <str> PREFIX 77%token <str> LINK 78%token <str> RELAY 79 80%token <str> STRING 81%token <num> NUMBER 82%token <snum> SIGNEDNUMBER 83%token <dec> DECIMAL 84%token <bool> BOOLEAN 85%token <addr> IPV6ADDR 86%token <str> INFINITY 87 88%token <str> HOST 89%token <str> POOL 90%token <str> RANGE 91%token <str> GROUP 92%token <str> LINKLOCAL 93%token <str> OPTION ALLOW SEND 94%token <str> PREFERENCE 95%token <str> RENEWTIME 96%token <str> REBINDTIME 97%token <str> RAPIDCOMMIT 98%token <str> ADDRESS 99%token <str> VALIDLIFETIME 100%token <str> PREFERLIFETIME 101%token <str> UNICAST 102%token <str> TEMPIPV6ADDR 103%token <str> DNS_SERVERS 104%token <str> SIP_SERVERS 105%token <str> NTP_SERVERS 106%token <str> DUID DUID_ID 107%token <str> IAID IAIDINFO 108%token <str> INFO_ONLY 109%token <str> TO 110 111%token <str> BAD_TOKEN 112%type <str> name 113%type <num> number_or_infinity 114%type <dhcp6addr> hostaddr6 hostprefix6 addr6para v6address 115 116%union { 117 unsigned int num; 118 int snum; 119 char *str; 120 int dec; 121 int bool; 122 struct in6_addr addr; 123 struct dhcp6_addr *dhcp6addr; 124} 125%% 126statements 127 : 128 | statements networkdef 129 ; 130 131networkdef 132 : ifdef 133 | groupdef 134 | confdecl 135 | linkdef 136 ; 137 138ifdef 139 : ifhead '{' ifbody '}' ';' 140 { 141 if (linklist) { 142 ifnetwork->linklist = linklist; 143 linklist = NULL; 144 } 145 if (hostlist) { 146 ifnetwork->hostlist = hostlist; 147 hostlist = NULL; 148 } 149 if (currentgroup) 150 ifnetwork->group = currentgroup->scope; 151 152 dprintf(LOG_DEBUG, "interface definition for %s is ok", ifnetwork->name); 153 ifnetwork->next = ifnetworklist; 154 ifnetworklist = ifnetwork; 155 ifnetwork = NULL; 156 157 globalgroup->iflist = ifnetworklist; 158 159 /* leave interface scope we know the current scope is not point to NULL*/ 160 currentscope = pop_double_list(currentscope); 161 } 162 ; 163 164ifhead 165 : INTERFACE IFNAME 166 { 167 struct interface *temp_if = ifnetworklist; 168 while (temp_if) 169 { 170 if (!strcmp(temp_if->name, $2)) 171 { 172 dprintf(LOG_ERR, "duplicate interface definition for %s", 173 temp_if->name); 174 ABORT; 175 } 176 temp_if = temp_if->next; 177 } 178 ifnetwork = (struct interface *)malloc(sizeof(*ifnetwork)); 179 if (ifnetwork == NULL) { 180 dprintf(LOG_ERR, "failed to allocate memory"); 181 ABORT; 182 } 183 memset(ifnetwork, 0, sizeof(*ifnetwork)); 184 TAILQ_INIT(&ifnetwork->ifscope.dnslist.addrlist); 185 TAILQ_INIT(&ifnetwork->ifscope.siplist); 186 TAILQ_INIT(&ifnetwork->ifscope.ntplist); 187 strncpy(ifnetwork->name, $2, strlen($2)); 188 if (get_linklocal(ifnetwork->name, &ifnetwork->linklocal) < 0) { 189 dprintf(LOG_ERR, "get device %s linklocal failed", ifnetwork->name); 190 } 191 192 /* check device, if the device is not available, 193 * it is OK, it might be added later 194 * so keep this in the configuration file. 195 */ 196 if (if_nametoindex(ifnetwork->name) == 0) { 197 dprintf(LOG_ERR, "this device %s doesn't exist.", $2); 198 } 199 /* set up hw_addr, link local, primary ipv6addr */ 200 /* enter interface scope */ 201 currentscope = push_double_list(currentscope, &ifnetwork->ifscope); 202 if (currentscope == NULL) 203 ABORT; 204 } 205 ; 206ifbody 207 : 208 | ifbody ifparams 209 ; 210 211ifparams 212 : linkdef 213 | hostdef 214 | groupdef 215 | confdecl 216 ; 217 218linkdef 219 : linkhead '{' linkbody '}' ';' 220 { 221 if (poollist) { 222 link->poollist = poollist; 223 poollist = NULL; 224 } 225 if (currentgroup) 226 link->group = currentgroup->scope; 227 228 link->next = linklist; 229 linklist = link; 230 link = NULL; 231 /* leave iink scope we know the current scope is not point to NULL*/ 232 currentscope = pop_double_list(currentscope); 233 } 234 ; 235 236linkhead 237 : LINK name 238 { 239 struct link_decl *temp_sub = linklist; 240 /* memory allocation for link */ 241 link = (struct link_decl *)malloc(sizeof(*link)); 242 if (link == NULL) { 243 dprintf(LOG_ERR, "failed to allocate memory"); 244 ABORT; 245 } 246 memset(link, 0, sizeof(*link)); 247 TAILQ_INIT(&link->linkscope.dnslist.addrlist); 248 TAILQ_INIT(&link->linkscope.siplist); 249 TAILQ_INIT(&link->linkscope.ntplist); 250 while (temp_sub) { 251 if (!strcmp(temp_sub->name, $2)) 252 { 253 dprintf(LOG_ERR, "duplicate link definition for %s", $2); 254 ABORT; 255 } 256 temp_sub = temp_sub->next; 257 } 258 /* link set */ 259 strncpy(link->name, $2, strlen($2)); 260 if (ifnetwork) 261 link->network = ifnetwork; 262 else { 263 /* create a ifnetwork for this interface */ 264 } 265 link->relaylist = NULL; 266 link->seglist = NULL; 267 /* enter link scope */ 268 currentscope = push_double_list(currentscope, &link->linkscope); 269 if (currentscope == NULL) 270 ABORT; 271 } 272 ; 273 274linkbody 275 : 276 | linkbody linkparams 277 ; 278 279linkparams 280 : pooldef 281 | rangedef 282 | prefixdef 283 | hostdef 284 | groupdef 285 | confdecl 286 | relaylist 287 ; 288 289relaylist 290 : relaylist relaypara 291 | relaypara 292 ; 293 294relaypara 295 : RELAY IPV6ADDR '/' NUMBER ';' 296 { 297 struct v6addrlist *temprelay; 298 if (!link) { 299 dprintf(LOG_ERR, "relay must be defined under link"); 300 ABORT; 301 } 302 temprelay = (struct v6addrlist *)malloc(sizeof(*temprelay)); 303 if (temprelay == NULL) { 304 dprintf(LOG_ERR, "failed to allocate memory"); 305 ABORT; 306 } 307 memset(temprelay, 0, sizeof(*temprelay)); 308 memcpy(&temprelay->v6addr.addr, &$2, sizeof(temprelay->v6addr.addr)); 309 temprelay->v6addr.plen = $4; 310 temprelay->next = link->relaylist; 311 link->relaylist = temprelay; 312 temprelay = NULL; 313 } 314 ; 315 316pooldef 317 : poolhead '{' poolbody '}' ';' 318 { 319 if (currentgroup) 320 pool->group = currentgroup->scope; 321 pool->next = poollist; 322 poollist = pool; 323 pool = NULL; 324 /* leave pool scope we know the current scope is not point to NULL*/ 325 currentscope = pop_double_list(currentscope); 326 } 327 ; 328 329poolhead 330 : POOL 331 { 332 if (!link) { 333 dprintf(LOG_ERR, "pooldef must be defined under link"); 334 ABORT; 335 } 336 pool = (struct pool_decl *)malloc(sizeof(*pool)); 337 if (pool == NULL) { 338 dprintf(LOG_ERR, "fail to allocate memory"); 339 ABORT; 340 } 341 memset(pool, 0, sizeof(*pool)); 342 TAILQ_INIT(&pool->poolscope.dnslist.addrlist); 343 TAILQ_INIT(&pool->poolscope.siplist); 344 TAILQ_INIT(&pool->poolscope.ntplist); 345 if (link) 346 pool->link = link; 347 348 /* enter pool scope */ 349 currentscope = push_double_list(currentscope, &pool->poolscope); 350 if (currentscope == NULL) 351 ABORT; 352 } 353 ; 354 355poolbody 356 : 357 | poolbody poolparas 358 ; 359 360poolparas 361 : hostdef 362 | groupdef 363 | rangedef 364 | prefixdef 365 | confdecl 366 ; 367 368prefixdef 369 : PREFIX IPV6ADDR '/' NUMBER ';' 370 { 371 struct v6prefix *v6prefix, *v6prefix0; 372 struct v6addr *prefix; 373 if (!link) { 374 dprintf(LOG_ERR, "prefix must be defined under link"); 375 ABORT; 376 } 377 v6prefix = (struct v6prefix *)malloc(sizeof(*v6prefix)); 378 if (v6prefix == NULL) { 379 dprintf(LOG_ERR, "failed to allocate memory"); 380 ABORT; 381 } 382 memset(v6prefix, 0, sizeof(*v6prefix)); 383 v6prefix->link = link; 384 if (pool) 385 v6prefix->pool = pool; 386 /* make sure the range ipv6 address within the prefixaddr */ 387 if ($4 > 128 || $4 < 0) { 388 dprintf(LOG_ERR, "invalid prefix length in line %d", num_lines); 389 ABORT; 390 } 391 prefix = getprefix(&$2, $4); 392 for (v6prefix0 = link->prefixlist; v6prefix0; v6prefix0 = v6prefix0->next) { 393 if (IN6_ARE_ADDR_EQUAL(prefix, &v6prefix0->prefix.addr) && 394 $4 == v6prefix0->prefix.plen) { 395 dprintf(LOG_ERR, "duplicated prefix defined within same link"); 396 ABORT; 397 } 398 } 399 /* check the assigned prefix is not reserved pv6 addresses */ 400 if (IN6_IS_ADDR_RESERVED(prefix)) { 401 dprintf(LOG_ERR, "config reserved prefix"); 402 ABORT; 403 } 404 memcpy(&v6prefix->prefix, prefix, sizeof(v6prefix->prefix)); 405 v6prefix->next = link->prefixlist; 406 link->prefixlist = v6prefix; 407 free(prefix); 408 } 409 ; 410 411rangedef 412 : RANGE IPV6ADDR TO IPV6ADDR '/' NUMBER ';' 413 { 414 struct v6addrseg *seg, *temp_seg; 415 struct v6addr *prefix1, *prefix2; 416 if (!link) { 417 dprintf(LOG_ERR, "range must be defined under link"); 418 ABORT; 419 } 420 seg = (struct v6addrseg *)malloc(sizeof(*seg)); 421 if (seg == NULL) { 422 dprintf(LOG_ERR, "failed to allocate memory"); 423 ABORT; 424 } 425 memset(seg, 0, sizeof(*seg)); 426 temp_seg = link->seglist; 427 seg->link = link; 428 if (pool) 429 seg->pool = pool; 430 /* make sure the range ipv6 address within the prefixaddr */ 431 if ($6 > 128 || $6 < 0) { 432 dprintf(LOG_ERR, "invalid prefix length in line %d", num_lines); 433 ABORT; 434 } 435 prefix1 = getprefix(&$2, $6); 436 prefix2 = getprefix(&$4, $6); 437 if (!prefix1 || !prefix2) { 438 dprintf(LOG_ERR, "address range defined error"); 439 ABORT; 440 } 441 if (ipv6addrcmp(&prefix1->addr, &prefix2->addr)) { 442 dprintf(LOG_ERR, 443 "address range defined doesn't in the same prefix range"); 444 ABORT; 445 } 446 if (ipv6addrcmp(&$2, &$4) < 0) { 447 memcpy(&seg->min, &$2, sizeof(seg->min)); 448 memcpy(&seg->max, &$4, sizeof(seg->max)); 449 } else { 450 memcpy(&seg->max, &$2, sizeof(seg->max)); 451 memcpy(&seg->min, &$4, sizeof(seg->min)); 452 } 453 /* check the assigned addresses are not reserved ipv6 addresses */ 454 if (IN6_IS_ADDR_RESERVED(&seg->max) || IN6_IS_ADDR_RESERVED(&seg->max)) { 455 dprintf(LOG_ERR, "config reserved ipv6address"); 456 ABORT; 457 } 458 459 memcpy(&seg->prefix, prefix1, sizeof(seg->prefix)); 460 memcpy(&seg->free, &seg->min, sizeof(seg->free)); 461 if (pool) 462 seg->pool = pool; 463 /* make sure there is no overlap in the rangelist */ 464 /* the segaddr is sorted by prefix len, thus most specific 465 ipv6 address is going to be assigned. 466 */ 467 if (!temp_seg) { 468 seg->next = NULL; 469 seg->prev = NULL; 470 link->seglist = seg; 471 } else { 472 for (; temp_seg; temp_seg = temp_seg->next) { 473 if ( prefix1->plen < temp_seg->prefix.plen) { 474 if (temp_seg->next == NULL) { 475 temp_seg->next = seg; 476 seg->prev = temp_seg; 477 seg->next = NULL; 478 break; 479 } 480 continue; 481 } 482 if (prefix1->plen == temp_seg->prefix.plen) { 483 if (!(ipv6addrcmp(&seg->min, &temp_seg->max) > 0 484 || ipv6addrcmp(&seg->max, &temp_seg->min) < 0)) { 485 dprintf(LOG_ERR, "overlap range addr defined"); 486 ABORT; 487 } 488 } 489 if (temp_seg->prev == NULL) { 490 link->seglist = seg; 491 seg->prev = NULL; 492 } else { 493 temp_seg->prev->next = seg; 494 seg->prev = temp_seg->prev; 495 } 496 temp_seg->prev = seg; 497 seg->next = temp_seg; 498 break; 499 } 500 } 501 free(prefix1); 502 free(prefix2); 503 } 504 ; 505 506groupdef 507 : grouphead '{' groupbody '}' ';' 508 { 509 /* return to prev group scope if any */ 510 currentgroup = pop_double_list(currentgroup); 511 512 /* leave current group scope */ 513 currentscope = pop_double_list(currentscope); 514 } 515 ; 516 517groupbody 518 : 519 | groupbody groupparas 520 ; 521 522groupparas 523 : hostdef 524 | pooldef 525 | linkdef 526 | rangedef 527 | prefixdef 528 | ifdef 529 | confdecl 530 ; 531 532grouphead 533 : GROUP 534 { 535 struct scope *groupscope; 536 groupscope = (struct scope *)malloc(sizeof(*groupscope)); 537 if (groupscope == NULL) { 538 dprintf(LOG_ERR, "group memory allocation failed"); 539 ABORT; 540 } 541 memset(groupscope, 0, sizeof(*groupscope)); 542 TAILQ_INIT(&groupscope->dnslist.addrlist); 543 TAILQ_INIT(&groupscope->siplist); 544 TAILQ_INIT(&groupscope->ntplist); 545 /* set up current group */ 546 currentgroup = push_double_list(currentgroup, groupscope); 547 if (currentgroup == NULL) 548 ABORT; 549 550 /* enter group scope */ 551 currentscope = push_double_list(currentscope, groupscope); 552 if (currentscope == NULL) 553 ABORT; 554 } 555 ; 556 557hostdef 558 : hosthead '{' hostbody '}' ';' 559 { 560 struct host_decl *temp_host = hostlist; 561 while (temp_host) 562 { 563 if (temp_host->iaidinfo.iaid == host->iaidinfo.iaid) { 564 dprintf(LOG_ERR, "duplicated host %d redefined", 565 host->iaidinfo.iaid); 566 ABORT; 567 } 568 temp_host = temp_host->next; 569 } 570 if (currentgroup) 571 host->group = currentgroup->scope; 572 host->next = hostlist; 573 hostlist = host; 574 host = NULL; 575 /* leave host scope we know the current scope is not point to NULL*/ 576 currentscope = pop_double_list(currentscope); 577 } 578 ; 579 580 581hosthead 582 : HOST name 583 { 584 struct host_decl *temp_host = hostlist; 585 while (temp_host) 586 { 587 if (!strcmp(temp_host->name, $2)) { 588 dprintf(LOG_ERR, "duplicated host %s redefined", $2); 589 ABORT; 590 } 591 temp_host = temp_host->next; 592 } 593 host = (struct host_decl *)malloc(sizeof(*host)); 594 if (host == NULL) { 595 dprintf(LOG_ERR, "fail to allocate memory"); 596 ABORT; 597 } 598 memset(host, 0, sizeof(*host)); 599 TAILQ_INIT(&host->addrlist); 600 TAILQ_INIT(&host->prefixlist); 601 TAILQ_INIT(&host->hostscope.dnslist.addrlist); 602 TAILQ_INIT(&host->hostscope.siplist); 603 TAILQ_INIT(&host->hostscope.ntplist); 604 host->network = ifnetwork; 605 strncpy(host->name, $2, strlen($2)); 606 /* enter host scope */ 607 currentscope = push_double_list(currentscope, &host->hostscope); 608 if (currentscope == NULL) 609 ABORT; 610 } 611 ; 612 613hostbody 614 : hostbody hostdecl 615 | hostdecl 616 ; 617 618hostdecl 619 : DUID DUID_ID ';' 620 { 621 if (host == NULL) { 622 dprintf(LOG_DEBUG, "duid should be defined under host decl"); 623 ABORT; 624 } 625 configure_duid($2, &host->cid); 626 } 627 | iaiddef 628 | hostparas 629 ; 630 631iaiddef 632 : IAIDINFO '{' iaidbody '}' ';' 633 { 634 } 635 ; 636 637iaidbody 638 : iaidbody RENEWTIME number_or_infinity ';' 639 { 640 host->iaidinfo.renewtime = $3; 641 } 642 | iaidbody REBINDTIME number_or_infinity ';' 643 { 644 host->iaidinfo.rebindtime = $3; 645 } 646 | iaidpara 647 ; 648 649iaidpara 650 : IAID NUMBER ';' 651 { 652 if (host == NULL) { 653 dprintf(LOG_DEBUG, "iaid should be defined under host decl"); 654 ABORT; 655 } 656 host->iaidinfo.iaid = $2; 657 } 658 ; 659 660hostparas 661 : hostparas hostpara 662 | hostpara 663 ; 664 665hostpara 666 : hostaddr6 667 { 668 if (host == NULL) { 669 dprintf(LOG_DEBUG, "address should be defined under host decl"); 670 ABORT; 671 } 672 dhcp6_add_listval(&host->addrlist, $1, DHCP6_LISTVAL_DHCP6ADDR); 673 if (hash_add(host_addr_hash_table, &($1->addr), $1) != 0) { 674 dprintf(LOG_ERR, "%s" "hash add lease failed for %s", 675 FNAME, in6addr2str(&($1->addr), 0)); 676 free($1); 677 return (-1); 678 } 679 } 680 | hostprefix6 681 { 682 if (host == NULL) { 683 dprintf(LOG_DEBUG, "prefix should be defined under host decl"); 684 ABORT; 685 } 686 dhcp6_add_listval(&host->prefixlist, $1, DHCP6_LISTVAL_DHCP6ADDR); 687 } 688 | optiondecl 689 ; 690 691hostaddr6 692 : ADDRESS '{' addr6para '}' ';' 693 { 694 $3->type = IANA; 695 $$ = $3; 696 } 697 ; 698 699hostprefix6 700 : PREFIX '{' addr6para '}' ';' 701 { 702 $3->type = IAPD; 703 $$ = $3; 704 } 705 ; 706 707addr6para 708 : addr6para VALIDLIFETIME number_or_infinity ';' 709 { 710 $1->validlifetime = $3; 711 } 712 | addr6para PREFERLIFETIME number_or_infinity ';' 713 { 714 $1->preferlifetime = $3; 715 } 716 | v6address 717 { 718 $$ = $1; 719 } 720 ; 721 722v6address 723 : IPV6ADDR '/' NUMBER ';' 724 { 725 struct dhcp6_addr *temp; 726 temp = (struct dhcp6_addr *)malloc(sizeof(*temp)); 727 if (temp == NULL) { 728 dprintf(LOG_ERR, "v6addr memory allocation failed"); 729 ABORT; 730 } 731 memset(temp, 0, sizeof(*temp)); 732 memcpy(&temp->addr, &$1, sizeof(temp->addr)); 733 if ($3 > 128 || $3 < 0) { 734 dprintf(LOG_ERR, "invalid prefix length in line %d", num_lines); 735 ABORT; 736 } 737 temp->plen = $3; 738 $$ = temp; 739 } 740 ; 741 742optiondecl 743 : optionhead optionpara 744 ; 745 746optionhead 747 : SEND 748 { 749 if (!currentscope) { 750 currentscope = push_double_list(currentscope, &globalgroup->scope); 751 if (currentscope == NULL) 752 ABORT; 753 } 754 } 755 | ALLOW 756 { 757 if (!currentscope) { 758 currentscope = push_double_list(currentscope, &globalgroup->scope); 759 if (currentscope == NULL) 760 ABORT; 761 } 762 allow = 1; 763 } 764 | OPTION 765 { 766 if (!currentscope) { 767 currentscope = push_double_list(currentscope, &globalgroup->scope); 768 if (currentscope == NULL) 769 ABORT; 770 } 771 } 772 ; 773 774optionpara 775 : RAPIDCOMMIT ';' 776 { 777 if (allow) 778 currentscope->scope->allow_flags |= DHCIFF_RAPID_COMMIT; 779 else 780 currentscope->scope->send_flags |= DHCIFF_RAPID_COMMIT; 781 } 782 | TEMPIPV6ADDR ';' 783 { 784 if (allow) 785 currentscope->scope->allow_flags |= DHCIFF_TEMP_ADDRS; 786 else 787 currentscope->scope->send_flags |= DHCIFF_TEMP_ADDRS; 788 } 789 | UNICAST ';' 790 { 791 if (allow) 792 currentscope->scope->allow_flags |= DHCIFF_UNICAST; 793 else 794 currentscope->scope->send_flags |= DHCIFF_UNICAST; 795 } 796 | INFO_ONLY ';' 797 { 798 if (allow) 799 currentscope->scope->allow_flags |= DHCIFF_INFO_ONLY; 800 else 801 currentscope->scope->send_flags |= DHCIFF_INFO_ONLY; 802 } 803 | DNS_SERVERS dns_paras ';' 804 { 805 } 806 | SIP_SERVERS sip_paras ';' 807 { 808 } 809 | NTP_SERVERS ntp_paras ';' 810 { 811 } 812 ; 813 814dns_paras 815 : dns_paras dns_para 816 | dns_para 817 ; 818 819dns_para 820 : IPV6ADDR 821 { 822 dhcp6_add_listval(¤tscope->scope->dnslist.addrlist, &$1, 823 DHCP6_LISTVAL_ADDR6); 824 } 825 826sip_paras 827 : sip_paras sip_para 828 | sip_para 829 ; 830 831sip_para 832 : IPV6ADDR 833 { 834 dhcp6_add_listval(¤tscope->scope->siplist, &$1, 835 DHCP6_LISTVAL_ADDR6); 836 } 837 838ntp_paras 839 : ntp_paras ntp_para 840 | ntp_para 841 ; 842 843ntp_para 844 : IPV6ADDR 845 { 846 dhcp6_add_listval(¤tscope->scope->ntplist, &$1, 847 DHCP6_LISTVAL_ADDR6); 848 } 849 850 | STRING 851 { 852 struct domain_list *domainname, *temp; 853 int len = 0; 854 domainname = (struct domain_list *)malloc(sizeof(*domainname)); 855 if (domainname == NULL) 856 ABORT; 857 len = strlen($1); 858 if (len > MAXDNAME) 859 ABORT; 860 strncpy(domainname->name, $1, len); 861 domainname->name[len] = '\0'; 862 domainname->next = NULL; 863 if (currentscope->scope->dnslist.domainlist == NULL) { 864 currentscope->scope->dnslist.domainlist = domainname; 865 dprintf(LOG_DEBUG, "add domain name %s", domainname->name); 866 } else { 867 for (temp = currentscope->scope->dnslist.domainlist; temp; 868 temp = temp->next) { 869 if (temp->next == NULL) { 870 dprintf(LOG_DEBUG, "add domain name %s", 871 domainname->name); 872 temp->next = domainname; 873 break; 874 } 875 } 876 } 877 } 878 ; 879 880confdecl 881 : paradecl 882 | optiondecl 883 ; 884 885paradecl 886 : RENEWTIME number_or_infinity ';' 887 { 888 if (!currentscope) { 889 currentscope = push_double_list(currentscope, &globalgroup->scope); 890 if (currentscope == NULL) 891 ABORT; 892 } 893 currentscope->scope->renew_time = $2; 894 } 895 | REBINDTIME number_or_infinity ';' 896 { 897 if (!currentscope) { 898 currentscope = push_double_list(currentscope, &globalgroup->scope); 899 if (currentscope == NULL) 900 ABORT; 901 } 902 currentscope->scope->rebind_time = $2; 903 } 904 | VALIDLIFETIME number_or_infinity ';' 905 { 906 if (!currentscope) { 907 currentscope = push_double_list(currentscope, &globalgroup->scope); 908 if (currentscope == NULL) 909 ABORT; 910 } 911 currentscope->scope->valid_life_time = $2; 912 if (currentscope->scope->prefer_life_time != 0 && 913 currentscope->scope->valid_life_time < 914 currentscope->scope->prefer_life_time) { 915 dprintf(LOG_ERR, "%s" 916 "validlifetime is less than preferlifetime", FNAME); 917 ABORT; 918 } 919 } 920 | PREFERLIFETIME number_or_infinity ';' 921 { 922 if (!currentscope) { 923 currentscope = push_double_list(currentscope, &globalgroup->scope); 924 if (currentscope == NULL) 925 ABORT; 926 } 927 currentscope->scope->prefer_life_time = $2; 928 if (currentscope->scope->valid_life_time != 0 && 929 currentscope->scope->valid_life_time < 930 currentscope->scope->prefer_life_time) { 931 dprintf(LOG_ERR, "%s" 932 "validlifetime is less than preferlifetime", FNAME); 933 ABORT; 934 } 935 } 936 | PREFERENCE NUMBER ';' 937 { 938 if (!currentscope) { 939 currentscope = push_double_list(currentscope, &globalgroup->scope); 940 if (currentscope == NULL) 941 ABORT; 942 } 943 if ($2 < 0 || $2 > 255) 944 dprintf(LOG_ERR, "%s" "bad server preference number", FNAME); 945 currentscope->scope->server_pref = $2; 946 } 947 ; 948 949number_or_infinity 950 : NUMBER 951 { 952 $$ = $1; 953 } 954 | INFINITY 955 { 956 $$ = DHCP6_DURATITION_INFINITE; 957 } 958 ; 959 960name 961 : STRING 962 { 963 $$ = $1; 964 } 965 ; 966 967%% 968 969 970static 971void cleanup(void) 972{ 973 /* it is not necessary to free all the pre malloc(), if it fails, 974 * exit will free them automatically. 975 */ 976} 977 978void 979sfyyerror(char *msg) 980{ 981 cleanup(); 982 dprintf(LOG_ERR, "%s in line %d: %s ", msg, num_lines, sfyytext); 983} 984 985