1 /* $NetBSD: parse.c,v 1.2 2018/04/07 22:37:29 christos Exp $ */ 2 3 /* parse.c 4 5 Common parser code for dhcpd and dhclient. */ 6 7 /* 8 * Copyright (c) 2004-2017 by 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 * 950 Charter Street 25 * Redwood City, CA 94063 26 * <info@isc.org> 27 * https://www.isc.org/ 28 * 29 */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: parse.c,v 1.2 2018/04/07 22:37:29 christos Exp $"); 33 34 #include "dhcpd.h" 35 #include <isc/util.h> 36 #include <syslog.h> 37 38 struct collection default_collection = { NULL, "default", NULL }; 39 struct collection *collections = &default_collection; 40 41 /* Enumerations can be specified in option formats, and are used for 42 parsing, so we define the routines that manage them here. */ 43 44 struct enumeration *enumerations; 45 46 void add_enumeration (struct enumeration *enumeration) 47 { 48 enumeration -> next = enumerations; 49 enumerations = enumeration; 50 } 51 52 struct enumeration *find_enumeration (const char *name, int length) 53 { 54 struct enumeration *e; 55 56 for (e = enumerations; e; e = e -> next) 57 if (strlen (e -> name) == length && 58 !memcmp (e -> name, name, (unsigned)length)) 59 return e; 60 return (struct enumeration *)0; 61 } 62 63 struct enumeration_value *find_enumeration_value (const char *name, 64 int length, 65 unsigned *widthp, 66 const char *value) 67 { 68 struct enumeration *e; 69 int i; 70 71 e = find_enumeration (name, length); 72 if (e) { 73 if (widthp != NULL) 74 *widthp = e->width; 75 for (i = 0; e -> values [i].name; i++) { 76 if (!strcmp (value, e -> values [i].name)) 77 return &e -> values [i]; 78 } 79 } 80 return (struct enumeration_value *)0; 81 } 82 83 /* Skip to the semicolon ending the current statement. If we encounter 84 braces, the matching closing brace terminates the statement. 85 */ 86 void skip_to_semi (cfile) 87 struct parse *cfile; 88 { 89 skip_to_rbrace(cfile, 0); 90 } 91 92 /* Skips everything from the current point upto (and including) the given 93 number of right braces. If we encounter a semicolon but haven't seen a 94 left brace, consume it and return. 95 This lets us skip over: 96 97 statement; 98 statement foo bar { } 99 statement foo bar { statement { } } 100 statement} 101 102 ...et cetera. */ 103 void skip_to_rbrace (cfile, brace_count) 104 struct parse *cfile; 105 int brace_count; 106 { 107 enum dhcp_token token; 108 const char *val; 109 110 #if defined (DEBUG_TOKENS) 111 log_error("skip_to_rbrace: %d\n", brace_count); 112 #endif 113 do { 114 token = peek_token(&val, NULL, cfile); 115 if (token == RBRACE) { 116 if (brace_count > 0) { 117 --brace_count; 118 } 119 120 if (brace_count == 0) { 121 /* Eat the brace and return. */ 122 skip_token(&val, NULL, cfile); 123 return; 124 } 125 } else if (token == LBRACE) { 126 brace_count++; 127 } else if (token == SEMI && (brace_count == 0)) { 128 /* Eat the semicolon and return. */ 129 skip_token(&val, NULL, cfile); 130 return; 131 } else if (token == EOL) { 132 /* EOL only happens when parsing /etc/resolv.conf, 133 and we treat it like a semicolon because the 134 resolv.conf file is line-oriented. */ 135 skip_token(&val, NULL, cfile); 136 return; 137 } 138 139 /* Eat the current token */ 140 token = next_token(&val, NULL, cfile); 141 } while (token != END_OF_FILE); 142 } 143 144 int parse_semi (cfile) 145 struct parse *cfile; 146 { 147 enum dhcp_token token; 148 const char *val; 149 150 token = next_token (&val, (unsigned *)0, cfile); 151 if (token != SEMI) { 152 parse_warn (cfile, "semicolon expected."); 153 skip_to_semi (cfile); 154 return 0; 155 } 156 return 1; 157 } 158 159 /* string-parameter :== STRING SEMI */ 160 161 int parse_string (cfile, sptr, lptr) 162 struct parse *cfile; 163 char **sptr; 164 unsigned *lptr; 165 { 166 const char *val; 167 enum dhcp_token token; 168 char *s; 169 unsigned len; 170 171 token = next_token (&val, &len, cfile); 172 if (token != STRING) { 173 parse_warn (cfile, "expecting a string"); 174 skip_to_semi (cfile); 175 return 0; 176 } 177 s = (char *)dmalloc (len + 1, MDL); 178 if (!s) 179 log_fatal ("no memory for string %s.", val); 180 memcpy (s, val, len + 1); 181 182 if (!parse_semi (cfile)) { 183 dfree (s, MDL); 184 return 0; 185 } 186 if (sptr) 187 *sptr = s; 188 else 189 dfree (s, MDL); 190 if (lptr) 191 *lptr = len; 192 return 1; 193 } 194 195 /* 196 * hostname :== IDENTIFIER 197 * | IDENTIFIER DOT 198 * | hostname DOT IDENTIFIER 199 */ 200 201 char *parse_host_name (cfile) 202 struct parse *cfile; 203 { 204 const char *val; 205 enum dhcp_token token; 206 unsigned len = 0; 207 char *s; 208 char *t; 209 pair c = (pair)0; 210 int ltid = 0; 211 212 /* Read a dotted hostname... */ 213 do { 214 /* Read a token, which should be an identifier. */ 215 token = peek_token (&val, (unsigned *)0, cfile); 216 if (!is_identifier (token) && token != NUMBER) 217 break; 218 skip_token(&val, (unsigned *)0, cfile); 219 220 /* Store this identifier... */ 221 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL))) 222 log_fatal ("can't allocate temp space for hostname."); 223 strcpy (s, val); 224 c = cons ((caddr_t)s, c); 225 len += strlen (s) + 1; 226 /* Look for a dot; if it's there, keep going, otherwise 227 we're done. */ 228 token = peek_token (&val, (unsigned *)0, cfile); 229 if (token == DOT) { 230 token = next_token (&val, (unsigned *)0, cfile); 231 ltid = 1; 232 } else 233 ltid = 0; 234 } while (token == DOT); 235 236 /* Should be at least one token. */ 237 if (!len) 238 return (char *)0; 239 240 /* Assemble the hostname together into a string. */ 241 if (!(s = (char *)dmalloc (len + ltid, MDL))) 242 log_fatal ("can't allocate space for hostname."); 243 t = s + len + ltid; 244 *--t = 0; 245 if (ltid) 246 *--t = '.'; 247 while (c) { 248 pair cdr = c -> cdr; 249 unsigned l = strlen ((char *)(c -> car)); 250 t -= l; 251 memcpy (t, (char *)(c -> car), l); 252 /* Free up temp space. */ 253 dfree (c -> car, MDL); 254 dfree (c, MDL); 255 c = cdr; 256 if (t != s) 257 *--t = '.'; 258 } 259 return s; 260 } 261 262 /* ip-addr-or-hostname :== ip-address | hostname 263 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER 264 265 Parse an ip address or a hostname. If uniform is zero, put in 266 an expr_substring node to limit hostnames that evaluate to more 267 than one IP address. 268 269 Note that RFC1123 permits hostnames to consist of all digits, 270 making it difficult to quickly disambiguate them from ip addresses. 271 */ 272 273 int parse_ip_addr_or_hostname (expr, cfile, uniform) 274 struct expression **expr; 275 struct parse *cfile; 276 int uniform; 277 { 278 const char *val; 279 enum dhcp_token token; 280 unsigned char addr [4]; 281 unsigned len = sizeof addr; 282 char *name; 283 struct expression *x = (struct expression *)0; 284 int ipaddr = 0; 285 286 token = peek_token (&val, (unsigned *)0, cfile); 287 288 if (token == NUMBER) { 289 /* 290 * a hostname may be numeric, but domain names must 291 * start with a letter, so we can disambiguate by 292 * looking ahead a few tokens. we save the parse 293 * context first, and restore it after we know what 294 * we're dealing with. 295 */ 296 save_parse_state(cfile); 297 skip_token(NULL, NULL, cfile); 298 if (next_token(NULL, NULL, cfile) == DOT && 299 next_token(NULL, NULL, cfile) == NUMBER) 300 ipaddr = 1; 301 restore_parse_state(cfile); 302 303 if (ipaddr && 304 parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) 305 return make_const_data (expr, addr, len, 0, 1, MDL); 306 307 } 308 309 if (is_identifier (token) || token == NUMBER) { 310 name = parse_host_name (cfile); 311 if (!name) 312 return 0; 313 if (!make_host_lookup (expr, name)) { 314 dfree(name, MDL); 315 return 0; 316 } 317 dfree(name, MDL); 318 if (!uniform) { 319 if (!make_limit (&x, *expr, 4)) 320 return 0; 321 expression_dereference (expr, MDL); 322 *expr = x; 323 } 324 } else { 325 if (token != RBRACE && token != LBRACE) 326 token = next_token (&val, (unsigned *)0, cfile); 327 parse_warn (cfile, "%s (%d): expecting IP address or hostname", 328 val, token); 329 if (token != SEMI) 330 skip_to_semi (cfile); 331 return 0; 332 } 333 334 return 1; 335 } 336 337 /* 338 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER 339 */ 340 341 int parse_ip_addr (cfile, addr) 342 struct parse *cfile; 343 struct iaddr *addr; 344 { 345 addr -> len = 4; 346 if (parse_numeric_aggregate (cfile, addr -> iabuf, 347 &addr -> len, DOT, 10, 8)) 348 return 1; 349 return 0; 350 } 351 352 /* 353 * Return true if every character in the string is hexadecimal. 354 */ 355 static int 356 is_hex_string(const char *s) { 357 while (*s != '\0') { 358 if (!isxdigit((int)*s)) { 359 return 0; 360 } 361 s++; 362 } 363 return 1; 364 } 365 366 /* 367 * ip-address6 :== (complicated set of rules) 368 * 369 * See section 2.2 of RFC 1884 for details. 370 * 371 * We are lazy for this. We pull numbers, names, colons, and dots 372 * together and then throw the resulting string at the inet_pton() 373 * function. 374 */ 375 376 int 377 parse_ip6_addr(struct parse *cfile, struct iaddr *addr) { 378 enum dhcp_token token; 379 const char *val; 380 int val_len; 381 382 char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 383 int v6_len; 384 385 /* 386 * First token is non-raw. This way we eat any whitespace before 387 * our IPv6 address begins, like one would expect. 388 */ 389 token = peek_token(&val, NULL, cfile); 390 391 /* 392 * Gather symbols. 393 */ 394 v6_len = 0; 395 for (;;) { 396 if ((((token == NAME) || (token == NUMBER_OR_NAME)) && 397 is_hex_string(val)) || 398 (token == NUMBER) || 399 (token == TOKEN_ADD) || 400 (token == DOT) || 401 (token == COLON)) { 402 403 next_raw_token(&val, NULL, cfile); 404 val_len = strlen(val); 405 if ((v6_len + val_len) >= sizeof(v6)) { 406 parse_warn(cfile, "Invalid IPv6 address."); 407 skip_to_semi(cfile); 408 return 0; 409 } 410 memcpy(v6+v6_len, val, val_len); 411 v6_len += val_len; 412 413 } else { 414 break; 415 } 416 token = peek_raw_token(&val, NULL, cfile); 417 } 418 v6[v6_len] = '\0'; 419 420 /* 421 * Use inet_pton() for actual work. 422 */ 423 if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) { 424 parse_warn(cfile, "Invalid IPv6 address."); 425 skip_to_semi(cfile); 426 return 0; 427 } 428 addr->len = 16; 429 return 1; 430 } 431 432 /* 433 * Same as parse_ip6_addr() above, but returns the value in the 434 * expression rather than in an address structure. 435 */ 436 int 437 parse_ip6_addr_expr(struct expression **expr, 438 struct parse *cfile) { 439 struct iaddr addr; 440 441 if (!parse_ip6_addr(cfile, &addr)) { 442 return 0; 443 } 444 return make_const_data(expr, addr.iabuf, addr.len, 0, 1, MDL); 445 } 446 447 /* 448 * ip6-prefix :== ip6-address "/" NUMBER 449 */ 450 int 451 parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen) { 452 enum dhcp_token token; 453 const char *val; 454 int n; 455 456 if (!parse_ip6_addr(cfile, addr)) { 457 return 0; 458 } 459 token = next_token(&val, NULL, cfile); 460 if (token != SLASH) { 461 parse_warn(cfile, "Slash expected."); 462 if (token != SEMI) 463 skip_to_semi(cfile); 464 return 0; 465 } 466 token = next_token(&val, NULL, cfile); 467 if (token != NUMBER) { 468 parse_warn(cfile, "Number expected."); 469 if (token != SEMI) 470 skip_to_semi(cfile); 471 return 0; 472 } 473 n = atoi(val); 474 if ((n < 0) || (n > 128)) { 475 parse_warn(cfile, "Invalid IPv6 prefix length."); 476 skip_to_semi(cfile); 477 return 0; 478 } 479 if (!is_cidr_mask_valid(addr, n)) { 480 parse_warn(cfile, "network mask too short."); 481 skip_to_semi(cfile); 482 return 0; 483 } 484 *plen = n; 485 return 1; 486 } 487 488 /* 489 * ip-address-with-subnet :== ip-address | 490 * ip-address "/" NUMBER 491 */ 492 493 int 494 parse_ip_addr_with_subnet(cfile, match) 495 struct parse *cfile; 496 struct iaddrmatch *match; 497 { 498 const char *val, *orig; 499 enum dhcp_token token; 500 int prefixlen; 501 int fflen; 502 unsigned char newval, warnmask=0; 503 504 if (parse_ip_addr(cfile, &match->addr)) { 505 /* default to host mask */ 506 prefixlen = match->addr.len * 8; 507 508 token = peek_token(&val, NULL, cfile); 509 510 if (token == SLASH) { 511 skip_token(&val, NULL, cfile); 512 token = next_token(&val, NULL, cfile); 513 514 if (token != NUMBER) { 515 parse_warn(cfile, "Invalid CIDR prefix length:" 516 " expecting a number."); 517 return 0; 518 } 519 520 prefixlen = atoi(val); 521 522 if (prefixlen < 0 || 523 prefixlen > (match->addr.len * 8)) { 524 parse_warn(cfile, "subnet prefix is out of " 525 "range [0..%d].", 526 match->addr.len * 8); 527 return 0; 528 } 529 } 530 531 /* construct a suitable mask field */ 532 533 /* copy length */ 534 match->mask.len = match->addr.len; 535 536 /* count of 0xff bytes in mask */ 537 fflen = prefixlen / 8; 538 539 /* set leading mask */ 540 memset(match->mask.iabuf, 0xff, fflen); 541 542 /* set zeroes */ 543 if (fflen < match->mask.len) { 544 match->mask.iabuf[fflen] = 545 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen % 8]; 546 547 memset(match->mask.iabuf+fflen+1, 0x00, 548 match->mask.len - fflen - 1); 549 550 /* AND-out insignificant bits from supplied netmask. */ 551 orig = piaddr(match->addr); 552 do { 553 newval = match->addr.iabuf[fflen] & 554 match->mask.iabuf[fflen]; 555 556 if (newval != match->addr.iabuf[fflen]) { 557 warnmask = 1; 558 match->addr.iabuf[fflen] = newval; 559 } 560 } while (++fflen < match->mask.len); 561 562 if (warnmask) { 563 log_error("Warning: Extraneous bits removed " 564 "in address component of %s/%d.", 565 orig, prefixlen); 566 log_error("New value: %s/%d.", 567 piaddr(match->addr), prefixlen); 568 } 569 } 570 571 return 1; 572 } 573 574 parse_warn(cfile, 575 "expecting ip-address or ip-address/prefixlen"); 576 577 return 0; /* let caller pick up pieces */ 578 } 579 580 /* 581 * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI 582 * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI | INFINIBAND 583 * Note that INFINIBAND may not be useful for some items, such as classification 584 * as the hardware address won't always be available. 585 */ 586 587 void parse_hardware_param (cfile, hardware) 588 struct parse *cfile; 589 struct hardware *hardware; 590 { 591 const char *val; 592 enum dhcp_token token; 593 unsigned hlen; 594 unsigned char *t; 595 596 token = next_token(&val, NULL, cfile); 597 switch (token) { 598 case ETHERNET: 599 hardware->hbuf[0] = HTYPE_ETHER; 600 break; 601 case TOKEN_RING: 602 hardware->hbuf[0] = HTYPE_IEEE802; 603 break; 604 case TOKEN_FDDI: 605 hardware->hbuf[0] = HTYPE_FDDI; 606 break; 607 case TOKEN_INFINIBAND: 608 hardware->hbuf[0] = HTYPE_INFINIBAND; 609 break; 610 default: 611 if (!strncmp(val, "unknown-", 8)) { 612 hardware->hbuf[0] = atoi(&val[8]); 613 } else { 614 parse_warn(cfile, 615 "expecting a network hardware type"); 616 skip_to_semi(cfile); 617 618 return; 619 } 620 } 621 622 /* Parse the hardware address information. Technically, 623 it would make a lot of sense to restrict the length of the 624 data we'll accept here to the length of a particular hardware 625 address type. Unfortunately, there are some broken clients 626 out there that put bogus data in the chaddr buffer, and we accept 627 that data in the lease file rather than simply failing on such 628 clients. Yuck. */ 629 hlen = 0; 630 token = peek_token(&val, NULL, cfile); 631 if (token == SEMI) { 632 hardware->hlen = 1; 633 goto out; 634 } 635 t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8); 636 if (t == NULL) { 637 hardware->hlen = 1; 638 return; 639 } 640 if (hlen + 1 > sizeof(hardware->hbuf)) { 641 dfree(t, MDL); 642 parse_warn(cfile, "hardware address too long"); 643 } else { 644 hardware->hlen = hlen + 1; 645 memcpy((unsigned char *)&hardware->hbuf[1], t, hlen); 646 if (hlen + 1 < sizeof(hardware->hbuf)) 647 memset(&hardware->hbuf[hlen + 1], 0, 648 (sizeof(hardware->hbuf)) - hlen - 1); 649 dfree(t, MDL); 650 } 651 652 out: 653 token = next_token(&val, NULL, cfile); 654 if (token != SEMI) { 655 parse_warn(cfile, "expecting semicolon."); 656 skip_to_semi(cfile); 657 } 658 } 659 660 /* lease-time :== NUMBER SEMI */ 661 662 void parse_lease_time (cfile, timep) 663 struct parse *cfile; 664 TIME *timep; 665 { 666 const char *val; 667 enum dhcp_token token; 668 u_int32_t num; 669 670 token = next_token (&val, (unsigned *)0, cfile); 671 if (token != NUMBER) { 672 parse_warn (cfile, "Expecting numeric lease time"); 673 skip_to_semi (cfile); 674 return; 675 } 676 convert_num(cfile, (unsigned char *)&num, val, 10, 32); 677 /* Unswap the number - convert_num returns stuff in NBO. */ 678 *timep = ntohl(num); 679 680 parse_semi (cfile); 681 } 682 683 /* No BNF for numeric aggregates - that's defined by the caller. What 684 this function does is to parse a sequence of numbers separated by 685 the token specified in separator. If max is zero, any number of 686 numbers will be parsed; otherwise, exactly max numbers are 687 expected. Base and size tell us how to internalize the numbers 688 once they've been tokenized. 689 690 buf - A pointer to space to return the parsed value, if it is null 691 then the function will allocate space for the return. 692 693 max - The maximum number of items to store. If zero there is no 694 maximum. When buf is null and the function needs to allocate space 695 it will do an allocation of max size at the beginning if max is non 696 zero. If max is zero then the allocation will be done later, after 697 the function has determined the size necessary for the incoming 698 string. 699 700 returns NULL on errors or a pointer to the value string on success. 701 The pointer will either be buf if it was non-NULL or newly allocated 702 space if buf was NULL 703 */ 704 705 706 unsigned char *parse_numeric_aggregate (cfile, buf, 707 max, separator, base, size) 708 struct parse *cfile; 709 unsigned char *buf; 710 unsigned *max; 711 int separator; 712 int base; 713 unsigned size; 714 { 715 const char *val; 716 enum dhcp_token token; 717 unsigned char *bufp = buf, *s, *t; 718 unsigned count = 0; 719 pair c = (pair)0; 720 721 if (!bufp && *max) { 722 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL); 723 if (!bufp) 724 log_fatal ("no space for numeric aggregate"); 725 } 726 s = bufp; 727 728 do { 729 if (count) { 730 token = peek_token (&val, (unsigned *)0, cfile); 731 if (token != separator) { 732 if (!*max) 733 break; 734 if (token != RBRACE && token != LBRACE) 735 token = next_token (&val, 736 (unsigned *)0, 737 cfile); 738 parse_warn (cfile, "too few numbers."); 739 if (token != SEMI) 740 skip_to_semi (cfile); 741 /* free bufp if it was allocated */ 742 if ((bufp != NULL) && (bufp != buf)) 743 dfree(bufp, MDL); 744 return (unsigned char *)0; 745 } 746 skip_token(&val, (unsigned *)0, cfile); 747 } 748 token = next_token (&val, (unsigned *)0, cfile); 749 750 if (token == END_OF_FILE) { 751 parse_warn (cfile, "unexpected end of file"); 752 break; 753 } 754 755 /* Allow NUMBER_OR_NAME if base is 16. */ 756 if (token != NUMBER && 757 (base != 16 || token != NUMBER_OR_NAME)) { 758 parse_warn (cfile, "expecting numeric value."); 759 skip_to_semi (cfile); 760 /* free bufp if it was allocated */ 761 if ((bufp != NULL) && (bufp != buf)) 762 dfree(bufp, MDL); 763 /* free any linked numbers we may have allocated */ 764 while (c) { 765 pair cdr = c->cdr; 766 dfree(c->car, MDL); 767 dfree(c, MDL); 768 c = cdr; 769 } 770 return (NULL); 771 } 772 /* If we can, convert the number now; otherwise, build 773 a linked list of all the numbers. */ 774 if (s) { 775 convert_num (cfile, s, val, base, size); 776 s += size / 8; 777 } else { 778 t = (unsigned char *)dmalloc (strlen (val) + 1, MDL); 779 if (!t) 780 log_fatal ("no temp space for number."); 781 strcpy ((char *)t, val); 782 c = cons ((caddr_t)t, c); 783 } 784 } while (++count != *max); 785 786 /* If we had to cons up a list, convert it now. */ 787 if (c) { 788 /* 789 * No need to cleanup bufp, to get here we didn't allocate 790 * bufp above 791 */ 792 bufp = (unsigned char *)dmalloc (count * size / 8, MDL); 793 if (!bufp) 794 log_fatal ("no space for numeric aggregate."); 795 s = bufp + count - size / 8; 796 *max = count; 797 } 798 while (c) { 799 pair cdr = c -> cdr; 800 convert_num (cfile, s, (char *)(c -> car), base, size); 801 s -= size / 8; 802 /* Free up temp space. */ 803 dfree (c -> car, MDL); 804 dfree (c, MDL); 805 c = cdr; 806 } 807 return bufp; 808 } 809 810 void convert_num (cfile, buf, str, base, size) 811 struct parse *cfile; 812 unsigned char *buf; 813 const char *str; 814 int base; 815 unsigned size; 816 { 817 const unsigned char *ptr = (const unsigned char *)str; 818 int negative = 0; 819 u_int32_t val = 0; 820 int tval; 821 int max; 822 823 if (*ptr == '-') { 824 negative = 1; 825 ++ptr; 826 } 827 828 /* If base wasn't specified, figure it out from the data. */ 829 if (!base) { 830 if (ptr [0] == '0') { 831 if (ptr [1] == 'x') { 832 base = 16; 833 ptr += 2; 834 } else if (isascii (ptr [1]) && isdigit (ptr [1])) { 835 base = 8; 836 ptr += 1; 837 } else { 838 base = 10; 839 } 840 } else { 841 base = 10; 842 } 843 } 844 845 do { 846 tval = *ptr++; 847 /* XXX assumes ASCII... */ 848 if (tval >= 'a') 849 tval = tval - 'a' + 10; 850 else if (tval >= 'A') 851 tval = tval - 'A' + 10; 852 else if (tval >= '0') 853 tval -= '0'; 854 else { 855 parse_warn (cfile, "Bogus number: %s.", str); 856 break; 857 } 858 if (tval >= base) { 859 parse_warn (cfile, 860 "Bogus number %s: digit %d not in base %d", 861 str, tval, base); 862 break; 863 } 864 val = val * base + tval; 865 } while (*ptr); 866 867 if (negative) 868 max = (1 << (size - 1)); 869 else 870 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1); 871 if (val > max) { 872 switch (base) { 873 case 8: 874 parse_warn (cfile, 875 "%s%lo exceeds max (%d) for precision.", 876 negative ? "-" : "", 877 (unsigned long)val, max); 878 break; 879 case 16: 880 parse_warn (cfile, 881 "%s%lx exceeds max (%d) for precision.", 882 negative ? "-" : "", 883 (unsigned long)val, max); 884 break; 885 default: 886 parse_warn (cfile, 887 "%s%lu exceeds max (%d) for precision.", 888 negative ? "-" : "", 889 (unsigned long)val, max); 890 break; 891 } 892 } 893 894 if (negative) { 895 switch (size) { 896 case 8: 897 *buf = -(unsigned long)val; 898 break; 899 case 16: 900 putShort (buf, -(long)val); 901 break; 902 case 32: 903 putLong (buf, -(long)val); 904 break; 905 default: 906 parse_warn (cfile, 907 "Unexpected integer size: %d\n", size); 908 break; 909 } 910 } else { 911 switch (size) { 912 case 8: 913 *buf = (u_int8_t)val; 914 break; 915 case 16: 916 putUShort (buf, (u_int16_t)val); 917 break; 918 case 32: 919 putULong (buf, val); 920 break; 921 default: 922 parse_warn (cfile, 923 "Unexpected integer size: %d\n", size); 924 break; 925 } 926 } 927 } 928 929 /* 930 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER 931 * NUMBER COLON NUMBER COLON NUMBER | 932 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER 933 * NUMBER COLON NUMBER COLON NUMBER NUMBER | 934 * EPOCH NUMBER | 935 * NEVER 936 * 937 * Dates are stored in UTC or with a timezone offset; first number is day 938 * of week; next is year/month/day; next is hours:minutes:seconds on a 939 * 24-hour clock, followed by the timezone offset in seconds, which is 940 * optional. 941 */ 942 943 /* 944 * just parse the date 945 * any trailing semi must be consumed by the caller of this routine 946 */ 947 TIME 948 parse_date_core(cfile) 949 struct parse *cfile; 950 { 951 int guess; 952 int tzoff, year, mon, mday, hour, min, sec; 953 const char *val; 954 enum dhcp_token token; 955 static int months[11] = { 31, 59, 90, 120, 151, 181, 956 212, 243, 273, 304, 334 }; 957 958 /* "never", "epoch" or day of week */ 959 token = peek_token(&val, NULL, cfile); 960 if (token == NEVER) { 961 skip_token(&val, NULL, cfile); /* consume NEVER */ 962 return(MAX_TIME); 963 } 964 965 /* This indicates 'local' time format. */ 966 if (token == EPOCH) { 967 skip_token(&val, NULL, cfile); /* consume EPOCH */ 968 token = peek_token(&val, NULL, cfile); 969 970 if (token != NUMBER) { 971 if (token != SEMI) 972 skip_token(&val, NULL, cfile); 973 parse_warn(cfile, "Seconds since epoch expected."); 974 return((TIME)0); 975 } 976 977 skip_token(&val, NULL, cfile); /* consume number */ 978 guess = atoi(val); 979 980 return((TIME)guess); 981 } 982 983 if (token != NUMBER) { 984 if (token != SEMI) 985 skip_token(&val, NULL, cfile); 986 parse_warn(cfile, "numeric day of week expected."); 987 return((TIME)0); 988 } 989 skip_token(&val, NULL, cfile); /* consume day of week */ 990 /* we are not using this for anything */ 991 992 /* Year... */ 993 token = peek_token(&val, NULL, cfile); 994 if (token != NUMBER) { 995 if (token != SEMI) 996 skip_token(&val, NULL, cfile); 997 parse_warn(cfile, "numeric year expected."); 998 return((TIME)0); 999 } 1000 skip_token(&val, NULL, cfile); /* consume year */ 1001 1002 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until 1003 somebody invents a time machine, I think we can safely disregard 1004 it. This actually works around a stupid Y2K bug that was present 1005 in a very early beta release of dhcpd. */ 1006 year = atoi(val); 1007 if (year > 1900) 1008 year -= 1900; 1009 1010 /* Slash separating year from month... */ 1011 token = peek_token(&val, NULL, cfile); 1012 if (token != SLASH) { 1013 if (token != SEMI) 1014 skip_token(&val, NULL, cfile); 1015 parse_warn(cfile, 1016 "expected slash separating year from month."); 1017 return((TIME)0); 1018 } 1019 skip_token(&val, NULL, cfile); /* consume SLASH */ 1020 1021 /* Month... */ 1022 token = peek_token(&val, NULL, cfile); 1023 if (token != NUMBER) { 1024 if (token != SEMI) 1025 skip_token(&val, NULL, cfile); 1026 parse_warn(cfile, "numeric month expected."); 1027 return((TIME)0); 1028 } 1029 skip_token(&val, NULL, cfile); /* consume month */ 1030 mon = atoi(val) - 1; 1031 1032 /* Slash separating month from day... */ 1033 token = peek_token(&val, NULL, cfile); 1034 if (token != SLASH) { 1035 if (token != SEMI) 1036 skip_token(&val, NULL, cfile); 1037 parse_warn(cfile, 1038 "expected slash separating month from day."); 1039 return((TIME)0); 1040 } 1041 skip_token(&val, NULL, cfile); /* consume SLASH */ 1042 1043 /* Day of month... */ 1044 token = peek_token(&val, NULL, cfile); 1045 if (token != NUMBER) { 1046 if (token != SEMI) 1047 skip_token(&val, NULL, cfile); 1048 parse_warn(cfile, "numeric day of month expected."); 1049 return((TIME)0); 1050 } 1051 skip_token(&val, NULL, cfile); /* consume day of month */ 1052 mday = atoi(val); 1053 1054 /* Hour... */ 1055 token = peek_token(&val, NULL, cfile); 1056 if (token != NUMBER) { 1057 if (token != SEMI) 1058 skip_token(&val, NULL, cfile); 1059 parse_warn(cfile, "numeric hour expected."); 1060 return((TIME)0); 1061 } 1062 skip_token(&val, NULL, cfile); /* consume hour */ 1063 hour = atoi(val); 1064 1065 /* Colon separating hour from minute... */ 1066 token = peek_token(&val, NULL, cfile); 1067 if (token != COLON) { 1068 if (token != SEMI) 1069 skip_token(&val, NULL, cfile); 1070 parse_warn(cfile, 1071 "expected colon separating hour from minute."); 1072 return((TIME)0); 1073 } 1074 skip_token(&val, NULL, cfile); /* consume colon */ 1075 1076 /* Minute... */ 1077 token = peek_token(&val, NULL, cfile); 1078 if (token != NUMBER) { 1079 if (token != SEMI) 1080 skip_token(&val, NULL, cfile); 1081 parse_warn(cfile, "numeric minute expected."); 1082 return((TIME)0); 1083 } 1084 skip_token(&val, NULL, cfile); /* consume minute */ 1085 min = atoi(val); 1086 1087 /* Colon separating minute from second... */ 1088 token = peek_token(&val, NULL, cfile); 1089 if (token != COLON) { 1090 if (token != SEMI) 1091 skip_token(&val, NULL, cfile); 1092 parse_warn(cfile, 1093 "expected colon separating minute from second."); 1094 return((TIME)0); 1095 } 1096 skip_token(&val, NULL, cfile); /* consume colon */ 1097 1098 /* Second... */ 1099 token = peek_token(&val, NULL, cfile); 1100 if (token != NUMBER) { 1101 if (token != SEMI) 1102 skip_token(&val, NULL, cfile); 1103 parse_warn(cfile, "numeric second expected."); 1104 return((TIME)0); 1105 } 1106 skip_token(&val, NULL, cfile); /* consume second */ 1107 sec = atoi(val); 1108 1109 tzoff = 0; 1110 token = peek_token(&val, NULL, cfile); 1111 if (token == NUMBER) { 1112 skip_token(&val, NULL, cfile); /* consume tzoff */ 1113 tzoff = atoi(val); 1114 } else if (token != SEMI) { 1115 skip_token(&val, NULL, cfile); 1116 parse_warn(cfile, 1117 "Time zone offset or semicolon expected."); 1118 return((TIME)0); 1119 } 1120 1121 /* If the year is 2038 or greater return the max time to avoid 1122 * overflow issues. We could try and be more precise but there 1123 * doesn't seem to be a good reason to worry about it and waste 1124 * the cpu looking at the rest of the date. */ 1125 if (year >= 138) 1126 return(MAX_TIME); 1127 1128 /* Guess the time value... */ 1129 guess = ((((((365 * (year - 70) + /* Days in years since '70 */ 1130 (year - 69) / 4 + /* Leap days since '70 */ 1131 (mon /* Days in months this year */ 1132 ? months [mon - 1] 1133 : 0) + 1134 (mon > 1 && /* Leap day this year */ 1135 !((year - 72) & 3)) + 1136 mday - 1) * 24) + /* Day of month */ 1137 hour) * 60) + 1138 min) * 60) + sec + tzoff; 1139 1140 /* This guess could be wrong because of leap seconds or other 1141 weirdness we don't know about that the system does. For 1142 now, we're just going to accept the guess, but at some point 1143 it might be nice to do a successive approximation here to 1144 get an exact value. Even if the error is small, if the 1145 server is restarted frequently (and thus the lease database 1146 is reread), the error could accumulate into something 1147 significant. */ 1148 1149 return((TIME)guess); 1150 } 1151 1152 /* 1153 * Wrapper to consume the semicolon after the date 1154 * :== date semi 1155 */ 1156 1157 TIME 1158 parse_date(cfile) 1159 struct parse *cfile; 1160 { 1161 TIME guess; 1162 guess = parse_date_core(cfile); 1163 1164 /* Make sure the date ends in a semicolon... */ 1165 if (!parse_semi(cfile)) 1166 return((TIME)0); 1167 return(guess); 1168 } 1169 1170 1171 1172 /* 1173 * option-name :== IDENTIFIER | 1174 IDENTIFIER . IDENTIFIER 1175 */ 1176 1177 isc_result_t 1178 parse_option_name (cfile, allocate, known, opt) 1179 struct parse *cfile; 1180 int allocate; 1181 int *known; 1182 struct option **opt; 1183 { 1184 const char *val; 1185 enum dhcp_token token; 1186 char *uname; 1187 struct universe *universe; 1188 struct option *option; 1189 unsigned code; 1190 1191 if (opt == NULL) 1192 return DHCP_R_INVALIDARG; 1193 1194 token = next_token (&val, (unsigned *)0, cfile); 1195 if (!is_identifier (token)) { 1196 parse_warn (cfile, 1197 "expecting identifier after option keyword."); 1198 if (token != SEMI) 1199 skip_to_semi (cfile); 1200 return DHCP_R_BADPARSE; 1201 } 1202 uname = dmalloc (strlen (val) + 1, MDL); 1203 if (!uname) 1204 log_fatal ("no memory for uname information."); 1205 strcpy (uname, val); 1206 token = peek_token (&val, (unsigned *)0, cfile); 1207 if (token == DOT) { 1208 /* Go ahead and take the DOT token... */ 1209 skip_token(&val, (unsigned *)0, cfile); 1210 1211 /* The next token should be an identifier... */ 1212 token = next_token (&val, (unsigned *)0, cfile); 1213 if (!is_identifier (token)) { 1214 parse_warn (cfile, "expecting identifier after '.'"); 1215 if (token != SEMI) 1216 skip_to_semi (cfile); 1217 return DHCP_R_BADPARSE; 1218 } 1219 1220 /* Look up the option name hash table for the specified 1221 uname. */ 1222 universe = (struct universe *)0; 1223 if (!universe_hash_lookup (&universe, universe_hash, 1224 uname, 0, MDL)) { 1225 parse_warn (cfile, "no option space named %s.", uname); 1226 skip_to_semi (cfile); 1227 return ISC_R_NOTFOUND; 1228 } 1229 } else { 1230 /* Use the default hash table, which contains all the 1231 standard dhcp option names. */ 1232 val = uname; 1233 universe = &dhcp_universe; 1234 } 1235 1236 /* Look up the actual option info... */ 1237 option_name_hash_lookup(opt, universe->name_hash, val, 0, MDL); 1238 option = *opt; 1239 1240 /* If we didn't get an option structure, it's an undefined option. */ 1241 if (option) { 1242 if (known) 1243 *known = 1; 1244 /* If the option name is of the form unknown-[decimal], use 1245 * the trailing decimal value to find the option definition. 1246 * If there is no definition, construct one. This is to 1247 * support legacy use of unknown options in config files or 1248 * lease databases. 1249 */ 1250 } else if (strncasecmp(val, "unknown-", 8) == 0) { 1251 code = atoi(val+8); 1252 1253 /* Option code 0 is always illegal for us, thanks 1254 * to the option decoder. 1255 */ 1256 if (code == 0 || code == universe->end) { 1257 parse_warn(cfile, "Option codes 0 and %u are illegal " 1258 "in the %s space.", universe->end, 1259 universe->name); 1260 skip_to_semi(cfile); 1261 dfree(uname, MDL); 1262 return ISC_R_FAILURE; 1263 } 1264 1265 /* It's odd to think of unknown option codes as 1266 * being known, but this means we know what the 1267 * parsed name is talking about. 1268 */ 1269 if (known) 1270 *known = 1; 1271 1272 option_code_hash_lookup(opt, universe->code_hash, 1273 &code, 0, MDL); 1274 option = *opt; 1275 1276 /* If we did not find an option of that code, 1277 * manufacture an unknown-xxx option definition. 1278 * Its single reference will ensure that it is 1279 * deleted once the option is recycled out of 1280 * existence (by the parent). 1281 */ 1282 if (option == NULL) { 1283 option = new_option(val, MDL); 1284 option->universe = universe; 1285 option->code = code; 1286 option->format = default_option_format; 1287 option_reference(opt, option, MDL); 1288 } else 1289 log_info("option %s has been redefined as option %s. " 1290 "Please update your configs if necessary.", 1291 val, option->name); 1292 /* If we've been told to allocate, that means that this 1293 * (might) be an option code definition, so we'll create 1294 * an option structure and return it for the parent to 1295 * decide. 1296 */ 1297 } else if (allocate) { 1298 option = new_option(val, MDL); 1299 option -> universe = universe; 1300 option_reference(opt, option, MDL); 1301 } else { 1302 parse_warn(cfile, "no option named %s in space %s", 1303 val, universe->name); 1304 skip_to_semi (cfile); 1305 dfree(uname, MDL); 1306 return ISC_R_NOTFOUND; 1307 } 1308 1309 /* Free the initial identifier token. */ 1310 dfree (uname, MDL); 1311 return ISC_R_SUCCESS; 1312 } 1313 1314 /* IDENTIFIER [WIDTHS] SEMI 1315 * WIDTHS ~= LENGTH WIDTH NUMBER 1316 * CODE WIDTH NUMBER 1317 */ 1318 1319 void parse_option_space_decl (cfile) 1320 struct parse *cfile; 1321 { 1322 int token; 1323 const char *val; 1324 struct universe **ua, *nu; 1325 char *nu_name; 1326 int tsize=1, lsize=1, hsize = 0; 1327 1328 skip_token(&val, (unsigned *)0, cfile); /* Discard the SPACE token, 1329 which was checked by the 1330 caller. */ 1331 token = next_token (&val, (unsigned *)0, cfile); 1332 if (!is_identifier (token)) { 1333 parse_warn (cfile, "expecting identifier."); 1334 skip_to_semi (cfile); 1335 return; 1336 } 1337 nu = new_universe (MDL); 1338 if (!nu) 1339 log_fatal ("No memory for new option space."); 1340 1341 /* Set up the server option universe... */ 1342 nu_name = dmalloc (strlen (val) + 1, MDL); 1343 if (!nu_name) 1344 log_fatal ("No memory for new option space name."); 1345 strcpy (nu_name, val); 1346 nu -> name = nu_name; 1347 1348 do { 1349 token = next_token(&val, NULL, cfile); 1350 switch(token) { 1351 case SEMI: 1352 break; 1353 1354 case CODE: 1355 token = next_token(&val, NULL, cfile); 1356 if (token != WIDTH) { 1357 parse_warn(cfile, "expecting width token."); 1358 goto bad; 1359 } 1360 1361 token = next_token(&val, NULL, cfile); 1362 if (token != NUMBER) { 1363 parse_warn(cfile, "expecting number 1, 2, 4."); 1364 goto bad; 1365 } 1366 1367 tsize = atoi(val); 1368 1369 1370 switch (tsize) { 1371 case 1: 1372 if (!hsize) 1373 hsize = BYTE_NAME_HASH_SIZE; 1374 break; 1375 case 2: 1376 if (!hsize) 1377 hsize = WORD_NAME_HASH_SIZE; 1378 break; 1379 case 4: 1380 if (!hsize) 1381 hsize = QUAD_NAME_HASH_SIZE; 1382 break; 1383 default: 1384 parse_warn(cfile, "invalid code width (%d), " 1385 "expecting a 1, 2 or 4.", 1386 tsize); 1387 goto bad; 1388 } 1389 break; 1390 1391 case LENGTH: 1392 token = next_token(&val, NULL, cfile); 1393 if (token != WIDTH) { 1394 parse_warn(cfile, "expecting width token."); 1395 goto bad; 1396 } 1397 1398 token = next_token(&val, NULL, cfile); 1399 if (token != NUMBER) { 1400 parse_warn(cfile, "expecting number 1 or 2."); 1401 goto bad; 1402 } 1403 1404 lsize = atoi(val); 1405 if (lsize != 1 && lsize != 2) { 1406 parse_warn(cfile, "invalid length width (%d) " 1407 "expecting 1 or 2.", lsize); 1408 goto bad; 1409 } 1410 1411 break; 1412 1413 case HASH: 1414 token = next_token(&val, NULL, cfile); 1415 if (token != SIZE) { 1416 parse_warn(cfile, "expecting size token."); 1417 goto bad; 1418 } 1419 1420 token = next_token(&val, NULL, cfile); 1421 if (token != NUMBER) { 1422 parse_warn(cfile, "expecting a 10base number"); 1423 goto bad; 1424 } 1425 1426 /* (2^31)-1 is the highest Mersenne prime we should 1427 * probably allow... 1428 */ 1429 hsize = atoi(val); 1430 if (hsize < 0 || hsize > 0x7FFFFFFF) { 1431 parse_warn(cfile, "invalid hash length: %d", 1432 hsize); 1433 goto bad; 1434 } 1435 1436 break; 1437 1438 default: 1439 parse_warn(cfile, "Unexpected token."); 1440 } 1441 } while (token != SEMI); 1442 1443 if (!hsize) 1444 hsize = DEFAULT_SPACE_HASH_SIZE; 1445 1446 nu -> lookup_func = lookup_hashed_option; 1447 nu -> option_state_dereference = hashed_option_state_dereference; 1448 nu -> foreach = hashed_option_space_foreach; 1449 nu -> save_func = save_hashed_option; 1450 nu -> delete_func = delete_hashed_option; 1451 nu -> encapsulate = hashed_option_space_encapsulate; 1452 nu -> decode = parse_option_buffer; 1453 nu -> length_size = lsize; 1454 nu -> tag_size = tsize; 1455 switch(tsize) { 1456 case 1: 1457 nu->get_tag = getUChar; 1458 nu->store_tag = putUChar; 1459 break; 1460 case 2: 1461 nu->get_tag = getUShort; 1462 nu->store_tag = putUShort; 1463 break; 1464 case 4: 1465 nu->get_tag = getULong; 1466 nu->store_tag = putULong; 1467 break; 1468 default: 1469 log_fatal("Impossible condition at %s:%d.", MDL); 1470 } 1471 switch(lsize) { 1472 case 0: 1473 nu->get_length = NULL; 1474 nu->store_length = NULL; 1475 break; 1476 case 1: 1477 nu->get_length = getUChar; 1478 nu->store_length = putUChar; 1479 break; 1480 case 2: 1481 nu->get_length = getUShort; 1482 nu->store_length = putUShort; 1483 break; 1484 default: 1485 log_fatal("Impossible condition at %s:%d.", MDL); 1486 } 1487 nu -> index = universe_count++; 1488 if (nu -> index >= universe_max) { 1489 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL); 1490 if (!ua) 1491 log_fatal ("No memory to expand option space array."); 1492 memcpy (ua, universes, universe_max * sizeof *ua); 1493 universe_max *= 2; 1494 dfree (universes, MDL); 1495 universes = ua; 1496 } 1497 universes [nu -> index] = nu; 1498 if (!option_name_new_hash(&nu->name_hash, hsize, MDL) || 1499 !option_code_new_hash(&nu->code_hash, hsize, MDL)) 1500 log_fatal("Can't allocate %s option hash table.", nu->name); 1501 universe_hash_add (universe_hash, nu -> name, 0, nu, MDL); 1502 return; 1503 1504 bad: 1505 dfree(nu_name, MDL); 1506 dfree(nu, MDL); 1507 } 1508 1509 /* This is faked up to look good right now. Ideally, this should do a 1510 recursive parse and allow arbitrary data structure definitions, but for 1511 now it just allows you to specify a single type, an array of single types, 1512 a sequence of types, or an array of sequences of types. 1513 1514 ocd :== NUMBER EQUALS ocsd SEMI 1515 1516 ocsd :== ocsd_type | 1517 ocsd_type_sequence | 1518 ARRAY OF ocsd_simple_type_sequence 1519 1520 ocsd_type_sequence :== LBRACE ocsd_types RBRACE 1521 1522 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE 1523 1524 ocsd_types :== ocsd_type | 1525 ocsd_types ocsd_type 1526 1527 ocsd_type :== ocsd_simple_type | 1528 ARRAY OF ocsd_simple_type 1529 1530 ocsd_simple_types :== ocsd_simple_type | 1531 ocsd_simple_types ocsd_simple_type 1532 1533 ocsd_simple_type :== BOOLEAN | 1534 INTEGER NUMBER | 1535 SIGNED INTEGER NUMBER | 1536 UNSIGNED INTEGER NUMBER | 1537 IP-ADDRESS | 1538 TEXT | 1539 STRING | 1540 ENCAPSULATE identifier */ 1541 1542 int parse_option_code_definition (cfile, option) 1543 struct parse *cfile; 1544 struct option *option; 1545 { 1546 const char *val; 1547 enum dhcp_token token; 1548 struct option *oldopt; 1549 unsigned arrayp = 0; 1550 int recordp = 0; 1551 int no_more_in_record = 0; 1552 char tokbuf [128]; 1553 unsigned tokix = 0; 1554 char type; 1555 int is_signed; 1556 char *s; 1557 int has_encapsulation = 0; 1558 struct universe *encapsulated; 1559 1560 /* Parse the option code. */ 1561 token = next_token (&val, (unsigned *)0, cfile); 1562 if (token != NUMBER) { 1563 parse_warn (cfile, "expecting option code number."); 1564 skip_to_semi (cfile); 1565 return 0; 1566 } 1567 option -> code = atoi (val); 1568 1569 token = next_token (&val, (unsigned *)0, cfile); 1570 if (token != EQUAL) { 1571 parse_warn (cfile, "expecting \"=\""); 1572 skip_to_semi (cfile); 1573 return 0; 1574 } 1575 1576 /* See if this is an array. */ 1577 token = next_token (&val, (unsigned *)0, cfile); 1578 if (token == ARRAY) { 1579 token = next_token (&val, (unsigned *)0, cfile); 1580 if (token != OF) { 1581 parse_warn (cfile, "expecting \"of\"."); 1582 skip_to_semi (cfile); 1583 return 0; 1584 } 1585 arrayp = 1; 1586 token = next_token (&val, (unsigned *)0, cfile); 1587 } 1588 1589 if (token == LBRACE) { 1590 recordp = 1; 1591 token = next_token (&val, (unsigned *)0, cfile); 1592 } 1593 1594 /* At this point we're expecting a data type. */ 1595 next_type: 1596 if (has_encapsulation) { 1597 parse_warn (cfile, 1598 "encapsulate must always be the last item."); 1599 skip_to_semi (cfile); 1600 return 0; 1601 } 1602 1603 switch (token) { 1604 case ARRAY: 1605 if (arrayp) { 1606 parse_warn (cfile, "no nested arrays."); 1607 skip_to_rbrace (cfile, recordp); 1608 if (recordp) 1609 skip_to_semi (cfile); 1610 return 0; 1611 } 1612 token = next_token (&val, (unsigned *)0, cfile); 1613 if (token != OF) { 1614 parse_warn (cfile, "expecting \"of\"."); 1615 skip_to_semi (cfile); 1616 return 0; 1617 } 1618 arrayp = recordp + 1; 1619 token = next_token (&val, (unsigned *)0, cfile); 1620 if ((recordp) && (token == LBRACE)) { 1621 parse_warn (cfile, 1622 "only uniform array inside record."); 1623 skip_to_rbrace (cfile, recordp + 1); 1624 skip_to_semi (cfile); 1625 return 0; 1626 } 1627 goto next_type; 1628 case BOOLEAN: 1629 type = 'f'; 1630 break; 1631 case INTEGER: 1632 is_signed = 1; 1633 parse_integer: 1634 token = next_token (&val, (unsigned *)0, cfile); 1635 if (token != NUMBER) { 1636 parse_warn (cfile, "expecting number."); 1637 skip_to_rbrace (cfile, recordp); 1638 if (recordp) 1639 skip_to_semi (cfile); 1640 return 0; 1641 } 1642 switch (atoi (val)) { 1643 case 8: 1644 type = is_signed ? 'b' : 'B'; 1645 break; 1646 case 16: 1647 type = is_signed ? 's' : 'S'; 1648 break; 1649 case 32: 1650 type = is_signed ? 'l' : 'L'; 1651 break; 1652 default: 1653 parse_warn (cfile, 1654 "%s bit precision is not supported.", val); 1655 skip_to_rbrace (cfile, recordp); 1656 if (recordp) 1657 skip_to_semi (cfile); 1658 return 0; 1659 } 1660 break; 1661 case SIGNED: 1662 is_signed = 1; 1663 parse_signed: 1664 token = next_token (&val, (unsigned *)0, cfile); 1665 if (token != INTEGER) { 1666 parse_warn (cfile, "expecting \"integer\" keyword."); 1667 skip_to_rbrace (cfile, recordp); 1668 if (recordp) 1669 skip_to_semi (cfile); 1670 return 0; 1671 } 1672 goto parse_integer; 1673 case UNSIGNED: 1674 is_signed = 0; 1675 goto parse_signed; 1676 1677 case IP_ADDRESS: 1678 type = 'I'; 1679 break; 1680 case IP6_ADDRESS: 1681 type = '6'; 1682 break; 1683 case DOMAIN_NAME: 1684 type = 'd'; 1685 goto no_arrays; 1686 case DOMAIN_LIST: 1687 /* Consume optional compression indicator. */ 1688 token = peek_token(&val, NULL, cfile); 1689 if (token == COMPRESSED) { 1690 skip_token(&val, NULL, cfile); 1691 tokbuf[tokix++] = 'D'; 1692 type = 'c'; 1693 } else 1694 type = 'D'; 1695 goto no_arrays; 1696 case TEXT: 1697 type = 't'; 1698 no_arrays: 1699 if (arrayp) { 1700 parse_warn (cfile, "arrays of text strings not %s", 1701 "yet supported."); 1702 skip_to_rbrace (cfile, recordp); 1703 if (recordp) 1704 skip_to_semi (cfile); 1705 return 0; 1706 } 1707 no_more_in_record = 1; 1708 break; 1709 case STRING_TOKEN: 1710 type = 'X'; 1711 goto no_arrays; 1712 1713 case ENCAPSULATE: 1714 token = next_token (&val, (unsigned *)0, cfile); 1715 if (!is_identifier (token)) { 1716 parse_warn (cfile, 1717 "expecting option space identifier"); 1718 skip_to_semi (cfile); 1719 return 0; 1720 } 1721 encapsulated = NULL; 1722 if (!universe_hash_lookup(&encapsulated, universe_hash, 1723 val, strlen(val), MDL)) { 1724 parse_warn(cfile, "unknown option space %s", val); 1725 skip_to_semi (cfile); 1726 return 0; 1727 } 1728 if (strlen (val) + tokix + 2 > sizeof (tokbuf)) 1729 goto toobig; 1730 tokbuf [tokix++] = 'E'; 1731 strcpy (&tokbuf [tokix], val); 1732 tokix += strlen (val); 1733 type = '.'; 1734 has_encapsulation = 1; 1735 break; 1736 1737 case ZEROLEN: 1738 type = 'Z'; 1739 if (arrayp) { 1740 parse_warn (cfile, "array incompatible with zerolen."); 1741 skip_to_rbrace (cfile, recordp); 1742 if (recordp) 1743 skip_to_semi (cfile); 1744 return 0; 1745 } 1746 no_more_in_record = 1; 1747 break; 1748 1749 default: 1750 parse_warn (cfile, "unknown data type %s", val); 1751 skip_to_rbrace (cfile, recordp); 1752 if (recordp) 1753 skip_to_semi (cfile); 1754 return 0; 1755 } 1756 1757 if (tokix == sizeof tokbuf) { 1758 toobig: 1759 parse_warn (cfile, "too many types in record."); 1760 skip_to_rbrace (cfile, recordp); 1761 if (recordp) 1762 skip_to_semi (cfile); 1763 return 0; 1764 } 1765 tokbuf [tokix++] = type; 1766 1767 if (recordp) { 1768 token = next_token (&val, (unsigned *)0, cfile); 1769 if (arrayp > recordp) { 1770 if (tokix == sizeof tokbuf) { 1771 parse_warn (cfile, 1772 "too many types in record."); 1773 skip_to_rbrace (cfile, 1); 1774 skip_to_semi (cfile); 1775 return 0; 1776 } 1777 arrayp = 0; 1778 tokbuf[tokix++] = 'a'; 1779 } 1780 if (token == COMMA) { 1781 if (no_more_in_record) { 1782 parse_warn (cfile, 1783 "%s must be at end of record.", 1784 type == 't' ? "text" : "string"); 1785 skip_to_rbrace (cfile, 1); 1786 if (recordp) 1787 skip_to_semi (cfile); 1788 return 0; 1789 } 1790 token = next_token (&val, (unsigned *)0, cfile); 1791 goto next_type; 1792 } 1793 if (token != RBRACE) { 1794 parse_warn (cfile, "expecting right brace."); 1795 skip_to_rbrace (cfile, 1); 1796 if (recordp) 1797 skip_to_semi (cfile); 1798 return 0; 1799 } 1800 } 1801 if (!parse_semi (cfile)) { 1802 parse_warn (cfile, "semicolon expected."); 1803 skip_to_semi (cfile); 1804 if (recordp) 1805 skip_to_semi (cfile); 1806 return 0; 1807 } 1808 if (has_encapsulation && arrayp) { 1809 parse_warn (cfile, 1810 "Arrays of encapsulations don't make sense."); 1811 return 0; 1812 } 1813 s = dmalloc(tokix + (arrayp ? 1 : 0) + 1, MDL); 1814 if (s == NULL) { 1815 log_fatal("no memory for option format."); 1816 } 1817 memcpy(s, tokbuf, tokix); 1818 if (arrayp) { 1819 s[tokix++] = (arrayp > recordp) ? 'a' : 'A'; 1820 } 1821 s[tokix] = '\0'; 1822 1823 option -> format = s; 1824 1825 oldopt = NULL; 1826 option_code_hash_lookup(&oldopt, option->universe->code_hash, 1827 &option->code, 0, MDL); 1828 if (oldopt != NULL) { 1829 /* 1830 * XXX: This illegalizes a configuration syntax that was 1831 * valid in 3.0.x, where multiple name->code mappings are 1832 * given, but only one code->name mapping survives. It is 1833 * unclear what can or should be done at this point, but it 1834 * seems best to retain 3.0.x behaviour for upgrades to go 1835 * smoothly. 1836 * 1837 option_name_hash_delete(option->universe->name_hash, 1838 oldopt->name, 0, MDL); 1839 */ 1840 option_code_hash_delete(option->universe->code_hash, 1841 &oldopt->code, 0, MDL); 1842 1843 option_dereference(&oldopt, MDL); 1844 } 1845 option_code_hash_add(option->universe->code_hash, &option->code, 0, 1846 option, MDL); 1847 option_name_hash_add(option->universe->name_hash, option->name, 0, 1848 option, MDL); 1849 if (has_encapsulation) { 1850 /* INSIST(tokbuf[0] == 'E'); */ 1851 /* INSIST(encapsulated != NULL); */ 1852 if (!option_code_hash_lookup(&encapsulated->enc_opt, 1853 option->universe->code_hash, 1854 &option->code, 0, MDL)) { 1855 log_fatal("error finding encapsulated option (%s:%d)", 1856 MDL); 1857 } 1858 } 1859 return 1; 1860 } 1861 1862 /* 1863 * base64 :== NUMBER_OR_STRING 1864 */ 1865 1866 int parse_base64 (data, cfile) 1867 struct data_string *data; 1868 struct parse *cfile; 1869 { 1870 const char *val; 1871 int i, j, k; 1872 unsigned acc = 0; 1873 static unsigned char 1874 from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */ 1875 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */ 1876 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */ 1877 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */ 1878 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */ 1879 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */ 1880 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */ 1881 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */ 1882 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */ 1883 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */ 1884 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */ 1885 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */ 1886 struct string_list *bufs = NULL, 1887 *last = NULL, 1888 *t; 1889 int cc = 0; 1890 int terminated = 0; 1891 int valid_base64; 1892 1893 /* It's possible for a + or a / to cause a base64 quantity to be 1894 tokenized into more than one token, so we have to parse them all 1895 in before decoding. */ 1896 do { 1897 unsigned l; 1898 1899 (void)next_token(&val, &l, cfile); 1900 t = dmalloc(l + sizeof(*t), MDL); 1901 if (t == NULL) 1902 log_fatal("no memory for base64 buffer."); 1903 memset(t, 0, (sizeof(*t)) - 1); 1904 memcpy(t->string, val, l + 1); 1905 cc += l; 1906 if (last) 1907 last->next = t; 1908 else 1909 bufs = t; 1910 last = t; 1911 (void)peek_token(&val, NULL, cfile); 1912 valid_base64 = 1; 1913 for (i = 0; val[i]; i++) { 1914 /* Check to see if the character is valid. It 1915 may be out of range or within the right range 1916 but not used in the mapping */ 1917 if (((val[i] < ' ') || (val[i] > 'z')) || 1918 ((from64[val[i] - ' '] > 63) && (val[i] != '='))) { 1919 valid_base64 = 0; 1920 break; /* no need to continue for loop */ 1921 } 1922 } 1923 } while (valid_base64); 1924 1925 data->len = cc; 1926 data->len = (data->len * 3) / 4; 1927 if (!buffer_allocate(&data->buffer, data->len, MDL)) { 1928 parse_warn (cfile, "can't allocate buffer for base64 data."); 1929 data->len = 0; 1930 data->data = NULL; 1931 goto out; 1932 } 1933 1934 j = k = 0; 1935 for (t = bufs; t; t = t->next) { 1936 for (i = 0; t->string[i]; i++) { 1937 unsigned foo = t->string[i]; 1938 if (terminated && foo != '=') { 1939 parse_warn(cfile, 1940 "stuff after base64 '=' terminator: %s.", 1941 &t->string[i]); 1942 goto bad; 1943 } 1944 if ((foo < ' ') || (foo > 'z')) { 1945 bad64: 1946 parse_warn(cfile, 1947 "invalid base64 character %d.", 1948 t->string[i]); 1949 bad: 1950 data_string_forget(data, MDL); 1951 goto out; 1952 } 1953 if (foo == '=') 1954 terminated = 1; 1955 else { 1956 foo = from64[foo - ' ']; 1957 if (foo == 64) 1958 goto bad64; 1959 acc = (acc << 6) + foo; 1960 switch (k % 4) { 1961 case 0: 1962 break; 1963 case 1: 1964 data->buffer->data[j++] = (acc >> 4); 1965 acc = acc & 0x0f; 1966 break; 1967 1968 case 2: 1969 data->buffer->data[j++] = (acc >> 2); 1970 acc = acc & 0x03; 1971 break; 1972 case 3: 1973 data->buffer->data[j++] = acc; 1974 acc = 0; 1975 break; 1976 } 1977 } 1978 k++; 1979 } 1980 } 1981 if (k % 4) { 1982 if (acc) { 1983 parse_warn(cfile, 1984 "partial base64 value left over: %d.", 1985 acc); 1986 } 1987 } 1988 data->len = j; 1989 data->data = data->buffer->data; 1990 out: 1991 for (t = bufs; t; t = last) { 1992 last = t->next; 1993 dfree(t, MDL); 1994 } 1995 if (data->len) 1996 return 1; 1997 else 1998 return 0; 1999 } 2000 2001 2002 /* 2003 * colon-separated-hex-list :== NUMBER | 2004 * NUMBER COLON colon-separated-hex-list 2005 */ 2006 2007 int parse_cshl (data, cfile) 2008 struct data_string *data; 2009 struct parse *cfile; 2010 { 2011 u_int8_t ibuf [128]; 2012 unsigned ilen = 0; 2013 unsigned tlen = 0; 2014 struct option_tag *sl = (struct option_tag *)0; 2015 struct option_tag *next, **last = &sl; 2016 enum dhcp_token token; 2017 const char *val; 2018 unsigned char *rvp; 2019 2020 do { 2021 token = next_token (&val, (unsigned *)0, cfile); 2022 if (token != NUMBER && token != NUMBER_OR_NAME) { 2023 parse_warn (cfile, "expecting hexadecimal number."); 2024 skip_to_semi (cfile); 2025 for (; sl; sl = next) { 2026 next = sl -> next; 2027 dfree (sl, MDL); 2028 } 2029 return 0; 2030 } 2031 if (ilen == sizeof ibuf) { 2032 next = (struct option_tag *) 2033 dmalloc (ilen - 1 + 2034 sizeof (struct option_tag), MDL); 2035 if (!next) 2036 log_fatal ("no memory for string list."); 2037 memcpy (next -> data, ibuf, ilen); 2038 *last = next; 2039 last = &next -> next; 2040 tlen += ilen; 2041 ilen = 0; 2042 } 2043 convert_num (cfile, &ibuf [ilen++], val, 16, 8); 2044 2045 token = peek_token (&val, (unsigned *)0, cfile); 2046 if (token != COLON) 2047 break; 2048 skip_token(&val, (unsigned *)0, cfile); 2049 } while (1); 2050 2051 if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL)) 2052 log_fatal ("no memory to store octet data."); 2053 data -> data = &data -> buffer -> data [0]; 2054 data -> len = tlen + ilen; 2055 data -> terminated = 0; 2056 2057 rvp = &data -> buffer -> data [0]; 2058 while (sl) { 2059 next = sl -> next; 2060 memcpy (rvp, sl -> data, sizeof ibuf); 2061 rvp += sizeof ibuf; 2062 dfree (sl, MDL); 2063 sl = next; 2064 } 2065 2066 memcpy (rvp, ibuf, ilen); 2067 return 1; 2068 } 2069 2070 /* 2071 * executable-statements :== executable-statement executable-statements | 2072 * executable-statement 2073 * 2074 * executable-statement :== 2075 * IF if-statement | 2076 * ADD class-name SEMI | 2077 * BREAK SEMI | 2078 * OPTION option-parameter SEMI | 2079 * SUPERSEDE option-parameter SEMI | 2080 * PREPEND option-parameter SEMI | 2081 * APPEND option-parameter SEMI 2082 */ 2083 2084 int parse_executable_statements (statements, cfile, lose, case_context) 2085 struct executable_statement **statements; 2086 struct parse *cfile; 2087 int *lose; 2088 enum expression_context case_context; 2089 { 2090 struct executable_statement **next; 2091 2092 next = statements; 2093 while (parse_executable_statement (next, cfile, lose, case_context)) 2094 next = &((*next) -> next); 2095 if (!*lose) 2096 return 1; 2097 return 0; 2098 } 2099 2100 int parse_executable_statement (result, cfile, lose, case_context) 2101 struct executable_statement **result; 2102 struct parse *cfile; 2103 int *lose; 2104 enum expression_context case_context; 2105 { 2106 #if defined(ENABLE_EXECUTE) 2107 unsigned len; 2108 struct expression **ep; 2109 #endif 2110 enum dhcp_token token; 2111 const char *val; 2112 struct class *cta; 2113 struct option *option=NULL; 2114 struct option_cache *cache; 2115 int known; 2116 int flag; 2117 int i; 2118 struct dns_zone *zone; 2119 isc_result_t status; 2120 char *s; 2121 2122 token = peek_token (&val, (unsigned *)0, cfile); 2123 switch (token) { 2124 case DB_TIME_FORMAT: 2125 skip_token(&val, NULL, cfile); 2126 token = next_token(&val, NULL, cfile); 2127 if (token == DEFAULT) { 2128 db_time_format = DEFAULT_TIME_FORMAT; 2129 } else if (token == LOCAL) { 2130 db_time_format = LOCAL_TIME_FORMAT; 2131 } else { 2132 parse_warn(cfile, "Expecting 'local' or 'default'."); 2133 if (token != SEMI) 2134 skip_to_semi(cfile); 2135 *lose = 1; 2136 return 0; 2137 } 2138 2139 token = next_token(&val, NULL, cfile); 2140 if (token != SEMI) { 2141 parse_warn(cfile, "Expecting a semicolon."); 2142 *lose = 1; 2143 return 0; 2144 } 2145 2146 /* We're done here. */ 2147 return 1; 2148 2149 case IF: 2150 skip_token(&val, (unsigned *)0, cfile); 2151 return parse_if_statement (result, cfile, lose); 2152 2153 case TOKEN_ADD: 2154 skip_token(&val, (unsigned *)0, cfile); 2155 token = next_token (&val, (unsigned *)0, cfile); 2156 if (token != STRING) { 2157 parse_warn (cfile, "expecting class name."); 2158 skip_to_semi (cfile); 2159 *lose = 1; 2160 return 0; 2161 } 2162 cta = (struct class *)0; 2163 status = libdhcp_callbacks.find_class (&cta, val, MDL); 2164 if (status != ISC_R_SUCCESS) { 2165 parse_warn (cfile, "class %s: %s", 2166 val, isc_result_totext (status)); 2167 skip_to_semi (cfile); 2168 *lose = 1; 2169 return 0; 2170 } 2171 if (!parse_semi (cfile)) { 2172 *lose = 1; 2173 return 0; 2174 } 2175 if (!executable_statement_allocate (result, MDL)) 2176 log_fatal ("no memory for new statement."); 2177 (*result) -> op = add_statement; 2178 (*result) -> data.add = cta; 2179 break; 2180 2181 case BREAK: 2182 skip_token(&val, (unsigned *)0, cfile); 2183 if (!parse_semi (cfile)) { 2184 *lose = 1; 2185 return 0; 2186 } 2187 if (!executable_statement_allocate (result, MDL)) 2188 log_fatal ("no memory for new statement."); 2189 (*result) -> op = break_statement; 2190 break; 2191 2192 case SEND: 2193 skip_token(&val, (unsigned *)0, cfile); 2194 known = 0; 2195 status = parse_option_name (cfile, 0, &known, &option); 2196 if (status != ISC_R_SUCCESS || option == NULL) { 2197 *lose = 1; 2198 return 0; 2199 } 2200 status = parse_option_statement(result, cfile, 1, option, 2201 send_option_statement); 2202 option_dereference(&option, MDL); 2203 return status; 2204 2205 case SUPERSEDE: 2206 case OPTION: 2207 skip_token(&val, (unsigned *)0, cfile); 2208 known = 0; 2209 status = parse_option_name (cfile, 0, &known, &option); 2210 if (status != ISC_R_SUCCESS || option == NULL) { 2211 *lose = 1; 2212 return 0; 2213 } 2214 status = parse_option_statement(result, cfile, 1, option, 2215 supersede_option_statement); 2216 option_dereference(&option, MDL); 2217 return status; 2218 2219 case ALLOW: 2220 flag = 1; 2221 goto pad; 2222 case DENY: 2223 flag = 0; 2224 goto pad; 2225 case IGNORE: 2226 flag = 2; 2227 pad: 2228 skip_token(&val, (unsigned *)0, cfile); 2229 cache = (struct option_cache *)0; 2230 if (!libdhcp_callbacks.parse_allow_deny (&cache, cfile, flag)) 2231 return 0; 2232 if (!executable_statement_allocate (result, MDL)) 2233 log_fatal ("no memory for new statement."); 2234 (*result) -> op = supersede_option_statement; 2235 (*result) -> data.option = cache; 2236 break; 2237 2238 case DEFAULT: 2239 skip_token(&val, (unsigned *)0, cfile); 2240 token = peek_token (&val, (unsigned *)0, cfile); 2241 if (token == COLON) 2242 goto switch_default; 2243 known = 0; 2244 status = parse_option_name (cfile, 0, &known, &option); 2245 if (status != ISC_R_SUCCESS || option == NULL) { 2246 *lose = 1; 2247 return 0; 2248 } 2249 status = parse_option_statement(result, cfile, 1, option, 2250 default_option_statement); 2251 option_dereference(&option, MDL); 2252 return status; 2253 2254 case PREPEND: 2255 skip_token(&val, (unsigned *)0, cfile); 2256 known = 0; 2257 status = parse_option_name (cfile, 0, &known, &option); 2258 if (status != ISC_R_SUCCESS || option == NULL) { 2259 *lose = 1; 2260 return 0; 2261 } 2262 status = parse_option_statement(result, cfile, 1, option, 2263 prepend_option_statement); 2264 option_dereference(&option, MDL); 2265 return status; 2266 2267 case APPEND: 2268 skip_token(&val, (unsigned *)0, cfile); 2269 known = 0; 2270 status = parse_option_name (cfile, 0, &known, &option); 2271 if (status != ISC_R_SUCCESS || option == NULL) { 2272 *lose = 1; 2273 return 0; 2274 } 2275 status = parse_option_statement(result, cfile, 1, option, 2276 append_option_statement); 2277 option_dereference(&option, MDL); 2278 return status; 2279 2280 case ON: 2281 skip_token(&val, (unsigned *)0, cfile); 2282 return parse_on_statement (result, cfile, lose); 2283 2284 case SWITCH: 2285 skip_token(&val, (unsigned *)0, cfile); 2286 return parse_switch_statement (result, cfile, lose); 2287 2288 case CASE: 2289 skip_token(&val, (unsigned *)0, cfile); 2290 if (case_context == context_any) { 2291 parse_warn (cfile, 2292 "case statement in inappropriate scope."); 2293 *lose = 1; 2294 skip_to_semi (cfile); 2295 return 0; 2296 } 2297 return parse_case_statement (result, 2298 cfile, lose, case_context); 2299 2300 switch_default: 2301 skip_token(&val, (unsigned *)0, cfile); 2302 if (case_context == context_any) { 2303 parse_warn (cfile, "switch default statement in %s", 2304 "inappropriate scope."); 2305 2306 *lose = 1; 2307 return 0; 2308 } else { 2309 if (!executable_statement_allocate (result, MDL)) 2310 log_fatal ("no memory for default statement."); 2311 (*result) -> op = default_statement; 2312 return 1; 2313 } 2314 2315 case DEFINE: 2316 case TOKEN_SET: 2317 skip_token(&val, (unsigned *)0, cfile); 2318 if (token == DEFINE) 2319 flag = 1; 2320 else 2321 flag = 0; 2322 2323 token = next_token (&val, (unsigned *)0, cfile); 2324 if (token != NAME && token != NUMBER_OR_NAME) { 2325 parse_warn (cfile, 2326 "%s can't be a variable name", val); 2327 badset: 2328 skip_to_semi (cfile); 2329 *lose = 1; 2330 return 0; 2331 } 2332 2333 if (!executable_statement_allocate (result, MDL)) 2334 log_fatal ("no memory for set statement."); 2335 (*result) -> op = flag ? define_statement : set_statement; 2336 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL); 2337 if (!(*result)->data.set.name) 2338 log_fatal ("can't allocate variable name"); 2339 strcpy ((*result) -> data.set.name, val); 2340 token = next_token (&val, (unsigned *)0, cfile); 2341 2342 if (token == LPAREN) { 2343 struct string_list *head, *cur, *new; 2344 struct expression *expr; 2345 head = cur = (struct string_list *)0; 2346 do { 2347 token = next_token (&val, 2348 (unsigned *)0, cfile); 2349 if (token == RPAREN) 2350 break; 2351 if (token != NAME && token != NUMBER_OR_NAME) { 2352 parse_warn (cfile, 2353 "expecting argument name"); 2354 skip_to_rbrace (cfile, 0); 2355 *lose = 1; 2356 executable_statement_dereference 2357 (result, MDL); 2358 return 0; 2359 } 2360 new = ((struct string_list *) 2361 dmalloc (sizeof (struct string_list) + 2362 strlen (val), MDL)); 2363 if (!new) 2364 log_fatal ("can't allocate string."); 2365 memset (new, 0, sizeof *new); 2366 strcpy (new -> string, val); 2367 if (cur) { 2368 cur -> next = new; 2369 cur = new; 2370 } else { 2371 head = cur = new; 2372 } 2373 token = next_token (&val, 2374 (unsigned *)0, cfile); 2375 } while (token == COMMA); 2376 2377 if (token != RPAREN) { 2378 parse_warn (cfile, "expecting right paren."); 2379 badx: 2380 skip_to_semi (cfile); 2381 *lose = 1; 2382 executable_statement_dereference (result, MDL); 2383 return 0; 2384 } 2385 2386 token = next_token (&val, (unsigned *)0, cfile); 2387 if (token != LBRACE) { 2388 parse_warn (cfile, "expecting left brace."); 2389 goto badx; 2390 } 2391 2392 expr = (struct expression *)0; 2393 if (!(expression_allocate (&expr, MDL))) 2394 log_fatal ("can't allocate expression."); 2395 expr -> op = expr_function; 2396 if (!fundef_allocate (&expr -> data.func, MDL)) 2397 log_fatal ("can't allocate fundef."); 2398 expr -> data.func -> args = head; 2399 (*result) -> data.set.expr = expr; 2400 2401 if (!(parse_executable_statements 2402 (&expr -> data.func -> statements, cfile, lose, 2403 case_context))) { 2404 if (*lose) 2405 goto badx; 2406 } 2407 2408 token = next_token (&val, (unsigned *)0, cfile); 2409 if (token != RBRACE) { 2410 parse_warn (cfile, "expecting rigt brace."); 2411 goto badx; 2412 } 2413 } else { 2414 if (token != EQUAL) { 2415 parse_warn (cfile, 2416 "expecting '=' in %s statement.", 2417 flag ? "define" : "set"); 2418 goto badset; 2419 } 2420 2421 if (!parse_expression (&(*result) -> data.set.expr, 2422 cfile, lose, context_any, 2423 (struct expression **)0, 2424 expr_none)) { 2425 if (!*lose) 2426 parse_warn (cfile, 2427 "expecting expression."); 2428 else 2429 *lose = 1; 2430 skip_to_semi (cfile); 2431 executable_statement_dereference (result, MDL); 2432 return 0; 2433 } 2434 if (!parse_semi (cfile)) { 2435 *lose = 1; 2436 executable_statement_dereference (result, MDL); 2437 return 0; 2438 } 2439 } 2440 break; 2441 2442 case UNSET: 2443 skip_token(&val, (unsigned *)0, cfile); 2444 token = next_token (&val, (unsigned *)0, cfile); 2445 if (token != NAME && token != NUMBER_OR_NAME) { 2446 parse_warn (cfile, 2447 "%s can't be a variable name", val); 2448 skip_to_semi (cfile); 2449 *lose = 1; 2450 return 0; 2451 } 2452 2453 if (!executable_statement_allocate (result, MDL)) 2454 log_fatal ("no memory for set statement."); 2455 (*result) -> op = unset_statement; 2456 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL); 2457 if (!(*result)->data.unset) 2458 log_fatal ("can't allocate variable name"); 2459 strcpy ((*result) -> data.unset, val); 2460 if (!parse_semi (cfile)) { 2461 *lose = 1; 2462 executable_statement_dereference (result, MDL); 2463 return 0; 2464 } 2465 break; 2466 2467 case EVAL: 2468 skip_token(&val, (unsigned *)0, cfile); 2469 if (!executable_statement_allocate (result, MDL)) 2470 log_fatal ("no memory for eval statement."); 2471 (*result) -> op = eval_statement; 2472 2473 if (!parse_expression (&(*result) -> data.eval, 2474 cfile, lose, context_data, /* XXX */ 2475 (struct expression **)0, expr_none)) { 2476 if (!*lose) 2477 parse_warn (cfile, 2478 "expecting data expression."); 2479 else 2480 *lose = 1; 2481 skip_to_semi (cfile); 2482 executable_statement_dereference (result, MDL); 2483 return 0; 2484 } 2485 if (!parse_semi (cfile)) { 2486 *lose = 1; 2487 executable_statement_dereference (result, MDL); 2488 } 2489 break; 2490 2491 case EXECUTE: 2492 #ifdef ENABLE_EXECUTE 2493 skip_token(&val, NULL, cfile); 2494 2495 if (!executable_statement_allocate (result, MDL)) 2496 log_fatal ("no memory for execute statement."); 2497 (*result)->op = execute_statement; 2498 2499 token = next_token(&val, NULL, cfile); 2500 if (token != LPAREN) { 2501 parse_warn(cfile, "left parenthesis expected."); 2502 skip_to_semi(cfile); 2503 *lose = 1; 2504 return 0; 2505 } 2506 2507 token = next_token(&val, &len, cfile); 2508 if (token != STRING) { 2509 parse_warn(cfile, "Expecting a quoted string."); 2510 skip_to_semi(cfile); 2511 *lose = 1; 2512 return 0; 2513 } 2514 2515 (*result)->data.execute.command = dmalloc(len + 1, MDL); 2516 if ((*result)->data.execute.command == NULL) 2517 log_fatal("can't allocate command name"); 2518 strcpy((*result)->data.execute.command, val); 2519 2520 ep = &(*result)->data.execute.arglist; 2521 (*result)->data.execute.argc = 0; 2522 2523 while((token = next_token(&val, NULL, cfile)) == COMMA) { 2524 if (!expression_allocate(ep, MDL)) 2525 log_fatal ("can't allocate expression"); 2526 2527 if (!parse_data_expression (&(*ep) -> data.arg.val, 2528 cfile, lose)) { 2529 if (!*lose) { 2530 parse_warn (cfile, 2531 "expecting expression."); 2532 *lose = 1; 2533 } 2534 skip_to_semi(cfile); 2535 *lose = 1; 2536 return 0; 2537 } 2538 ep = &(*ep)->data.arg.next; 2539 (*result)->data.execute.argc++; 2540 } 2541 2542 if (token != RPAREN) { 2543 parse_warn(cfile, "right parenthesis expected."); 2544 skip_to_semi(cfile); 2545 *lose = 1; 2546 return 0; 2547 } 2548 2549 if (!parse_semi (cfile)) { 2550 *lose = 1; 2551 executable_statement_dereference (result, MDL); 2552 } 2553 #else /* ! ENABLE_EXECUTE */ 2554 parse_warn(cfile, "define ENABLE_EXECUTE in site.h to " 2555 "enable execute(); expressions."); 2556 skip_to_semi(cfile); 2557 *lose = 1; 2558 return 0; 2559 #endif /* ENABLE_EXECUTE */ 2560 break; 2561 2562 case RETURN: 2563 skip_token(&val, (unsigned *)0, cfile); 2564 2565 if (!executable_statement_allocate (result, MDL)) 2566 log_fatal ("no memory for return statement."); 2567 (*result) -> op = return_statement; 2568 2569 if (!parse_expression (&(*result) -> data.retval, 2570 cfile, lose, context_data, 2571 (struct expression **)0, expr_none)) { 2572 if (!*lose) 2573 parse_warn (cfile, 2574 "expecting data expression."); 2575 else 2576 *lose = 1; 2577 skip_to_semi (cfile); 2578 executable_statement_dereference (result, MDL); 2579 return 0; 2580 } 2581 if (!parse_semi (cfile)) { 2582 *lose = 1; 2583 executable_statement_dereference (result, MDL); 2584 return 0; 2585 } 2586 break; 2587 2588 case LOG: 2589 skip_token(&val, (unsigned *)0, cfile); 2590 2591 if (!executable_statement_allocate (result, MDL)) 2592 log_fatal ("no memory for log statement."); 2593 (*result) -> op = log_statement; 2594 2595 token = next_token (&val, (unsigned *)0, cfile); 2596 if (token != LPAREN) { 2597 parse_warn (cfile, "left parenthesis expected."); 2598 skip_to_semi (cfile); 2599 *lose = 1; 2600 return 0; 2601 } 2602 2603 token = peek_token (&val, (unsigned *)0, cfile); 2604 i = 1; 2605 if (token == FATAL) { 2606 (*result) -> data.log.priority = log_priority_fatal; 2607 } else if (token == ERROR) { 2608 (*result) -> data.log.priority = log_priority_error; 2609 } else if (token == TOKEN_DEBUG) { 2610 (*result) -> data.log.priority = log_priority_debug; 2611 } else if (token == INFO) { 2612 (*result) -> data.log.priority = log_priority_info; 2613 } else { 2614 (*result) -> data.log.priority = log_priority_debug; 2615 i = 0; 2616 } 2617 if (i) { 2618 skip_token(&val, (unsigned *)0, cfile); 2619 token = next_token (&val, (unsigned *)0, cfile); 2620 if (token != COMMA) { 2621 parse_warn (cfile, "comma expected."); 2622 skip_to_semi (cfile); 2623 *lose = 1; 2624 return 0; 2625 } 2626 } 2627 2628 if (!(parse_data_expression 2629 (&(*result) -> data.log.expr, cfile, lose))) { 2630 skip_to_semi (cfile); 2631 *lose = 1; 2632 return 0; 2633 } 2634 2635 token = next_token (&val, (unsigned *)0, cfile); 2636 if (token != RPAREN) { 2637 parse_warn (cfile, "right parenthesis expected."); 2638 skip_to_semi (cfile); 2639 *lose = 1; 2640 return 0; 2641 } 2642 2643 token = next_token (&val, (unsigned *)0, cfile); 2644 if (token != SEMI) { 2645 parse_warn (cfile, "semicolon expected."); 2646 skip_to_semi (cfile); 2647 *lose = 1; 2648 return 0; 2649 } 2650 break; 2651 2652 case PARSE_VENDOR_OPT: 2653 /* The parse-vendor-option; The statement has no arguments. 2654 * We simply set up the statement and when it gets executed it 2655 * will find all information it needs in the packet and options. 2656 */ 2657 skip_token(&val, NULL, cfile); 2658 if (!parse_semi(cfile)) { 2659 *lose = 1; 2660 return (0); 2661 } 2662 2663 if (!executable_statement_allocate(result, MDL)) 2664 log_fatal("no memory for execute statement."); 2665 (*result)->op = vendor_opt_statement; 2666 break; 2667 2668 /* Not really a statement, but we parse it here anyway 2669 because it's appropriate for all DHCP agents with 2670 parsers. */ 2671 case ZONE: 2672 skip_token(&val, (unsigned *)0, cfile); 2673 zone = (struct dns_zone *)0; 2674 if (!dns_zone_allocate (&zone, MDL)) 2675 log_fatal ("no memory for new zone."); 2676 zone -> name = parse_host_name (cfile); 2677 if (!zone -> name) { 2678 parse_warn (cfile, "expecting hostname."); 2679 badzone: 2680 *lose = 1; 2681 skip_to_semi (cfile); 2682 dns_zone_dereference (&zone, MDL); 2683 return 0; 2684 } 2685 i = strlen (zone -> name); 2686 if (zone -> name [i - 1] != '.') { 2687 s = dmalloc ((unsigned)i + 2, MDL); 2688 if (!s) { 2689 parse_warn (cfile, "no trailing '.' on zone"); 2690 goto badzone; 2691 } 2692 strcpy (s, zone -> name); 2693 s [i] = '.'; 2694 s [i + 1] = 0; 2695 dfree (zone -> name, MDL); 2696 zone -> name = s; 2697 } 2698 if (!parse_zone (zone, cfile)) 2699 goto badzone; 2700 status = enter_dns_zone (zone); 2701 if (status != ISC_R_SUCCESS) { 2702 parse_warn (cfile, "dns zone key %s: %s", 2703 zone -> name, isc_result_totext (status)); 2704 dns_zone_dereference (&zone, MDL); 2705 return 0; 2706 } 2707 dns_zone_dereference (&zone, MDL); 2708 return 1; 2709 2710 /* Also not really a statement, but same idea as above. */ 2711 case KEY: 2712 skip_token(&val, (unsigned *)0, cfile); 2713 if (!parse_key (cfile)) { 2714 *lose = 1; 2715 return 0; 2716 } 2717 return 1; 2718 2719 default: 2720 if (config_universe && is_identifier (token)) { 2721 option = (struct option *)0; 2722 option_name_hash_lookup(&option, 2723 config_universe->name_hash, 2724 val, 0, MDL); 2725 if (option) { 2726 skip_token(&val, (unsigned *)0, cfile); 2727 status = parse_option_statement 2728 (result, cfile, 1, option, 2729 supersede_option_statement); 2730 option_dereference(&option, MDL); 2731 return status; 2732 } 2733 } 2734 2735 if (token == NUMBER_OR_NAME || token == NAME) { 2736 /* This is rather ugly. Since function calls are 2737 data expressions, fake up an eval statement. */ 2738 if (!executable_statement_allocate (result, MDL)) 2739 log_fatal ("no memory for eval statement."); 2740 (*result) -> op = eval_statement; 2741 2742 if (!parse_expression (&(*result) -> data.eval, 2743 cfile, lose, context_data, 2744 (struct expression **)0, 2745 expr_none)) { 2746 if (!*lose) 2747 parse_warn (cfile, "expecting " 2748 "function call."); 2749 else 2750 *lose = 1; 2751 skip_to_semi (cfile); 2752 executable_statement_dereference (result, MDL); 2753 return 0; 2754 } 2755 if (!parse_semi (cfile)) { 2756 *lose = 1; 2757 executable_statement_dereference (result, MDL); 2758 return 0; 2759 } 2760 break; 2761 } 2762 2763 *lose = 0; 2764 return 0; 2765 } 2766 2767 return 1; 2768 } 2769 2770 /* zone-statements :== zone-statement | 2771 zone-statement zone-statements 2772 zone-statement :== 2773 PRIMARY ip-addresses SEMI | 2774 SECONDARY ip-addresses SEMI | 2775 PRIMARY6 ip-address6 SEMI | 2776 SECONDARY6 ip-address6 SEMI | 2777 key-reference SEMI 2778 ip-addresses :== ip-addr-or-hostname | 2779 ip-addr-or-hostname COMMA ip-addresses 2780 key-reference :== KEY STRING | 2781 KEY identifier */ 2782 2783 int parse_zone (struct dns_zone *zone, struct parse *cfile) 2784 { 2785 int token; 2786 const char *val; 2787 char *key_name; 2788 struct option_cache *oc; 2789 int done = 0; 2790 2791 token = next_token (&val, (unsigned *)0, cfile); 2792 if (token != LBRACE) { 2793 parse_warn (cfile, "expecting left brace"); 2794 return 0; 2795 } 2796 2797 do { 2798 token = peek_token (&val, (unsigned *)0, cfile); 2799 switch (token) { 2800 case PRIMARY: 2801 if (zone -> primary) { 2802 parse_warn (cfile, 2803 "more than one primary."); 2804 skip_to_semi (cfile); 2805 return 0; 2806 } 2807 if (!option_cache_allocate (&zone -> primary, MDL)) 2808 log_fatal ("can't allocate primary option cache."); 2809 oc = zone -> primary; 2810 goto consemup; 2811 2812 case SECONDARY: 2813 if (zone -> secondary) { 2814 parse_warn (cfile, "more than one secondary."); 2815 skip_to_semi (cfile); 2816 return 0; 2817 } 2818 if (!option_cache_allocate (&zone -> secondary, MDL)) 2819 log_fatal ("can't allocate secondary."); 2820 oc = zone -> secondary; 2821 consemup: 2822 skip_token(&val, (unsigned *)0, cfile); 2823 do { 2824 struct expression *expr = (struct expression *)0; 2825 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) { 2826 parse_warn (cfile, 2827 "expecting IP addr or hostname."); 2828 skip_to_semi (cfile); 2829 return 0; 2830 } 2831 if (oc -> expression) { 2832 struct expression *old = 2833 (struct expression *)0; 2834 expression_reference (&old, 2835 oc -> expression, 2836 MDL); 2837 expression_dereference (&oc -> expression, 2838 MDL); 2839 if (!make_concat (&oc -> expression, 2840 old, expr)) 2841 log_fatal ("no memory for concat."); 2842 expression_dereference (&expr, MDL); 2843 expression_dereference (&old, MDL); 2844 } else { 2845 expression_reference (&oc -> expression, 2846 expr, MDL); 2847 expression_dereference (&expr, MDL); 2848 } 2849 token = next_token (&val, (unsigned *)0, cfile); 2850 } while (token == COMMA); 2851 if (token != SEMI) { 2852 parse_warn (cfile, "expecting semicolon."); 2853 skip_to_semi (cfile); 2854 return 0; 2855 } 2856 break; 2857 2858 case PRIMARY6: 2859 if (zone->primary6) { 2860 parse_warn(cfile, "more than one primary6."); 2861 skip_to_semi(cfile); 2862 return (0); 2863 } 2864 if (!option_cache_allocate (&zone->primary6, MDL)) 2865 log_fatal("can't allocate primary6 option cache."); 2866 oc = zone->primary6; 2867 goto consemup6; 2868 2869 case SECONDARY6: 2870 if (zone->secondary6) { 2871 parse_warn(cfile, "more than one secondary6."); 2872 skip_to_semi(cfile); 2873 return (0); 2874 } 2875 if (!option_cache_allocate (&zone->secondary6, MDL)) 2876 log_fatal("can't allocate secondary6 " 2877 "option cache."); 2878 oc = zone->secondary6; 2879 consemup6: 2880 skip_token(&val, NULL, cfile); 2881 do { 2882 struct expression *expr = NULL; 2883 if (parse_ip6_addr_expr(&expr, cfile) == 0) { 2884 parse_warn(cfile, "expecting IPv6 addr."); 2885 skip_to_semi(cfile); 2886 return (0); 2887 } 2888 if (oc->expression) { 2889 struct expression *old = NULL; 2890 expression_reference(&old, oc->expression, 2891 MDL); 2892 expression_dereference(&oc->expression, 2893 MDL); 2894 if (!make_concat(&oc->expression, 2895 old, expr)) 2896 log_fatal("no memory for concat."); 2897 expression_dereference(&expr, MDL); 2898 expression_dereference(&old, MDL); 2899 } else { 2900 expression_reference(&oc->expression, 2901 expr, MDL); 2902 expression_dereference(&expr, MDL); 2903 } 2904 token = next_token(&val, NULL, cfile); 2905 } while (token == COMMA); 2906 if (token != SEMI) { 2907 parse_warn(cfile, "expecting semicolon."); 2908 skip_to_semi(cfile); 2909 return (0); 2910 } 2911 break; 2912 2913 case KEY: 2914 skip_token(&val, NULL, cfile); 2915 token = peek_token(&val, NULL, cfile); 2916 if (token == STRING) { 2917 skip_token(&val, NULL, cfile); 2918 key_name = NULL; 2919 } else { 2920 key_name = parse_host_name(cfile); 2921 if (!key_name) { 2922 parse_warn(cfile, "expecting key name."); 2923 skip_to_semi(cfile); 2924 return (0); 2925 } 2926 val = key_name; 2927 } 2928 if (zone->key) { 2929 log_fatal("Multiple key definitions for zone %s.", 2930 zone->name); 2931 } 2932 if (omapi_auth_key_lookup_name(&zone->key, val) != 2933 ISC_R_SUCCESS) 2934 parse_warn(cfile, "unknown key %s", val); 2935 if (key_name) 2936 dfree(key_name, MDL); 2937 if (!parse_semi(cfile)) 2938 return (0); 2939 break; 2940 2941 default: 2942 done = 1; 2943 break; 2944 } 2945 } while (!done); 2946 2947 token = next_token(&val, NULL, cfile); 2948 if (token != RBRACE) { 2949 parse_warn(cfile, "expecting right brace."); 2950 return (0); 2951 } 2952 return (1); 2953 } 2954 2955 /* key-statements :== key-statement | 2956 key-statement key-statements 2957 key-statement :== 2958 ALGORITHM host-name SEMI | 2959 secret-definition SEMI 2960 secret-definition :== SECRET base64val | 2961 SECRET STRING */ 2962 2963 int parse_key (struct parse *cfile) 2964 { 2965 int token; 2966 const char *val; 2967 int done = 0; 2968 struct auth_key *key; 2969 struct data_string ds; 2970 isc_result_t status; 2971 char *s; 2972 2973 key = (struct auth_key *)0; 2974 if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS) 2975 log_fatal ("no memory for key"); 2976 2977 token = peek_token (&val, (unsigned *)0, cfile); 2978 if (token == STRING) { 2979 skip_token(&val, (unsigned *)0, cfile); 2980 key -> name = dmalloc (strlen (val) + 1, MDL); 2981 if (!key -> name) 2982 log_fatal ("no memory for key name."); 2983 strcpy (key -> name, val); 2984 2985 } else { 2986 key -> name = parse_host_name (cfile); 2987 if (!key -> name) { 2988 parse_warn (cfile, "expecting key name."); 2989 skip_to_semi (cfile); 2990 goto bad; 2991 } 2992 } 2993 2994 token = next_token (&val, (unsigned *)0, cfile); 2995 if (token != LBRACE) { 2996 parse_warn (cfile, "expecting left brace"); 2997 goto bad; 2998 } 2999 3000 do { 3001 token = next_token (&val, (unsigned *)0, cfile); 3002 switch (token) { 3003 case ALGORITHM: 3004 if (key -> algorithm) { 3005 parse_warn (cfile, 3006 "key %s: too many algorithms", 3007 key -> name); 3008 goto rbad; 3009 } 3010 key -> algorithm = parse_host_name (cfile); 3011 if (!key -> algorithm) { 3012 parse_warn (cfile, 3013 "expecting key algorithm name."); 3014 goto rbad; 3015 } 3016 if (!parse_semi (cfile)) 3017 goto rbad; 3018 /* If the algorithm name isn't an FQDN, tack on 3019 the .SIG-ALG.REG.NET. domain. */ 3020 s = strrchr (key -> algorithm, '.'); 3021 if (!s) { 3022 static char add [] = ".SIG-ALG.REG.INT."; 3023 s = dmalloc (strlen (key -> algorithm) + 3024 sizeof (add), MDL); 3025 if (!s) { 3026 log_error ("no memory for key %s.", 3027 "algorithm"); 3028 goto rbad; 3029 } 3030 strcpy (s, key -> algorithm); 3031 strcat (s, add); 3032 dfree (key -> algorithm, MDL); 3033 key -> algorithm = s; 3034 } else if (s [1]) { 3035 /* If there is no trailing '.', hack one in. */ 3036 s = dmalloc (strlen (key -> algorithm) + 2, MDL); 3037 if (!s) { 3038 log_error ("no memory for key %s.", 3039 key -> algorithm); 3040 goto rbad; 3041 } 3042 strcpy (s, key -> algorithm); 3043 strcat (s, "."); 3044 dfree (key -> algorithm, MDL); 3045 key -> algorithm = s; 3046 } 3047 break; 3048 3049 case SECRET: 3050 if (key -> key) { 3051 parse_warn (cfile, "key %s: too many secrets", 3052 key -> name); 3053 goto rbad; 3054 } 3055 3056 memset (&ds, 0, sizeof(ds)); 3057 if (!parse_base64 (&ds, cfile)) 3058 goto rbad; 3059 status = omapi_data_string_new (&key -> key, ds.len, 3060 MDL); 3061 if (status != ISC_R_SUCCESS) 3062 goto rbad; 3063 memcpy (key -> key -> value, 3064 ds.buffer -> data, ds.len); 3065 data_string_forget (&ds, MDL); 3066 3067 if (!parse_semi (cfile)) 3068 goto rbad; 3069 break; 3070 3071 default: 3072 done = 1; 3073 break; 3074 } 3075 } while (!done); 3076 if (token != RBRACE) { 3077 parse_warn (cfile, "expecting right brace."); 3078 goto rbad; 3079 } 3080 /* Allow the BIND 8 syntax, which has a semicolon after each 3081 closing brace. */ 3082 token = peek_token (&val, (unsigned *)0, cfile); 3083 if (token == SEMI) { 3084 skip_token(&val, (unsigned *)0, cfile); 3085 } 3086 3087 /* Remember the key. */ 3088 status = omapi_auth_key_enter (key); 3089 if (status != ISC_R_SUCCESS) { 3090 parse_warn (cfile, "tsig key %s: %s", 3091 key -> name, isc_result_totext (status)); 3092 goto bad; 3093 } 3094 omapi_auth_key_dereference (&key, MDL); 3095 return 1; 3096 3097 rbad: 3098 skip_to_rbrace (cfile, 1); 3099 bad: 3100 omapi_auth_key_dereference (&key, MDL); 3101 return 0; 3102 } 3103 3104 /* 3105 * on-statement :== event-types LBRACE executable-statements RBRACE 3106 * event-types :== event-type OR event-types | 3107 * event-type 3108 * event-type :== EXPIRY | COMMIT | RELEASE 3109 */ 3110 3111 int parse_on_statement (result, cfile, lose) 3112 struct executable_statement **result; 3113 struct parse *cfile; 3114 int *lose; 3115 { 3116 enum dhcp_token token; 3117 const char *val; 3118 3119 if (!executable_statement_allocate (result, MDL)) 3120 log_fatal ("no memory for new statement."); 3121 (*result) -> op = on_statement; 3122 3123 do { 3124 token = next_token (&val, (unsigned *)0, cfile); 3125 switch (token) { 3126 case EXPIRY: 3127 (*result) -> data.on.evtypes |= ON_EXPIRY; 3128 break; 3129 3130 case COMMIT: 3131 (*result) -> data.on.evtypes |= ON_COMMIT; 3132 break; 3133 3134 case RELEASE: 3135 (*result) -> data.on.evtypes |= ON_RELEASE; 3136 break; 3137 3138 case TRANSMISSION: 3139 (*result) -> data.on.evtypes |= ON_TRANSMISSION; 3140 break; 3141 3142 default: 3143 parse_warn (cfile, "expecting a lease event type"); 3144 skip_to_semi (cfile); 3145 *lose = 1; 3146 executable_statement_dereference (result, MDL); 3147 return 0; 3148 } 3149 token = next_token (&val, (unsigned *)0, cfile); 3150 } while (token == OR); 3151 3152 /* Semicolon means no statements. */ 3153 if (token == SEMI) 3154 return 1; 3155 3156 if (token != LBRACE) { 3157 parse_warn (cfile, "left brace expected."); 3158 skip_to_semi (cfile); 3159 *lose = 1; 3160 executable_statement_dereference (result, MDL); 3161 return 0; 3162 } 3163 if (!parse_executable_statements (&(*result) -> data.on.statements, 3164 cfile, lose, context_any)) { 3165 if (*lose) { 3166 /* Try to even things up. */ 3167 do { 3168 token = next_token (&val, 3169 (unsigned *)0, cfile); 3170 } while (token != END_OF_FILE && token != RBRACE); 3171 executable_statement_dereference (result, MDL); 3172 return 0; 3173 } 3174 } 3175 token = next_token (&val, (unsigned *)0, cfile); 3176 if (token != RBRACE) { 3177 parse_warn (cfile, "right brace expected."); 3178 skip_to_semi (cfile); 3179 *lose = 1; 3180 executable_statement_dereference (result, MDL); 3181 return 0; 3182 } 3183 return 1; 3184 } 3185 3186 /* 3187 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE 3188 * 3189 */ 3190 3191 int parse_switch_statement (result, cfile, lose) 3192 struct executable_statement **result; 3193 struct parse *cfile; 3194 int *lose; 3195 { 3196 enum dhcp_token token; 3197 const char *val; 3198 3199 if (!executable_statement_allocate (result, MDL)) 3200 log_fatal ("no memory for new statement."); 3201 (*result) -> op = switch_statement; 3202 3203 token = next_token (&val, (unsigned *)0, cfile); 3204 if (token != LPAREN) { 3205 parse_warn (cfile, "expecting left brace."); 3206 pfui: 3207 *lose = 1; 3208 skip_to_semi (cfile); 3209 gnorf: 3210 executable_statement_dereference (result, MDL); 3211 return 0; 3212 } 3213 3214 if (!parse_expression (&(*result) -> data.s_switch.expr, 3215 cfile, lose, context_data_or_numeric, 3216 (struct expression **)0, expr_none)) { 3217 if (!*lose) { 3218 parse_warn (cfile, 3219 "expecting data or numeric expression."); 3220 goto pfui; 3221 } 3222 goto gnorf; 3223 } 3224 3225 token = next_token (&val, (unsigned *)0, cfile); 3226 if (token != RPAREN) { 3227 parse_warn (cfile, "right paren expected."); 3228 goto pfui; 3229 } 3230 3231 token = next_token (&val, (unsigned *)0, cfile); 3232 if (token != LBRACE) { 3233 parse_warn (cfile, "left brace expected."); 3234 goto pfui; 3235 } 3236 if (!(parse_executable_statements 3237 (&(*result) -> data.s_switch.statements, cfile, lose, 3238 (is_data_expression ((*result) -> data.s_switch.expr) 3239 ? context_data : context_numeric)))) { 3240 if (*lose) { 3241 skip_to_rbrace (cfile, 1); 3242 executable_statement_dereference (result, MDL); 3243 return 0; 3244 } 3245 } 3246 token = next_token (&val, (unsigned *)0, cfile); 3247 if (token != RBRACE) { 3248 parse_warn (cfile, "right brace expected."); 3249 goto pfui; 3250 } 3251 return 1; 3252 } 3253 3254 /* 3255 * case-statement :== CASE expr COLON 3256 * 3257 */ 3258 3259 int parse_case_statement (result, cfile, lose, case_context) 3260 struct executable_statement **result; 3261 struct parse *cfile; 3262 int *lose; 3263 enum expression_context case_context; 3264 { 3265 enum dhcp_token token; 3266 const char *val; 3267 3268 if (!executable_statement_allocate (result, MDL)) 3269 log_fatal ("no memory for new statement."); 3270 (*result) -> op = case_statement; 3271 3272 if (!parse_expression (&(*result) -> data.c_case, 3273 cfile, lose, case_context, 3274 (struct expression **)0, expr_none)) 3275 { 3276 if (!*lose) { 3277 parse_warn (cfile, "expecting %s expression.", 3278 (case_context == context_data 3279 ? "data" : "numeric")); 3280 } 3281 pfui: 3282 *lose = 1; 3283 skip_to_semi (cfile); 3284 executable_statement_dereference (result, MDL); 3285 return 0; 3286 } 3287 3288 token = next_token (&val, (unsigned *)0, cfile); 3289 if (token != COLON) { 3290 parse_warn (cfile, "colon expected."); 3291 goto pfui; 3292 } 3293 return 1; 3294 } 3295 3296 /* 3297 * if-statement :== boolean-expression LBRACE executable-statements RBRACE 3298 * else-statement 3299 * 3300 * else-statement :== <null> | 3301 * ELSE LBRACE executable-statements RBRACE | 3302 * ELSE IF if-statement | 3303 * ELSIF if-statement 3304 */ 3305 3306 int parse_if_statement (result, cfile, lose) 3307 struct executable_statement **result; 3308 struct parse *cfile; 3309 int *lose; 3310 { 3311 enum dhcp_token token; 3312 const char *val; 3313 int parenp; 3314 3315 if (!executable_statement_allocate (result, MDL)) 3316 log_fatal ("no memory for if statement."); 3317 3318 (*result) -> op = if_statement; 3319 3320 token = peek_token (&val, (unsigned *)0, cfile); 3321 if (token == LPAREN) { 3322 parenp = 1; 3323 skip_token(&val, (unsigned *)0, cfile); 3324 } else 3325 parenp = 0; 3326 3327 3328 if (!parse_boolean_expression (&(*result) -> data.ie.expr, 3329 cfile, lose)) { 3330 if (!*lose) 3331 parse_warn (cfile, "boolean expression expected."); 3332 executable_statement_dereference (result, MDL); 3333 *lose = 1; 3334 return 0; 3335 } 3336 #if defined (DEBUG_EXPRESSION_PARSE) 3337 print_expression ("if condition", (*result) -> data.ie.expr); 3338 #endif 3339 if (parenp) { 3340 token = next_token (&val, (unsigned *)0, cfile); 3341 if (token != RPAREN) { 3342 parse_warn (cfile, "expecting right paren."); 3343 *lose = 1; 3344 executable_statement_dereference (result, MDL); 3345 return 0; 3346 } 3347 } 3348 token = next_token (&val, (unsigned *)0, cfile); 3349 if (token != LBRACE) { 3350 parse_warn (cfile, "left brace expected."); 3351 skip_to_semi (cfile); 3352 *lose = 1; 3353 executable_statement_dereference (result, MDL); 3354 return 0; 3355 } 3356 if (!parse_executable_statements (&(*result) -> data.ie.tc, 3357 cfile, lose, context_any)) { 3358 if (*lose) { 3359 /* Try to even things up. */ 3360 do { 3361 token = next_token (&val, 3362 (unsigned *)0, cfile); 3363 } while (token != END_OF_FILE && token != RBRACE); 3364 executable_statement_dereference (result, MDL); 3365 return 0; 3366 } 3367 } 3368 token = next_token (&val, (unsigned *)0, cfile); 3369 if (token != RBRACE) { 3370 parse_warn (cfile, "right brace expected."); 3371 skip_to_semi (cfile); 3372 *lose = 1; 3373 executable_statement_dereference (result, MDL); 3374 return 0; 3375 } 3376 token = peek_token (&val, (unsigned *)0, cfile); 3377 if (token == ELSE) { 3378 skip_token(&val, (unsigned *)0, cfile); 3379 token = peek_token (&val, (unsigned *)0, cfile); 3380 if (token == IF) { 3381 skip_token(&val, (unsigned *)0, cfile); 3382 if (!parse_if_statement (&(*result) -> data.ie.fc, 3383 cfile, lose)) { 3384 if (!*lose) 3385 parse_warn (cfile, 3386 "expecting if statement"); 3387 executable_statement_dereference (result, MDL); 3388 *lose = 1; 3389 return 0; 3390 } 3391 } else if (token != LBRACE) { 3392 parse_warn (cfile, "left brace or if expected."); 3393 skip_to_semi (cfile); 3394 *lose = 1; 3395 executable_statement_dereference (result, MDL); 3396 return 0; 3397 } else { 3398 skip_token(&val, (unsigned *)0, cfile); 3399 if (!(parse_executable_statements 3400 (&(*result) -> data.ie.fc, 3401 cfile, lose, context_any))) { 3402 executable_statement_dereference (result, MDL); 3403 return 0; 3404 } 3405 token = next_token (&val, (unsigned *)0, cfile); 3406 if (token != RBRACE) { 3407 parse_warn (cfile, "right brace expected."); 3408 skip_to_semi (cfile); 3409 *lose = 1; 3410 executable_statement_dereference (result, MDL); 3411 return 0; 3412 } 3413 } 3414 } else if (token == ELSIF) { 3415 skip_token(&val, (unsigned *)0, cfile); 3416 if (!parse_if_statement (&(*result) -> data.ie.fc, 3417 cfile, lose)) { 3418 if (!*lose) 3419 parse_warn (cfile, 3420 "expecting conditional."); 3421 executable_statement_dereference (result, MDL); 3422 *lose = 1; 3423 return 0; 3424 } 3425 } else 3426 (*result) -> data.ie.fc = (struct executable_statement *)0; 3427 3428 return 1; 3429 } 3430 3431 /* 3432 * boolean_expression :== CHECK STRING | 3433 * NOT boolean-expression | 3434 * data-expression EQUAL data-expression | 3435 * data-expression BANG EQUAL data-expression | 3436 * data-expression REGEX_MATCH data-expression | 3437 * boolean-expression AND boolean-expression | 3438 * boolean-expression OR boolean-expression 3439 * EXISTS OPTION-NAME 3440 */ 3441 3442 int parse_boolean_expression (expr, cfile, lose) 3443 struct expression **expr; 3444 struct parse *cfile; 3445 int *lose; 3446 { 3447 /* Parse an expression... */ 3448 if (!parse_expression (expr, cfile, lose, context_boolean, 3449 (struct expression **)0, expr_none)) 3450 return 0; 3451 3452 if (!is_boolean_expression (*expr) && 3453 (*expr) -> op != expr_variable_reference && 3454 (*expr) -> op != expr_funcall) { 3455 parse_warn (cfile, "Expecting a boolean expression."); 3456 *lose = 1; 3457 expression_dereference (expr, MDL); 3458 return 0; 3459 } 3460 return 1; 3461 } 3462 3463 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */ 3464 3465 int parse_boolean (cfile) 3466 struct parse *cfile; 3467 { 3468 const char *val; 3469 int rv; 3470 3471 (void)next_token(&val, NULL, cfile); 3472 if (!strcasecmp (val, "true") 3473 || !strcasecmp (val, "on")) 3474 rv = 1; 3475 else if (!strcasecmp (val, "false") 3476 || !strcasecmp (val, "off")) 3477 rv = 0; 3478 else { 3479 parse_warn (cfile, 3480 "boolean value (true/false/on/off) expected"); 3481 skip_to_semi (cfile); 3482 return 0; 3483 } 3484 parse_semi (cfile); 3485 return rv; 3486 } 3487 3488 3489 /* 3490 * data_expression :== SUBSTRING LPAREN data-expression COMMA 3491 * numeric-expression COMMA 3492 * numeric-expression RPAREN | 3493 * CONCAT LPAREN data-expression COMMA 3494 * data-expression RPAREN 3495 * SUFFIX LPAREN data_expression COMMA 3496 * numeric-expression RPAREN | 3497 * LCASE LPAREN data_expression RPAREN | 3498 * UCASE LPAREN data_expression RPAREN | 3499 * OPTION option_name | 3500 * HARDWARE | 3501 * PACKET LPAREN numeric-expression COMMA 3502 * numeric-expression RPAREN | 3503 * V6RELAY LPAREN numeric-expression COMMA 3504 * data-expression RPAREN | 3505 * STRING | 3506 * colon_separated_hex_list 3507 */ 3508 3509 int parse_data_expression (expr, cfile, lose) 3510 struct expression **expr; 3511 struct parse *cfile; 3512 int *lose; 3513 { 3514 /* Parse an expression... */ 3515 if (!parse_expression (expr, cfile, lose, context_data, 3516 (struct expression **)0, expr_none)) 3517 return 0; 3518 3519 if (!is_data_expression (*expr) && 3520 (*expr) -> op != expr_variable_reference && 3521 (*expr) -> op != expr_funcall) { 3522 expression_dereference (expr, MDL); 3523 parse_warn (cfile, "Expecting a data expression."); 3524 *lose = 1; 3525 return 0; 3526 } 3527 return 1; 3528 } 3529 3530 /* 3531 * numeric-expression :== EXTRACT_INT LPAREN data-expression 3532 * COMMA number RPAREN | 3533 * NUMBER 3534 */ 3535 3536 int parse_numeric_expression (expr, cfile, lose) 3537 struct expression **expr; 3538 struct parse *cfile; 3539 int *lose; 3540 { 3541 /* Parse an expression... */ 3542 if (!parse_expression (expr, cfile, lose, context_numeric, 3543 (struct expression **)0, expr_none)) 3544 return 0; 3545 3546 if (!is_numeric_expression (*expr) && 3547 (*expr) -> op != expr_variable_reference && 3548 (*expr) -> op != expr_funcall) { 3549 expression_dereference (expr, MDL); 3550 parse_warn (cfile, "Expecting a numeric expression."); 3551 *lose = 1; 3552 return 0; 3553 } 3554 return 1; 3555 } 3556 3557 /* Parse a subexpression that does not contain a binary operator. */ 3558 3559 int parse_non_binary (expr, cfile, lose, context) 3560 struct expression **expr; 3561 struct parse *cfile; 3562 int *lose; 3563 enum expression_context context; 3564 { 3565 enum dhcp_token token; 3566 const char *val; 3567 struct collection *col; 3568 struct expression *nexp, **ep; 3569 int known; 3570 char *cptr; 3571 isc_result_t status; 3572 unsigned len; 3573 3574 token = peek_token (&val, (unsigned *)0, cfile); 3575 3576 /* Check for unary operators... */ 3577 switch (token) { 3578 case CHECK: 3579 skip_token(&val, (unsigned *)0, cfile); 3580 token = next_token (&val, (unsigned *)0, cfile); 3581 if (token != STRING) { 3582 parse_warn (cfile, "string expected."); 3583 skip_to_semi (cfile); 3584 *lose = 1; 3585 return 0; 3586 } 3587 for (col = collections; col; col = col -> next) 3588 if (!strcmp (col -> name, val)) 3589 break; 3590 if (!col) { 3591 parse_warn (cfile, "unknown collection."); 3592 *lose = 1; 3593 return 0; 3594 } 3595 if (!expression_allocate (expr, MDL)) 3596 log_fatal ("can't allocate expression"); 3597 (*expr) -> op = expr_check; 3598 (*expr) -> data.check = col; 3599 break; 3600 3601 case TOKEN_NOT: 3602 skip_token(&val, NULL, cfile); 3603 if (!expression_allocate (expr, MDL)) 3604 log_fatal ("can't allocate expression"); 3605 (*expr)->op = expr_not; 3606 if (!parse_non_binary (&(*expr)->data.not, 3607 cfile, lose, context_boolean)) { 3608 if (!*lose) { 3609 parse_warn (cfile, "expression expected"); 3610 skip_to_semi (cfile); 3611 } 3612 *lose = 1; 3613 expression_dereference (expr, MDL); 3614 return (0); 3615 } 3616 if (!is_boolean_expression ((*expr) -> data.not)) { 3617 *lose = 1; 3618 parse_warn (cfile, "boolean expression expected"); 3619 skip_to_semi (cfile); 3620 expression_dereference (expr, MDL); 3621 return 0; 3622 } 3623 break; 3624 3625 case LPAREN: 3626 skip_token(&val, (unsigned *)0, cfile); 3627 if (!parse_expression (expr, cfile, lose, context, 3628 (struct expression **)0, expr_none)) { 3629 if (!*lose) { 3630 parse_warn (cfile, "expression expected"); 3631 skip_to_semi (cfile); 3632 } 3633 *lose = 1; 3634 return 0; 3635 } 3636 token = next_token (&val, (unsigned *)0, cfile); 3637 if (token != RPAREN) { 3638 *lose = 1; 3639 parse_warn (cfile, "right paren expected"); 3640 skip_to_semi (cfile); 3641 return 0; 3642 } 3643 break; 3644 3645 case EXISTS: 3646 skip_token(&val, NULL, cfile); 3647 if (!expression_allocate (expr, MDL)) 3648 log_fatal ("can't allocate expression"); 3649 (*expr)->op = expr_exists; 3650 known = 0; 3651 /* Pass reference directly to expression structure. */ 3652 status = parse_option_name(cfile, 0, &known, 3653 &(*expr)->data.option); 3654 if (status != ISC_R_SUCCESS || 3655 (*expr)->data.option == NULL) { 3656 *lose = 1; 3657 expression_dereference (expr, MDL); 3658 return (0); 3659 } 3660 break; 3661 3662 case STATIC: 3663 skip_token(&val, (unsigned *)0, cfile); 3664 if (!expression_allocate (expr, MDL)) 3665 log_fatal ("can't allocate expression"); 3666 (*expr) -> op = expr_static; 3667 break; 3668 3669 case KNOWN: 3670 skip_token(&val, (unsigned *)0, cfile); 3671 if (!expression_allocate (expr, MDL)) 3672 log_fatal ("can't allocate expression"); 3673 (*expr) -> op = expr_known; 3674 break; 3675 3676 case SUBSTRING: 3677 skip_token(&val, (unsigned *)0, cfile); 3678 if (!expression_allocate (expr, MDL)) 3679 log_fatal ("can't allocate expression"); 3680 (*expr) -> op = expr_substring; 3681 3682 token = next_token (&val, (unsigned *)0, cfile); 3683 if (token != LPAREN) { 3684 nolparen: 3685 expression_dereference (expr, MDL); 3686 parse_warn (cfile, "left parenthesis expected."); 3687 *lose = 1; 3688 return 0; 3689 } 3690 3691 if (!parse_data_expression (&(*expr) -> data.substring.expr, 3692 cfile, lose)) { 3693 nodata: 3694 expression_dereference (expr, MDL); 3695 if (!*lose) { 3696 parse_warn (cfile, 3697 "expecting data expression."); 3698 skip_to_semi (cfile); 3699 *lose = 1; 3700 } 3701 return 0; 3702 } 3703 3704 token = next_token (&val, (unsigned *)0, cfile); 3705 if (token != COMMA) { 3706 nocomma: 3707 expression_dereference (expr, MDL); 3708 parse_warn (cfile, "comma expected."); 3709 *lose = 1; 3710 3711 return 0; 3712 } 3713 3714 if (!parse_numeric_expression 3715 (&(*expr) -> data.substring.offset,cfile, lose)) { 3716 nonum: 3717 if (!*lose) { 3718 parse_warn (cfile, 3719 "expecting numeric expression."); 3720 skip_to_semi (cfile); 3721 *lose = 1; 3722 } 3723 expression_dereference (expr, MDL); 3724 return 0; 3725 } 3726 3727 token = next_token (&val, (unsigned *)0, cfile); 3728 if (token != COMMA) 3729 goto nocomma; 3730 3731 if (!parse_numeric_expression 3732 (&(*expr) -> data.substring.len, cfile, lose)) 3733 goto nonum; 3734 3735 token = next_token (&val, (unsigned *)0, cfile); 3736 if (token != RPAREN) { 3737 norparen: 3738 parse_warn (cfile, "right parenthesis expected."); 3739 *lose = 1; 3740 expression_dereference (expr, MDL); 3741 return 0; 3742 } 3743 break; 3744 3745 case SUFFIX: 3746 skip_token(&val, (unsigned *)0, cfile); 3747 if (!expression_allocate (expr, MDL)) 3748 log_fatal ("can't allocate expression"); 3749 (*expr) -> op = expr_suffix; 3750 3751 token = next_token (&val, (unsigned *)0, cfile); 3752 if (token != LPAREN) 3753 goto nolparen; 3754 3755 if (!parse_data_expression (&(*expr) -> data.suffix.expr, 3756 cfile, lose)) 3757 goto nodata; 3758 3759 token = next_token (&val, (unsigned *)0, cfile); 3760 if (token != COMMA) 3761 goto nocomma; 3762 3763 if (!parse_numeric_expression (&(*expr) -> data.suffix.len, 3764 cfile, lose)) 3765 goto nonum; 3766 3767 token = next_token (&val, (unsigned *)0, cfile); 3768 if (token != RPAREN) 3769 goto norparen; 3770 break; 3771 3772 case LCASE: 3773 skip_token(&val, (unsigned *)0, cfile); 3774 if (!expression_allocate(expr, MDL)) 3775 log_fatal ("can't allocate expression"); 3776 (*expr)->op = expr_lcase; 3777 3778 token = next_token(&val, (unsigned *)0, cfile); 3779 if (token != LPAREN) 3780 goto nolparen; 3781 3782 if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose)) 3783 goto nodata; 3784 3785 token = next_token(&val, (unsigned *)0, cfile); 3786 if (token != RPAREN) 3787 goto norparen; 3788 break; 3789 3790 case UCASE: 3791 skip_token(&val, (unsigned *)0, cfile); 3792 if (!expression_allocate(expr, MDL)) 3793 log_fatal ("can't allocate expression"); 3794 (*expr)->op = expr_ucase; 3795 3796 token = next_token (&val, (unsigned *)0, cfile); 3797 if (token != LPAREN) 3798 goto nolparen; 3799 3800 if (!parse_data_expression(&(*expr)->data.ucase, 3801 cfile, lose)) 3802 goto nodata; 3803 3804 token = next_token(&val, (unsigned *)0, cfile); 3805 if (token != RPAREN) 3806 goto norparen; 3807 break; 3808 3809 case CONCAT: 3810 skip_token(&val, (unsigned *)0, cfile); 3811 if (!expression_allocate (expr, MDL)) 3812 log_fatal ("can't allocate expression"); 3813 (*expr) -> op = expr_concat; 3814 3815 token = next_token (&val, (unsigned *)0, cfile); 3816 if (token != LPAREN) 3817 goto nolparen; 3818 3819 if (!parse_data_expression (&(*expr) -> data.concat [0], 3820 cfile, lose)) 3821 goto nodata; 3822 3823 token = next_token (&val, (unsigned *)0, cfile); 3824 if (token != COMMA) 3825 goto nocomma; 3826 3827 concat_another: 3828 if (!parse_data_expression (&(*expr) -> data.concat [1], 3829 cfile, lose)) 3830 goto nodata; 3831 3832 token = next_token (&val, (unsigned *)0, cfile); 3833 3834 if (token == COMMA) { 3835 nexp = (struct expression *)0; 3836 if (!expression_allocate (&nexp, MDL)) 3837 log_fatal ("can't allocate at CONCAT2"); 3838 nexp -> op = expr_concat; 3839 expression_reference (&nexp -> data.concat [0], 3840 *expr, MDL); 3841 expression_dereference (expr, MDL); 3842 expression_reference (expr, nexp, MDL); 3843 expression_dereference (&nexp, MDL); 3844 goto concat_another; 3845 } 3846 3847 if (token != RPAREN) 3848 goto norparen; 3849 break; 3850 3851 case BINARY_TO_ASCII: 3852 skip_token(&val, (unsigned *)0, cfile); 3853 if (!expression_allocate (expr, MDL)) 3854 log_fatal ("can't allocate expression"); 3855 (*expr) -> op = expr_binary_to_ascii; 3856 3857 token = next_token (&val, (unsigned *)0, cfile); 3858 if (token != LPAREN) 3859 goto nolparen; 3860 3861 if (!parse_numeric_expression (&(*expr) -> data.b2a.base, 3862 cfile, lose)) 3863 goto nodata; 3864 3865 token = next_token (&val, (unsigned *)0, cfile); 3866 if (token != COMMA) 3867 goto nocomma; 3868 3869 if (!parse_numeric_expression (&(*expr) -> data.b2a.width, 3870 cfile, lose)) 3871 goto nodata; 3872 3873 token = next_token (&val, (unsigned *)0, cfile); 3874 if (token != COMMA) 3875 goto nocomma; 3876 3877 if (!parse_data_expression (&(*expr) -> data.b2a.separator, 3878 cfile, lose)) 3879 goto nodata; 3880 3881 token = next_token (&val, (unsigned *)0, cfile); 3882 if (token != COMMA) 3883 goto nocomma; 3884 3885 if (!parse_data_expression (&(*expr) -> data.b2a.buffer, 3886 cfile, lose)) 3887 goto nodata; 3888 3889 token = next_token (&val, (unsigned *)0, cfile); 3890 if (token != RPAREN) 3891 goto norparen; 3892 break; 3893 3894 case REVERSE: 3895 skip_token(&val, (unsigned *)0, cfile); 3896 if (!expression_allocate (expr, MDL)) 3897 log_fatal ("can't allocate expression"); 3898 (*expr) -> op = expr_reverse; 3899 3900 token = next_token (&val, (unsigned *)0, cfile); 3901 if (token != LPAREN) 3902 goto nolparen; 3903 3904 if (!(parse_numeric_expression 3905 (&(*expr) -> data.reverse.width, cfile, lose))) 3906 goto nodata; 3907 3908 token = next_token (&val, (unsigned *)0, cfile); 3909 if (token != COMMA) 3910 goto nocomma; 3911 3912 if (!(parse_data_expression 3913 (&(*expr) -> data.reverse.buffer, cfile, lose))) 3914 goto nodata; 3915 3916 token = next_token (&val, (unsigned *)0, cfile); 3917 if (token != RPAREN) 3918 goto norparen; 3919 break; 3920 3921 case PICK: 3922 /* pick (a, b, c) actually produces an internal representation 3923 that looks like pick (a, pick (b, pick (c, nil))). */ 3924 skip_token(&val, (unsigned *)0, cfile); 3925 if (!(expression_allocate (expr, MDL))) 3926 log_fatal ("can't allocate expression"); 3927 3928 token = next_token (&val, (unsigned *)0, cfile); 3929 if (token != LPAREN) 3930 goto nolparen; 3931 3932 nexp = (struct expression *)0; 3933 expression_reference (&nexp, *expr, MDL); 3934 do { 3935 nexp -> op = expr_pick_first_value; 3936 if (!(parse_data_expression 3937 (&nexp -> data.pick_first_value.car, 3938 cfile, lose))) 3939 goto nodata; 3940 3941 token = next_token (&val, (unsigned *)0, cfile); 3942 if (token == COMMA) { 3943 struct expression *foo = (struct expression *)0; 3944 if (!expression_allocate (&foo, MDL)) 3945 log_fatal ("can't allocate expr"); 3946 expression_reference 3947 (&nexp -> data.pick_first_value.cdr, foo, MDL); 3948 expression_dereference (&nexp, MDL); 3949 expression_reference (&nexp, foo, MDL); 3950 expression_dereference (&foo, MDL); 3951 } 3952 } while (token == COMMA); 3953 expression_dereference (&nexp, MDL); 3954 3955 if (token != RPAREN) 3956 goto norparen; 3957 break; 3958 3959 case OPTION: 3960 case CONFIG_OPTION: 3961 if (!expression_allocate (expr, MDL)) 3962 log_fatal ("can't allocate expression"); 3963 (*expr) -> op = (token == OPTION 3964 ? expr_option 3965 : expr_config_option); 3966 skip_token(&val, (unsigned *)0, cfile); 3967 known = 0; 3968 /* Pass reference directly to expression structure. */ 3969 status = parse_option_name(cfile, 0, &known, 3970 &(*expr)->data.option); 3971 if (status != ISC_R_SUCCESS || 3972 (*expr)->data.option == NULL) { 3973 *lose = 1; 3974 expression_dereference (expr, MDL); 3975 return 0; 3976 } 3977 break; 3978 3979 case HARDWARE: 3980 skip_token(&val, (unsigned *)0, cfile); 3981 if (!expression_allocate (expr, MDL)) 3982 log_fatal ("can't allocate expression"); 3983 (*expr) -> op = expr_hardware; 3984 break; 3985 3986 case LEASED_ADDRESS: 3987 skip_token(&val, (unsigned *)0, cfile); 3988 if (!expression_allocate (expr, MDL)) 3989 log_fatal ("can't allocate expression"); 3990 (*expr) -> op = expr_leased_address; 3991 break; 3992 3993 case CLIENT_STATE: 3994 skip_token(&val, (unsigned *)0, cfile); 3995 if (!expression_allocate (expr, MDL)) 3996 log_fatal ("can't allocate expression"); 3997 (*expr) -> op = expr_client_state; 3998 break; 3999 4000 case FILENAME: 4001 skip_token(&val, (unsigned *)0, cfile); 4002 if (!expression_allocate (expr, MDL)) 4003 log_fatal ("can't allocate expression"); 4004 (*expr) -> op = expr_filename; 4005 break; 4006 4007 case SERVER_NAME: 4008 skip_token(&val, (unsigned *)0, cfile); 4009 if (!expression_allocate (expr, MDL)) 4010 log_fatal ("can't allocate expression"); 4011 (*expr) -> op = expr_sname; 4012 break; 4013 4014 case LEASE_TIME: 4015 skip_token(&val, (unsigned *)0, cfile); 4016 if (!expression_allocate (expr, MDL)) 4017 log_fatal ("can't allocate expression"); 4018 (*expr) -> op = expr_lease_time; 4019 break; 4020 4021 case TOKEN_NULL: 4022 skip_token(&val, (unsigned *)0, cfile); 4023 if (!expression_allocate (expr, MDL)) 4024 log_fatal ("can't allocate expression"); 4025 (*expr) -> op = expr_null; 4026 break; 4027 4028 case HOST_DECL_NAME: 4029 skip_token(&val, (unsigned *)0, cfile); 4030 if (!expression_allocate (expr, MDL)) 4031 log_fatal ("can't allocate expression"); 4032 (*expr) -> op = expr_host_decl_name; 4033 break; 4034 4035 case PACKET: 4036 skip_token(&val, (unsigned *)0, cfile); 4037 if (!expression_allocate (expr, MDL)) 4038 log_fatal ("can't allocate expression"); 4039 (*expr) -> op = expr_packet; 4040 4041 token = next_token (&val, (unsigned *)0, cfile); 4042 if (token != LPAREN) 4043 goto nolparen; 4044 4045 if (!parse_numeric_expression (&(*expr) -> data.packet.offset, 4046 cfile, lose)) 4047 goto nonum; 4048 4049 token = next_token (&val, (unsigned *)0, cfile); 4050 if (token != COMMA) 4051 goto nocomma; 4052 4053 if (!parse_numeric_expression (&(*expr) -> data.packet.len, 4054 cfile, lose)) 4055 goto nonum; 4056 4057 token = next_token (&val, (unsigned *)0, cfile); 4058 if (token != RPAREN) 4059 goto norparen; 4060 break; 4061 4062 case STRING: 4063 skip_token(&val, &len, cfile); 4064 if (!make_const_data (expr, (const unsigned char *)val, 4065 len, 1, 1, MDL)) 4066 log_fatal ("can't make constant string expression."); 4067 break; 4068 4069 case EXTRACT_INT: 4070 skip_token(&val, (unsigned *)0, cfile); 4071 token = next_token (&val, (unsigned *)0, cfile); 4072 if (token != LPAREN) { 4073 parse_warn (cfile, "left parenthesis expected."); 4074 *lose = 1; 4075 return 0; 4076 } 4077 4078 if (!expression_allocate (expr, MDL)) 4079 log_fatal ("can't allocate expression"); 4080 4081 if (!parse_data_expression (&(*expr) -> data.extract_int, 4082 cfile, lose)) { 4083 if (!*lose) { 4084 parse_warn (cfile, 4085 "expecting data expression."); 4086 skip_to_semi (cfile); 4087 *lose = 1; 4088 } 4089 expression_dereference (expr, MDL); 4090 return 0; 4091 } 4092 4093 token = next_token (&val, (unsigned *)0, cfile); 4094 if (token != COMMA) { 4095 parse_warn (cfile, "comma expected."); 4096 *lose = 1; 4097 expression_dereference (expr, MDL); 4098 return 0; 4099 } 4100 4101 token = next_token (&val, (unsigned *)0, cfile); 4102 if (token != NUMBER) { 4103 parse_warn (cfile, "number expected."); 4104 *lose = 1; 4105 expression_dereference (expr, MDL); 4106 return 0; 4107 } 4108 switch (atoi (val)) { 4109 case 8: 4110 (*expr) -> op = expr_extract_int8; 4111 break; 4112 4113 case 16: 4114 (*expr) -> op = expr_extract_int16; 4115 break; 4116 4117 case 32: 4118 (*expr) -> op = expr_extract_int32; 4119 break; 4120 4121 default: 4122 parse_warn (cfile, 4123 "unsupported integer size %d", atoi (val)); 4124 *lose = 1; 4125 skip_to_semi (cfile); 4126 expression_dereference (expr, MDL); 4127 return 0; 4128 } 4129 4130 token = next_token (&val, (unsigned *)0, cfile); 4131 if (token != RPAREN) { 4132 parse_warn (cfile, "right parenthesis expected."); 4133 *lose = 1; 4134 expression_dereference (expr, MDL); 4135 return 0; 4136 } 4137 break; 4138 4139 case ENCODE_INT: 4140 skip_token(&val, (unsigned *)0, cfile); 4141 token = next_token (&val, (unsigned *)0, cfile); 4142 if (token != LPAREN) { 4143 parse_warn (cfile, "left parenthesis expected."); 4144 *lose = 1; 4145 return 0; 4146 } 4147 4148 if (!expression_allocate (expr, MDL)) 4149 log_fatal ("can't allocate expression"); 4150 4151 if (!parse_numeric_expression (&(*expr) -> data.encode_int, 4152 cfile, lose)) { 4153 parse_warn (cfile, "expecting numeric expression."); 4154 skip_to_semi (cfile); 4155 *lose = 1; 4156 expression_dereference (expr, MDL); 4157 return 0; 4158 } 4159 4160 token = next_token (&val, (unsigned *)0, cfile); 4161 if (token != COMMA) { 4162 parse_warn (cfile, "comma expected."); 4163 *lose = 1; 4164 expression_dereference (expr, MDL); 4165 return 0; 4166 } 4167 4168 token = next_token (&val, (unsigned *)0, cfile); 4169 if (token != NUMBER) { 4170 parse_warn (cfile, "number expected."); 4171 *lose = 1; 4172 expression_dereference (expr, MDL); 4173 return 0; 4174 } 4175 switch (atoi (val)) { 4176 case 8: 4177 (*expr) -> op = expr_encode_int8; 4178 break; 4179 4180 case 16: 4181 (*expr) -> op = expr_encode_int16; 4182 break; 4183 4184 case 32: 4185 (*expr) -> op = expr_encode_int32; 4186 break; 4187 4188 default: 4189 parse_warn (cfile, 4190 "unsupported integer size %d", atoi (val)); 4191 *lose = 1; 4192 skip_to_semi (cfile); 4193 expression_dereference (expr, MDL); 4194 return 0; 4195 } 4196 4197 token = next_token (&val, (unsigned *)0, cfile); 4198 if (token != RPAREN) { 4199 parse_warn (cfile, "right parenthesis expected."); 4200 *lose = 1; 4201 expression_dereference (expr, MDL); 4202 return 0; 4203 } 4204 break; 4205 4206 case NUMBER: 4207 /* If we're in a numeric context, this should just be a 4208 number, by itself. */ 4209 if (context == context_numeric || 4210 context == context_data_or_numeric) { 4211 skip_token(&val, (unsigned *)0, cfile); 4212 if (!expression_allocate (expr, MDL)) 4213 log_fatal ("can't allocate expression"); 4214 (*expr) -> op = expr_const_int; 4215 (*expr) -> data.const_int = atoi (val); 4216 break; 4217 } 4218 4219 case NUMBER_OR_NAME: 4220 if (!expression_allocate (expr, MDL)) 4221 log_fatal ("can't allocate expression"); 4222 4223 (*expr) -> op = expr_const_data; 4224 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) { 4225 expression_dereference (expr, MDL); 4226 return 0; 4227 } 4228 break; 4229 4230 case NS_FORMERR: 4231 known = FORMERR; 4232 goto ns_const; 4233 ns_const: 4234 skip_token(&val, (unsigned *)0, cfile); 4235 if (!expression_allocate (expr, MDL)) 4236 log_fatal ("can't allocate expression"); 4237 (*expr) -> op = expr_const_int; 4238 (*expr) -> data.const_int = known; 4239 break; 4240 4241 case NS_NOERROR: 4242 known = ISC_R_SUCCESS; 4243 goto ns_const; 4244 4245 case NS_NOTAUTH: 4246 known = DHCP_R_NOTAUTH; 4247 goto ns_const; 4248 4249 case NS_NOTIMP: 4250 known = ISC_R_NOTIMPLEMENTED; 4251 goto ns_const; 4252 4253 case NS_NOTZONE: 4254 known = DHCP_R_NOTZONE; 4255 goto ns_const; 4256 4257 case NS_NXDOMAIN: 4258 known = DHCP_R_NXDOMAIN; 4259 goto ns_const; 4260 4261 case NS_NXRRSET: 4262 known = DHCP_R_NXRRSET; 4263 goto ns_const; 4264 4265 case NS_REFUSED: 4266 known = DHCP_R_REFUSED; 4267 goto ns_const; 4268 4269 case NS_SERVFAIL: 4270 known = DHCP_R_SERVFAIL; 4271 goto ns_const; 4272 4273 case NS_YXDOMAIN: 4274 known = DHCP_R_YXDOMAIN; 4275 goto ns_const; 4276 4277 case NS_YXRRSET: 4278 known = DHCP_R_YXRRSET; 4279 goto ns_const; 4280 4281 case BOOTING: 4282 known = S_INIT; 4283 goto ns_const; 4284 4285 case REBOOT: 4286 known = S_REBOOTING; 4287 goto ns_const; 4288 4289 case SELECT: 4290 known = S_SELECTING; 4291 goto ns_const; 4292 4293 case REQUEST: 4294 known = S_REQUESTING; 4295 goto ns_const; 4296 4297 case BOUND: 4298 known = S_BOUND; 4299 goto ns_const; 4300 4301 case RENEW: 4302 known = S_RENEWING; 4303 goto ns_const; 4304 4305 case REBIND: 4306 known = S_REBINDING; 4307 goto ns_const; 4308 4309 case DEFINED: 4310 skip_token(&val, (unsigned *)0, cfile); 4311 token = next_token (&val, (unsigned *)0, cfile); 4312 if (token != LPAREN) 4313 goto nolparen; 4314 4315 token = next_token (&val, (unsigned *)0, cfile); 4316 if (token != NAME && token != NUMBER_OR_NAME) { 4317 parse_warn (cfile, "%s can't be a variable name", val); 4318 skip_to_semi (cfile); 4319 *lose = 1; 4320 return 0; 4321 } 4322 4323 if (!expression_allocate (expr, MDL)) 4324 log_fatal ("can't allocate expression"); 4325 (*expr) -> op = expr_variable_exists; 4326 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL); 4327 if (!(*expr)->data.variable) 4328 log_fatal ("can't allocate variable name"); 4329 strcpy ((*expr) -> data.variable, val); 4330 token = next_token (&val, (unsigned *)0, cfile); 4331 if (token != RPAREN) 4332 goto norparen; 4333 break; 4334 4335 /* This parses 'gethostname()'. */ 4336 case GETHOSTNAME: 4337 skip_token(&val, NULL, cfile); 4338 if (!expression_allocate(expr, MDL)) 4339 log_fatal("can't allocate expression"); 4340 (*expr)->op = expr_gethostname; 4341 4342 token = next_token(NULL, NULL, cfile); 4343 if (token != LPAREN) 4344 goto nolparen; 4345 4346 token = next_token(NULL, NULL, cfile); 4347 if (token != RPAREN) 4348 goto norparen; 4349 break; 4350 4351 case GETHOSTBYNAME: 4352 skip_token(&val, NULL, cfile); 4353 token = next_token(NULL, NULL, cfile); 4354 if (token != LPAREN) 4355 goto nolparen; 4356 4357 /* The argument is a quoted string. */ 4358 token = next_token(&val, NULL, cfile); 4359 if (token != STRING) { 4360 parse_warn(cfile, "Expecting quoted literal: " 4361 "\"foo.example.com\""); 4362 skip_to_semi(cfile); 4363 *lose = 1; 4364 return 0; 4365 } 4366 if (!make_host_lookup(expr, val)) 4367 log_fatal("Error creating gethostbyname() internal " 4368 "record. (%s:%d)", MDL); 4369 4370 token = next_token(NULL, NULL, cfile); 4371 if (token != RPAREN) 4372 goto norparen; 4373 break; 4374 4375 case V6RELAY: 4376 skip_token(&val, NULL, cfile); 4377 if (!expression_allocate (expr, MDL)) 4378 log_fatal ("can't allocate expression"); 4379 (*expr)->op = expr_v6relay; 4380 4381 token = next_token (&val, NULL, cfile); 4382 if (token != LPAREN) 4383 goto nolparen; 4384 4385 if (!parse_numeric_expression (&(*expr)->data.v6relay.relay, 4386 cfile, lose)) 4387 goto nodata; 4388 4389 token = next_token (&val, NULL, cfile); 4390 if (token != COMMA) 4391 goto nocomma; 4392 4393 if (!parse_data_expression (&(*expr)->data.v6relay.roption, 4394 cfile, lose)) 4395 goto nodata; 4396 4397 token = next_token (&val, NULL, cfile); 4398 4399 if (token != RPAREN) 4400 goto norparen; 4401 break; 4402 4403 /* Not a valid start to an expression... */ 4404 default: 4405 if (token != NAME && token != NUMBER_OR_NAME) 4406 return 0; 4407 4408 skip_token(&val, (unsigned *)0, cfile); 4409 4410 /* Save the name of the variable being referenced. */ 4411 cptr = dmalloc (strlen (val) + 1, MDL); 4412 if (!cptr) 4413 log_fatal ("can't allocate variable name"); 4414 strcpy (cptr, val); 4415 4416 /* Simple variable reference, as far as we can tell. */ 4417 token = peek_token (&val, (unsigned *)0, cfile); 4418 if (token != LPAREN) { 4419 if (!expression_allocate (expr, MDL)) 4420 log_fatal ("can't allocate expression"); 4421 (*expr) -> op = expr_variable_reference; 4422 (*expr) -> data.variable = cptr; 4423 break; 4424 } 4425 4426 skip_token(&val, (unsigned *)0, cfile); 4427 if (!expression_allocate (expr, MDL)) 4428 log_fatal ("can't allocate expression"); 4429 (*expr) -> op = expr_funcall; 4430 (*expr) -> data.funcall.name = cptr; 4431 4432 /* Now parse the argument list. */ 4433 ep = &(*expr) -> data.funcall.arglist; 4434 do { 4435 if (!expression_allocate (ep, MDL)) 4436 log_fatal ("can't allocate expression"); 4437 (*ep) -> op = expr_arg; 4438 if (!parse_expression (&(*ep) -> data.arg.val, 4439 cfile, lose, context_any, 4440 (struct expression **)0, 4441 expr_none)) { 4442 if (!*lose) { 4443 parse_warn (cfile, 4444 "expecting expression."); 4445 *lose = 1; 4446 } 4447 skip_to_semi (cfile); 4448 expression_dereference (expr, MDL); 4449 return 0; 4450 } 4451 ep = &((*ep) -> data.arg.next); 4452 token = next_token (&val, (unsigned *)0, cfile); 4453 } while (token == COMMA); 4454 if (token != RPAREN) { 4455 parse_warn (cfile, "Right parenthesis expected."); 4456 skip_to_semi (cfile); 4457 *lose = 1; 4458 expression_dereference (expr, MDL); 4459 return 0; 4460 } 4461 break; 4462 } 4463 return 1; 4464 } 4465 4466 /* Parse an expression. */ 4467 4468 int parse_expression (expr, cfile, lose, context, plhs, binop) 4469 struct expression **expr; 4470 struct parse *cfile; 4471 int *lose; 4472 enum expression_context context; 4473 struct expression **plhs; 4474 enum expr_op binop; 4475 { 4476 enum dhcp_token token; 4477 const char *val; 4478 struct expression *rhs = (struct expression *)0, *tmp; 4479 struct expression *lhs = (struct expression *)0; 4480 enum expr_op next_op; 4481 enum expression_context 4482 lhs_context = context_any, 4483 rhs_context = context_any; 4484 4485 /* Consume the left hand side we were passed. */ 4486 if (plhs) { 4487 expression_reference (&lhs, *plhs, MDL); 4488 expression_dereference (plhs, MDL); 4489 } 4490 4491 new_rhs: 4492 if (!parse_non_binary (&rhs, cfile, lose, context)) { 4493 /* If we already have a left-hand side, then it's not 4494 okay for there not to be a right-hand side here, so 4495 we need to flag it as an error. */ 4496 if (lhs) { 4497 if (!*lose) { 4498 parse_warn (cfile, 4499 "expecting right-hand side."); 4500 *lose = 1; 4501 skip_to_semi (cfile); 4502 } 4503 expression_dereference (&lhs, MDL); 4504 } 4505 return 0; 4506 } 4507 4508 /* At this point, rhs contains either an entire subexpression, 4509 or at least a left-hand-side. If we do not see a binary token 4510 as the next token, we're done with the expression. */ 4511 4512 token = peek_token (&val, (unsigned *)0, cfile); 4513 switch (token) { 4514 case BANG: 4515 skip_token(&val, (unsigned *)0, cfile); 4516 token = peek_token (&val, (unsigned *)0, cfile); 4517 if (token != EQUAL) { 4518 parse_warn (cfile, "! in boolean context without ="); 4519 *lose = 1; 4520 skip_to_semi (cfile); 4521 if (lhs) 4522 expression_dereference (&lhs, MDL); 4523 return 0; 4524 } 4525 next_op = expr_not_equal; 4526 context = expression_context (rhs); 4527 break; 4528 4529 case EQUAL: 4530 next_op = expr_equal; 4531 context = expression_context (rhs); 4532 break; 4533 4534 case TILDE: 4535 #ifdef HAVE_REGEX_H 4536 skip_token(&val, NULL, cfile); 4537 token = peek_token(&val, NULL, cfile); 4538 4539 if (token == TILDE) 4540 next_op = expr_iregex_match; 4541 else if (token == EQUAL) 4542 next_op = expr_regex_match; 4543 else { 4544 parse_warn(cfile, "expecting ~= or ~~ operator"); 4545 *lose = 1; 4546 skip_to_semi(cfile); 4547 if (lhs) 4548 expression_dereference(&lhs, MDL); 4549 return 0; 4550 } 4551 4552 context = expression_context(rhs); 4553 #else 4554 parse_warn(cfile, "No support for regex operator."); 4555 *lose = 1; 4556 skip_to_semi(cfile); 4557 if (lhs != NULL) 4558 expression_dereference(&lhs, MDL); 4559 return 0; 4560 #endif 4561 break; 4562 4563 case AND: 4564 next_op = expr_and; 4565 context = expression_context (rhs); 4566 break; 4567 4568 case OR: 4569 next_op = expr_or; 4570 context = expression_context (rhs); 4571 break; 4572 4573 case PLUS: 4574 next_op = expr_add; 4575 context = expression_context (rhs); 4576 break; 4577 4578 case MINUS: 4579 next_op = expr_subtract; 4580 context = expression_context (rhs); 4581 break; 4582 4583 case SLASH: 4584 next_op = expr_divide; 4585 context = expression_context (rhs); 4586 break; 4587 4588 case ASTERISK: 4589 next_op = expr_multiply; 4590 context = expression_context (rhs); 4591 break; 4592 4593 case PERCENT: 4594 next_op = expr_remainder; 4595 context = expression_context (rhs); 4596 break; 4597 4598 case AMPERSAND: 4599 next_op = expr_binary_and; 4600 context = expression_context (rhs); 4601 break; 4602 4603 case PIPE: 4604 next_op = expr_binary_or; 4605 context = expression_context (rhs); 4606 break; 4607 4608 case CARET: 4609 next_op = expr_binary_xor; 4610 context = expression_context (rhs); 4611 break; 4612 4613 default: 4614 next_op = expr_none; 4615 } 4616 4617 /* If we have no lhs yet, we just parsed it. */ 4618 if (!lhs) { 4619 /* If there was no operator following what we just parsed, 4620 then we're done - return it. */ 4621 if (next_op == expr_none) { 4622 *expr = rhs; 4623 return 1; 4624 } 4625 lhs = rhs; 4626 rhs = (struct expression *)0; 4627 binop = next_op; 4628 skip_token(&val, (unsigned *)0, cfile); 4629 goto new_rhs; 4630 } 4631 4632 /* If the next binary operator is of greater precedence than the 4633 * current operator, then rhs we have parsed so far is actually 4634 * the lhs of the next operator. To get this value, we have to 4635 * recurse. 4636 */ 4637 if (binop != expr_none && next_op != expr_none && 4638 op_precedence (binop, next_op) < 0) { 4639 4640 /* Eat the subexpression operator token, which we pass to 4641 * parse_expression...we only peek()'d earlier. 4642 */ 4643 skip_token(&val, (unsigned *)0, cfile); 4644 4645 /* Continue parsing of the right hand side with that token. */ 4646 tmp = rhs; 4647 rhs = (struct expression *)0; 4648 if (!parse_expression (&rhs, cfile, lose, op_context (next_op), 4649 &tmp, next_op)) { 4650 if (!*lose) { 4651 parse_warn (cfile, 4652 "expecting a subexpression"); 4653 *lose = 1; 4654 } 4655 return 0; 4656 } 4657 next_op = expr_none; 4658 } 4659 4660 if (binop != expr_none) { 4661 rhs_context = expression_context(rhs); 4662 lhs_context = expression_context(lhs); 4663 4664 if ((rhs_context != context_any) && (lhs_context != context_any) && 4665 (rhs_context != lhs_context)) { 4666 parse_warn (cfile, "illegal expression relating different types"); 4667 skip_to_semi (cfile); 4668 expression_dereference (&rhs, MDL); 4669 expression_dereference (&lhs, MDL); 4670 *lose = 1; 4671 return 0; 4672 } 4673 4674 switch(binop) { 4675 case expr_not_equal: 4676 case expr_equal: 4677 if ((rhs_context != context_data_or_numeric) && 4678 (rhs_context != context_data) && 4679 (rhs_context != context_numeric) && 4680 (rhs_context != context_any)) { 4681 parse_warn (cfile, "expecting data/numeric expression"); 4682 skip_to_semi (cfile); 4683 expression_dereference (&rhs, MDL); 4684 *lose = 1; 4685 return 0; 4686 } 4687 break; 4688 4689 case expr_regex_match: 4690 #ifdef HAVE_REGEX_H 4691 if (expression_context(rhs) != context_data) { 4692 parse_warn(cfile, "expecting data expression"); 4693 skip_to_semi(cfile); 4694 expression_dereference(&rhs, MDL); 4695 *lose = 1; 4696 return 0; 4697 } 4698 #else 4699 /* It should not be possible to attempt to parse the right 4700 * hand side of an operator there is no support for. 4701 */ 4702 log_fatal("Impossible condition at %s:%d.", MDL); 4703 #endif 4704 break; 4705 4706 case expr_and: 4707 case expr_or: 4708 if ((rhs_context != context_boolean) && 4709 (rhs_context != context_any)) { 4710 parse_warn (cfile, "expecting boolean expressions"); 4711 skip_to_semi (cfile); 4712 expression_dereference (&rhs, MDL); 4713 *lose = 1; 4714 return 0; 4715 } 4716 break; 4717 4718 case expr_add: 4719 case expr_subtract: 4720 case expr_divide: 4721 case expr_multiply: 4722 case expr_remainder: 4723 case expr_binary_and: 4724 case expr_binary_or: 4725 case expr_binary_xor: 4726 if ((rhs_context != context_numeric) && 4727 (rhs_context != context_any)) { 4728 parse_warn (cfile, "expecting numeric expressions"); 4729 skip_to_semi (cfile); 4730 expression_dereference (&rhs, MDL); 4731 *lose = 1; 4732 return 0; 4733 } 4734 break; 4735 4736 default: 4737 break; 4738 } 4739 } 4740 4741 /* Now, if we didn't find a binary operator, we're done parsing 4742 this subexpression, so combine it with the preceding binary 4743 operator and return the result. */ 4744 if (next_op == expr_none) { 4745 if (!expression_allocate (expr, MDL)) 4746 log_fatal ("Can't allocate expression!"); 4747 4748 (*expr) -> op = binop; 4749 /* All the binary operators' data union members 4750 are the same, so we'll cheat and use the member 4751 for the equals operator. */ 4752 (*expr) -> data.equal [0] = lhs; 4753 (*expr) -> data.equal [1] = rhs; 4754 return 1; 4755 } 4756 4757 /* Eat the operator token - we now know it was a binary operator... */ 4758 skip_token(&val, (unsigned *)0, cfile); 4759 4760 /* Now combine the LHS and the RHS using binop. */ 4761 tmp = (struct expression *)0; 4762 if (!expression_allocate (&tmp, MDL)) 4763 log_fatal ("No memory for equal precedence combination."); 4764 4765 /* Store the LHS and RHS. */ 4766 tmp -> data.equal [0] = lhs; 4767 tmp -> data.equal [1] = rhs; 4768 tmp -> op = binop; 4769 4770 lhs = tmp; 4771 tmp = (struct expression *)0; 4772 rhs = (struct expression *)0; 4773 4774 binop = next_op; 4775 goto new_rhs; 4776 } 4777 4778 4779 int parse_option_data (expr, cfile, lookups, option) 4780 struct expression **expr; 4781 struct parse *cfile; 4782 int lookups; 4783 struct option *option; 4784 { 4785 const char *val; 4786 const char *fmt = NULL; 4787 struct expression *tmp; 4788 enum dhcp_token token; 4789 4790 do { 4791 /* 4792 * Set a flag if this is an array of a simple type (i.e., 4793 * not an array of pairs of IP addresses, or something like 4794 * that. 4795 */ 4796 int uniform = 0; 4797 4798 and_again: 4799 /* Set fmt to start of format for 'A' and one char back 4800 * for 'a'. 4801 */ 4802 if ((fmt != NULL) && (fmt != option->format) && (*fmt == 'a')) 4803 fmt -= 1; 4804 else if ((fmt == NULL) || (*fmt == 'A')) 4805 fmt = option->format; 4806 4807 /* 'a' means always uniform */ 4808 if ((fmt[0] != 'Z') && (tolower((unsigned char)fmt[1]) == 'a')) 4809 uniform = 1; 4810 4811 do { 4812 if ((*fmt == 'A') || (*fmt == 'a')) 4813 break; 4814 if (*fmt == 'o') { 4815 /* consume the optional flag */ 4816 fmt++; 4817 continue; 4818 } 4819 4820 if (fmt[1] == 'o') { 4821 /* 4822 * A value for the current format is 4823 * optional - check to see if the next 4824 * token is a semi-colon if so we don't 4825 * need to parse it and doing so would 4826 * consume the semi-colon which our 4827 * caller is expecting to parse 4828 */ 4829 token = peek_token(&val, (unsigned *)0, 4830 cfile); 4831 if (token == SEMI) { 4832 fmt++; 4833 continue; 4834 } 4835 } 4836 4837 tmp = *expr; 4838 *expr = NULL; 4839 4840 if (!parse_option_token(expr, cfile, &fmt, tmp, 4841 uniform, lookups)) { 4842 if (fmt [1] != 'o') { 4843 if (tmp) 4844 expression_dereference (&tmp, 4845 MDL); 4846 return 0; 4847 } 4848 *expr = tmp; 4849 tmp = NULL; 4850 } 4851 if (tmp) 4852 expression_dereference (&tmp, MDL); 4853 4854 fmt++; 4855 } while (*fmt != '\0'); 4856 4857 if ((*fmt == 'A') || (*fmt == 'a')) { 4858 token = peek_token (&val, (unsigned *)0, cfile); 4859 /* Comma means: continue with next element in array */ 4860 if (token == COMMA) { 4861 skip_token(&val, (unsigned *)0, cfile); 4862 continue; 4863 } 4864 /* no comma: end of array. 4865 'A' or end of string means: leave the loop */ 4866 if ((*fmt == 'A') || (fmt[1] == '\0')) 4867 break; 4868 /* 'a' means: go on with next char */ 4869 if (*fmt == 'a') { 4870 fmt++; 4871 goto and_again; 4872 } 4873 } 4874 } while ((*fmt == 'A') || (*fmt == 'a')); 4875 4876 return 1; 4877 } 4878 4879 /* option-statement :== identifier DOT identifier <syntax> SEMI 4880 | identifier <syntax> SEMI 4881 4882 Option syntax is handled specially through format strings, so it 4883 would be painful to come up with BNF for it. However, it always 4884 starts as above and ends in a SEMI. */ 4885 4886 int parse_option_statement (result, cfile, lookups, option, op) 4887 struct executable_statement **result; 4888 struct parse *cfile; 4889 int lookups; 4890 struct option *option; 4891 enum statement_op op; 4892 { 4893 const char *val; 4894 enum dhcp_token token; 4895 struct expression *expr = (struct expression *)0; 4896 int lose; 4897 4898 token = peek_token (&val, (unsigned *)0, cfile); 4899 if ((token == SEMI) && (option->format[0] != 'Z')) { 4900 /* Eat the semicolon... */ 4901 /* 4902 * XXXSK: I'm not sure why we should ever get here, but we 4903 * do during our startup. This confuses things if 4904 * we are parsing a zero-length option, so don't 4905 * eat the semicolon token in that case. 4906 */ 4907 skip_token(&val, (unsigned *)0, cfile); 4908 } else if (token == EQUAL) { 4909 /* Eat the equals sign. */ 4910 skip_token(&val, (unsigned *)0, cfile); 4911 4912 /* Parse a data expression and use its value for the data. */ 4913 if (!parse_data_expression (&expr, cfile, &lose)) { 4914 /* In this context, we must have an executable 4915 statement, so if we found something else, it's 4916 still an error. */ 4917 if (!lose) { 4918 parse_warn (cfile, 4919 "expecting a data expression."); 4920 skip_to_semi (cfile); 4921 } 4922 return 0; 4923 } 4924 } else { 4925 if (! parse_option_data(&expr, cfile, lookups, option)) 4926 return 0; 4927 } 4928 4929 if (!parse_semi (cfile)) 4930 return 0; 4931 if (!executable_statement_allocate (result, MDL)) 4932 log_fatal ("no memory for option statement."); 4933 4934 (*result)->op = op; 4935 if (expr && !option_cache (&(*result)->data.option, 4936 NULL, expr, option, MDL)) 4937 log_fatal ("no memory for option cache"); 4938 4939 if (expr) 4940 expression_dereference (&expr, MDL); 4941 4942 return 1; 4943 } 4944 4945 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) 4946 struct expression **rv; 4947 struct parse *cfile; 4948 const char **fmt; 4949 struct expression *expr; 4950 int uniform; 4951 int lookups; 4952 { 4953 const char *val; 4954 enum dhcp_token token; 4955 struct expression *t = (struct expression *)0; 4956 unsigned char buf [4]; 4957 unsigned len; 4958 struct iaddr addr; 4959 int compress; 4960 isc_boolean_t freeval = ISC_FALSE; 4961 const char *f, *g; 4962 struct enumeration_value *e; 4963 4964 switch (**fmt) { 4965 case 'U': 4966 token = next_token (&val, &len, cfile); 4967 if (!is_identifier (token)) { 4968 if ((*fmt) [1] != 'o') { 4969 parse_warn (cfile, "expecting identifier."); 4970 if (token != SEMI) 4971 skip_to_semi (cfile); 4972 } 4973 return 0; 4974 } 4975 if (!make_const_data (&t, (const unsigned char *)val, 4976 len, 1, 1, MDL)) 4977 log_fatal ("No memory for %s", val); 4978 break; 4979 4980 case 'E': 4981 g = strchr (*fmt, '.'); 4982 if (!g) { 4983 parse_warn (cfile, 4984 "malformed encapsulation format (bug!)"); 4985 skip_to_semi (cfile); 4986 return 0; 4987 } 4988 *fmt = g; 4989 /* FALL THROUGH */ 4990 /* to get string value for the option */ 4991 case 'X': 4992 token = peek_token (&val, (unsigned *)0, cfile); 4993 if (token == NUMBER_OR_NAME || token == NUMBER) { 4994 if (!expression_allocate (&t, MDL)) 4995 return 0; 4996 if (!parse_cshl (&t -> data.const_data, cfile)) { 4997 expression_dereference (&t, MDL); 4998 return 0; 4999 } 5000 t -> op = expr_const_data; 5001 } else { 5002 token = next_token (&val, &len, cfile); 5003 5004 if(token == STRING) { 5005 if (!make_const_data (&t, 5006 (const unsigned char *)val, 5007 len, 1, 1, MDL)) 5008 log_fatal ("No memory for \"%s\"", val); 5009 } else { 5010 if ((*fmt) [1] != 'o') { 5011 parse_warn (cfile, "expecting string " 5012 "or hexadecimal data."); 5013 skip_to_semi (cfile); 5014 } 5015 return 0; 5016 } 5017 } 5018 break; 5019 5020 case 'D': /* Domain list... */ 5021 if ((*fmt)[1] == 'c') { 5022 compress = 1; 5023 /* Skip the compress-flag atom. */ 5024 (*fmt)++; 5025 } else 5026 compress = 0; 5027 5028 t = parse_domain_list(cfile, compress); 5029 5030 if (!t) { 5031 if ((*fmt)[1] != 'o') 5032 skip_to_semi(cfile); 5033 return 0; 5034 } 5035 5036 break; 5037 5038 case 'd': /* Domain name... */ 5039 val = parse_host_name (cfile); 5040 if (!val) { 5041 parse_warn (cfile, "not a valid domain name."); 5042 skip_to_semi (cfile); 5043 return 0; 5044 } 5045 len = strlen (val); 5046 freeval = ISC_TRUE; 5047 goto make_string; 5048 5049 case 't': /* Text string... */ 5050 token = next_token (&val, &len, cfile); 5051 if (token != STRING && !is_identifier (token)) { 5052 if ((*fmt) [1] != 'o') { 5053 parse_warn (cfile, "expecting string."); 5054 if (token != SEMI) 5055 skip_to_semi (cfile); 5056 } 5057 return 0; 5058 } 5059 make_string: 5060 if (!make_const_data (&t, (const unsigned char *)val, 5061 len, 1, 1, MDL)) 5062 log_fatal ("No memory for concatenation"); 5063 if (freeval == ISC_TRUE) { 5064 dfree((char *)val, MDL); 5065 freeval = ISC_FALSE; 5066 POST(freeval); 5067 } 5068 break; 5069 5070 case 'N': 5071 f = (*fmt) + 1; 5072 g = strchr (*fmt, '.'); 5073 if (!g) { 5074 parse_warn (cfile, "malformed %s (bug!)", 5075 "enumeration format"); 5076 foo: 5077 skip_to_semi (cfile); 5078 return 0; 5079 } 5080 *fmt = g; 5081 token = next_token (&val, (unsigned *)0, cfile); 5082 if (!is_identifier (token)) { 5083 parse_warn (cfile, 5084 "identifier expected"); 5085 goto foo; 5086 } 5087 e = find_enumeration_value (f, (*fmt) - f, &len, val); 5088 if (!e) { 5089 parse_warn (cfile, "unknown value"); 5090 goto foo; 5091 } 5092 if (!make_const_data (&t, &e -> value, len, 0, 1, MDL)) 5093 return 0; 5094 break; 5095 5096 case 'I': /* IP address or hostname. */ 5097 if (lookups) { 5098 if (!parse_ip_addr_or_hostname (&t, cfile, uniform)) 5099 return 0; 5100 } else { 5101 if (!parse_ip_addr (cfile, &addr)) 5102 return 0; 5103 if (!make_const_data (&t, addr.iabuf, addr.len, 5104 0, 1, MDL)) 5105 return 0; 5106 } 5107 break; 5108 5109 case '6': /* IPv6 address. */ 5110 if (!parse_ip6_addr(cfile, &addr)) { 5111 return 0; 5112 } 5113 if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) { 5114 return 0; 5115 } 5116 break; 5117 5118 case 'T': /* Lease interval. */ 5119 token = next_token (&val, (unsigned *)0, cfile); 5120 if (token != INFINITE) 5121 goto check_number; 5122 putLong (buf, -1); 5123 if (!make_const_data (&t, buf, 4, 0, 1, MDL)) 5124 return 0; 5125 break; 5126 5127 case 'L': /* Unsigned 32-bit integer... */ 5128 case 'l': /* Signed 32-bit integer... */ 5129 token = next_token (&val, (unsigned *)0, cfile); 5130 check_number: 5131 if ((token != NUMBER) && (token != NUMBER_OR_NAME)) { 5132 need_number: 5133 if ((*fmt) [1] != 'o') { 5134 parse_warn (cfile, "expecting number."); 5135 if (token != SEMI) 5136 skip_to_semi (cfile); 5137 } 5138 return 0; 5139 } 5140 convert_num (cfile, buf, val, 0, 32); 5141 if (!make_const_data (&t, buf, 4, 0, 1, MDL)) 5142 return 0; 5143 break; 5144 5145 case 's': /* Signed 16-bit integer. */ 5146 case 'S': /* Unsigned 16-bit integer. */ 5147 token = next_token (&val, (unsigned *)0, cfile); 5148 if ((token != NUMBER) && (token != NUMBER_OR_NAME)) 5149 goto need_number; 5150 convert_num (cfile, buf, val, 0, 16); 5151 if (!make_const_data (&t, buf, 2, 0, 1, MDL)) 5152 return 0; 5153 break; 5154 5155 case 'b': /* Signed 8-bit integer. */ 5156 case 'B': /* Unsigned 8-bit integer. */ 5157 token = next_token (&val, (unsigned *)0, cfile); 5158 if ((token != NUMBER) && (token != NUMBER_OR_NAME)) 5159 goto need_number; 5160 convert_num (cfile, buf, val, 0, 8); 5161 if (!make_const_data (&t, buf, 1, 0, 1, MDL)) 5162 return 0; 5163 break; 5164 5165 case 'f': /* Boolean flag. */ 5166 token = next_token (&val, (unsigned *)0, cfile); 5167 if (!is_identifier (token)) { 5168 if ((*fmt) [1] != 'o') 5169 parse_warn (cfile, "expecting identifier."); 5170 bad_flag: 5171 if ((*fmt) [1] != 'o') { 5172 if (token != SEMI) 5173 skip_to_semi (cfile); 5174 } 5175 return 0; 5176 } 5177 if (!strcasecmp (val, "true") 5178 || !strcasecmp (val, "on")) 5179 buf [0] = 1; 5180 else if (!strcasecmp (val, "false") 5181 || !strcasecmp (val, "off")) 5182 buf [0] = 0; 5183 else if (!strcasecmp (val, "ignore")) 5184 buf [0] = 2; 5185 else { 5186 if ((*fmt) [1] != 'o') 5187 parse_warn (cfile, "expecting boolean."); 5188 goto bad_flag; 5189 } 5190 if (!make_const_data (&t, buf, 1, 0, 1, MDL)) 5191 return 0; 5192 break; 5193 5194 case 'Z': /* Zero-length option. */ 5195 token = peek_token (&val, (unsigned *)0, cfile); 5196 if (token != SEMI) { 5197 parse_warn(cfile, "semicolon expected."); 5198 skip_to_semi(cfile); 5199 } 5200 buf[0] = '\0'; 5201 if (!make_const_data(&t, /* expression */ 5202 buf, /* buffer */ 5203 0, /* length */ 5204 0, /* terminated */ 5205 1, /* allocate */ 5206 MDL)) 5207 return 0; 5208 break; 5209 5210 default: 5211 parse_warn (cfile, "Bad format '%c' in parse_option_token.", 5212 **fmt); 5213 skip_to_semi (cfile); 5214 return 0; 5215 } 5216 if (expr) { 5217 if (!make_concat (rv, expr, t)) 5218 return 0; 5219 } else 5220 expression_reference (rv, t, MDL); 5221 expression_dereference (&t, MDL); 5222 return 1; 5223 } 5224 5225 int parse_option_decl (oc, cfile) 5226 struct option_cache **oc; 5227 struct parse *cfile; 5228 { 5229 const char *val; 5230 int token; 5231 u_int8_t buf [4]; 5232 u_int8_t hunkbuf [1024]; 5233 unsigned hunkix = 0; 5234 const char *fmt, *f; 5235 struct option *option=NULL; 5236 struct iaddr ip_addr; 5237 u_int8_t *dp; 5238 const u_int8_t *cdp; 5239 unsigned len; 5240 int nul_term = 0; 5241 struct buffer *bp; 5242 int known = 0; 5243 int compress; 5244 struct expression *express = NULL; 5245 struct enumeration_value *e; 5246 isc_result_t status; 5247 5248 status = parse_option_name (cfile, 0, &known, &option); 5249 if (status != ISC_R_SUCCESS || option == NULL) 5250 return 0; 5251 5252 fmt = option->format; 5253 5254 /* Parse the option data... */ 5255 do { 5256 for (; *fmt; fmt++) { 5257 if (*fmt == 'A') { 5258 /* 'A' is an array of records, start at 5259 * the beginning 5260 */ 5261 fmt = option->format; 5262 break; 5263 } 5264 5265 if (*fmt == 'a') { 5266 /* 'a' is an array of the last field, 5267 * back up one format character 5268 */ 5269 fmt--; 5270 break; 5271 } 5272 if (*fmt == 'o' && fmt != option -> format) 5273 continue; 5274 switch (*fmt) { 5275 case 'E': 5276 fmt = strchr (fmt, '.'); 5277 if (!fmt) { 5278 parse_warn (cfile, 5279 "malformed %s (bug!)", 5280 "encapsulation format"); 5281 goto parse_exit; 5282 } 5283 /* FALL THROUGH */ 5284 /* to get string value for the option */ 5285 case 'X': 5286 len = parse_X (cfile, &hunkbuf [hunkix], 5287 sizeof hunkbuf - hunkix); 5288 hunkix += len; 5289 break; 5290 5291 case 't': /* Text string... */ 5292 token = peek_token (&val, 5293 &len, cfile); 5294 if (token == SEMI && fmt[1] == 'o') { 5295 fmt++; 5296 break; 5297 } 5298 token = next_token (&val, 5299 &len, cfile); 5300 if (token != STRING) { 5301 parse_warn (cfile, 5302 "expecting string."); 5303 goto parse_exit; 5304 } 5305 if (hunkix + len + 1 > sizeof hunkbuf) { 5306 parse_warn (cfile, 5307 "option data buffer %s", 5308 "overflow"); 5309 goto parse_exit; 5310 } 5311 memcpy (&hunkbuf [hunkix], val, len + 1); 5312 nul_term = 1; 5313 hunkix += len; 5314 break; 5315 5316 case 'D': 5317 if (fmt[1] == 'c') { 5318 compress = 1; 5319 fmt++; 5320 } else 5321 compress = 0; 5322 5323 express = parse_domain_list(cfile, compress); 5324 5325 if (express == NULL) 5326 goto exit; 5327 5328 if (express->op != expr_const_data) { 5329 parse_warn(cfile, "unexpected " 5330 "expression"); 5331 goto parse_exit; 5332 } 5333 5334 len = express->data.const_data.len; 5335 cdp = express->data.const_data.data; 5336 5337 if ((hunkix + len) > sizeof(hunkbuf)) { 5338 parse_warn(cfile, "option data buffer " 5339 "overflow"); 5340 goto parse_exit; 5341 } 5342 memcpy(&hunkbuf[hunkix], cdp, len); 5343 hunkix += len; 5344 5345 expression_dereference(&express, MDL); 5346 break; 5347 5348 case 'N': 5349 f = fmt + 1; 5350 fmt = strchr (fmt, '.'); 5351 if (!fmt) { 5352 parse_warn (cfile, 5353 "malformed %s (bug!)", 5354 "enumeration format"); 5355 goto parse_exit; 5356 } 5357 token = next_token (&val, 5358 (unsigned *)0, cfile); 5359 if (!is_identifier (token)) { 5360 parse_warn (cfile, 5361 "identifier expected"); 5362 goto parse_exit; 5363 } 5364 e = find_enumeration_value (f, fmt - f, 5365 &len, val); 5366 if (!e) { 5367 parse_warn (cfile, 5368 "unknown value"); 5369 goto parse_exit; 5370 } 5371 dp = &e -> value; 5372 goto alloc; 5373 5374 case '6': 5375 if (!parse_ip6_addr(cfile, &ip_addr)) 5376 goto exit; 5377 len = ip_addr.len; 5378 dp = ip_addr.iabuf; 5379 goto alloc; 5380 5381 case 'I': /* IP address. */ 5382 if (!parse_ip_addr (cfile, &ip_addr)) 5383 goto exit; 5384 len = ip_addr.len; 5385 dp = ip_addr.iabuf; 5386 5387 alloc: 5388 if (hunkix + len > sizeof hunkbuf) { 5389 parse_warn (cfile, 5390 "option data buffer %s", 5391 "overflow"); 5392 goto parse_exit; 5393 } 5394 memcpy (&hunkbuf [hunkix], dp, len); 5395 hunkix += len; 5396 break; 5397 5398 case 'L': /* Unsigned 32-bit integer... */ 5399 case 'l': /* Signed 32-bit integer... */ 5400 token = next_token (&val, 5401 (unsigned *)0, cfile); 5402 if ((token != NUMBER) && 5403 (token != NUMBER_OR_NAME)) { 5404 need_number: 5405 parse_warn (cfile, 5406 "expecting number."); 5407 if (token != SEMI) 5408 goto parse_exit; 5409 else 5410 goto exit; 5411 } 5412 convert_num (cfile, buf, val, 0, 32); 5413 len = 4; 5414 dp = buf; 5415 goto alloc; 5416 5417 case 's': /* Signed 16-bit integer. */ 5418 case 'S': /* Unsigned 16-bit integer. */ 5419 token = next_token (&val, 5420 (unsigned *)0, cfile); 5421 if ((token != NUMBER) && 5422 (token != NUMBER_OR_NAME)) 5423 goto need_number; 5424 convert_num (cfile, buf, val, 0, 16); 5425 len = 2; 5426 dp = buf; 5427 goto alloc; 5428 5429 case 'b': /* Signed 8-bit integer. */ 5430 case 'B': /* Unsigned 8-bit integer. */ 5431 token = next_token (&val, 5432 (unsigned *)0, cfile); 5433 if ((token != NUMBER) && 5434 (token != NUMBER_OR_NAME)) 5435 goto need_number; 5436 convert_num (cfile, buf, val, 0, 8); 5437 len = 1; 5438 dp = buf; 5439 goto alloc; 5440 5441 case 'f': /* Boolean flag. */ 5442 token = next_token (&val, 5443 (unsigned *)0, cfile); 5444 if (!is_identifier (token)) { 5445 parse_warn (cfile, 5446 "expecting identifier."); 5447 bad_flag: 5448 if (token != SEMI) 5449 goto parse_exit; 5450 else 5451 goto exit; 5452 } 5453 if (!strcasecmp (val, "true") 5454 || !strcasecmp (val, "on")) 5455 buf [0] = 1; 5456 else if (!strcasecmp (val, "false") 5457 || !strcasecmp (val, "off")) 5458 buf [0] = 0; 5459 else { 5460 parse_warn (cfile, 5461 "expecting boolean."); 5462 goto bad_flag; 5463 } 5464 len = 1; 5465 dp = buf; 5466 goto alloc; 5467 5468 case 'Z': /* Zero-length option */ 5469 token = peek_token(&val, (unsigned *)0, cfile); 5470 if (token != SEMI) { 5471 parse_warn(cfile, 5472 "semicolon expected."); 5473 goto parse_exit; 5474 } 5475 len = 0; 5476 buf[0] = '\0'; 5477 break; 5478 5479 default: 5480 log_error ("parse_option_param: Bad format %c", 5481 *fmt); 5482 goto parse_exit; 5483 } 5484 } 5485 token = next_token (&val, (unsigned *)0, cfile); 5486 } while (*fmt && token == COMMA); 5487 5488 if (token != SEMI) { 5489 parse_warn (cfile, "semicolon expected."); 5490 goto parse_exit; 5491 } 5492 5493 bp = (struct buffer *)0; 5494 if (!buffer_allocate (&bp, hunkix + nul_term, MDL)) 5495 log_fatal ("no memory to store option declaration."); 5496 memcpy (bp -> data, hunkbuf, hunkix + nul_term); 5497 5498 if (!option_cache_allocate (oc, MDL)) 5499 log_fatal ("out of memory allocating option cache."); 5500 5501 (*oc) -> data.buffer = bp; 5502 (*oc) -> data.data = &bp -> data [0]; 5503 (*oc) -> data.terminated = nul_term; 5504 (*oc) -> data.len = hunkix; 5505 option_reference(&(*oc)->option, option, MDL); 5506 option_dereference(&option, MDL); 5507 return 1; 5508 5509 parse_exit: 5510 if (express != NULL) 5511 expression_dereference(&express, MDL); 5512 skip_to_semi (cfile); 5513 exit: 5514 option_dereference(&option, MDL); 5515 5516 return 0; 5517 } 5518 5519 /* Consider merging parse_cshl into this. */ 5520 5521 int parse_X (cfile, buf, max) 5522 struct parse *cfile; 5523 u_int8_t *buf; 5524 unsigned max; 5525 { 5526 int token; 5527 const char *val; 5528 unsigned len; 5529 5530 token = peek_token (&val, (unsigned *)0, cfile); 5531 if (token == NUMBER_OR_NAME || token == NUMBER) { 5532 len = 0; 5533 do { 5534 token = next_token (&val, (unsigned *)0, cfile); 5535 if (token != NUMBER && token != NUMBER_OR_NAME) { 5536 parse_warn (cfile, 5537 "expecting hexadecimal constant."); 5538 skip_to_semi (cfile); 5539 return 0; 5540 } 5541 convert_num (cfile, &buf [len], val, 16, 8); 5542 if (len++ > max) { 5543 parse_warn (cfile, 5544 "hexadecimal constant too long."); 5545 skip_to_semi (cfile); 5546 return 0; 5547 } 5548 token = peek_token (&val, (unsigned *)0, cfile); 5549 if (token == COLON) 5550 token = next_token (&val, 5551 (unsigned *)0, cfile); 5552 } while (token == COLON); 5553 val = (char *)buf; 5554 } else if (token == STRING) { 5555 skip_token(&val, &len, cfile); 5556 if (len + 1 > max) { 5557 parse_warn (cfile, "string constant too long."); 5558 skip_to_semi (cfile); 5559 return 0; 5560 } 5561 memcpy (buf, val, len + 1); 5562 } else { 5563 parse_warn (cfile, "expecting string or hexadecimal data"); 5564 skip_to_semi (cfile); 5565 return 0; 5566 } 5567 return len; 5568 } 5569 5570 int parse_warn (struct parse *cfile, const char *fmt, ...) 5571 { 5572 va_list list; 5573 char lexbuf [256]; 5574 char mbuf [1024]; 5575 char fbuf [1024]; 5576 unsigned i, lix; 5577 5578 do_percentm (mbuf, fmt); 5579 /* %Audit% This is log output. %2004.06.17,Safe% 5580 * If we truncate we hope the user can get a hint from the log. 5581 */ 5582 snprintf (fbuf, sizeof fbuf, "%s line %d: %s", 5583 cfile -> tlname, cfile -> lexline, mbuf); 5584 5585 va_start (list, fmt); 5586 vsnprintf (mbuf, sizeof mbuf, fbuf, list); 5587 va_end (list); 5588 5589 lix = 0; 5590 for (i = 0; 5591 cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) { 5592 if (lix < (sizeof lexbuf) - 1) 5593 lexbuf [lix++] = ' '; 5594 if (cfile -> token_line [i] == '\t') { 5595 for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++) 5596 lexbuf [lix] = ' '; 5597 } 5598 } 5599 lexbuf [lix] = 0; 5600 5601 #ifndef DEBUG 5602 syslog (LOG_ERR, "%s", mbuf); 5603 syslog (LOG_ERR, "%s", cfile -> token_line); 5604 if (cfile -> lexchar < 81) 5605 syslog (LOG_ERR, "%s^", lexbuf); 5606 #endif 5607 5608 if (log_perror) { 5609 IGNORE_RET (write (STDERR_FILENO, mbuf, strlen (mbuf))); 5610 IGNORE_RET (write (STDERR_FILENO, "\n", 1)); 5611 IGNORE_RET (write (STDERR_FILENO, cfile -> token_line, 5612 strlen (cfile -> token_line))); 5613 IGNORE_RET (write (STDERR_FILENO, "\n", 1)); 5614 if (cfile -> lexchar < 81) 5615 IGNORE_RET (write (STDERR_FILENO, lexbuf, lix)); 5616 IGNORE_RET (write (STDERR_FILENO, "^\n", 2)); 5617 } 5618 5619 cfile -> warnings_occurred = 1; 5620 5621 return 0; 5622 } 5623 5624 struct expression * 5625 parse_domain_list(struct parse *cfile, int compress) 5626 { 5627 const char *val; 5628 enum dhcp_token token = SEMI; 5629 struct expression *t = NULL; 5630 unsigned len, clen = 0; 5631 int result; 5632 unsigned char compbuf[256 * NS_MAXCDNAME]; 5633 const unsigned char *dnptrs[256], **lastdnptr; 5634 5635 memset(compbuf, 0, sizeof(compbuf)); 5636 memset(dnptrs, 0, sizeof(dnptrs)); 5637 dnptrs[0] = compbuf; 5638 lastdnptr = &dnptrs[255]; 5639 5640 do { 5641 /* Consume the COMMA token if peeked. */ 5642 if (token == COMMA) 5643 skip_token(&val, NULL, cfile); 5644 5645 /* Get next (or first) value. */ 5646 token = next_token(&val, &len, cfile); 5647 5648 if (token != STRING) { 5649 parse_warn(cfile, "Expecting a domain string."); 5650 return NULL; 5651 } 5652 5653 /* If compression pointers are enabled, compress. If not, 5654 * just pack the names in series into the buffer. 5655 */ 5656 if (compress) { 5657 result = MRns_name_compress(val, compbuf + clen, 5658 sizeof(compbuf) - clen, 5659 dnptrs, lastdnptr); 5660 5661 if (result < 0) { 5662 parse_warn(cfile, "Error compressing domain " 5663 "list: %m"); 5664 return NULL; 5665 } 5666 5667 clen += result; 5668 } else { 5669 result = MRns_name_pton(val, compbuf + clen, 5670 sizeof(compbuf) - clen); 5671 5672 /* result == 1 means the input was fully qualified. 5673 * result == 0 means the input wasn't. 5674 * result == -1 means bad things. 5675 */ 5676 if (result < 0) { 5677 parse_warn(cfile, "Error assembling domain " 5678 "list: %m"); 5679 return NULL; 5680 } 5681 5682 /* 5683 * We need to figure out how many bytes to increment 5684 * our buffer pointer since pton doesn't tell us. 5685 */ 5686 while (compbuf[clen] != 0) 5687 clen += compbuf[clen] + 1; 5688 5689 /* Count the last label (0). */ 5690 clen++; 5691 } 5692 5693 if (clen > sizeof(compbuf)) 5694 log_fatal("Impossible error at %s:%d", MDL); 5695 5696 token = peek_token(&val, NULL, cfile); 5697 } while (token == COMMA); 5698 5699 if (!make_const_data(&t, compbuf, clen, 1, 1, MDL)) 5700 log_fatal("No memory for domain list object."); 5701 5702 return t; 5703 } 5704 5705