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