1 /* $NetBSD: confpars.c,v 1.2 2014/07/12 12:09:38 spz Exp $ */ 2 /* confpars.c 3 4 Parser for dhcpd config file... */ 5 6 /* 7 * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC") 8 * Copyright (c) 1995-2003 by Internet Software Consortium 9 * 10 * Permission to use, copy, modify, and distribute this software for any 11 * purpose with or without fee is hereby granted, provided that the above 12 * copyright notice and this permission notice appear in all copies. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Internet Systems Consortium, Inc. 23 * 950 Charter Street 24 * Redwood City, CA 94063 25 * <info@isc.org> 26 * https://www.isc.org/ 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __RCSID("$NetBSD: confpars.c,v 1.2 2014/07/12 12:09:38 spz Exp $"); 32 33 /*! \file server/confpars.c */ 34 35 #include "dhcpd.h" 36 37 static unsigned char global_host_once = 1; 38 39 static int parse_binding_value(struct parse *cfile, 40 struct binding_value *value); 41 42 #if defined (TRACING) 43 trace_type_t *trace_readconf_type; 44 trace_type_t *trace_readleases_type; 45 46 void parse_trace_setup () 47 { 48 trace_readconf_type = trace_type_register ("readconf", (void *)0, 49 trace_conf_input, 50 trace_conf_stop, MDL); 51 trace_readleases_type = trace_type_register ("readleases", (void *)0, 52 trace_conf_input, 53 trace_conf_stop, MDL); 54 } 55 #endif 56 57 /* conf-file :== parameters declarations END_OF_FILE 58 parameters :== <nil> | parameter | parameters parameter 59 declarations :== <nil> | declaration | declarations declaration */ 60 61 isc_result_t readconf () 62 { 63 isc_result_t res; 64 65 res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0); 66 #if defined(LDAP_CONFIGURATION) 67 if (res != ISC_R_SUCCESS) 68 return (res); 69 70 return ldap_read_config (); 71 #else 72 return (res); 73 #endif 74 } 75 76 isc_result_t read_conf_file (const char *filename, struct group *group, 77 int group_type, int leasep) 78 { 79 int file; 80 struct parse *cfile; 81 isc_result_t status; 82 #if defined (TRACING) 83 char *fbuf, *dbuf; 84 off_t flen; 85 int result; 86 unsigned tflen, ulen; 87 trace_type_t *ttype; 88 89 if (leasep) 90 ttype = trace_readleases_type; 91 else 92 ttype = trace_readconf_type; 93 94 /* If we're in playback, we need to snarf the contents of the 95 named file out of the playback file rather than trying to 96 open and read it. */ 97 if (trace_playback ()) { 98 dbuf = (char *)0; 99 tflen = 0; 100 status = trace_get_file (ttype, filename, &tflen, &dbuf); 101 if (status != ISC_R_SUCCESS) 102 return status; 103 ulen = tflen; 104 105 /* What we get back is filename\0contents, where contents is 106 terminated just by the length. So we figure out the length 107 of the filename, and subtract that and the NUL from the 108 total length to get the length of the contents of the file. 109 We make fbuf a pointer to the contents of the file, and 110 leave dbuf as it is so we can free it later. */ 111 tflen = strlen (dbuf); 112 ulen = ulen - tflen - 1; 113 fbuf = dbuf + tflen + 1; 114 goto memfile; 115 } 116 #endif 117 118 if ((file = open (filename, O_RDONLY)) < 0) { 119 if (leasep) { 120 log_error ("Can't open lease database %s: %m --", 121 path_dhcpd_db); 122 log_error (" check for failed database %s!", 123 "rewrite attempt"); 124 log_error ("Please read the dhcpd.leases manual%s", 125 " page if you"); 126 log_fatal ("don't know what to do about this."); 127 } else { 128 log_fatal ("Can't open %s: %m", filename); 129 } 130 } 131 132 cfile = (struct parse *)0; 133 #if defined (TRACING) 134 flen = lseek (file, (off_t)0, SEEK_END); 135 if (flen < 0) { 136 boom: 137 log_fatal ("Can't lseek on %s: %m", filename); 138 } 139 if (lseek (file, (off_t)0, SEEK_SET) < 0) 140 goto boom; 141 /* Can't handle files greater than 2^31-1. */ 142 if (flen > 0x7FFFFFFFUL) 143 log_fatal ("%s: file is too long to buffer.", filename); 144 ulen = flen; 145 146 /* Allocate a buffer that will be what's written to the tracefile, 147 and also will be what we parse from. */ 148 tflen = strlen (filename); 149 dbuf = dmalloc (ulen + tflen + 1, MDL); 150 if (!dbuf) 151 log_fatal ("No memory for %s (%d bytes)", 152 filename, ulen); 153 154 /* Copy the name into the beginning, nul-terminated. */ 155 strcpy (dbuf, filename); 156 157 /* Load the file in after the NUL. */ 158 fbuf = dbuf + tflen + 1; 159 result = read (file, fbuf, ulen); 160 if (result < 0) 161 log_fatal ("Can't read in %s: %m", filename); 162 if (result != ulen) 163 log_fatal ("%s: short read of %d bytes instead of %d.", 164 filename, ulen, result); 165 close (file); 166 memfile: 167 /* If we're recording, write out the filename and file contents. */ 168 if (trace_record ()) 169 trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL); 170 status = new_parse(&cfile, -1, fbuf, ulen, filename, 0); /* XXX */ 171 #else 172 status = new_parse(&cfile, file, NULL, 0, filename, 0); 173 #endif 174 if (status != ISC_R_SUCCESS || cfile == NULL) 175 return status; 176 177 if (leasep) 178 status = lease_file_subparse (cfile); 179 else 180 status = conf_file_subparse (cfile, group, group_type); 181 end_parse (&cfile); 182 #if defined (TRACING) 183 dfree (dbuf, MDL); 184 #endif 185 return status; 186 } 187 188 #if defined (TRACING) 189 void trace_conf_input (trace_type_t *ttype, unsigned len, char *data) 190 { 191 char *fbuf; 192 unsigned flen; 193 unsigned tflen; 194 struct parse *cfile = (struct parse *)0; 195 static int postconf_initialized; 196 static int leaseconf_initialized; 197 isc_result_t status; 198 199 /* Do what's done above, except that we don't have to read in the 200 data, because it's already been read for us. */ 201 tflen = strlen (data); 202 flen = len - tflen - 1; 203 fbuf = data + tflen + 1; 204 205 /* If we're recording, write out the filename and file contents. */ 206 if (trace_record ()) 207 trace_write_packet (ttype, len, data, MDL); 208 209 status = new_parse(&cfile, -1, fbuf, flen, data, 0); 210 if (status == ISC_R_SUCCESS || cfile != NULL) { 211 if (ttype == trace_readleases_type) 212 lease_file_subparse (cfile); 213 else 214 conf_file_subparse (cfile, root_group, ROOT_GROUP); 215 end_parse (&cfile); 216 } 217 218 /* Postconfiguration needs to be done after the config file 219 has been loaded. */ 220 if (!postconf_initialized && ttype == trace_readconf_type) { 221 postconf_initialization (0); 222 postconf_initialized = 1; 223 } 224 225 if (!leaseconf_initialized && ttype == trace_readleases_type) { 226 db_startup (0); 227 leaseconf_initialized = 1; 228 postdb_startup (); 229 } 230 } 231 232 void trace_conf_stop (trace_type_t *ttype) { } 233 #endif 234 235 /* conf-file :== parameters declarations END_OF_FILE 236 parameters :== <nil> | parameter | parameters parameter 237 declarations :== <nil> | declaration | declarations declaration */ 238 239 isc_result_t conf_file_subparse (struct parse *cfile, struct group *group, 240 int group_type) 241 { 242 const char *val; 243 enum dhcp_token token; 244 int declaration = 0; 245 int status; 246 247 do { 248 token = peek_token (&val, (unsigned *)0, cfile); 249 if (token == END_OF_FILE) 250 break; 251 declaration = parse_statement (cfile, group, group_type, 252 (struct host_decl *)0, 253 declaration); 254 } while (1); 255 skip_token(&val, (unsigned *)0, cfile); 256 257 status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS; 258 return status; 259 } 260 261 /* lease-file :== lease-declarations END_OF_FILE 262 lease-statements :== <nil> 263 | lease-declaration 264 | lease-declarations lease-declaration */ 265 266 isc_result_t lease_file_subparse (struct parse *cfile) 267 { 268 const char *val; 269 enum dhcp_token token; 270 isc_result_t status; 271 272 do { 273 token = next_token (&val, (unsigned *)0, cfile); 274 if (token == END_OF_FILE) 275 break; 276 if (token == LEASE) { 277 struct lease *lease = (struct lease *)0; 278 if (parse_lease_declaration (&lease, cfile)) { 279 enter_lease (lease); 280 lease_dereference (&lease, MDL); 281 } else 282 parse_warn (cfile, 283 "possibly corrupt lease file"); 284 } else if (token == IA_NA) { 285 parse_ia_na_declaration(cfile); 286 } else if (token == IA_TA) { 287 parse_ia_ta_declaration(cfile); 288 } else if (token == IA_PD) { 289 parse_ia_pd_declaration(cfile); 290 } else if (token == CLASS) { 291 parse_class_declaration(0, cfile, root_group, 292 CLASS_TYPE_CLASS); 293 } else if (token == SUBCLASS) { 294 parse_class_declaration(0, cfile, root_group, 295 CLASS_TYPE_SUBCLASS); 296 } else if (token == HOST) { 297 parse_host_declaration (cfile, root_group); 298 } else if (token == GROUP) { 299 parse_group_declaration (cfile, root_group); 300 #if defined (FAILOVER_PROTOCOL) 301 } else if (token == FAILOVER) { 302 parse_failover_state_declaration 303 (cfile, (dhcp_failover_state_t *)0); 304 #endif 305 #ifdef DHCPv6 306 } else if (token == SERVER_DUID) { 307 parse_server_duid(cfile); 308 #endif /* DHCPv6 */ 309 } else { 310 log_error ("Corrupt lease file - possible data loss!"); 311 skip_to_semi (cfile); 312 } 313 314 } while (1); 315 316 status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS; 317 return status; 318 } 319 320 /* statement :== parameter | declaration 321 322 parameter :== DEFAULT_LEASE_TIME lease_time 323 | MAX_LEASE_TIME lease_time 324 | DYNAMIC_BOOTP_LEASE_CUTOFF date 325 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time 326 | BOOT_UNKNOWN_CLIENTS boolean 327 | ONE_LEASE_PER_CLIENT boolean 328 | GET_LEASE_HOSTNAMES boolean 329 | USE_HOST_DECL_NAME boolean 330 | NEXT_SERVER ip-addr-or-hostname SEMI 331 | option_parameter 332 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI 333 | FILENAME string-parameter 334 | SERVER_NAME string-parameter 335 | hardware-parameter 336 | fixed-address-parameter 337 | ALLOW allow-deny-keyword 338 | DENY allow-deny-keyword 339 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean 340 | AUTHORITATIVE 341 | NOT AUTHORITATIVE 342 343 declaration :== host-declaration 344 | group-declaration 345 | shared-network-declaration 346 | subnet-declaration 347 | VENDOR_CLASS class-declaration 348 | USER_CLASS class-declaration 349 | RANGE address-range-declaration */ 350 351 int parse_statement (cfile, group, type, host_decl, declaration) 352 struct parse *cfile; 353 struct group *group; 354 int type; 355 struct host_decl *host_decl; 356 int declaration; 357 { 358 enum dhcp_token token; 359 const char *val; 360 struct shared_network *share; 361 char *n; 362 struct hardware hardware; 363 struct executable_statement *et, *ep; 364 struct option *option = NULL; 365 struct option_cache *cache; 366 int lose; 367 int known; 368 isc_result_t status; 369 unsigned code; 370 371 token = peek_token (&val, (unsigned *)0, cfile); 372 373 switch (token) { 374 case INCLUDE: 375 skip_token(&val, (unsigned *)0, cfile); 376 token = next_token (&val, (unsigned *)0, cfile); 377 if (token != STRING) { 378 parse_warn (cfile, "filename string expected."); 379 skip_to_semi (cfile); 380 } else { 381 status = read_conf_file (val, group, type, 0); 382 if (status != ISC_R_SUCCESS) 383 parse_warn (cfile, "%s: bad parse.", val); 384 parse_semi (cfile); 385 } 386 return 1; 387 388 case HOST: 389 skip_token(&val, (unsigned *)0, cfile); 390 if (type != HOST_DECL && type != CLASS_DECL) { 391 if (global_host_once && 392 (type == SUBNET_DECL || type == SHARED_NET_DECL)) { 393 global_host_once = 0; 394 log_error("WARNING: Host declarations are " 395 "global. They are not limited to " 396 "the scope you declared them in."); 397 } 398 399 parse_host_declaration (cfile, group); 400 } else { 401 parse_warn (cfile, 402 "host declarations not allowed here."); 403 skip_to_semi (cfile); 404 } 405 return 1; 406 407 case GROUP: 408 skip_token(&val, (unsigned *)0, cfile); 409 if (type != HOST_DECL && type != CLASS_DECL) 410 parse_group_declaration (cfile, group); 411 else { 412 parse_warn (cfile, 413 "group declarations not allowed here."); 414 skip_to_semi (cfile); 415 } 416 return 1; 417 418 case SHARED_NETWORK: 419 skip_token(&val, (unsigned *)0, cfile); 420 if (type == SHARED_NET_DECL || 421 type == HOST_DECL || 422 type == SUBNET_DECL || 423 type == CLASS_DECL) { 424 parse_warn (cfile, "shared-network parameters not %s.", 425 "allowed here"); 426 skip_to_semi (cfile); 427 break; 428 } 429 430 parse_shared_net_declaration (cfile, group); 431 return 1; 432 433 case SUBNET: 434 case SUBNET6: 435 skip_token(&val, (unsigned *)0, cfile); 436 if (type == HOST_DECL || type == SUBNET_DECL || 437 type == CLASS_DECL) { 438 parse_warn (cfile, 439 "subnet declarations not allowed here."); 440 skip_to_semi (cfile); 441 return 1; 442 } 443 444 /* If we're in a subnet declaration, just do the parse. */ 445 if (group->shared_network != NULL) { 446 if (token == SUBNET) { 447 parse_subnet_declaration(cfile, 448 group->shared_network); 449 } else { 450 parse_subnet6_declaration(cfile, 451 group->shared_network); 452 } 453 break; 454 } 455 456 /* 457 * Otherwise, cons up a fake shared network structure 458 * and populate it with the lone subnet...because the 459 * intention most likely is to refer to the entire link 460 * by shorthand, any configuration inside the subnet is 461 * actually placed in the shared-network's group. 462 */ 463 464 share = NULL; 465 status = shared_network_allocate (&share, MDL); 466 if (status != ISC_R_SUCCESS) 467 log_fatal ("Can't allocate shared subnet: %s", 468 isc_result_totext (status)); 469 if (!clone_group (&share -> group, group, MDL)) 470 log_fatal ("Can't allocate group for shared net"); 471 shared_network_reference (&share -> group -> shared_network, 472 share, MDL); 473 474 /* 475 * This is an implicit shared network, not explicit in 476 * the config. 477 */ 478 share->flags |= SHARED_IMPLICIT; 479 480 if (token == SUBNET) { 481 parse_subnet_declaration(cfile, share); 482 } else { 483 parse_subnet6_declaration(cfile, share); 484 } 485 486 /* share -> subnets is the subnet we just parsed. */ 487 if (share->subnets) { 488 interface_reference(&share->interface, 489 share->subnets->interface, 490 MDL); 491 492 /* Make the shared network name from network number. */ 493 if (token == SUBNET) { 494 n = piaddrmask(&share->subnets->net, 495 &share->subnets->netmask); 496 } else { 497 n = piaddrcidr(&share->subnets->net, 498 share->subnets->prefix_len); 499 } 500 501 share->name = strdup(n); 502 503 if (share->name == NULL) 504 log_fatal("Out of memory allocating default " 505 "shared network name (\"%s\").", n); 506 507 /* Copy the authoritative parameter from the subnet, 508 since there is no opportunity to declare it here. */ 509 share->group->authoritative = 510 share->subnets->group->authoritative; 511 enter_shared_network(share); 512 } 513 shared_network_dereference(&share, MDL); 514 return 1; 515 516 case VENDOR_CLASS: 517 skip_token(&val, (unsigned *)0, cfile); 518 if (type == CLASS_DECL) { 519 parse_warn (cfile, 520 "class declarations not allowed here."); 521 skip_to_semi (cfile); 522 break; 523 } 524 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_VENDOR); 525 return 1; 526 527 case USER_CLASS: 528 skip_token(&val, (unsigned *)0, cfile); 529 if (type == CLASS_DECL) { 530 parse_warn (cfile, 531 "class declarations not allowed here."); 532 skip_to_semi (cfile); 533 break; 534 } 535 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_USER); 536 return 1; 537 538 case CLASS: 539 skip_token(&val, (unsigned *)0, cfile); 540 if (type == CLASS_DECL) { 541 parse_warn (cfile, 542 "class declarations not allowed here."); 543 skip_to_semi (cfile); 544 break; 545 } 546 parse_class_declaration(NULL, cfile, group, CLASS_TYPE_CLASS); 547 return 1; 548 549 case SUBCLASS: 550 skip_token(&val, (unsigned *)0, cfile); 551 if (type == CLASS_DECL) { 552 parse_warn (cfile, 553 "class declarations not allowed here."); 554 skip_to_semi (cfile); 555 break; 556 } 557 parse_class_declaration(NULL, cfile, group, 558 CLASS_TYPE_SUBCLASS); 559 return 1; 560 561 case HARDWARE: 562 skip_token(&val, (unsigned *)0, cfile); 563 memset (&hardware, 0, sizeof hardware); 564 if (host_decl && memcmp(&hardware, &(host_decl->interface), 565 sizeof(hardware)) != 0) { 566 parse_warn(cfile, "Host %s hardware address already " 567 "configured.", host_decl->name); 568 break; 569 } 570 571 parse_hardware_param (cfile, &hardware); 572 if (host_decl) 573 host_decl -> interface = hardware; 574 else 575 parse_warn (cfile, "hardware address parameter %s", 576 "not allowed here."); 577 break; 578 579 case FIXED_ADDR: 580 case FIXED_ADDR6: 581 skip_token(&val, NULL, cfile); 582 cache = NULL; 583 if (parse_fixed_addr_param(&cache, cfile, token)) { 584 if (host_decl) { 585 if (host_decl->fixed_addr) { 586 option_cache_dereference(&cache, MDL); 587 parse_warn(cfile, 588 "Only one fixed address " 589 "declaration per host."); 590 } else { 591 host_decl->fixed_addr = cache; 592 } 593 } else { 594 parse_warn(cfile, 595 "fixed-address parameter not " 596 "allowed here."); 597 option_cache_dereference(&cache, MDL); 598 } 599 } 600 break; 601 602 case POOL: 603 skip_token(&val, (unsigned *)0, cfile); 604 if (type == POOL_DECL) { 605 parse_warn (cfile, "pool declared within pool."); 606 skip_to_semi(cfile); 607 } else if (type != SUBNET_DECL && type != SHARED_NET_DECL) { 608 parse_warn (cfile, "pool declared outside of network"); 609 skip_to_semi(cfile); 610 } else 611 parse_pool_statement (cfile, group, type); 612 613 return declaration; 614 615 case RANGE: 616 skip_token(&val, (unsigned *)0, cfile); 617 if (type != SUBNET_DECL || !group -> subnet) { 618 parse_warn (cfile, 619 "range declaration not allowed here."); 620 skip_to_semi (cfile); 621 return declaration; 622 } 623 parse_address_range (cfile, group, type, (struct pool *)0, 624 (struct lease **)0); 625 return declaration; 626 627 #ifdef DHCPv6 628 case RANGE6: 629 skip_token(NULL, NULL, cfile); 630 if ((type != SUBNET_DECL) || (group->subnet == NULL)) { 631 parse_warn (cfile, 632 "range6 declaration not allowed here."); 633 skip_to_semi(cfile); 634 return declaration; 635 } 636 parse_address_range6(cfile, group, NULL); 637 return declaration; 638 639 case PREFIX6: 640 skip_token(NULL, NULL, cfile); 641 if ((type != SUBNET_DECL) || (group->subnet == NULL)) { 642 parse_warn (cfile, 643 "prefix6 declaration not allowed here."); 644 skip_to_semi(cfile); 645 return declaration; 646 } 647 parse_prefix6(cfile, group, NULL); 648 return declaration; 649 650 case FIXED_PREFIX6: 651 skip_token(&val, NULL, cfile); 652 if (!host_decl) { 653 parse_warn (cfile, 654 "fixed-prefix6 declaration not " 655 "allowed here."); 656 skip_to_semi(cfile); 657 break; 658 } 659 parse_fixed_prefix6(cfile, host_decl); 660 break; 661 662 case POOL6: 663 skip_token(&val, NULL, cfile); 664 if (type == POOL_DECL) { 665 parse_warn (cfile, "pool declared within pool."); 666 skip_to_semi(cfile); 667 } else if (type != SUBNET_DECL) { 668 parse_warn (cfile, "pool declared outside of network"); 669 skip_to_semi(cfile); 670 } else 671 parse_pool6_statement (cfile, group, type); 672 673 return declaration; 674 675 #endif /* DHCPv6 */ 676 677 case TOKEN_NOT: 678 skip_token(&val, (unsigned *)0, cfile); 679 token = next_token (&val, (unsigned *)0, cfile); 680 switch (token) { 681 case AUTHORITATIVE: 682 group -> authoritative = 0; 683 goto authoritative; 684 default: 685 parse_warn (cfile, "expecting assertion"); 686 skip_to_semi (cfile); 687 break; 688 } 689 break; 690 case AUTHORITATIVE: 691 skip_token(&val, (unsigned *)0, cfile); 692 group -> authoritative = 1; 693 authoritative: 694 if (type == HOST_DECL) 695 parse_warn (cfile, "authority makes no sense here."); 696 parse_semi (cfile); 697 break; 698 699 /* "server-identifier" is a special hack, equivalent to 700 "option dhcp-server-identifier". */ 701 case SERVER_IDENTIFIER: 702 code = DHO_DHCP_SERVER_IDENTIFIER; 703 if (!option_code_hash_lookup(&option, dhcp_universe.code_hash, 704 &code, 0, MDL)) 705 log_fatal("Server identifier not in hash (%s:%d).", 706 MDL); 707 skip_token(&val, (unsigned *)0, cfile); 708 goto finish_option; 709 710 case OPTION: 711 skip_token(&val, (unsigned *)0, cfile); 712 token = peek_token (&val, (unsigned *)0, cfile); 713 if (token == SPACE) { 714 if (type != ROOT_GROUP) { 715 parse_warn (cfile, 716 "option space definitions %s", 717 "may not be scoped."); 718 skip_to_semi (cfile); 719 break; 720 } 721 parse_option_space_decl (cfile); 722 return declaration; 723 } 724 725 known = 0; 726 status = parse_option_name(cfile, 1, &known, &option); 727 if (status == ISC_R_SUCCESS) { 728 token = peek_token (&val, (unsigned *)0, cfile); 729 if (token == CODE) { 730 if (type != ROOT_GROUP) { 731 parse_warn (cfile, 732 "option definitions%s", 733 " may not be scoped."); 734 skip_to_semi (cfile); 735 option_dereference(&option, MDL); 736 break; 737 } 738 skip_token(&val, (unsigned *)0, cfile); 739 740 /* 741 * If the option was known, remove it from the 742 * code and name hashes before redefining it. 743 */ 744 if (known) { 745 option_name_hash_delete( 746 option->universe->name_hash, 747 option->name, 0, MDL); 748 option_code_hash_delete( 749 option->universe->code_hash, 750 &option->code, 0, MDL); 751 } 752 753 parse_option_code_definition(cfile, option); 754 option_dereference(&option, MDL); 755 return declaration; 756 } 757 758 /* If this wasn't an option code definition, don't 759 allow an unknown option. */ 760 if (!known) { 761 parse_warn (cfile, "unknown option %s.%s", 762 option -> universe -> name, 763 option -> name); 764 skip_to_semi (cfile); 765 option_dereference(&option, MDL); 766 return declaration; 767 } 768 769 finish_option: 770 et = (struct executable_statement *)0; 771 if (!parse_option_statement 772 (&et, cfile, 1, option, 773 supersede_option_statement)) 774 return declaration; 775 option_dereference(&option, MDL); 776 goto insert_statement; 777 } else 778 return declaration; 779 780 break; 781 782 case FAILOVER: 783 if (type != ROOT_GROUP && type != SHARED_NET_DECL) { 784 parse_warn (cfile, "failover peers may only be %s", 785 "defined in shared-network"); 786 log_error ("declarations and the outer scope."); 787 skip_to_semi (cfile); 788 break; 789 } 790 token = next_token (&val, (unsigned *)0, cfile); 791 #if defined (FAILOVER_PROTOCOL) 792 parse_failover_peer (cfile, group, type); 793 #else 794 parse_warn (cfile, "No failover support."); 795 skip_to_semi (cfile); 796 #endif 797 break; 798 799 #ifdef DHCPv6 800 case SERVER_DUID: 801 parse_server_duid_conf(cfile); 802 break; 803 #endif /* DHCPv6 */ 804 805 default: 806 et = (struct executable_statement *)0; 807 lose = 0; 808 if (!parse_executable_statement (&et, cfile, &lose, 809 context_any)) { 810 if (!lose) { 811 if (declaration) 812 parse_warn (cfile, 813 "expecting a declaration"); 814 else 815 parse_warn (cfile, 816 "expecting a parameter %s", 817 "or declaration"); 818 skip_to_semi (cfile); 819 } 820 return declaration; 821 } 822 if (!et) 823 return declaration; 824 insert_statement: 825 if (group -> statements) { 826 int multi = 0; 827 828 /* If this set of statements is only referenced 829 by this group, just add the current statement 830 to the end of the chain. */ 831 for (ep = group -> statements; ep -> next; 832 ep = ep -> next) 833 if (ep -> refcnt > 1) /* XXX */ 834 multi = 1; 835 if (!multi) { 836 executable_statement_reference (&ep -> next, 837 et, MDL); 838 executable_statement_dereference (&et, MDL); 839 return declaration; 840 } 841 842 /* Otherwise, make a parent chain, and put the 843 current group statements first and the new 844 statement in the next pointer. */ 845 ep = (struct executable_statement *)0; 846 if (!executable_statement_allocate (&ep, MDL)) 847 log_fatal ("No memory for statements."); 848 ep -> op = statements_statement; 849 executable_statement_reference (&ep -> data.statements, 850 group -> statements, 851 MDL); 852 executable_statement_reference (&ep -> next, et, MDL); 853 executable_statement_dereference (&group -> statements, 854 MDL); 855 executable_statement_reference (&group -> statements, 856 ep, MDL); 857 executable_statement_dereference (&ep, MDL); 858 } else { 859 executable_statement_reference (&group -> statements, 860 et, MDL); 861 } 862 executable_statement_dereference (&et, MDL); 863 return declaration; 864 } 865 866 return 0; 867 } 868 869 #if defined (FAILOVER_PROTOCOL) 870 void parse_failover_peer (cfile, group, type) 871 struct parse *cfile; 872 struct group *group; 873 int type; 874 { 875 enum dhcp_token token; 876 const char *val; 877 dhcp_failover_state_t *peer; 878 u_int32_t *tp; 879 char *name; 880 u_int32_t split; 881 u_int8_t hba [32]; 882 unsigned hba_len = sizeof hba; 883 int i; 884 struct expression *expr; 885 isc_result_t status; 886 dhcp_failover_config_t *cp; 887 888 token = next_token (&val, (unsigned *)0, cfile); 889 if (token != PEER) { 890 parse_warn (cfile, "expecting \"peer\""); 891 skip_to_semi (cfile); 892 return; 893 } 894 895 token = next_token (&val, (unsigned *)0, cfile); 896 if (is_identifier (token) || token == STRING) { 897 name = dmalloc (strlen (val) + 1, MDL); 898 if (!name) 899 log_fatal ("no memory for peer name %s", name); 900 strcpy (name, val); 901 } else { 902 parse_warn (cfile, "expecting failover peer name."); 903 skip_to_semi (cfile); 904 return; 905 } 906 907 /* See if there's a peer declaration by this name. */ 908 peer = (dhcp_failover_state_t *)0; 909 find_failover_peer (&peer, name, MDL); 910 911 token = next_token (&val, (unsigned *)0, cfile); 912 if (token == SEMI) { 913 dfree (name, MDL); 914 if (type != SHARED_NET_DECL) 915 parse_warn (cfile, "failover peer reference not %s", 916 "in shared-network declaration"); 917 else { 918 if (!peer) { 919 parse_warn (cfile, "reference to unknown%s%s", 920 " failover peer ", name); 921 return; 922 } 923 dhcp_failover_state_reference 924 (&group -> shared_network -> failover_peer, 925 peer, MDL); 926 } 927 dhcp_failover_state_dereference (&peer, MDL); 928 return; 929 } else if (token == STATE) { 930 if (!peer) { 931 parse_warn (cfile, "state declaration for unknown%s%s", 932 " failover peer ", name); 933 return; 934 } 935 parse_failover_state_declaration (cfile, peer); 936 dhcp_failover_state_dereference (&peer, MDL); 937 return; 938 } else if (token != LBRACE) { 939 parse_warn (cfile, "expecting left brace"); 940 skip_to_semi (cfile); 941 } 942 943 /* Make sure this isn't a redeclaration. */ 944 if (peer) { 945 parse_warn (cfile, "redeclaration of failover peer %s", name); 946 skip_to_rbrace (cfile, 1); 947 dhcp_failover_state_dereference (&peer, MDL); 948 return; 949 } 950 951 status = dhcp_failover_state_allocate (&peer, MDL); 952 if (status != ISC_R_SUCCESS) 953 log_fatal ("Can't allocate failover peer %s: %s", 954 name, isc_result_totext (status)); 955 956 /* Save the name. */ 957 peer -> name = name; 958 959 do { 960 cp = &peer -> me; 961 peer: 962 token = next_token (&val, (unsigned *)0, cfile); 963 switch (token) { 964 case RBRACE: 965 break; 966 967 case PRIMARY: 968 peer -> i_am = primary; 969 break; 970 971 case SECONDARY: 972 peer -> i_am = secondary; 973 if (peer -> hba) 974 parse_warn (cfile, 975 "secondary may not define %s", 976 "load balance settings."); 977 break; 978 979 case PEER: 980 cp = &peer -> partner; 981 goto peer; 982 983 case ADDRESS: 984 expr = (struct expression *)0; 985 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) { 986 skip_to_rbrace (cfile, 1); 987 dhcp_failover_state_dereference (&peer, MDL); 988 return; 989 } 990 option_cache (&cp -> address, 991 (struct data_string *)0, expr, 992 (struct option *)0, MDL); 993 expression_dereference (&expr, MDL); 994 break; 995 996 case PORT: 997 token = next_token (&val, (unsigned *)0, cfile); 998 if (token != NUMBER) { 999 parse_warn (cfile, "expecting number"); 1000 skip_to_rbrace (cfile, 1); 1001 } 1002 cp -> port = atoi (val); 1003 break; 1004 1005 case MAX_LEASE_MISBALANCE: 1006 tp = &peer->max_lease_misbalance; 1007 goto parse_idle; 1008 1009 case MAX_LEASE_OWNERSHIP: 1010 tp = &peer->max_lease_ownership; 1011 goto parse_idle; 1012 1013 case MAX_BALANCE: 1014 tp = &peer->max_balance; 1015 goto parse_idle; 1016 1017 case MIN_BALANCE: 1018 tp = &peer->min_balance; 1019 goto parse_idle; 1020 1021 case AUTO_PARTNER_DOWN: 1022 tp = &peer->auto_partner_down; 1023 goto parse_idle; 1024 1025 case MAX_RESPONSE_DELAY: 1026 tp = &cp -> max_response_delay; 1027 parse_idle: 1028 token = next_token (&val, (unsigned *)0, cfile); 1029 if (token != NUMBER) { 1030 parse_warn (cfile, "expecting number."); 1031 skip_to_rbrace (cfile, 1); 1032 dhcp_failover_state_dereference (&peer, MDL); 1033 return; 1034 } 1035 *tp = atoi (val); 1036 break; 1037 1038 case MAX_UNACKED_UPDATES: 1039 tp = &cp -> max_flying_updates; 1040 goto parse_idle; 1041 1042 case MCLT: 1043 tp = &peer -> mclt; 1044 goto parse_idle; 1045 1046 case HBA: 1047 hba_len = 32; 1048 if (peer -> i_am == secondary) 1049 parse_warn (cfile, 1050 "secondary may not define %s", 1051 "load balance settings."); 1052 if (!parse_numeric_aggregate (cfile, hba, &hba_len, 1053 COLON, 16, 8)) { 1054 skip_to_rbrace (cfile, 1); 1055 dhcp_failover_state_dereference (&peer, MDL); 1056 return; 1057 } 1058 if (hba_len != 32) { 1059 parse_warn (cfile, 1060 "HBA must be exactly 32 bytes."); 1061 break; 1062 } 1063 make_hba: 1064 peer -> hba = dmalloc (32, MDL); 1065 if (!peer -> hba) { 1066 dfree (peer -> name, MDL); 1067 dfree (peer, MDL); 1068 } 1069 memcpy (peer -> hba, hba, 32); 1070 break; 1071 1072 case SPLIT: 1073 token = next_token (&val, (unsigned *)0, cfile); 1074 if (peer -> i_am == secondary) 1075 parse_warn (cfile, 1076 "secondary may not define %s", 1077 "load balance settings."); 1078 if (token != NUMBER) { 1079 parse_warn (cfile, "expecting number"); 1080 skip_to_rbrace (cfile, 1); 1081 dhcp_failover_state_dereference (&peer, MDL); 1082 return; 1083 } 1084 split = atoi (val); 1085 if (split > 255) { 1086 parse_warn (cfile, "split must be < 256"); 1087 } else { 1088 memset (hba, 0, sizeof hba); 1089 for (i = 0; i < split; i++) { 1090 if (i < split) 1091 hba [i / 8] |= (1 << (i & 7)); 1092 } 1093 goto make_hba; 1094 } 1095 break; 1096 1097 case LOAD: 1098 token = next_token (&val, (unsigned *)0, cfile); 1099 if (token != BALANCE) { 1100 parse_warn (cfile, "expecting 'balance'"); 1101 badload: 1102 skip_to_rbrace (cfile, 1); 1103 break; 1104 } 1105 token = next_token (&val, (unsigned *)0, cfile); 1106 if (token != TOKEN_MAX) { 1107 parse_warn (cfile, "expecting 'max'"); 1108 goto badload; 1109 } 1110 token = next_token (&val, (unsigned *)0, cfile); 1111 if (token != SECONDS) { 1112 parse_warn (cfile, "expecting 'secs'"); 1113 goto badload; 1114 } 1115 token = next_token (&val, (unsigned *)0, cfile); 1116 if (token != NUMBER) { 1117 parse_warn (cfile, "expecting number"); 1118 goto badload; 1119 } 1120 peer -> load_balance_max_secs = atoi (val); 1121 break; 1122 1123 default: 1124 parse_warn (cfile, 1125 "invalid statement in peer declaration"); 1126 skip_to_rbrace (cfile, 1); 1127 dhcp_failover_state_dereference (&peer, MDL); 1128 return; 1129 } 1130 if (token != RBRACE && !parse_semi (cfile)) { 1131 skip_to_rbrace (cfile, 1); 1132 dhcp_failover_state_dereference (&peer, MDL); 1133 return; 1134 } 1135 } while (token != RBRACE); 1136 1137 /* me.address can be null; the failover link initiate code tries to 1138 * derive a reasonable address to use. 1139 */ 1140 if (!peer -> partner.address) 1141 parse_warn (cfile, "peer address may not be omitted"); 1142 1143 if (!peer->me.port) 1144 peer->me.port = DEFAULT_FAILOVER_PORT; 1145 if (!peer->partner.port) 1146 peer->partner.port = DEFAULT_FAILOVER_PORT; 1147 1148 if (peer -> i_am == primary) { 1149 if (!peer -> hba) { 1150 parse_warn (cfile, 1151 "primary failover server must have hba or split."); 1152 } else if (!peer -> mclt) { 1153 parse_warn (cfile, 1154 "primary failover server must have mclt."); 1155 } 1156 } 1157 1158 if (!peer->max_lease_misbalance) 1159 peer->max_lease_misbalance = DEFAULT_MAX_LEASE_MISBALANCE; 1160 if (!peer->max_lease_ownership) 1161 peer->max_lease_ownership = DEFAULT_MAX_LEASE_OWNERSHIP; 1162 if (!peer->max_balance) 1163 peer->max_balance = DEFAULT_MAX_BALANCE_TIME; 1164 if (!peer->min_balance) 1165 peer->min_balance = DEFAULT_MIN_BALANCE_TIME; 1166 if (!peer->me.max_flying_updates) 1167 peer->me.max_flying_updates = DEFAULT_MAX_FLYING_UPDATES; 1168 if (!peer->me.max_response_delay) 1169 peer->me.max_response_delay = DEFAULT_MAX_RESPONSE_DELAY; 1170 1171 if (type == SHARED_NET_DECL) 1172 group->shared_network->failover_peer = peer; 1173 1174 /* Set the initial state. */ 1175 if (peer -> i_am == primary) { 1176 peer -> me.state = recover; 1177 peer -> me.stos = cur_time; 1178 peer -> partner.state = unknown_state; 1179 peer -> partner.stos = cur_time; 1180 } else { 1181 peer -> me.state = recover; 1182 peer -> me.stos = cur_time; 1183 peer -> partner.state = unknown_state; 1184 peer -> partner.stos = cur_time; 1185 } 1186 1187 status = enter_failover_peer (peer); 1188 if (status != ISC_R_SUCCESS) 1189 parse_warn (cfile, "failover peer %s: %s", 1190 peer -> name, isc_result_totext (status)); 1191 dhcp_failover_state_dereference (&peer, MDL); 1192 } 1193 1194 void parse_failover_state_declaration (struct parse *cfile, 1195 dhcp_failover_state_t *peer) 1196 { 1197 enum dhcp_token token; 1198 const char *val; 1199 char *name; 1200 dhcp_failover_state_t *state; 1201 dhcp_failover_config_t *cp; 1202 1203 if (!peer) { 1204 token = next_token (&val, (unsigned *)0, cfile); 1205 if (token != PEER) { 1206 parse_warn (cfile, "expecting \"peer\""); 1207 skip_to_semi (cfile); 1208 return; 1209 } 1210 1211 token = next_token (&val, (unsigned *)0, cfile); 1212 if (is_identifier (token) || token == STRING) { 1213 name = dmalloc (strlen (val) + 1, MDL); 1214 if (!name) 1215 log_fatal ("failover peer name %s: no memory", 1216 name); 1217 strcpy (name, val); 1218 } else { 1219 parse_warn (cfile, "expecting failover peer name."); 1220 skip_to_semi (cfile); 1221 return; 1222 } 1223 1224 /* See if there's a peer declaration by this name. */ 1225 state = (dhcp_failover_state_t *)0; 1226 find_failover_peer (&state, name, MDL); 1227 if (!state) { 1228 parse_warn (cfile, "unknown failover peer: %s", name); 1229 skip_to_semi (cfile); 1230 return; 1231 } 1232 1233 token = next_token (&val, (unsigned *)0, cfile); 1234 if (token != STATE) { 1235 parse_warn (cfile, "expecting 'state'"); 1236 if (token != SEMI) 1237 skip_to_semi (cfile); 1238 return; 1239 } 1240 } else { 1241 state = (dhcp_failover_state_t *)0; 1242 dhcp_failover_state_reference (&state, peer, MDL); 1243 } 1244 token = next_token (&val, (unsigned *)0, cfile); 1245 if (token != LBRACE) { 1246 parse_warn (cfile, "expecting left brace"); 1247 if (token != SEMI) 1248 skip_to_semi (cfile); 1249 dhcp_failover_state_dereference (&state, MDL); 1250 return; 1251 } 1252 do { 1253 token = next_token (&val, (unsigned *)0, cfile); 1254 switch (token) { 1255 case RBRACE: 1256 break; 1257 case MY: 1258 cp = &state -> me; 1259 do_state: 1260 token = next_token (&val, (unsigned *)0, cfile); 1261 if (token != STATE) { 1262 parse_warn (cfile, "expecting 'state'"); 1263 goto bogus; 1264 } 1265 parse_failover_state (cfile, 1266 &cp -> state, &cp -> stos); 1267 break; 1268 1269 case PARTNER: 1270 cp = &state -> partner; 1271 goto do_state; 1272 1273 case MCLT: 1274 if (state -> i_am == primary) { 1275 parse_warn (cfile, 1276 "mclt not valid for primary"); 1277 goto bogus; 1278 } 1279 token = next_token (&val, (unsigned *)0, cfile); 1280 if (token != NUMBER) { 1281 parse_warn (cfile, "expecting a number."); 1282 goto bogus; 1283 } 1284 state -> mclt = atoi (val); 1285 parse_semi (cfile); 1286 break; 1287 1288 default: 1289 parse_warn (cfile, "expecting state setting."); 1290 bogus: 1291 skip_to_rbrace (cfile, 1); 1292 dhcp_failover_state_dereference (&state, MDL); 1293 return; 1294 } 1295 } while (token != RBRACE); 1296 dhcp_failover_state_dereference (&state, MDL); 1297 } 1298 1299 void parse_failover_state (cfile, state, stos) 1300 struct parse *cfile; 1301 enum failover_state *state; 1302 TIME *stos; 1303 { 1304 enum dhcp_token token; 1305 const char *val; 1306 enum failover_state state_in; 1307 TIME stos_in; 1308 1309 token = next_token (&val, (unsigned *)0, cfile); 1310 switch (token) { 1311 case UNKNOWN_STATE: 1312 state_in = unknown_state; 1313 break; 1314 1315 case PARTNER_DOWN: 1316 state_in = partner_down; 1317 break; 1318 1319 case NORMAL: 1320 state_in = normal; 1321 break; 1322 1323 case COMMUNICATIONS_INTERRUPTED: 1324 state_in = communications_interrupted; 1325 break; 1326 1327 case CONFLICT_DONE: 1328 state_in = conflict_done; 1329 break; 1330 1331 case RESOLUTION_INTERRUPTED: 1332 state_in = resolution_interrupted; 1333 break; 1334 1335 case POTENTIAL_CONFLICT: 1336 state_in = potential_conflict; 1337 break; 1338 1339 case RECOVER: 1340 state_in = recover; 1341 break; 1342 1343 case RECOVER_WAIT: 1344 state_in = recover_wait; 1345 break; 1346 1347 case RECOVER_DONE: 1348 state_in = recover_done; 1349 break; 1350 1351 case SHUTDOWN: 1352 state_in = shut_down; 1353 break; 1354 1355 case PAUSED: 1356 state_in = paused; 1357 break; 1358 1359 case STARTUP: 1360 state_in = startup; 1361 break; 1362 1363 default: 1364 parse_warn (cfile, "unknown failover state"); 1365 skip_to_semi (cfile); 1366 return; 1367 } 1368 1369 token = next_token (&val, (unsigned *)0, cfile); 1370 if (token == SEMI) { 1371 stos_in = cur_time; 1372 } else { 1373 if (token != AT) { 1374 parse_warn (cfile, "expecting \"at\""); 1375 skip_to_semi (cfile); 1376 return; 1377 } 1378 1379 stos_in = parse_date (cfile); 1380 if (!stos_in) 1381 return; 1382 } 1383 1384 /* Now that we've apparently gotten a clean parse, we 1385 can trust that this is a state that was fully committed to 1386 disk, so we can install it. */ 1387 *stos = stos_in; 1388 *state = state_in; 1389 } 1390 #endif /* defined (FAILOVER_PROTOCOL) */ 1391 1392 /*! 1393 * 1394 * \brief Parse allow and deny statements 1395 * 1396 * This function handles the common processing code for permit and deny 1397 * statements in the parse_pool_statement and parse_pool6_statement functions. 1398 * It reads in the configuration and constructs a new permit structure that it 1399 * attachs to the permit_head passed in from the caller. 1400 * 1401 * The allow or deny token should already be consumed, this function expects 1402 * one of the following: 1403 * known-clients; 1404 * unknown-clients; 1405 * known clients; 1406 * unknown clients; 1407 * authenticated clients; 1408 * unauthenticated clients; 1409 * all clients; 1410 * dynamic bootp clients; 1411 * members of <class name>; 1412 * after <date>; 1413 * 1414 * \param[in] cfile = the configuration file being parsed 1415 * \param[in] permit_head = the head of the permit list (permit or prohibit) 1416 * to which to attach the newly created permit structure 1417 * \param[in] is_allow = 1 if this is being invoked for an allow statement 1418 * = 0 if this is being invoked for a deny statement 1419 * \param[in] valid_from = pointers to the time values from the enclosing pool 1420 * \param[in] valid_until or pond structure. One of them will be filled in if 1421 * the configuration includes an "after" clause 1422 */ 1423 1424 static void get_permit(struct parse *cfile, struct permit **permit_head, 1425 int is_allow, TIME *valid_from, TIME *valid_until) 1426 { 1427 enum dhcp_token token; 1428 struct permit *permit; 1429 const char *val; 1430 int need_clients = 1; 1431 TIME t; 1432 1433 /* Create our permit structure */ 1434 permit = new_permit(MDL); 1435 if (!permit) 1436 log_fatal ("no memory for permit"); 1437 1438 token = next_token(&val, NULL, cfile); 1439 switch (token) { 1440 case UNKNOWN: 1441 permit->type = permit_unknown_clients; 1442 break; 1443 1444 case KNOWN_CLIENTS: 1445 need_clients = 0; 1446 permit->type = permit_known_clients; 1447 break; 1448 1449 case UNKNOWN_CLIENTS: 1450 need_clients = 0; 1451 permit->type = permit_unknown_clients; 1452 break; 1453 1454 case KNOWN: 1455 permit->type = permit_known_clients; 1456 break; 1457 1458 case AUTHENTICATED: 1459 permit->type = permit_authenticated_clients; 1460 break; 1461 1462 case UNAUTHENTICATED: 1463 permit->type = permit_unauthenticated_clients; 1464 break; 1465 1466 case ALL: 1467 permit->type = permit_all_clients; 1468 break; 1469 1470 case DYNAMIC: 1471 permit->type = permit_dynamic_bootp_clients; 1472 if (next_token (&val, NULL, cfile) != TOKEN_BOOTP) { 1473 parse_warn (cfile, "expecting \"bootp\""); 1474 skip_to_semi (cfile); 1475 free_permit (permit, MDL); 1476 return; 1477 } 1478 break; 1479 1480 case MEMBERS: 1481 need_clients = 0; 1482 if (next_token (&val, NULL, cfile) != OF) { 1483 parse_warn (cfile, "expecting \"of\""); 1484 skip_to_semi (cfile); 1485 free_permit (permit, MDL); 1486 return; 1487 } 1488 if (next_token (&val, NULL, cfile) != STRING) { 1489 parse_warn (cfile, "expecting class name."); 1490 skip_to_semi (cfile); 1491 free_permit (permit, MDL); 1492 return; 1493 } 1494 permit->type = permit_class; 1495 permit->class = NULL; 1496 find_class(&permit->class, val, MDL); 1497 if (!permit->class) 1498 parse_warn(cfile, "no such class: %s", val); 1499 break; 1500 1501 case AFTER: 1502 need_clients = 0; 1503 if (*valid_from || *valid_until) { 1504 parse_warn(cfile, "duplicate \"after\" clause."); 1505 skip_to_semi(cfile); 1506 free_permit(permit, MDL); 1507 return; 1508 } 1509 t = parse_date_core(cfile); 1510 permit->type = permit_after; 1511 permit->after = t; 1512 if (is_allow) { 1513 *valid_from = t; 1514 } else { 1515 *valid_until = t; 1516 } 1517 break; 1518 1519 default: 1520 parse_warn (cfile, "expecting permit type."); 1521 skip_to_semi (cfile); 1522 free_permit (permit, MDL); 1523 return; 1524 } 1525 1526 /* 1527 * The need_clients flag is set if we are expecting the 1528 * CLIENTS token 1529 */ 1530 if ((need_clients != 0) && 1531 (next_token (&val, NULL, cfile) != CLIENTS)) { 1532 parse_warn (cfile, "expecting \"clients\""); 1533 skip_to_semi (cfile); 1534 free_permit (permit, MDL); 1535 return; 1536 } 1537 1538 while (*permit_head) 1539 permit_head = &((*permit_head)->next); 1540 *permit_head = permit; 1541 parse_semi (cfile); 1542 1543 return; 1544 } 1545 1546 /* Permit_list_match returns 1 if every element of the permit list in lhs 1547 also appears in rhs. Note that this doesn't by itself mean that the 1548 two lists are equal - to check for equality, permit_list_match has to 1549 return 1 with (list1, list2) and with (list2, list1). */ 1550 1551 int permit_list_match (struct permit *lhs, struct permit *rhs) 1552 { 1553 struct permit *plp, *prp; 1554 int matched; 1555 1556 if (!lhs) 1557 return 1; 1558 if (!rhs) 1559 return 0; 1560 for (plp = lhs; plp; plp = plp -> next) { 1561 matched = 0; 1562 for (prp = rhs; prp; prp = prp -> next) { 1563 if (prp -> type == plp -> type && 1564 (prp -> type != permit_class || 1565 prp -> class == plp -> class)) { 1566 matched = 1; 1567 break; 1568 } 1569 } 1570 if (!matched) 1571 return 0; 1572 } 1573 return 1; 1574 } 1575 1576 /*! 1577 * 1578 * \brief Parse a pool statement 1579 * 1580 * Pool statements are used to group declarations and permit & deny information 1581 * with a specific address range. They must be declared within a shared network 1582 * or subnet and there may be multiple pools withing a shared network or subnet. 1583 * Each pool may have a different set of permit or deny options. 1584 * 1585 * \param[in] cfile = the configuration file being parsed 1586 * \param[in] group = the group structure for this pool 1587 * \param[in] type = the type of the enclosing statement. This must be 1588 * SHARED_NET_DECL or SUBNET_DECL for this function. 1589 * 1590 * \return 1591 * void - This function either parses the statement and updates the structures 1592 * or it generates an error message and possible halts the program if 1593 * it encounters a problem. 1594 */ 1595 void parse_pool_statement (cfile, group, type) 1596 struct parse *cfile; 1597 struct group *group; 1598 int type; 1599 { 1600 enum dhcp_token token; 1601 const char *val; 1602 int done = 0; 1603 struct pool *pool, **p, *pp; 1604 int declaration = 0; 1605 isc_result_t status; 1606 struct lease *lpchain = NULL, *lp; 1607 1608 pool = NULL; 1609 status = pool_allocate(&pool, MDL); 1610 if (status != ISC_R_SUCCESS) 1611 log_fatal ("no memory for pool: %s", 1612 isc_result_totext (status)); 1613 1614 if (type == SUBNET_DECL) 1615 shared_network_reference(&pool->shared_network, 1616 group->subnet->shared_network, 1617 MDL); 1618 else if (type == SHARED_NET_DECL) 1619 shared_network_reference(&pool->shared_network, 1620 group->shared_network, MDL); 1621 else { 1622 parse_warn(cfile, "Dynamic pools are only valid inside " 1623 "subnet or shared-network statements."); 1624 skip_to_semi(cfile); 1625 return; 1626 } 1627 1628 if (pool->shared_network == NULL || 1629 !clone_group(&pool->group, pool->shared_network->group, MDL)) 1630 log_fatal("can't clone pool group."); 1631 1632 #if defined (FAILOVER_PROTOCOL) 1633 /* Inherit the failover peer from the shared network. */ 1634 if (pool->shared_network->failover_peer) 1635 dhcp_failover_state_reference 1636 (&pool->failover_peer, 1637 pool->shared_network->failover_peer, MDL); 1638 #endif 1639 1640 if (!parse_lbrace(cfile)) { 1641 pool_dereference(&pool, MDL); 1642 return; 1643 } 1644 1645 do { 1646 token = peek_token(&val, NULL, cfile); 1647 switch (token) { 1648 case TOKEN_NO: 1649 skip_token(&val, NULL, cfile); 1650 token = next_token(&val, NULL, cfile); 1651 if (token != FAILOVER || 1652 (token = next_token(&val, NULL, cfile)) != PEER) { 1653 parse_warn(cfile, 1654 "expecting \"failover peer\"."); 1655 skip_to_semi(cfile); 1656 continue; 1657 } 1658 #if defined (FAILOVER_PROTOCOL) 1659 if (pool->failover_peer) 1660 dhcp_failover_state_dereference 1661 (&pool->failover_peer, MDL); 1662 #endif 1663 break; 1664 1665 #if defined (FAILOVER_PROTOCOL) 1666 case FAILOVER: 1667 skip_token(&val, NULL, cfile); 1668 token = next_token (&val, NULL, cfile); 1669 if (token != PEER) { 1670 parse_warn(cfile, "expecting 'peer'."); 1671 skip_to_semi(cfile); 1672 break; 1673 } 1674 token = next_token(&val, NULL, cfile); 1675 if (token != STRING) { 1676 parse_warn(cfile, "expecting string."); 1677 skip_to_semi(cfile); 1678 break; 1679 } 1680 if (pool->failover_peer) 1681 dhcp_failover_state_dereference 1682 (&pool->failover_peer, MDL); 1683 status = find_failover_peer(&pool->failover_peer, 1684 val, MDL); 1685 if (status != ISC_R_SUCCESS) 1686 parse_warn(cfile, 1687 "failover peer %s: %s", val, 1688 isc_result_totext (status)); 1689 else 1690 pool->failover_peer->pool_count++; 1691 parse_semi(cfile); 1692 break; 1693 #endif 1694 1695 case RANGE: 1696 skip_token(&val, NULL, cfile); 1697 parse_address_range (cfile, group, type, 1698 pool, &lpchain); 1699 break; 1700 case ALLOW: 1701 skip_token(&val, NULL, cfile); 1702 get_permit(cfile, &pool->permit_list, 1, 1703 &pool->valid_from, &pool->valid_until); 1704 break; 1705 1706 case DENY: 1707 skip_token(&val, NULL, cfile); 1708 get_permit(cfile, &pool->prohibit_list, 0, 1709 &pool->valid_from, &pool->valid_until); 1710 break; 1711 1712 case RBRACE: 1713 skip_token(&val, NULL, cfile); 1714 done = 1; 1715 break; 1716 1717 case END_OF_FILE: 1718 /* 1719 * We can get to END_OF_FILE if, for instance, 1720 * the parse_statement() reads all available tokens 1721 * and leaves us at the end. 1722 */ 1723 parse_warn(cfile, "unexpected end of file"); 1724 goto cleanup; 1725 1726 default: 1727 declaration = parse_statement(cfile, pool->group, 1728 POOL_DECL, NULL, 1729 declaration); 1730 break; 1731 } 1732 } while (!done); 1733 1734 /* See if there's already a pool into which we can merge this one. */ 1735 for (pp = pool->shared_network->pools; pp; pp = pp->next) { 1736 if (pp->group->statements != pool->group->statements) 1737 continue; 1738 #if defined (FAILOVER_PROTOCOL) 1739 if (pool->failover_peer != pp->failover_peer) 1740 continue; 1741 #endif 1742 if (!permit_list_match(pp->permit_list, 1743 pool->permit_list) || 1744 !permit_list_match(pool->permit_list, 1745 pp->permit_list) || 1746 !permit_list_match(pp->prohibit_list, 1747 pool->prohibit_list) || 1748 !permit_list_match(pool->prohibit_list, 1749 pp->prohibit_list)) 1750 continue; 1751 1752 /* Okay, we can merge these two pools. All we have to 1753 do is fix up the leases, which all point to their pool. */ 1754 for (lp = lpchain; lp; lp = lp->next) { 1755 pool_dereference(&lp->pool, MDL); 1756 pool_reference(&lp->pool, pp, MDL); 1757 } 1758 break; 1759 } 1760 1761 /* If we didn't succeed in merging this pool into another, put 1762 it on the list. */ 1763 if (!pp) { 1764 p = &pool->shared_network->pools; 1765 for (; *p; p = &((*p)->next)) 1766 ; 1767 pool_reference(p, pool, MDL); 1768 } 1769 1770 /* Don't allow a pool declaration with no addresses, since it is 1771 probably a configuration error. */ 1772 if (!lpchain) { 1773 parse_warn(cfile, "Pool declaration with no address range."); 1774 log_error("Pool declarations must always contain at least"); 1775 log_error("one range statement."); 1776 } 1777 1778 cleanup: 1779 /* Dereference the lease chain. */ 1780 lp = NULL; 1781 while (lpchain) { 1782 lease_reference(&lp, lpchain, MDL); 1783 lease_dereference(&lpchain, MDL); 1784 if (lp->next) { 1785 lease_reference(&lpchain, lp->next, MDL); 1786 lease_dereference(&lp->next, MDL); 1787 lease_dereference(&lp, MDL); 1788 } 1789 } 1790 pool_dereference(&pool, MDL); 1791 } 1792 1793 /* Expect a left brace; if there isn't one, skip over the rest of the 1794 statement and return zero; otherwise, return 1. */ 1795 1796 int parse_lbrace (cfile) 1797 struct parse *cfile; 1798 { 1799 enum dhcp_token token; 1800 const char *val; 1801 1802 token = next_token (&val, (unsigned *)0, cfile); 1803 if (token != LBRACE) { 1804 parse_warn (cfile, "expecting left brace."); 1805 skip_to_semi (cfile); 1806 return 0; 1807 } 1808 return 1; 1809 } 1810 1811 1812 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */ 1813 1814 void parse_host_declaration (cfile, group) 1815 struct parse *cfile; 1816 struct group *group; 1817 { 1818 const char *val; 1819 enum dhcp_token token; 1820 struct host_decl *host; 1821 char *name; 1822 int declaration = 0; 1823 int dynamicp = 0; 1824 int deleted = 0; 1825 isc_result_t status; 1826 int known; 1827 struct option *option; 1828 struct expression *expr = NULL; 1829 1830 name = parse_host_name (cfile); 1831 if (!name) { 1832 parse_warn (cfile, "expecting a name for host declaration."); 1833 skip_to_semi (cfile); 1834 return; 1835 } 1836 1837 host = (struct host_decl *)0; 1838 status = host_allocate (&host, MDL); 1839 if (status != ISC_R_SUCCESS) 1840 log_fatal ("can't allocate host decl struct %s: %s", 1841 name, isc_result_totext (status)); 1842 host -> name = name; 1843 if (!clone_group (&host -> group, group, MDL)) { 1844 log_fatal ("can't clone group for host %s", name); 1845 boom: 1846 host_dereference (&host, MDL); 1847 return; 1848 } 1849 1850 if (!parse_lbrace (cfile)) 1851 goto boom; 1852 1853 do { 1854 token = peek_token (&val, (unsigned *)0, cfile); 1855 if (token == RBRACE) { 1856 skip_token(&val, (unsigned *)0, cfile); 1857 break; 1858 } 1859 if (token == END_OF_FILE) { 1860 skip_token(&val, (unsigned *)0, cfile); 1861 parse_warn (cfile, "unexpected end of file"); 1862 break; 1863 } 1864 /* If the host declaration was created by the server, 1865 remember to save it. */ 1866 if (token == DYNAMIC) { 1867 dynamicp = 1; 1868 skip_token(&val, (unsigned *)0, cfile); 1869 if (!parse_semi (cfile)) 1870 break; 1871 continue; 1872 } 1873 /* If the host declaration was created by the server, 1874 remember to save it. */ 1875 if (token == TOKEN_DELETED) { 1876 deleted = 1; 1877 skip_token(&val, (unsigned *)0, cfile); 1878 if (!parse_semi (cfile)) 1879 break; 1880 continue; 1881 } 1882 1883 if (token == GROUP) { 1884 struct group_object *go; 1885 skip_token(&val, (unsigned *)0, cfile); 1886 token = next_token (&val, (unsigned *)0, cfile); 1887 if (token != STRING && !is_identifier (token)) { 1888 parse_warn (cfile, 1889 "expecting string or identifier."); 1890 skip_to_rbrace (cfile, 1); 1891 break; 1892 } 1893 go = (struct group_object *)0; 1894 if (!group_hash_lookup (&go, group_name_hash, 1895 val, strlen (val), MDL)) { 1896 parse_warn (cfile, "unknown group %s in host %s", 1897 val, host -> name); 1898 } else { 1899 if (host -> named_group) 1900 group_object_dereference 1901 (&host -> named_group, MDL); 1902 group_object_reference (&host -> named_group, 1903 go, MDL); 1904 group_object_dereference (&go, MDL); 1905 } 1906 if (!parse_semi (cfile)) 1907 break; 1908 continue; 1909 } 1910 1911 if (token == UID) { 1912 const char *s; 1913 unsigned char *t = 0; 1914 unsigned len; 1915 1916 skip_token(&val, (unsigned *)0, cfile); 1917 data_string_forget (&host -> client_identifier, MDL); 1918 1919 if (host->client_identifier.len != 0) { 1920 parse_warn(cfile, "Host %s already has a " 1921 "client identifier.", 1922 host->name); 1923 break; 1924 } 1925 1926 /* See if it's a string or a cshl. */ 1927 token = peek_token (&val, (unsigned *)0, cfile); 1928 if (token == STRING) { 1929 skip_token(&val, &len, cfile); 1930 s = val; 1931 host -> client_identifier.terminated = 1; 1932 } else { 1933 len = 0; 1934 t = parse_numeric_aggregate 1935 (cfile, 1936 (unsigned char *)0, &len, ':', 16, 8); 1937 if (!t) { 1938 parse_warn (cfile, 1939 "expecting hex list."); 1940 skip_to_semi (cfile); 1941 } 1942 s = (const char *)t; 1943 } 1944 if (!buffer_allocate 1945 (&host -> client_identifier.buffer, 1946 len + host -> client_identifier.terminated, MDL)) 1947 log_fatal ("no memory for uid for host %s.", 1948 host -> name); 1949 host -> client_identifier.data = 1950 host -> client_identifier.buffer -> data; 1951 host -> client_identifier.len = len; 1952 memcpy (host -> client_identifier.buffer -> data, s, 1953 len + host -> client_identifier.terminated); 1954 if (t) 1955 dfree (t, MDL); 1956 1957 if (!parse_semi (cfile)) 1958 break; 1959 continue; 1960 } 1961 1962 if (token == HOST_IDENTIFIER) { 1963 if (host->host_id_option != NULL) { 1964 parse_warn(cfile, 1965 "only one host-identifier allowed " 1966 "per host"); 1967 skip_to_rbrace(cfile, 1); 1968 break; 1969 } 1970 skip_token(&val, NULL, cfile); 1971 token = next_token(&val, NULL, cfile); 1972 if (token == V6RELOPT) { 1973 token = next_token(&val, NULL, cfile); 1974 if (token != NUMBER) { 1975 parse_warn(cfile, 1976 "host-identifier v6relopt " 1977 "must have a number"); 1978 skip_to_rbrace(cfile, 1); 1979 break; 1980 } 1981 host->relays = atoi(val); 1982 if (host->relays < 0) { 1983 parse_warn(cfile, 1984 "host-identifier v6relopt " 1985 "must have a number >= 0"); 1986 skip_to_rbrace(cfile, 1); 1987 break; 1988 } 1989 } else if (token != OPTION) { 1990 parse_warn(cfile, 1991 "host-identifier must be an option" 1992 " or v6relopt"); 1993 skip_to_rbrace(cfile, 1); 1994 break; 1995 } 1996 known = 0; 1997 option = NULL; 1998 status = parse_option_name(cfile, 1, &known, &option); 1999 if ((status != ISC_R_SUCCESS) || (option == NULL)) { 2000 break; 2001 } 2002 if (!known) { 2003 parse_warn(cfile, "unknown option %s.%s", 2004 option->universe->name, 2005 option->name); 2006 skip_to_rbrace(cfile, 1); 2007 break; 2008 } 2009 2010 if (! parse_option_data(&expr, cfile, 1, option)) { 2011 skip_to_rbrace(cfile, 1); 2012 option_dereference(&option, MDL); 2013 break; 2014 } 2015 2016 if (!parse_semi(cfile)) { 2017 skip_to_rbrace(cfile, 1); 2018 expression_dereference(&expr, MDL); 2019 option_dereference(&option, MDL); 2020 break; 2021 } 2022 2023 option_reference(&host->host_id_option, option, MDL); 2024 option_dereference(&option, MDL); 2025 data_string_copy(&host->host_id, 2026 &expr->data.const_data, MDL); 2027 expression_dereference(&expr, MDL); 2028 continue; 2029 } 2030 2031 declaration = parse_statement(cfile, host->group, HOST_DECL, 2032 host, declaration); 2033 } while (1); 2034 2035 if (deleted) { 2036 struct host_decl *hp = (struct host_decl *)0; 2037 if (host_hash_lookup (&hp, host_name_hash, 2038 (unsigned char *)host -> name, 2039 strlen (host -> name), MDL)) { 2040 delete_host (hp, 0); 2041 host_dereference (&hp, MDL); 2042 } 2043 } else { 2044 if (host -> named_group && host -> named_group -> group) { 2045 if (host -> group -> statements || 2046 (host -> group -> authoritative != 2047 host -> named_group -> group -> authoritative)) { 2048 if (host -> group -> next) 2049 group_dereference (&host -> group -> next, 2050 MDL); 2051 group_reference (&host -> group -> next, 2052 host -> named_group -> group, 2053 MDL); 2054 } else { 2055 group_dereference (&host -> group, MDL); 2056 group_reference (&host -> group, 2057 host -> named_group -> group, 2058 MDL); 2059 } 2060 } 2061 2062 if (dynamicp) 2063 host -> flags |= HOST_DECL_DYNAMIC; 2064 else 2065 host -> flags |= HOST_DECL_STATIC; 2066 2067 status = enter_host (host, dynamicp, 0); 2068 if (status != ISC_R_SUCCESS) 2069 parse_warn (cfile, "host %s: %s", host -> name, 2070 isc_result_totext (status)); 2071 } 2072 host_dereference (&host, MDL); 2073 } 2074 2075 /* class-declaration :== STRING LBRACE parameters declarations RBRACE 2076 */ 2077 2078 int parse_class_declaration (cp, cfile, group, type) 2079 struct class **cp; 2080 struct parse *cfile; 2081 struct group *group; 2082 int type; 2083 { 2084 const char *val; 2085 enum dhcp_token token; 2086 struct class *class = NULL, *pc = NULL; 2087 int declaration = 0; 2088 int lose = 0; 2089 struct data_string data; 2090 char *name; 2091 const char *tname; 2092 struct executable_statement *stmt = NULL; 2093 int new = 1; 2094 isc_result_t status = ISC_R_FAILURE; 2095 int matchedonce = 0; 2096 int submatchedonce = 0; 2097 unsigned code; 2098 2099 token = next_token (&val, NULL, cfile); 2100 if (token != STRING) { 2101 parse_warn (cfile, "Expecting class name"); 2102 skip_to_semi (cfile); 2103 return 0; 2104 } 2105 2106 /* See if there's already a class with the specified name. */ 2107 find_class (&pc, val, MDL); 2108 2109 /* If it is a class, we're updating it. If it's any of the other 2110 * types (subclass, vendor or user class), the named class is a 2111 * reference to the parent class so its mandatory. 2112 */ 2113 if (pc && (type == CLASS_TYPE_CLASS)) { 2114 class_reference(&class, pc, MDL); 2115 new = 0; 2116 class_dereference(&pc, MDL); 2117 } else if (!pc && (type != CLASS_TYPE_CLASS)) { 2118 parse_warn(cfile, "no class named %s", val); 2119 skip_to_semi(cfile); 2120 return 0; 2121 } 2122 2123 /* The old vendor-class and user-class declarations had an implicit 2124 match. We don't do the implicit match anymore. Instead, for 2125 backward compatibility, we have an implicit-vendor-class and an 2126 implicit-user-class. vendor-class and user-class declarations 2127 are turned into subclasses of the implicit classes, and the 2128 submatch expression of the implicit classes extracts the contents of 2129 the vendor class or user class. */ 2130 if ((type == CLASS_TYPE_VENDOR) || (type == CLASS_TYPE_USER)) { 2131 data.len = strlen (val); 2132 data.buffer = NULL; 2133 if (!buffer_allocate (&data.buffer, data.len + 1, MDL)) 2134 log_fatal ("no memory for class name."); 2135 data.data = &data.buffer -> data [0]; 2136 data.terminated = 1; 2137 2138 tname = type ? "implicit-vendor-class" : "implicit-user-class"; 2139 } else if (type == CLASS_TYPE_CLASS) { 2140 tname = val; 2141 } else { 2142 tname = NULL; 2143 } 2144 2145 if (tname) { 2146 name = dmalloc (strlen (tname) + 1, MDL); 2147 if (!name) 2148 log_fatal ("No memory for class name %s.", tname); 2149 strcpy (name, val); 2150 } else 2151 name = NULL; 2152 2153 /* If this is a straight subclass, parse the hash string. */ 2154 if (type == CLASS_TYPE_SUBCLASS) { 2155 token = peek_token (&val, NULL, cfile); 2156 if (token == STRING) { 2157 skip_token(&val, &data.len, cfile); 2158 data.buffer = NULL; 2159 2160 if (!buffer_allocate (&data.buffer, 2161 data.len + 1, MDL)) { 2162 if (pc) 2163 class_dereference (&pc, MDL); 2164 2165 return 0; 2166 } 2167 data.terminated = 1; 2168 data.data = &data.buffer -> data [0]; 2169 memcpy ((char *)data.buffer -> data, val, 2170 data.len + 1); 2171 } else if (token == NUMBER_OR_NAME || token == NUMBER) { 2172 memset (&data, 0, sizeof data); 2173 if (!parse_cshl (&data, cfile)) { 2174 if (pc) 2175 class_dereference (&pc, MDL); 2176 return 0; 2177 } 2178 } else { 2179 parse_warn (cfile, "Expecting string or hex list."); 2180 if (pc) 2181 class_dereference (&pc, MDL); 2182 return 0; 2183 } 2184 } 2185 2186 /* See if there's already a class in the hash table matching the 2187 hash data. */ 2188 if (type != CLASS_TYPE_CLASS) 2189 class_hash_lookup (&class, pc -> hash, 2190 (const char *)data.data, data.len, MDL); 2191 2192 /* If we didn't find an existing class, allocate a new one. */ 2193 if (!class) { 2194 /* Allocate the class structure... */ 2195 if (type == CLASS_TYPE_SUBCLASS) { 2196 status = subclass_allocate (&class, MDL); 2197 } else { 2198 status = class_allocate (&class, MDL); 2199 } 2200 if (pc) { 2201 group_reference (&class -> group, pc -> group, MDL); 2202 class_reference (&class -> superclass, pc, MDL); 2203 class -> lease_limit = pc -> lease_limit; 2204 if (class -> lease_limit) { 2205 class -> billed_leases = 2206 dmalloc (class -> lease_limit * 2207 sizeof (struct lease *), MDL); 2208 if (!class -> billed_leases) 2209 log_fatal ("no memory for billing"); 2210 memset (class -> billed_leases, 0, 2211 (class -> lease_limit * 2212 sizeof (struct lease *))); 2213 } 2214 data_string_copy (&class -> hash_string, &data, MDL); 2215 if (!pc -> hash && 2216 !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL)) 2217 log_fatal ("No memory for subclass hash."); 2218 class_hash_add (pc -> hash, 2219 (const char *)class -> hash_string.data, 2220 class -> hash_string.len, 2221 (void *)class, MDL); 2222 } else { 2223 if (class->group) 2224 group_dereference(&class->group, MDL); 2225 if (!clone_group (&class -> group, group, MDL)) 2226 log_fatal ("no memory to clone class group."); 2227 } 2228 2229 /* If this is an implicit vendor or user class, add a 2230 statement that causes the vendor or user class ID to 2231 be sent back in the reply. */ 2232 if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) { 2233 stmt = NULL; 2234 if (!executable_statement_allocate (&stmt, MDL)) 2235 log_fatal ("no memory for class statement."); 2236 stmt -> op = supersede_option_statement; 2237 if (option_cache_allocate (&stmt -> data.option, 2238 MDL)) { 2239 stmt -> data.option -> data = data; 2240 code = (type == CLASS_TYPE_VENDOR) 2241 ? DHO_VENDOR_CLASS_IDENTIFIER 2242 : DHO_USER_CLASS; 2243 option_code_hash_lookup( 2244 &stmt->data.option->option, 2245 dhcp_universe.code_hash, 2246 &code, 0, MDL); 2247 } 2248 class -> statements = stmt; 2249 } 2250 2251 /* Save the name, if there is one. */ 2252 if (class->name != NULL) 2253 dfree(class->name, MDL); 2254 class->name = name; 2255 } 2256 2257 if (type != CLASS_TYPE_CLASS) 2258 data_string_forget(&data, MDL); 2259 2260 /* Spawned classes don't have to have their own settings. */ 2261 if (class -> superclass) { 2262 token = peek_token (&val, NULL, cfile); 2263 if (token == SEMI) { 2264 skip_token(&val, NULL, cfile); 2265 2266 if (cp) 2267 status = class_reference (cp, class, MDL); 2268 class_dereference (&class, MDL); 2269 if (pc) 2270 class_dereference (&pc, MDL); 2271 return cp ? (status == ISC_R_SUCCESS) : 1; 2272 } 2273 /* Give the subclass its own group. */ 2274 if (!clone_group (&class -> group, class -> group, MDL)) 2275 log_fatal ("can't clone class group."); 2276 2277 } 2278 2279 if (!parse_lbrace (cfile)) { 2280 class_dereference (&class, MDL); 2281 if (pc) 2282 class_dereference (&pc, MDL); 2283 return 0; 2284 } 2285 2286 do { 2287 token = peek_token (&val, NULL, cfile); 2288 if (token == RBRACE) { 2289 skip_token(&val, NULL, cfile); 2290 break; 2291 } else if (token == END_OF_FILE) { 2292 skip_token(&val, NULL, cfile); 2293 parse_warn (cfile, "unexpected end of file"); 2294 break; 2295 } else if (token == DYNAMIC) { 2296 class->flags |= CLASS_DECL_DYNAMIC; 2297 skip_token(&val, NULL, cfile); 2298 if (!parse_semi (cfile)) 2299 break; 2300 continue; 2301 } else if (token == TOKEN_DELETED) { 2302 class->flags |= CLASS_DECL_DELETED; 2303 skip_token(&val, NULL, cfile); 2304 if (!parse_semi (cfile)) 2305 break; 2306 continue; 2307 } else if (token == MATCH) { 2308 if (pc) { 2309 parse_warn (cfile, 2310 "invalid match in subclass."); 2311 skip_to_semi (cfile); 2312 break; 2313 } 2314 skip_token(&val, NULL, cfile); 2315 token = peek_token (&val, NULL, cfile); 2316 if (token != IF) 2317 goto submatch; 2318 skip_token(&val, NULL, cfile); 2319 if (matchedonce) { 2320 parse_warn(cfile, "A class may only have " 2321 "one 'match if' clause."); 2322 skip_to_semi(cfile); 2323 break; 2324 } 2325 matchedonce = 1; 2326 if (class->expr) 2327 expression_dereference(&class->expr, MDL); 2328 if (!parse_boolean_expression (&class->expr, cfile, 2329 &lose)) { 2330 if (!lose) { 2331 parse_warn (cfile, 2332 "expecting boolean expr."); 2333 skip_to_semi (cfile); 2334 } 2335 } else { 2336 #if defined (DEBUG_EXPRESSION_PARSE) 2337 print_expression ("class match", 2338 class -> expr); 2339 #endif 2340 parse_semi (cfile); 2341 } 2342 } else if (token == SPAWN) { 2343 skip_token(&val, NULL, cfile); 2344 if (pc) { 2345 parse_warn (cfile, 2346 "invalid spawn in subclass."); 2347 skip_to_semi (cfile); 2348 break; 2349 } 2350 class -> spawning = 1; 2351 token = next_token (&val, NULL, cfile); 2352 if (token != WITH) { 2353 parse_warn (cfile, 2354 "expecting with after spawn"); 2355 skip_to_semi (cfile); 2356 break; 2357 } 2358 submatch: 2359 if (submatchedonce) { 2360 parse_warn (cfile, 2361 "can't override existing %s.", 2362 "submatch/spawn"); 2363 skip_to_semi (cfile); 2364 break; 2365 } 2366 submatchedonce = 1; 2367 if (class->submatch) 2368 expression_dereference(&class->submatch, MDL); 2369 if (!parse_data_expression (&class -> submatch, 2370 cfile, &lose)) { 2371 if (!lose) { 2372 parse_warn (cfile, 2373 "expecting data expr."); 2374 skip_to_semi (cfile); 2375 } 2376 } else { 2377 #if defined (DEBUG_EXPRESSION_PARSE) 2378 print_expression ("class submatch", 2379 class -> submatch); 2380 #endif 2381 parse_semi (cfile); 2382 } 2383 } else if (token == LEASE) { 2384 skip_token(&val, NULL, cfile); 2385 token = next_token (&val, NULL, cfile); 2386 if (token != LIMIT) { 2387 parse_warn (cfile, "expecting \"limit\""); 2388 if (token != SEMI) 2389 skip_to_semi (cfile); 2390 break; 2391 } 2392 token = next_token (&val, NULL, cfile); 2393 if (token != NUMBER) { 2394 parse_warn (cfile, "expecting a number"); 2395 if (token != SEMI) 2396 skip_to_semi (cfile); 2397 break; 2398 } 2399 class -> lease_limit = atoi (val); 2400 if (class->billed_leases) 2401 dfree(class->billed_leases, MDL); 2402 class -> billed_leases = 2403 dmalloc (class -> lease_limit * 2404 sizeof (struct lease *), MDL); 2405 if (!class -> billed_leases) 2406 log_fatal ("no memory for billed leases."); 2407 memset (class -> billed_leases, 0, 2408 (class -> lease_limit * 2409 sizeof (struct lease *))); 2410 have_billing_classes = 1; 2411 parse_semi (cfile); 2412 } else { 2413 declaration = parse_statement (cfile, class -> group, 2414 CLASS_DECL, NULL, 2415 declaration); 2416 } 2417 } while (1); 2418 2419 if (class->flags & CLASS_DECL_DELETED) { 2420 if (type == CLASS_TYPE_CLASS) { 2421 struct class *theclass = NULL; 2422 2423 status = find_class(&theclass, class->name, MDL); 2424 if (status == ISC_R_SUCCESS) { 2425 delete_class(theclass, 0); 2426 class_dereference(&theclass, MDL); 2427 } 2428 } else { 2429 class_hash_delete(pc->hash, 2430 (char *)class->hash_string.data, 2431 class->hash_string.len, MDL); 2432 } 2433 } else if (type == CLASS_TYPE_CLASS && new) { 2434 if (!collections -> classes) 2435 class_reference (&collections -> classes, class, MDL); 2436 else { 2437 struct class *c; 2438 for (c = collections -> classes; 2439 c -> nic; c = c -> nic) 2440 ; 2441 class_reference (&c -> nic, class, MDL); 2442 } 2443 } 2444 2445 if (cp) /* should always be 0??? */ 2446 status = class_reference (cp, class, MDL); 2447 class_dereference (&class, MDL); 2448 if (pc) 2449 class_dereference (&pc, MDL); 2450 return cp ? (status == ISC_R_SUCCESS) : 1; 2451 } 2452 2453 /* shared-network-declaration :== 2454 hostname LBRACE declarations parameters RBRACE */ 2455 2456 void parse_shared_net_declaration (cfile, group) 2457 struct parse *cfile; 2458 struct group *group; 2459 { 2460 const char *val; 2461 enum dhcp_token token; 2462 struct shared_network *share; 2463 char *name; 2464 int declaration = 0; 2465 isc_result_t status; 2466 2467 share = (struct shared_network *)0; 2468 status = shared_network_allocate (&share, MDL); 2469 if (status != ISC_R_SUCCESS) 2470 log_fatal ("Can't allocate shared subnet: %s", 2471 isc_result_totext (status)); 2472 if (clone_group (&share -> group, group, MDL) == 0) { 2473 log_fatal ("Can't clone group for shared net"); 2474 } 2475 shared_network_reference (&share -> group -> shared_network, 2476 share, MDL); 2477 2478 /* Get the name of the shared network... */ 2479 token = peek_token (&val, (unsigned *)0, cfile); 2480 if (token == STRING) { 2481 skip_token(&val, (unsigned *)0, cfile); 2482 2483 if (val [0] == 0) { 2484 parse_warn (cfile, "zero-length shared network name"); 2485 val = "<no-name-given>"; 2486 } 2487 name = dmalloc (strlen (val) + 1, MDL); 2488 if (!name) 2489 log_fatal ("no memory for shared network name"); 2490 strcpy (name, val); 2491 } else { 2492 name = parse_host_name (cfile); 2493 if (!name) { 2494 parse_warn (cfile, 2495 "expecting a name for shared-network"); 2496 skip_to_semi (cfile); 2497 shared_network_dereference (&share, MDL); 2498 return; 2499 } 2500 } 2501 share -> name = name; 2502 2503 if (!parse_lbrace (cfile)) { 2504 shared_network_dereference (&share, MDL); 2505 return; 2506 } 2507 2508 do { 2509 token = peek_token (&val, (unsigned *)0, cfile); 2510 if (token == RBRACE) { 2511 skip_token(&val, (unsigned *)0, cfile); 2512 if (!share -> subnets) 2513 parse_warn (cfile, 2514 "empty shared-network decl"); 2515 else 2516 enter_shared_network (share); 2517 shared_network_dereference (&share, MDL); 2518 return; 2519 } else if (token == END_OF_FILE) { 2520 skip_token(&val, (unsigned *)0, cfile); 2521 parse_warn (cfile, "unexpected end of file"); 2522 break; 2523 } else if (token == INTERFACE) { 2524 skip_token(&val, (unsigned *)0, cfile); 2525 token = next_token (&val, (unsigned *)0, cfile); 2526 new_shared_network_interface (cfile, share, val); 2527 if (!parse_semi (cfile)) 2528 break; 2529 continue; 2530 } 2531 2532 declaration = parse_statement (cfile, share -> group, 2533 SHARED_NET_DECL, 2534 (struct host_decl *)0, 2535 declaration); 2536 } while (1); 2537 shared_network_dereference (&share, MDL); 2538 } 2539 2540 2541 static int 2542 common_subnet_parsing(struct parse *cfile, 2543 struct shared_network *share, 2544 struct subnet *subnet) { 2545 enum dhcp_token token; 2546 struct subnet *t, *u; 2547 const char *val; 2548 int declaration = 0; 2549 2550 enter_subnet(subnet); 2551 2552 if (!parse_lbrace(cfile)) { 2553 subnet_dereference(&subnet, MDL); 2554 return 0; 2555 } 2556 2557 do { 2558 token = peek_token(&val, NULL, cfile); 2559 if (token == RBRACE) { 2560 skip_token(&val, NULL, cfile); 2561 break; 2562 } else if (token == END_OF_FILE) { 2563 skip_token(&val, NULL, cfile); 2564 parse_warn (cfile, "unexpected end of file"); 2565 break; 2566 } else if (token == INTERFACE) { 2567 skip_token(&val, NULL, cfile); 2568 token = next_token(&val, NULL, cfile); 2569 new_shared_network_interface(cfile, share, val); 2570 if (!parse_semi(cfile)) 2571 break; 2572 continue; 2573 } 2574 declaration = parse_statement(cfile, subnet->group, 2575 SUBNET_DECL, 2576 NULL, 2577 declaration); 2578 } while (1); 2579 2580 /* Add the subnet to the list of subnets in this shared net. */ 2581 if (share->subnets == NULL) { 2582 subnet_reference(&share->subnets, subnet, MDL); 2583 } else { 2584 u = NULL; 2585 for (t = share->subnets; t->next_sibling; t = t->next_sibling) { 2586 if (subnet_inner_than(subnet, t, 0)) { 2587 subnet_reference(&subnet->next_sibling, t, MDL); 2588 if (u) { 2589 subnet_dereference(&u->next_sibling, 2590 MDL); 2591 subnet_reference(&u->next_sibling, 2592 subnet, MDL); 2593 } else { 2594 subnet_dereference(&share->subnets, 2595 MDL); 2596 subnet_reference(&share->subnets, 2597 subnet, MDL); 2598 } 2599 subnet_dereference(&subnet, MDL); 2600 return 1; 2601 } 2602 u = t; 2603 } 2604 subnet_reference(&t->next_sibling, subnet, MDL); 2605 } 2606 subnet_dereference(&subnet, MDL); 2607 return 1; 2608 } 2609 2610 /* subnet-declaration :== 2611 net NETMASK netmask RBRACE parameters declarations LBRACE */ 2612 2613 void parse_subnet_declaration (cfile, share) 2614 struct parse *cfile; 2615 struct shared_network *share; 2616 { 2617 const char *val; 2618 enum dhcp_token token; 2619 struct subnet *subnet; 2620 struct iaddr iaddr; 2621 unsigned char addr [4]; 2622 unsigned len = sizeof addr; 2623 isc_result_t status; 2624 2625 subnet = (struct subnet *)0; 2626 status = subnet_allocate (&subnet, MDL); 2627 if (status != ISC_R_SUCCESS) 2628 log_fatal ("Allocation of new subnet failed: %s", 2629 isc_result_totext (status)); 2630 shared_network_reference (&subnet -> shared_network, share, MDL); 2631 2632 /* 2633 * If our parent shared network was implicitly created by the software, 2634 * and not explicitly configured by the user, then we actually put all 2635 * configuration scope in the parent (the shared network and subnet 2636 * share the same {}-level scope). 2637 * 2638 * Otherwise, we clone the parent group and continue as normal. 2639 */ 2640 if (share->flags & SHARED_IMPLICIT) { 2641 group_reference(&subnet->group, share->group, MDL); 2642 } else { 2643 if (!clone_group(&subnet->group, share->group, MDL)) { 2644 log_fatal("Allocation of group for new subnet failed."); 2645 } 2646 } 2647 subnet_reference (&subnet -> group -> subnet, subnet, MDL); 2648 2649 /* Get the network number... */ 2650 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) { 2651 subnet_dereference (&subnet, MDL); 2652 return; 2653 } 2654 memcpy (iaddr.iabuf, addr, len); 2655 iaddr.len = len; 2656 subnet -> net = iaddr; 2657 2658 token = next_token (&val, (unsigned *)0, cfile); 2659 if (token != NETMASK) { 2660 parse_warn (cfile, "Expecting netmask"); 2661 skip_to_semi (cfile); 2662 return; 2663 } 2664 2665 /* Get the netmask... */ 2666 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) { 2667 subnet_dereference (&subnet, MDL); 2668 return; 2669 } 2670 memcpy (iaddr.iabuf, addr, len); 2671 iaddr.len = len; 2672 subnet -> netmask = iaddr; 2673 2674 /* Validate the network number/netmask pair. */ 2675 if (host_addr (subnet -> net, subnet -> netmask)) { 2676 char *maskstr; 2677 2678 maskstr = strdup (piaddr (subnet -> netmask)); 2679 parse_warn (cfile, 2680 "subnet %s netmask %s: bad subnet number/mask combination.", 2681 piaddr (subnet -> net), maskstr); 2682 free(maskstr); 2683 subnet_dereference (&subnet, MDL); 2684 skip_to_semi (cfile); 2685 return; 2686 } 2687 2688 common_subnet_parsing(cfile, share, subnet); 2689 } 2690 2691 /* subnet6-declaration :== 2692 net / bits RBRACE parameters declarations LBRACE */ 2693 2694 void 2695 parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) { 2696 #if !defined(DHCPv6) 2697 parse_warn(cfile, "No DHCPv6 support."); 2698 skip_to_semi(cfile); 2699 #else /* defined(DHCPv6) */ 2700 struct subnet *subnet; 2701 isc_result_t status; 2702 enum dhcp_token token; 2703 const char *val; 2704 char *endp; 2705 int ofs; 2706 const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0, 2707 0xF0, 0xF8, 0xFC, 0xFE }; 2708 struct iaddr iaddr; 2709 2710 if (local_family != AF_INET6) { 2711 parse_warn(cfile, "subnet6 statement is only supported " 2712 "in DHCPv6 mode."); 2713 skip_to_semi(cfile); 2714 return; 2715 } 2716 2717 subnet = NULL; 2718 status = subnet_allocate(&subnet, MDL); 2719 if (status != ISC_R_SUCCESS) { 2720 log_fatal("Allocation of new subnet failed: %s", 2721 isc_result_totext(status)); 2722 } 2723 shared_network_reference(&subnet->shared_network, share, MDL); 2724 2725 /* 2726 * If our parent shared network was implicitly created by the software, 2727 * and not explicitly configured by the user, then we actually put all 2728 * configuration scope in the parent (the shared network and subnet 2729 * share the same {}-level scope). 2730 * 2731 * Otherwise, we clone the parent group and continue as normal. 2732 */ 2733 if (share->flags & SHARED_IMPLICIT) { 2734 group_reference(&subnet->group, share->group, MDL); 2735 } else { 2736 if (!clone_group(&subnet->group, share->group, MDL)) { 2737 log_fatal("Allocation of group for new subnet failed."); 2738 } 2739 } 2740 subnet_reference(&subnet->group->subnet, subnet, MDL); 2741 2742 if (!parse_ip6_addr(cfile, &subnet->net)) { 2743 subnet_dereference(&subnet, MDL); 2744 return; 2745 } 2746 2747 token = next_token(&val, NULL, cfile); 2748 if (token != SLASH) { 2749 parse_warn(cfile, "Expecting a '/'."); 2750 skip_to_semi(cfile); 2751 return; 2752 } 2753 2754 token = next_token(&val, NULL, cfile); 2755 if (token != NUMBER) { 2756 parse_warn(cfile, "Expecting a number."); 2757 skip_to_semi(cfile); 2758 return; 2759 } 2760 2761 subnet->prefix_len = strtol(val, &endp, 10); 2762 if ((subnet->prefix_len < 0) || 2763 (subnet->prefix_len > 128) || 2764 (*endp != '\0')) { 2765 parse_warn(cfile, "Expecting a number between 0 and 128."); 2766 skip_to_semi(cfile); 2767 return; 2768 } 2769 2770 if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) { 2771 parse_warn(cfile, "New subnet mask too short."); 2772 skip_to_semi(cfile); 2773 return; 2774 } 2775 2776 /* 2777 * Create a netmask. 2778 */ 2779 subnet->netmask.len = 16; 2780 ofs = subnet->prefix_len / 8; 2781 if (ofs < subnet->netmask.len) { 2782 subnet->netmask.iabuf[ofs] = mask[subnet->prefix_len % 8]; 2783 } 2784 while (--ofs >= 0) { 2785 subnet->netmask.iabuf[ofs] = 0xFF; 2786 } 2787 2788 /* Validate the network number/netmask pair. */ 2789 iaddr = subnet_number(subnet->net, subnet->netmask); 2790 if (memcmp(&iaddr, &subnet->net, 16) != 0) { 2791 parse_warn(cfile, 2792 "subnet %s/%d: prefix not long enough for address.", 2793 piaddr(subnet->net), subnet->prefix_len); 2794 subnet_dereference(&subnet, MDL); 2795 skip_to_semi(cfile); 2796 return; 2797 } 2798 2799 if (!common_subnet_parsing(cfile, share, subnet)) { 2800 return; 2801 } 2802 #endif /* defined(DHCPv6) */ 2803 } 2804 2805 /* group-declaration :== RBRACE parameters declarations LBRACE */ 2806 2807 void parse_group_declaration (cfile, group) 2808 struct parse *cfile; 2809 struct group *group; 2810 { 2811 const char *val; 2812 enum dhcp_token token; 2813 struct group *g; 2814 int declaration = 0; 2815 struct group_object *t = NULL; 2816 isc_result_t status; 2817 char *name = NULL; 2818 int deletedp = 0; 2819 int dynamicp = 0; 2820 int staticp = 0; 2821 2822 g = NULL; 2823 if (!clone_group(&g, group, MDL)) 2824 log_fatal("no memory for explicit group."); 2825 2826 token = peek_token(&val, NULL, cfile); 2827 if (is_identifier (token) || token == STRING) { 2828 skip_token(&val, NULL, cfile); 2829 2830 name = dmalloc(strlen(val) + 1, MDL); 2831 if (!name) 2832 log_fatal("no memory for group decl name %s", val); 2833 strcpy(name, val); 2834 } 2835 2836 if (!parse_lbrace(cfile)) { 2837 group_dereference(&g, MDL); 2838 return; 2839 } 2840 2841 do { 2842 token = peek_token(&val, NULL, cfile); 2843 if (token == RBRACE) { 2844 skip_token(&val, NULL, cfile); 2845 break; 2846 } else if (token == END_OF_FILE) { 2847 skip_token(&val, NULL, cfile); 2848 parse_warn(cfile, "unexpected end of file"); 2849 break; 2850 } else if (token == TOKEN_DELETED) { 2851 skip_token(&val, NULL, cfile); 2852 parse_semi(cfile); 2853 deletedp = 1; 2854 } else if (token == DYNAMIC) { 2855 skip_token(&val, NULL, cfile); 2856 parse_semi(cfile); 2857 dynamicp = 1; 2858 } else if (token == STATIC) { 2859 skip_token(&val, NULL, cfile); 2860 parse_semi(cfile); 2861 staticp = 1; 2862 } 2863 declaration = parse_statement(cfile, g, GROUP_DECL, 2864 NULL, declaration); 2865 } while (1); 2866 2867 if (name) { 2868 if (deletedp) { 2869 if (group_name_hash) { 2870 t = NULL; 2871 if (group_hash_lookup(&t, group_name_hash, 2872 name, 2873 strlen(name), MDL)) { 2874 delete_group(t, 0); 2875 } 2876 } 2877 } else { 2878 t = NULL; 2879 status = group_object_allocate(&t, MDL); 2880 if (status != ISC_R_SUCCESS) 2881 log_fatal("no memory for group decl %s: %s", 2882 val, isc_result_totext(status)); 2883 group_reference(&t->group, g, MDL); 2884 t->name = name; 2885 /* no need to include deletedp as it's handled above */ 2886 t->flags = ((staticp ? GROUP_OBJECT_STATIC : 0) | 2887 (dynamicp ? GROUP_OBJECT_DYNAMIC : 0)); 2888 supersede_group(t, 0); 2889 } 2890 if (t != NULL) 2891 group_object_dereference(&t, MDL); 2892 } 2893 } 2894 2895 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI 2896 ip-addrs-or-hostnames :== ip-addr-or-hostname 2897 | ip-addrs-or-hostnames ip-addr-or-hostname */ 2898 2899 int 2900 parse_fixed_addr_param(struct option_cache **oc, 2901 struct parse *cfile, 2902 enum dhcp_token type) { 2903 int parse_ok; 2904 const char *val; 2905 enum dhcp_token token; 2906 struct expression *expr = NULL; 2907 struct expression *tmp, *new; 2908 int status; 2909 2910 do { 2911 tmp = NULL; 2912 if (type == FIXED_ADDR) { 2913 parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1); 2914 } else { 2915 /* INSIST(type == FIXED_ADDR6); */ 2916 parse_ok = parse_ip6_addr_expr(&tmp, cfile); 2917 } 2918 if (parse_ok) { 2919 if (expr != NULL) { 2920 new = NULL; 2921 status = make_concat(&new, expr, tmp); 2922 expression_dereference(&expr, MDL); 2923 expression_dereference(&tmp, MDL); 2924 if (!status) { 2925 return 0; 2926 } 2927 expr = new; 2928 } else { 2929 expr = tmp; 2930 } 2931 } else { 2932 if (expr != NULL) { 2933 expression_dereference (&expr, MDL); 2934 } 2935 return 0; 2936 } 2937 token = peek_token(&val, NULL, cfile); 2938 if (token == COMMA) { 2939 token = next_token(&val, NULL, cfile); 2940 } 2941 } while (token == COMMA); 2942 2943 if (!parse_semi(cfile)) { 2944 if (expr) { 2945 expression_dereference (&expr, MDL); 2946 } 2947 return 0; 2948 } 2949 2950 status = option_cache(oc, NULL, expr, NULL, MDL); 2951 expression_dereference(&expr, MDL); 2952 return status; 2953 } 2954 2955 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE 2956 2957 lease_parameters :== <nil> 2958 | lease_parameter 2959 | lease_parameters lease_parameter 2960 2961 lease_parameter :== STARTS date 2962 | ENDS date 2963 | TIMESTAMP date 2964 | HARDWARE hardware-parameter 2965 | UID hex_numbers SEMI 2966 | HOSTNAME hostname SEMI 2967 | CLIENT_HOSTNAME hostname SEMI 2968 | CLASS identifier SEMI 2969 | DYNAMIC_BOOTP SEMI */ 2970 2971 int parse_lease_declaration (struct lease **lp, struct parse *cfile) 2972 { 2973 const char *val; 2974 enum dhcp_token token; 2975 unsigned char addr [4]; 2976 unsigned len = sizeof addr; 2977 int seenmask = 0; 2978 int seenbit; 2979 char tbuf [32]; 2980 struct lease *lease; 2981 struct executable_statement *on; 2982 int lose; 2983 TIME t; 2984 int noequal, newbinding; 2985 struct binding *binding; 2986 struct binding_value *nv; 2987 isc_result_t status; 2988 struct option_cache *oc; 2989 pair *p; 2990 binding_state_t new_state; 2991 unsigned buflen = 0; 2992 struct class *class; 2993 2994 lease = (struct lease *)0; 2995 status = lease_allocate (&lease, MDL); 2996 if (status != ISC_R_SUCCESS) 2997 return 0; 2998 2999 /* Get the address for which the lease has been issued. */ 3000 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) { 3001 lease_dereference (&lease, MDL); 3002 return 0; 3003 } 3004 memcpy (lease -> ip_addr.iabuf, addr, len); 3005 lease -> ip_addr.len = len; 3006 3007 if (!parse_lbrace (cfile)) { 3008 lease_dereference (&lease, MDL); 3009 return 0; 3010 } 3011 3012 do { 3013 token = next_token (&val, (unsigned *)0, cfile); 3014 if (token == RBRACE) 3015 break; 3016 else if (token == END_OF_FILE) { 3017 parse_warn (cfile, "unexpected end of file"); 3018 break; 3019 } 3020 strncpy (tbuf, val, sizeof tbuf); 3021 tbuf [(sizeof tbuf) - 1] = 0; 3022 3023 /* Parse any of the times associated with the lease. */ 3024 switch (token) { 3025 case STARTS: 3026 case ENDS: 3027 case TIMESTAMP: 3028 case TSTP: 3029 case TSFP: 3030 case ATSFP: 3031 case CLTT: 3032 t = parse_date (cfile); 3033 switch (token) { 3034 case STARTS: 3035 seenbit = 1; 3036 lease -> starts = t; 3037 break; 3038 3039 case ENDS: 3040 seenbit = 2; 3041 lease -> ends = t; 3042 break; 3043 3044 case TSTP: 3045 seenbit = 65536; 3046 lease -> tstp = t; 3047 break; 3048 3049 case TSFP: 3050 seenbit = 131072; 3051 lease -> tsfp = t; 3052 break; 3053 3054 case ATSFP: 3055 seenbit = 262144; 3056 lease->atsfp = t; 3057 break; 3058 3059 case CLTT: 3060 seenbit = 524288; 3061 lease -> cltt = t; 3062 break; 3063 3064 default: /* for gcc, we'll never get here. */ 3065 log_fatal ("Impossible error at %s:%d.", MDL); 3066 return 0; 3067 } 3068 break; 3069 3070 /* Colon-separated hexadecimal octets... */ 3071 case UID: 3072 seenbit = 8; 3073 token = peek_token (&val, (unsigned *)0, cfile); 3074 if (token == STRING) { 3075 unsigned char *tuid; 3076 skip_token(&val, &buflen, cfile); 3077 if (buflen < sizeof lease -> uid_buf) { 3078 tuid = lease -> uid_buf; 3079 lease -> uid_max = 3080 sizeof lease -> uid_buf; 3081 } else { 3082 tuid = ((unsigned char *) 3083 dmalloc (buflen, MDL)); 3084 if (!tuid) { 3085 log_error ("no space for uid"); 3086 lease_dereference (&lease, 3087 MDL); 3088 return 0; 3089 } 3090 lease -> uid_max = buflen; 3091 } 3092 lease -> uid_len = buflen; 3093 memcpy (tuid, val, lease -> uid_len); 3094 lease -> uid = tuid; 3095 } else { 3096 buflen = 0; 3097 lease -> uid = (parse_numeric_aggregate 3098 (cfile, (unsigned char *)0, 3099 &buflen, ':', 16, 8)); 3100 if (!lease -> uid) { 3101 lease_dereference (&lease, MDL); 3102 return 0; 3103 } 3104 lease -> uid_len = buflen; 3105 lease -> uid_max = buflen; 3106 if (lease -> uid_len == 0) { 3107 lease -> uid = (unsigned char *)0; 3108 parse_warn (cfile, "zero-length uid"); 3109 seenbit = 0; 3110 parse_semi (cfile); 3111 break; 3112 } 3113 } 3114 parse_semi (cfile); 3115 if (!lease -> uid) { 3116 log_fatal ("No memory for lease uid"); 3117 } 3118 break; 3119 3120 case CLASS: 3121 seenbit = 32; 3122 token = next_token (&val, (unsigned *)0, cfile); 3123 if (!is_identifier (token)) { 3124 if (token != SEMI) 3125 skip_to_rbrace (cfile, 1); 3126 lease_dereference (&lease, MDL); 3127 return 0; 3128 } 3129 parse_semi (cfile); 3130 /* for now, we aren't using this. */ 3131 break; 3132 3133 case HARDWARE: 3134 seenbit = 64; 3135 parse_hardware_param (cfile, 3136 &lease -> hardware_addr); 3137 break; 3138 3139 case TOKEN_RESERVED: 3140 seenbit = 0; 3141 lease->flags |= RESERVED_LEASE; 3142 parse_semi(cfile); 3143 break; 3144 3145 case DYNAMIC_BOOTP: 3146 seenbit = 0; 3147 lease -> flags |= BOOTP_LEASE; 3148 parse_semi (cfile); 3149 break; 3150 3151 /* XXX: Reverse compatibility? */ 3152 case TOKEN_ABANDONED: 3153 seenbit = 256; 3154 lease -> binding_state = FTS_ABANDONED; 3155 lease -> next_binding_state = FTS_ABANDONED; 3156 parse_semi (cfile); 3157 break; 3158 3159 case TOKEN_NEXT: 3160 seenbit = 128; 3161 token = next_token (&val, (unsigned *)0, cfile); 3162 if (token != BINDING) { 3163 parse_warn (cfile, "expecting 'binding'"); 3164 skip_to_semi (cfile); 3165 break; 3166 } 3167 goto do_binding_state; 3168 3169 case REWIND: 3170 seenbit = 512; 3171 token = next_token(&val, NULL, cfile); 3172 if (token != BINDING) { 3173 parse_warn(cfile, "expecting 'binding'"); 3174 skip_to_semi(cfile); 3175 break; 3176 } 3177 goto do_binding_state; 3178 3179 case BINDING: 3180 seenbit = 256; 3181 3182 do_binding_state: 3183 token = next_token (&val, (unsigned *)0, cfile); 3184 if (token != STATE) { 3185 parse_warn (cfile, "expecting 'state'"); 3186 skip_to_semi (cfile); 3187 break; 3188 } 3189 token = next_token (&val, (unsigned *)0, cfile); 3190 switch (token) { 3191 case TOKEN_ABANDONED: 3192 new_state = FTS_ABANDONED; 3193 break; 3194 case TOKEN_FREE: 3195 new_state = FTS_FREE; 3196 break; 3197 case TOKEN_ACTIVE: 3198 new_state = FTS_ACTIVE; 3199 break; 3200 case TOKEN_EXPIRED: 3201 new_state = FTS_EXPIRED; 3202 break; 3203 case TOKEN_RELEASED: 3204 new_state = FTS_RELEASED; 3205 break; 3206 case TOKEN_RESET: 3207 new_state = FTS_RESET; 3208 break; 3209 case TOKEN_BACKUP: 3210 new_state = FTS_BACKUP; 3211 break; 3212 3213 /* RESERVED and BOOTP states preserved for 3214 * compatibleness with older versions. 3215 */ 3216 case TOKEN_RESERVED: 3217 new_state = FTS_ACTIVE; 3218 lease->flags |= RESERVED_LEASE; 3219 break; 3220 case TOKEN_BOOTP: 3221 new_state = FTS_ACTIVE; 3222 lease->flags |= BOOTP_LEASE; 3223 break; 3224 3225 default: 3226 parse_warn (cfile, 3227 "%s: expecting a binding state.", 3228 val); 3229 skip_to_semi (cfile); 3230 return 0; 3231 } 3232 3233 if (seenbit == 256) { 3234 lease -> binding_state = new_state; 3235 3236 /* 3237 * Apply default/conservative next/rewind 3238 * binding states if they haven't been set 3239 * yet. These defaults will be over-ridden if 3240 * they are set later in parsing. 3241 */ 3242 if (!(seenmask & 128)) 3243 lease->next_binding_state = new_state; 3244 3245 /* The most conservative rewind state. */ 3246 if (!(seenmask & 512)) 3247 lease->rewind_binding_state = new_state; 3248 } else if (seenbit == 128) 3249 lease -> next_binding_state = new_state; 3250 else if (seenbit == 512) 3251 lease->rewind_binding_state = new_state; 3252 else 3253 log_fatal("Impossible condition at %s:%d.", 3254 MDL); 3255 3256 parse_semi (cfile); 3257 break; 3258 3259 case CLIENT_HOSTNAME: 3260 seenbit = 1024; 3261 token = peek_token (&val, (unsigned *)0, cfile); 3262 if (token == STRING) { 3263 if (!parse_string (cfile, 3264 &lease -> client_hostname, 3265 (unsigned *)0)) { 3266 lease_dereference (&lease, MDL); 3267 return 0; 3268 } 3269 } else { 3270 lease -> client_hostname = 3271 parse_host_name (cfile); 3272 if (lease -> client_hostname) 3273 parse_semi (cfile); 3274 else { 3275 parse_warn (cfile, 3276 "expecting a hostname."); 3277 skip_to_semi (cfile); 3278 lease_dereference (&lease, MDL); 3279 return 0; 3280 } 3281 } 3282 break; 3283 3284 case BILLING: 3285 seenbit = 2048; 3286 class = (struct class *)0; 3287 token = next_token (&val, (unsigned *)0, cfile); 3288 if (token == CLASS) { 3289 token = next_token (&val, 3290 (unsigned *)0, cfile); 3291 if (token != STRING) { 3292 parse_warn (cfile, "expecting string"); 3293 if (token != SEMI) 3294 skip_to_semi (cfile); 3295 token = BILLING; 3296 break; 3297 } 3298 if (lease -> billing_class) 3299 class_dereference (&lease -> billing_class, 3300 MDL); 3301 find_class (&class, val, MDL); 3302 if (!class) 3303 parse_warn (cfile, 3304 "unknown class %s", val); 3305 parse_semi (cfile); 3306 } else if (token == SUBCLASS) { 3307 if (lease -> billing_class) 3308 class_dereference (&lease -> billing_class, 3309 MDL); 3310 parse_class_declaration(&class, cfile, NULL, 3311 CLASS_TYPE_SUBCLASS); 3312 } else { 3313 parse_warn (cfile, "expecting \"class\""); 3314 if (token != SEMI) 3315 skip_to_semi (cfile); 3316 } 3317 if (class) { 3318 class_reference (&lease -> billing_class, 3319 class, MDL); 3320 class_dereference (&class, MDL); 3321 } 3322 break; 3323 3324 case ON: 3325 on = (struct executable_statement *)0; 3326 lose = 0; 3327 if (!parse_on_statement (&on, cfile, &lose)) { 3328 skip_to_rbrace (cfile, 1); 3329 lease_dereference (&lease, MDL); 3330 return 0; 3331 } 3332 seenbit = 0; 3333 if ((on->data.on.evtypes & ON_EXPIRY) && 3334 on->data.on.statements) { 3335 seenbit |= 16384; 3336 executable_statement_reference 3337 (&lease->on_star.on_expiry, 3338 on->data.on.statements, MDL); 3339 } 3340 if ((on->data.on.evtypes & ON_RELEASE) && 3341 on->data.on.statements) { 3342 seenbit |= 32768; 3343 executable_statement_reference 3344 (&lease->on_star.on_release, 3345 on->data.on.statements, MDL); 3346 } 3347 executable_statement_dereference (&on, MDL); 3348 break; 3349 3350 case OPTION: 3351 case SUPERSEDE: 3352 noequal = 0; 3353 seenbit = 0; 3354 oc = (struct option_cache *)0; 3355 if (parse_option_decl (&oc, cfile)) { 3356 if (oc -> option -> universe != 3357 &agent_universe) { 3358 parse_warn (cfile, 3359 "agent option expected."); 3360 option_cache_dereference (&oc, MDL); 3361 break; 3362 } 3363 if (!lease -> agent_options && 3364 !(option_chain_head_allocate 3365 (&lease -> agent_options, MDL))) { 3366 log_error ("no memory to stash agent option"); 3367 break; 3368 } 3369 for (p = &lease -> agent_options -> first; 3370 *p; p = &((*p) -> cdr)) 3371 ; 3372 *p = cons (0, 0); 3373 option_cache_reference (((struct option_cache **) 3374 &((*p) -> car)), oc, MDL); 3375 option_cache_dereference (&oc, MDL); 3376 } 3377 break; 3378 3379 case TOKEN_SET: 3380 noequal = 0; 3381 3382 token = next_token (&val, (unsigned *)0, cfile); 3383 if (token != NAME && token != NUMBER_OR_NAME) { 3384 parse_warn (cfile, 3385 "%s can't be a variable name", 3386 val); 3387 badset: 3388 skip_to_semi (cfile); 3389 lease_dereference (&lease, MDL); 3390 return 0; 3391 } 3392 3393 seenbit = 0; 3394 special_set: 3395 if (lease -> scope) 3396 binding = find_binding (lease -> scope, val); 3397 else 3398 binding = (struct binding *)0; 3399 3400 if (!binding) { 3401 if (!lease -> scope) 3402 if (!(binding_scope_allocate 3403 (&lease -> scope, MDL))) 3404 log_fatal ("no memory for scope"); 3405 binding = dmalloc (sizeof *binding, MDL); 3406 if (!binding) 3407 log_fatal ("No memory for lease %s.", 3408 "binding"); 3409 memset (binding, 0, sizeof *binding); 3410 binding -> name = 3411 dmalloc (strlen (val) + 1, MDL); 3412 if (!binding -> name) 3413 log_fatal ("No memory for binding %s.", 3414 "name"); 3415 strcpy (binding -> name, val); 3416 newbinding = 1; 3417 } else { 3418 newbinding = 0; 3419 } 3420 3421 nv = NULL; 3422 if (!binding_value_allocate(&nv, MDL)) 3423 log_fatal("no memory for binding value."); 3424 3425 if (!noequal) { 3426 token = next_token (&val, (unsigned *)0, cfile); 3427 if (token != EQUAL) { 3428 parse_warn (cfile, 3429 "expecting '=' in set statement."); 3430 goto badset; 3431 } 3432 } 3433 3434 if (!parse_binding_value(cfile, nv)) { 3435 binding_value_dereference(&nv, MDL); 3436 lease_dereference(&lease, MDL); 3437 return 0; 3438 } 3439 3440 if (newbinding) { 3441 binding_value_reference(&binding->value, 3442 nv, MDL); 3443 binding->next = lease->scope->bindings; 3444 lease->scope->bindings = binding; 3445 } else { 3446 binding_value_dereference(&binding->value, MDL); 3447 binding_value_reference(&binding->value, 3448 nv, MDL); 3449 } 3450 3451 binding_value_dereference(&nv, MDL); 3452 parse_semi(cfile); 3453 break; 3454 3455 /* case NAME: */ 3456 default: 3457 if (!strcasecmp (val, "ddns-fwd-name")) { 3458 seenbit = 4096; 3459 noequal = 1; 3460 goto special_set; 3461 } else if (!strcasecmp (val, "ddns-rev-name")) { 3462 seenbit = 8192; 3463 noequal = 1; 3464 goto special_set; 3465 } else 3466 parse_warn(cfile, "Unexpected configuration " 3467 "directive."); 3468 skip_to_semi (cfile); 3469 seenbit = 0; 3470 lease_dereference (&lease, MDL); 3471 return 0; 3472 } 3473 3474 if (seenmask & seenbit) { 3475 parse_warn (cfile, 3476 "Too many %s parameters in lease %s\n", 3477 tbuf, piaddr (lease -> ip_addr)); 3478 } else 3479 seenmask |= seenbit; 3480 3481 } while (1); 3482 3483 /* If no binding state is specified, make one up. */ 3484 if (!(seenmask & 256)) { 3485 if (lease->ends > cur_time || 3486 lease->on_star.on_expiry || lease->on_star.on_release) 3487 lease->binding_state = FTS_ACTIVE; 3488 #if defined (FAILOVER_PROTOCOL) 3489 else if (lease->pool && lease->pool->failover_peer) 3490 lease->binding_state = FTS_EXPIRED; 3491 #endif 3492 else 3493 lease->binding_state = FTS_FREE; 3494 if (lease->binding_state == FTS_ACTIVE) { 3495 #if defined (FAILOVER_PROTOCOL) 3496 if (lease->pool && lease->pool->failover_peer) 3497 lease->next_binding_state = FTS_EXPIRED; 3498 else 3499 #endif 3500 lease->next_binding_state = FTS_FREE; 3501 } else 3502 lease->next_binding_state = lease->binding_state; 3503 3504 /* The most conservative rewind state implies no rewind. */ 3505 lease->rewind_binding_state = lease->binding_state; 3506 } 3507 3508 if (!(seenmask & 65536)) 3509 lease->tstp = lease->ends; 3510 3511 lease_reference (lp, lease, MDL); 3512 lease_dereference (&lease, MDL); 3513 return 1; 3514 } 3515 3516 /* Parse the right side of a 'binding value'. 3517 * 3518 * set foo = "bar"; is a string 3519 * set foo = false; is a boolean 3520 * set foo = %31; is a numeric value. 3521 */ 3522 static int 3523 parse_binding_value(struct parse *cfile, struct binding_value *value) 3524 { 3525 struct data_string *data; 3526 unsigned char *s; 3527 const char *val; 3528 unsigned buflen; 3529 int token; 3530 3531 if ((cfile == NULL) || (value == NULL)) 3532 log_fatal("Invalid arguments at %s:%d.", MDL); 3533 3534 token = peek_token(&val, NULL, cfile); 3535 if (token == STRING) { 3536 skip_token(&val, &buflen, cfile); 3537 3538 value->type = binding_data; 3539 value->value.data.len = buflen; 3540 3541 data = &value->value.data; 3542 3543 if (!buffer_allocate(&data->buffer, buflen + 1, MDL)) 3544 log_fatal ("No memory for binding."); 3545 3546 memcpy(data->buffer->data, val, buflen + 1); 3547 3548 data->data = data->buffer->data; 3549 data->terminated = 1; 3550 } else if (token == NUMBER_OR_NAME) { 3551 value->type = binding_data; 3552 3553 data = &value->value.data; 3554 s = parse_numeric_aggregate(cfile, NULL, &data->len, 3555 ':', 16, 8); 3556 if (s == NULL) { 3557 skip_to_semi(cfile); 3558 return 0; 3559 } 3560 3561 if (data->len) { 3562 if (!buffer_allocate(&data->buffer, data->len + 1, 3563 MDL)) 3564 log_fatal("No memory for binding."); 3565 3566 memcpy(data->buffer->data, s, data->len); 3567 data->data = data->buffer->data; 3568 3569 dfree (s, MDL); 3570 } 3571 } else if (token == PERCENT) { 3572 skip_token(&val, NULL, cfile); 3573 token = next_token(&val, NULL, cfile); 3574 if (token != NUMBER) { 3575 parse_warn(cfile, "expecting decimal number."); 3576 if (token != SEMI) 3577 skip_to_semi(cfile); 3578 return 0; 3579 } 3580 value->type = binding_numeric; 3581 value->value.intval = atol(val); 3582 } else if (token == NAME) { 3583 token = next_token(&val, NULL, cfile); 3584 value->type = binding_boolean; 3585 if (!strcasecmp(val, "true")) 3586 value->value.boolean = 1; 3587 else if (!strcasecmp(val, "false")) 3588 value->value.boolean = 0; 3589 else { 3590 parse_warn(cfile, "expecting true or false"); 3591 if (token != SEMI) 3592 skip_to_semi(cfile); 3593 return 0; 3594 } 3595 } else { 3596 parse_warn (cfile, "expecting a constant value."); 3597 if (token != SEMI) 3598 skip_to_semi (cfile); 3599 return 0; 3600 } 3601 3602 return 1; 3603 } 3604 3605 /* address-range-declaration :== ip-address ip-address SEMI 3606 | DYNAMIC_BOOTP ip-address ip-address SEMI */ 3607 3608 void parse_address_range (cfile, group, type, inpool, lpchain) 3609 struct parse *cfile; 3610 struct group *group; 3611 int type; 3612 struct pool *inpool; 3613 struct lease **lpchain; 3614 { 3615 struct iaddr low, high, net; 3616 unsigned char addr [4]; 3617 unsigned len = sizeof addr; 3618 enum dhcp_token token; 3619 const char *val; 3620 int dynamic = 0; 3621 struct subnet *subnet; 3622 struct shared_network *share; 3623 struct pool *pool; 3624 isc_result_t status; 3625 3626 if ((token = peek_token (&val, 3627 (unsigned *)0, cfile)) == DYNAMIC_BOOTP) { 3628 skip_token(&val, (unsigned *)0, cfile); 3629 dynamic = 1; 3630 } 3631 3632 /* Get the bottom address in the range... */ 3633 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) 3634 return; 3635 memcpy (low.iabuf, addr, len); 3636 low.len = len; 3637 3638 /* Only one address? */ 3639 token = peek_token (&val, (unsigned *)0, cfile); 3640 if (token == SEMI) 3641 high = low; 3642 else { 3643 /* Get the top address in the range... */ 3644 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) 3645 return; 3646 memcpy (high.iabuf, addr, len); 3647 high.len = len; 3648 } 3649 3650 token = next_token (&val, (unsigned *)0, cfile); 3651 if (token != SEMI) { 3652 parse_warn (cfile, "semicolon expected."); 3653 skip_to_semi (cfile); 3654 return; 3655 } 3656 3657 if (type == SUBNET_DECL) { 3658 subnet = group -> subnet; 3659 share = subnet -> shared_network; 3660 } else { 3661 share = group -> shared_network; 3662 for (subnet = share -> subnets; 3663 subnet; subnet = subnet -> next_sibling) { 3664 net = subnet_number (low, subnet -> netmask); 3665 if (addr_eq (net, subnet -> net)) 3666 break; 3667 } 3668 if (!subnet) { 3669 parse_warn (cfile, "address range not on network %s", 3670 group -> shared_network -> name); 3671 log_error ("Be sure to place pool statement after %s", 3672 "related subnet declarations."); 3673 return; 3674 } 3675 } 3676 3677 if (!inpool) { 3678 struct pool *last = (struct pool *)0; 3679 3680 /* If we're permitting dynamic bootp for this range, 3681 then look for a pool with an empty prohibit list and 3682 a permit list with one entry that permits all clients. */ 3683 for (pool = share -> pools; pool; pool = pool -> next) { 3684 if ((!dynamic && !pool -> permit_list && 3685 pool -> prohibit_list && 3686 !pool -> prohibit_list -> next && 3687 (pool -> prohibit_list -> type == 3688 permit_dynamic_bootp_clients)) || 3689 (dynamic && !pool -> prohibit_list && 3690 pool -> permit_list && 3691 !pool -> permit_list -> next && 3692 (pool -> permit_list -> type == 3693 permit_all_clients))) { 3694 break; 3695 } 3696 last = pool; 3697 } 3698 3699 /* If we didn't get a pool, make one. */ 3700 if (!pool) { 3701 struct permit *p; 3702 status = pool_allocate (&pool, MDL); 3703 if (status != ISC_R_SUCCESS) 3704 log_fatal ("no memory for ad-hoc pool: %s", 3705 isc_result_totext (status)); 3706 p = new_permit (MDL); 3707 if (!p) 3708 log_fatal ("no memory for ad-hoc permit."); 3709 3710 /* Dynamic pools permit all clients. Otherwise 3711 we prohibit BOOTP clients. */ 3712 if (dynamic) { 3713 p -> type = permit_all_clients; 3714 pool -> permit_list = p; 3715 } else { 3716 p -> type = permit_dynamic_bootp_clients; 3717 pool -> prohibit_list = p; 3718 } 3719 3720 if (share -> pools) 3721 pool_reference (&last -> next, pool, MDL); 3722 else 3723 pool_reference (&share -> pools, pool, MDL); 3724 shared_network_reference (&pool -> shared_network, 3725 share, MDL); 3726 if (!clone_group (&pool -> group, share -> group, MDL)) 3727 log_fatal ("no memory for anon pool group."); 3728 } else { 3729 pool = (struct pool *)0; 3730 if (last) 3731 pool_reference (&pool, last, MDL); 3732 else 3733 pool_reference (&pool, share -> pools, MDL); 3734 } 3735 } else { 3736 pool = (struct pool *)0; 3737 pool_reference (&pool, inpool, MDL); 3738 } 3739 3740 #if defined (FAILOVER_PROTOCOL) 3741 if (pool -> failover_peer && dynamic) { 3742 /* Doctor, do you think I'm overly sensitive 3743 about getting bug reports I can't fix? */ 3744 parse_warn (cfile, "dynamic-bootp flag is %s", 3745 "not permitted for address"); 3746 log_error ("range declarations where there is a failover"); 3747 log_error ("peer in scope. If you wish to declare an"); 3748 log_error ("address range from which dynamic bootp leases"); 3749 log_error ("can be allocated, please declare it within a"); 3750 log_error ("pool declaration that also contains the \"no"); 3751 log_error ("failover\" statement. The failover protocol"); 3752 log_error ("itself does not permit dynamic bootp - this"); 3753 log_error ("is not a limitation specific to the ISC DHCP"); 3754 log_error ("server. Please don't ask me to defend this"); 3755 log_error ("until you have read and really tried %s", 3756 "to understand"); 3757 log_error ("the failover protocol specification."); 3758 3759 /* We don't actually bomb at this point - instead, 3760 we let parse_lease_file notice the error and 3761 bomb at that point - it's easier. */ 3762 } 3763 #endif /* FAILOVER_PROTOCOL */ 3764 3765 /* Create the new address range... */ 3766 new_address_range (cfile, low, high, subnet, pool, lpchain); 3767 pool_dereference (&pool, MDL); 3768 } 3769 3770 #ifdef DHCPv6 3771 static void 3772 add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type, 3773 struct iaddr *lo_addr, int bits, int units, 3774 struct ipv6_pond *pond) { 3775 struct ipv6_pool *pool; 3776 struct in6_addr tmp_in6_addr; 3777 int num_pools; 3778 struct ipv6_pool **tmp; 3779 3780 /* 3781 * Create our pool. 3782 */ 3783 if (lo_addr->len != sizeof(tmp_in6_addr)) { 3784 log_fatal("Internal error: Attempt to add non-IPv6 address " 3785 "to IPv6 shared network."); 3786 } 3787 memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr)); 3788 pool = NULL; 3789 if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr, 3790 bits, units, MDL) != ISC_R_SUCCESS) { 3791 log_fatal("Out of memory"); 3792 } 3793 3794 /* 3795 * Add to our global IPv6 pool set. 3796 */ 3797 if (add_ipv6_pool(pool) != ISC_R_SUCCESS) { 3798 log_fatal ("Out of memory"); 3799 } 3800 3801 /* 3802 * Link the pool to its network. 3803 */ 3804 pool->subnet = NULL; 3805 subnet_reference(&pool->subnet, subnet, MDL); 3806 pool->shared_network = NULL; 3807 shared_network_reference(&pool->shared_network, 3808 subnet->shared_network, MDL); 3809 pool->ipv6_pond = NULL; 3810 ipv6_pond_reference(&pool->ipv6_pond, pond, MDL); 3811 3812 /* 3813 * Increase our array size for ipv6_pools in the pond 3814 */ 3815 if (pond->ipv6_pools == NULL) { 3816 num_pools = 0; 3817 } else { 3818 num_pools = 0; 3819 while (pond->ipv6_pools[num_pools] != NULL) { 3820 num_pools++; 3821 } 3822 } 3823 tmp = dmalloc(sizeof(struct ipv6_pool *) * (num_pools + 2), MDL); 3824 if (tmp == NULL) { 3825 log_fatal("Out of memory"); 3826 } 3827 if (num_pools > 0) { 3828 memcpy(tmp, pond->ipv6_pools, 3829 sizeof(struct ipv6_pool *) * num_pools); 3830 } 3831 if (pond->ipv6_pools != NULL) { 3832 dfree(pond->ipv6_pools, MDL); 3833 } 3834 pond->ipv6_pools = tmp; 3835 3836 /* 3837 * Record this pool in our array of pools for this shared network. 3838 */ 3839 ipv6_pool_reference(&pond->ipv6_pools[num_pools], pool, MDL); 3840 pond->ipv6_pools[num_pools+1] = NULL; 3841 } 3842 3843 /*! 3844 * 3845 * \brief Find or create a default pond 3846 * 3847 * Find or create an ipv6_pond on which to attach the ipv6_pools. We 3848 * check the shared network to see if there is a general purpose 3849 * entry - this will have an empty prohibit list and a permit list 3850 * with a single entry that permits all clients. If the shared 3851 * network doesn't have one of them create it and attach it to 3852 * the shared network and the return argument. 3853 * 3854 * This function is used when we have a range6 or prefix6 statement 3855 * inside a subnet6 statement but outside of a pool6 statement. 3856 * This routine constructs the missing ipv6_pond structure so 3857 * we always have 3858 * shared_network -> ipv6_pond -> ipv6_pool 3859 * 3860 * \param[in] group = a pointer to the group structure from which 3861 * we can find the subnet and shared netowrk 3862 * structures 3863 * \param[out] ret_pond = a pointer to space for the pointer to 3864 * the structure to return 3865 * 3866 * \return 3867 * void 3868 */ 3869 static void 3870 add_ipv6_pond_to_network(struct group *group, 3871 struct ipv6_pond **ret_pond) { 3872 3873 struct ipv6_pond *pond = NULL, *last = NULL; 3874 struct permit *p; 3875 isc_result_t status; 3876 struct shared_network *shared = group->subnet->shared_network; 3877 3878 for (pond = shared->ipv6_pond; pond; pond = pond->next) { 3879 if ((pond->group->statements == group->statements) && 3880 (pond->prohibit_list == NULL) && 3881 (pond->permit_list != NULL) && 3882 (pond->permit_list->next == NULL) && 3883 (pond->permit_list->type == permit_all_clients)) { 3884 ipv6_pond_reference(ret_pond, pond, MDL); 3885 return; 3886 } 3887 last = pond; 3888 } 3889 3890 /* no pond available, make one */ 3891 status = ipv6_pond_allocate(&pond, MDL); 3892 if (status != ISC_R_SUCCESS) 3893 log_fatal ("no memory for ad-hoc ipv6 pond: %s", 3894 isc_result_totext (status)); 3895 p = new_permit (MDL); 3896 if (p == NULL) 3897 log_fatal ("no memory for ad-hoc ipv6 permit."); 3898 3899 /* we permit all clients */ 3900 p->type = permit_all_clients; 3901 pond->permit_list = p; 3902 3903 /* and attach the pond to the return argument and the shared network */ 3904 ipv6_pond_reference(ret_pond, pond, MDL); 3905 3906 if (shared->ipv6_pond) 3907 ipv6_pond_reference(&last->next, pond, MDL); 3908 else 3909 ipv6_pond_reference(&shared->ipv6_pond, pond, MDL); 3910 3911 shared_network_reference(&pond->shared_network, shared, MDL); 3912 if (!clone_group (&pond->group, group, MDL)) 3913 log_fatal ("no memory for anon pool group."); 3914 3915 ipv6_pond_dereference(&pond, MDL); 3916 return; 3917 } 3918 3919 3920 /* address-range6-declaration :== ip-address6 ip-address6 SEMI 3921 | ip-address6 SLASH number SEMI 3922 | ip-address6 [SLASH number] TEMPORARY SEMI */ 3923 3924 void 3925 parse_address_range6(struct parse *cfile, 3926 struct group *group, 3927 struct ipv6_pond *inpond) { 3928 struct iaddr lo, hi; 3929 int bits; 3930 enum dhcp_token token; 3931 const char *val; 3932 struct iaddrcidrnetlist *nets, net; 3933 struct iaddrcidrnetlist *p; 3934 u_int16_t type = D6O_IA_NA; 3935 struct ipv6_pond *pond = NULL; 3936 3937 if (local_family != AF_INET6) { 3938 parse_warn(cfile, "range6 statement is only supported " 3939 "in DHCPv6 mode."); 3940 skip_to_semi(cfile); 3941 return; 3942 } 3943 3944 /* This is enforced by the caller, this is just a sanity check. */ 3945 if (group->subnet == NULL) 3946 log_fatal("Impossible condition at %s:%d.", MDL); 3947 3948 /* 3949 * Read starting address. 3950 */ 3951 if (!parse_ip6_addr(cfile, &lo)) { 3952 return; 3953 } 3954 3955 /* 3956 * zero out the net entry in case we use it 3957 */ 3958 memset(&net, 0, sizeof(net)); 3959 net.cidrnet.lo_addr = lo; 3960 3961 /* 3962 * See if we we're using range or CIDR notation or TEMPORARY 3963 */ 3964 token = peek_token(&val, NULL, cfile); 3965 if (token == SLASH) { 3966 /* 3967 * '/' means CIDR notation, so read the bits we want. 3968 */ 3969 skip_token(NULL, NULL, cfile); 3970 token = next_token(&val, NULL, cfile); 3971 if (token != NUMBER) { 3972 parse_warn(cfile, "expecting number"); 3973 skip_to_semi(cfile); 3974 return; 3975 } 3976 net.cidrnet.bits = atoi(val); 3977 bits = net.cidrnet.bits; 3978 if ((bits < 0) || (bits > 128)) { 3979 parse_warn(cfile, "networks have 0 to 128 bits"); 3980 skip_to_semi(cfile); 3981 return; 3982 } 3983 3984 if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, bits)) { 3985 parse_warn(cfile, "network mask too short"); 3986 skip_to_semi(cfile); 3987 return; 3988 } 3989 3990 /* 3991 * can be temporary (RFC 4941 like) 3992 */ 3993 token = peek_token(&val, NULL, cfile); 3994 if (token == TEMPORARY) { 3995 if (bits < 64) 3996 parse_warn(cfile, "temporary mask too short"); 3997 if (bits == 128) 3998 parse_warn(cfile, "temporary singleton?"); 3999 skip_token(NULL, NULL, cfile); 4000 type = D6O_IA_TA; 4001 } 4002 4003 nets = &net; 4004 4005 } else if (token == TEMPORARY) { 4006 /* 4007 * temporary (RFC 4941) 4008 */ 4009 type = D6O_IA_TA; 4010 skip_token(NULL, NULL, cfile); 4011 net.cidrnet.bits = 64; 4012 if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, 4013 net.cidrnet.bits)) { 4014 parse_warn(cfile, "network mask too short"); 4015 skip_to_semi(cfile); 4016 return; 4017 } 4018 4019 nets = &net; 4020 4021 } else { 4022 /* 4023 * No '/', so we are looking for the end address of 4024 * the IPv6 pool. 4025 */ 4026 if (!parse_ip6_addr(cfile, &hi)) { 4027 return; 4028 } 4029 4030 /* 4031 * Convert our range to a set of CIDR networks. 4032 */ 4033 nets = NULL; 4034 if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) { 4035 log_fatal("Error converting range to CIDR networks"); 4036 } 4037 4038 } 4039 4040 /* 4041 * See if we have a pond for this set of pools. 4042 * If the caller supplied one we use it, otherwise 4043 * check the shared network 4044 */ 4045 4046 if (inpond != NULL) { 4047 ipv6_pond_reference(&pond, inpond, MDL); 4048 } else { 4049 add_ipv6_pond_to_network(group, &pond); 4050 } 4051 4052 /* Now that we have a pond add the nets we have parsed */ 4053 for (p=nets; p != NULL; p=p->next) { 4054 add_ipv6_pool_to_subnet(group->subnet, type, 4055 &p->cidrnet.lo_addr, 4056 p->cidrnet.bits, 128, pond); 4057 } 4058 4059 /* if we allocated a list free it now */ 4060 if (nets != &net) 4061 free_iaddrcidrnetlist(&nets); 4062 4063 ipv6_pond_dereference(&pond, MDL); 4064 4065 token = next_token(NULL, NULL, cfile); 4066 if (token != SEMI) { 4067 parse_warn(cfile, "semicolon expected."); 4068 skip_to_semi(cfile); 4069 return; 4070 } 4071 } 4072 4073 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */ 4074 4075 void 4076 parse_prefix6(struct parse *cfile, 4077 struct group *group, 4078 struct ipv6_pond *inpond) { 4079 struct iaddr lo, hi; 4080 int bits; 4081 enum dhcp_token token; 4082 const char *val; 4083 struct iaddrcidrnetlist *nets; 4084 struct iaddrcidrnetlist *p; 4085 struct ipv6_pond *pond = NULL; 4086 4087 if (local_family != AF_INET6) { 4088 parse_warn(cfile, "prefix6 statement is only supported " 4089 "in DHCPv6 mode."); 4090 skip_to_semi(cfile); 4091 return; 4092 } 4093 4094 /* This is enforced by the caller, so it's just a sanity check. */ 4095 if (group->subnet == NULL) 4096 log_fatal("Impossible condition at %s:%d.", MDL); 4097 4098 /* 4099 * Read starting and ending address. 4100 */ 4101 if (!parse_ip6_addr(cfile, &lo)) { 4102 return; 4103 } 4104 if (!parse_ip6_addr(cfile, &hi)) { 4105 return; 4106 } 4107 4108 /* 4109 * Next is '/' number ';'. 4110 */ 4111 token = next_token(NULL, NULL, cfile); 4112 if (token != SLASH) { 4113 parse_warn(cfile, "expecting '/'"); 4114 if (token != SEMI) 4115 skip_to_semi(cfile); 4116 return; 4117 } 4118 token = next_token(&val, NULL, cfile); 4119 if (token != NUMBER) { 4120 parse_warn(cfile, "expecting number"); 4121 if (token != SEMI) 4122 skip_to_semi(cfile); 4123 return; 4124 } 4125 bits = atoi(val); 4126 if ((bits <= 0) || (bits >= 128)) { 4127 parse_warn(cfile, "networks have 0 to 128 bits (exclusive)"); 4128 return; 4129 } 4130 if (!is_cidr_mask_valid(&lo, bits) || 4131 !is_cidr_mask_valid(&hi, bits)) { 4132 parse_warn(cfile, "network mask too short"); 4133 return; 4134 } 4135 token = next_token(NULL, NULL, cfile); 4136 if (token != SEMI) { 4137 parse_warn(cfile, "semicolon expected."); 4138 skip_to_semi(cfile); 4139 return; 4140 } 4141 4142 /* 4143 * Convert our range to a set of CIDR networks. 4144 */ 4145 nets = NULL; 4146 if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) { 4147 log_fatal("Error converting prefix to CIDR"); 4148 } 4149 4150 /* 4151 * See if we have a pond for this set of pools. 4152 * If the caller supplied one we use it, otherwise 4153 * check the shared network 4154 */ 4155 4156 if (inpond != NULL) { 4157 ipv6_pond_reference(&pond, inpond, MDL); 4158 } else { 4159 add_ipv6_pond_to_network(group, &pond); 4160 } 4161 4162 for (p = nets; p != NULL; p = p->next) { 4163 /* Normalize and check. */ 4164 if (p->cidrnet.bits == 128) { 4165 p->cidrnet.bits = bits; 4166 } 4167 if (p->cidrnet.bits > bits) { 4168 parse_warn(cfile, "impossible mask length"); 4169 continue; 4170 } 4171 add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD, 4172 &p->cidrnet.lo_addr, 4173 p->cidrnet.bits, bits, pond); 4174 } 4175 4176 free_iaddrcidrnetlist(&nets); 4177 } 4178 4179 /* fixed-prefix6 :== ip6-address SLASH number SEMI */ 4180 4181 void 4182 parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) { 4183 struct iaddrcidrnetlist *ia, **h; 4184 enum dhcp_token token; 4185 const char *val; 4186 4187 /* 4188 * Get the head of the fixed-prefix list. 4189 */ 4190 h = &host_decl->fixed_prefix; 4191 4192 /* 4193 * Walk to the end. 4194 */ 4195 while (*h != NULL) { 4196 h = &((*h)->next); 4197 } 4198 4199 /* 4200 * Allocate a new iaddrcidrnetlist structure. 4201 */ 4202 ia = dmalloc(sizeof(*ia), MDL); 4203 if (!ia) { 4204 log_fatal("Out of memory"); 4205 } 4206 4207 /* 4208 * Parse it. 4209 */ 4210 if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) { 4211 dfree(ia, MDL); 4212 return; 4213 } 4214 token = next_token(NULL, NULL, cfile); 4215 if (token != SLASH) { 4216 dfree(ia, MDL); 4217 parse_warn(cfile, "expecting '/'"); 4218 if (token != SEMI) 4219 skip_to_semi(cfile); 4220 return; 4221 } 4222 token = next_token(&val, NULL, cfile); 4223 if (token != NUMBER) { 4224 dfree(ia, MDL); 4225 parse_warn(cfile, "expecting number"); 4226 if (token != SEMI) 4227 skip_to_semi(cfile); 4228 return; 4229 } 4230 token = next_token(NULL, NULL, cfile); 4231 if (token != SEMI) { 4232 dfree(ia, MDL); 4233 parse_warn(cfile, "semicolon expected."); 4234 skip_to_semi(cfile); 4235 return; 4236 } 4237 4238 /* 4239 * Fill it. 4240 */ 4241 ia->cidrnet.bits = atoi(val); 4242 if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) { 4243 dfree(ia, MDL); 4244 parse_warn(cfile, "networks have 0 to 128 bits"); 4245 return; 4246 } 4247 if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) { 4248 dfree(ia, MDL); 4249 parse_warn(cfile, "network mask too short"); 4250 return; 4251 } 4252 4253 /* 4254 * Store it. 4255 */ 4256 *h = ia; 4257 return; 4258 } 4259 4260 /*! 4261 * 4262 * \brief Parse a pool6 statement 4263 * 4264 * Pool statements are used to group declarations and permit & deny information 4265 * with a specific address range. They must be declared within a shared network 4266 * or subnet and there may be multiple pools withing a shared network or subnet. 4267 * Each pool may have a different set of permit or deny options. 4268 * 4269 * \param[in] cfile = the configuration file being parsed 4270 * \param[in] group = the group structure for this pool 4271 * \param[in] type = the type of the enclosing statement. This must be 4272 * SUBNET_DECL for this function. 4273 * 4274 * \return 4275 * void - This function either parses the statement and updates the structures 4276 * or it generates an error message and possible halts the program if 4277 * it encounters a problem. 4278 */ 4279 void parse_pool6_statement (cfile, group, type) 4280 struct parse *cfile; 4281 struct group *group; 4282 int type; 4283 { 4284 enum dhcp_token token; 4285 const char *val; 4286 int done = 0; 4287 struct ipv6_pond *pond, **p; 4288 int declaration = 0; 4289 isc_result_t status; 4290 4291 pond = NULL; 4292 status = ipv6_pond_allocate(&pond, MDL); 4293 if (status != ISC_R_SUCCESS) 4294 log_fatal("no memory for pool6: %s", 4295 isc_result_totext (status)); 4296 4297 if (type == SUBNET_DECL) 4298 shared_network_reference(&pond->shared_network, 4299 group->subnet->shared_network, 4300 MDL); 4301 else { 4302 parse_warn(cfile, "Dynamic pool6s are only valid inside " 4303 "subnet statements."); 4304 skip_to_semi(cfile); 4305 return; 4306 } 4307 4308 if (clone_group(&pond->group, group, MDL) == 0) 4309 log_fatal("can't clone pool6 group."); 4310 4311 if (parse_lbrace(cfile) == 0) { 4312 ipv6_pond_dereference(&pond, MDL); 4313 return; 4314 } 4315 4316 do { 4317 token = peek_token(&val, NULL, cfile); 4318 switch (token) { 4319 case RANGE6: 4320 skip_token(NULL, NULL, cfile); 4321 parse_address_range6(cfile, group, pond); 4322 break; 4323 4324 case PREFIX6: 4325 skip_token(NULL, NULL, cfile); 4326 parse_prefix6(cfile, group, pond); 4327 break; 4328 4329 case ALLOW: 4330 skip_token(NULL, NULL, cfile); 4331 get_permit(cfile, &pond->permit_list, 1, 4332 &pond->valid_from, &pond->valid_until); 4333 break; 4334 4335 case DENY: 4336 skip_token(NULL, NULL, cfile); 4337 get_permit(cfile, &pond->prohibit_list, 0, 4338 &pond->valid_from, &pond->valid_until); 4339 break; 4340 4341 case RBRACE: 4342 skip_token(&val, NULL, cfile); 4343 done = 1; 4344 break; 4345 4346 case END_OF_FILE: 4347 /* 4348 * We can get to END_OF_FILE if, for instance, 4349 * the parse_statement() reads all available tokens 4350 * and leaves us at the end. 4351 */ 4352 parse_warn(cfile, "unexpected end of file"); 4353 goto cleanup; 4354 4355 default: 4356 declaration = parse_statement(cfile, pond->group, 4357 POOL_DECL, NULL, 4358 declaration); 4359 break; 4360 } 4361 } while (!done); 4362 4363 /* 4364 * A possible optimization is to see if this pond can be merged into 4365 * an already existing pond. But I'll pass on that for now as we need 4366 * to repoint the leases to the other pond which is annoying. SAR 4367 */ 4368 4369 /* 4370 * Add this pond to the list (will need updating if we add the 4371 * optimization). 4372 */ 4373 4374 p = &pond->shared_network->ipv6_pond; 4375 for (; *p; p = &((*p)->next)) 4376 ; 4377 ipv6_pond_reference(p, pond, MDL); 4378 4379 /* Don't allow a pool6 declaration with no addresses or 4380 prefixes, since it is probably a configuration error. */ 4381 if (pond->ipv6_pools == NULL) { 4382 parse_warn (cfile, "Pool6 declaration with no %s.", 4383 "address range6 or prefix6"); 4384 log_error ("Pool6 declarations must always contain at least"); 4385 log_error ("one range6 or prefix6 statement."); 4386 } 4387 4388 cleanup: 4389 ipv6_pond_dereference(&pond, MDL); 4390 } 4391 4392 4393 4394 #endif /* DHCPv6 */ 4395 4396 /* allow-deny-keyword :== BOOTP 4397 | BOOTING 4398 | DYNAMIC_BOOTP 4399 | UNKNOWN_CLIENTS */ 4400 4401 int parse_allow_deny (oc, cfile, flag) 4402 struct option_cache **oc; 4403 struct parse *cfile; 4404 int flag; 4405 { 4406 enum dhcp_token token; 4407 const char *val; 4408 unsigned char rf = flag; 4409 unsigned code; 4410 struct option *option = NULL; 4411 struct expression *data = (struct expression *)0; 4412 int status; 4413 4414 if (!make_const_data (&data, &rf, 1, 0, 1, MDL)) 4415 return 0; 4416 4417 token = next_token (&val, (unsigned *)0, cfile); 4418 switch (token) { 4419 case TOKEN_BOOTP: 4420 code = SV_ALLOW_BOOTP; 4421 break; 4422 4423 case BOOTING: 4424 code = SV_ALLOW_BOOTING; 4425 break; 4426 4427 case DYNAMIC_BOOTP: 4428 code = SV_DYNAMIC_BOOTP; 4429 break; 4430 4431 case UNKNOWN_CLIENTS: 4432 code = SV_BOOT_UNKNOWN_CLIENTS; 4433 break; 4434 4435 case DUPLICATES: 4436 code = SV_DUPLICATES; 4437 break; 4438 4439 case DECLINES: 4440 code= SV_DECLINES; 4441 break; 4442 4443 case CLIENT_UPDATES: 4444 code = SV_CLIENT_UPDATES; 4445 break; 4446 4447 case LEASEQUERY: 4448 code = SV_LEASEQUERY; 4449 break; 4450 4451 default: 4452 parse_warn (cfile, "expecting allow/deny key"); 4453 skip_to_semi (cfile); 4454 return 0; 4455 } 4456 /* Reference on option is passed to option cache. */ 4457 if (!option_code_hash_lookup(&option, server_universe.code_hash, 4458 &code, 0, MDL)) 4459 log_fatal("Unable to find server option %u (%s:%d).", 4460 code, MDL); 4461 status = option_cache(oc, NULL, data, option, MDL); 4462 expression_dereference (&data, MDL); 4463 parse_semi (cfile); 4464 return status; 4465 } 4466 4467 void 4468 parse_ia_na_declaration(struct parse *cfile) { 4469 #if !defined(DHCPv6) 4470 parse_warn(cfile, "No DHCPv6 support."); 4471 skip_to_semi(cfile); 4472 #else /* defined(DHCPv6) */ 4473 enum dhcp_token token; 4474 struct ia_xx *ia; 4475 const char *val; 4476 struct ia_xx *old_ia; 4477 unsigned int len; 4478 u_int32_t iaid; 4479 struct iaddr iaddr; 4480 binding_state_t state; 4481 u_int32_t prefer; 4482 u_int32_t valid; 4483 TIME end_time; 4484 struct iasubopt *iaaddr; 4485 struct ipv6_pool *pool; 4486 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 4487 isc_boolean_t newbinding; 4488 struct binding_scope *scope = NULL; 4489 struct binding *bnd; 4490 struct binding_value *nv = NULL; 4491 struct executable_statement *on_star[2] = {NULL, NULL}; 4492 int lose, i; 4493 4494 if (local_family != AF_INET6) { 4495 parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode."); 4496 skip_to_semi(cfile); 4497 return; 4498 } 4499 4500 token = next_token(&val, &len, cfile); 4501 if (token != STRING) { 4502 parse_warn(cfile, "corrupt lease file; " 4503 "expecting an iaid+ia_na string"); 4504 skip_to_semi(cfile); 4505 return; 4506 } 4507 if (len < 5) { 4508 parse_warn(cfile, "corrupt lease file; " 4509 "iaid+ia_na string too short"); 4510 skip_to_semi(cfile); 4511 return; 4512 } 4513 4514 memcpy(&iaid, val, 4); 4515 ia = NULL; 4516 if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) { 4517 log_fatal("Out of memory."); 4518 } 4519 ia->ia_type = D6O_IA_NA; 4520 4521 token = next_token(&val, NULL, cfile); 4522 if (token != LBRACE) { 4523 parse_warn(cfile, "corrupt lease file; expecting left brace"); 4524 skip_to_semi(cfile); 4525 return; 4526 } 4527 4528 for (;;) { 4529 token = next_token(&val, NULL, cfile); 4530 if (token == RBRACE) break; 4531 4532 if (token == CLTT) { 4533 ia->cltt = parse_date (cfile); 4534 continue; 4535 } 4536 4537 if (token != IAADDR) { 4538 parse_warn(cfile, "corrupt lease file; " 4539 "expecting IAADDR or right brace"); 4540 skip_to_semi(cfile); 4541 return; 4542 } 4543 4544 if (!parse_ip6_addr(cfile, &iaddr)) { 4545 parse_warn(cfile, "corrupt lease file; " 4546 "expecting IPv6 address"); 4547 skip_to_semi(cfile); 4548 return; 4549 } 4550 4551 token = next_token(&val, NULL, cfile); 4552 if (token != LBRACE) { 4553 parse_warn(cfile, "corrupt lease file; " 4554 "expecting left brace"); 4555 skip_to_semi(cfile); 4556 return; 4557 } 4558 4559 state = FTS_LAST+1; 4560 prefer = valid = 0; 4561 end_time = -1; 4562 for (;;) { 4563 token = next_token(&val, NULL, cfile); 4564 if (token == RBRACE) break; 4565 4566 switch(token) { 4567 /* Lease binding state. */ 4568 case BINDING: 4569 token = next_token(&val, NULL, cfile); 4570 if (token != STATE) { 4571 parse_warn(cfile, "corrupt lease file; " 4572 "expecting state"); 4573 skip_to_semi(cfile); 4574 return; 4575 } 4576 token = next_token(&val, NULL, cfile); 4577 switch (token) { 4578 case TOKEN_ABANDONED: 4579 state = FTS_ABANDONED; 4580 break; 4581 case TOKEN_FREE: 4582 state = FTS_FREE; 4583 break; 4584 case TOKEN_ACTIVE: 4585 state = FTS_ACTIVE; 4586 break; 4587 case TOKEN_EXPIRED: 4588 state = FTS_EXPIRED; 4589 break; 4590 case TOKEN_RELEASED: 4591 state = FTS_RELEASED; 4592 break; 4593 default: 4594 parse_warn(cfile, 4595 "corrupt lease " 4596 "file; " 4597 "expecting a " 4598 "binding state."); 4599 skip_to_semi(cfile); 4600 return; 4601 } 4602 4603 token = next_token(&val, NULL, cfile); 4604 if (token != SEMI) { 4605 parse_warn(cfile, "corrupt lease file; " 4606 "expecting " 4607 "semicolon."); 4608 } 4609 break; 4610 4611 /* Lease preferred lifetime. */ 4612 case PREFERRED_LIFE: 4613 token = next_token(&val, NULL, cfile); 4614 if (token != NUMBER) { 4615 parse_warn(cfile, "%s is not a valid " 4616 "preferred time", 4617 val); 4618 skip_to_semi(cfile); 4619 continue; 4620 } 4621 prefer = atoi (val); 4622 4623 /* 4624 * Currently we peek for the semi-colon to 4625 * allow processing of older lease files that 4626 * don't have the semi-colon. Eventually we 4627 * should remove the peeking code. 4628 */ 4629 token = peek_token(&val, NULL, cfile); 4630 if (token == SEMI) { 4631 skip_token(&val, NULL, cfile); 4632 } else { 4633 parse_warn(cfile, 4634 "corrupt lease file; " 4635 "expecting semicolon."); 4636 } 4637 break; 4638 4639 /* Lease valid lifetime. */ 4640 case MAX_LIFE: 4641 token = next_token(&val, NULL, cfile); 4642 if (token != NUMBER) { 4643 parse_warn(cfile, "%s is not a valid " 4644 "max time", 4645 val); 4646 skip_to_semi(cfile); 4647 continue; 4648 } 4649 valid = atoi (val); 4650 4651 /* 4652 * Currently we peek for the semi-colon to 4653 * allow processing of older lease files that 4654 * don't have the semi-colon. Eventually we 4655 * should remove the peeking code. 4656 */ 4657 token = peek_token(&val, NULL, cfile); 4658 if (token == SEMI) { 4659 skip_token(&val, NULL, cfile); 4660 } else { 4661 parse_warn(cfile, 4662 "corrupt lease file; " 4663 "expecting semicolon."); 4664 } 4665 break; 4666 4667 /* Lease expiration time. */ 4668 case ENDS: 4669 end_time = parse_date(cfile); 4670 break; 4671 4672 /* Lease binding scopes. */ 4673 case TOKEN_SET: 4674 token = next_token(&val, NULL, cfile); 4675 if ((token != NAME) && 4676 (token != NUMBER_OR_NAME)) { 4677 parse_warn(cfile, "%s is not a valid " 4678 "variable name", 4679 val); 4680 skip_to_semi(cfile); 4681 continue; 4682 } 4683 4684 if (scope != NULL) 4685 bnd = find_binding(scope, val); 4686 else { 4687 if (!binding_scope_allocate(&scope, 4688 MDL)) { 4689 log_fatal("Out of memory for " 4690 "lease binding " 4691 "scope."); 4692 } 4693 4694 bnd = NULL; 4695 } 4696 4697 if (bnd == NULL) { 4698 bnd = dmalloc(sizeof(*bnd), 4699 MDL); 4700 if (bnd == NULL) { 4701 log_fatal("No memory for " 4702 "lease binding."); 4703 } 4704 4705 bnd->name = dmalloc(strlen(val) + 1, 4706 MDL); 4707 if (bnd->name == NULL) { 4708 log_fatal("No memory for " 4709 "binding name."); 4710 } 4711 strcpy(bnd->name, val); 4712 4713 newbinding = ISC_TRUE; 4714 } else { 4715 newbinding = ISC_FALSE; 4716 } 4717 4718 if (!binding_value_allocate(&nv, MDL)) { 4719 log_fatal("no memory for binding " 4720 "value."); 4721 } 4722 4723 token = next_token(NULL, NULL, cfile); 4724 if (token != EQUAL) { 4725 parse_warn(cfile, "expecting '=' in " 4726 "set statement."); 4727 goto binding_err; 4728 } 4729 4730 if (!parse_binding_value(cfile, nv)) { 4731 binding_err: 4732 binding_value_dereference(&nv, MDL); 4733 binding_scope_dereference(&scope, MDL); 4734 return; 4735 } 4736 4737 if (newbinding) { 4738 binding_value_reference(&bnd->value, 4739 nv, MDL); 4740 bnd->next = scope->bindings; 4741 scope->bindings = bnd; 4742 } else { 4743 binding_value_dereference(&bnd->value, 4744 MDL); 4745 binding_value_reference(&bnd->value, 4746 nv, MDL); 4747 } 4748 4749 binding_value_dereference(&nv, MDL); 4750 parse_semi(cfile); 4751 break; 4752 4753 case ON: 4754 lose = 0; 4755 /* 4756 * Depending on the user config we may 4757 * have one or two on statements. We 4758 * need to save information about both 4759 * of them until we allocate the 4760 * iasubopt to hold them. 4761 */ 4762 if (on_star[0] == NULL) { 4763 if (!parse_on_statement (&on_star[0], 4764 cfile, 4765 &lose)) { 4766 parse_warn(cfile, 4767 "corrupt lease " 4768 "file; bad ON " 4769 "statement"); 4770 skip_to_rbrace (cfile, 1); 4771 return; 4772 } 4773 } else { 4774 if (!parse_on_statement (&on_star[1], 4775 cfile, 4776 &lose)) { 4777 parse_warn(cfile, 4778 "corrupt lease " 4779 "file; bad ON " 4780 "statement"); 4781 skip_to_rbrace (cfile, 1); 4782 return; 4783 } 4784 } 4785 4786 break; 4787 4788 default: 4789 parse_warn(cfile, "corrupt lease file; " 4790 "expecting ia_na contents, " 4791 "got '%s'", val); 4792 skip_to_semi(cfile); 4793 continue; 4794 } 4795 } 4796 4797 if (state == FTS_LAST+1) { 4798 parse_warn(cfile, "corrupt lease file; " 4799 "missing state in iaaddr"); 4800 return; 4801 } 4802 if (end_time == -1) { 4803 parse_warn(cfile, "corrupt lease file; " 4804 "missing end time in iaaddr"); 4805 return; 4806 } 4807 4808 iaaddr = NULL; 4809 if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { 4810 log_fatal("Out of memory."); 4811 } 4812 memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr)); 4813 iaaddr->plen = 0; 4814 iaaddr->state = state; 4815 iaaddr->prefer = prefer; 4816 iaaddr->valid = valid; 4817 if (iaaddr->state == FTS_RELEASED) 4818 iaaddr->hard_lifetime_end_time = end_time; 4819 4820 if (scope != NULL) { 4821 binding_scope_reference(&iaaddr->scope, scope, MDL); 4822 binding_scope_dereference(&scope, MDL); 4823 } 4824 4825 /* 4826 * Check on both on statements. Because of how we write the 4827 * lease file we know which is which if we have two but it's 4828 * easier to write the code to be independent. We do assume 4829 * that the statements won't overlap. 4830 */ 4831 for (i = 0; 4832 (i < 2) && on_star[i] != NULL ; 4833 i++) { 4834 if ((on_star[i]->data.on.evtypes & ON_EXPIRY) && 4835 on_star[i]->data.on.statements) { 4836 executable_statement_reference 4837 (&iaaddr->on_star.on_expiry, 4838 on_star[i]->data.on.statements, MDL); 4839 } 4840 if ((on_star[i]->data.on.evtypes & ON_RELEASE) && 4841 on_star[i]->data.on.statements) { 4842 executable_statement_reference 4843 (&iaaddr->on_star.on_release, 4844 on_star[i]->data.on.statements, MDL); 4845 } 4846 executable_statement_dereference (&on_star[i], MDL); 4847 } 4848 4849 /* find the pool this address is in */ 4850 pool = NULL; 4851 if (find_ipv6_pool(&pool, D6O_IA_NA, 4852 &iaaddr->addr) != ISC_R_SUCCESS) { 4853 inet_ntop(AF_INET6, &iaaddr->addr, 4854 addr_buf, sizeof(addr_buf)); 4855 parse_warn(cfile, "no pool found for address %s", 4856 addr_buf); 4857 return; 4858 } 4859 4860 /* remove old information */ 4861 if (cleanup_lease6(ia_na_active, pool, 4862 iaaddr, ia) != ISC_R_SUCCESS) { 4863 inet_ntop(AF_INET6, &iaaddr->addr, 4864 addr_buf, sizeof(addr_buf)); 4865 parse_warn(cfile, "duplicate na lease for address %s", 4866 addr_buf); 4867 } 4868 4869 /* 4870 * if we like the lease we add it to our various structues 4871 * otherwise we leave it and it will get cleaned when we 4872 * do the iasubopt_dereference. 4873 */ 4874 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) { 4875 ia_add_iasubopt(ia, iaaddr, MDL); 4876 ia_reference(&iaaddr->ia, ia, MDL); 4877 add_lease6(pool, iaaddr, end_time); 4878 } 4879 4880 iasubopt_dereference(&iaaddr, MDL); 4881 ipv6_pool_dereference(&pool, MDL); 4882 } 4883 4884 /* 4885 * If we have an existing record for this IA_NA, remove it. 4886 */ 4887 old_ia = NULL; 4888 if (ia_hash_lookup(&old_ia, ia_na_active, 4889 (unsigned char *)ia->iaid_duid.data, 4890 ia->iaid_duid.len, MDL)) { 4891 ia_hash_delete(ia_na_active, 4892 (unsigned char *)ia->iaid_duid.data, 4893 ia->iaid_duid.len, MDL); 4894 ia_dereference(&old_ia, MDL); 4895 } 4896 4897 /* 4898 * If we have addresses, add this, otherwise don't bother. 4899 */ 4900 if (ia->num_iasubopt > 0) { 4901 ia_hash_add(ia_na_active, 4902 (unsigned char *)ia->iaid_duid.data, 4903 ia->iaid_duid.len, ia, MDL); 4904 } 4905 ia_dereference(&ia, MDL); 4906 #endif /* defined(DHCPv6) */ 4907 } 4908 4909 void 4910 parse_ia_ta_declaration(struct parse *cfile) { 4911 #if !defined(DHCPv6) 4912 parse_warn(cfile, "No DHCPv6 support."); 4913 skip_to_semi(cfile); 4914 #else /* defined(DHCPv6) */ 4915 enum dhcp_token token; 4916 struct ia_xx *ia; 4917 const char *val; 4918 struct ia_xx *old_ia; 4919 unsigned int len; 4920 u_int32_t iaid; 4921 struct iaddr iaddr; 4922 binding_state_t state; 4923 u_int32_t prefer; 4924 u_int32_t valid; 4925 TIME end_time; 4926 struct iasubopt *iaaddr; 4927 struct ipv6_pool *pool; 4928 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 4929 isc_boolean_t newbinding; 4930 struct binding_scope *scope = NULL; 4931 struct binding *bnd; 4932 struct binding_value *nv = NULL; 4933 struct executable_statement *on_star[2] = {NULL, NULL}; 4934 int lose, i; 4935 4936 if (local_family != AF_INET6) { 4937 parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode."); 4938 skip_to_semi(cfile); 4939 return; 4940 } 4941 4942 token = next_token(&val, &len, cfile); 4943 if (token != STRING) { 4944 parse_warn(cfile, "corrupt lease file; " 4945 "expecting an iaid+ia_ta string"); 4946 skip_to_semi(cfile); 4947 return; 4948 } 4949 if (len < 5) { 4950 parse_warn(cfile, "corrupt lease file; " 4951 "iaid+ia_ta string too short"); 4952 skip_to_semi(cfile); 4953 return; 4954 } 4955 4956 memcpy(&iaid, val, 4); 4957 ia = NULL; 4958 if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) { 4959 log_fatal("Out of memory."); 4960 } 4961 ia->ia_type = D6O_IA_TA; 4962 4963 token = next_token(&val, NULL, cfile); 4964 if (token != LBRACE) { 4965 parse_warn(cfile, "corrupt lease file; expecting left brace"); 4966 skip_to_semi(cfile); 4967 return; 4968 } 4969 4970 for (;;) { 4971 token = next_token(&val, NULL, cfile); 4972 if (token == RBRACE) break; 4973 4974 if (token == CLTT) { 4975 ia->cltt = parse_date (cfile); 4976 continue; 4977 } 4978 4979 if (token != IAADDR) { 4980 parse_warn(cfile, "corrupt lease file; " 4981 "expecting IAADDR or right brace"); 4982 skip_to_semi(cfile); 4983 return; 4984 } 4985 4986 if (!parse_ip6_addr(cfile, &iaddr)) { 4987 parse_warn(cfile, "corrupt lease file; " 4988 "expecting IPv6 address"); 4989 skip_to_semi(cfile); 4990 return; 4991 } 4992 4993 token = next_token(&val, NULL, cfile); 4994 if (token != LBRACE) { 4995 parse_warn(cfile, "corrupt lease file; " 4996 "expecting left brace"); 4997 skip_to_semi(cfile); 4998 return; 4999 } 5000 5001 state = FTS_LAST+1; 5002 prefer = valid = 0; 5003 end_time = -1; 5004 for (;;) { 5005 token = next_token(&val, NULL, cfile); 5006 if (token == RBRACE) break; 5007 5008 switch(token) { 5009 /* Lease binding state. */ 5010 case BINDING: 5011 token = next_token(&val, NULL, cfile); 5012 if (token != STATE) { 5013 parse_warn(cfile, "corrupt lease file; " 5014 "expecting state"); 5015 skip_to_semi(cfile); 5016 return; 5017 } 5018 token = next_token(&val, NULL, cfile); 5019 switch (token) { 5020 case TOKEN_ABANDONED: 5021 state = FTS_ABANDONED; 5022 break; 5023 case TOKEN_FREE: 5024 state = FTS_FREE; 5025 break; 5026 case TOKEN_ACTIVE: 5027 state = FTS_ACTIVE; 5028 break; 5029 case TOKEN_EXPIRED: 5030 state = FTS_EXPIRED; 5031 break; 5032 case TOKEN_RELEASED: 5033 state = FTS_RELEASED; 5034 break; 5035 default: 5036 parse_warn(cfile, 5037 "corrupt lease " 5038 "file; " 5039 "expecting a " 5040 "binding state."); 5041 skip_to_semi(cfile); 5042 return; 5043 } 5044 5045 token = next_token(&val, NULL, cfile); 5046 if (token != SEMI) { 5047 parse_warn(cfile, "corrupt lease file; " 5048 "expecting " 5049 "semicolon."); 5050 } 5051 break; 5052 5053 /* Lease preferred lifetime. */ 5054 case PREFERRED_LIFE: 5055 token = next_token(&val, NULL, cfile); 5056 if (token != NUMBER) { 5057 parse_warn(cfile, "%s is not a valid " 5058 "preferred time", 5059 val); 5060 skip_to_semi(cfile); 5061 continue; 5062 } 5063 prefer = atoi (val); 5064 5065 /* 5066 * Currently we peek for the semi-colon to 5067 * allow processing of older lease files that 5068 * don't have the semi-colon. Eventually we 5069 * should remove the peeking code. 5070 */ 5071 token = peek_token(&val, NULL, cfile); 5072 if (token == SEMI) { 5073 skip_token(&val, NULL, cfile); 5074 } else { 5075 parse_warn(cfile, 5076 "corrupt lease file; " 5077 "expecting semicolon."); 5078 } 5079 break; 5080 5081 /* Lease valid lifetime. */ 5082 case MAX_LIFE: 5083 token = next_token(&val, NULL, cfile); 5084 if (token != NUMBER) { 5085 parse_warn(cfile, "%s is not a valid " 5086 "max time", 5087 val); 5088 skip_to_semi(cfile); 5089 continue; 5090 } 5091 valid = atoi (val); 5092 5093 /* 5094 * Currently we peek for the semi-colon to 5095 * allow processing of older lease files that 5096 * don't have the semi-colon. Eventually we 5097 * should remove the peeking code. 5098 */ 5099 token = peek_token(&val, NULL, cfile); 5100 if (token == SEMI) { 5101 skip_token(&val, NULL, cfile); 5102 } else { 5103 parse_warn(cfile, 5104 "corrupt lease file; " 5105 "expecting semicolon."); 5106 } 5107 break; 5108 5109 /* Lease expiration time. */ 5110 case ENDS: 5111 end_time = parse_date(cfile); 5112 break; 5113 5114 /* Lease binding scopes. */ 5115 case TOKEN_SET: 5116 token = next_token(&val, NULL, cfile); 5117 if ((token != NAME) && 5118 (token != NUMBER_OR_NAME)) { 5119 parse_warn(cfile, "%s is not a valid " 5120 "variable name", 5121 val); 5122 skip_to_semi(cfile); 5123 continue; 5124 } 5125 5126 if (scope != NULL) 5127 bnd = find_binding(scope, val); 5128 else { 5129 if (!binding_scope_allocate(&scope, 5130 MDL)) { 5131 log_fatal("Out of memory for " 5132 "lease binding " 5133 "scope."); 5134 } 5135 5136 bnd = NULL; 5137 } 5138 5139 if (bnd == NULL) { 5140 bnd = dmalloc(sizeof(*bnd), 5141 MDL); 5142 if (bnd == NULL) { 5143 log_fatal("No memory for " 5144 "lease binding."); 5145 } 5146 5147 bnd->name = dmalloc(strlen(val) + 1, 5148 MDL); 5149 if (bnd->name == NULL) { 5150 log_fatal("No memory for " 5151 "binding name."); 5152 } 5153 strcpy(bnd->name, val); 5154 5155 newbinding = ISC_TRUE; 5156 } else { 5157 newbinding = ISC_FALSE; 5158 } 5159 5160 if (!binding_value_allocate(&nv, MDL)) { 5161 log_fatal("no memory for binding " 5162 "value."); 5163 } 5164 5165 token = next_token(NULL, NULL, cfile); 5166 if (token != EQUAL) { 5167 parse_warn(cfile, "expecting '=' in " 5168 "set statement."); 5169 goto binding_err; 5170 } 5171 5172 if (!parse_binding_value(cfile, nv)) { 5173 binding_err: 5174 binding_value_dereference(&nv, MDL); 5175 binding_scope_dereference(&scope, MDL); 5176 return; 5177 } 5178 5179 if (newbinding) { 5180 binding_value_reference(&bnd->value, 5181 nv, MDL); 5182 bnd->next = scope->bindings; 5183 scope->bindings = bnd; 5184 } else { 5185 binding_value_dereference(&bnd->value, 5186 MDL); 5187 binding_value_reference(&bnd->value, 5188 nv, MDL); 5189 } 5190 5191 binding_value_dereference(&nv, MDL); 5192 parse_semi(cfile); 5193 break; 5194 5195 case ON: 5196 lose = 0; 5197 /* 5198 * Depending on the user config we may 5199 * have one or two on statements. We 5200 * need to save information about both 5201 * of them until we allocate the 5202 * iasubopt to hold them. 5203 */ 5204 if (on_star[0] == NULL) { 5205 if (!parse_on_statement (&on_star[0], 5206 cfile, 5207 &lose)) { 5208 parse_warn(cfile, 5209 "corrupt lease " 5210 "file; bad ON " 5211 "statement"); 5212 skip_to_rbrace (cfile, 1); 5213 return; 5214 } 5215 } else { 5216 if (!parse_on_statement (&on_star[1], 5217 cfile, 5218 &lose)) { 5219 parse_warn(cfile, 5220 "corrupt lease " 5221 "file; bad ON " 5222 "statement"); 5223 skip_to_rbrace (cfile, 1); 5224 return; 5225 } 5226 } 5227 5228 break; 5229 5230 default: 5231 parse_warn(cfile, "corrupt lease file; " 5232 "expecting ia_ta contents, " 5233 "got '%s'", val); 5234 skip_to_semi(cfile); 5235 continue; 5236 } 5237 } 5238 5239 if (state == FTS_LAST+1) { 5240 parse_warn(cfile, "corrupt lease file; " 5241 "missing state in iaaddr"); 5242 return; 5243 } 5244 if (end_time == -1) { 5245 parse_warn(cfile, "corrupt lease file; " 5246 "missing end time in iaaddr"); 5247 return; 5248 } 5249 5250 iaaddr = NULL; 5251 if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { 5252 log_fatal("Out of memory."); 5253 } 5254 memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr)); 5255 iaaddr->plen = 0; 5256 iaaddr->state = state; 5257 iaaddr->prefer = prefer; 5258 iaaddr->valid = valid; 5259 if (iaaddr->state == FTS_RELEASED) 5260 iaaddr->hard_lifetime_end_time = end_time; 5261 5262 if (scope != NULL) { 5263 binding_scope_reference(&iaaddr->scope, scope, MDL); 5264 binding_scope_dereference(&scope, MDL); 5265 } 5266 5267 /* 5268 * Check on both on statements. Because of how we write the 5269 * lease file we know which is which if we have two but it's 5270 * easier to write the code to be independent. We do assume 5271 * that the statements won't overlap. 5272 */ 5273 for (i = 0; 5274 (i < 2) && on_star[i] != NULL ; 5275 i++) { 5276 if ((on_star[i]->data.on.evtypes & ON_EXPIRY) && 5277 on_star[i]->data.on.statements) { 5278 executable_statement_reference 5279 (&iaaddr->on_star.on_expiry, 5280 on_star[i]->data.on.statements, MDL); 5281 } 5282 if ((on_star[i]->data.on.evtypes & ON_RELEASE) && 5283 on_star[i]->data.on.statements) { 5284 executable_statement_reference 5285 (&iaaddr->on_star.on_release, 5286 on_star[i]->data.on.statements, MDL); 5287 } 5288 executable_statement_dereference (&on_star[i], MDL); 5289 } 5290 5291 /* find the pool this address is in */ 5292 pool = NULL; 5293 if (find_ipv6_pool(&pool, D6O_IA_TA, 5294 &iaaddr->addr) != ISC_R_SUCCESS) { 5295 inet_ntop(AF_INET6, &iaaddr->addr, 5296 addr_buf, sizeof(addr_buf)); 5297 parse_warn(cfile, "no pool found for address %s", 5298 addr_buf); 5299 return; 5300 } 5301 5302 /* remove old information */ 5303 if (cleanup_lease6(ia_ta_active, pool, 5304 iaaddr, ia) != ISC_R_SUCCESS) { 5305 inet_ntop(AF_INET6, &iaaddr->addr, 5306 addr_buf, sizeof(addr_buf)); 5307 parse_warn(cfile, "duplicate ta lease for address %s", 5308 addr_buf); 5309 } 5310 5311 /* 5312 * if we like the lease we add it to our various structues 5313 * otherwise we leave it and it will get cleaned when we 5314 * do the iasubopt_dereference. 5315 */ 5316 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) { 5317 ia_add_iasubopt(ia, iaaddr, MDL); 5318 ia_reference(&iaaddr->ia, ia, MDL); 5319 add_lease6(pool, iaaddr, end_time); 5320 } 5321 5322 ipv6_pool_dereference(&pool, MDL); 5323 iasubopt_dereference(&iaaddr, MDL); 5324 } 5325 5326 /* 5327 * If we have an existing record for this IA_TA, remove it. 5328 */ 5329 old_ia = NULL; 5330 if (ia_hash_lookup(&old_ia, ia_ta_active, 5331 (unsigned char *)ia->iaid_duid.data, 5332 ia->iaid_duid.len, MDL)) { 5333 ia_hash_delete(ia_ta_active, 5334 (unsigned char *)ia->iaid_duid.data, 5335 ia->iaid_duid.len, MDL); 5336 ia_dereference(&old_ia, MDL); 5337 } 5338 5339 /* 5340 * If we have addresses, add this, otherwise don't bother. 5341 */ 5342 if (ia->num_iasubopt > 0) { 5343 ia_hash_add(ia_ta_active, 5344 (unsigned char *)ia->iaid_duid.data, 5345 ia->iaid_duid.len, ia, MDL); 5346 } 5347 ia_dereference(&ia, MDL); 5348 #endif /* defined(DHCPv6) */ 5349 } 5350 5351 void 5352 parse_ia_pd_declaration(struct parse *cfile) { 5353 #if !defined(DHCPv6) 5354 parse_warn(cfile, "No DHCPv6 support."); 5355 skip_to_semi(cfile); 5356 #else /* defined(DHCPv6) */ 5357 enum dhcp_token token; 5358 struct ia_xx *ia; 5359 const char *val; 5360 struct ia_xx *old_ia; 5361 unsigned int len; 5362 u_int32_t iaid; 5363 struct iaddr iaddr; 5364 u_int8_t plen; 5365 binding_state_t state; 5366 u_int32_t prefer; 5367 u_int32_t valid; 5368 TIME end_time; 5369 struct iasubopt *iapref; 5370 struct ipv6_pool *pool; 5371 char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 5372 isc_boolean_t newbinding; 5373 struct binding_scope *scope = NULL; 5374 struct binding *bnd; 5375 struct binding_value *nv = NULL; 5376 struct executable_statement *on_star[2] = {NULL, NULL}; 5377 int lose, i; 5378 5379 if (local_family != AF_INET6) { 5380 parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode."); 5381 skip_to_semi(cfile); 5382 return; 5383 } 5384 5385 token = next_token(&val, &len, cfile); 5386 if (token != STRING) { 5387 parse_warn(cfile, "corrupt lease file; " 5388 "expecting an iaid+ia_pd string"); 5389 skip_to_semi(cfile); 5390 return; 5391 } 5392 if (len < 5) { 5393 parse_warn(cfile, "corrupt lease file; " 5394 "iaid+ia_pd string too short"); 5395 skip_to_semi(cfile); 5396 return; 5397 } 5398 5399 memcpy(&iaid, val, 4); 5400 ia = NULL; 5401 if (ia_allocate(&ia, iaid, val+4, len-4, MDL) != ISC_R_SUCCESS) { 5402 log_fatal("Out of memory."); 5403 } 5404 ia->ia_type = D6O_IA_PD; 5405 5406 token = next_token(&val, NULL, cfile); 5407 if (token != LBRACE) { 5408 parse_warn(cfile, "corrupt lease file; expecting left brace"); 5409 skip_to_semi(cfile); 5410 return; 5411 } 5412 5413 for (;;) { 5414 token = next_token(&val, NULL, cfile); 5415 if (token == RBRACE) break; 5416 5417 if (token == CLTT) { 5418 ia->cltt = parse_date (cfile); 5419 continue; 5420 } 5421 5422 if (token != IAPREFIX) { 5423 parse_warn(cfile, "corrupt lease file; expecting " 5424 "IAPREFIX or right brace"); 5425 skip_to_semi(cfile); 5426 return; 5427 } 5428 5429 if (!parse_ip6_prefix(cfile, &iaddr, &plen)) { 5430 parse_warn(cfile, "corrupt lease file; " 5431 "expecting IPv6 prefix"); 5432 skip_to_semi(cfile); 5433 return; 5434 } 5435 5436 token = next_token(&val, NULL, cfile); 5437 if (token != LBRACE) { 5438 parse_warn(cfile, "corrupt lease file; " 5439 "expecting left brace"); 5440 skip_to_semi(cfile); 5441 return; 5442 } 5443 5444 state = FTS_LAST+1; 5445 prefer = valid = 0; 5446 end_time = -1; 5447 for (;;) { 5448 token = next_token(&val, NULL, cfile); 5449 if (token == RBRACE) break; 5450 5451 switch(token) { 5452 /* Prefix binding state. */ 5453 case BINDING: 5454 token = next_token(&val, NULL, cfile); 5455 if (token != STATE) { 5456 parse_warn(cfile, "corrupt lease file; " 5457 "expecting state"); 5458 skip_to_semi(cfile); 5459 return; 5460 } 5461 token = next_token(&val, NULL, cfile); 5462 switch (token) { 5463 case TOKEN_ABANDONED: 5464 state = FTS_ABANDONED; 5465 break; 5466 case TOKEN_FREE: 5467 state = FTS_FREE; 5468 break; 5469 case TOKEN_ACTIVE: 5470 state = FTS_ACTIVE; 5471 break; 5472 case TOKEN_EXPIRED: 5473 state = FTS_EXPIRED; 5474 break; 5475 case TOKEN_RELEASED: 5476 state = FTS_RELEASED; 5477 break; 5478 default: 5479 parse_warn(cfile, 5480 "corrupt lease " 5481 "file; " 5482 "expecting a " 5483 "binding state."); 5484 skip_to_semi(cfile); 5485 return; 5486 } 5487 5488 token = next_token(&val, NULL, cfile); 5489 if (token != SEMI) { 5490 parse_warn(cfile, "corrupt lease file; " 5491 "expecting " 5492 "semicolon."); 5493 } 5494 break; 5495 5496 /* Lease preferred lifetime. */ 5497 case PREFERRED_LIFE: 5498 token = next_token(&val, NULL, cfile); 5499 if (token != NUMBER) { 5500 parse_warn(cfile, "%s is not a valid " 5501 "preferred time", 5502 val); 5503 skip_to_semi(cfile); 5504 continue; 5505 } 5506 prefer = atoi (val); 5507 5508 /* 5509 * Currently we peek for the semi-colon to 5510 * allow processing of older lease files that 5511 * don't have the semi-colon. Eventually we 5512 * should remove the peeking code. 5513 */ 5514 token = peek_token(&val, NULL, cfile); 5515 if (token == SEMI) { 5516 skip_token(&val, NULL, cfile); 5517 } else { 5518 parse_warn(cfile, 5519 "corrupt lease file; " 5520 "expecting semicolon."); 5521 } 5522 break; 5523 5524 /* Lease valid lifetime. */ 5525 case MAX_LIFE: 5526 token = next_token(&val, NULL, cfile); 5527 if (token != NUMBER) { 5528 parse_warn(cfile, "%s is not a valid " 5529 "max time", 5530 val); 5531 skip_to_semi(cfile); 5532 continue; 5533 } 5534 valid = atoi (val); 5535 5536 /* 5537 * Currently we peek for the semi-colon to 5538 * allow processing of older lease files that 5539 * don't have the semi-colon. Eventually we 5540 * should remove the peeking code. 5541 */ 5542 token = peek_token(&val, NULL, cfile); 5543 if (token == SEMI) { 5544 skip_token(&val, NULL, cfile); 5545 } else { 5546 parse_warn(cfile, 5547 "corrupt lease file; " 5548 "expecting semicolon."); 5549 } 5550 break; 5551 5552 /* Prefix expiration time. */ 5553 case ENDS: 5554 end_time = parse_date(cfile); 5555 break; 5556 5557 /* Prefix binding scopes. */ 5558 case TOKEN_SET: 5559 token = next_token(&val, NULL, cfile); 5560 if ((token != NAME) && 5561 (token != NUMBER_OR_NAME)) { 5562 parse_warn(cfile, "%s is not a valid " 5563 "variable name", 5564 val); 5565 skip_to_semi(cfile); 5566 continue; 5567 } 5568 5569 if (scope != NULL) 5570 bnd = find_binding(scope, val); 5571 else { 5572 if (!binding_scope_allocate(&scope, 5573 MDL)) { 5574 log_fatal("Out of memory for " 5575 "lease binding " 5576 "scope."); 5577 } 5578 5579 bnd = NULL; 5580 } 5581 5582 if (bnd == NULL) { 5583 bnd = dmalloc(sizeof(*bnd), 5584 MDL); 5585 if (bnd == NULL) { 5586 log_fatal("No memory for " 5587 "prefix binding."); 5588 } 5589 5590 bnd->name = dmalloc(strlen(val) + 1, 5591 MDL); 5592 if (bnd->name == NULL) { 5593 log_fatal("No memory for " 5594 "binding name."); 5595 } 5596 strcpy(bnd->name, val); 5597 5598 newbinding = ISC_TRUE; 5599 } else { 5600 newbinding = ISC_FALSE; 5601 } 5602 5603 if (!binding_value_allocate(&nv, MDL)) { 5604 log_fatal("no memory for binding " 5605 "value."); 5606 } 5607 5608 token = next_token(NULL, NULL, cfile); 5609 if (token != EQUAL) { 5610 parse_warn(cfile, "expecting '=' in " 5611 "set statement."); 5612 goto binding_err; 5613 } 5614 5615 if (!parse_binding_value(cfile, nv)) { 5616 binding_err: 5617 binding_value_dereference(&nv, MDL); 5618 binding_scope_dereference(&scope, MDL); 5619 return; 5620 } 5621 5622 if (newbinding) { 5623 binding_value_reference(&bnd->value, 5624 nv, MDL); 5625 bnd->next = scope->bindings; 5626 scope->bindings = bnd; 5627 } else { 5628 binding_value_dereference(&bnd->value, 5629 MDL); 5630 binding_value_reference(&bnd->value, 5631 nv, MDL); 5632 } 5633 5634 binding_value_dereference(&nv, MDL); 5635 parse_semi(cfile); 5636 break; 5637 5638 case ON: 5639 lose = 0; 5640 /* 5641 * Depending on the user config we may 5642 * have one or two on statements. We 5643 * need to save information about both 5644 * of them until we allocate the 5645 * iasubopt to hold them. 5646 */ 5647 if (on_star[0] == NULL) { 5648 if (!parse_on_statement (&on_star[0], 5649 cfile, 5650 &lose)) { 5651 parse_warn(cfile, 5652 "corrupt lease " 5653 "file; bad ON " 5654 "statement"); 5655 skip_to_rbrace (cfile, 1); 5656 return; 5657 } 5658 } else { 5659 if (!parse_on_statement (&on_star[1], 5660 cfile, 5661 &lose)) { 5662 parse_warn(cfile, 5663 "corrupt lease " 5664 "file; bad ON " 5665 "statement"); 5666 skip_to_rbrace (cfile, 1); 5667 return; 5668 } 5669 } 5670 5671 break; 5672 5673 default: 5674 parse_warn(cfile, "corrupt lease file; " 5675 "expecting ia_pd contents, " 5676 "got '%s'", val); 5677 skip_to_semi(cfile); 5678 continue; 5679 } 5680 } 5681 5682 if (state == FTS_LAST+1) { 5683 parse_warn(cfile, "corrupt lease file; " 5684 "missing state in iaprefix"); 5685 return; 5686 } 5687 if (end_time == -1) { 5688 parse_warn(cfile, "corrupt lease file; " 5689 "missing end time in iaprefix"); 5690 return; 5691 } 5692 5693 iapref = NULL; 5694 if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) { 5695 log_fatal("Out of memory."); 5696 } 5697 memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr)); 5698 iapref->plen = plen; 5699 iapref->state = state; 5700 iapref->prefer = prefer; 5701 iapref->valid = valid; 5702 if (iapref->state == FTS_RELEASED) 5703 iapref->hard_lifetime_end_time = end_time; 5704 5705 if (scope != NULL) { 5706 binding_scope_reference(&iapref->scope, scope, MDL); 5707 binding_scope_dereference(&scope, MDL); 5708 } 5709 5710 /* 5711 * Check on both on statements. Because of how we write the 5712 * lease file we know which is which if we have two but it's 5713 * easier to write the code to be independent. We do assume 5714 * that the statements won't overlap. 5715 */ 5716 for (i = 0; 5717 (i < 2) && on_star[i] != NULL ; 5718 i++) { 5719 if ((on_star[i]->data.on.evtypes & ON_EXPIRY) && 5720 on_star[i]->data.on.statements) { 5721 executable_statement_reference 5722 (&iapref->on_star.on_expiry, 5723 on_star[i]->data.on.statements, MDL); 5724 } 5725 if ((on_star[i]->data.on.evtypes & ON_RELEASE) && 5726 on_star[i]->data.on.statements) { 5727 executable_statement_reference 5728 (&iapref->on_star.on_release, 5729 on_star[i]->data.on.statements, MDL); 5730 } 5731 executable_statement_dereference (&on_star[i], MDL); 5732 } 5733 5734 /* find the pool this address is in */ 5735 pool = NULL; 5736 if (find_ipv6_pool(&pool, D6O_IA_PD, 5737 &iapref->addr) != ISC_R_SUCCESS) { 5738 inet_ntop(AF_INET6, &iapref->addr, 5739 addr_buf, sizeof(addr_buf)); 5740 parse_warn(cfile, "no pool found for address %s", 5741 addr_buf); 5742 return; 5743 } 5744 5745 /* remove old information */ 5746 if (cleanup_lease6(ia_pd_active, pool, 5747 iapref, ia) != ISC_R_SUCCESS) { 5748 inet_ntop(AF_INET6, &iapref->addr, 5749 addr_buf, sizeof(addr_buf)); 5750 parse_warn(cfile, "duplicate pd lease for address %s", 5751 addr_buf); 5752 } 5753 5754 /* 5755 * if we like the lease we add it to our various structues 5756 * otherwise we leave it and it will get cleaned when we 5757 * do the iasubopt_dereference. 5758 */ 5759 if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) { 5760 ia_add_iasubopt(ia, iapref, MDL); 5761 ia_reference(&iapref->ia, ia, MDL); 5762 add_lease6(pool, iapref, end_time); 5763 } 5764 5765 ipv6_pool_dereference(&pool, MDL); 5766 iasubopt_dereference(&iapref, MDL); 5767 } 5768 5769 /* 5770 * If we have an existing record for this IA_PD, remove it. 5771 */ 5772 old_ia = NULL; 5773 if (ia_hash_lookup(&old_ia, ia_pd_active, 5774 (unsigned char *)ia->iaid_duid.data, 5775 ia->iaid_duid.len, MDL)) { 5776 ia_hash_delete(ia_pd_active, 5777 (unsigned char *)ia->iaid_duid.data, 5778 ia->iaid_duid.len, MDL); 5779 ia_dereference(&old_ia, MDL); 5780 } 5781 5782 /* 5783 * If we have prefixes, add this, otherwise don't bother. 5784 */ 5785 if (ia->num_iasubopt > 0) { 5786 ia_hash_add(ia_pd_active, 5787 (unsigned char *)ia->iaid_duid.data, 5788 ia->iaid_duid.len, ia, MDL); 5789 } 5790 ia_dereference(&ia, MDL); 5791 #endif /* defined(DHCPv6) */ 5792 } 5793 5794 #ifdef DHCPv6 5795 /* 5796 * When we parse a server-duid statement in a lease file, we are 5797 * looking at the saved server DUID from a previous run. In this case 5798 * we expect it to be followed by the binary representation of the 5799 * DUID stored in a string: 5800 * 5801 * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y"; 5802 */ 5803 void 5804 parse_server_duid(struct parse *cfile) { 5805 enum dhcp_token token; 5806 const char *val; 5807 unsigned int len; 5808 struct data_string duid; 5809 5810 token = next_token(&val, &len, cfile); 5811 if (token != STRING) { 5812 parse_warn(cfile, "corrupt lease file; expecting a DUID"); 5813 skip_to_semi(cfile); 5814 return; 5815 } 5816 5817 memset(&duid, 0, sizeof(duid)); 5818 duid.len = len; 5819 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) { 5820 log_fatal("Out of memory storing DUID"); 5821 } 5822 duid.data = (unsigned char *)duid.buffer->data; 5823 memcpy(duid.buffer->data, val, len); 5824 5825 set_server_duid(&duid); 5826 5827 data_string_forget(&duid, MDL); 5828 5829 token = next_token(&val, &len, cfile); 5830 if (token != SEMI) { 5831 parse_warn(cfile, "corrupt lease file; expecting a semicolon"); 5832 skip_to_semi(cfile); 5833 return; 5834 } 5835 } 5836 5837 /* 5838 * When we parse a server-duid statement in a config file, we will 5839 * have the type of the server DUID to generate, and possibly the 5840 * actual value defined. 5841 * 5842 * server-duid llt; 5843 * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B; 5844 * server-duid ll; 5845 * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B; 5846 * server-duid en 2495 "enterprise-specific-identifier-1234"; 5847 */ 5848 void 5849 parse_server_duid_conf(struct parse *cfile) { 5850 enum dhcp_token token; 5851 const char *val; 5852 unsigned int len; 5853 u_int32_t enterprise_number; 5854 int ll_type; 5855 struct data_string ll_addr; 5856 u_int32_t llt_time; 5857 struct data_string duid; 5858 int duid_type_num; 5859 5860 /* 5861 * Consume the SERVER_DUID token. 5862 */ 5863 skip_token(NULL, NULL, cfile); 5864 5865 /* 5866 * Obtain the DUID type. 5867 */ 5868 token = next_token(&val, NULL, cfile); 5869 5870 /* 5871 * Enterprise is the easiest - enterprise number and raw data 5872 * are required. 5873 */ 5874 if (token == EN) { 5875 /* 5876 * Get enterprise number and identifier. 5877 */ 5878 token = next_token(&val, NULL, cfile); 5879 if (token != NUMBER) { 5880 parse_warn(cfile, "enterprise number expected"); 5881 skip_to_semi(cfile); 5882 return; 5883 } 5884 enterprise_number = atoi(val); 5885 5886 token = next_token(&val, &len, cfile); 5887 if (token != STRING) { 5888 parse_warn(cfile, "identifier expected"); 5889 skip_to_semi(cfile); 5890 return; 5891 } 5892 5893 /* 5894 * Save the DUID. 5895 */ 5896 memset(&duid, 0, sizeof(duid)); 5897 duid.len = 2 + 4 + len; 5898 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) { 5899 log_fatal("Out of memory storing DUID"); 5900 } 5901 duid.data = (unsigned char *)duid.buffer->data; 5902 putUShort(duid.buffer->data, DUID_EN); 5903 putULong(duid.buffer->data + 2, enterprise_number); 5904 memcpy(duid.buffer->data + 6, val, len); 5905 5906 set_server_duid(&duid); 5907 data_string_forget(&duid, MDL); 5908 } 5909 5910 /* 5911 * Next easiest is the link-layer DUID. It consists only of 5912 * the LL directive, or optionally the specific value to use. 5913 * 5914 * If we have LL only, then we set the type. If we have the 5915 * value, then we set the actual DUID. 5916 */ 5917 else if (token == LL) { 5918 if (peek_token(NULL, NULL, cfile) == SEMI) { 5919 set_server_duid_type(DUID_LL); 5920 } else { 5921 /* 5922 * Get our hardware type and address. 5923 */ 5924 token = next_token(NULL, NULL, cfile); 5925 switch (token) { 5926 case ETHERNET: 5927 ll_type = HTYPE_ETHER; 5928 break; 5929 case TOKEN_RING: 5930 ll_type = HTYPE_IEEE802; 5931 break; 5932 case TOKEN_FDDI: 5933 ll_type = HTYPE_FDDI; 5934 break; 5935 default: 5936 parse_warn(cfile, "hardware type expected"); 5937 skip_to_semi(cfile); 5938 return; 5939 } 5940 memset(&ll_addr, 0, sizeof(ll_addr)); 5941 if (!parse_cshl(&ll_addr, cfile)) { 5942 return; 5943 } 5944 5945 /* 5946 * Save the DUID. 5947 */ 5948 memset(&duid, 0, sizeof(duid)); 5949 duid.len = 2 + 2 + ll_addr.len; 5950 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) { 5951 log_fatal("Out of memory storing DUID"); 5952 } 5953 duid.data = (unsigned char *)duid.buffer->data; 5954 putUShort(duid.buffer->data, DUID_LL); 5955 putULong(duid.buffer->data + 2, ll_type); 5956 memcpy(duid.buffer->data + 4, 5957 ll_addr.data, ll_addr.len); 5958 5959 set_server_duid(&duid); 5960 data_string_forget(&duid, MDL); 5961 data_string_forget(&ll_addr, MDL); 5962 } 5963 } 5964 5965 /* 5966 * Finally the link-layer DUID plus time. It consists only of 5967 * the LLT directive, or optionally the specific value to use. 5968 * 5969 * If we have LLT only, then we set the type. If we have the 5970 * value, then we set the actual DUID. 5971 */ 5972 else if (token == LLT) { 5973 if (peek_token(NULL, NULL, cfile) == SEMI) { 5974 set_server_duid_type(DUID_LLT); 5975 } else { 5976 /* 5977 * Get our hardware type, timestamp, and address. 5978 */ 5979 token = next_token(NULL, NULL, cfile); 5980 switch (token) { 5981 case ETHERNET: 5982 ll_type = HTYPE_ETHER; 5983 break; 5984 case TOKEN_RING: 5985 ll_type = HTYPE_IEEE802; 5986 break; 5987 case TOKEN_FDDI: 5988 ll_type = HTYPE_FDDI; 5989 break; 5990 default: 5991 parse_warn(cfile, "hardware type expected"); 5992 skip_to_semi(cfile); 5993 return; 5994 } 5995 5996 token = next_token(&val, NULL, cfile); 5997 if (token != NUMBER) { 5998 parse_warn(cfile, "timestamp expected"); 5999 skip_to_semi(cfile); 6000 return; 6001 } 6002 llt_time = atoi(val); 6003 6004 memset(&ll_addr, 0, sizeof(ll_addr)); 6005 if (!parse_cshl(&ll_addr, cfile)) { 6006 return; 6007 } 6008 6009 /* 6010 * Save the DUID. 6011 */ 6012 memset(&duid, 0, sizeof(duid)); 6013 duid.len = 2 + 2 + 4 + ll_addr.len; 6014 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) { 6015 log_fatal("Out of memory storing DUID"); 6016 } 6017 duid.data = (unsigned char *)duid.buffer->data; 6018 putUShort(duid.buffer->data, DUID_LLT); 6019 putULong(duid.buffer->data + 2, ll_type); 6020 putULong(duid.buffer->data + 4, llt_time); 6021 memcpy(duid.buffer->data + 8, 6022 ll_addr.data, ll_addr.len); 6023 6024 set_server_duid(&duid); 6025 data_string_forget(&duid, MDL); 6026 data_string_forget(&ll_addr, MDL); 6027 } 6028 } 6029 6030 /* 6031 * If users want they can use a number for DUID types. 6032 * This is useful for supporting future, not-yet-defined 6033 * DUID types. 6034 * 6035 * In this case, they have to put in the complete value. 6036 * 6037 * This also works for existing DUID types of course. 6038 */ 6039 else if (token == NUMBER) { 6040 duid_type_num = atoi(val); 6041 6042 token = next_token(&val, &len, cfile); 6043 if (token != STRING) { 6044 parse_warn(cfile, "identifier expected"); 6045 skip_to_semi(cfile); 6046 return; 6047 } 6048 6049 /* 6050 * Save the DUID. 6051 */ 6052 memset(&duid, 0, sizeof(duid)); 6053 duid.len = 2 + len; 6054 if (!buffer_allocate(&duid.buffer, duid.len, MDL)) { 6055 log_fatal("Out of memory storing DUID"); 6056 } 6057 duid.data = (unsigned char *)duid.buffer->data; 6058 putUShort(duid.buffer->data, duid_type_num); 6059 memcpy(duid.buffer->data + 2, val, len); 6060 6061 set_server_duid(&duid); 6062 data_string_forget(&duid, MDL); 6063 } 6064 6065 /* 6066 * Anything else is an error. 6067 */ 6068 else { 6069 parse_warn(cfile, "DUID type of LLT, EN, or LL expected"); 6070 skip_to_semi(cfile); 6071 return; 6072 } 6073 6074 /* 6075 * Finally consume our trailing semicolon. 6076 */ 6077 token = next_token(NULL, NULL, cfile); 6078 if (token != SEMI) { 6079 parse_warn(cfile, "semicolon expected"); 6080 skip_to_semi(cfile); 6081 } 6082 } 6083 6084 #endif /* DHCPv6 */ 6085 6086