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