00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "dhcpd.h"
00030 #include <syslog.h>
00031
00032
00033
00034
00035 struct enumeration *enumerations;
00036
00037 void add_enumeration (struct enumeration *enumeration)
00038 {
00039 enumeration -> next = enumerations;
00040 enumerations = enumeration;
00041 }
00042
00043 struct enumeration *find_enumeration (const char *name, int length)
00044 {
00045 struct enumeration *e;
00046
00047 for (e = enumerations; e; e = e -> next)
00048 if (strlen (e -> name) == length &&
00049 !memcmp (e -> name, name, (unsigned)length))
00050 return e;
00051 return (struct enumeration *)0;
00052 }
00053
00054 struct enumeration_value *find_enumeration_value (const char *name,
00055 int length,
00056 unsigned *widthp,
00057 const char *value)
00058 {
00059 struct enumeration *e;
00060 int i;
00061
00062 e = find_enumeration (name, length);
00063 if (e) {
00064 if (widthp != NULL)
00065 *widthp = e->width;
00066 for (i = 0; e -> values [i].name; i++) {
00067 if (!strcmp (value, e -> values [i].name))
00068 return &e -> values [i];
00069 }
00070 }
00071 return (struct enumeration_value *)0;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 void skip_to_semi (cfile)
00089 struct parse *cfile;
00090 {
00091 skip_to_rbrace (cfile, 0);
00092 }
00093
00094 void skip_to_rbrace (cfile, brace_count)
00095 struct parse *cfile;
00096 int brace_count;
00097 {
00098 enum dhcp_token token;
00099 const char *val;
00100
00101 #if defined (DEBUG_TOKEN)
00102 log_error ("skip_to_rbrace: %d\n", brace_count);
00103 #endif
00104 do {
00105 token = peek_token (&val, (unsigned *)0, cfile);
00106 if (token == RBRACE) {
00107 skip_token(&val, (unsigned *)0, cfile);
00108 if (brace_count) {
00109 if (!--brace_count)
00110 return;
00111 } else
00112 return;
00113 } else if (token == LBRACE) {
00114 brace_count++;
00115 } else if (token == SEMI && !brace_count) {
00116 skip_token(&val, (unsigned *)0, cfile);
00117 return;
00118 } else if (token == EOL) {
00119
00120
00121
00122 skip_token(&val, (unsigned *)0, cfile);
00123 return;
00124 }
00125 token = next_token (&val, (unsigned *)0, cfile);
00126 } while (token != END_OF_FILE);
00127 }
00128
00129 int parse_semi (cfile)
00130 struct parse *cfile;
00131 {
00132 enum dhcp_token token;
00133 const char *val;
00134
00135 token = next_token (&val, (unsigned *)0, cfile);
00136 if (token != SEMI) {
00137 parse_warn (cfile, "semicolon expected.");
00138 skip_to_semi (cfile);
00139 return 0;
00140 }
00141 return 1;
00142 }
00143
00144
00145
00146 int parse_string (cfile, sptr, lptr)
00147 struct parse *cfile;
00148 char **sptr;
00149 unsigned *lptr;
00150 {
00151 const char *val;
00152 enum dhcp_token token;
00153 char *s;
00154 unsigned len;
00155
00156 token = next_token (&val, &len, cfile);
00157 if (token != STRING) {
00158 parse_warn (cfile, "expecting a string");
00159 skip_to_semi (cfile);
00160 return 0;
00161 }
00162 s = (char *)dmalloc (len + 1, MDL);
00163 if (!s)
00164 log_fatal ("no memory for string %s.", val);
00165 memcpy (s, val, len + 1);
00166
00167 if (!parse_semi (cfile)) {
00168 dfree (s, MDL);
00169 return 0;
00170 }
00171 if (sptr)
00172 *sptr = s;
00173 else
00174 dfree (s, MDL);
00175 if (lptr)
00176 *lptr = len;
00177 return 1;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 char *parse_host_name (cfile)
00187 struct parse *cfile;
00188 {
00189 const char *val;
00190 enum dhcp_token token;
00191 unsigned len = 0;
00192 char *s;
00193 char *t;
00194 pair c = (pair)0;
00195 int ltid = 0;
00196
00197
00198 do {
00199
00200 token = peek_token (&val, (unsigned *)0, cfile);
00201 if (!is_identifier (token) && token != NUMBER)
00202 break;
00203 skip_token(&val, (unsigned *)0, cfile);
00204
00205
00206 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
00207 log_fatal ("can't allocate temp space for hostname.");
00208 strcpy (s, val);
00209 c = cons ((caddr_t)s, c);
00210 len += strlen (s) + 1;
00211
00212
00213 token = peek_token (&val, (unsigned *)0, cfile);
00214 if (token == DOT) {
00215 token = next_token (&val, (unsigned *)0, cfile);
00216 ltid = 1;
00217 } else
00218 ltid = 0;
00219 } while (token == DOT);
00220
00221
00222 if (!len)
00223 return (char *)0;
00224
00225
00226 if (!(s = (char *)dmalloc (len + ltid, MDL)))
00227 log_fatal ("can't allocate space for hostname.");
00228 t = s + len + ltid;
00229 *--t = 0;
00230 if (ltid)
00231 *--t = '.';
00232 while (c) {
00233 pair cdr = c -> cdr;
00234 unsigned l = strlen ((char *)(c -> car));
00235 t -= l;
00236 memcpy (t, (char *)(c -> car), l);
00237
00238 dfree (c -> car, MDL);
00239 dfree (c, MDL);
00240 c = cdr;
00241 if (t != s)
00242 *--t = '.';
00243 }
00244 return s;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 int parse_ip_addr_or_hostname (expr, cfile, uniform)
00259 struct expression **expr;
00260 struct parse *cfile;
00261 int uniform;
00262 {
00263 const char *val;
00264 enum dhcp_token token;
00265 unsigned char addr [4];
00266 unsigned len = sizeof addr;
00267 char *name;
00268 struct expression *x = (struct expression *)0;
00269 int ipaddr = 0;
00270
00271 token = peek_token (&val, (unsigned *)0, cfile);
00272
00273 if (token == NUMBER) {
00274
00275
00276
00277
00278
00279
00280
00281 save_parse_state(cfile);
00282 skip_token(NULL, NULL, cfile);
00283 if (next_token(NULL, NULL, cfile) == DOT &&
00284 next_token(NULL, NULL, cfile) == NUMBER)
00285 ipaddr = 1;
00286 restore_parse_state(cfile);
00287
00288 if (ipaddr &&
00289 parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
00290 return make_const_data (expr, addr, len, 0, 1, MDL);
00291
00292 }
00293
00294 if (is_identifier (token) || token == NUMBER) {
00295 name = parse_host_name (cfile);
00296 if (!name)
00297 return 0;
00298 if (!make_host_lookup (expr, name)) {
00299 dfree(name, MDL);
00300 return 0;
00301 }
00302 dfree(name, MDL);
00303 if (!uniform) {
00304 if (!make_limit (&x, *expr, 4))
00305 return 0;
00306 expression_dereference (expr, MDL);
00307 *expr = x;
00308 }
00309 } else {
00310 if (token != RBRACE && token != LBRACE)
00311 token = next_token (&val, (unsigned *)0, cfile);
00312 parse_warn (cfile, "%s (%d): expecting IP address or hostname",
00313 val, token);
00314 if (token != SEMI)
00315 skip_to_semi (cfile);
00316 return 0;
00317 }
00318
00319 return 1;
00320 }
00321
00322
00323
00324
00325
00326 int parse_ip_addr (cfile, addr)
00327 struct parse *cfile;
00328 struct iaddr *addr;
00329 {
00330 addr -> len = 4;
00331 if (parse_numeric_aggregate (cfile, addr -> iabuf,
00332 &addr -> len, DOT, 10, 8))
00333 return 1;
00334 return 0;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344 int parse_destination_descriptor (cfile, addr)
00345 struct parse *cfile;
00346 struct iaddr *addr;
00347 {
00348 unsigned int mask_width, dest_dest_len;
00349 addr -> len = 0;
00350 if (parse_numeric_aggregate (cfile, addr -> iabuf,
00351 &addr -> len, DOT, 10, 8)) {
00352 mask_width = (unsigned int)addr->iabuf[0];
00353 dest_dest_len = (((mask_width+7)/8)+1);
00354 if (mask_width > 32) {
00355 parse_warn (cfile,
00356 "subnet mask width (%u) greater than 32.", mask_width);
00357 }
00358 else if (dest_dest_len != addr->len) {
00359 parse_warn (cfile,
00360 "destination descriptor with subnet mask width %u "
00361 "should have %u octets, but has %u octets.",
00362 mask_width, dest_dest_len, addr->len);
00363 }
00364
00365 return 1;
00366 }
00367 return 0;
00368 }
00369
00370
00371
00372
00373 static int
00374 is_hex_string(const char *s) {
00375 while (*s != '\0') {
00376 if (!isxdigit((int)*s)) {
00377 return 0;
00378 }
00379 s++;
00380 }
00381 return 1;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 int
00395 parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
00396 enum dhcp_token token;
00397 const char *val;
00398 int val_len;
00399
00400 char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
00401 int v6_len;
00402
00403
00404
00405
00406
00407 token = peek_token(&val, NULL, cfile);
00408
00409
00410
00411
00412 v6_len = 0;
00413 for (;;) {
00414 if ((((token == NAME) || (token == NUMBER_OR_NAME)) &&
00415 is_hex_string(val)) ||
00416 (token == NUMBER) ||
00417 (token == DOT) ||
00418 (token == COLON)) {
00419
00420 next_raw_token(&val, NULL, cfile);
00421 val_len = strlen(val);
00422 if ((v6_len + val_len) >= sizeof(v6)) {
00423 parse_warn(cfile, "Invalid IPv6 address.");
00424 skip_to_semi(cfile);
00425 return 0;
00426 }
00427 memcpy(v6+v6_len, val, val_len);
00428 v6_len += val_len;
00429
00430 } else {
00431 break;
00432 }
00433 token = peek_raw_token(&val, NULL, cfile);
00434 }
00435 v6[v6_len] = '\0';
00436
00437
00438
00439
00440 if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
00441 parse_warn(cfile, "Invalid IPv6 address.");
00442 skip_to_semi(cfile);
00443 return 0;
00444 }
00445 addr->len = 16;
00446 return 1;
00447 }
00448
00449
00450
00451
00452
00453 int
00454 parse_ip6_addr_expr(struct expression **expr,
00455 struct parse *cfile) {
00456 struct iaddr addr;
00457
00458 if (!parse_ip6_addr(cfile, &addr)) {
00459 return 0;
00460 }
00461 return make_const_data(expr, addr.iabuf, addr.len, 0, 1, MDL);
00462 }
00463
00464
00465
00466
00467 int
00468 parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen) {
00469 enum dhcp_token token;
00470 const char *val;
00471 int n;
00472
00473 if (!parse_ip6_addr(cfile, addr)) {
00474 return 0;
00475 }
00476 token = next_token(&val, NULL, cfile);
00477 if (token != SLASH) {
00478 parse_warn(cfile, "Slash expected.");
00479 if (token != SEMI)
00480 skip_to_semi(cfile);
00481 return 0;
00482 }
00483 token = next_token(&val, NULL, cfile);
00484 if (token != NUMBER) {
00485 parse_warn(cfile, "Number expected.");
00486 if (token != SEMI)
00487 skip_to_semi(cfile);
00488 return 0;
00489 }
00490 n = atoi(val);
00491 if ((n < 0) || (n > 128)) {
00492 parse_warn(cfile, "Invalid IPv6 prefix length.");
00493 skip_to_semi(cfile);
00494 return 0;
00495 }
00496 if (!is_cidr_mask_valid(addr, n)) {
00497 parse_warn(cfile, "network mask too short.");
00498 skip_to_semi(cfile);
00499 return 0;
00500 }
00501 *plen = n;
00502 return 1;
00503 }
00504
00505
00506
00507
00508
00509
00510 int
00511 parse_ip_addr_with_subnet(cfile, match)
00512 struct parse *cfile;
00513 struct iaddrmatch *match;
00514 {
00515 const char *val, *orig;
00516 enum dhcp_token token;
00517 int prefixlen;
00518 int fflen;
00519 unsigned char newval, warnmask=0;
00520
00521 if (parse_ip_addr(cfile, &match->addr)) {
00522
00523 prefixlen = match->addr.len * 8;
00524
00525 token = peek_token(&val, NULL, cfile);
00526
00527 if (token == SLASH) {
00528 skip_token(&val, NULL, cfile);
00529 token = next_token(&val, NULL, cfile);
00530
00531 if (token != NUMBER) {
00532 parse_warn(cfile, "Invalid CIDR prefix length:"
00533 " expecting a number.");
00534 return 0;
00535 }
00536
00537 prefixlen = atoi(val);
00538
00539 if (prefixlen < 0 ||
00540 prefixlen > (match->addr.len * 8)) {
00541 parse_warn(cfile, "subnet prefix is out of "
00542 "range [0..%d].",
00543 match->addr.len * 8);
00544 return 0;
00545 }
00546 }
00547
00548
00549
00550
00551 match->mask.len = match->addr.len;
00552
00553
00554 fflen = prefixlen / 8;
00555
00556
00557 memset(match->mask.iabuf, 0xff, fflen);
00558
00559
00560 if (fflen < match->mask.len) {
00561 match->mask.iabuf[fflen] =
00562 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen % 8];
00563
00564 memset(match->mask.iabuf+fflen+1, 0x00,
00565 match->mask.len - fflen - 1);
00566
00567
00568 orig = piaddr(match->addr);
00569 do {
00570 newval = match->addr.iabuf[fflen] &
00571 match->mask.iabuf[fflen];
00572
00573 if (newval != match->addr.iabuf[fflen]) {
00574 warnmask = 1;
00575 match->addr.iabuf[fflen] = newval;
00576 }
00577 } while (++fflen < match->mask.len);
00578
00579 if (warnmask) {
00580 log_error("Warning: Extraneous bits removed "
00581 "in address component of %s/%d.",
00582 orig, prefixlen);
00583 log_error("New value: %s/%d.",
00584 piaddr(match->addr), prefixlen);
00585 }
00586 }
00587
00588 return 1;
00589 }
00590
00591 parse_warn(cfile,
00592 "expecting ip-address or ip-address/prefixlen");
00593
00594 return 0;
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604 void parse_hardware_param (cfile, hardware)
00605 struct parse *cfile;
00606 struct hardware *hardware;
00607 {
00608 const char *val;
00609 enum dhcp_token token;
00610 unsigned hlen;
00611 unsigned char *t;
00612
00613 token = next_token(&val, NULL, cfile);
00614 switch (token) {
00615 case ETHERNET:
00616 hardware->hbuf[0] = HTYPE_ETHER;
00617 break;
00618 case TOKEN_RING:
00619 hardware->hbuf[0] = HTYPE_IEEE802;
00620 break;
00621 case TOKEN_FDDI:
00622 hardware->hbuf[0] = HTYPE_FDDI;
00623 break;
00624 case TOKEN_INFINIBAND:
00625 hardware->hbuf[0] = HTYPE_INFINIBAND;
00626 break;
00627 default:
00628 if (!strncmp(val, "unknown-", 8)) {
00629 hardware->hbuf[0] = atoi(&val[8]);
00630 } else {
00631 parse_warn(cfile,
00632 "expecting a network hardware type");
00633 skip_to_semi(cfile);
00634
00635 return;
00636 }
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646 hlen = 0;
00647 token = peek_token(&val, NULL, cfile);
00648 if (token == SEMI) {
00649 hardware->hlen = 1;
00650 goto out;
00651 }
00652 t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
00653 if (t == NULL) {
00654 hardware->hlen = 1;
00655 return;
00656 }
00657 if (hlen + 1 > sizeof(hardware->hbuf)) {
00658 dfree(t, MDL);
00659 parse_warn(cfile, "hardware address too long");
00660 } else {
00661 hardware->hlen = hlen + 1;
00662 memcpy((unsigned char *)&hardware->hbuf[1], t, hlen);
00663 if (hlen + 1 < sizeof(hardware->hbuf))
00664 memset(&hardware->hbuf[hlen + 1], 0,
00665 (sizeof(hardware->hbuf)) - hlen - 1);
00666 dfree(t, MDL);
00667 }
00668
00669 out:
00670 token = next_token(&val, NULL, cfile);
00671 if (token != SEMI) {
00672 parse_warn(cfile, "expecting semicolon.");
00673 skip_to_semi(cfile);
00674 }
00675 }
00676
00677
00678
00679 void parse_lease_time (cfile, timep)
00680 struct parse *cfile;
00681 TIME *timep;
00682 {
00683 const char *val;
00684 enum dhcp_token token;
00685 u_int32_t num;
00686
00687 token = next_token (&val, (unsigned *)0, cfile);
00688 if (token != NUMBER) {
00689 parse_warn (cfile, "Expecting numeric lease time");
00690 skip_to_semi (cfile);
00691 return;
00692 }
00693 convert_num(cfile, (unsigned char *)&num, val, 10, 32);
00694
00695 *timep = ntohl(num);
00696
00697 parse_semi (cfile);
00698 }
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723 unsigned char *parse_numeric_aggregate (cfile, buf,
00724 max, separator, base, size)
00725 struct parse *cfile;
00726 unsigned char *buf;
00727 unsigned *max;
00728 int separator;
00729 int base;
00730 unsigned size;
00731 {
00732 const char *val;
00733 enum dhcp_token token;
00734 unsigned char *bufp = buf, *s, *t;
00735 unsigned count = 0;
00736 pair c = (pair)0;
00737
00738 if (!bufp && *max) {
00739 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
00740 if (!bufp)
00741 log_fatal ("no space for numeric aggregate");
00742 }
00743 s = bufp;
00744
00745 do {
00746 if (count) {
00747 token = peek_token (&val, (unsigned *)0, cfile);
00748 if (token != separator) {
00749 if (!*max) {
00750 *max = count;
00751 break;
00752 }
00753 if (token != RBRACE && token != LBRACE)
00754 token = next_token (&val,
00755 (unsigned *)0,
00756 cfile);
00757 parse_warn (cfile, "too few numbers.");
00758 if (token != SEMI)
00759 skip_to_semi (cfile);
00760
00761 if ((bufp != NULL) && (bufp != buf))
00762 dfree(bufp, MDL);
00763 return (unsigned char *)0;
00764 }
00765 skip_token(&val, (unsigned *)0, cfile);
00766 }
00767 token = next_token (&val, (unsigned *)0, cfile);
00768
00769 if (token == END_OF_FILE) {
00770 parse_warn (cfile, "unexpected end of file");
00771 break;
00772 }
00773
00774
00775 if (token != NUMBER &&
00776 (base != 16 || token != NUMBER_OR_NAME)) {
00777 parse_warn (cfile, "expecting numeric value.");
00778 skip_to_semi (cfile);
00779
00780 if ((bufp != NULL) && (bufp != buf))
00781 dfree(bufp, MDL);
00782
00783 while (c) {
00784 pair cdr = c->cdr;
00785 dfree(c->car, MDL);
00786 dfree(c, MDL);
00787 c = cdr;
00788 }
00789 return (NULL);
00790 }
00791
00792
00793 if (s) {
00794 convert_num (cfile, s, val, base, size);
00795 s += size / 8;
00796 } else {
00797 t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
00798 if (!t)
00799 log_fatal ("no temp space for number.");
00800 strcpy ((char *)t, val);
00801 c = cons ((caddr_t)t, c);
00802 }
00803 } while (++count != *max);
00804
00805
00806 if (c) {
00807
00808
00809
00810
00811 bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
00812 if (!bufp)
00813 log_fatal ("no space for numeric aggregate.");
00814 s = bufp + count - size / 8;
00815 *max = count;
00816 }
00817 while (c) {
00818 pair cdr = c -> cdr;
00819 convert_num (cfile, s, (char *)(c -> car), base, size);
00820 s -= size / 8;
00821
00822 dfree (c -> car, MDL);
00823 dfree (c, MDL);
00824 c = cdr;
00825 }
00826 return bufp;
00827 }
00828
00829 void convert_num (cfile, buf, str, base, size)
00830 struct parse *cfile;
00831 unsigned char *buf;
00832 const char *str;
00833 int base;
00834 unsigned size;
00835 {
00836 const unsigned char *ptr = (const unsigned char *)str;
00837 int negative = 0;
00838 u_int32_t val = 0;
00839 int tval;
00840 int max;
00841
00842 if (*ptr == '-') {
00843 negative = 1;
00844 ++ptr;
00845 }
00846
00847
00848 if (!base) {
00849 if (ptr [0] == '0') {
00850 if (ptr [1] == 'x') {
00851 base = 16;
00852 ptr += 2;
00853 } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
00854 base = 8;
00855 ptr += 1;
00856 } else {
00857 base = 10;
00858 }
00859 } else {
00860 base = 10;
00861 }
00862 }
00863
00864 do {
00865 tval = *ptr++;
00866
00867 if (tval >= 'a')
00868 tval = tval - 'a' + 10;
00869 else if (tval >= 'A')
00870 tval = tval - 'A' + 10;
00871 else if (tval >= '0')
00872 tval -= '0';
00873 else {
00874 parse_warn (cfile, "Bogus number: %s.", str);
00875 break;
00876 }
00877 if (tval >= base) {
00878 parse_warn (cfile,
00879 "Bogus number %s: digit %d not in base %d",
00880 str, tval, base);
00881 break;
00882 }
00883 val = val * base + tval;
00884 } while (*ptr);
00885
00886 if (negative)
00887 max = (1 << (size - 1));
00888 else
00889 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
00890 if (val > max) {
00891 switch (base) {
00892 case 8:
00893 parse_warn (cfile,
00894 "%s%lo exceeds max (%d) for precision.",
00895 negative ? "-" : "",
00896 (unsigned long)val, max);
00897 break;
00898 case 16:
00899 parse_warn (cfile,
00900 "%s%lx exceeds max (%d) for precision.",
00901 negative ? "-" : "",
00902 (unsigned long)val, max);
00903 break;
00904 default:
00905 parse_warn (cfile,
00906 "%s%lu exceeds max (%d) for precision.",
00907 negative ? "-" : "",
00908 (unsigned long)val, max);
00909 break;
00910 }
00911 }
00912
00913 if (negative) {
00914 switch (size) {
00915 case 8:
00916 *buf = -(unsigned long)val;
00917 break;
00918 case 16:
00919 putShort (buf, -(long)val);
00920 break;
00921 case 32:
00922 putLong (buf, -(long)val);
00923 break;
00924 default:
00925 parse_warn (cfile,
00926 "Unexpected integer size: %d\n", size);
00927 break;
00928 }
00929 } else {
00930 switch (size) {
00931 case 8:
00932 *buf = (u_int8_t)val;
00933 break;
00934 case 16:
00935 putUShort (buf, (u_int16_t)val);
00936 break;
00937 case 32:
00938 putULong (buf, val);
00939 break;
00940 default:
00941 parse_warn (cfile,
00942 "Unexpected integer size: %d\n", size);
00943 break;
00944 }
00945 }
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 TIME
00967 parse_date_core(cfile)
00968 struct parse *cfile;
00969 {
00970 TIME guess;
00971 long int tzoff, year, mon, mday, hour, min, sec;
00972 const char *val;
00973 enum dhcp_token token;
00974 static int months[11] = { 31, 59, 90, 120, 151, 181,
00975 212, 243, 273, 304, 334 };
00976
00977
00978 token = peek_token(&val, NULL, cfile);
00979 if (token == NEVER) {
00980 skip_token(&val, NULL, cfile);
00981 return(MAX_TIME);
00982 }
00983
00984
00985 if (token == EPOCH) {
00986 skip_token(&val, NULL, cfile);
00987 token = peek_token(&val, NULL, cfile);
00988
00989 if (token != NUMBER) {
00990 if (token != SEMI)
00991 skip_token(&val, NULL, cfile);
00992 parse_warn(cfile, "Seconds since epoch expected.");
00993 return((TIME)0);
00994 }
00995
00996 skip_token(&val, NULL, cfile);
00997 guess = atol(val);
00998
00999 return((TIME)guess);
01000 }
01001
01002 if (token != NUMBER) {
01003 if (token != SEMI)
01004 skip_token(&val, NULL, cfile);
01005 parse_warn(cfile, "numeric day of week expected.");
01006 return((TIME)0);
01007 }
01008 skip_token(&val, NULL, cfile);
01009
01010
01011
01012 token = peek_token(&val, NULL, cfile);
01013 if (token != NUMBER) {
01014 if (token != SEMI)
01015 skip_token(&val, NULL, cfile);
01016 parse_warn(cfile, "numeric year expected.");
01017 return((TIME)0);
01018 }
01019 skip_token(&val, NULL, cfile);
01020
01021
01022
01023
01024
01025 year = atol(val);
01026 if (year > 1900)
01027 year -= 1900;
01028
01029
01030 token = peek_token(&val, NULL, cfile);
01031 if (token != SLASH) {
01032 if (token != SEMI)
01033 skip_token(&val, NULL, cfile);
01034 parse_warn(cfile,
01035 "expected slash separating year from month.");
01036 return((TIME)0);
01037 }
01038 skip_token(&val, NULL, cfile);
01039
01040
01041 token = peek_token(&val, NULL, cfile);
01042 if (token != NUMBER) {
01043 if (token != SEMI)
01044 skip_token(&val, NULL, cfile);
01045 parse_warn(cfile, "numeric month expected.");
01046 return((TIME)0);
01047 }
01048 skip_token(&val, NULL, cfile);
01049 mon = atoi(val) - 1;
01050
01051
01052 token = peek_token(&val, NULL, cfile);
01053 if (token != SLASH) {
01054 if (token != SEMI)
01055 skip_token(&val, NULL, cfile);
01056 parse_warn(cfile,
01057 "expected slash separating month from day.");
01058 return((TIME)0);
01059 }
01060 skip_token(&val, NULL, cfile);
01061
01062
01063 token = peek_token(&val, NULL, cfile);
01064 if (token != NUMBER) {
01065 if (token != SEMI)
01066 skip_token(&val, NULL, cfile);
01067 parse_warn(cfile, "numeric day of month expected.");
01068 return((TIME)0);
01069 }
01070 skip_token(&val, NULL, cfile);
01071 mday = atol(val);
01072
01073
01074 token = peek_token(&val, NULL, cfile);
01075 if (token != NUMBER) {
01076 if (token != SEMI)
01077 skip_token(&val, NULL, cfile);
01078 parse_warn(cfile, "numeric hour expected.");
01079 return((TIME)0);
01080 }
01081 skip_token(&val, NULL, cfile);
01082 hour = atol(val);
01083
01084
01085 token = peek_token(&val, NULL, cfile);
01086 if (token != COLON) {
01087 if (token != SEMI)
01088 skip_token(&val, NULL, cfile);
01089 parse_warn(cfile,
01090 "expected colon separating hour from minute.");
01091 return((TIME)0);
01092 }
01093 skip_token(&val, NULL, cfile);
01094
01095
01096 token = peek_token(&val, NULL, cfile);
01097 if (token != NUMBER) {
01098 if (token != SEMI)
01099 skip_token(&val, NULL, cfile);
01100 parse_warn(cfile, "numeric minute expected.");
01101 return((TIME)0);
01102 }
01103 skip_token(&val, NULL, cfile);
01104 min = atol(val);
01105
01106
01107 token = peek_token(&val, NULL, cfile);
01108 if (token != COLON) {
01109 if (token != SEMI)
01110 skip_token(&val, NULL, cfile);
01111 parse_warn(cfile,
01112 "expected colon separating minute from second.");
01113 return((TIME)0);
01114 }
01115 skip_token(&val, NULL, cfile);
01116
01117
01118 token = peek_token(&val, NULL, cfile);
01119 if (token != NUMBER) {
01120 if (token != SEMI)
01121 skip_token(&val, NULL, cfile);
01122 parse_warn(cfile, "numeric second expected.");
01123 return((TIME)0);
01124 }
01125 skip_token(&val, NULL, cfile);
01126 sec = atol(val);
01127
01128 tzoff = 0;
01129 token = peek_token(&val, NULL, cfile);
01130 if (token == NUMBER) {
01131 skip_token(&val, NULL, cfile);
01132 tzoff = atol(val);
01133 } else if (token != SEMI) {
01134 skip_token(&val, NULL, cfile);
01135 parse_warn(cfile,
01136 "Time zone offset or semicolon expected.");
01137 return((TIME)0);
01138 }
01139
01140
01141 guess = ((((((365 * (year - 70) +
01142 (year - 69) / 4 +
01143 (mon
01144 ? months [mon - 1]
01145 : 0) +
01146 (mon > 1 &&
01147 !((year - 72) & 3)) +
01148 mday - 1) * 24) +
01149 hour) * 60) +
01150 min) * 60) + sec + tzoff;
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 return((TIME)guess);
01162 }
01163
01164
01165
01166
01167
01168
01169 TIME
01170 parse_date(cfile)
01171 struct parse *cfile;
01172 {
01173 TIME guess;
01174 guess = parse_date_core(cfile);
01175
01176
01177 if (!parse_semi(cfile))
01178 return((TIME)0);
01179 return(guess);
01180 }
01181
01182
01183
01184
01185
01186
01187
01188
01189 isc_result_t
01190 parse_option_name (cfile, allocate, known, opt)
01191 struct parse *cfile;
01192 int allocate;
01193 int *known;
01194 struct option **opt;
01195 {
01196 const char *val;
01197 enum dhcp_token token;
01198 char *uname;
01199 struct universe *universe;
01200 struct option *option;
01201 unsigned code;
01202
01203 if (opt == NULL)
01204 return DHCP_R_INVALIDARG;
01205
01206 token = next_token (&val, (unsigned *)0, cfile);
01207 if (!is_identifier (token)) {
01208 parse_warn (cfile,
01209 "expecting identifier after option keyword.");
01210 if (token != SEMI)
01211 skip_to_semi (cfile);
01212 return DHCP_R_BADPARSE;
01213 }
01214 uname = dmalloc (strlen (val) + 1, MDL);
01215 if (!uname)
01216 log_fatal ("no memory for uname information.");
01217 strcpy (uname, val);
01218 token = peek_token (&val, (unsigned *)0, cfile);
01219 if (token == DOT) {
01220
01221 skip_token(&val, (unsigned *)0, cfile);
01222
01223
01224 token = next_token (&val, (unsigned *)0, cfile);
01225 if (!is_identifier (token)) {
01226 parse_warn (cfile, "expecting identifier after '.'");
01227 if (token != SEMI)
01228 skip_to_semi (cfile);
01229 return DHCP_R_BADPARSE;
01230 }
01231
01232
01233
01234 universe = (struct universe *)0;
01235 if (!universe_hash_lookup (&universe, universe_hash,
01236 uname, 0, MDL)) {
01237 parse_warn (cfile, "no option space named %s.", uname);
01238 skip_to_semi (cfile);
01239 return ISC_R_NOTFOUND;
01240 }
01241 } else {
01242
01243
01244 val = uname;
01245 universe = &dhcp_universe;
01246 }
01247
01248
01249 option_name_hash_lookup(opt, universe->name_hash, val, 0, MDL);
01250 option = *opt;
01251
01252
01253 if (option) {
01254 if (known)
01255 *known = 1;
01256
01257
01258
01259
01260
01261
01262 } else if (strncasecmp(val, "unknown-", 8) == 0) {
01263 code = atoi(val+8);
01264
01265
01266
01267
01268 if (code == 0 || code == universe->end) {
01269 parse_warn(cfile, "Option codes 0 and %u are illegal "
01270 "in the %s space.", universe->end,
01271 universe->name);
01272 skip_to_semi(cfile);
01273 dfree(uname, MDL);
01274 return ISC_R_FAILURE;
01275 }
01276
01277
01278
01279
01280
01281 if (known)
01282 *known = 1;
01283
01284 option_code_hash_lookup(opt, universe->code_hash,
01285 &code, 0, MDL);
01286 option = *opt;
01287
01288
01289
01290
01291
01292
01293
01294 if (option == NULL) {
01295 option = new_option(val, MDL);
01296 option->universe = universe;
01297 option->code = code;
01298 option->format = default_option_format;
01299 option_reference(opt, option, MDL);
01300 } else
01301 log_info("option %s has been redefined as option %s. "
01302 "Please update your configs if neccessary.",
01303 val, option->name);
01304
01305
01306
01307
01308
01309 } else if (allocate) {
01310 option = new_option(val, MDL);
01311 option -> universe = universe;
01312 option_reference(opt, option, MDL);
01313 } else {
01314 parse_warn(cfile, "no option named %s in space %s",
01315 val, universe->name);
01316 skip_to_semi (cfile);
01317 dfree(uname, MDL);
01318 return ISC_R_NOTFOUND;
01319 }
01320
01321
01322 dfree (uname, MDL);
01323 return ISC_R_SUCCESS;
01324 }
01325
01326
01327
01328
01329
01330
01331 void parse_option_space_decl (cfile)
01332 struct parse *cfile;
01333 {
01334 int token;
01335 const char *val;
01336 struct universe **ua, *nu;
01337 char *nu_name;
01338 int tsize=1, lsize=1, hsize = 0;
01339
01340 skip_token(&val, (unsigned *)0, cfile);
01341
01342
01343 token = next_token (&val, (unsigned *)0, cfile);
01344 if (!is_identifier (token)) {
01345 parse_warn (cfile, "expecting identifier.");
01346 skip_to_semi (cfile);
01347 return;
01348 }
01349 nu = new_universe (MDL);
01350 if (!nu)
01351 log_fatal ("No memory for new option space.");
01352
01353
01354 nu_name = dmalloc (strlen (val) + 1, MDL);
01355 if (!nu_name)
01356 log_fatal ("No memory for new option space name.");
01357 strcpy (nu_name, val);
01358 nu -> name = nu_name;
01359
01360 do {
01361 token = next_token(&val, NULL, cfile);
01362 switch(token) {
01363 case SEMI:
01364 break;
01365
01366 case CODE:
01367 token = next_token(&val, NULL, cfile);
01368 if (token != WIDTH) {
01369 parse_warn(cfile, "expecting width token.");
01370 goto bad;
01371 }
01372
01373 token = next_token(&val, NULL, cfile);
01374 if (token != NUMBER) {
01375 parse_warn(cfile, "expecting number 1, 2, 4.");
01376 goto bad;
01377 }
01378
01379 tsize = atoi(val);
01380
01381
01382 switch (tsize) {
01383 case 1:
01384 if (!hsize)
01385 hsize = BYTE_NAME_HASH_SIZE;
01386 break;
01387 case 2:
01388 if (!hsize)
01389 hsize = WORD_NAME_HASH_SIZE;
01390 break;
01391 case 4:
01392 if (!hsize)
01393 hsize = QUAD_NAME_HASH_SIZE;
01394 break;
01395 default:
01396 parse_warn(cfile, "invalid code width (%d), "
01397 "expecting a 1, 2 or 4.",
01398 tsize);
01399 goto bad;
01400 }
01401 break;
01402
01403 case LENGTH:
01404 token = next_token(&val, NULL, cfile);
01405 if (token != WIDTH) {
01406 parse_warn(cfile, "expecting width token.");
01407 goto bad;
01408 }
01409
01410 token = next_token(&val, NULL, cfile);
01411 if (token != NUMBER) {
01412 parse_warn(cfile, "expecting number 1 or 2.");
01413 goto bad;
01414 }
01415
01416 lsize = atoi(val);
01417 if (lsize != 1 && lsize != 2) {
01418 parse_warn(cfile, "invalid length width (%d) "
01419 "expecting 1 or 2.", lsize);
01420 goto bad;
01421 }
01422
01423 break;
01424
01425 case HASH:
01426 token = next_token(&val, NULL, cfile);
01427 if (token != SIZE) {
01428 parse_warn(cfile, "expecting size token.");
01429 goto bad;
01430 }
01431
01432 token = next_token(&val, NULL, cfile);
01433 if (token != NUMBER) {
01434 parse_warn(cfile, "expecting a 10base number");
01435 goto bad;
01436 }
01437
01438
01439
01440
01441 hsize = atoi(val);
01442 if (hsize < 0 || hsize > 0x7FFFFFFF) {
01443 parse_warn(cfile, "invalid hash length: %d",
01444 hsize);
01445 goto bad;
01446 }
01447
01448 break;
01449
01450 default:
01451 parse_warn(cfile, "Unexpected token.");
01452 }
01453 } while (token != SEMI);
01454
01455 if (!hsize)
01456 hsize = DEFAULT_SPACE_HASH_SIZE;
01457
01458 nu -> lookup_func = lookup_hashed_option;
01459 nu -> option_state_dereference = hashed_option_state_dereference;
01460 nu -> foreach = hashed_option_space_foreach;
01461 nu -> save_func = save_hashed_option;
01462 nu -> delete_func = delete_hashed_option;
01463 nu -> encapsulate = hashed_option_space_encapsulate;
01464 nu -> decode = parse_option_buffer;
01465 nu -> length_size = lsize;
01466 nu -> tag_size = tsize;
01467 switch(tsize) {
01468 case 1:
01469 nu->get_tag = getUChar;
01470 nu->store_tag = putUChar;
01471 break;
01472 case 2:
01473 nu->get_tag = getUShort;
01474 nu->store_tag = putUShort;
01475 break;
01476 case 4:
01477 nu->get_tag = getULong;
01478 nu->store_tag = putULong;
01479 break;
01480 default:
01481 log_fatal("Impossible condition at %s:%d.", MDL);
01482 }
01483 switch(lsize) {
01484 case 0:
01485 nu->get_length = NULL;
01486 nu->store_length = NULL;
01487 break;
01488 case 1:
01489 nu->get_length = getUChar;
01490 nu->store_length = putUChar;
01491 break;
01492 case 2:
01493 nu->get_length = getUShort;
01494 nu->store_length = putUShort;
01495 break;
01496 default:
01497 log_fatal("Impossible condition at %s:%d.", MDL);
01498 }
01499 nu -> index = universe_count++;
01500 if (nu -> index >= universe_max) {
01501 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
01502 if (!ua)
01503 log_fatal ("No memory to expand option space array.");
01504 memcpy (ua, universes, universe_max * sizeof *ua);
01505 universe_max *= 2;
01506 dfree (universes, MDL);
01507 universes = ua;
01508 }
01509 universes [nu -> index] = nu;
01510 if (!option_name_new_hash(&nu->name_hash, hsize, MDL) ||
01511 !option_code_new_hash(&nu->code_hash, hsize, MDL))
01512 log_fatal("Can't allocate %s option hash table.", nu->name);
01513 universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
01514 return;
01515
01516 bad:
01517 dfree(nu_name, MDL);
01518 dfree(nu, MDL);
01519 }
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 int parse_option_code_definition (cfile, option)
01555 struct parse *cfile;
01556 struct option *option;
01557 {
01558 const char *val;
01559 enum dhcp_token token;
01560 struct option *oldopt;
01561 unsigned arrayp = 0;
01562 int recordp = 0;
01563 int no_more_in_record = 0;
01564 char tokbuf [128];
01565 unsigned tokix = 0;
01566 char type;
01567 int is_signed;
01568 char *s;
01569 int has_encapsulation = 0;
01570 struct universe *encapsulated;
01571
01572
01573 token = next_token (&val, (unsigned *)0, cfile);
01574 if (token != NUMBER) {
01575 parse_warn (cfile, "expecting option code number.");
01576 skip_to_semi (cfile);
01577 return 0;
01578 }
01579 option -> code = atoi (val);
01580
01581 token = next_token (&val, (unsigned *)0, cfile);
01582 if (token != EQUAL) {
01583 parse_warn (cfile, "expecting \"=\"");
01584 skip_to_semi (cfile);
01585 return 0;
01586 }
01587
01588
01589 token = next_token (&val, (unsigned *)0, cfile);
01590 if (token == ARRAY) {
01591 token = next_token (&val, (unsigned *)0, cfile);
01592 if (token != OF) {
01593 parse_warn (cfile, "expecting \"of\".");
01594 skip_to_semi (cfile);
01595 return 0;
01596 }
01597 arrayp = 1;
01598 token = next_token (&val, (unsigned *)0, cfile);
01599 }
01600
01601 if (token == LBRACE) {
01602 recordp = 1;
01603 token = next_token (&val, (unsigned *)0, cfile);
01604 }
01605
01606
01607 next_type:
01608 if (has_encapsulation) {
01609 parse_warn (cfile,
01610 "encapsulate must always be the last item.");
01611 skip_to_semi (cfile);
01612 return 0;
01613 }
01614
01615 switch (token) {
01616 case ARRAY:
01617 if (arrayp) {
01618 parse_warn (cfile, "no nested arrays.");
01619 skip_to_rbrace (cfile, recordp);
01620 if (recordp)
01621 skip_to_semi (cfile);
01622 return 0;
01623 }
01624 token = next_token (&val, (unsigned *)0, cfile);
01625 if (token != OF) {
01626 parse_warn (cfile, "expecting \"of\".");
01627 skip_to_semi (cfile);
01628 return 0;
01629 }
01630 arrayp = recordp + 1;
01631 token = next_token (&val, (unsigned *)0, cfile);
01632 if ((recordp) && (token == LBRACE)) {
01633 parse_warn (cfile,
01634 "only uniform array inside record.");
01635 skip_to_rbrace (cfile, recordp + 1);
01636 skip_to_semi (cfile);
01637 return 0;
01638 }
01639 goto next_type;
01640 case BOOLEAN:
01641 type = 'f';
01642 break;
01643 case INTEGER:
01644 is_signed = 1;
01645 parse_integer:
01646 token = next_token (&val, (unsigned *)0, cfile);
01647 if (token != NUMBER) {
01648 parse_warn (cfile, "expecting number.");
01649 skip_to_rbrace (cfile, recordp);
01650 if (recordp)
01651 skip_to_semi (cfile);
01652 return 0;
01653 }
01654 switch (atoi (val)) {
01655 case 8:
01656 type = is_signed ? 'b' : 'B';
01657 break;
01658 case 16:
01659 type = is_signed ? 's' : 'S';
01660 break;
01661 case 32:
01662 type = is_signed ? 'l' : 'L';
01663 break;
01664 default:
01665 parse_warn (cfile,
01666 "%s bit precision is not supported.", val);
01667 skip_to_rbrace (cfile, recordp);
01668 if (recordp)
01669 skip_to_semi (cfile);
01670 return 0;
01671 }
01672 break;
01673 case SIGNED:
01674 is_signed = 1;
01675 parse_signed:
01676 token = next_token (&val, (unsigned *)0, cfile);
01677 if (token != INTEGER) {
01678 parse_warn (cfile, "expecting \"integer\" keyword.");
01679 skip_to_rbrace (cfile, recordp);
01680 if (recordp)
01681 skip_to_semi (cfile);
01682 return 0;
01683 }
01684 goto parse_integer;
01685 case UNSIGNED:
01686 is_signed = 0;
01687 goto parse_signed;
01688
01689 case IP_ADDRESS:
01690 type = 'I';
01691 break;
01692 case DESTINATION_DESCRIPTOR:
01693 type = 'R';
01694 break;
01695 case IP6_ADDRESS:
01696 type = '6';
01697 break;
01698 case DOMAIN_NAME:
01699 type = 'd';
01700 goto no_arrays;
01701 case DOMAIN_LIST:
01702
01703 token = peek_token(&val, NULL, cfile);
01704 if (token == COMPRESSED) {
01705 skip_token(&val, NULL, cfile);
01706 tokbuf[tokix++] = 'D';
01707 type = 'c';
01708 } else
01709 type = 'D';
01710 goto no_arrays;
01711 case TEXT:
01712 type = 't';
01713 no_arrays:
01714 if (arrayp) {
01715 parse_warn (cfile, "arrays of text strings not %s",
01716 "yet supported.");
01717 skip_to_rbrace (cfile, recordp);
01718 if (recordp)
01719 skip_to_semi (cfile);
01720 return 0;
01721 }
01722 no_more_in_record = 1;
01723 break;
01724 case STRING_TOKEN:
01725 type = 'X';
01726 goto no_arrays;
01727
01728 case ENCAPSULATE:
01729 token = next_token (&val, (unsigned *)0, cfile);
01730 if (!is_identifier (token)) {
01731 parse_warn (cfile,
01732 "expecting option space identifier");
01733 skip_to_semi (cfile);
01734 return 0;
01735 }
01736 encapsulated = NULL;
01737 if (!universe_hash_lookup(&encapsulated, universe_hash,
01738 val, strlen(val), MDL)) {
01739 parse_warn(cfile, "unknown option space %s", val);
01740 skip_to_semi (cfile);
01741 return 0;
01742 }
01743 if (strlen (val) + tokix + 2 > sizeof (tokbuf))
01744 goto toobig;
01745 tokbuf [tokix++] = 'E';
01746 strcpy (&tokbuf [tokix], val);
01747 tokix += strlen (val);
01748 type = '.';
01749 has_encapsulation = 1;
01750 break;
01751
01752 case ZEROLEN:
01753 type = 'Z';
01754 if (arrayp) {
01755 parse_warn (cfile, "array incompatible with zerolen.");
01756 skip_to_rbrace (cfile, recordp);
01757 if (recordp)
01758 skip_to_semi (cfile);
01759 return 0;
01760 }
01761 no_more_in_record = 1;
01762 break;
01763
01764 default:
01765 parse_warn (cfile, "unknown data type %s", val);
01766 skip_to_rbrace (cfile, recordp);
01767 if (recordp)
01768 skip_to_semi (cfile);
01769 return 0;
01770 }
01771
01772 if (tokix == sizeof tokbuf) {
01773 toobig:
01774 parse_warn (cfile, "too many types in record.");
01775 skip_to_rbrace (cfile, recordp);
01776 if (recordp)
01777 skip_to_semi (cfile);
01778 return 0;
01779 }
01780 tokbuf [tokix++] = type;
01781
01782 if (recordp) {
01783 token = next_token (&val, (unsigned *)0, cfile);
01784 if (arrayp > recordp) {
01785 if (tokix == sizeof tokbuf) {
01786 parse_warn (cfile,
01787 "too many types in record.");
01788 skip_to_rbrace (cfile, 1);
01789 skip_to_semi (cfile);
01790 return 0;
01791 }
01792 arrayp = 0;
01793 tokbuf[tokix++] = 'a';
01794 }
01795 if (token == COMMA) {
01796 if (no_more_in_record) {
01797 parse_warn (cfile,
01798 "%s must be at end of record.",
01799 type == 't' ? "text" : "string");
01800 skip_to_rbrace (cfile, 1);
01801 if (recordp)
01802 skip_to_semi (cfile);
01803 return 0;
01804 }
01805 token = next_token (&val, (unsigned *)0, cfile);
01806 goto next_type;
01807 }
01808 if (token != RBRACE) {
01809 parse_warn (cfile, "expecting right brace.");
01810 skip_to_rbrace (cfile, 1);
01811 if (recordp)
01812 skip_to_semi (cfile);
01813 return 0;
01814 }
01815 }
01816 if (!parse_semi (cfile)) {
01817 parse_warn (cfile, "semicolon expected.");
01818 skip_to_semi (cfile);
01819 if (recordp)
01820 skip_to_semi (cfile);
01821 return 0;
01822 }
01823 if (has_encapsulation && arrayp) {
01824 parse_warn (cfile,
01825 "Arrays of encapsulations don't make sense.");
01826 return 0;
01827 }
01828 s = dmalloc(tokix + (arrayp ? 1 : 0) + 1, MDL);
01829 if (s == NULL) {
01830 log_fatal("no memory for option format.");
01831 }
01832 memcpy(s, tokbuf, tokix);
01833 if (arrayp) {
01834 s[tokix++] = (arrayp > recordp) ? 'a' : 'A';
01835 }
01836 s[tokix] = '\0';
01837
01838 option -> format = s;
01839
01840 oldopt = NULL;
01841 option_code_hash_lookup(&oldopt, option->universe->code_hash,
01842 &option->code, 0, MDL);
01843 if (oldopt != NULL) {
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855 option_code_hash_delete(option->universe->code_hash,
01856 &oldopt->code, 0, MDL);
01857
01858 option_dereference(&oldopt, MDL);
01859 }
01860 option_code_hash_add(option->universe->code_hash, &option->code, 0,
01861 option, MDL);
01862 option_name_hash_add(option->universe->name_hash, option->name, 0,
01863 option, MDL);
01864 if (has_encapsulation) {
01865
01866
01867 if (!option_code_hash_lookup(&encapsulated->enc_opt,
01868 option->universe->code_hash,
01869 &option->code, 0, MDL)) {
01870 log_fatal("error finding encapsulated option (%s:%d)",
01871 MDL);
01872 }
01873 }
01874 return 1;
01875 }
01876
01877
01878
01879
01880
01881 int parse_base64 (data, cfile)
01882 struct data_string *data;
01883 struct parse *cfile;
01884 {
01885 const char *val;
01886 int i, j, k;
01887 unsigned acc = 0;
01888 static unsigned char
01889 from64 [] = {64, 64, 64, 64, 64, 64, 64, 64,
01890 64, 64, 64, 62, 64, 64, 64, 63,
01891 52, 53, 54, 55, 56, 57, 58, 59,
01892 60, 61, 64, 64, 64, 64, 64, 64,
01893 64, 0, 1, 2, 3, 4, 5, 6,
01894 7, 8, 9, 10, 11, 12, 13, 14,
01895 15, 16, 17, 18, 19, 20, 21, 22,
01896 23, 24, 25, 64, 64, 64, 64, 64,
01897 64, 26, 27, 28, 29, 30, 31, 32,
01898 33, 34, 35, 36, 37, 38, 39, 40,
01899 41, 42, 43, 44, 45, 46, 47, 48,
01900 49, 50, 51, 64, 64, 64, 64, 64};
01901 struct string_list *bufs = NULL,
01902 *last = NULL,
01903 *t;
01904 int cc = 0;
01905 int terminated = 0;
01906 int valid_base64;
01907
01908
01909
01910
01911 do {
01912 unsigned l;
01913
01914 (void)next_token(&val, &l, cfile);
01915 t = dmalloc(l + sizeof(*t), MDL);
01916 if (t == NULL)
01917 log_fatal("no memory for base64 buffer.");
01918 memset(t, 0, (sizeof(*t)) - 1);
01919 memcpy(t->string, val, l + 1);
01920 cc += l;
01921 if (last)
01922 last->next = t;
01923 else
01924 bufs = t;
01925 last = t;
01926 (void)peek_token(&val, NULL, cfile);
01927 valid_base64 = 1;
01928 for (i = 0; val[i]; i++) {
01929
01930
01931
01932 if (((val[i] < ' ') || (val[i] > 'z')) ||
01933 ((from64[val[i] - ' '] > 63) && (val[i] != '='))) {
01934 valid_base64 = 0;
01935 break;
01936 }
01937 }
01938 } while (valid_base64);
01939
01940 data->len = cc;
01941 data->len = (data->len * 3) / 4;
01942 if (!buffer_allocate(&data->buffer, data->len, MDL)) {
01943 parse_warn (cfile, "can't allocate buffer for base64 data.");
01944 data->len = 0;
01945 data->data = NULL;
01946 goto out;
01947 }
01948
01949 j = k = 0;
01950 for (t = bufs; t; t = t->next) {
01951 for (i = 0; t->string[i]; i++) {
01952 unsigned foo = t->string[i];
01953 if (terminated && foo != '=') {
01954 parse_warn(cfile,
01955 "stuff after base64 '=' terminator: %s.",
01956 &t->string[i]);
01957 goto bad;
01958 }
01959 if ((foo < ' ') || (foo > 'z')) {
01960 bad64:
01961 parse_warn(cfile,
01962 "invalid base64 character %d.",
01963 t->string[i]);
01964 bad:
01965 data_string_forget(data, MDL);
01966 goto out;
01967 }
01968 if (foo == '=')
01969 terminated = 1;
01970 else {
01971 foo = from64[foo - ' '];
01972 if (foo == 64)
01973 goto bad64;
01974 acc = (acc << 6) + foo;
01975 switch (k % 4) {
01976 case 0:
01977 break;
01978 case 1:
01979 data->buffer->data[j++] = (acc >> 4);
01980 acc = acc & 0x0f;
01981 break;
01982
01983 case 2:
01984 data->buffer->data[j++] = (acc >> 2);
01985 acc = acc & 0x03;
01986 break;
01987 case 3:
01988 data->buffer->data[j++] = acc;
01989 acc = 0;
01990 break;
01991 }
01992 }
01993 k++;
01994 }
01995 }
01996 if (k % 4) {
01997 if (acc) {
01998 parse_warn(cfile,
01999 "partial base64 value left over: %d.",
02000 acc);
02001 }
02002 }
02003 data->len = j;
02004 data->data = data->buffer->data;
02005 out:
02006 for (t = bufs; t; t = last) {
02007 last = t->next;
02008 dfree(t, MDL);
02009 }
02010 if (data->len)
02011 return 1;
02012 else
02013 return 0;
02014 }
02015
02016
02017
02018
02019
02020
02021
02022 int parse_cshl (data, cfile)
02023 struct data_string *data;
02024 struct parse *cfile;
02025 {
02026 u_int8_t ibuf [128];
02027 unsigned ilen = 0;
02028 unsigned tlen = 0;
02029 struct option_tag *sl = (struct option_tag *)0;
02030 struct option_tag *next, **last = &sl;
02031 enum dhcp_token token;
02032 const char *val;
02033 unsigned char *rvp;
02034
02035 do {
02036 token = next_token (&val, (unsigned *)0, cfile);
02037 if (token != NUMBER && token != NUMBER_OR_NAME) {
02038 parse_warn (cfile, "expecting hexadecimal number.");
02039 skip_to_semi (cfile);
02040 for (; sl; sl = next) {
02041 next = sl -> next;
02042 dfree (sl, MDL);
02043 }
02044 return 0;
02045 }
02046 if (ilen == sizeof ibuf) {
02047 next = (struct option_tag *)
02048 dmalloc (ilen - 1 +
02049 sizeof (struct option_tag), MDL);
02050 if (!next)
02051 log_fatal ("no memory for string list.");
02052 memcpy (next -> data, ibuf, ilen);
02053 *last = next;
02054 last = &next -> next;
02055 tlen += ilen;
02056 ilen = 0;
02057 }
02058 convert_num (cfile, &ibuf [ilen++], val, 16, 8);
02059
02060 token = peek_token (&val, (unsigned *)0, cfile);
02061 if (token != COLON)
02062 break;
02063 skip_token(&val, (unsigned *)0, cfile);
02064 } while (1);
02065
02066 if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
02067 log_fatal ("no memory to store octet data.");
02068 data -> data = &data -> buffer -> data [0];
02069 data -> len = tlen + ilen;
02070 data -> terminated = 0;
02071
02072 rvp = &data -> buffer -> data [0];
02073 while (sl) {
02074 next = sl -> next;
02075 memcpy (rvp, sl -> data, sizeof ibuf);
02076 rvp += sizeof ibuf;
02077 dfree (sl, MDL);
02078 sl = next;
02079 }
02080
02081 memcpy (rvp, ibuf, ilen);
02082 return 1;
02083 }
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099 int parse_executable_statements (statements, cfile, lose, case_context)
02100 struct executable_statement **statements;
02101 struct parse *cfile;
02102 int *lose;
02103 enum expression_context case_context;
02104 {
02105 struct executable_statement **next;
02106
02107 next = statements;
02108 while (parse_executable_statement (next, cfile, lose, case_context))
02109 next = &((*next) -> next);
02110 if (!*lose)
02111 return 1;
02112 return 0;
02113 }
02114
02115 int parse_executable_statement (result, cfile, lose, case_context)
02116 struct executable_statement **result;
02117 struct parse *cfile;
02118 int *lose;
02119 enum expression_context case_context;
02120 {
02121 #if defined(ENABLE_EXECUTE)
02122 unsigned len;
02123 struct expression **ep;
02124 #endif
02125 enum dhcp_token token;
02126 const char *val;
02127 struct class *cta;
02128 struct option *option=NULL;
02129 struct option_cache *cache;
02130 int known;
02131 int flag;
02132 int i;
02133 struct dns_zone *zone;
02134 isc_result_t status;
02135 char *s;
02136
02137 token = peek_token (&val, (unsigned *)0, cfile);
02138 switch (token) {
02139 case DB_TIME_FORMAT:
02140 skip_token(&val, NULL, cfile);
02141 token = next_token(&val, NULL, cfile);
02142 if (token == DEFAULT) {
02143 db_time_format = DEFAULT_TIME_FORMAT;
02144 } else if (token == LOCAL) {
02145 db_time_format = LOCAL_TIME_FORMAT;
02146 } else {
02147 parse_warn(cfile, "Expecting 'local' or 'default'.");
02148 if (token != SEMI)
02149 skip_to_semi(cfile);
02150 *lose = 1;
02151 return 0;
02152 }
02153
02154 token = next_token(&val, NULL, cfile);
02155 if (token != SEMI) {
02156 parse_warn(cfile, "Expecting a semicolon.");
02157 *lose = 1;
02158 return 0;
02159 }
02160
02161
02162 return 1;
02163
02164 case IF:
02165 skip_token(&val, (unsigned *)0, cfile);
02166 return parse_if_statement (result, cfile, lose);
02167
02168 case TOKEN_ADD:
02169 skip_token(&val, (unsigned *)0, cfile);
02170 token = next_token (&val, (unsigned *)0, cfile);
02171 if (token != STRING) {
02172 parse_warn (cfile, "expecting class name.");
02173 skip_to_semi (cfile);
02174 *lose = 1;
02175 return 0;
02176 }
02177 cta = (struct class *)0;
02178 status = find_class (&cta, val, MDL);
02179 if (status != ISC_R_SUCCESS) {
02180 parse_warn (cfile, "class %s: %s",
02181 val, isc_result_totext (status));
02182 skip_to_semi (cfile);
02183 *lose = 1;
02184 return 0;
02185 }
02186 if (!parse_semi (cfile)) {
02187 *lose = 1;
02188 return 0;
02189 }
02190 if (!executable_statement_allocate (result, MDL))
02191 log_fatal ("no memory for new statement.");
02192 (*result) -> op = add_statement;
02193 (*result) -> data.add = cta;
02194 break;
02195
02196 case BREAK:
02197 skip_token(&val, (unsigned *)0, cfile);
02198 if (!parse_semi (cfile)) {
02199 *lose = 1;
02200 return 0;
02201 }
02202 if (!executable_statement_allocate (result, MDL))
02203 log_fatal ("no memory for new statement.");
02204 (*result) -> op = break_statement;
02205 break;
02206
02207 case SEND:
02208 skip_token(&val, (unsigned *)0, cfile);
02209 known = 0;
02210 status = parse_option_name (cfile, 0, &known, &option);
02211 if (status != ISC_R_SUCCESS || option == NULL) {
02212 *lose = 1;
02213 return 0;
02214 }
02215 status = parse_option_statement(result, cfile, 1, option,
02216 send_option_statement);
02217 option_dereference(&option, MDL);
02218 return status;
02219
02220 case SUPERSEDE:
02221 case OPTION:
02222 skip_token(&val, (unsigned *)0, cfile);
02223 known = 0;
02224 status = parse_option_name (cfile, 0, &known, &option);
02225 if (status != ISC_R_SUCCESS || option == NULL) {
02226 *lose = 1;
02227 return 0;
02228 }
02229 status = parse_option_statement(result, cfile, 1, option,
02230 supersede_option_statement);
02231 option_dereference(&option, MDL);
02232 return status;
02233
02234 case ALLOW:
02235 flag = 1;
02236 goto pad;
02237 case DENY:
02238 flag = 0;
02239 goto pad;
02240 case IGNORE:
02241 flag = 2;
02242 pad:
02243 skip_token(&val, (unsigned *)0, cfile);
02244 cache = (struct option_cache *)0;
02245 if (!parse_allow_deny (&cache, cfile, flag))
02246 return 0;
02247 if (!executable_statement_allocate (result, MDL))
02248 log_fatal ("no memory for new statement.");
02249 (*result) -> op = supersede_option_statement;
02250 (*result) -> data.option = cache;
02251 break;
02252
02253 case DEFAULT:
02254 skip_token(&val, (unsigned *)0, cfile);
02255 token = peek_token (&val, (unsigned *)0, cfile);
02256 if (token == COLON)
02257 goto switch_default;
02258 known = 0;
02259 status = parse_option_name (cfile, 0, &known, &option);
02260 if (status != ISC_R_SUCCESS || option == NULL) {
02261 *lose = 1;
02262 return 0;
02263 }
02264 status = parse_option_statement(result, cfile, 1, option,
02265 default_option_statement);
02266 option_dereference(&option, MDL);
02267 return status;
02268
02269 case PREPEND:
02270 skip_token(&val, (unsigned *)0, cfile);
02271 known = 0;
02272 status = parse_option_name (cfile, 0, &known, &option);
02273 if (status != ISC_R_SUCCESS || option == NULL) {
02274 *lose = 1;
02275 return 0;
02276 }
02277 status = parse_option_statement(result, cfile, 1, option,
02278 prepend_option_statement);
02279 option_dereference(&option, MDL);
02280 return status;
02281
02282 case APPEND:
02283 skip_token(&val, (unsigned *)0, cfile);
02284 known = 0;
02285 status = parse_option_name (cfile, 0, &known, &option);
02286 if (status != ISC_R_SUCCESS || option == NULL) {
02287 *lose = 1;
02288 return 0;
02289 }
02290 status = parse_option_statement(result, cfile, 1, option,
02291 append_option_statement);
02292 option_dereference(&option, MDL);
02293 return status;
02294
02295 case ON:
02296 skip_token(&val, (unsigned *)0, cfile);
02297 return parse_on_statement (result, cfile, lose);
02298
02299 case SWITCH:
02300 skip_token(&val, (unsigned *)0, cfile);
02301 return parse_switch_statement (result, cfile, lose);
02302
02303 case CASE:
02304 skip_token(&val, (unsigned *)0, cfile);
02305 if (case_context == context_any) {
02306 parse_warn (cfile,
02307 "case statement in inappropriate scope.");
02308 *lose = 1;
02309 skip_to_semi (cfile);
02310 return 0;
02311 }
02312 return parse_case_statement (result,
02313 cfile, lose, case_context);
02314
02315 switch_default:
02316 skip_token(&val, (unsigned *)0, cfile);
02317 if (case_context == context_any) {
02318 parse_warn (cfile, "switch default statement in %s",
02319 "inappropriate scope.");
02320
02321 *lose = 1;
02322 return 0;
02323 } else {
02324 if (!executable_statement_allocate (result, MDL))
02325 log_fatal ("no memory for default statement.");
02326 (*result) -> op = default_statement;
02327 return 1;
02328 }
02329
02330 case DEFINE:
02331 case TOKEN_SET:
02332 skip_token(&val, (unsigned *)0, cfile);
02333 if (token == DEFINE)
02334 flag = 1;
02335 else
02336 flag = 0;
02337
02338 token = next_token (&val, (unsigned *)0, cfile);
02339 if (token != NAME && token != NUMBER_OR_NAME) {
02340 parse_warn (cfile,
02341 "%s can't be a variable name", val);
02342 badset:
02343 skip_to_semi (cfile);
02344 *lose = 1;
02345 return 0;
02346 }
02347
02348 if (!executable_statement_allocate (result, MDL))
02349 log_fatal ("no memory for set statement.");
02350 (*result) -> op = flag ? define_statement : set_statement;
02351 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
02352 if (!(*result)->data.set.name)
02353 log_fatal ("can't allocate variable name");
02354 strcpy ((*result) -> data.set.name, val);
02355 token = next_token (&val, (unsigned *)0, cfile);
02356
02357 if (token == LPAREN) {
02358 struct string_list *head, *cur, *new;
02359 struct expression *expr;
02360 head = cur = (struct string_list *)0;
02361 do {
02362 token = next_token (&val,
02363 (unsigned *)0, cfile);
02364 if (token == RPAREN)
02365 break;
02366 if (token != NAME && token != NUMBER_OR_NAME) {
02367 parse_warn (cfile,
02368 "expecting argument name");
02369 skip_to_rbrace (cfile, 0);
02370 *lose = 1;
02371 executable_statement_dereference
02372 (result, MDL);
02373 return 0;
02374 }
02375 new = ((struct string_list *)
02376 dmalloc (sizeof (struct string_list) +
02377 strlen (val), MDL));
02378 if (!new)
02379 log_fatal ("can't allocate string.");
02380 memset (new, 0, sizeof *new);
02381 strcpy (new -> string, val);
02382 if (cur) {
02383 cur -> next = new;
02384 cur = new;
02385 } else {
02386 head = cur = new;
02387 }
02388 token = next_token (&val,
02389 (unsigned *)0, cfile);
02390 } while (token == COMMA);
02391
02392 if (token != RPAREN) {
02393 parse_warn (cfile, "expecting right paren.");
02394 badx:
02395 skip_to_semi (cfile);
02396 *lose = 1;
02397 executable_statement_dereference (result, MDL);
02398 return 0;
02399 }
02400
02401 token = next_token (&val, (unsigned *)0, cfile);
02402 if (token != LBRACE) {
02403 parse_warn (cfile, "expecting left brace.");
02404 goto badx;
02405 }
02406
02407 expr = (struct expression *)0;
02408 if (!(expression_allocate (&expr, MDL)))
02409 log_fatal ("can't allocate expression.");
02410 expr -> op = expr_function;
02411 if (!fundef_allocate (&expr -> data.func, MDL))
02412 log_fatal ("can't allocate fundef.");
02413 expr -> data.func -> args = head;
02414 (*result) -> data.set.expr = expr;
02415
02416 if (!(parse_executable_statements
02417 (&expr -> data.func -> statements, cfile, lose,
02418 case_context))) {
02419 if (*lose)
02420 goto badx;
02421 }
02422
02423 token = next_token (&val, (unsigned *)0, cfile);
02424 if (token != RBRACE) {
02425 parse_warn (cfile, "expecting rigt brace.");
02426 goto badx;
02427 }
02428 } else {
02429 if (token != EQUAL) {
02430 parse_warn (cfile,
02431 "expecting '=' in %s statement.",
02432 flag ? "define" : "set");
02433 goto badset;
02434 }
02435
02436 if (!parse_expression (&(*result) -> data.set.expr,
02437 cfile, lose, context_any,
02438 (struct expression **)0,
02439 expr_none)) {
02440 if (!*lose)
02441 parse_warn (cfile,
02442 "expecting expression.");
02443 else
02444 *lose = 1;
02445 skip_to_semi (cfile);
02446 executable_statement_dereference (result, MDL);
02447 return 0;
02448 }
02449 if (!parse_semi (cfile)) {
02450 *lose = 1;
02451 executable_statement_dereference (result, MDL);
02452 return 0;
02453 }
02454 }
02455 break;
02456
02457 case UNSET:
02458 skip_token(&val, (unsigned *)0, cfile);
02459 token = next_token (&val, (unsigned *)0, cfile);
02460 if (token != NAME && token != NUMBER_OR_NAME) {
02461 parse_warn (cfile,
02462 "%s can't be a variable name", val);
02463 skip_to_semi (cfile);
02464 *lose = 1;
02465 return 0;
02466 }
02467
02468 if (!executable_statement_allocate (result, MDL))
02469 log_fatal ("no memory for set statement.");
02470 (*result) -> op = unset_statement;
02471 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
02472 if (!(*result)->data.unset)
02473 log_fatal ("can't allocate variable name");
02474 strcpy ((*result) -> data.unset, val);
02475 if (!parse_semi (cfile)) {
02476 *lose = 1;
02477 executable_statement_dereference (result, MDL);
02478 return 0;
02479 }
02480 break;
02481
02482 case EVAL:
02483 skip_token(&val, (unsigned *)0, cfile);
02484 if (!executable_statement_allocate (result, MDL))
02485 log_fatal ("no memory for eval statement.");
02486 (*result) -> op = eval_statement;
02487
02488 if (!parse_expression (&(*result) -> data.eval,
02489 cfile, lose, context_data,
02490 (struct expression **)0, expr_none)) {
02491 if (!*lose)
02492 parse_warn (cfile,
02493 "expecting data expression.");
02494 else
02495 *lose = 1;
02496 skip_to_semi (cfile);
02497 executable_statement_dereference (result, MDL);
02498 return 0;
02499 }
02500 if (!parse_semi (cfile)) {
02501 *lose = 1;
02502 executable_statement_dereference (result, MDL);
02503 }
02504 break;
02505
02506 case EXECUTE:
02507 #ifdef ENABLE_EXECUTE
02508 skip_token(&val, NULL, cfile);
02509
02510 if (!executable_statement_allocate (result, MDL))
02511 log_fatal ("no memory for execute statement.");
02512 (*result)->op = execute_statement;
02513
02514 token = next_token(&val, NULL, cfile);
02515 if (token != LPAREN) {
02516 parse_warn(cfile, "left parenthesis expected.");
02517 skip_to_semi(cfile);
02518 *lose = 1;
02519 return 0;
02520 }
02521
02522 token = next_token(&val, &len, cfile);
02523 if (token != STRING) {
02524 parse_warn(cfile, "Expecting a quoted string.");
02525 skip_to_semi(cfile);
02526 *lose = 1;
02527 return 0;
02528 }
02529
02530 (*result)->data.execute.command = dmalloc(len + 1, MDL);
02531 if ((*result)->data.execute.command == NULL)
02532 log_fatal("can't allocate command name");
02533 strcpy((*result)->data.execute.command, val);
02534
02535 ep = &(*result)->data.execute.arglist;
02536 (*result)->data.execute.argc = 0;
02537
02538 while((token = next_token(&val, NULL, cfile)) == COMMA) {
02539 if (!expression_allocate(ep, MDL))
02540 log_fatal ("can't allocate expression");
02541
02542 if (!parse_data_expression (&(*ep) -> data.arg.val,
02543 cfile, lose)) {
02544 if (!*lose) {
02545 parse_warn (cfile,
02546 "expecting expression.");
02547 *lose = 1;
02548 }
02549 skip_to_semi(cfile);
02550 *lose = 1;
02551 return 0;
02552 }
02553 ep = &(*ep)->data.arg.next;
02554 (*result)->data.execute.argc++;
02555 }
02556
02557 if (token != RPAREN) {
02558 parse_warn(cfile, "right parenthesis expected.");
02559 skip_to_semi(cfile);
02560 *lose = 1;
02561 return 0;
02562 }
02563
02564 if (!parse_semi (cfile)) {
02565 *lose = 1;
02566 executable_statement_dereference (result, MDL);
02567 }
02568 #else
02569 parse_warn(cfile, "define ENABLE_EXECUTE in site.h to "
02570 "enable execute(); expressions.");
02571 skip_to_semi(cfile);
02572 *lose = 1;
02573 return 0;
02574 #endif
02575 break;
02576
02577 case RETURN:
02578 skip_token(&val, (unsigned *)0, cfile);
02579
02580 if (!executable_statement_allocate (result, MDL))
02581 log_fatal ("no memory for return statement.");
02582 (*result) -> op = return_statement;
02583
02584 if (!parse_expression (&(*result) -> data.retval,
02585 cfile, lose, context_data,
02586 (struct expression **)0, expr_none)) {
02587 if (!*lose)
02588 parse_warn (cfile,
02589 "expecting data expression.");
02590 else
02591 *lose = 1;
02592 skip_to_semi (cfile);
02593 executable_statement_dereference (result, MDL);
02594 return 0;
02595 }
02596 if (!parse_semi (cfile)) {
02597 *lose = 1;
02598 executable_statement_dereference (result, MDL);
02599 return 0;
02600 }
02601 break;
02602
02603 case LOG:
02604 skip_token(&val, (unsigned *)0, cfile);
02605
02606 if (!executable_statement_allocate (result, MDL))
02607 log_fatal ("no memory for log statement.");
02608 (*result) -> op = log_statement;
02609
02610 token = next_token (&val, (unsigned *)0, cfile);
02611 if (token != LPAREN) {
02612 parse_warn (cfile, "left parenthesis expected.");
02613 skip_to_semi (cfile);
02614 *lose = 1;
02615 return 0;
02616 }
02617
02618 token = peek_token (&val, (unsigned *)0, cfile);
02619 i = 1;
02620 if (token == FATAL) {
02621 (*result) -> data.log.priority = log_priority_fatal;
02622 } else if (token == ERROR) {
02623 (*result) -> data.log.priority = log_priority_error;
02624 } else if (token == TOKEN_DEBUG) {
02625 (*result) -> data.log.priority = log_priority_debug;
02626 } else if (token == INFO) {
02627 (*result) -> data.log.priority = log_priority_info;
02628 } else {
02629 (*result) -> data.log.priority = log_priority_debug;
02630 i = 0;
02631 }
02632 if (i) {
02633 skip_token(&val, (unsigned *)0, cfile);
02634 token = next_token (&val, (unsigned *)0, cfile);
02635 if (token != COMMA) {
02636 parse_warn (cfile, "comma expected.");
02637 skip_to_semi (cfile);
02638 *lose = 1;
02639 return 0;
02640 }
02641 }
02642
02643 if (!(parse_data_expression
02644 (&(*result) -> data.log.expr, cfile, lose))) {
02645 skip_to_semi (cfile);
02646 *lose = 1;
02647 return 0;
02648 }
02649
02650 token = next_token (&val, (unsigned *)0, cfile);
02651 if (token != RPAREN) {
02652 parse_warn (cfile, "right parenthesis expected.");
02653 skip_to_semi (cfile);
02654 *lose = 1;
02655 return 0;
02656 }
02657
02658 token = next_token (&val, (unsigned *)0, cfile);
02659 if (token != SEMI) {
02660 parse_warn (cfile, "semicolon expected.");
02661 skip_to_semi (cfile);
02662 *lose = 1;
02663 return 0;
02664 }
02665 break;
02666
02667
02668
02669
02670 case ZONE:
02671 skip_token(&val, (unsigned *)0, cfile);
02672 zone = (struct dns_zone *)0;
02673 if (!dns_zone_allocate (&zone, MDL))
02674 log_fatal ("no memory for new zone.");
02675 zone -> name = parse_host_name (cfile);
02676 if (!zone -> name) {
02677 parse_warn (cfile, "expecting hostname.");
02678 badzone:
02679 *lose = 1;
02680 skip_to_semi (cfile);
02681 dns_zone_dereference (&zone, MDL);
02682 return 0;
02683 }
02684 i = strlen (zone -> name);
02685 if (zone -> name [i - 1] != '.') {
02686 s = dmalloc ((unsigned)i + 2, MDL);
02687 if (!s) {
02688 parse_warn (cfile, "no trailing '.' on zone");
02689 goto badzone;
02690 }
02691 strcpy (s, zone -> name);
02692 s [i] = '.';
02693 s [i + 1] = 0;
02694 dfree (zone -> name, MDL);
02695 zone -> name = s;
02696 }
02697 if (!parse_zone (zone, cfile))
02698 goto badzone;
02699 status = enter_dns_zone (zone);
02700 if (status != ISC_R_SUCCESS) {
02701 parse_warn (cfile, "dns zone key %s: %s",
02702 zone -> name, isc_result_totext (status));
02703 dns_zone_dereference (&zone, MDL);
02704 return 0;
02705 }
02706 dns_zone_dereference (&zone, MDL);
02707 return 1;
02708
02709
02710 case KEY:
02711 skip_token(&val, (unsigned *)0, cfile);
02712 if (!parse_key (cfile)) {
02713 *lose = 1;
02714 return 0;
02715 }
02716 return 1;
02717
02718 default:
02719 if (config_universe && is_identifier (token)) {
02720 option = (struct option *)0;
02721 option_name_hash_lookup(&option,
02722 config_universe->name_hash,
02723 val, 0, MDL);
02724 if (option) {
02725 skip_token(&val, (unsigned *)0, cfile);
02726 status = parse_option_statement
02727 (result, cfile, 1, option,
02728 supersede_option_statement);
02729 option_dereference(&option, MDL);
02730 return status;
02731 }
02732 }
02733
02734 if (token == NUMBER_OR_NAME || token == NAME) {
02735
02736
02737 if (!executable_statement_allocate (result, MDL))
02738 log_fatal ("no memory for eval statement.");
02739 (*result) -> op = eval_statement;
02740
02741 if (!parse_expression (&(*result) -> data.eval,
02742 cfile, lose, context_data,
02743 (struct expression **)0,
02744 expr_none)) {
02745 if (!*lose)
02746 parse_warn (cfile, "expecting "
02747 "function call.");
02748 else
02749 *lose = 1;
02750 skip_to_semi (cfile);
02751 executable_statement_dereference (result, MDL);
02752 return 0;
02753 }
02754 if (!parse_semi (cfile)) {
02755 *lose = 1;
02756 executable_statement_dereference (result, MDL);
02757 return 0;
02758 }
02759 break;
02760 }
02761
02762 *lose = 0;
02763 return 0;
02764 }
02765
02766 return 1;
02767 }
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782 int parse_zone (struct dns_zone *zone, struct parse *cfile)
02783 {
02784 int token;
02785 const char *val;
02786 char *key_name;
02787 struct option_cache *oc;
02788 int done = 0;
02789
02790 token = next_token (&val, (unsigned *)0, cfile);
02791 if (token != LBRACE) {
02792 parse_warn (cfile, "expecting left brace");
02793 return 0;
02794 }
02795
02796 do {
02797 token = peek_token (&val, (unsigned *)0, cfile);
02798 switch (token) {
02799 case PRIMARY:
02800 if (zone -> primary) {
02801 parse_warn (cfile,
02802 "more than one primary.");
02803 skip_to_semi (cfile);
02804 return 0;
02805 }
02806 if (!option_cache_allocate (&zone -> primary, MDL))
02807 log_fatal ("can't allocate primary option cache.");
02808 oc = zone -> primary;
02809 goto consemup;
02810
02811 case SECONDARY:
02812 if (zone -> secondary) {
02813 parse_warn (cfile, "more than one secondary.");
02814 skip_to_semi (cfile);
02815 return 0;
02816 }
02817 if (!option_cache_allocate (&zone -> secondary, MDL))
02818 log_fatal ("can't allocate secondary.");
02819 oc = zone -> secondary;
02820 consemup:
02821 skip_token(&val, (unsigned *)0, cfile);
02822 do {
02823 struct expression *expr = (struct expression *)0;
02824 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
02825 parse_warn (cfile,
02826 "expecting IP addr or hostname.");
02827 skip_to_semi (cfile);
02828 return 0;
02829 }
02830 if (oc -> expression) {
02831 struct expression *old =
02832 (struct expression *)0;
02833 expression_reference (&old,
02834 oc -> expression,
02835 MDL);
02836 expression_dereference (&oc -> expression,
02837 MDL);
02838 if (!make_concat (&oc -> expression,
02839 old, expr))
02840 log_fatal ("no memory for concat.");
02841 expression_dereference (&expr, MDL);
02842 expression_dereference (&old, MDL);
02843 } else {
02844 expression_reference (&oc -> expression,
02845 expr, MDL);
02846 expression_dereference (&expr, MDL);
02847 }
02848 token = next_token (&val, (unsigned *)0, cfile);
02849 } while (token == COMMA);
02850 if (token != SEMI) {
02851 parse_warn (cfile, "expecting semicolon.");
02852 skip_to_semi (cfile);
02853 return 0;
02854 }
02855 break;
02856
02857 case PRIMARY6:
02858 if (zone->primary6) {
02859 parse_warn(cfile, "more than one primary6.");
02860 skip_to_semi(cfile);
02861 return (0);
02862 }
02863 if (!option_cache_allocate (&zone->primary6, MDL))
02864 log_fatal("can't allocate primary6 option cache.");
02865 oc = zone->primary6;
02866 goto consemup6;
02867
02868 case SECONDARY6:
02869 if (zone->secondary6) {
02870 parse_warn(cfile, "more than one secondary6.");
02871 skip_to_semi(cfile);
02872 return (0);
02873 }
02874 if (!option_cache_allocate (&zone->secondary6, MDL))
02875 log_fatal("can't allocate secondary6 "
02876 "option cache.");
02877 oc = zone->secondary6;
02878 consemup6:
02879 skip_token(&val, NULL, cfile);
02880 do {
02881 struct expression *expr = NULL;
02882 if (parse_ip6_addr_expr(&expr, cfile) == 0) {
02883 parse_warn(cfile, "expecting IPv6 addr.");
02884 skip_to_semi(cfile);
02885 return (0);
02886 }
02887 if (oc->expression) {
02888 struct expression *old = NULL;
02889 expression_reference(&old, oc->expression,
02890 MDL);
02891 expression_dereference(&oc->expression,
02892 MDL);
02893 if (!make_concat(&oc->expression,
02894 old, expr))
02895 log_fatal("no memory for concat.");
02896 expression_dereference(&expr, MDL);
02897 expression_dereference(&old, MDL);
02898 } else {
02899 expression_reference(&oc->expression,
02900 expr, MDL);
02901 expression_dereference(&expr, MDL);
02902 }
02903 token = next_token(&val, NULL, cfile);
02904 } while (token == COMMA);
02905 if (token != SEMI) {
02906 parse_warn(cfile, "expecting semicolon.");
02907 skip_to_semi(cfile);
02908 return (0);
02909 }
02910 break;
02911
02912 case KEY:
02913 skip_token(&val, (unsigned *)0, cfile);
02914 token = peek_token (&val, (unsigned *)0, cfile);
02915 if (token == STRING) {
02916 skip_token(&val, (unsigned *)0, cfile);
02917 key_name = (char *)0;
02918 } else {
02919 key_name = parse_host_name (cfile);
02920 if (!key_name) {
02921 parse_warn (cfile, "expecting key name.");
02922 skip_to_semi (cfile);
02923 return 0;
02924 }
02925 val = key_name;
02926 }
02927 if (zone->key)
02928 log_fatal("Multiple key definition for zone %s.",
02929 zone->name);
02930 if (omapi_auth_key_lookup_name (&zone -> key, val) !=
02931 ISC_R_SUCCESS)
02932 parse_warn (cfile, "unknown key %s", val);
02933 if (key_name)
02934 dfree (key_name, MDL);
02935 if (!parse_semi (cfile))
02936 return 0;
02937 break;
02938
02939 default:
02940 done = 1;
02941 break;
02942 }
02943 } while (!done);
02944
02945 token = next_token (&val, (unsigned *)0, cfile);
02946 if (token != RBRACE) {
02947 parse_warn (cfile, "expecting right brace.");
02948 return 0;
02949 }
02950 return 1;
02951 }
02952
02953
02954
02955
02956
02957
02958
02959
02960
02961 int parse_key (struct parse *cfile)
02962 {
02963 int token;
02964 const char *val;
02965 int done = 0;
02966 struct auth_key *key;
02967 struct data_string ds;
02968 isc_result_t status;
02969 char *s;
02970
02971 key = (struct auth_key *)0;
02972 if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
02973 log_fatal ("no memory for key");
02974
02975 token = peek_token (&val, (unsigned *)0, cfile);
02976 if (token == STRING) {
02977 skip_token(&val, (unsigned *)0, cfile);
02978 key -> name = dmalloc (strlen (val) + 1, MDL);
02979 if (!key -> name)
02980 log_fatal ("no memory for key name.");
02981 strcpy (key -> name, val);
02982
02983 } else {
02984 key -> name = parse_host_name (cfile);
02985 if (!key -> name) {
02986 parse_warn (cfile, "expecting key name.");
02987 skip_to_semi (cfile);
02988 goto bad;
02989 }
02990 }
02991
02992 token = next_token (&val, (unsigned *)0, cfile);
02993 if (token != LBRACE) {
02994 parse_warn (cfile, "expecting left brace");
02995 goto bad;
02996 }
02997
02998 do {
02999 token = next_token (&val, (unsigned *)0, cfile);
03000 switch (token) {
03001 case ALGORITHM:
03002 if (key -> algorithm) {
03003 parse_warn (cfile,
03004 "key %s: too many algorithms",
03005 key -> name);
03006 goto rbad;
03007 }
03008 key -> algorithm = parse_host_name (cfile);
03009 if (!key -> algorithm) {
03010 parse_warn (cfile,
03011 "expecting key algorithm name.");
03012 goto rbad;
03013 }
03014 if (!parse_semi (cfile))
03015 goto rbad;
03016
03017
03018 s = strrchr (key -> algorithm, '.');
03019 if (!s) {
03020 static char add [] = ".SIG-ALG.REG.INT.";
03021 s = dmalloc (strlen (key -> algorithm) +
03022 sizeof (add), MDL);
03023 if (!s) {
03024 log_error ("no memory for key %s.",
03025 "algorithm");
03026 goto rbad;
03027 }
03028 strcpy (s, key -> algorithm);
03029 strcat (s, add);
03030 dfree (key -> algorithm, MDL);
03031 key -> algorithm = s;
03032 } else if (s [1]) {
03033
03034 s = dmalloc (strlen (key -> algorithm) + 2, MDL);
03035 if (!s) {
03036 log_error ("no memory for key %s.",
03037 key -> algorithm);
03038 goto rbad;
03039 }
03040 strcpy (s, key -> algorithm);
03041 strcat (s, ".");
03042 dfree (key -> algorithm, MDL);
03043 key -> algorithm = s;
03044 }
03045 break;
03046
03047 case SECRET:
03048 if (key -> key) {
03049 parse_warn (cfile, "key %s: too many secrets",
03050 key -> name);
03051 goto rbad;
03052 }
03053
03054 memset (&ds, 0, sizeof(ds));
03055 if (!parse_base64 (&ds, cfile))
03056 goto rbad;
03057 status = omapi_data_string_new (&key -> key, ds.len,
03058 MDL);
03059 if (status != ISC_R_SUCCESS)
03060 goto rbad;
03061 memcpy (key -> key -> value,
03062 ds.buffer -> data, ds.len);
03063 data_string_forget (&ds, MDL);
03064
03065 if (!parse_semi (cfile))
03066 goto rbad;
03067 break;
03068
03069 default:
03070 done = 1;
03071 break;
03072 }
03073 } while (!done);
03074 if (token != RBRACE) {
03075 parse_warn (cfile, "expecting right brace.");
03076 goto rbad;
03077 }
03078
03079
03080 token = peek_token (&val, (unsigned *)0, cfile);
03081 if (token == SEMI) {
03082 skip_token(&val, (unsigned *)0, cfile);
03083 }
03084
03085
03086 status = omapi_auth_key_enter (key);
03087 if (status != ISC_R_SUCCESS) {
03088 parse_warn (cfile, "tsig key %s: %s",
03089 key -> name, isc_result_totext (status));
03090 goto bad;
03091 }
03092 omapi_auth_key_dereference (&key, MDL);
03093 return 1;
03094
03095 rbad:
03096 skip_to_rbrace (cfile, 1);
03097 bad:
03098 omapi_auth_key_dereference (&key, MDL);
03099 return 0;
03100 }
03101
03102
03103
03104
03105
03106
03107
03108
03109 int parse_on_statement (result, cfile, lose)
03110 struct executable_statement **result;
03111 struct parse *cfile;
03112 int *lose;
03113 {
03114 enum dhcp_token token;
03115 const char *val;
03116
03117 if (!executable_statement_allocate (result, MDL))
03118 log_fatal ("no memory for new statement.");
03119 (*result) -> op = on_statement;
03120
03121 do {
03122 token = next_token (&val, (unsigned *)0, cfile);
03123 switch (token) {
03124 case EXPIRY:
03125 (*result) -> data.on.evtypes |= ON_EXPIRY;
03126 break;
03127
03128 case COMMIT:
03129 (*result) -> data.on.evtypes |= ON_COMMIT;
03130 break;
03131
03132 case RELEASE:
03133 (*result) -> data.on.evtypes |= ON_RELEASE;
03134 break;
03135
03136 case TRANSMISSION:
03137 (*result) -> data.on.evtypes |= ON_TRANSMISSION;
03138 break;
03139
03140 default:
03141 parse_warn (cfile, "expecting a lease event type");
03142 skip_to_semi (cfile);
03143 *lose = 1;
03144 executable_statement_dereference (result, MDL);
03145 return 0;
03146 }
03147 token = next_token (&val, (unsigned *)0, cfile);
03148 } while (token == OR);
03149
03150
03151 if (token == SEMI)
03152 return 1;
03153
03154 if (token != LBRACE) {
03155 parse_warn (cfile, "left brace expected.");
03156 skip_to_semi (cfile);
03157 *lose = 1;
03158 executable_statement_dereference (result, MDL);
03159 return 0;
03160 }
03161 if (!parse_executable_statements (&(*result) -> data.on.statements,
03162 cfile, lose, context_any)) {
03163 if (*lose) {
03164
03165 do {
03166 token = next_token (&val,
03167 (unsigned *)0, cfile);
03168 } while (token != END_OF_FILE && token != RBRACE);
03169 executable_statement_dereference (result, MDL);
03170 return 0;
03171 }
03172 }
03173 token = next_token (&val, (unsigned *)0, cfile);
03174 if (token != RBRACE) {
03175 parse_warn (cfile, "right brace expected.");
03176 skip_to_semi (cfile);
03177 *lose = 1;
03178 executable_statement_dereference (result, MDL);
03179 return 0;
03180 }
03181 return 1;
03182 }
03183
03184
03185
03186
03187
03188
03189 int parse_switch_statement (result, cfile, lose)
03190 struct executable_statement **result;
03191 struct parse *cfile;
03192 int *lose;
03193 {
03194 enum dhcp_token token;
03195 const char *val;
03196
03197 if (!executable_statement_allocate (result, MDL))
03198 log_fatal ("no memory for new statement.");
03199 (*result) -> op = switch_statement;
03200
03201 token = next_token (&val, (unsigned *)0, cfile);
03202 if (token != LPAREN) {
03203 parse_warn (cfile, "expecting left brace.");
03204 pfui:
03205 *lose = 1;
03206 skip_to_semi (cfile);
03207 gnorf:
03208 executable_statement_dereference (result, MDL);
03209 return 0;
03210 }
03211
03212 if (!parse_expression (&(*result) -> data.s_switch.expr,
03213 cfile, lose, context_data_or_numeric,
03214 (struct expression **)0, expr_none)) {
03215 if (!*lose) {
03216 parse_warn (cfile,
03217 "expecting data or numeric expression.");
03218 goto pfui;
03219 }
03220 goto gnorf;
03221 }
03222
03223 token = next_token (&val, (unsigned *)0, cfile);
03224 if (token != RPAREN) {
03225 parse_warn (cfile, "right paren expected.");
03226 goto pfui;
03227 }
03228
03229 token = next_token (&val, (unsigned *)0, cfile);
03230 if (token != LBRACE) {
03231 parse_warn (cfile, "left brace expected.");
03232 goto pfui;
03233 }
03234 if (!(parse_executable_statements
03235 (&(*result) -> data.s_switch.statements, cfile, lose,
03236 (is_data_expression ((*result) -> data.s_switch.expr)
03237 ? context_data : context_numeric)))) {
03238 if (*lose) {
03239 skip_to_rbrace (cfile, 1);
03240 executable_statement_dereference (result, MDL);
03241 return 0;
03242 }
03243 }
03244 token = next_token (&val, (unsigned *)0, cfile);
03245 if (token != RBRACE) {
03246 parse_warn (cfile, "right brace expected.");
03247 goto pfui;
03248 }
03249 return 1;
03250 }
03251
03252
03253
03254
03255
03256
03257 int parse_case_statement (result, cfile, lose, case_context)
03258 struct executable_statement **result;
03259 struct parse *cfile;
03260 int *lose;
03261 enum expression_context case_context;
03262 {
03263 enum dhcp_token token;
03264 const char *val;
03265
03266 if (!executable_statement_allocate (result, MDL))
03267 log_fatal ("no memory for new statement.");
03268 (*result) -> op = case_statement;
03269
03270 if (!parse_expression (&(*result) -> data.c_case,
03271 cfile, lose, case_context,
03272 (struct expression **)0, expr_none))
03273 {
03274 if (!*lose) {
03275 parse_warn (cfile, "expecting %s expression.",
03276 (case_context == context_data
03277 ? "data" : "numeric"));
03278 }
03279 pfui:
03280 *lose = 1;
03281 skip_to_semi (cfile);
03282 executable_statement_dereference (result, MDL);
03283 return 0;
03284 }
03285
03286 token = next_token (&val, (unsigned *)0, cfile);
03287 if (token != COLON) {
03288 parse_warn (cfile, "colon expected.");
03289 goto pfui;
03290 }
03291 return 1;
03292 }
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304 int parse_if_statement (result, cfile, lose)
03305 struct executable_statement **result;
03306 struct parse *cfile;
03307 int *lose;
03308 {
03309 enum dhcp_token token;
03310 const char *val;
03311 int parenp;
03312
03313 if (!executable_statement_allocate (result, MDL))
03314 log_fatal ("no memory for if statement.");
03315
03316 (*result) -> op = if_statement;
03317
03318 token = peek_token (&val, (unsigned *)0, cfile);
03319 if (token == LPAREN) {
03320 parenp = 1;
03321 skip_token(&val, (unsigned *)0, cfile);
03322 } else
03323 parenp = 0;
03324
03325
03326 if (!parse_boolean_expression (&(*result) -> data.ie.expr,
03327 cfile, lose)) {
03328 if (!*lose)
03329 parse_warn (cfile, "boolean expression expected.");
03330 executable_statement_dereference (result, MDL);
03331 *lose = 1;
03332 return 0;
03333 }
03334 #if defined (DEBUG_EXPRESSION_PARSE)
03335 print_expression ("if condition", (*result) -> data.ie.expr);
03336 #endif
03337 if (parenp) {
03338 token = next_token (&val, (unsigned *)0, cfile);
03339 if (token != RPAREN) {
03340 parse_warn (cfile, "expecting right paren.");
03341 *lose = 1;
03342 executable_statement_dereference (result, MDL);
03343 return 0;
03344 }
03345 }
03346 token = next_token (&val, (unsigned *)0, cfile);
03347 if (token != LBRACE) {
03348 parse_warn (cfile, "left brace expected.");
03349 skip_to_semi (cfile);
03350 *lose = 1;
03351 executable_statement_dereference (result, MDL);
03352 return 0;
03353 }
03354 if (!parse_executable_statements (&(*result) -> data.ie.tc,
03355 cfile, lose, context_any)) {
03356 if (*lose) {
03357
03358 do {
03359 token = next_token (&val,
03360 (unsigned *)0, cfile);
03361 } while (token != END_OF_FILE && token != RBRACE);
03362 executable_statement_dereference (result, MDL);
03363 return 0;
03364 }
03365 }
03366 token = next_token (&val, (unsigned *)0, cfile);
03367 if (token != RBRACE) {
03368 parse_warn (cfile, "right brace expected.");
03369 skip_to_semi (cfile);
03370 *lose = 1;
03371 executable_statement_dereference (result, MDL);
03372 return 0;
03373 }
03374 token = peek_token (&val, (unsigned *)0, cfile);
03375 if (token == ELSE) {
03376 skip_token(&val, (unsigned *)0, cfile);
03377 token = peek_token (&val, (unsigned *)0, cfile);
03378 if (token == IF) {
03379 skip_token(&val, (unsigned *)0, cfile);
03380 if (!parse_if_statement (&(*result) -> data.ie.fc,
03381 cfile, lose)) {
03382 if (!*lose)
03383 parse_warn (cfile,
03384 "expecting if statement");
03385 executable_statement_dereference (result, MDL);
03386 *lose = 1;
03387 return 0;
03388 }
03389 } else if (token != LBRACE) {
03390 parse_warn (cfile, "left brace or if expected.");
03391 skip_to_semi (cfile);
03392 *lose = 1;
03393 executable_statement_dereference (result, MDL);
03394 return 0;
03395 } else {
03396 skip_token(&val, (unsigned *)0, cfile);
03397 if (!(parse_executable_statements
03398 (&(*result) -> data.ie.fc,
03399 cfile, lose, context_any))) {
03400 executable_statement_dereference (result, MDL);
03401 return 0;
03402 }
03403 token = next_token (&val, (unsigned *)0, cfile);
03404 if (token != RBRACE) {
03405 parse_warn (cfile, "right brace expected.");
03406 skip_to_semi (cfile);
03407 *lose = 1;
03408 executable_statement_dereference (result, MDL);
03409 return 0;
03410 }
03411 }
03412 } else if (token == ELSIF) {
03413 skip_token(&val, (unsigned *)0, cfile);
03414 if (!parse_if_statement (&(*result) -> data.ie.fc,
03415 cfile, lose)) {
03416 if (!*lose)
03417 parse_warn (cfile,
03418 "expecting conditional.");
03419 executable_statement_dereference (result, MDL);
03420 *lose = 1;
03421 return 0;
03422 }
03423 } else
03424 (*result) -> data.ie.fc = (struct executable_statement *)0;
03425
03426 return 1;
03427 }
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440 int parse_boolean_expression (expr, cfile, lose)
03441 struct expression **expr;
03442 struct parse *cfile;
03443 int *lose;
03444 {
03445
03446 if (!parse_expression (expr, cfile, lose, context_boolean,
03447 (struct expression **)0, expr_none))
03448 return 0;
03449
03450 if (!is_boolean_expression (*expr) &&
03451 (*expr) -> op != expr_variable_reference &&
03452 (*expr) -> op != expr_funcall) {
03453 parse_warn (cfile, "Expecting a boolean expression.");
03454 *lose = 1;
03455 expression_dereference (expr, MDL);
03456 return 0;
03457 }
03458 return 1;
03459 }
03460
03461
03462
03463 int parse_boolean (cfile)
03464 struct parse *cfile;
03465 {
03466 const char *val;
03467 int rv;
03468
03469 (void)next_token(&val, NULL, cfile);
03470 if (!strcasecmp (val, "true")
03471 || !strcasecmp (val, "on"))
03472 rv = 1;
03473 else if (!strcasecmp (val, "false")
03474 || !strcasecmp (val, "off"))
03475 rv = 0;
03476 else {
03477 parse_warn (cfile,
03478 "boolean value (true/false/on/off) expected");
03479 skip_to_semi (cfile);
03480 return 0;
03481 }
03482 parse_semi (cfile);
03483 return rv;
03484 }
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507 int parse_data_expression (expr, cfile, lose)
03508 struct expression **expr;
03509 struct parse *cfile;
03510 int *lose;
03511 {
03512
03513 if (!parse_expression (expr, cfile, lose, context_data,
03514 (struct expression **)0, expr_none))
03515 return 0;
03516
03517 if (!is_data_expression (*expr) &&
03518 (*expr) -> op != expr_variable_reference &&
03519 (*expr) -> op != expr_funcall) {
03520 expression_dereference (expr, MDL);
03521 parse_warn (cfile, "Expecting a data expression.");
03522 *lose = 1;
03523 return 0;
03524 }
03525 return 1;
03526 }
03527
03528
03529
03530
03531
03532
03533
03534 int parse_numeric_expression (expr, cfile, lose)
03535 struct expression **expr;
03536 struct parse *cfile;
03537 int *lose;
03538 {
03539
03540 if (!parse_expression (expr, cfile, lose, context_numeric,
03541 (struct expression **)0, expr_none))
03542 return 0;
03543
03544 if (!is_numeric_expression (*expr) &&
03545 (*expr) -> op != expr_variable_reference &&
03546 (*expr) -> op != expr_funcall) {
03547 expression_dereference (expr, MDL);
03548 parse_warn (cfile, "Expecting a numeric expression.");
03549 *lose = 1;
03550 return 0;
03551 }
03552 return 1;
03553 }
03554
03555
03556
03557 int parse_non_binary (expr, cfile, lose, context)
03558 struct expression **expr;
03559 struct parse *cfile;
03560 int *lose;
03561 enum expression_context context;
03562 {
03563 enum dhcp_token token;
03564 const char *val;
03565 struct collection *col;
03566 struct expression *nexp, **ep;
03567 int known;
03568 char *cptr;
03569 isc_result_t status;
03570 unsigned len;
03571
03572 token = peek_token (&val, (unsigned *)0, cfile);
03573
03574
03575 switch (token) {
03576 case CHECK:
03577 skip_token(&val, (unsigned *)0, cfile);
03578 token = next_token (&val, (unsigned *)0, cfile);
03579 if (token != STRING) {
03580 parse_warn (cfile, "string expected.");
03581 skip_to_semi (cfile);
03582 *lose = 1;
03583 return 0;
03584 }
03585 for (col = collections; col; col = col -> next)
03586 if (!strcmp (col -> name, val))
03587 break;
03588 if (!col) {
03589 parse_warn (cfile, "unknown collection.");
03590 *lose = 1;
03591 return 0;
03592 }
03593 if (!expression_allocate (expr, MDL))
03594 log_fatal ("can't allocate expression");
03595 (*expr) -> op = expr_check;
03596 (*expr) -> data.check = col;
03597 break;
03598
03599 case TOKEN_NOT:
03600 skip_token(&val, NULL, cfile);
03601 if (!expression_allocate (expr, MDL))
03602 log_fatal ("can't allocate expression");
03603 (*expr)->op = expr_not;
03604 if (!parse_non_binary (&(*expr)->data.not,
03605 cfile, lose, context_boolean)) {
03606 if (!*lose) {
03607 parse_warn (cfile, "expression expected");
03608 skip_to_semi (cfile);
03609 }
03610 *lose = 1;
03611 expression_dereference (expr, MDL);
03612 return (0);
03613 }
03614 if (!is_boolean_expression ((*expr) -> data.not)) {
03615 *lose = 1;
03616 parse_warn (cfile, "boolean expression expected");
03617 skip_to_semi (cfile);
03618 expression_dereference (expr, MDL);
03619 return 0;
03620 }
03621 break;
03622
03623 case LPAREN:
03624 skip_token(&val, (unsigned *)0, cfile);
03625 if (!parse_expression (expr, cfile, lose, context,
03626 (struct expression **)0, expr_none)) {
03627 if (!*lose) {
03628 parse_warn (cfile, "expression expected");
03629 skip_to_semi (cfile);
03630 }
03631 *lose = 1;
03632 return 0;
03633 }
03634 token = next_token (&val, (unsigned *)0, cfile);
03635 if (token != RPAREN) {
03636 *lose = 1;
03637 parse_warn (cfile, "right paren expected");
03638 skip_to_semi (cfile);
03639 return 0;
03640 }
03641 break;
03642
03643 case EXISTS:
03644 skip_token(&val, NULL, cfile);
03645 if (!expression_allocate (expr, MDL))
03646 log_fatal ("can't allocate expression");
03647 (*expr)->op = expr_exists;
03648 known = 0;
03649
03650 status = parse_option_name(cfile, 0, &known,
03651 &(*expr)->data.option);
03652 if (status != ISC_R_SUCCESS ||
03653 (*expr)->data.option == NULL) {
03654 *lose = 1;
03655 expression_dereference (expr, MDL);
03656 return (0);
03657 }
03658 break;
03659
03660 case STATIC:
03661 skip_token(&val, (unsigned *)0, cfile);
03662 if (!expression_allocate (expr, MDL))
03663 log_fatal ("can't allocate expression");
03664 (*expr) -> op = expr_static;
03665 break;
03666
03667 case KNOWN:
03668 skip_token(&val, (unsigned *)0, cfile);
03669 if (!expression_allocate (expr, MDL))
03670 log_fatal ("can't allocate expression");
03671 (*expr) -> op = expr_known;
03672 break;
03673
03674 case SUBSTRING:
03675 skip_token(&val, (unsigned *)0, cfile);
03676 if (!expression_allocate (expr, MDL))
03677 log_fatal ("can't allocate expression");
03678 (*expr) -> op = expr_substring;
03679
03680 token = next_token (&val, (unsigned *)0, cfile);
03681 if (token != LPAREN) {
03682 nolparen:
03683 expression_dereference (expr, MDL);
03684 parse_warn (cfile, "left parenthesis expected.");
03685 *lose = 1;
03686 return 0;
03687 }
03688
03689 if (!parse_data_expression (&(*expr) -> data.substring.expr,
03690 cfile, lose)) {
03691 nodata:
03692 expression_dereference (expr, MDL);
03693 if (!*lose) {
03694 parse_warn (cfile,
03695 "expecting data expression.");
03696 skip_to_semi (cfile);
03697 *lose = 1;
03698 }
03699 return 0;
03700 }
03701
03702 token = next_token (&val, (unsigned *)0, cfile);
03703 if (token != COMMA) {
03704 nocomma:
03705 expression_dereference (expr, MDL);
03706 parse_warn (cfile, "comma expected.");
03707 *lose = 1;
03708
03709 return 0;
03710 }
03711
03712 if (!parse_numeric_expression
03713 (&(*expr) -> data.substring.offset,cfile, lose)) {
03714 nonum:
03715 if (!*lose) {
03716 parse_warn (cfile,
03717 "expecting numeric expression.");
03718 skip_to_semi (cfile);
03719 *lose = 1;
03720 }
03721 expression_dereference (expr, MDL);
03722 return 0;
03723 }
03724
03725 token = next_token (&val, (unsigned *)0, cfile);
03726 if (token != COMMA)
03727 goto nocomma;
03728
03729 if (!parse_numeric_expression
03730 (&(*expr) -> data.substring.len, cfile, lose))
03731 goto nonum;
03732
03733 token = next_token (&val, (unsigned *)0, cfile);
03734 if (token != RPAREN) {
03735 norparen:
03736 parse_warn (cfile, "right parenthesis expected.");
03737 *lose = 1;
03738 expression_dereference (expr, MDL);
03739 return 0;
03740 }
03741 break;
03742
03743 case SUFFIX:
03744 skip_token(&val, (unsigned *)0, cfile);
03745 if (!expression_allocate (expr, MDL))
03746 log_fatal ("can't allocate expression");
03747 (*expr) -> op = expr_suffix;
03748
03749 token = next_token (&val, (unsigned *)0, cfile);
03750 if (token != LPAREN)
03751 goto nolparen;
03752
03753 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
03754 cfile, lose))
03755 goto nodata;
03756
03757 token = next_token (&val, (unsigned *)0, cfile);
03758 if (token != COMMA)
03759 goto nocomma;
03760
03761 if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
03762 cfile, lose))
03763 goto nonum;
03764
03765 token = next_token (&val, (unsigned *)0, cfile);
03766 if (token != RPAREN)
03767 goto norparen;
03768 break;
03769
03770 case LCASE:
03771 skip_token(&val, (unsigned *)0, cfile);
03772 if (!expression_allocate(expr, MDL))
03773 log_fatal ("can't allocate expression");
03774 (*expr)->op = expr_lcase;
03775
03776 token = next_token(&val, (unsigned *)0, cfile);
03777 if (token != LPAREN)
03778 goto nolparen;
03779
03780 if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose))
03781 goto nodata;
03782
03783 token = next_token(&val, (unsigned *)0, cfile);
03784 if (token != RPAREN)
03785 goto norparen;
03786 break;
03787
03788 case UCASE:
03789 skip_token(&val, (unsigned *)0, cfile);
03790 if (!expression_allocate(expr, MDL))
03791 log_fatal ("can't allocate expression");
03792 (*expr)->op = expr_ucase;
03793
03794 token = next_token (&val, (unsigned *)0, cfile);
03795 if (token != LPAREN)
03796 goto nolparen;
03797
03798 if (!parse_data_expression(&(*expr)->data.ucase,
03799 cfile, lose))
03800 goto nodata;
03801
03802 token = next_token(&val, (unsigned *)0, cfile);
03803 if (token != RPAREN)
03804 goto norparen;
03805 break;
03806
03807 case CONCAT:
03808 skip_token(&val, (unsigned *)0, cfile);
03809 if (!expression_allocate (expr, MDL))
03810 log_fatal ("can't allocate expression");
03811 (*expr) -> op = expr_concat;
03812
03813 token = next_token (&val, (unsigned *)0, cfile);
03814 if (token != LPAREN)
03815 goto nolparen;
03816
03817 if (!parse_data_expression (&(*expr) -> data.concat [0],
03818 cfile, lose))
03819 goto nodata;
03820
03821 token = next_token (&val, (unsigned *)0, cfile);
03822 if (token != COMMA)
03823 goto nocomma;
03824
03825 concat_another:
03826 if (!parse_data_expression (&(*expr) -> data.concat [1],
03827 cfile, lose))
03828 goto nodata;
03829
03830 token = next_token (&val, (unsigned *)0, cfile);
03831
03832 if (token == COMMA) {
03833 nexp = (struct expression *)0;
03834 if (!expression_allocate (&nexp, MDL))
03835 log_fatal ("can't allocate at CONCAT2");
03836 nexp -> op = expr_concat;
03837 expression_reference (&nexp -> data.concat [0],
03838 *expr, MDL);
03839 expression_dereference (expr, MDL);
03840 expression_reference (expr, nexp, MDL);
03841 expression_dereference (&nexp, MDL);
03842 goto concat_another;
03843 }
03844
03845 if (token != RPAREN)
03846 goto norparen;
03847 break;
03848
03849 case BINARY_TO_ASCII:
03850 skip_token(&val, (unsigned *)0, cfile);
03851 if (!expression_allocate (expr, MDL))
03852 log_fatal ("can't allocate expression");
03853 (*expr) -> op = expr_binary_to_ascii;
03854
03855 token = next_token (&val, (unsigned *)0, cfile);
03856 if (token != LPAREN)
03857 goto nolparen;
03858
03859 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
03860 cfile, lose))
03861 goto nodata;
03862
03863 token = next_token (&val, (unsigned *)0, cfile);
03864 if (token != COMMA)
03865 goto nocomma;
03866
03867 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
03868 cfile, lose))
03869 goto nodata;
03870
03871 token = next_token (&val, (unsigned *)0, cfile);
03872 if (token != COMMA)
03873 goto nocomma;
03874
03875 if (!parse_data_expression (&(*expr) -> data.b2a.separator,
03876 cfile, lose))
03877 goto nodata;
03878
03879 token = next_token (&val, (unsigned *)0, cfile);
03880 if (token != COMMA)
03881 goto nocomma;
03882
03883 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
03884 cfile, lose))
03885 goto nodata;
03886
03887 token = next_token (&val, (unsigned *)0, cfile);
03888 if (token != RPAREN)
03889 goto norparen;
03890 break;
03891
03892 case REVERSE:
03893 skip_token(&val, (unsigned *)0, cfile);
03894 if (!expression_allocate (expr, MDL))
03895 log_fatal ("can't allocate expression");
03896 (*expr) -> op = expr_reverse;
03897
03898 token = next_token (&val, (unsigned *)0, cfile);
03899 if (token != LPAREN)
03900 goto nolparen;
03901
03902 if (!(parse_numeric_expression
03903 (&(*expr) -> data.reverse.width, cfile, lose)))
03904 goto nodata;
03905
03906 token = next_token (&val, (unsigned *)0, cfile);
03907 if (token != COMMA)
03908 goto nocomma;
03909
03910 if (!(parse_data_expression
03911 (&(*expr) -> data.reverse.buffer, cfile, lose)))
03912 goto nodata;
03913
03914 token = next_token (&val, (unsigned *)0, cfile);
03915 if (token != RPAREN)
03916 goto norparen;
03917 break;
03918
03919 case PICK:
03920
03921
03922 skip_token(&val, (unsigned *)0, cfile);
03923 if (!(expression_allocate (expr, MDL)))
03924 log_fatal ("can't allocate expression");
03925
03926 token = next_token (&val, (unsigned *)0, cfile);
03927 if (token != LPAREN)
03928 goto nolparen;
03929
03930 nexp = (struct expression *)0;
03931 expression_reference (&nexp, *expr, MDL);
03932 do {
03933 nexp -> op = expr_pick_first_value;
03934 if (!(parse_data_expression
03935 (&nexp -> data.pick_first_value.car,
03936 cfile, lose)))
03937 goto nodata;
03938
03939 token = next_token (&val, (unsigned *)0, cfile);
03940 if (token == COMMA) {
03941 struct expression *foo = (struct expression *)0;
03942 if (!expression_allocate (&foo, MDL))
03943 log_fatal ("can't allocate expr");
03944 expression_reference
03945 (&nexp -> data.pick_first_value.cdr, foo, MDL);
03946 expression_dereference (&nexp, MDL);
03947 expression_reference (&nexp, foo, MDL);
03948 expression_dereference (&foo, MDL);
03949 }
03950 } while (token == COMMA);
03951 expression_dereference (&nexp, MDL);
03952
03953 if (token != RPAREN)
03954 goto norparen;
03955 break;
03956
03957 case OPTION:
03958 case CONFIG_OPTION:
03959 if (!expression_allocate (expr, MDL))
03960 log_fatal ("can't allocate expression");
03961 (*expr) -> op = (token == OPTION
03962 ? expr_option
03963 : expr_config_option);
03964 skip_token(&val, (unsigned *)0, cfile);
03965 known = 0;
03966
03967 status = parse_option_name(cfile, 0, &known,
03968 &(*expr)->data.option);
03969 if (status != ISC_R_SUCCESS ||
03970 (*expr)->data.option == NULL) {
03971 *lose = 1;
03972 expression_dereference (expr, MDL);
03973 return 0;
03974 }
03975 break;
03976
03977 case HARDWARE:
03978 skip_token(&val, (unsigned *)0, cfile);
03979 if (!expression_allocate (expr, MDL))
03980 log_fatal ("can't allocate expression");
03981 (*expr) -> op = expr_hardware;
03982 break;
03983
03984 case LEASED_ADDRESS:
03985 skip_token(&val, (unsigned *)0, cfile);
03986 if (!expression_allocate (expr, MDL))
03987 log_fatal ("can't allocate expression");
03988 (*expr) -> op = expr_leased_address;
03989 break;
03990
03991 case CLIENT_STATE:
03992 skip_token(&val, (unsigned *)0, cfile);
03993 if (!expression_allocate (expr, MDL))
03994 log_fatal ("can't allocate expression");
03995 (*expr) -> op = expr_client_state;
03996 break;
03997
03998 case FILENAME:
03999 skip_token(&val, (unsigned *)0, cfile);
04000 if (!expression_allocate (expr, MDL))
04001 log_fatal ("can't allocate expression");
04002 (*expr) -> op = expr_filename;
04003 break;
04004
04005 case SERVER_NAME:
04006 skip_token(&val, (unsigned *)0, cfile);
04007 if (!expression_allocate (expr, MDL))
04008 log_fatal ("can't allocate expression");
04009 (*expr) -> op = expr_sname;
04010 break;
04011
04012 case LEASE_TIME:
04013 skip_token(&val, (unsigned *)0, cfile);
04014 if (!expression_allocate (expr, MDL))
04015 log_fatal ("can't allocate expression");
04016 (*expr) -> op = expr_lease_time;
04017 break;
04018
04019 case TOKEN_NULL:
04020 skip_token(&val, (unsigned *)0, cfile);
04021 if (!expression_allocate (expr, MDL))
04022 log_fatal ("can't allocate expression");
04023 (*expr) -> op = expr_null;
04024 break;
04025
04026 case HOST_DECL_NAME:
04027 skip_token(&val, (unsigned *)0, cfile);
04028 if (!expression_allocate (expr, MDL))
04029 log_fatal ("can't allocate expression");
04030 (*expr) -> op = expr_host_decl_name;
04031 break;
04032
04033 case PACKET:
04034 skip_token(&val, (unsigned *)0, cfile);
04035 if (!expression_allocate (expr, MDL))
04036 log_fatal ("can't allocate expression");
04037 (*expr) -> op = expr_packet;
04038
04039 token = next_token (&val, (unsigned *)0, cfile);
04040 if (token != LPAREN)
04041 goto nolparen;
04042
04043 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
04044 cfile, lose))
04045 goto nonum;
04046
04047 token = next_token (&val, (unsigned *)0, cfile);
04048 if (token != COMMA)
04049 goto nocomma;
04050
04051 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
04052 cfile, lose))
04053 goto nonum;
04054
04055 token = next_token (&val, (unsigned *)0, cfile);
04056 if (token != RPAREN)
04057 goto norparen;
04058 break;
04059
04060 case STRING:
04061 skip_token(&val, &len, cfile);
04062 if (!make_const_data (expr, (const unsigned char *)val,
04063 len, 1, 1, MDL))
04064 log_fatal ("can't make constant string expression.");
04065 break;
04066
04067 case EXTRACT_INT:
04068 skip_token(&val, (unsigned *)0, cfile);
04069 token = next_token (&val, (unsigned *)0, cfile);
04070 if (token != LPAREN) {
04071 parse_warn (cfile, "left parenthesis expected.");
04072 *lose = 1;
04073 return 0;
04074 }
04075
04076 if (!expression_allocate (expr, MDL))
04077 log_fatal ("can't allocate expression");
04078
04079 if (!parse_data_expression (&(*expr) -> data.extract_int,
04080 cfile, lose)) {
04081 if (!*lose) {
04082 parse_warn (cfile,
04083 "expecting data expression.");
04084 skip_to_semi (cfile);
04085 *lose = 1;
04086 }
04087 expression_dereference (expr, MDL);
04088 return 0;
04089 }
04090
04091 token = next_token (&val, (unsigned *)0, cfile);
04092 if (token != COMMA) {
04093 parse_warn (cfile, "comma expected.");
04094 *lose = 1;
04095 expression_dereference (expr, MDL);
04096 return 0;
04097 }
04098
04099 token = next_token (&val, (unsigned *)0, cfile);
04100 if (token != NUMBER) {
04101 parse_warn (cfile, "number expected.");
04102 *lose = 1;
04103 expression_dereference (expr, MDL);
04104 return 0;
04105 }
04106 switch (atoi (val)) {
04107 case 8:
04108 (*expr) -> op = expr_extract_int8;
04109 break;
04110
04111 case 16:
04112 (*expr) -> op = expr_extract_int16;
04113 break;
04114
04115 case 32:
04116 (*expr) -> op = expr_extract_int32;
04117 break;
04118
04119 default:
04120 parse_warn (cfile,
04121 "unsupported integer size %d", atoi (val));
04122 *lose = 1;
04123 skip_to_semi (cfile);
04124 expression_dereference (expr, MDL);
04125 return 0;
04126 }
04127
04128 token = next_token (&val, (unsigned *)0, cfile);
04129 if (token != RPAREN) {
04130 parse_warn (cfile, "right parenthesis expected.");
04131 *lose = 1;
04132 expression_dereference (expr, MDL);
04133 return 0;
04134 }
04135 break;
04136
04137 case ENCODE_INT:
04138 skip_token(&val, (unsigned *)0, cfile);
04139 token = next_token (&val, (unsigned *)0, cfile);
04140 if (token != LPAREN) {
04141 parse_warn (cfile, "left parenthesis expected.");
04142 *lose = 1;
04143 return 0;
04144 }
04145
04146 if (!expression_allocate (expr, MDL))
04147 log_fatal ("can't allocate expression");
04148
04149 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
04150 cfile, lose)) {
04151 parse_warn (cfile, "expecting numeric expression.");
04152 skip_to_semi (cfile);
04153 *lose = 1;
04154 expression_dereference (expr, MDL);
04155 return 0;
04156 }
04157
04158 token = next_token (&val, (unsigned *)0, cfile);
04159 if (token != COMMA) {
04160 parse_warn (cfile, "comma expected.");
04161 *lose = 1;
04162 expression_dereference (expr, MDL);
04163 return 0;
04164 }
04165
04166 token = next_token (&val, (unsigned *)0, cfile);
04167 if (token != NUMBER) {
04168 parse_warn (cfile, "number expected.");
04169 *lose = 1;
04170 expression_dereference (expr, MDL);
04171 return 0;
04172 }
04173 switch (atoi (val)) {
04174 case 8:
04175 (*expr) -> op = expr_encode_int8;
04176 break;
04177
04178 case 16:
04179 (*expr) -> op = expr_encode_int16;
04180 break;
04181
04182 case 32:
04183 (*expr) -> op = expr_encode_int32;
04184 break;
04185
04186 default:
04187 parse_warn (cfile,
04188 "unsupported integer size %d", atoi (val));
04189 *lose = 1;
04190 skip_to_semi (cfile);
04191 expression_dereference (expr, MDL);
04192 return 0;
04193 }
04194
04195 token = next_token (&val, (unsigned *)0, cfile);
04196 if (token != RPAREN) {
04197 parse_warn (cfile, "right parenthesis expected.");
04198 *lose = 1;
04199 expression_dereference (expr, MDL);
04200 return 0;
04201 }
04202 break;
04203
04204 case NUMBER:
04205
04206
04207 if (context == context_numeric ||
04208 context == context_data_or_numeric) {
04209 skip_token(&val, (unsigned *)0, cfile);
04210 if (!expression_allocate (expr, MDL))
04211 log_fatal ("can't allocate expression");
04212 (*expr) -> op = expr_const_int;
04213 (*expr) -> data.const_int = atoi (val);
04214 break;
04215 }
04216
04217 case NUMBER_OR_NAME:
04218 if (!expression_allocate (expr, MDL))
04219 log_fatal ("can't allocate expression");
04220
04221 (*expr) -> op = expr_const_data;
04222 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
04223 expression_dereference (expr, MDL);
04224 return 0;
04225 }
04226 break;
04227
04228 case NS_FORMERR:
04229 known = FORMERR;
04230 goto ns_const;
04231 ns_const:
04232 skip_token(&val, (unsigned *)0, cfile);
04233 if (!expression_allocate (expr, MDL))
04234 log_fatal ("can't allocate expression");
04235 (*expr) -> op = expr_const_int;
04236 (*expr) -> data.const_int = known;
04237 break;
04238
04239 case NS_NOERROR:
04240 known = ISC_R_SUCCESS;
04241 goto ns_const;
04242
04243 case NS_NOTAUTH:
04244 known = DHCP_R_NOTAUTH;
04245 goto ns_const;
04246
04247 case NS_NOTIMP:
04248 known = ISC_R_NOTIMPLEMENTED;
04249 goto ns_const;
04250
04251 case NS_NOTZONE:
04252 known = DHCP_R_NOTZONE;
04253 goto ns_const;
04254
04255 case NS_NXDOMAIN:
04256 known = DHCP_R_NXDOMAIN;
04257 goto ns_const;
04258
04259 case NS_NXRRSET:
04260 known = DHCP_R_NXRRSET;
04261 goto ns_const;
04262
04263 case NS_REFUSED:
04264 known = DHCP_R_REFUSED;
04265 goto ns_const;
04266
04267 case NS_SERVFAIL:
04268 known = DHCP_R_SERVFAIL;
04269 goto ns_const;
04270
04271 case NS_YXDOMAIN:
04272 known = DHCP_R_YXDOMAIN;
04273 goto ns_const;
04274
04275 case NS_YXRRSET:
04276 known = DHCP_R_YXRRSET;
04277 goto ns_const;
04278
04279 case BOOTING:
04280 known = S_INIT;
04281 goto ns_const;
04282
04283 case REBOOT:
04284 known = S_REBOOTING;
04285 goto ns_const;
04286
04287 case SELECT:
04288 known = S_SELECTING;
04289 goto ns_const;
04290
04291 case REQUEST:
04292 known = S_REQUESTING;
04293 goto ns_const;
04294
04295 case BOUND:
04296 known = S_BOUND;
04297 goto ns_const;
04298
04299 case RENEW:
04300 known = S_RENEWING;
04301 goto ns_const;
04302
04303 case REBIND:
04304 known = S_REBINDING;
04305 goto ns_const;
04306
04307 case DEFINED:
04308 skip_token(&val, (unsigned *)0, cfile);
04309 token = next_token (&val, (unsigned *)0, cfile);
04310 if (token != LPAREN)
04311 goto nolparen;
04312
04313 token = next_token (&val, (unsigned *)0, cfile);
04314 if (token != NAME && token != NUMBER_OR_NAME) {
04315 parse_warn (cfile, "%s can't be a variable name", val);
04316 skip_to_semi (cfile);
04317 *lose = 1;
04318 return 0;
04319 }
04320
04321 if (!expression_allocate (expr, MDL))
04322 log_fatal ("can't allocate expression");
04323 (*expr) -> op = expr_variable_exists;
04324 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
04325 if (!(*expr)->data.variable)
04326 log_fatal ("can't allocate variable name");
04327 strcpy ((*expr) -> data.variable, val);
04328 token = next_token (&val, (unsigned *)0, cfile);
04329 if (token != RPAREN)
04330 goto norparen;
04331 break;
04332
04333
04334 case GETHOSTNAME:
04335 skip_token(&val, NULL, cfile);
04336 if (!expression_allocate(expr, MDL))
04337 log_fatal("can't allocate expression");
04338 (*expr)->op = expr_gethostname;
04339
04340 token = next_token(NULL, NULL, cfile);
04341 if (token != LPAREN)
04342 goto nolparen;
04343
04344 token = next_token(NULL, NULL, cfile);
04345 if (token != RPAREN)
04346 goto norparen;
04347 break;
04348
04349 case GETHOSTBYNAME:
04350 skip_token(&val, NULL, cfile);
04351 token = next_token(NULL, NULL, cfile);
04352 if (token != LPAREN)
04353 goto nolparen;
04354
04355
04356 token = next_token(&val, NULL, cfile);
04357 if (token != STRING) {
04358 parse_warn(cfile, "Expecting quoted literal: "
04359 "\"foo.example.com\"");
04360 skip_to_semi(cfile);
04361 *lose = 1;
04362 return 0;
04363 }
04364 if (!make_host_lookup(expr, val))
04365 log_fatal("Error creating gethostbyname() internal "
04366 "record. (%s:%d)", MDL);
04367
04368 token = next_token(NULL, NULL, cfile);
04369 if (token != RPAREN)
04370 goto norparen;
04371 break;
04372
04373 case V6RELAY:
04374 skip_token(&val, NULL, cfile);
04375 if (!expression_allocate (expr, MDL))
04376 log_fatal ("can't allocate expression");
04377 (*expr)->op = expr_v6relay;
04378
04379 token = next_token (&val, NULL, cfile);
04380 if (token != LPAREN)
04381 goto nolparen;
04382
04383 if (!parse_numeric_expression (&(*expr)->data.v6relay.relay,
04384 cfile, lose))
04385 goto nodata;
04386
04387 token = next_token (&val, NULL, cfile);
04388 if (token != COMMA)
04389 goto nocomma;
04390
04391 if (!parse_data_expression (&(*expr)->data.v6relay.roption,
04392 cfile, lose))
04393 goto nodata;
04394
04395 token = next_token (&val, NULL, cfile);
04396
04397 if (token != RPAREN)
04398 goto norparen;
04399 break;
04400
04401
04402 default:
04403 if (token != NAME && token != NUMBER_OR_NAME)
04404 return 0;
04405
04406 skip_token(&val, (unsigned *)0, cfile);
04407
04408
04409 cptr = dmalloc (strlen (val) + 1, MDL);
04410 if (!cptr)
04411 log_fatal ("can't allocate variable name");
04412 strcpy (cptr, val);
04413
04414
04415 token = peek_token (&val, (unsigned *)0, cfile);
04416 if (token != LPAREN) {
04417 if (!expression_allocate (expr, MDL))
04418 log_fatal ("can't allocate expression");
04419 (*expr) -> op = expr_variable_reference;
04420 (*expr) -> data.variable = cptr;
04421 break;
04422 }
04423
04424 skip_token(&val, (unsigned *)0, cfile);
04425 if (!expression_allocate (expr, MDL))
04426 log_fatal ("can't allocate expression");
04427 (*expr) -> op = expr_funcall;
04428 (*expr) -> data.funcall.name = cptr;
04429
04430
04431 ep = &(*expr) -> data.funcall.arglist;
04432 do {
04433 if (!expression_allocate (ep, MDL))
04434 log_fatal ("can't allocate expression");
04435 (*ep) -> op = expr_arg;
04436 if (!parse_expression (&(*ep) -> data.arg.val,
04437 cfile, lose, context_any,
04438 (struct expression **)0,
04439 expr_none)) {
04440 if (!*lose) {
04441 parse_warn (cfile,
04442 "expecting expression.");
04443 *lose = 1;
04444 }
04445 skip_to_semi (cfile);
04446 expression_dereference (expr, MDL);
04447 return 0;
04448 }
04449 ep = &((*ep) -> data.arg.next);
04450 token = next_token (&val, (unsigned *)0, cfile);
04451 } while (token == COMMA);
04452 if (token != RPAREN) {
04453 parse_warn (cfile, "Right parenthesis expected.");
04454 skip_to_semi (cfile);
04455 *lose = 1;
04456 expression_dereference (expr, MDL);
04457 return 0;
04458 }
04459 break;
04460 }
04461 return 1;
04462 }
04463
04464
04465
04466 int parse_expression (expr, cfile, lose, context, plhs, binop)
04467 struct expression **expr;
04468 struct parse *cfile;
04469 int *lose;
04470 enum expression_context context;
04471 struct expression **plhs;
04472 enum expr_op binop;
04473 {
04474 enum dhcp_token token;
04475 const char *val;
04476 struct expression *rhs = (struct expression *)0, *tmp;
04477 struct expression *lhs = (struct expression *)0;
04478 enum expr_op next_op;
04479 enum expression_context
04480 lhs_context = context_any,
04481 rhs_context = context_any;
04482
04483
04484 if (plhs) {
04485 expression_reference (&lhs, *plhs, MDL);
04486 expression_dereference (plhs, MDL);
04487 }
04488
04489 new_rhs:
04490 if (!parse_non_binary (&rhs, cfile, lose, context)) {
04491
04492
04493
04494 if (lhs) {
04495 if (!*lose) {
04496 parse_warn (cfile,
04497 "expecting right-hand side.");
04498 *lose = 1;
04499 skip_to_semi (cfile);
04500 }
04501 expression_dereference (&lhs, MDL);
04502 }
04503 return 0;
04504 }
04505
04506
04507
04508
04509
04510 token = peek_token (&val, (unsigned *)0, cfile);
04511 switch (token) {
04512 case BANG:
04513 skip_token(&val, (unsigned *)0, cfile);
04514 token = peek_token (&val, (unsigned *)0, cfile);
04515 if (token != EQUAL) {
04516 parse_warn (cfile, "! in boolean context without =");
04517 *lose = 1;
04518 skip_to_semi (cfile);
04519 if (lhs)
04520 expression_dereference (&lhs, MDL);
04521 return 0;
04522 }
04523 next_op = expr_not_equal;
04524 context = expression_context (rhs);
04525 break;
04526
04527 case EQUAL:
04528 next_op = expr_equal;
04529 context = expression_context (rhs);
04530 break;
04531
04532 case TILDE:
04533 #ifdef HAVE_REGEX_H
04534 skip_token(&val, NULL, cfile);
04535 token = peek_token(&val, NULL, cfile);
04536
04537 if (token == TILDE)
04538 next_op = expr_iregex_match;
04539 else if (token == EQUAL)
04540 next_op = expr_regex_match;
04541 else {
04542 parse_warn(cfile, "expecting ~= or ~~ operator");
04543 *lose = 1;
04544 skip_to_semi(cfile);
04545 if (lhs)
04546 expression_dereference(&lhs, MDL);
04547 return 0;
04548 }
04549
04550 context = expression_context(rhs);
04551 #else
04552 parse_warn(cfile, "No support for regex operator.");
04553 *lose = 1;
04554 skip_to_semi(cfile);
04555 if (lhs != NULL)
04556 expression_dereference(&lhs, MDL);
04557 return 0;
04558 #endif
04559 break;
04560
04561 case AND:
04562 next_op = expr_and;
04563 context = expression_context (rhs);
04564 break;
04565
04566 case OR:
04567 next_op = expr_or;
04568 context = expression_context (rhs);
04569 break;
04570
04571 case PLUS:
04572 next_op = expr_add;
04573 context = expression_context (rhs);
04574 break;
04575
04576 case MINUS:
04577 next_op = expr_subtract;
04578 context = expression_context (rhs);
04579 break;
04580
04581 case SLASH:
04582 next_op = expr_divide;
04583 context = expression_context (rhs);
04584 break;
04585
04586 case ASTERISK:
04587 next_op = expr_multiply;
04588 context = expression_context (rhs);
04589 break;
04590
04591 case PERCENT:
04592 next_op = expr_remainder;
04593 context = expression_context (rhs);
04594 break;
04595
04596 case AMPERSAND:
04597 next_op = expr_binary_and;
04598 context = expression_context (rhs);
04599 break;
04600
04601 case PIPE:
04602 next_op = expr_binary_or;
04603 context = expression_context (rhs);
04604 break;
04605
04606 case CARET:
04607 next_op = expr_binary_xor;
04608 context = expression_context (rhs);
04609 break;
04610
04611 default:
04612 next_op = expr_none;
04613 }
04614
04615
04616 if (!lhs) {
04617
04618
04619 if (next_op == expr_none) {
04620 *expr = rhs;
04621 return 1;
04622 }
04623 lhs = rhs;
04624 rhs = (struct expression *)0;
04625 binop = next_op;
04626 skip_token(&val, (unsigned *)0, cfile);
04627 goto new_rhs;
04628 }
04629
04630
04631
04632
04633
04634
04635 if (binop != expr_none && next_op != expr_none &&
04636 op_precedence (binop, next_op) < 0) {
04637
04638
04639
04640
04641 skip_token(&val, (unsigned *)0, cfile);
04642
04643
04644 tmp = rhs;
04645 rhs = (struct expression *)0;
04646 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
04647 &tmp, next_op)) {
04648 if (!*lose) {
04649 parse_warn (cfile,
04650 "expecting a subexpression");
04651 *lose = 1;
04652 }
04653 return 0;
04654 }
04655 next_op = expr_none;
04656 }
04657
04658 if (binop != expr_none) {
04659 rhs_context = expression_context(rhs);
04660 lhs_context = expression_context(lhs);
04661
04662 if ((rhs_context != context_any) && (lhs_context != context_any) &&
04663 (rhs_context != lhs_context)) {
04664 parse_warn (cfile, "illegal expression relating different types");
04665 skip_to_semi (cfile);
04666 expression_dereference (&rhs, MDL);
04667 expression_dereference (&lhs, MDL);
04668 *lose = 1;
04669 return 0;
04670 }
04671
04672 switch(binop) {
04673 case expr_not_equal:
04674 case expr_equal:
04675 if ((rhs_context != context_data_or_numeric) &&
04676 (rhs_context != context_data) &&
04677 (rhs_context != context_numeric) &&
04678 (rhs_context != context_any)) {
04679 parse_warn (cfile, "expecting data/numeric expression");
04680 skip_to_semi (cfile);
04681 expression_dereference (&rhs, MDL);
04682 *lose = 1;
04683 return 0;
04684 }
04685 break;
04686
04687 case expr_regex_match:
04688 #ifdef HAVE_REGEX_H
04689 if (expression_context(rhs) != context_data) {
04690 parse_warn(cfile, "expecting data expression");
04691 skip_to_semi(cfile);
04692 expression_dereference(&rhs, MDL);
04693 *lose = 1;
04694 return 0;
04695 }
04696 #else
04697
04698
04699
04700 log_fatal("Impossible condition at %s:%d.", MDL);
04701 #endif
04702 break;
04703
04704 case expr_and:
04705 case expr_or:
04706 if ((rhs_context != context_boolean) &&
04707 (rhs_context != context_any)) {
04708 parse_warn (cfile, "expecting boolean expressions");
04709 skip_to_semi (cfile);
04710 expression_dereference (&rhs, MDL);
04711 *lose = 1;
04712 return 0;
04713 }
04714 break;
04715
04716 case expr_add:
04717 case expr_subtract:
04718 case expr_divide:
04719 case expr_multiply:
04720 case expr_remainder:
04721 case expr_binary_and:
04722 case expr_binary_or:
04723 case expr_binary_xor:
04724 if ((rhs_context != context_numeric) &&
04725 (rhs_context != context_any)) {
04726 parse_warn (cfile, "expecting numeric expressions");
04727 skip_to_semi (cfile);
04728 expression_dereference (&rhs, MDL);
04729 *lose = 1;
04730 return 0;
04731 }
04732 break;
04733
04734 default:
04735 break;
04736 }
04737 }
04738
04739
04740
04741
04742 if (next_op == expr_none) {
04743 if (!expression_allocate (expr, MDL))
04744 log_fatal ("Can't allocate expression!");
04745
04746 (*expr) -> op = binop;
04747
04748
04749
04750 (*expr) -> data.equal [0] = lhs;
04751 (*expr) -> data.equal [1] = rhs;
04752 return 1;
04753 }
04754
04755
04756 skip_token(&val, (unsigned *)0, cfile);
04757
04758
04759 tmp = (struct expression *)0;
04760 if (!expression_allocate (&tmp, MDL))
04761 log_fatal ("No memory for equal precedence combination.");
04762
04763
04764 tmp -> data.equal [0] = lhs;
04765 tmp -> data.equal [1] = rhs;
04766 tmp -> op = binop;
04767
04768 lhs = tmp;
04769 tmp = (struct expression *)0;
04770 rhs = (struct expression *)0;
04771
04772
04773
04774
04775 if (next_op == expr_none) {
04776 *expr = lhs;
04777 return 1;
04778 }
04779
04780 binop = next_op;
04781 goto new_rhs;
04782 }
04783
04784
04785 int parse_option_data (expr, cfile, lookups, option)
04786 struct expression **expr;
04787 struct parse *cfile;
04788 int lookups;
04789 struct option *option;
04790 {
04791 const char *val;
04792 const char *fmt = NULL;
04793 struct expression *tmp;
04794 enum dhcp_token token;
04795
04796 do {
04797
04798
04799
04800
04801
04802 int uniform = 0;
04803
04804 and_again:
04805
04806
04807
04808 if ((fmt != NULL) && (fmt != option->format) && (*fmt == 'a'))
04809 fmt -= 1;
04810 else if ((fmt == NULL) || (*fmt == 'A'))
04811 fmt = option->format;
04812
04813
04814 if ((fmt[0] != 'Z') && (tolower((unsigned char)fmt[1]) == 'a'))
04815 uniform = 1;
04816
04817 do {
04818 if ((*fmt == 'A') || (*fmt == 'a'))
04819 break;
04820 if (*fmt == 'o') {
04821
04822 fmt++;
04823 continue;
04824 }
04825
04826 if (fmt[1] == 'o') {
04827
04828
04829
04830
04831
04832
04833
04834
04835 token = peek_token(&val, (unsigned *)0,
04836 cfile);
04837 if (token == SEMI) {
04838 fmt++;
04839 continue;
04840 }
04841 }
04842
04843 tmp = *expr;
04844 *expr = NULL;
04845
04846 if (!parse_option_token(expr, cfile, &fmt, tmp,
04847 uniform, lookups)) {
04848 if (fmt [1] != 'o') {
04849 if (tmp)
04850 expression_dereference (&tmp,
04851 MDL);
04852 return 0;
04853 }
04854 *expr = tmp;
04855 tmp = NULL;
04856 }
04857 if (tmp)
04858 expression_dereference (&tmp, MDL);
04859
04860 fmt++;
04861 } while (*fmt != '\0');
04862
04863 if ((*fmt == 'A') || (*fmt == 'a')) {
04864 token = peek_token (&val, (unsigned *)0, cfile);
04865
04866 if (token == COMMA) {
04867 skip_token(&val, (unsigned *)0, cfile);
04868 continue;
04869 }
04870
04871
04872 if ((*fmt == 'A') || (fmt[1] == '\0'))
04873 break;
04874
04875 if (*fmt == 'a') {
04876 fmt++;
04877 goto and_again;
04878 }
04879 }
04880 } while ((*fmt == 'A') || (*fmt == 'a'));
04881
04882 return 1;
04883 }
04884
04885
04886
04887
04888
04889
04890
04891
04892 int parse_option_statement (result, cfile, lookups, option, op)
04893 struct executable_statement **result;
04894 struct parse *cfile;
04895 int lookups;
04896 struct option *option;
04897 enum statement_op op;
04898 {
04899 const char *val;
04900 enum dhcp_token token;
04901 struct expression *expr = (struct expression *)0;
04902 int lose;
04903
04904 token = peek_token (&val, (unsigned *)0, cfile);
04905 if ((token == SEMI) && (option->format[0] != 'Z')) {
04906
04907
04908
04909
04910
04911
04912
04913 skip_token(&val, (unsigned *)0, cfile);
04914 } else if (token == EQUAL) {
04915
04916 skip_token(&val, (unsigned *)0, cfile);
04917
04918
04919 if (!parse_data_expression (&expr, cfile, &lose)) {
04920
04921
04922
04923 if (!lose) {
04924 parse_warn (cfile,
04925 "expecting a data expression.");
04926 skip_to_semi (cfile);
04927 }
04928 return 0;
04929 }
04930 } else {
04931 if (! parse_option_data(&expr, cfile, lookups, option))
04932 return 0;
04933 }
04934
04935 if (!parse_semi (cfile))
04936 return 0;
04937 if (!executable_statement_allocate (result, MDL))
04938 log_fatal ("no memory for option statement.");
04939
04940 (*result)->op = op;
04941 if (expr && !option_cache (&(*result)->data.option,
04942 NULL, expr, option, MDL))
04943 log_fatal ("no memory for option cache");
04944
04945 if (expr)
04946 expression_dereference (&expr, MDL);
04947
04948 return 1;
04949 }
04950
04951 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
04952 struct expression **rv;
04953 struct parse *cfile;
04954 const char **fmt;
04955 struct expression *expr;
04956 int uniform;
04957 int lookups;
04958 {
04959 const char *val;
04960 enum dhcp_token token;
04961 struct expression *t = (struct expression *)0;
04962 unsigned char buf [4];
04963 unsigned len;
04964 struct iaddr addr;
04965 int compress;
04966 isc_boolean_t freeval = ISC_FALSE;
04967 const char *f, *g;
04968 struct enumeration_value *e;
04969
04970 switch (**fmt) {
04971 case 'U':
04972 token = next_token (&val, &len, cfile);
04973 if (!is_identifier (token)) {
04974 if ((*fmt) [1] != 'o') {
04975 parse_warn (cfile, "expecting identifier.");
04976 if (token != SEMI)
04977 skip_to_semi (cfile);
04978 }
04979 return 0;
04980 }
04981 if (!make_const_data (&t, (const unsigned char *)val,
04982 len, 1, 1, MDL))
04983 log_fatal ("No memory for %s", val);
04984 break;
04985
04986 case 'E':
04987 g = strchr (*fmt, '.');
04988 if (!g) {
04989 parse_warn (cfile,
04990 "malformed encapsulation format (bug!)");
04991 skip_to_semi (cfile);
04992 return 0;
04993 }
04994 *fmt = g;
04995
04996
04997 case 'X':
04998 token = peek_token (&val, (unsigned *)0, cfile);
04999 if (token == NUMBER_OR_NAME || token == NUMBER) {
05000 if (!expression_allocate (&t, MDL))
05001 return 0;
05002 if (!parse_cshl (&t -> data.const_data, cfile)) {
05003 expression_dereference (&t, MDL);
05004 return 0;
05005 }
05006 t -> op = expr_const_data;
05007 } else {
05008 token = next_token (&val, &len, cfile);
05009
05010 if(token == STRING) {
05011 if (!make_const_data (&t,
05012 (const unsigned char *)val,
05013 len, 1, 1, MDL))
05014 log_fatal ("No memory for \"%s\"", val);
05015 } else {
05016 if ((*fmt) [1] != 'o') {
05017 parse_warn (cfile, "expecting string "
05018 "or hexadecimal data.");
05019 skip_to_semi (cfile);
05020 }
05021 return 0;
05022 }
05023 }
05024 break;
05025
05026 case 'D':
05027 if ((*fmt)[1] == 'c') {
05028 compress = 1;
05029
05030 (*fmt)++;
05031 } else
05032 compress = 0;
05033
05034 t = parse_domain_list(cfile, compress);
05035
05036 if (!t) {
05037 if ((*fmt)[1] != 'o')
05038 skip_to_semi(cfile);
05039 return 0;
05040 }
05041
05042 break;
05043
05044 case 'd':
05045 val = parse_host_name (cfile);
05046 if (!val) {
05047 parse_warn (cfile, "not a valid domain name.");
05048 skip_to_semi (cfile);
05049 return 0;
05050 }
05051 len = strlen (val);
05052 freeval = ISC_TRUE;
05053 goto make_string;
05054
05055 case 't':
05056 token = next_token (&val, &len, cfile);
05057 if (token != STRING && !is_identifier (token)) {
05058 if ((*fmt) [1] != 'o') {
05059 parse_warn (cfile, "expecting string.");
05060 if (token != SEMI)
05061 skip_to_semi (cfile);
05062 }
05063 return 0;
05064 }
05065 make_string:
05066 if (!make_const_data (&t, (const unsigned char *)val,
05067 len, 1, 1, MDL))
05068 log_fatal ("No memory for concatenation");
05069 if (freeval == ISC_TRUE) {
05070 dfree((char *)val, MDL);
05071 freeval = ISC_FALSE;
05072 POST(freeval);
05073 }
05074 break;
05075
05076 case 'N':
05077 f = (*fmt) + 1;
05078 g = strchr (*fmt, '.');
05079 if (!g) {
05080 parse_warn (cfile, "malformed %s (bug!)",
05081 "enumeration format");
05082 foo:
05083 skip_to_semi (cfile);
05084 return 0;
05085 }
05086 *fmt = g;
05087 token = next_token (&val, (unsigned *)0, cfile);
05088 if (!is_identifier (token)) {
05089 parse_warn (cfile,
05090 "identifier expected");
05091 goto foo;
05092 }
05093 e = find_enumeration_value (f, (*fmt) - f, &len, val);
05094 if (!e) {
05095 parse_warn (cfile, "unknown value");
05096 goto foo;
05097 }
05098 if (!make_const_data (&t, &e -> value, len, 0, 1, MDL))
05099 return 0;
05100 break;
05101
05102 case 'I':
05103 if (lookups) {
05104 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
05105 return 0;
05106 } else {
05107 if (!parse_ip_addr (cfile, &addr))
05108 return 0;
05109 if (!make_const_data (&t, addr.iabuf, addr.len,
05110 0, 1, MDL))
05111 return 0;
05112 }
05113 break;
05114
05115 case 'R':
05116 if (!parse_destination_descriptor (cfile, &addr)) {
05117 return 0;
05118 }
05119 if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1, MDL)) {
05120 return 0;
05121 }
05122 break;
05123
05124 case '6':
05125 if (!parse_ip6_addr(cfile, &addr)) {
05126 return 0;
05127 }
05128 if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) {
05129 return 0;
05130 }
05131 break;
05132
05133 case 'T':
05134 token = next_token (&val, (unsigned *)0, cfile);
05135 if (token != INFINITE)
05136 goto check_number;
05137 putLong (buf, -1);
05138 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
05139 return 0;
05140 break;
05141
05142 case 'L':
05143 case 'l':
05144 token = next_token (&val, (unsigned *)0, cfile);
05145 check_number:
05146 if ((token != NUMBER) && (token != NUMBER_OR_NAME)) {
05147 need_number:
05148 if ((*fmt) [1] != 'o') {
05149 parse_warn (cfile, "expecting number.");
05150 if (token != SEMI)
05151 skip_to_semi (cfile);
05152 }
05153 return 0;
05154 }
05155 convert_num (cfile, buf, val, 0, 32);
05156 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
05157 return 0;
05158 break;
05159
05160 case 's':
05161 case 'S':
05162 token = next_token (&val, (unsigned *)0, cfile);
05163 if ((token != NUMBER) && (token != NUMBER_OR_NAME))
05164 goto need_number;
05165 convert_num (cfile, buf, val, 0, 16);
05166 if (!make_const_data (&t, buf, 2, 0, 1, MDL))
05167 return 0;
05168 break;
05169
05170 case 'b':
05171 case 'B':
05172 token = next_token (&val, (unsigned *)0, cfile);
05173 if ((token != NUMBER) && (token != NUMBER_OR_NAME))
05174 goto need_number;
05175 convert_num (cfile, buf, val, 0, 8);
05176 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
05177 return 0;
05178 break;
05179
05180 case 'f':
05181 token = next_token (&val, (unsigned *)0, cfile);
05182 if (!is_identifier (token)) {
05183 if ((*fmt) [1] != 'o')
05184 parse_warn (cfile, "expecting identifier.");
05185 bad_flag:
05186 if ((*fmt) [1] != 'o') {
05187 if (token != SEMI)
05188 skip_to_semi (cfile);
05189 }
05190 return 0;
05191 }
05192 if (!strcasecmp (val, "true")
05193 || !strcasecmp (val, "on"))
05194 buf [0] = 1;
05195 else if (!strcasecmp (val, "false")
05196 || !strcasecmp (val, "off"))
05197 buf [0] = 0;
05198 else if (!strcasecmp (val, "ignore"))
05199 buf [0] = 2;
05200 else {
05201 if ((*fmt) [1] != 'o')
05202 parse_warn (cfile, "expecting boolean.");
05203 goto bad_flag;
05204 }
05205 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
05206 return 0;
05207 break;
05208
05209 case 'Z':
05210 token = peek_token (&val, (unsigned *)0, cfile);
05211 if (token != SEMI) {
05212 parse_warn(cfile, "semicolon expected.");
05213 skip_to_semi(cfile);
05214 }
05215 buf[0] = '\0';
05216 if (!make_const_data(&t,
05217 buf,
05218 0,
05219 0,
05220 1,
05221 MDL))
05222 return 0;
05223 break;
05224
05225 default:
05226 parse_warn (cfile, "Bad format '%c' in parse_option_token.",
05227 **fmt);
05228 skip_to_semi (cfile);
05229 return 0;
05230 }
05231 if (expr) {
05232 if (!make_concat (rv, expr, t))
05233 return 0;
05234 } else
05235 expression_reference (rv, t, MDL);
05236 expression_dereference (&t, MDL);
05237 return 1;
05238 }
05239
05240 int parse_option_decl (oc, cfile)
05241 struct option_cache **oc;
05242 struct parse *cfile;
05243 {
05244 const char *val;
05245 int token;
05246 u_int8_t buf [4];
05247 u_int8_t hunkbuf [1024];
05248 unsigned hunkix = 0;
05249 const char *fmt, *f;
05250 struct option *option=NULL;
05251 struct iaddr ip_addr;
05252 u_int8_t *dp;
05253 const u_int8_t *cdp;
05254 unsigned len;
05255 int nul_term = 0;
05256 struct buffer *bp;
05257 int known = 0;
05258 int compress;
05259 struct expression *express = NULL;
05260 struct enumeration_value *e;
05261 isc_result_t status;
05262
05263 status = parse_option_name (cfile, 0, &known, &option);
05264 if (status != ISC_R_SUCCESS || option == NULL)
05265 return 0;
05266
05267 fmt = option->format;
05268
05269
05270 do {
05271 for (; *fmt; fmt++) {
05272 if (*fmt == 'A') {
05273
05274
05275
05276 fmt = option->format;
05277 break;
05278 }
05279
05280 if (*fmt == 'a') {
05281
05282
05283
05284 fmt--;
05285 break;
05286 }
05287 if (*fmt == 'o' && fmt != option -> format)
05288 continue;
05289 switch (*fmt) {
05290 case 'E':
05291 fmt = strchr (fmt, '.');
05292 if (!fmt) {
05293 parse_warn (cfile,
05294 "malformed %s (bug!)",
05295 "encapsulation format");
05296 goto parse_exit;
05297 }
05298
05299
05300 case 'X':
05301 len = parse_X (cfile, &hunkbuf [hunkix],
05302 sizeof hunkbuf - hunkix);
05303 hunkix += len;
05304 break;
05305
05306 case 't':
05307 token = peek_token (&val,
05308 &len, cfile);
05309 if (token == SEMI && fmt[1] == 'o') {
05310 fmt++;
05311 break;
05312 }
05313 token = next_token (&val,
05314 &len, cfile);
05315 if (token != STRING) {
05316 parse_warn (cfile,
05317 "expecting string.");
05318 goto parse_exit;
05319 }
05320 if (hunkix + len + 1 > sizeof hunkbuf) {
05321 parse_warn (cfile,
05322 "option data buffer %s",
05323 "overflow");
05324 goto parse_exit;
05325 }
05326 memcpy (&hunkbuf [hunkix], val, len + 1);
05327 nul_term = 1;
05328 hunkix += len;
05329 break;
05330
05331 case 'D':
05332 if (fmt[1] == 'c') {
05333 compress = 1;
05334 fmt++;
05335 } else
05336 compress = 0;
05337
05338 express = parse_domain_list(cfile, compress);
05339
05340 if (express == NULL)
05341 goto exit;
05342
05343 if (express->op != expr_const_data) {
05344 parse_warn(cfile, "unexpected "
05345 "expression");
05346 goto parse_exit;
05347 }
05348
05349 len = express->data.const_data.len;
05350 cdp = express->data.const_data.data;
05351
05352 if ((hunkix + len) > sizeof(hunkbuf)) {
05353 parse_warn(cfile, "option data buffer "
05354 "overflow");
05355 goto parse_exit;
05356 }
05357 memcpy(&hunkbuf[hunkix], cdp, len);
05358 hunkix += len;
05359
05360 expression_dereference(&express, MDL);
05361 break;
05362
05363 case 'N':
05364 f = fmt + 1;
05365 fmt = strchr (fmt, '.');
05366 if (!fmt) {
05367 parse_warn (cfile,
05368 "malformed %s (bug!)",
05369 "enumeration format");
05370 goto parse_exit;
05371 }
05372 token = next_token (&val,
05373 (unsigned *)0, cfile);
05374 if (!is_identifier (token)) {
05375 parse_warn (cfile,
05376 "identifier expected");
05377 goto parse_exit;
05378 }
05379 e = find_enumeration_value (f, fmt - f,
05380 &len, val);
05381 if (!e) {
05382 parse_warn (cfile,
05383 "unknown value");
05384 goto parse_exit;
05385 }
05386 dp = &e -> value;
05387 goto alloc;
05388
05389 case '6':
05390 if (!parse_ip6_addr(cfile, &ip_addr))
05391 goto exit;
05392 len = ip_addr.len;
05393 dp = ip_addr.iabuf;
05394 goto alloc;
05395
05396 case 'I':
05397 if (!parse_ip_addr (cfile, &ip_addr))
05398 goto exit;
05399 len = ip_addr.len;
05400 dp = ip_addr.iabuf;
05401 goto alloc;
05402
05403 case 'R':
05404 if (!parse_destination_descriptor (cfile, &ip_addr))
05405 goto exit;
05406 len = ip_addr.len;
05407 dp = ip_addr.iabuf;
05408
05409 alloc:
05410 if (hunkix + len > sizeof hunkbuf) {
05411 parse_warn (cfile,
05412 "option data buffer %s",
05413 "overflow");
05414 goto parse_exit;
05415 }
05416 memcpy (&hunkbuf [hunkix], dp, len);
05417 hunkix += len;
05418 break;
05419
05420 case 'L':
05421 case 'l':
05422 token = next_token (&val,
05423 (unsigned *)0, cfile);
05424 if ((token != NUMBER) &&
05425 (token != NUMBER_OR_NAME)) {
05426 need_number:
05427 parse_warn (cfile,
05428 "expecting number.");
05429 if (token != SEMI)
05430 goto parse_exit;
05431 else
05432 goto exit;
05433 }
05434 convert_num (cfile, buf, val, 0, 32);
05435 len = 4;
05436 dp = buf;
05437 goto alloc;
05438
05439 case 's':
05440 case 'S':
05441 token = next_token (&val,
05442 (unsigned *)0, cfile);
05443 if ((token != NUMBER) &&
05444 (token != NUMBER_OR_NAME))
05445 goto need_number;
05446 convert_num (cfile, buf, val, 0, 16);
05447 len = 2;
05448 dp = buf;
05449 goto alloc;
05450
05451 case 'b':
05452 case 'B':
05453 token = next_token (&val,
05454 (unsigned *)0, cfile);
05455 if ((token != NUMBER) &&
05456 (token != NUMBER_OR_NAME))
05457 goto need_number;
05458 convert_num (cfile, buf, val, 0, 8);
05459 len = 1;
05460 dp = buf;
05461 goto alloc;
05462
05463 case 'f':
05464 token = next_token (&val,
05465 (unsigned *)0, cfile);
05466 if (!is_identifier (token)) {
05467 parse_warn (cfile,
05468 "expecting identifier.");
05469 bad_flag:
05470 if (token != SEMI)
05471 goto parse_exit;
05472 else
05473 goto exit;
05474 }
05475 if (!strcasecmp (val, "true")
05476 || !strcasecmp (val, "on"))
05477 buf [0] = 1;
05478 else if (!strcasecmp (val, "false")
05479 || !strcasecmp (val, "off"))
05480 buf [0] = 0;
05481 else {
05482 parse_warn (cfile,
05483 "expecting boolean.");
05484 goto bad_flag;
05485 }
05486 len = 1;
05487 dp = buf;
05488 goto alloc;
05489
05490 case 'Z':
05491 token = peek_token(&val, (unsigned *)0, cfile);
05492 if (token != SEMI) {
05493 parse_warn(cfile,
05494 "semicolon expected.");
05495 goto parse_exit;
05496 }
05497 len = 0;
05498 buf[0] = '\0';
05499 break;
05500
05501 default:
05502 log_error ("parse_option_param: Bad format %c",
05503 *fmt);
05504 goto parse_exit;
05505 }
05506 }
05507 token = next_token (&val, (unsigned *)0, cfile);
05508 } while (*fmt && token == COMMA);
05509
05510 if (token != SEMI) {
05511 parse_warn (cfile, "semicolon expected.");
05512 goto parse_exit;
05513 }
05514
05515 bp = (struct buffer *)0;
05516 if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
05517 log_fatal ("no memory to store option declaration.");
05518 memcpy (bp -> data, hunkbuf, hunkix + nul_term);
05519
05520 if (!option_cache_allocate (oc, MDL))
05521 log_fatal ("out of memory allocating option cache.");
05522
05523 (*oc) -> data.buffer = bp;
05524 (*oc) -> data.data = &bp -> data [0];
05525 (*oc) -> data.terminated = nul_term;
05526 (*oc) -> data.len = hunkix;
05527 option_reference(&(*oc)->option, option, MDL);
05528 option_dereference(&option, MDL);
05529 return 1;
05530
05531 parse_exit:
05532 if (express != NULL)
05533 expression_dereference(&express, MDL);
05534 skip_to_semi (cfile);
05535 exit:
05536 option_dereference(&option, MDL);
05537
05538 return 0;
05539 }
05540
05541
05542
05543 int parse_X (cfile, buf, max)
05544 struct parse *cfile;
05545 u_int8_t *buf;
05546 unsigned max;
05547 {
05548 int token;
05549 const char *val;
05550 unsigned len;
05551
05552 token = peek_token (&val, (unsigned *)0, cfile);
05553 if (token == NUMBER_OR_NAME || token == NUMBER) {
05554 len = 0;
05555 do {
05556 token = next_token (&val, (unsigned *)0, cfile);
05557 if (token != NUMBER && token != NUMBER_OR_NAME) {
05558 parse_warn (cfile,
05559 "expecting hexadecimal constant.");
05560 skip_to_semi (cfile);
05561 return 0;
05562 }
05563 convert_num (cfile, &buf [len], val, 16, 8);
05564 if (len++ > max) {
05565 parse_warn (cfile,
05566 "hexadecimal constant too long.");
05567 skip_to_semi (cfile);
05568 return 0;
05569 }
05570 token = peek_token (&val, (unsigned *)0, cfile);
05571 if (token == COLON)
05572 token = next_token (&val,
05573 (unsigned *)0, cfile);
05574 } while (token == COLON);
05575 val = (char *)buf;
05576 } else if (token == STRING) {
05577 skip_token(&val, &len, cfile);
05578 if (len + 1 > max) {
05579 parse_warn (cfile, "string constant too long.");
05580 skip_to_semi (cfile);
05581 return 0;
05582 }
05583 memcpy (buf, val, len + 1);
05584 } else {
05585 parse_warn (cfile, "expecting string or hexadecimal data");
05586 skip_to_semi (cfile);
05587 return 0;
05588 }
05589 return len;
05590 }
05591
05592 int parse_warn (struct parse *cfile, const char *fmt, ...)
05593 {
05594 va_list list;
05595 char lexbuf [256];
05596 char mbuf [1024];
05597 char fbuf [1024];
05598 unsigned i, lix;
05599
05600 do_percentm (mbuf, fmt);
05601
05602
05603
05604 snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
05605 cfile -> tlname, cfile -> lexline, mbuf);
05606
05607 va_start (list, fmt);
05608 vsnprintf (mbuf, sizeof mbuf, fbuf, list);
05609 va_end (list);
05610
05611 lix = 0;
05612 for (i = 0;
05613 cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
05614 if (lix < (sizeof lexbuf) - 1)
05615 lexbuf [lix++] = ' ';
05616 if (cfile -> token_line [i] == '\t') {
05617 for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
05618 lexbuf [lix] = ' ';
05619 }
05620 }
05621 lexbuf [lix] = 0;
05622
05623 #ifndef DEBUG
05624 syslog (log_priority | LOG_ERR, "%s", mbuf);
05625 syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
05626 if (cfile -> lexchar < 81)
05627 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
05628 #endif
05629
05630 if (log_perror) {
05631 IGNORE_RET (write (STDERR_FILENO, mbuf, strlen (mbuf)));
05632 IGNORE_RET (write (STDERR_FILENO, "\n", 1));
05633 IGNORE_RET (write (STDERR_FILENO, cfile -> token_line,
05634 strlen (cfile -> token_line)));
05635 IGNORE_RET (write (STDERR_FILENO, "\n", 1));
05636 if (cfile -> lexchar < 81)
05637 IGNORE_RET (write (STDERR_FILENO, lexbuf, lix));
05638 IGNORE_RET (write (STDERR_FILENO, "^\n", 2));
05639 }
05640
05641 cfile -> warnings_occurred = 1;
05642
05643 return 0;
05644 }
05645
05646 struct expression *
05647 parse_domain_list(struct parse *cfile, int compress)
05648 {
05649 const char *val;
05650 enum dhcp_token token = SEMI;
05651 struct expression *t = NULL;
05652 unsigned len, clen = 0;
05653 int result;
05654 unsigned char compbuf[256 * NS_MAXCDNAME];
05655 const unsigned char *dnptrs[256], **lastdnptr;
05656
05657 memset(compbuf, 0, sizeof(compbuf));
05658 memset(dnptrs, 0, sizeof(dnptrs));
05659 dnptrs[0] = compbuf;
05660 lastdnptr = &dnptrs[255];
05661
05662 do {
05663
05664 if (token == COMMA)
05665 skip_token(&val, NULL, cfile);
05666
05667
05668 token = next_token(&val, &len, cfile);
05669
05670 if (token != STRING) {
05671 parse_warn(cfile, "Expecting a domain string.");
05672 return NULL;
05673 }
05674
05675
05676
05677
05678 if (compress) {
05679 result = MRns_name_compress(val, compbuf + clen,
05680 sizeof(compbuf) - clen,
05681 dnptrs, lastdnptr);
05682
05683 if (result < 0) {
05684 parse_warn(cfile, "Error compressing domain "
05685 "list: %m");
05686 return NULL;
05687 }
05688
05689 clen += result;
05690 } else {
05691 result = MRns_name_pton(val, compbuf + clen,
05692 sizeof(compbuf) - clen);
05693
05694
05695
05696
05697
05698 if (result < 0) {
05699 parse_warn(cfile, "Error assembling domain "
05700 "list: %m");
05701 return NULL;
05702 }
05703
05704
05705
05706
05707
05708 while (compbuf[clen] != 0)
05709 clen += compbuf[clen] + 1;
05710
05711
05712 clen++;
05713 }
05714
05715 if (clen > sizeof(compbuf))
05716 log_fatal("Impossible error at %s:%d", MDL);
05717
05718 token = peek_token(&val, NULL, cfile);
05719 } while (token == COMMA);
05720
05721 if (!make_const_data(&t, compbuf, clen, 1, 1, MDL))
05722 log_fatal("No memory for domain list object.");
05723
05724 return t;
05725 }
05726