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