Merge from vendor branch LIBARCHIVE:
[dragonfly/vkernel-mp.git] / contrib / dhcp-3.0 / common / parse.c
blobe29fdcff03f3ba044cb49b4287d6fa0832be839b
1 /* parse.c
3 Common parser code for dhcpd and dhclient. */
5 /*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
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.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: parse.c,v 1.104.2.20 2004/09/30 20:38:31 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
42 /* Enumerations can be specified in option formats, and are used for
43 parsing, so we define the routines that manage them here. */
45 struct enumeration *enumerations;
47 void add_enumeration (struct enumeration *enumeration)
49 enumeration -> next = enumerations;
50 enumerations = enumeration;
53 struct enumeration *find_enumeration (const char *name, int length)
55 struct enumeration *e;
57 for (e = enumerations; e; e = e -> next)
58 if (strlen (e -> name) == length &&
59 !memcmp (e -> name, name, (unsigned)length))
60 return e;
61 return (struct enumeration *)0;
64 struct enumeration_value *find_enumeration_value (const char *name,
65 int length,
66 const char *value)
68 struct enumeration *e;
69 int i;
71 e = find_enumeration (name, length);
72 if (e) {
73 for (i = 0; e -> values [i].name; i++) {
74 if (!strcmp (value, e -> values [i].name))
75 return &e -> values [i];
78 return (struct enumeration_value *)0;
81 /* Skip to the semicolon ending the current statement. If we encounter
82 braces, the matching closing brace terminates the statement. If we
83 encounter a right brace but haven't encountered a left brace, return
84 leaving the brace in the token buffer for the caller. If we see a
85 semicolon and haven't seen a left brace, return. This lets us skip
86 over:
88 statement;
89 statement foo bar { }
90 statement foo bar { statement { } }
91 statement}
93 ...et cetera. */
95 void skip_to_semi (cfile)
96 struct parse *cfile;
98 skip_to_rbrace (cfile, 0);
101 void skip_to_rbrace (cfile, brace_count)
102 struct parse *cfile;
103 int brace_count;
105 enum dhcp_token token;
106 const char *val;
108 #if defined (DEBUG_TOKEN)
109 log_error ("skip_to_rbrace: %d\n", brace_count);
110 #endif
111 do {
112 token = peek_token (&val, (unsigned *)0, cfile);
113 if (token == RBRACE) {
114 token = next_token (&val, (unsigned *)0, cfile);
115 if (brace_count) {
116 if (!--brace_count)
117 return;
118 } else
119 return;
120 } else if (token == LBRACE) {
121 brace_count++;
122 } else if (token == SEMI && !brace_count) {
123 token = next_token (&val, (unsigned *)0, cfile);
124 return;
125 } else if (token == EOL) {
126 /* EOL only happens when parsing /etc/resolv.conf,
127 and we treat it like a semicolon because the
128 resolv.conf file is line-oriented. */
129 token = next_token (&val, (unsigned *)0, cfile);
130 return;
132 token = next_token (&val, (unsigned *)0, cfile);
133 } while (token != END_OF_FILE);
136 int parse_semi (cfile)
137 struct parse *cfile;
139 enum dhcp_token token;
140 const char *val;
142 token = next_token (&val, (unsigned *)0, cfile);
143 if (token != SEMI) {
144 parse_warn (cfile, "semicolon expected.");
145 skip_to_semi (cfile);
146 return 0;
148 return 1;
151 /* string-parameter :== STRING SEMI */
153 int parse_string (cfile, sptr, lptr)
154 struct parse *cfile;
155 char **sptr;
156 unsigned *lptr;
158 const char *val;
159 enum dhcp_token token;
160 char *s;
161 unsigned len;
163 token = next_token (&val, &len, cfile);
164 if (token != STRING) {
165 parse_warn (cfile, "expecting a string");
166 skip_to_semi (cfile);
167 return 0;
169 s = (char *)dmalloc (len + 1, MDL);
170 if (!s)
171 log_fatal ("no memory for string %s.", val);
172 memcpy (s, val, len + 1);
174 if (!parse_semi (cfile)) {
175 dfree (s, MDL);
176 return 0;
178 if (sptr)
179 *sptr = s;
180 else
181 dfree (s, MDL);
182 if (lptr)
183 *lptr = len;
184 return 1;
188 * hostname :== IDENTIFIER
189 * | IDENTIFIER DOT
190 * | hostname DOT IDENTIFIER
193 char *parse_host_name (cfile)
194 struct parse *cfile;
196 const char *val;
197 enum dhcp_token token;
198 unsigned len = 0;
199 char *s;
200 char *t;
201 pair c = (pair)0;
202 int ltid = 0;
204 /* Read a dotted hostname... */
205 do {
206 /* Read a token, which should be an identifier. */
207 token = peek_token (&val, (unsigned *)0, cfile);
208 if (!is_identifier (token) && token != NUMBER)
209 break;
210 token = next_token (&val, (unsigned *)0, cfile);
212 /* Store this identifier... */
213 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
214 log_fatal ("can't allocate temp space for hostname.");
215 strcpy (s, val);
216 c = cons ((caddr_t)s, c);
217 len += strlen (s) + 1;
218 /* Look for a dot; if it's there, keep going, otherwise
219 we're done. */
220 token = peek_token (&val, (unsigned *)0, cfile);
221 if (token == DOT) {
222 token = next_token (&val, (unsigned *)0, cfile);
223 ltid = 1;
224 } else
225 ltid = 0;
226 } while (token == DOT);
228 /* Should be at least one token. */
229 if (!len)
230 return (char *)0;
232 /* Assemble the hostname together into a string. */
233 if (!(s = (char *)dmalloc (len + ltid, MDL)))
234 log_fatal ("can't allocate space for hostname.");
235 t = s + len + ltid;
236 *--t = 0;
237 if (ltid)
238 *--t = '.';
239 while (c) {
240 pair cdr = c -> cdr;
241 unsigned l = strlen ((char *)(c -> car));
242 t -= l;
243 memcpy (t, (char *)(c -> car), l);
244 /* Free up temp space. */
245 dfree (c -> car, MDL);
246 dfree (c, MDL);
247 c = cdr;
248 if (t != s)
249 *--t = '.';
251 return s;
254 /* ip-addr-or-hostname :== ip-address | hostname
255 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
257 Parse an ip address or a hostname. If uniform is zero, put in
258 an expr_substring node to limit hostnames that evaluate to more
259 than one IP address. */
261 int parse_ip_addr_or_hostname (expr, cfile, uniform)
262 struct expression **expr;
263 struct parse *cfile;
264 int uniform;
266 const char *val;
267 enum dhcp_token token;
268 unsigned char addr [4];
269 unsigned len = sizeof addr;
270 char *name;
271 struct expression *x = (struct expression *)0;
273 token = peek_token (&val, (unsigned *)0, cfile);
274 if (is_identifier (token)) {
275 name = parse_host_name (cfile);
276 if (!name)
277 return 0;
278 if (!make_host_lookup (expr, name)) {
279 dfree(name, MDL);
280 return 0;
282 dfree(name, MDL);
283 if (!uniform) {
284 if (!make_limit (&x, *expr, 4))
285 return 0;
286 expression_dereference (expr, MDL);
287 *expr = x;
289 } else if (token == NUMBER) {
290 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
291 return 0;
292 return make_const_data (expr, addr, len, 0, 1, MDL);
293 } else {
294 if (token != RBRACE && token != LBRACE)
295 token = next_token (&val, (unsigned *)0, cfile);
296 parse_warn (cfile, "%s (%d): expecting IP address or hostname",
297 val, token);
298 if (token != SEMI)
299 skip_to_semi (cfile);
300 return 0;
303 return 1;
307 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
310 int parse_ip_addr (cfile, addr)
311 struct parse *cfile;
312 struct iaddr *addr;
314 const char *val;
315 enum dhcp_token token;
317 addr -> len = 4;
318 if (parse_numeric_aggregate (cfile, addr -> iabuf,
319 &addr -> len, DOT, 10, 8))
320 return 1;
321 return 0;
325 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
326 * hardware-type :== ETHERNET | TOKEN_RING | FDDI
329 void parse_hardware_param (cfile, hardware)
330 struct parse *cfile;
331 struct hardware *hardware;
333 const char *val;
334 enum dhcp_token token;
335 unsigned hlen;
336 unsigned char *t;
338 token = next_token (&val, (unsigned *)0, cfile);
339 switch (token) {
340 case ETHERNET:
341 hardware -> hbuf [0] = HTYPE_ETHER;
342 break;
343 case TOKEN_RING:
344 hardware -> hbuf [0] = HTYPE_IEEE802;
345 break;
346 case FDDI:
347 hardware -> hbuf [0] = HTYPE_FDDI;
348 break;
349 default:
350 if (!strncmp (val, "unknown-", 8)) {
351 hardware -> hbuf [0] = atoi (&val [8]);
352 } else {
353 parse_warn (cfile,
354 "expecting a network hardware type");
355 skip_to_semi (cfile);
357 return;
361 /* Parse the hardware address information. Technically,
362 it would make a lot of sense to restrict the length of the
363 data we'll accept here to the length of a particular hardware
364 address type. Unfortunately, there are some broken clients
365 out there that put bogus data in the chaddr buffer, and we accept
366 that data in the lease file rather than simply failing on such
367 clients. Yuck. */
368 hlen = 0;
369 token = peek_token (&val, (unsigned *)0, cfile);
370 if (token == SEMI) {
371 hardware -> hlen = 1;
372 goto out;
374 t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen,
375 COLON, 16, 8);
376 if (!t) {
377 hardware -> hlen = 1;
378 return;
380 if (hlen + 1 > sizeof hardware -> hbuf) {
381 dfree (t, MDL);
382 parse_warn (cfile, "hardware address too long");
383 } else {
384 hardware -> hlen = hlen + 1;
385 memcpy ((unsigned char *)&hardware -> hbuf [1], t, hlen);
386 if (hlen + 1 < sizeof hardware -> hbuf)
387 memset (&hardware -> hbuf [hlen + 1], 0,
388 (sizeof hardware -> hbuf) - hlen - 1);
389 dfree (t, MDL);
392 out:
393 token = next_token (&val, (unsigned *)0, cfile);
394 if (token != SEMI) {
395 parse_warn (cfile, "expecting semicolon.");
396 skip_to_semi (cfile);
400 /* lease-time :== NUMBER SEMI */
402 void parse_lease_time (cfile, timep)
403 struct parse *cfile;
404 TIME *timep;
406 const char *val;
407 enum dhcp_token token;
409 token = next_token (&val, (unsigned *)0, cfile);
410 if (token != NUMBER) {
411 parse_warn (cfile, "Expecting numeric lease time");
412 skip_to_semi (cfile);
413 return;
415 convert_num (cfile, (unsigned char *)timep, val, 10, 32);
416 /* Unswap the number - convert_num returns stuff in NBO. */
417 *timep = ntohl (*timep); /* XXX */
419 parse_semi (cfile);
422 /* No BNF for numeric aggregates - that's defined by the caller. What
423 this function does is to parse a sequence of numbers seperated by
424 the token specified in seperator. If max is zero, any number of
425 numbers will be parsed; otherwise, exactly max numbers are
426 expected. Base and size tell us how to internalize the numbers
427 once they've been tokenized. */
429 unsigned char *parse_numeric_aggregate (cfile, buf,
430 max, seperator, base, size)
431 struct parse *cfile;
432 unsigned char *buf;
433 unsigned *max;
434 int seperator;
435 int base;
436 unsigned size;
438 const char *val;
439 enum dhcp_token token;
440 unsigned char *bufp = buf, *s, *t;
441 unsigned count = 0;
442 pair c = (pair)0;
444 if (!bufp && *max) {
445 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
446 if (!bufp)
447 log_fatal ("no space for numeric aggregate");
448 s = 0;
449 } else
450 s = bufp;
452 do {
453 if (count) {
454 token = peek_token (&val, (unsigned *)0, cfile);
455 if (token != seperator) {
456 if (!*max)
457 break;
458 if (token != RBRACE && token != LBRACE)
459 token = next_token (&val,
460 (unsigned *)0,
461 cfile);
462 parse_warn (cfile, "too few numbers.");
463 if (token != SEMI)
464 skip_to_semi (cfile);
465 return (unsigned char *)0;
467 token = next_token (&val, (unsigned *)0, cfile);
469 token = next_token (&val, (unsigned *)0, cfile);
471 if (token == END_OF_FILE) {
472 parse_warn (cfile, "unexpected end of file");
473 break;
476 /* Allow NUMBER_OR_NAME if base is 16. */
477 if (token != NUMBER &&
478 (base != 16 || token != NUMBER_OR_NAME)) {
479 parse_warn (cfile, "expecting numeric value.");
480 skip_to_semi (cfile);
481 return (unsigned char *)0;
483 /* If we can, convert the number now; otherwise, build
484 a linked list of all the numbers. */
485 if (s) {
486 convert_num (cfile, s, val, base, size);
487 s += size / 8;
488 } else {
489 t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
490 if (!t)
491 log_fatal ("no temp space for number.");
492 strcpy ((char *)t, val);
493 c = cons ((caddr_t)t, c);
495 } while (++count != *max);
497 /* If we had to cons up a list, convert it now. */
498 if (c) {
499 bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
500 if (!bufp)
501 log_fatal ("no space for numeric aggregate.");
502 s = bufp + count - size / 8;
503 *max = count;
505 while (c) {
506 pair cdr = c -> cdr;
507 convert_num (cfile, s, (char *)(c -> car), base, size);
508 s -= size / 8;
509 /* Free up temp space. */
510 dfree (c -> car, MDL);
511 dfree (c, MDL);
512 c = cdr;
514 return bufp;
517 void convert_num (cfile, buf, str, base, size)
518 struct parse *cfile;
519 unsigned char *buf;
520 const char *str;
521 int base;
522 unsigned size;
524 const char *ptr = str;
525 int negative = 0;
526 u_int32_t val = 0;
527 int tval;
528 int max;
530 if (*ptr == '-') {
531 negative = 1;
532 ++ptr;
535 /* If base wasn't specified, figure it out from the data. */
536 if (!base) {
537 if (ptr [0] == '0') {
538 if (ptr [1] == 'x') {
539 base = 16;
540 ptr += 2;
541 } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
542 base = 8;
543 ptr += 1;
544 } else {
545 base = 10;
547 } else {
548 base = 10;
552 do {
553 tval = *ptr++;
554 /* XXX assumes ASCII... */
555 if (tval >= 'a')
556 tval = tval - 'a' + 10;
557 else if (tval >= 'A')
558 tval = tval - 'A' + 10;
559 else if (tval >= '0')
560 tval -= '0';
561 else {
562 parse_warn (cfile, "Bogus number: %s.", str);
563 break;
565 if (tval >= base) {
566 parse_warn (cfile,
567 "Bogus number %s: digit %d not in base %d",
568 str, tval, base);
569 break;
571 val = val * base + tval;
572 } while (*ptr);
574 if (negative)
575 max = (1 << (size - 1));
576 else
577 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
578 if (val > max) {
579 switch (base) {
580 case 8:
581 parse_warn (cfile,
582 "%s%lo exceeds max (%d) for precision.",
583 negative ? "-" : "",
584 (unsigned long)val, max);
585 break;
586 case 16:
587 parse_warn (cfile,
588 "%s%lx exceeds max (%d) for precision.",
589 negative ? "-" : "",
590 (unsigned long)val, max);
591 break;
592 default:
593 parse_warn (cfile,
594 "%s%lu exceeds max (%d) for precision.",
595 negative ? "-" : "",
596 (unsigned long)val, max);
597 break;
601 if (negative) {
602 switch (size) {
603 case 8:
604 *buf = -(unsigned long)val;
605 break;
606 case 16:
607 putShort (buf, -(long)val);
608 break;
609 case 32:
610 putLong (buf, -(long)val);
611 break;
612 default:
613 parse_warn (cfile,
614 "Unexpected integer size: %d\n", size);
615 break;
617 } else {
618 switch (size) {
619 case 8:
620 *buf = (u_int8_t)val;
621 break;
622 case 16:
623 putUShort (buf, (u_int16_t)val);
624 break;
625 case 32:
626 putULong (buf, val);
627 break;
628 default:
629 parse_warn (cfile,
630 "Unexpected integer size: %d\n", size);
631 break;
637 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
638 * NUMBER COLON NUMBER COLON NUMBER SEMI |
639 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
640 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
641 * NEVER
643 * Dates are stored in GMT or with a timezone offset; first number is day
644 * of week; next is year/month/day; next is hours:minutes:seconds on a
645 * 24-hour clock, followed by the timezone offset in seconds, which is
646 * optional.
649 TIME parse_date (cfile)
650 struct parse *cfile;
652 struct tm tm;
653 int guess;
654 int tzoff, wday, year, mon, mday, hour, min, sec;
655 const char *val;
656 enum dhcp_token token;
657 static int months [11] = { 31, 59, 90, 120, 151, 181,
658 212, 243, 273, 304, 334 };
660 /* Day of week, or "never"... */
661 token = next_token (&val, (unsigned *)0, cfile);
662 if (token == NEVER) {
663 if (!parse_semi (cfile))
664 return 0;
665 return MAX_TIME;
668 if (token != NUMBER) {
669 parse_warn (cfile, "numeric day of week expected.");
670 if (token != SEMI)
671 skip_to_semi (cfile);
672 return (TIME)0;
674 wday = atoi (val);
676 /* Year... */
677 token = next_token (&val, (unsigned *)0, cfile);
678 if (token != NUMBER) {
679 parse_warn (cfile, "numeric year expected.");
680 if (token != SEMI)
681 skip_to_semi (cfile);
682 return (TIME)0;
685 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
686 somebody invents a time machine, I think we can safely disregard
687 it. This actually works around a stupid Y2K bug that was present
688 in a very early beta release of dhcpd. */
689 year = atoi (val);
690 if (year > 1900)
691 year -= 1900;
693 /* Slash seperating year from month... */
694 token = next_token (&val, (unsigned *)0, cfile);
695 if (token != SLASH) {
696 parse_warn (cfile,
697 "expected slash seperating year from month.");
698 if (token != SEMI)
699 skip_to_semi (cfile);
700 return (TIME)0;
703 /* Month... */
704 token = next_token (&val, (unsigned *)0, cfile);
705 if (token != NUMBER) {
706 parse_warn (cfile, "numeric month expected.");
707 if (token != SEMI)
708 skip_to_semi (cfile);
709 return (TIME)0;
711 mon = atoi (val) - 1;
713 /* Slash seperating month from day... */
714 token = next_token (&val, (unsigned *)0, cfile);
715 if (token != SLASH) {
716 parse_warn (cfile,
717 "expected slash seperating month from day.");
718 if (token != SEMI)
719 skip_to_semi (cfile);
720 return (TIME)0;
723 /* Month... */
724 token = next_token (&val, (unsigned *)0, cfile);
725 if (token != NUMBER) {
726 parse_warn (cfile, "numeric day of month expected.");
727 if (token != SEMI)
728 skip_to_semi (cfile);
729 return (TIME)0;
731 mday = atoi (val);
733 /* Hour... */
734 token = next_token (&val, (unsigned *)0, cfile);
735 if (token != NUMBER) {
736 parse_warn (cfile, "numeric hour expected.");
737 if (token != SEMI)
738 skip_to_semi (cfile);
739 return (TIME)0;
741 hour = atoi (val);
743 /* Colon seperating hour from minute... */
744 token = next_token (&val, (unsigned *)0, cfile);
745 if (token != COLON) {
746 parse_warn (cfile,
747 "expected colon seperating hour from minute.");
748 if (token != SEMI)
749 skip_to_semi (cfile);
750 return (TIME)0;
753 /* Minute... */
754 token = next_token (&val, (unsigned *)0, cfile);
755 if (token != NUMBER) {
756 parse_warn (cfile, "numeric minute expected.");
757 if (token != SEMI)
758 skip_to_semi (cfile);
759 return (TIME)0;
761 min = atoi (val);
763 /* Colon seperating minute from second... */
764 token = next_token (&val, (unsigned *)0, cfile);
765 if (token != COLON) {
766 parse_warn (cfile,
767 "expected colon seperating hour from minute.");
768 if (token != SEMI)
769 skip_to_semi (cfile);
770 return (TIME)0;
773 /* Minute... */
774 token = next_token (&val, (unsigned *)0, cfile);
775 if (token != NUMBER) {
776 parse_warn (cfile, "numeric minute expected.");
777 if (token != SEMI)
778 skip_to_semi (cfile);
779 return (TIME)0;
781 sec = atoi (val);
783 token = peek_token (&val, (unsigned *)0, cfile);
784 if (token == NUMBER) {
785 token = next_token (&val, (unsigned *)0, cfile);
786 tzoff = atoi (val);
787 } else
788 tzoff = 0;
790 /* Make sure the date ends in a semicolon... */
791 if (!parse_semi (cfile))
792 return 0;
794 /* Guess the time value... */
795 guess = ((((((365 * (year - 70) + /* Days in years since '70 */
796 (year - 69) / 4 + /* Leap days since '70 */
797 (mon /* Days in months this year */
798 ? months [mon - 1]
799 : 0) +
800 (mon > 1 && /* Leap day this year */
801 !((year - 72) & 3)) +
802 mday - 1) * 24) + /* Day of month */
803 hour) * 60) +
804 min) * 60) + sec + tzoff;
806 /* This guess could be wrong because of leap seconds or other
807 weirdness we don't know about that the system does. For
808 now, we're just going to accept the guess, but at some point
809 it might be nice to do a successive approximation here to
810 get an exact value. Even if the error is small, if the
811 server is restarted frequently (and thus the lease database
812 is reread), the error could accumulate into something
813 significant. */
815 return guess;
819 * option-name :== IDENTIFIER |
820 IDENTIFIER . IDENTIFIER
823 struct option *parse_option_name (cfile, allocate, known)
824 struct parse *cfile;
825 int allocate;
826 int *known;
828 const char *val;
829 enum dhcp_token token;
830 char *uname;
831 struct universe *universe;
832 struct option *option;
834 token = next_token (&val, (unsigned *)0, cfile);
835 if (!is_identifier (token)) {
836 parse_warn (cfile,
837 "expecting identifier after option keyword.");
838 if (token != SEMI)
839 skip_to_semi (cfile);
840 return (struct option *)0;
842 uname = dmalloc (strlen (val) + 1, MDL);
843 if (!uname)
844 log_fatal ("no memory for uname information.");
845 strcpy (uname, val);
846 token = peek_token (&val, (unsigned *)0, cfile);
847 if (token == DOT) {
848 /* Go ahead and take the DOT token... */
849 token = next_token (&val, (unsigned *)0, cfile);
851 /* The next token should be an identifier... */
852 token = next_token (&val, (unsigned *)0, cfile);
853 if (!is_identifier (token)) {
854 parse_warn (cfile, "expecting identifier after '.'");
855 if (token != SEMI)
856 skip_to_semi (cfile);
857 return (struct option *)0;
860 /* Look up the option name hash table for the specified
861 uname. */
862 universe = (struct universe *)0;
863 if (!universe_hash_lookup (&universe, universe_hash,
864 uname, 0, MDL)) {
865 parse_warn (cfile, "no option space named %s.", uname);
866 skip_to_semi (cfile);
867 return (struct option *)0;
869 } else {
870 /* Use the default hash table, which contains all the
871 standard dhcp option names. */
872 val = uname;
873 universe = &dhcp_universe;
876 /* Look up the actual option info... */
877 option = (struct option *)0;
878 option_hash_lookup (&option, universe -> hash, val, 0, MDL);
880 /* If we didn't get an option structure, it's an undefined option. */
881 if (option) {
882 if (known)
883 *known = 1;
884 } else {
885 /* If we've been told to allocate, that means that this
886 (might) be an option code definition, so we'll create
887 an option structure just in case. */
888 if (allocate) {
889 option = new_option (MDL);
890 if (val == uname)
891 option -> name = val;
892 else {
893 char *s;
894 dfree (uname, MDL);
895 s = dmalloc (strlen (val) + 1, MDL);
896 if (!s)
897 log_fatal ("no memory for option %s.%s",
898 universe -> name, val);
899 strcpy (s, val);
900 option -> name = s;
902 option -> universe = universe;
903 option -> code = 0;
904 return option;
906 if (val == uname)
907 parse_warn (cfile, "no option named %s", val);
908 else
909 parse_warn (cfile, "no option named %s in space %s",
910 val, uname);
911 skip_to_semi (cfile);
912 return (struct option *)0;
915 /* Free the initial identifier token. */
916 dfree (uname, MDL);
917 return option;
920 /* IDENTIFIER SEMI */
922 void parse_option_space_decl (cfile)
923 struct parse *cfile;
925 int token;
926 const char *val;
927 struct universe **ua, *nu;
928 char *s;
930 next_token (&val, (unsigned *)0, cfile); /* Discard the SPACE token,
931 which was checked by the
932 caller. */
933 token = next_token (&val, (unsigned *)0, cfile);
934 if (!is_identifier (token)) {
935 parse_warn (cfile, "expecting identifier.");
936 skip_to_semi (cfile);
937 return;
939 nu = new_universe (MDL);
940 if (!nu)
941 log_fatal ("No memory for new option space.");
943 /* Set up the server option universe... */
944 s = dmalloc (strlen (val) + 1, MDL);
945 if (!s)
946 log_fatal ("No memory for new option space name.");
947 strcpy (s, val);
948 nu -> name = s;
949 nu -> lookup_func = lookup_hashed_option;
950 nu -> option_state_dereference =
951 hashed_option_state_dereference;
952 nu -> foreach = hashed_option_space_foreach;
953 nu -> save_func = save_hashed_option;
954 nu -> delete_func = delete_hashed_option;
955 nu -> encapsulate = hashed_option_space_encapsulate;
956 nu -> decode = parse_option_buffer;
957 nu -> length_size = 1;
958 nu -> tag_size = 1;
959 nu -> store_tag = putUChar;
960 nu -> store_length = putUChar;
961 nu -> index = universe_count++;
962 if (nu -> index >= universe_max) {
963 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
964 if (!ua)
965 log_fatal ("No memory to expand option space array.");
966 memcpy (ua, universes, universe_max * sizeof *ua);
967 universe_max *= 2;
968 dfree (universes, MDL);
969 universes = ua;
971 universes [nu -> index] = nu;
972 option_new_hash (&nu -> hash, 1, MDL);
973 if (!nu -> hash)
974 log_fatal ("Can't allocate %s option hash table.", nu -> name);
975 universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
976 parse_semi (cfile);
979 /* This is faked up to look good right now. Ideally, this should do a
980 recursive parse and allow arbitrary data structure definitions, but for
981 now it just allows you to specify a single type, an array of single types,
982 a sequence of types, or an array of sequences of types.
984 ocd :== NUMBER EQUALS ocsd SEMI
986 ocsd :== ocsd_type |
987 ocsd_type_sequence |
988 ARRAY OF ocsd_simple_type_sequence
990 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
992 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
994 ocsd_types :== ocsd_type |
995 ocsd_types ocsd_type
997 ocsd_type :== ocsd_simple_type |
998 ARRAY OF ocsd_simple_type
1000 ocsd_simple_types :== ocsd_simple_type |
1001 ocsd_simple_types ocsd_simple_type
1003 ocsd_simple_type :== BOOLEAN |
1004 INTEGER NUMBER |
1005 SIGNED INTEGER NUMBER |
1006 UNSIGNED INTEGER NUMBER |
1007 IP-ADDRESS |
1008 TEXT |
1009 STRING |
1010 ENCAPSULATE identifier */
1012 int parse_option_code_definition (cfile, option)
1013 struct parse *cfile;
1014 struct option *option;
1016 const char *val;
1017 enum dhcp_token token;
1018 unsigned arrayp = 0;
1019 int recordp = 0;
1020 int no_more_in_record = 0;
1021 char tokbuf [128];
1022 unsigned tokix = 0;
1023 char type;
1024 int code;
1025 int is_signed;
1026 char *s;
1027 int has_encapsulation = 0;
1029 /* Parse the option code. */
1030 token = next_token (&val, (unsigned *)0, cfile);
1031 if (token != NUMBER) {
1032 parse_warn (cfile, "expecting option code number.");
1033 skip_to_semi (cfile);
1034 return 0;
1036 option -> code = atoi (val);
1038 token = next_token (&val, (unsigned *)0, cfile);
1039 if (token != EQUAL) {
1040 parse_warn (cfile, "expecting \"=\"");
1041 skip_to_semi (cfile);
1042 return 0;
1045 /* See if this is an array. */
1046 token = next_token (&val, (unsigned *)0, cfile);
1047 if (token == ARRAY) {
1048 token = next_token (&val, (unsigned *)0, cfile);
1049 if (token != OF) {
1050 parse_warn (cfile, "expecting \"of\".");
1051 skip_to_semi (cfile);
1052 return 0;
1054 arrayp = 1;
1055 token = next_token (&val, (unsigned *)0, cfile);
1058 if (token == LBRACE) {
1059 recordp = 1;
1060 token = next_token (&val, (unsigned *)0, cfile);
1063 /* At this point we're expecting a data type. */
1064 next_type:
1065 if (has_encapsulation) {
1066 parse_warn (cfile,
1067 "encapsulate must always be the last item.");
1068 skip_to_semi (cfile);
1069 return 0;
1072 switch (token) {
1073 case ARRAY:
1074 if (arrayp) {
1075 parse_warn (cfile, "no nested arrays.");
1076 skip_to_rbrace (cfile, recordp);
1077 if (recordp)
1078 skip_to_semi (cfile);
1079 return 0;
1081 token = next_token (&val, (unsigned *)0, cfile);
1082 if (token != OF) {
1083 parse_warn (cfile, "expecting \"of\".");
1084 skip_to_semi (cfile);
1085 return 0;
1087 arrayp = recordp + 1;
1088 token = next_token (&val, (unsigned *)0, cfile);
1089 if ((recordp) && (token == LBRACE)) {
1090 parse_warn (cfile,
1091 "only uniform array inside record.");
1092 skip_to_rbrace (cfile, recordp + 1);
1093 skip_to_semi (cfile);
1094 return 0;
1096 goto next_type;
1097 case BOOLEAN:
1098 type = 'f';
1099 break;
1100 case INTEGER:
1101 is_signed = 1;
1102 parse_integer:
1103 token = next_token (&val, (unsigned *)0, cfile);
1104 if (token != NUMBER) {
1105 parse_warn (cfile, "expecting number.");
1106 skip_to_rbrace (cfile, recordp);
1107 if (recordp)
1108 skip_to_semi (cfile);
1109 return 0;
1111 switch (atoi (val)) {
1112 case 8:
1113 type = is_signed ? 'b' : 'B';
1114 break;
1115 case 16:
1116 type = is_signed ? 's' : 'S';
1117 break;
1118 case 32:
1119 type = is_signed ? 'l' : 'L';
1120 break;
1121 default:
1122 parse_warn (cfile,
1123 "%s bit precision is not supported.", val);
1124 skip_to_rbrace (cfile, recordp);
1125 if (recordp)
1126 skip_to_semi (cfile);
1127 return 0;
1129 break;
1130 case SIGNED:
1131 is_signed = 1;
1132 parse_signed:
1133 token = next_token (&val, (unsigned *)0, cfile);
1134 if (token != INTEGER) {
1135 parse_warn (cfile, "expecting \"integer\" keyword.");
1136 skip_to_rbrace (cfile, recordp);
1137 if (recordp)
1138 skip_to_semi (cfile);
1139 return 0;
1141 goto parse_integer;
1142 case UNSIGNED:
1143 is_signed = 0;
1144 goto parse_signed;
1146 case IP_ADDRESS:
1147 type = 'I';
1148 break;
1149 case DOMAIN_NAME:
1150 type = 'd';
1151 goto no_arrays;
1152 case TEXT:
1153 type = 't';
1154 no_arrays:
1155 if (arrayp) {
1156 parse_warn (cfile, "arrays of text strings not %s",
1157 "yet supported.");
1158 skip_to_rbrace (cfile, recordp);
1159 if (recordp)
1160 skip_to_semi (cfile);
1161 return 0;
1163 no_more_in_record = 1;
1164 break;
1165 case STRING_TOKEN:
1166 type = 'X';
1167 goto no_arrays;
1169 case ENCAPSULATE:
1170 token = next_token (&val, (unsigned *)0, cfile);
1171 if (!is_identifier (token)) {
1172 parse_warn (cfile,
1173 "expecting option space identifier");
1174 skip_to_semi (cfile);
1175 return 0;
1177 if (strlen (val) + tokix + 2 > sizeof (tokbuf))
1178 goto toobig;
1179 tokbuf [tokix++] = 'E';
1180 strcpy (&tokbuf [tokix], val);
1181 tokix += strlen (val);
1182 type = '.';
1183 has_encapsulation = 1;
1184 break;
1186 default:
1187 parse_warn (cfile, "unknown data type %s", val);
1188 skip_to_rbrace (cfile, recordp);
1189 if (recordp)
1190 skip_to_semi (cfile);
1191 return 0;
1194 if (tokix == sizeof tokbuf) {
1195 toobig:
1196 parse_warn (cfile, "too many types in record.");
1197 skip_to_rbrace (cfile, recordp);
1198 if (recordp)
1199 skip_to_semi (cfile);
1200 return 0;
1202 tokbuf [tokix++] = type;
1204 if (recordp) {
1205 token = next_token (&val, (unsigned *)0, cfile);
1206 if (arrayp > recordp) {
1207 if (tokix == sizeof tokbuf) {
1208 parse_warn (cfile,
1209 "too many types in record.");
1210 skip_to_rbrace (cfile, 1);
1211 skip_to_semi (cfile);
1212 return 0;
1214 arrayp = 0;
1215 tokbuf[tokix++] = 'a';
1217 if (token == COMMA) {
1218 if (no_more_in_record) {
1219 parse_warn (cfile,
1220 "%s must be at end of record.",
1221 type == 't' ? "text" : "string");
1222 skip_to_rbrace (cfile, 1);
1223 if (recordp)
1224 skip_to_semi (cfile);
1225 return 0;
1227 token = next_token (&val, (unsigned *)0, cfile);
1228 goto next_type;
1230 if (token != RBRACE) {
1231 parse_warn (cfile, "expecting right brace.");
1232 skip_to_rbrace (cfile, 1);
1233 if (recordp)
1234 skip_to_semi (cfile);
1235 return 0;
1238 if (!parse_semi (cfile)) {
1239 parse_warn (cfile, "semicolon expected.");
1240 skip_to_semi (cfile);
1241 if (recordp)
1242 skip_to_semi (cfile);
1243 return 0;
1245 if (has_encapsulation && arrayp) {
1246 parse_warn (cfile,
1247 "Arrays of encapsulations don't make sense.");
1248 return 0;
1250 if (has_encapsulation && tokbuf [0] == 'E')
1251 has_encapsulation = 0;
1252 s = dmalloc (tokix +
1253 (arrayp ? 1 : 0) +
1254 (has_encapsulation ? 1 : 0) + 1, MDL);
1255 if (!s)
1256 log_fatal ("no memory for option format.");
1257 if (has_encapsulation)
1258 s [0] = 'e';
1259 memcpy (s + has_encapsulation, tokbuf, tokix);
1260 tokix += has_encapsulation;
1261 if (arrayp)
1262 s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
1263 s [tokix] = 0;
1264 option -> format = s;
1265 if (option -> universe -> options [option -> code]) {
1266 /* XXX Free the option, but we can't do that now because they
1267 XXX may start out static. */
1269 option -> universe -> options [option -> code] = option;
1270 option_hash_add (option -> universe -> hash,
1271 (const char *)option -> name,
1272 0, option, MDL);
1273 return 1;
1277 * base64 :== NUMBER_OR_STRING
1280 int parse_base64 (data, cfile)
1281 struct data_string *data;
1282 struct parse *cfile;
1284 enum dhcp_token token;
1285 const char *val;
1286 int i, j, k;
1287 unsigned acc = 0;
1288 static unsigned char
1289 from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1290 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1291 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1292 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1293 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1294 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1295 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1296 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1297 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1298 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1299 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1300 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1301 struct string_list *bufs = (struct string_list *)0,
1302 *last = (struct string_list *)0,
1304 int cc = 0;
1305 int terminated = 0;
1307 /* It's possible for a + or a / to cause a base64 quantity to be
1308 tokenized into more than one token, so we have to parse them all
1309 in before decoding. */
1310 do {
1311 unsigned l;
1313 token = next_token (&val, &l, cfile);
1314 t = dmalloc (l + sizeof *t, MDL);
1315 if (!t)
1316 log_fatal ("no memory for base64 buffer.");
1317 memset (t, 0, (sizeof *t) - 1);
1318 memcpy (t -> string, val, l + 1);
1319 cc += l;
1320 if (last)
1321 last -> next = t;
1322 else
1323 bufs = t;
1324 last = t;
1325 token = peek_token (&val, (unsigned *)0, cfile);
1326 } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL ||
1327 token == NUMBER || token == PLUS || token == SLASH ||
1328 token == STRING);
1330 data -> len = cc;
1331 data -> len = (data -> len * 3) / 4;
1332 if (!buffer_allocate (&data -> buffer, data -> len, MDL)) {
1333 parse_warn (cfile, "can't allocate buffer for base64 data.");
1334 data -> len = 0;
1335 data -> data = (unsigned char *)0;
1336 return 0;
1339 j = k = 0;
1340 for (t = bufs; t; t = t -> next) {
1341 for (i = 0; t -> string [i]; i++) {
1342 unsigned foo = t -> string [i];
1343 if (terminated && foo != '=') {
1344 parse_warn (cfile,
1345 "stuff after base64 '=' terminator: %s.",
1346 &t -> string [i]);
1347 goto bad;
1349 if (foo < ' ' || foo > 'z') {
1350 bad64:
1351 parse_warn (cfile,
1352 "invalid base64 character %d.",
1353 t -> string [i]);
1354 bad:
1355 data_string_forget (data, MDL);
1356 goto out;
1358 if (foo == '=')
1359 terminated = 1;
1360 else {
1361 foo = from64 [foo - ' '];
1362 if (foo == 64)
1363 goto bad64;
1364 acc = (acc << 6) + foo;
1365 switch (k % 4) {
1366 case 0:
1367 break;
1368 case 1:
1369 data -> buffer -> data [j++] = (acc >> 4);
1370 acc = acc & 0x0f;
1371 break;
1373 case 2:
1374 data -> buffer -> data [j++] = (acc >> 2);
1375 acc = acc & 0x03;
1376 break;
1377 case 3:
1378 data -> buffer -> data [j++] = acc;
1379 acc = 0;
1380 break;
1383 k++;
1386 if (k % 4) {
1387 if (acc) {
1388 parse_warn (cfile,
1389 "partial base64 value left over: %d.",
1390 acc);
1393 data -> len = j;
1394 data -> data = data -> buffer -> data;
1395 out:
1396 for (t = bufs; t; t = last) {
1397 last = t -> next;
1398 dfree (t, MDL);
1400 if (data -> len)
1401 return 1;
1402 else
1403 return 0;
1408 * colon-seperated-hex-list :== NUMBER |
1409 * NUMBER COLON colon-seperated-hex-list
1412 int parse_cshl (data, cfile)
1413 struct data_string *data;
1414 struct parse *cfile;
1416 u_int8_t ibuf [128];
1417 unsigned ilen = 0;
1418 unsigned tlen = 0;
1419 struct option_tag *sl = (struct option_tag *)0;
1420 struct option_tag *next, **last = &sl;
1421 enum dhcp_token token;
1422 const char *val;
1423 unsigned char *rvp;
1425 do {
1426 token = next_token (&val, (unsigned *)0, cfile);
1427 if (token != NUMBER && token != NUMBER_OR_NAME) {
1428 parse_warn (cfile, "expecting hexadecimal number.");
1429 skip_to_semi (cfile);
1430 for (; sl; sl = next) {
1431 next = sl -> next;
1432 dfree (sl, MDL);
1434 return 0;
1436 if (ilen == sizeof ibuf) {
1437 next = (struct option_tag *)
1438 dmalloc (ilen - 1 +
1439 sizeof (struct option_tag), MDL);
1440 if (!next)
1441 log_fatal ("no memory for string list.");
1442 memcpy (next -> data, ibuf, ilen);
1443 *last = next;
1444 last = &next -> next;
1445 tlen += ilen;
1446 ilen = 0;
1448 convert_num (cfile, &ibuf [ilen++], val, 16, 8);
1450 token = peek_token (&val, (unsigned *)0, cfile);
1451 if (token != COLON)
1452 break;
1453 token = next_token (&val, (unsigned *)0, cfile);
1454 } while (1);
1456 if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
1457 log_fatal ("no memory to store octet data.");
1458 data -> data = &data -> buffer -> data [0];
1459 data -> len = tlen + ilen;
1460 data -> terminated = 0;
1462 rvp = &data -> buffer -> data [0];
1463 while (sl) {
1464 next = sl -> next;
1465 memcpy (rvp, sl -> data, sizeof ibuf);
1466 rvp += sizeof ibuf;
1467 dfree (sl, MDL);
1468 sl = next;
1471 memcpy (rvp, ibuf, ilen);
1472 return 1;
1476 * executable-statements :== executable-statement executable-statements |
1477 * executable-statement
1479 * executable-statement :==
1480 * IF if-statement |
1481 * ADD class-name SEMI |
1482 * BREAK SEMI |
1483 * OPTION option-parameter SEMI |
1484 * SUPERSEDE option-parameter SEMI |
1485 * PREPEND option-parameter SEMI |
1486 * APPEND option-parameter SEMI
1489 int parse_executable_statements (statements, cfile, lose, case_context)
1490 struct executable_statement **statements;
1491 struct parse *cfile;
1492 int *lose;
1493 enum expression_context case_context;
1495 struct executable_statement **next;
1497 next = statements;
1498 while (parse_executable_statement (next, cfile, lose, case_context))
1499 next = &((*next) -> next);
1500 if (!*lose)
1501 return 1;
1502 return 0;
1505 int parse_executable_statement (result, cfile, lose, case_context)
1506 struct executable_statement **result;
1507 struct parse *cfile;
1508 int *lose;
1509 enum expression_context case_context;
1511 enum dhcp_token token;
1512 const char *val;
1513 struct executable_statement base;
1514 struct class *cta;
1515 struct option *option;
1516 struct option_cache *cache;
1517 int known;
1518 int flag;
1519 int i;
1520 struct dns_zone *zone;
1521 isc_result_t status;
1522 char *s;
1524 token = peek_token (&val, (unsigned *)0, cfile);
1525 switch (token) {
1526 case IF:
1527 next_token (&val, (unsigned *)0, cfile);
1528 return parse_if_statement (result, cfile, lose);
1530 case TOKEN_ADD:
1531 token = next_token (&val, (unsigned *)0, cfile);
1532 token = next_token (&val, (unsigned *)0, cfile);
1533 if (token != STRING) {
1534 parse_warn (cfile, "expecting class name.");
1535 skip_to_semi (cfile);
1536 *lose = 1;
1537 return 0;
1539 cta = (struct class *)0;
1540 status = find_class (&cta, val, MDL);
1541 if (status != ISC_R_SUCCESS) {
1542 parse_warn (cfile, "class %s: %s",
1543 val, isc_result_totext (status));
1544 skip_to_semi (cfile);
1545 *lose = 1;
1546 return 0;
1548 if (!parse_semi (cfile)) {
1549 *lose = 1;
1550 return 0;
1552 if (!executable_statement_allocate (result, MDL))
1553 log_fatal ("no memory for new statement.");
1554 (*result) -> op = add_statement;
1555 (*result) -> data.add = cta;
1556 break;
1558 case BREAK:
1559 token = next_token (&val, (unsigned *)0, cfile);
1560 if (!parse_semi (cfile)) {
1561 *lose = 1;
1562 return 0;
1564 if (!executable_statement_allocate (result, MDL))
1565 log_fatal ("no memory for new statement.");
1566 (*result) -> op = break_statement;
1567 break;
1569 case SEND:
1570 token = next_token (&val, (unsigned *)0, cfile);
1571 known = 0;
1572 option = parse_option_name (cfile, 0, &known);
1573 if (!option) {
1574 *lose = 1;
1575 return 0;
1577 return parse_option_statement (result, cfile, 1, option,
1578 send_option_statement);
1580 case SUPERSEDE:
1581 case OPTION:
1582 token = next_token (&val, (unsigned *)0, cfile);
1583 known = 0;
1584 option = parse_option_name (cfile, 0, &known);
1585 if (!option) {
1586 *lose = 1;
1587 return 0;
1589 return parse_option_statement (result, cfile, 1, option,
1590 supersede_option_statement);
1592 case ALLOW:
1593 flag = 1;
1594 goto pad;
1595 case DENY:
1596 flag = 0;
1597 goto pad;
1598 case IGNORE:
1599 flag = 2;
1600 pad:
1601 token = next_token (&val, (unsigned *)0, cfile);
1602 cache = (struct option_cache *)0;
1603 if (!parse_allow_deny (&cache, cfile, flag))
1604 return 0;
1605 if (!executable_statement_allocate (result, MDL))
1606 log_fatal ("no memory for new statement.");
1607 (*result) -> op = supersede_option_statement;
1608 (*result) -> data.option = cache;
1609 break;
1611 case DEFAULT:
1612 token = next_token (&val, (unsigned *)0, cfile);
1613 token = peek_token (&val, (unsigned *)0, cfile);
1614 if (token == COLON)
1615 goto switch_default;
1616 known = 0;
1617 option = parse_option_name (cfile, 0, &known);
1618 if (!option) {
1619 *lose = 1;
1620 return 0;
1622 return parse_option_statement (result, cfile, 1, option,
1623 default_option_statement);
1625 case PREPEND:
1626 token = next_token (&val, (unsigned *)0, cfile);
1627 known = 0;
1628 option = parse_option_name (cfile, 0, &known);
1629 if (!option) {
1630 *lose = 1;
1631 return 0;
1633 return parse_option_statement (result, cfile, 1, option,
1634 prepend_option_statement);
1636 case APPEND:
1637 token = next_token (&val, (unsigned *)0, cfile);
1638 known = 0;
1639 option = parse_option_name (cfile, 0, &known);
1640 if (!option) {
1641 *lose = 1;
1642 return 0;
1644 return parse_option_statement (result, cfile, 1, option,
1645 append_option_statement);
1647 case ON:
1648 token = next_token (&val, (unsigned *)0, cfile);
1649 return parse_on_statement (result, cfile, lose);
1651 case SWITCH:
1652 token = next_token (&val, (unsigned *)0, cfile);
1653 return parse_switch_statement (result, cfile, lose);
1655 case CASE:
1656 token = next_token (&val, (unsigned *)0, cfile);
1657 if (case_context == context_any) {
1658 parse_warn (cfile,
1659 "case statement in inappropriate scope.");
1660 *lose = 1;
1661 skip_to_semi (cfile);
1662 return 0;
1664 return parse_case_statement (result,
1665 cfile, lose, case_context);
1667 switch_default:
1668 token = next_token (&val, (unsigned *)0, cfile);
1669 if (case_context == context_any) {
1670 parse_warn (cfile, "switch default statement in %s",
1671 "inappropriate scope.");
1673 *lose = 1;
1674 return 0;
1675 } else {
1676 if (!executable_statement_allocate (result, MDL))
1677 log_fatal ("no memory for default statement.");
1678 (*result) -> op = default_statement;
1679 return 1;
1682 case DEFINE:
1683 case TOKEN_SET:
1684 token = next_token (&val, (unsigned *)0, cfile);
1685 if (token == DEFINE)
1686 flag = 1;
1687 else
1688 flag = 0;
1690 token = next_token (&val, (unsigned *)0, cfile);
1691 if (token != NAME && token != NUMBER_OR_NAME) {
1692 parse_warn (cfile,
1693 "%s can't be a variable name", val);
1694 badset:
1695 skip_to_semi (cfile);
1696 *lose = 1;
1697 return 0;
1700 if (!executable_statement_allocate (result, MDL))
1701 log_fatal ("no memory for set statement.");
1702 (*result) -> op = flag ? define_statement : set_statement;
1703 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
1704 if (!(*result)->data.set.name)
1705 log_fatal ("can't allocate variable name");
1706 strcpy ((*result) -> data.set.name, val);
1707 token = next_token (&val, (unsigned *)0, cfile);
1709 if (token == LPAREN) {
1710 struct string_list *head, *cur, *new;
1711 struct expression *expr;
1712 head = cur = (struct string_list *)0;
1713 do {
1714 token = next_token (&val,
1715 (unsigned *)0, cfile);
1716 if (token == RPAREN)
1717 break;
1718 if (token != NAME && token != NUMBER_OR_NAME) {
1719 parse_warn (cfile,
1720 "expecting argument name");
1721 skip_to_rbrace (cfile, 0);
1722 *lose = 1;
1723 executable_statement_dereference
1724 (result, MDL);
1725 return 0;
1727 new = ((struct string_list *)
1728 dmalloc (sizeof (struct string_list) +
1729 strlen (val), MDL));
1730 if (!new)
1731 log_fatal ("can't allocate string.");
1732 memset (new, 0, sizeof *new);
1733 strcpy (new -> string, val);
1734 if (cur) {
1735 cur -> next = new;
1736 cur = new;
1737 } else {
1738 head = cur = new;
1740 token = next_token (&val,
1741 (unsigned *)0, cfile);
1742 } while (token == COMMA);
1744 if (token != RPAREN) {
1745 parse_warn (cfile, "expecting right paren.");
1746 badx:
1747 skip_to_semi (cfile);
1748 *lose = 1;
1749 executable_statement_dereference (result, MDL);
1750 return 0;
1753 token = next_token (&val, (unsigned *)0, cfile);
1754 if (token != LBRACE) {
1755 parse_warn (cfile, "expecting left brace.");
1756 goto badx;
1759 expr = (struct expression *)0;
1760 if (!(expression_allocate (&expr, MDL)))
1761 log_fatal ("can't allocate expression.");
1762 expr -> op = expr_function;
1763 if (!fundef_allocate (&expr -> data.func, MDL))
1764 log_fatal ("can't allocate fundef.");
1765 expr -> data.func -> args = head;
1766 (*result) -> data.set.expr = expr;
1768 if (!(parse_executable_statements
1769 (&expr -> data.func -> statements, cfile, lose,
1770 case_context))) {
1771 if (*lose)
1772 goto badx;
1775 token = next_token (&val, (unsigned *)0, cfile);
1776 if (token != RBRACE) {
1777 parse_warn (cfile, "expecting rigt brace.");
1778 goto badx;
1780 } else {
1781 if (token != EQUAL) {
1782 parse_warn (cfile,
1783 "expecting '=' in %s statement.",
1784 flag ? "define" : "set");
1785 goto badset;
1788 if (!parse_expression (&(*result) -> data.set.expr,
1789 cfile, lose, context_any,
1790 (struct expression **)0,
1791 expr_none)) {
1792 if (!*lose)
1793 parse_warn (cfile,
1794 "expecting expression.");
1795 else
1796 *lose = 1;
1797 skip_to_semi (cfile);
1798 executable_statement_dereference (result, MDL);
1799 return 0;
1801 if (!parse_semi (cfile)) {
1802 *lose = 1;
1803 executable_statement_dereference (result, MDL);
1804 return 0;
1807 break;
1809 case UNSET:
1810 token = next_token (&val, (unsigned *)0, cfile);
1812 token = next_token (&val, (unsigned *)0, cfile);
1813 if (token != NAME && token != NUMBER_OR_NAME) {
1814 parse_warn (cfile,
1815 "%s can't be a variable name", val);
1816 badunset:
1817 skip_to_semi (cfile);
1818 *lose = 1;
1819 return 0;
1822 if (!executable_statement_allocate (result, MDL))
1823 log_fatal ("no memory for set statement.");
1824 (*result) -> op = unset_statement;
1825 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
1826 if (!(*result)->data.unset)
1827 log_fatal ("can't allocate variable name");
1828 strcpy ((*result) -> data.unset, val);
1829 if (!parse_semi (cfile)) {
1830 *lose = 1;
1831 executable_statement_dereference (result, MDL);
1832 return 0;
1834 break;
1836 case EVAL:
1837 token = next_token (&val, (unsigned *)0, cfile);
1839 if (!executable_statement_allocate (result, MDL))
1840 log_fatal ("no memory for eval statement.");
1841 (*result) -> op = eval_statement;
1843 if (!parse_expression (&(*result) -> data.eval,
1844 cfile, lose, context_data, /* XXX */
1845 (struct expression **)0, expr_none)) {
1846 if (!*lose)
1847 parse_warn (cfile,
1848 "expecting data expression.");
1849 else
1850 *lose = 1;
1851 skip_to_semi (cfile);
1852 executable_statement_dereference (result, MDL);
1853 return 0;
1855 if (!parse_semi (cfile)) {
1856 *lose = 1;
1857 executable_statement_dereference (result, MDL);
1859 break;
1861 case RETURN:
1862 token = next_token (&val, (unsigned *)0, cfile);
1864 if (!executable_statement_allocate (result, MDL))
1865 log_fatal ("no memory for return statement.");
1866 (*result) -> op = return_statement;
1868 if (!parse_expression (&(*result) -> data.retval,
1869 cfile, lose, context_data,
1870 (struct expression **)0, expr_none)) {
1871 if (!*lose)
1872 parse_warn (cfile,
1873 "expecting data expression.");
1874 else
1875 *lose = 1;
1876 skip_to_semi (cfile);
1877 executable_statement_dereference (result, MDL);
1878 return 0;
1880 if (!parse_semi (cfile)) {
1881 *lose = 1;
1882 executable_statement_dereference (result, MDL);
1883 return 0;
1885 break;
1887 case LOG:
1888 token = next_token (&val, (unsigned *)0, cfile);
1890 if (!executable_statement_allocate (result, MDL))
1891 log_fatal ("no memory for log statement.");
1892 (*result) -> op = log_statement;
1894 token = next_token (&val, (unsigned *)0, cfile);
1895 if (token != LPAREN) {
1896 parse_warn (cfile, "left parenthesis expected.");
1897 skip_to_semi (cfile);
1898 *lose = 1;
1899 return 0;
1902 token = peek_token (&val, (unsigned *)0, cfile);
1903 i = 1;
1904 if (token == FATAL) {
1905 (*result) -> data.log.priority = log_priority_fatal;
1906 } else if (token == ERROR) {
1907 (*result) -> data.log.priority = log_priority_error;
1908 } else if (token == TOKEN_DEBUG) {
1909 (*result) -> data.log.priority = log_priority_debug;
1910 } else if (token == INFO) {
1911 (*result) -> data.log.priority = log_priority_info;
1912 } else {
1913 (*result) -> data.log.priority = log_priority_debug;
1914 i = 0;
1916 if (i) {
1917 token = next_token (&val, (unsigned *)0, cfile);
1918 token = next_token (&val, (unsigned *)0, cfile);
1919 if (token != COMMA) {
1920 parse_warn (cfile, "comma expected.");
1921 skip_to_semi (cfile);
1922 *lose = 1;
1923 return 0;
1927 if (!(parse_data_expression
1928 (&(*result) -> data.log.expr, cfile, lose))) {
1929 skip_to_semi (cfile);
1930 *lose = 1;
1931 return 0;
1934 token = next_token (&val, (unsigned *)0, cfile);
1935 if (token != RPAREN) {
1936 parse_warn (cfile, "right parenthesis expected.");
1937 skip_to_semi (cfile);
1938 *lose = 1;
1939 return 0;
1942 token = next_token (&val, (unsigned *)0, cfile);
1943 if (token != SEMI) {
1944 parse_warn (cfile, "semicolon expected.");
1945 skip_to_semi (cfile);
1946 *lose = 1;
1947 return 0;
1949 break;
1951 /* Not really a statement, but we parse it here anyway
1952 because it's appropriate for all DHCP agents with
1953 parsers. */
1954 case ZONE:
1955 token = next_token (&val, (unsigned *)0, cfile);
1956 zone = (struct dns_zone *)0;
1957 if (!dns_zone_allocate (&zone, MDL))
1958 log_fatal ("no memory for new zone.");
1959 zone -> name = parse_host_name (cfile);
1960 if (!zone -> name) {
1961 parse_warn (cfile, "expecting hostname.");
1962 badzone:
1963 *lose = 1;
1964 skip_to_semi (cfile);
1965 dns_zone_dereference (&zone, MDL);
1966 return 0;
1968 i = strlen (zone -> name);
1969 if (zone -> name [i - 1] != '.') {
1970 s = dmalloc ((unsigned)i + 2, MDL);
1971 if (!s) {
1972 parse_warn (cfile, "no trailing '.' on zone");
1973 goto badzone;
1975 strcpy (s, zone -> name);
1976 s [i] = '.';
1977 s [i + 1] = 0;
1978 dfree (zone -> name, MDL);
1979 zone -> name = s;
1981 if (!parse_zone (zone, cfile))
1982 goto badzone;
1983 status = enter_dns_zone (zone);
1984 if (status != ISC_R_SUCCESS) {
1985 parse_warn (cfile, "dns zone key %s: %s",
1986 zone -> name, isc_result_totext (status));
1987 dns_zone_dereference (&zone, MDL);
1988 return 0;
1990 dns_zone_dereference (&zone, MDL);
1991 return 1;
1993 /* Also not really a statement, but same idea as above. */
1994 case KEY:
1995 token = next_token (&val, (unsigned *)0, cfile);
1996 if (!parse_key (cfile)) {
1997 *lose = 1;
1998 return 0;
2000 return 1;
2002 default:
2003 if (config_universe && is_identifier (token)) {
2004 option = (struct option *)0;
2005 option_hash_lookup (&option, config_universe -> hash,
2006 val, 0, MDL);
2007 if (option) {
2008 token = next_token (&val,
2009 (unsigned *)0, cfile);
2010 return parse_option_statement
2011 (result, cfile, 1, option,
2012 supersede_option_statement);
2016 if (token == NUMBER_OR_NAME || token == NAME) {
2017 /* This is rather ugly. Since function calls are
2018 data expressions, fake up an eval statement. */
2019 if (!executable_statement_allocate (result, MDL))
2020 log_fatal ("no memory for eval statement.");
2021 (*result) -> op = eval_statement;
2023 if (!parse_expression (&(*result) -> data.eval,
2024 cfile, lose, context_data,
2025 (struct expression **)0,
2026 expr_none)) {
2027 if (!*lose)
2028 parse_warn (cfile, "expecting "
2029 "function call.");
2030 else
2031 *lose = 1;
2032 skip_to_semi (cfile);
2033 executable_statement_dereference (result, MDL);
2034 return 0;
2036 if (!parse_semi (cfile)) {
2037 *lose = 1;
2038 executable_statement_dereference (result, MDL);
2039 return 0;
2041 break;
2044 *lose = 0;
2045 return 0;
2048 return 1;
2051 /* zone-statements :== zone-statement |
2052 zone-statement zone-statements
2053 zone-statement :==
2054 PRIMARY ip-addresses SEMI |
2055 SECONDARY ip-addresses SEMI |
2056 key-reference SEMI
2057 ip-addresses :== ip-addr-or-hostname |
2058 ip-addr-or-hostname COMMA ip-addresses
2059 key-reference :== KEY STRING |
2060 KEY identifier */
2062 int parse_zone (struct dns_zone *zone, struct parse *cfile)
2064 int token;
2065 const char *val;
2066 char *key_name;
2067 struct option_cache *oc;
2068 int done = 0;
2070 token = next_token (&val, (unsigned *)0, cfile);
2071 if (token != LBRACE) {
2072 parse_warn (cfile, "expecting left brace");
2073 return 0;
2076 do {
2077 token = peek_token (&val, (unsigned *)0, cfile);
2078 switch (token) {
2079 case PRIMARY:
2080 if (zone -> primary) {
2081 parse_warn (cfile,
2082 "more than one primary.");
2083 skip_to_semi (cfile);
2084 return 0;
2086 if (!option_cache_allocate (&zone -> primary, MDL))
2087 log_fatal ("can't allocate primary option cache.");
2088 oc = zone -> primary;
2089 goto consemup;
2091 case SECONDARY:
2092 if (zone -> secondary) {
2093 parse_warn (cfile, "more than one secondary.");
2094 skip_to_semi (cfile);
2095 return 0;
2097 if (!option_cache_allocate (&zone -> secondary, MDL))
2098 log_fatal ("can't allocate secondary.");
2099 oc = zone -> secondary;
2100 consemup:
2101 token = next_token (&val, (unsigned *)0, cfile);
2102 do {
2103 struct expression *expr = (struct expression *)0;
2104 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
2105 parse_warn (cfile,
2106 "expecting IP addr or hostname.");
2107 skip_to_semi (cfile);
2108 return 0;
2110 if (oc -> expression) {
2111 struct expression *old =
2112 (struct expression *)0;
2113 expression_reference (&old,
2114 oc -> expression,
2115 MDL);
2116 expression_dereference (&oc -> expression,
2117 MDL);
2118 if (!make_concat (&oc -> expression,
2119 old, expr))
2120 log_fatal ("no memory for concat.");
2121 expression_dereference (&expr, MDL);
2122 expression_dereference (&old, MDL);
2123 } else {
2124 expression_reference (&oc -> expression,
2125 expr, MDL);
2126 expression_dereference (&expr, MDL);
2128 token = next_token (&val, (unsigned *)0, cfile);
2129 } while (token == COMMA);
2130 if (token != SEMI) {
2131 parse_warn (cfile, "expecting semicolon.");
2132 skip_to_semi (cfile);
2133 return 0;
2135 break;
2137 case KEY:
2138 token = next_token (&val, (unsigned *)0, cfile);
2139 token = peek_token (&val, (unsigned *)0, cfile);
2140 if (token == STRING) {
2141 token = next_token (&val, (unsigned *)0, cfile);
2142 key_name = (char *)0;
2143 } else {
2144 key_name = parse_host_name (cfile);
2145 if (!key_name) {
2146 parse_warn (cfile, "expecting key name.");
2147 skip_to_semi (cfile);
2148 return 0;
2150 val = key_name;
2152 if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2153 ISC_R_SUCCESS)
2154 parse_warn (cfile, "unknown key %s", val);
2155 if (key_name)
2156 dfree (key_name, MDL);
2157 if (!parse_semi (cfile))
2158 return 0;
2159 break;
2161 default:
2162 done = 1;
2163 break;
2165 } while (!done);
2167 token = next_token (&val, (unsigned *)0, cfile);
2168 if (token != RBRACE) {
2169 parse_warn (cfile, "expecting right brace.");
2170 return 0;
2172 return 1;
2175 /* key-statements :== key-statement |
2176 key-statement key-statements
2177 key-statement :==
2178 ALGORITHM host-name SEMI |
2179 secret-definition SEMI
2180 secret-definition :== SECRET base64val |
2181 SECRET STRING */
2183 int parse_key (struct parse *cfile)
2185 int token;
2186 const char *val;
2187 int done = 0;
2188 struct auth_key *key;
2189 struct data_string ds;
2190 isc_result_t status;
2191 char *s;
2193 key = (struct auth_key *)0;
2194 if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2195 log_fatal ("no memory for key");
2197 token = peek_token (&val, (unsigned *)0, cfile);
2198 if (token == STRING) {
2199 token = next_token (&val, (unsigned *)0, cfile);
2200 key -> name = dmalloc (strlen (val) + 1, MDL);
2201 if (!key -> name)
2202 log_fatal ("no memory for key name.");
2203 strcpy (key -> name, val);
2205 } else {
2206 key -> name = parse_host_name (cfile);
2207 if (!key -> name) {
2208 parse_warn (cfile, "expecting key name.");
2209 skip_to_semi (cfile);
2210 goto bad;
2214 token = next_token (&val, (unsigned *)0, cfile);
2215 if (token != LBRACE) {
2216 parse_warn (cfile, "expecting left brace");
2217 goto bad;
2220 do {
2221 token = next_token (&val, (unsigned *)0, cfile);
2222 switch (token) {
2223 case ALGORITHM:
2224 if (key -> algorithm) {
2225 parse_warn (cfile,
2226 "key %s: too many algorithms",
2227 key -> name);
2228 goto rbad;
2230 key -> algorithm = parse_host_name (cfile);
2231 if (!key -> algorithm) {
2232 parse_warn (cfile,
2233 "expecting key algorithm name.");
2234 goto rbad;
2236 if (!parse_semi (cfile))
2237 goto rbad;
2238 /* If the algorithm name isn't an FQDN, tack on
2239 the .SIG-ALG.REG.NET. domain. */
2240 s = strrchr (key -> algorithm, '.');
2241 if (!s) {
2242 static char add [] = ".SIG-ALG.REG.INT.";
2243 s = dmalloc (strlen (key -> algorithm) +
2244 sizeof (add), MDL);
2245 if (!s) {
2246 log_error ("no memory for key %s.",
2247 "algorithm");
2248 goto rbad;
2250 strcpy (s, key -> algorithm);
2251 strcat (s, add);
2252 dfree (key -> algorithm, MDL);
2253 key -> algorithm = s;
2254 } else if (s [1]) {
2255 /* If there is no trailing '.', hack one in. */
2256 s = dmalloc (strlen (key -> algorithm) + 2, MDL);
2257 if (!s) {
2258 log_error ("no memory for key %s.",
2259 key -> algorithm);
2260 goto rbad;
2262 strcpy (s, key -> algorithm);
2263 strcat (s, ".");
2264 dfree (key -> algorithm, MDL);
2265 key -> algorithm = s;
2267 break;
2269 case SECRET:
2270 if (key -> key) {
2271 parse_warn (cfile, "key %s: too many secrets",
2272 key -> name);
2273 goto rbad;
2276 memset (&ds, 0, sizeof(ds));
2277 if (!parse_base64 (&ds, cfile))
2278 goto rbad;
2279 status = omapi_data_string_new (&key -> key, ds.len,
2280 MDL);
2281 if (status != ISC_R_SUCCESS)
2282 goto rbad;
2283 memcpy (key -> key -> value,
2284 ds.buffer -> data, ds.len);
2285 data_string_forget (&ds, MDL);
2287 if (!parse_semi (cfile))
2288 goto rbad;
2289 break;
2291 default:
2292 done = 1;
2293 break;
2295 } while (!done);
2296 if (token != RBRACE) {
2297 parse_warn (cfile, "expecting right brace.");
2298 goto rbad;
2300 /* Allow the BIND 8 syntax, which has a semicolon after each
2301 closing brace. */
2302 token = peek_token (&val, (unsigned *)0, cfile);
2303 if (token == SEMI)
2304 token = next_token (&val, (unsigned *)0, cfile);
2306 /* Remember the key. */
2307 status = omapi_auth_key_enter (key);
2308 if (status != ISC_R_SUCCESS) {
2309 parse_warn (cfile, "tsig key %s: %s",
2310 key -> name, isc_result_totext (status));
2311 goto bad;
2313 omapi_auth_key_dereference (&key, MDL);
2314 return 1;
2316 rbad:
2317 skip_to_rbrace (cfile, 1);
2318 bad:
2319 omapi_auth_key_dereference (&key, MDL);
2320 return 0;
2324 * on-statement :== event-types LBRACE executable-statements RBRACE
2325 * event-types :== event-type OR event-types |
2326 * event-type
2327 * event-type :== EXPIRY | COMMIT | RELEASE
2330 int parse_on_statement (result, cfile, lose)
2331 struct executable_statement **result;
2332 struct parse *cfile;
2333 int *lose;
2335 enum dhcp_token token;
2336 const char *val;
2338 if (!executable_statement_allocate (result, MDL))
2339 log_fatal ("no memory for new statement.");
2340 (*result) -> op = on_statement;
2342 do {
2343 token = next_token (&val, (unsigned *)0, cfile);
2344 switch (token) {
2345 case EXPIRY:
2346 (*result) -> data.on.evtypes |= ON_EXPIRY;
2347 break;
2349 case COMMIT:
2350 (*result) -> data.on.evtypes |= ON_COMMIT;
2351 break;
2353 case RELEASE:
2354 (*result) -> data.on.evtypes |= ON_RELEASE;
2355 break;
2357 case TRANSMISSION:
2358 (*result) -> data.on.evtypes |= ON_TRANSMISSION;
2359 break;
2361 default:
2362 parse_warn (cfile, "expecting a lease event type");
2363 skip_to_semi (cfile);
2364 *lose = 1;
2365 executable_statement_dereference (result, MDL);
2366 return 0;
2368 token = next_token (&val, (unsigned *)0, cfile);
2369 } while (token == OR);
2371 /* Semicolon means no statements. */
2372 if (token == SEMI)
2373 return 1;
2375 if (token != LBRACE) {
2376 parse_warn (cfile, "left brace expected.");
2377 skip_to_semi (cfile);
2378 *lose = 1;
2379 executable_statement_dereference (result, MDL);
2380 return 0;
2382 if (!parse_executable_statements (&(*result) -> data.on.statements,
2383 cfile, lose, context_any)) {
2384 if (*lose) {
2385 /* Try to even things up. */
2386 do {
2387 token = next_token (&val,
2388 (unsigned *)0, cfile);
2389 } while (token != END_OF_FILE && token != RBRACE);
2390 executable_statement_dereference (result, MDL);
2391 return 0;
2394 token = next_token (&val, (unsigned *)0, cfile);
2395 if (token != RBRACE) {
2396 parse_warn (cfile, "right brace expected.");
2397 skip_to_semi (cfile);
2398 *lose = 1;
2399 executable_statement_dereference (result, MDL);
2400 return 0;
2402 return 1;
2406 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2410 int parse_switch_statement (result, cfile, lose)
2411 struct executable_statement **result;
2412 struct parse *cfile;
2413 int *lose;
2415 enum dhcp_token token;
2416 const char *val;
2418 if (!executable_statement_allocate (result, MDL))
2419 log_fatal ("no memory for new statement.");
2420 (*result) -> op = switch_statement;
2422 token = next_token (&val, (unsigned *)0, cfile);
2423 if (token != LPAREN) {
2424 parse_warn (cfile, "expecting left brace.");
2425 pfui:
2426 *lose = 1;
2427 skip_to_semi (cfile);
2428 gnorf:
2429 executable_statement_dereference (result, MDL);
2430 return 0;
2433 if (!parse_expression (&(*result) -> data.s_switch.expr,
2434 cfile, lose, context_data_or_numeric,
2435 (struct expression **)0, expr_none)) {
2436 if (!*lose) {
2437 parse_warn (cfile,
2438 "expecting data or numeric expression.");
2439 goto pfui;
2441 goto gnorf;
2444 token = next_token (&val, (unsigned *)0, cfile);
2445 if (token != RPAREN) {
2446 parse_warn (cfile, "right paren expected.");
2447 goto pfui;
2450 token = next_token (&val, (unsigned *)0, cfile);
2451 if (token != LBRACE) {
2452 parse_warn (cfile, "left brace expected.");
2453 goto pfui;
2455 if (!(parse_executable_statements
2456 (&(*result) -> data.s_switch.statements, cfile, lose,
2457 (is_data_expression ((*result) -> data.s_switch.expr)
2458 ? context_data : context_numeric)))) {
2459 if (*lose) {
2460 skip_to_rbrace (cfile, 1);
2461 executable_statement_dereference (result, MDL);
2462 return 0;
2465 token = next_token (&val, (unsigned *)0, cfile);
2466 if (token != RBRACE) {
2467 parse_warn (cfile, "right brace expected.");
2468 goto pfui;
2470 return 1;
2474 * case-statement :== CASE expr COLON
2478 int parse_case_statement (result, cfile, lose, case_context)
2479 struct executable_statement **result;
2480 struct parse *cfile;
2481 int *lose;
2482 enum expression_context case_context;
2484 enum dhcp_token token;
2485 const char *val;
2487 if (!executable_statement_allocate (result, MDL))
2488 log_fatal ("no memory for new statement.");
2489 (*result) -> op = case_statement;
2491 if (!parse_expression (&(*result) -> data.c_case,
2492 cfile, lose, case_context,
2493 (struct expression **)0, expr_none))
2495 if (!*lose) {
2496 parse_warn (cfile, "expecting %s expression.",
2497 (case_context == context_data
2498 ? "data" : "numeric"));
2500 pfui:
2501 *lose = 1;
2502 skip_to_semi (cfile);
2503 executable_statement_dereference (result, MDL);
2504 return 0;
2507 token = next_token (&val, (unsigned *)0, cfile);
2508 if (token != COLON) {
2509 parse_warn (cfile, "colon expected.");
2510 goto pfui;
2512 return 1;
2516 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
2517 * else-statement
2519 * else-statement :== <null> |
2520 * ELSE LBRACE executable-statements RBRACE |
2521 * ELSE IF if-statement |
2522 * ELSIF if-statement
2525 int parse_if_statement (result, cfile, lose)
2526 struct executable_statement **result;
2527 struct parse *cfile;
2528 int *lose;
2530 enum dhcp_token token;
2531 const char *val;
2532 int parenp;
2534 if (!executable_statement_allocate (result, MDL))
2535 log_fatal ("no memory for if statement.");
2537 (*result) -> op = if_statement;
2539 token = peek_token (&val, (unsigned *)0, cfile);
2540 if (token == LPAREN) {
2541 parenp = 1;
2542 next_token (&val, (unsigned *)0, cfile);
2543 } else
2544 parenp = 0;
2547 if (!parse_boolean_expression (&(*result) -> data.ie.expr,
2548 cfile, lose)) {
2549 if (!*lose)
2550 parse_warn (cfile, "boolean expression expected.");
2551 executable_statement_dereference (result, MDL);
2552 *lose = 1;
2553 return 0;
2555 #if defined (DEBUG_EXPRESSION_PARSE)
2556 print_expression ("if condition", (*result) -> data.ie.expr);
2557 #endif
2558 if (parenp) {
2559 token = next_token (&val, (unsigned *)0, cfile);
2560 if (token != RPAREN) {
2561 parse_warn (cfile, "expecting right paren.");
2562 *lose = 1;
2563 executable_statement_dereference (result, MDL);
2564 return 0;
2567 token = next_token (&val, (unsigned *)0, cfile);
2568 if (token != LBRACE) {
2569 parse_warn (cfile, "left brace expected.");
2570 skip_to_semi (cfile);
2571 *lose = 1;
2572 executable_statement_dereference (result, MDL);
2573 return 0;
2575 if (!parse_executable_statements (&(*result) -> data.ie.tc,
2576 cfile, lose, context_any)) {
2577 if (*lose) {
2578 /* Try to even things up. */
2579 do {
2580 token = next_token (&val,
2581 (unsigned *)0, cfile);
2582 } while (token != END_OF_FILE && token != RBRACE);
2583 executable_statement_dereference (result, MDL);
2584 return 0;
2587 token = next_token (&val, (unsigned *)0, cfile);
2588 if (token != RBRACE) {
2589 parse_warn (cfile, "right brace expected.");
2590 skip_to_semi (cfile);
2591 *lose = 1;
2592 executable_statement_dereference (result, MDL);
2593 return 0;
2595 token = peek_token (&val, (unsigned *)0, cfile);
2596 if (token == ELSE) {
2597 token = next_token (&val, (unsigned *)0, cfile);
2598 token = peek_token (&val, (unsigned *)0, cfile);
2599 if (token == IF) {
2600 token = next_token (&val, (unsigned *)0, cfile);
2601 if (!parse_if_statement (&(*result) -> data.ie.fc,
2602 cfile, lose)) {
2603 if (!*lose)
2604 parse_warn (cfile,
2605 "expecting if statement");
2606 executable_statement_dereference (result, MDL);
2607 *lose = 1;
2608 return 0;
2610 } else if (token != LBRACE) {
2611 parse_warn (cfile, "left brace or if expected.");
2612 skip_to_semi (cfile);
2613 *lose = 1;
2614 executable_statement_dereference (result, MDL);
2615 return 0;
2616 } else {
2617 token = next_token (&val, (unsigned *)0, cfile);
2618 if (!(parse_executable_statements
2619 (&(*result) -> data.ie.fc,
2620 cfile, lose, context_any))) {
2621 executable_statement_dereference (result, MDL);
2622 return 0;
2624 token = next_token (&val, (unsigned *)0, cfile);
2625 if (token != RBRACE) {
2626 parse_warn (cfile, "right brace expected.");
2627 skip_to_semi (cfile);
2628 *lose = 1;
2629 executable_statement_dereference (result, MDL);
2630 return 0;
2633 } else if (token == ELSIF) {
2634 token = next_token (&val, (unsigned *)0, cfile);
2635 if (!parse_if_statement (&(*result) -> data.ie.fc,
2636 cfile, lose)) {
2637 if (!*lose)
2638 parse_warn (cfile,
2639 "expecting conditional.");
2640 executable_statement_dereference (result, MDL);
2641 *lose = 1;
2642 return 0;
2644 } else
2645 (*result) -> data.ie.fc = (struct executable_statement *)0;
2647 return 1;
2651 * boolean_expression :== CHECK STRING |
2652 * NOT boolean-expression |
2653 * data-expression EQUAL data-expression |
2654 * data-expression BANG EQUAL data-expression |
2655 * boolean-expression AND boolean-expression |
2656 * boolean-expression OR boolean-expression
2657 * EXISTS OPTION-NAME
2660 int parse_boolean_expression (expr, cfile, lose)
2661 struct expression **expr;
2662 struct parse *cfile;
2663 int *lose;
2665 /* Parse an expression... */
2666 if (!parse_expression (expr, cfile, lose, context_boolean,
2667 (struct expression **)0, expr_none))
2668 return 0;
2670 if (!is_boolean_expression (*expr) &&
2671 (*expr) -> op != expr_variable_reference &&
2672 (*expr) -> op != expr_funcall) {
2673 parse_warn (cfile, "Expecting a boolean expression.");
2674 *lose = 1;
2675 expression_dereference (expr, MDL);
2676 return 0;
2678 return 1;
2682 * data_expression :== SUBSTRING LPAREN data-expression COMMA
2683 * numeric-expression COMMA
2684 * numeric-expression RPAREN |
2685 * CONCAT LPAREN data-expression COMMA
2686 data-expression RPAREN
2687 * SUFFIX LPAREN data_expression COMMA
2688 * numeric-expression RPAREN |
2689 * OPTION option_name |
2690 * HARDWARE |
2691 * PACKET LPAREN numeric-expression COMMA
2692 * numeric-expression RPAREN |
2693 * STRING |
2694 * colon_seperated_hex_list
2697 int parse_data_expression (expr, cfile, lose)
2698 struct expression **expr;
2699 struct parse *cfile;
2700 int *lose;
2702 /* Parse an expression... */
2703 if (!parse_expression (expr, cfile, lose, context_data,
2704 (struct expression **)0, expr_none))
2705 return 0;
2707 if (!is_data_expression (*expr) &&
2708 (*expr) -> op != expr_variable_reference &&
2709 (*expr) -> op != expr_funcall) {
2710 expression_dereference (expr, MDL);
2711 parse_warn (cfile, "Expecting a data expression.");
2712 *lose = 1;
2713 return 0;
2715 return 1;
2719 * numeric-expression :== EXTRACT_INT LPAREN data-expression
2720 * COMMA number RPAREN |
2721 * NUMBER
2724 int parse_numeric_expression (expr, cfile, lose)
2725 struct expression **expr;
2726 struct parse *cfile;
2727 int *lose;
2729 /* Parse an expression... */
2730 if (!parse_expression (expr, cfile, lose, context_numeric,
2731 (struct expression **)0, expr_none))
2732 return 0;
2734 if (!is_numeric_expression (*expr) &&
2735 (*expr) -> op != expr_variable_reference &&
2736 (*expr) -> op != expr_funcall) {
2737 expression_dereference (expr, MDL);
2738 parse_warn (cfile, "Expecting a numeric expression.");
2739 *lose = 1;
2740 return 0;
2742 return 1;
2746 * dns-expression :==
2747 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2748 * data-expression COMMA numeric-expression RPAREN
2749 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2750 * data-expression RPAREN
2751 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2752 * data-expression RPAREN
2753 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2754 * data-expression RPAREN
2755 * ns-class :== IN | CHAOS | HS | NUMBER
2756 * ns-type :== A | PTR | MX | TXT | NUMBER
2759 int parse_dns_expression (expr, cfile, lose)
2760 struct expression **expr;
2761 struct parse *cfile;
2762 int *lose;
2764 /* Parse an expression... */
2765 if (!parse_expression (expr, cfile, lose, context_dns,
2766 (struct expression **)0, expr_none))
2767 return 0;
2769 if (!is_dns_expression (*expr) &&
2770 (*expr) -> op != expr_variable_reference &&
2771 (*expr) -> op != expr_funcall) {
2772 expression_dereference (expr, MDL);
2773 parse_warn (cfile, "Expecting a dns update subexpression.");
2774 *lose = 1;
2775 return 0;
2777 return 1;
2780 /* Parse a subexpression that does not contain a binary operator. */
2782 int parse_non_binary (expr, cfile, lose, context)
2783 struct expression **expr;
2784 struct parse *cfile;
2785 int *lose;
2786 enum expression_context context;
2788 enum dhcp_token token;
2789 const char *val;
2790 struct collection *col;
2791 struct option *option;
2792 struct expression *nexp, **ep;
2793 int known;
2794 enum expr_op opcode;
2795 const char *s;
2796 char *cptr;
2797 struct executable_statement *stmt;
2798 int i;
2799 unsigned long u;
2800 isc_result_t status, code;
2801 unsigned len;
2803 token = peek_token (&val, (unsigned *)0, cfile);
2805 /* Check for unary operators... */
2806 switch (token) {
2807 case CHECK:
2808 token = next_token (&val, (unsigned *)0, cfile);
2809 token = next_token (&val, (unsigned *)0, cfile);
2810 if (token != STRING) {
2811 parse_warn (cfile, "string expected.");
2812 skip_to_semi (cfile);
2813 *lose = 1;
2814 return 0;
2816 for (col = collections; col; col = col -> next)
2817 if (!strcmp (col -> name, val))
2818 break;
2819 if (!col) {
2820 parse_warn (cfile, "unknown collection.");
2821 *lose = 1;
2822 return 0;
2824 if (!expression_allocate (expr, MDL))
2825 log_fatal ("can't allocate expression");
2826 (*expr) -> op = expr_check;
2827 (*expr) -> data.check = col;
2828 break;
2830 case TOKEN_NOT:
2831 token = next_token (&val, (unsigned *)0, cfile);
2832 if (context == context_dns) {
2833 token = peek_token (&val, (unsigned *)0, cfile);
2834 goto not_exists;
2836 if (!expression_allocate (expr, MDL))
2837 log_fatal ("can't allocate expression");
2838 (*expr) -> op = expr_not;
2839 if (!parse_non_binary (&(*expr) -> data.not,
2840 cfile, lose, context_boolean)) {
2841 if (!*lose) {
2842 parse_warn (cfile, "expression expected");
2843 skip_to_semi (cfile);
2845 *lose = 1;
2846 expression_dereference (expr, MDL);
2847 return 0;
2849 if (!is_boolean_expression ((*expr) -> data.not)) {
2850 *lose = 1;
2851 parse_warn (cfile, "boolean expression expected");
2852 skip_to_semi (cfile);
2853 expression_dereference (expr, MDL);
2854 return 0;
2856 break;
2858 case LPAREN:
2859 token = next_token (&val, (unsigned *)0, cfile);
2860 if (!parse_expression (expr, cfile, lose, context,
2861 (struct expression **)0, expr_none)) {
2862 if (!*lose) {
2863 parse_warn (cfile, "expression expected");
2864 skip_to_semi (cfile);
2866 *lose = 1;
2867 return 0;
2869 token = next_token (&val, (unsigned *)0, cfile);
2870 if (token != RPAREN) {
2871 *lose = 1;
2872 parse_warn (cfile, "right paren expected");
2873 skip_to_semi (cfile);
2874 return 0;
2876 break;
2878 case EXISTS:
2879 if (context == context_dns)
2880 goto ns_exists;
2881 token = next_token (&val, (unsigned *)0, cfile);
2882 if (!expression_allocate (expr, MDL))
2883 log_fatal ("can't allocate expression");
2884 (*expr) -> op = expr_exists;
2885 known = 0;
2886 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
2887 if (!(*expr) -> data.option) {
2888 *lose = 1;
2889 expression_dereference (expr, MDL);
2890 return 0;
2892 break;
2894 case STATIC:
2895 token = next_token (&val, (unsigned *)0, cfile);
2896 if (!expression_allocate (expr, MDL))
2897 log_fatal ("can't allocate expression");
2898 (*expr) -> op = expr_static;
2899 break;
2901 case KNOWN:
2902 token = next_token (&val, (unsigned *)0, cfile);
2903 if (!expression_allocate (expr, MDL))
2904 log_fatal ("can't allocate expression");
2905 (*expr) -> op = expr_known;
2906 break;
2908 case SUBSTRING:
2909 token = next_token (&val, (unsigned *)0, cfile);
2910 if (!expression_allocate (expr, MDL))
2911 log_fatal ("can't allocate expression");
2912 (*expr) -> op = expr_substring;
2914 token = next_token (&val, (unsigned *)0, cfile);
2915 if (token != LPAREN) {
2916 nolparen:
2917 expression_dereference (expr, MDL);
2918 parse_warn (cfile, "left parenthesis expected.");
2919 *lose = 1;
2920 return 0;
2923 if (!parse_data_expression (&(*expr) -> data.substring.expr,
2924 cfile, lose)) {
2925 nodata:
2926 expression_dereference (expr, MDL);
2927 if (!*lose) {
2928 parse_warn (cfile,
2929 "expecting data expression.");
2930 skip_to_semi (cfile);
2931 *lose = 1;
2933 return 0;
2936 token = next_token (&val, (unsigned *)0, cfile);
2937 if (token != COMMA) {
2938 nocomma:
2939 expression_dereference (expr, MDL);
2940 parse_warn (cfile, "comma expected.");
2941 *lose = 1;
2943 return 0;
2946 if (!parse_numeric_expression
2947 (&(*expr) -> data.substring.offset,cfile, lose)) {
2948 nonum:
2949 if (!*lose) {
2950 parse_warn (cfile,
2951 "expecting numeric expression.");
2952 skip_to_semi (cfile);
2953 *lose = 1;
2955 expression_dereference (expr, MDL);
2956 return 0;
2959 token = next_token (&val, (unsigned *)0, cfile);
2960 if (token != COMMA)
2961 goto nocomma;
2963 if (!parse_numeric_expression
2964 (&(*expr) -> data.substring.len, cfile, lose))
2965 goto nonum;
2967 token = next_token (&val, (unsigned *)0, cfile);
2968 if (token != RPAREN) {
2969 norparen:
2970 parse_warn (cfile, "right parenthesis expected.");
2971 *lose = 1;
2972 expression_dereference (expr, MDL);
2973 return 0;
2975 break;
2977 case SUFFIX:
2978 token = next_token (&val, (unsigned *)0, cfile);
2979 if (!expression_allocate (expr, MDL))
2980 log_fatal ("can't allocate expression");
2981 (*expr) -> op = expr_suffix;
2983 token = next_token (&val, (unsigned *)0, cfile);
2984 if (token != LPAREN)
2985 goto nolparen;
2987 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
2988 cfile, lose))
2989 goto nodata;
2991 token = next_token (&val, (unsigned *)0, cfile);
2992 if (token != COMMA)
2993 goto nocomma;
2995 if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
2996 cfile, lose))
2997 goto nonum;
2999 token = next_token (&val, (unsigned *)0, cfile);
3000 if (token != RPAREN)
3001 goto norparen;
3002 break;
3004 case CONCAT:
3005 token = next_token (&val, (unsigned *)0, cfile);
3006 if (!expression_allocate (expr, MDL))
3007 log_fatal ("can't allocate expression");
3008 (*expr) -> op = expr_concat;
3010 token = next_token (&val, (unsigned *)0, cfile);
3011 if (token != LPAREN)
3012 goto nolparen;
3014 if (!parse_data_expression (&(*expr) -> data.concat [0],
3015 cfile, lose))
3016 goto nodata;
3018 token = next_token (&val, (unsigned *)0, cfile);
3019 if (token != COMMA)
3020 goto nocomma;
3022 concat_another:
3023 if (!parse_data_expression (&(*expr) -> data.concat [1],
3024 cfile, lose))
3025 goto nodata;
3027 token = next_token (&val, (unsigned *)0, cfile);
3029 if (token == COMMA) {
3030 nexp = (struct expression *)0;
3031 if (!expression_allocate (&nexp, MDL))
3032 log_fatal ("can't allocate at CONCAT2");
3033 nexp -> op = expr_concat;
3034 expression_reference (&nexp -> data.concat [0],
3035 *expr, MDL);
3036 expression_dereference (expr, MDL);
3037 expression_reference (expr, nexp, MDL);
3038 expression_dereference (&nexp, MDL);
3039 goto concat_another;
3042 if (token != RPAREN)
3043 goto norparen;
3044 break;
3046 case BINARY_TO_ASCII:
3047 token = next_token (&val, (unsigned *)0, cfile);
3048 if (!expression_allocate (expr, MDL))
3049 log_fatal ("can't allocate expression");
3050 (*expr) -> op = expr_binary_to_ascii;
3052 token = next_token (&val, (unsigned *)0, cfile);
3053 if (token != LPAREN)
3054 goto nolparen;
3056 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3057 cfile, lose))
3058 goto nodata;
3060 token = next_token (&val, (unsigned *)0, cfile);
3061 if (token != COMMA)
3062 goto nocomma;
3064 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3065 cfile, lose))
3066 goto nodata;
3068 token = next_token (&val, (unsigned *)0, cfile);
3069 if (token != COMMA)
3070 goto nocomma;
3072 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
3073 cfile, lose))
3074 goto nodata;
3076 token = next_token (&val, (unsigned *)0, cfile);
3077 if (token != COMMA)
3078 goto nocomma;
3080 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3081 cfile, lose))
3082 goto nodata;
3084 token = next_token (&val, (unsigned *)0, cfile);
3085 if (token != RPAREN)
3086 goto norparen;
3087 break;
3089 case REVERSE:
3090 token = next_token (&val, (unsigned *)0, cfile);
3091 if (!expression_allocate (expr, MDL))
3092 log_fatal ("can't allocate expression");
3093 (*expr) -> op = expr_reverse;
3095 token = next_token (&val, (unsigned *)0, cfile);
3096 if (token != LPAREN)
3097 goto nolparen;
3099 if (!(parse_numeric_expression
3100 (&(*expr) -> data.reverse.width, cfile, lose)))
3101 goto nodata;
3103 token = next_token (&val, (unsigned *)0, cfile);
3104 if (token != COMMA)
3105 goto nocomma;
3107 if (!(parse_data_expression
3108 (&(*expr) -> data.reverse.buffer, cfile, lose)))
3109 goto nodata;
3111 token = next_token (&val, (unsigned *)0, cfile);
3112 if (token != RPAREN)
3113 goto norparen;
3114 break;
3116 case PICK:
3117 /* pick (a, b, c) actually produces an internal representation
3118 that looks like pick (a, pick (b, pick (c, nil))). */
3119 token = next_token (&val, (unsigned *)0, cfile);
3120 if (!(expression_allocate (expr, MDL)))
3121 log_fatal ("can't allocate expression");
3123 token = next_token (&val, (unsigned *)0, cfile);
3124 if (token != LPAREN)
3125 goto nolparen;
3127 nexp = (struct expression *)0;
3128 expression_reference (&nexp, *expr, MDL);
3129 do {
3130 nexp -> op = expr_pick_first_value;
3131 if (!(parse_data_expression
3132 (&nexp -> data.pick_first_value.car,
3133 cfile, lose)))
3134 goto nodata;
3136 token = next_token (&val, (unsigned *)0, cfile);
3137 if (token == COMMA) {
3138 struct expression *foo = (struct expression *)0;
3139 if (!expression_allocate (&foo, MDL))
3140 log_fatal ("can't allocate expr");
3141 expression_reference
3142 (&nexp -> data.pick_first_value.cdr, foo, MDL);
3143 expression_dereference (&nexp, MDL);
3144 expression_reference (&nexp, foo, MDL);
3145 expression_dereference (&foo, MDL);
3147 } while (token == COMMA);
3148 expression_dereference (&nexp, MDL);
3150 if (token != RPAREN)
3151 goto norparen;
3152 break;
3154 /* dns-update and dns-delete are present for historical
3155 purposes, but are deprecated in favor of ns-update
3156 in combination with update, delete, exists and not
3157 exists. */
3158 case DNS_UPDATE:
3159 case DNS_DELETE:
3160 #if !defined (NSUPDATE)
3161 parse_warn (cfile,
3162 "Please rebuild dhcpd with --with-nsupdate.");
3163 #endif
3164 token = next_token (&val, (unsigned *)0, cfile);
3165 if (token == DNS_UPDATE)
3166 opcode = expr_ns_add;
3167 else
3168 opcode = expr_ns_delete;
3170 token = next_token (&val, (unsigned *)0, cfile);
3171 if (token != LPAREN)
3172 goto nolparen;
3174 token = next_token (&val, (unsigned *)0, cfile);
3175 if (token != STRING) {
3176 parse_warn (cfile,
3177 "parse_expression: expecting string.");
3178 badnsupdate:
3179 skip_to_semi (cfile);
3180 *lose = 1;
3181 return 0;
3184 if (!strcasecmp (val, "a"))
3185 u = T_A;
3186 else if (!strcasecmp (val, "ptr"))
3187 u = T_PTR;
3188 else if (!strcasecmp (val, "mx"))
3189 u = T_MX;
3190 else if (!strcasecmp (val, "cname"))
3191 u = T_CNAME;
3192 else if (!strcasecmp (val, "TXT"))
3193 u = T_TXT;
3194 else {
3195 parse_warn (cfile, "unexpected rrtype: %s", val);
3196 goto badnsupdate;
3199 s = (opcode == expr_ns_add
3200 ? "old-dns-update"
3201 : "old-dns-delete");
3202 cptr = dmalloc (strlen (s) + 1, MDL);
3203 if (!cptr)
3204 log_fatal ("can't allocate name for %s", s);
3205 strcpy (cptr, s);
3206 if (!expression_allocate (expr, MDL))
3207 log_fatal ("can't allocate expression");
3208 (*expr) -> op = expr_funcall;
3209 (*expr) -> data.funcall.name = cptr;
3211 /* Fake up a function call. */
3212 ep = &(*expr) -> data.funcall.arglist;
3213 if (!expression_allocate (ep, MDL))
3214 log_fatal ("can't allocate expression");
3215 (*ep) -> op = expr_arg;
3216 if (!make_const_int (&(*ep) -> data.arg.val, u))
3217 log_fatal ("can't allocate rrtype value.");
3219 token = next_token (&val, (unsigned *)0, cfile);
3220 if (token != COMMA)
3221 goto nocomma;
3222 ep = &((*ep) -> data.arg.next);
3223 if (!expression_allocate (ep, MDL))
3224 log_fatal ("can't allocate expression");
3225 (*ep) -> op = expr_arg;
3226 if (!(parse_data_expression (&(*ep) -> data.arg.val,
3227 cfile, lose)))
3228 goto nodata;
3230 token = next_token (&val, (unsigned *)0, cfile);
3231 if (token != COMMA)
3232 goto nocomma;
3234 ep = &((*ep) -> data.arg.next);
3235 if (!expression_allocate (ep, MDL))
3236 log_fatal ("can't allocate expression");
3237 (*ep) -> op = expr_arg;
3238 if (!(parse_data_expression (&(*ep) -> data.arg.val,
3239 cfile, lose)))
3240 goto nodata;
3242 if (opcode == expr_ns_add) {
3243 token = next_token (&val, (unsigned *)0, cfile);
3244 if (token != COMMA)
3245 goto nocomma;
3247 ep = &((*ep) -> data.arg.next);
3248 if (!expression_allocate (ep, MDL))
3249 log_fatal ("can't allocate expression");
3250 (*ep) -> op = expr_arg;
3251 if (!(parse_numeric_expression (&(*ep) -> data.arg.val,
3252 cfile, lose))) {
3253 parse_warn (cfile,
3254 "expecting numeric expression.");
3255 goto badnsupdate;
3259 token = next_token (&val, (unsigned *)0, cfile);
3260 if (token != RPAREN)
3261 goto norparen;
3262 break;
3264 case NS_UPDATE:
3265 #if !defined (NSUPDATE)
3266 parse_warn (cfile,
3267 "Please rebuild dhcpd with --with-nsupdate.");
3268 #endif
3269 token = next_token (&val, (unsigned *)0, cfile);
3270 if (!expression_allocate (expr, MDL))
3271 log_fatal ("can't allocate expression");
3273 token = next_token (&val, (unsigned *)0, cfile);
3274 if (token != LPAREN)
3275 goto nolparen;
3277 nexp = *expr;
3278 do {
3279 nexp -> op = expr_dns_transaction;
3280 if (!(parse_dns_expression
3281 (&nexp -> data.dns_transaction.car,
3282 cfile, lose)))
3284 if (!*lose)
3285 parse_warn
3286 (cfile,
3287 "expecting dns expression.");
3288 badnstrans:
3289 expression_dereference (expr, MDL);
3290 *lose = 1;
3291 return 0;
3294 token = next_token (&val, (unsigned *)0, cfile);
3296 if (token == COMMA) {
3297 if (!(expression_allocate
3298 (&nexp -> data.dns_transaction.cdr,
3299 MDL)))
3300 log_fatal
3301 ("can't allocate expression");
3302 nexp = nexp -> data.dns_transaction.cdr;
3304 } while (token == COMMA);
3306 if (token != RPAREN)
3307 goto norparen;
3308 break;
3310 /* NOT EXISTS is special cased above... */
3311 not_exists:
3312 token = peek_token (&val, (unsigned *)0, cfile);
3313 if (token != EXISTS) {
3314 parse_warn (cfile, "expecting DNS prerequisite.");
3315 *lose = 1;
3316 return 0;
3318 opcode = expr_ns_not_exists;
3319 goto nsupdatecode;
3320 case TOKEN_ADD:
3321 opcode = expr_ns_add;
3322 goto nsupdatecode;
3323 case TOKEN_DELETE:
3324 opcode = expr_ns_delete;
3325 goto nsupdatecode;
3326 ns_exists:
3327 opcode = expr_ns_exists;
3328 nsupdatecode:
3329 token = next_token (&val, (unsigned *)0, cfile);
3331 #if !defined (NSUPDATE)
3332 parse_warn (cfile,
3333 "Please rebuild dhcpd with --with-nsupdate.");
3334 #endif
3335 if (!expression_allocate (expr, MDL))
3336 log_fatal ("can't allocate expression");
3337 (*expr) -> op = opcode;
3339 token = next_token (&val, (unsigned *)0, cfile);
3340 if (token != LPAREN)
3341 goto nolparen;
3343 token = next_token (&val, (unsigned *)0, cfile);
3344 if (!is_identifier (token) && token != NUMBER) {
3345 parse_warn (cfile, "expecting identifier or number.");
3346 badnsop:
3347 expression_dereference (expr, MDL);
3348 skip_to_semi (cfile);
3349 *lose = 1;
3350 return 0;
3353 if (token == NUMBER)
3354 (*expr) -> data.ns_add.rrclass = atoi (val);
3355 else if (!strcasecmp (val, "in"))
3356 (*expr) -> data.ns_add.rrclass = C_IN;
3357 else if (!strcasecmp (val, "chaos"))
3358 (*expr) -> data.ns_add.rrclass = C_CHAOS;
3359 else if (!strcasecmp (val, "hs"))
3360 (*expr) -> data.ns_add.rrclass = C_HS;
3361 else {
3362 parse_warn (cfile, "unexpected rrclass: %s", val);
3363 goto badnsop;
3366 token = next_token (&val, (unsigned *)0, cfile);
3367 if (token != COMMA)
3368 goto nocomma;
3370 token = next_token (&val, (unsigned *)0, cfile);
3371 if (!is_identifier (token) && token != NUMBER) {
3372 parse_warn (cfile, "expecting identifier or number.");
3373 goto badnsop;
3376 if (token == NUMBER)
3377 (*expr) -> data.ns_add.rrtype = atoi (val);
3378 else if (!strcasecmp (val, "a"))
3379 (*expr) -> data.ns_add.rrtype = T_A;
3380 else if (!strcasecmp (val, "ptr"))
3381 (*expr) -> data.ns_add.rrtype = T_PTR;
3382 else if (!strcasecmp (val, "mx"))
3383 (*expr) -> data.ns_add.rrtype = T_MX;
3384 else if (!strcasecmp (val, "cname"))
3385 (*expr) -> data.ns_add.rrtype = T_CNAME;
3386 else if (!strcasecmp (val, "TXT"))
3387 (*expr) -> data.ns_add.rrtype = T_TXT;
3388 else {
3389 parse_warn (cfile, "unexpected rrtype: %s", val);
3390 goto badnsop;
3393 token = next_token (&val, (unsigned *)0, cfile);
3394 if (token != COMMA)
3395 goto nocomma;
3397 if (!(parse_data_expression
3398 (&(*expr) -> data.ns_add.rrname, cfile, lose)))
3399 goto nodata;
3401 token = next_token (&val, (unsigned *)0, cfile);
3402 if (token != COMMA)
3403 goto nocomma;
3405 if (!(parse_data_expression
3406 (&(*expr) -> data.ns_add.rrdata, cfile, lose)))
3407 goto nodata;
3409 if (opcode == expr_ns_add) {
3410 token = next_token (&val, (unsigned *)0, cfile);
3411 if (token != COMMA)
3412 goto nocomma;
3414 if (!(parse_numeric_expression
3415 (&(*expr) -> data.ns_add.ttl, cfile,
3416 lose))) {
3417 if (!*lose)
3418 parse_warn (cfile,
3419 "expecting numeric expression.");
3420 goto badnsupdate;
3424 token = next_token (&val, (unsigned *)0, cfile);
3425 if (token != RPAREN)
3426 goto norparen;
3427 break;
3429 case OPTION:
3430 case CONFIG_OPTION:
3431 if (!expression_allocate (expr, MDL))
3432 log_fatal ("can't allocate expression");
3433 (*expr) -> op = (token == OPTION
3434 ? expr_option
3435 : expr_config_option);
3436 token = next_token (&val, (unsigned *)0, cfile);
3437 known = 0;
3438 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
3439 if (!(*expr) -> data.option) {
3440 *lose = 1;
3441 expression_dereference (expr, MDL);
3442 return 0;
3444 break;
3446 case HARDWARE:
3447 token = next_token (&val, (unsigned *)0, cfile);
3448 if (!expression_allocate (expr, MDL))
3449 log_fatal ("can't allocate expression");
3450 (*expr) -> op = expr_hardware;
3451 break;
3453 case LEASED_ADDRESS:
3454 token = next_token (&val, (unsigned *)0, cfile);
3455 if (!expression_allocate (expr, MDL))
3456 log_fatal ("can't allocate expression");
3457 (*expr) -> op = expr_leased_address;
3458 break;
3460 case CLIENT_STATE:
3461 token = next_token (&val, (unsigned *)0, cfile);
3462 if (!expression_allocate (expr, MDL))
3463 log_fatal ("can't allocate expression");
3464 (*expr) -> op = expr_client_state;
3465 break;
3467 case FILENAME:
3468 token = next_token (&val, (unsigned *)0, cfile);
3469 if (!expression_allocate (expr, MDL))
3470 log_fatal ("can't allocate expression");
3471 (*expr) -> op = expr_filename;
3472 break;
3474 case SERVER_NAME:
3475 token = next_token (&val, (unsigned *)0, cfile);
3476 if (!expression_allocate (expr, MDL))
3477 log_fatal ("can't allocate expression");
3478 (*expr) -> op = expr_sname;
3479 break;
3481 case LEASE_TIME:
3482 token = next_token (&val, (unsigned *)0, cfile);
3483 if (!expression_allocate (expr, MDL))
3484 log_fatal ("can't allocate expression");
3485 (*expr) -> op = expr_lease_time;
3486 break;
3488 case TOKEN_NULL:
3489 token = next_token (&val, (unsigned *)0, cfile);
3490 if (!expression_allocate (expr, MDL))
3491 log_fatal ("can't allocate expression");
3492 (*expr) -> op = expr_null;
3493 break;
3495 case HOST_DECL_NAME:
3496 token = next_token (&val, (unsigned *)0, cfile);
3497 if (!expression_allocate (expr, MDL))
3498 log_fatal ("can't allocate expression");
3499 (*expr) -> op = expr_host_decl_name;
3500 break;
3502 case UPDATED_DNS_RR:
3503 token = next_token (&val, (unsigned *)0, cfile);
3505 token = next_token (&val, (unsigned *)0, cfile);
3506 if (token != LPAREN)
3507 goto nolparen;
3509 token = next_token (&val, (unsigned *)0, cfile);
3510 if (token != STRING) {
3511 parse_warn (cfile, "expecting string.");
3512 bad_rrtype:
3513 *lose = 1;
3514 return 0;
3516 if (!strcasecmp (val, "a"))
3517 s = "ddns-fwd-name";
3518 else if (!strcasecmp (val, "ptr"))
3519 s = "ddns-rev-name";
3520 else {
3521 parse_warn (cfile, "invalid DNS rrtype: %s", val);
3522 goto bad_rrtype;
3525 token = next_token (&val, (unsigned *)0, cfile);
3526 if (token != RPAREN)
3527 goto norparen;
3529 if (!expression_allocate (expr, MDL))
3530 log_fatal ("can't allocate expression");
3531 (*expr) -> op = expr_variable_reference;
3532 (*expr) -> data.variable =
3533 dmalloc (strlen (s) + 1, MDL);
3534 if (!(*expr) -> data.variable)
3535 log_fatal ("can't allocate variable name.");
3536 strcpy ((*expr) -> data.variable, s);
3537 break;
3539 case PACKET:
3540 token = next_token (&val, (unsigned *)0, cfile);
3541 if (!expression_allocate (expr, MDL))
3542 log_fatal ("can't allocate expression");
3543 (*expr) -> op = expr_packet;
3545 token = next_token (&val, (unsigned *)0, cfile);
3546 if (token != LPAREN)
3547 goto nolparen;
3549 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
3550 cfile, lose))
3551 goto nonum;
3553 token = next_token (&val, (unsigned *)0, cfile);
3554 if (token != COMMA)
3555 goto nocomma;
3557 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
3558 cfile, lose))
3559 goto nonum;
3561 token = next_token (&val, (unsigned *)0, cfile);
3562 if (token != RPAREN)
3563 goto norparen;
3564 break;
3566 case STRING:
3567 token = next_token (&val, &len, cfile);
3568 if (!make_const_data (expr, (const unsigned char *)val,
3569 len, 1, 1, MDL))
3570 log_fatal ("can't make constant string expression.");
3571 break;
3573 case EXTRACT_INT:
3574 token = next_token (&val, (unsigned *)0, cfile);
3575 token = next_token (&val, (unsigned *)0, cfile);
3576 if (token != LPAREN) {
3577 parse_warn (cfile, "left parenthesis expected.");
3578 *lose = 1;
3579 return 0;
3582 if (!expression_allocate (expr, MDL))
3583 log_fatal ("can't allocate expression");
3585 if (!parse_data_expression (&(*expr) -> data.extract_int,
3586 cfile, lose)) {
3587 if (!*lose) {
3588 parse_warn (cfile,
3589 "expecting data expression.");
3590 skip_to_semi (cfile);
3591 *lose = 1;
3593 expression_dereference (expr, MDL);
3594 return 0;
3597 token = next_token (&val, (unsigned *)0, cfile);
3598 if (token != COMMA) {
3599 parse_warn (cfile, "comma expected.");
3600 *lose = 1;
3601 expression_dereference (expr, MDL);
3602 return 0;
3605 token = next_token (&val, (unsigned *)0, cfile);
3606 if (token != NUMBER) {
3607 parse_warn (cfile, "number expected.");
3608 *lose = 1;
3609 expression_dereference (expr, MDL);
3610 return 0;
3612 switch (atoi (val)) {
3613 case 8:
3614 (*expr) -> op = expr_extract_int8;
3615 break;
3617 case 16:
3618 (*expr) -> op = expr_extract_int16;
3619 break;
3621 case 32:
3622 (*expr) -> op = expr_extract_int32;
3623 break;
3625 default:
3626 parse_warn (cfile,
3627 "unsupported integer size %d", atoi (val));
3628 *lose = 1;
3629 skip_to_semi (cfile);
3630 expression_dereference (expr, MDL);
3631 return 0;
3634 token = next_token (&val, (unsigned *)0, cfile);
3635 if (token != RPAREN) {
3636 parse_warn (cfile, "right parenthesis expected.");
3637 *lose = 1;
3638 expression_dereference (expr, MDL);
3639 return 0;
3641 break;
3643 case ENCODE_INT:
3644 token = next_token (&val, (unsigned *)0, cfile);
3645 token = next_token (&val, (unsigned *)0, cfile);
3646 if (token != LPAREN) {
3647 parse_warn (cfile, "left parenthesis expected.");
3648 *lose = 1;
3649 return 0;
3652 if (!expression_allocate (expr, MDL))
3653 log_fatal ("can't allocate expression");
3655 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
3656 cfile, lose)) {
3657 parse_warn (cfile, "expecting numeric expression.");
3658 skip_to_semi (cfile);
3659 *lose = 1;
3660 expression_dereference (expr, MDL);
3661 return 0;
3664 token = next_token (&val, (unsigned *)0, cfile);
3665 if (token != COMMA) {
3666 parse_warn (cfile, "comma expected.");
3667 *lose = 1;
3668 expression_dereference (expr, MDL);
3669 return 0;
3672 token = next_token (&val, (unsigned *)0, cfile);
3673 if (token != NUMBER) {
3674 parse_warn (cfile, "number expected.");
3675 *lose = 1;
3676 expression_dereference (expr, MDL);
3677 return 0;
3679 switch (atoi (val)) {
3680 case 8:
3681 (*expr) -> op = expr_encode_int8;
3682 break;
3684 case 16:
3685 (*expr) -> op = expr_encode_int16;
3686 break;
3688 case 32:
3689 (*expr) -> op = expr_encode_int32;
3690 break;
3692 default:
3693 parse_warn (cfile,
3694 "unsupported integer size %d", atoi (val));
3695 *lose = 1;
3696 skip_to_semi (cfile);
3697 expression_dereference (expr, MDL);
3698 return 0;
3701 token = next_token (&val, (unsigned *)0, cfile);
3702 if (token != RPAREN) {
3703 parse_warn (cfile, "right parenthesis expected.");
3704 *lose = 1;
3705 expression_dereference (expr, MDL);
3706 return 0;
3708 break;
3710 case NUMBER:
3711 /* If we're in a numeric context, this should just be a
3712 number, by itself. */
3713 if (context == context_numeric ||
3714 context == context_data_or_numeric) {
3715 next_token (&val, (unsigned *)0, cfile);
3716 if (!expression_allocate (expr, MDL))
3717 log_fatal ("can't allocate expression");
3718 (*expr) -> op = expr_const_int;
3719 (*expr) -> data.const_int = atoi (val);
3720 break;
3723 case NUMBER_OR_NAME:
3724 if (!expression_allocate (expr, MDL))
3725 log_fatal ("can't allocate expression");
3727 (*expr) -> op = expr_const_data;
3728 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
3729 expression_dereference (expr, MDL);
3730 return 0;
3732 break;
3734 case NS_FORMERR:
3735 known = FORMERR;
3736 goto ns_const;
3737 ns_const:
3738 token = next_token (&val, (unsigned *)0, cfile);
3739 if (!expression_allocate (expr, MDL))
3740 log_fatal ("can't allocate expression");
3741 (*expr) -> op = expr_const_int;
3742 (*expr) -> data.const_int = known;
3743 break;
3745 case NS_NOERROR:
3746 known = ISC_R_SUCCESS;
3747 goto ns_const;
3749 case NS_NOTAUTH:
3750 known = ISC_R_NOTAUTH;
3751 goto ns_const;
3753 case NS_NOTIMP:
3754 known = ISC_R_NOTIMPLEMENTED;
3755 goto ns_const;
3757 case NS_NOTZONE:
3758 known = ISC_R_NOTZONE;
3759 goto ns_const;
3761 case NS_NXDOMAIN:
3762 known = ISC_R_NXDOMAIN;
3763 goto ns_const;
3765 case NS_NXRRSET:
3766 known = ISC_R_NXRRSET;
3767 goto ns_const;
3769 case NS_REFUSED:
3770 known = ISC_R_REFUSED;
3771 goto ns_const;
3773 case NS_SERVFAIL:
3774 known = ISC_R_SERVFAIL;
3775 goto ns_const;
3777 case NS_YXDOMAIN:
3778 known = ISC_R_YXDOMAIN;
3779 goto ns_const;
3781 case NS_YXRRSET:
3782 known = ISC_R_YXRRSET;
3783 goto ns_const;
3785 case BOOTING:
3786 known = S_INIT;
3787 goto ns_const;
3789 case REBOOT:
3790 known = S_REBOOTING;
3791 goto ns_const;
3793 case SELECT:
3794 known = S_SELECTING;
3795 goto ns_const;
3797 case REQUEST:
3798 known = S_REQUESTING;
3799 goto ns_const;
3801 case BOUND:
3802 known = S_BOUND;
3803 goto ns_const;
3805 case RENEW:
3806 known = S_RENEWING;
3807 goto ns_const;
3809 case REBIND:
3810 known = S_REBINDING;
3811 goto ns_const;
3813 case DEFINED:
3814 token = next_token (&val, (unsigned *)0, cfile);
3815 token = next_token (&val, (unsigned *)0, cfile);
3816 if (token != LPAREN)
3817 goto nolparen;
3819 token = next_token (&val, (unsigned *)0, cfile);
3820 if (token != NAME && token != NUMBER_OR_NAME) {
3821 parse_warn (cfile, "%s can't be a variable name", val);
3822 skip_to_semi (cfile);
3823 *lose = 1;
3824 return 0;
3827 if (!expression_allocate (expr, MDL))
3828 log_fatal ("can't allocate expression");
3829 (*expr) -> op = expr_variable_exists;
3830 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
3831 if (!(*expr)->data.variable)
3832 log_fatal ("can't allocate variable name");
3833 strcpy ((*expr) -> data.variable, val);
3834 token = next_token (&val, (unsigned *)0, cfile);
3835 if (token != RPAREN)
3836 goto norparen;
3837 break;
3839 /* Not a valid start to an expression... */
3840 default:
3841 if (token != NAME && token != NUMBER_OR_NAME)
3842 return 0;
3844 token = next_token (&val, (unsigned *)0, cfile);
3846 /* Save the name of the variable being referenced. */
3847 cptr = dmalloc (strlen (val) + 1, MDL);
3848 if (!cptr)
3849 log_fatal ("can't allocate variable name");
3850 strcpy (cptr, val);
3852 /* Simple variable reference, as far as we can tell. */
3853 token = peek_token (&val, (unsigned *)0, cfile);
3854 if (token != LPAREN) {
3855 if (!expression_allocate (expr, MDL))
3856 log_fatal ("can't allocate expression");
3857 (*expr) -> op = expr_variable_reference;
3858 (*expr) -> data.variable = cptr;
3859 break;
3862 token = next_token (&val, (unsigned *)0, cfile);
3863 if (!expression_allocate (expr, MDL))
3864 log_fatal ("can't allocate expression");
3865 (*expr) -> op = expr_funcall;
3866 (*expr) -> data.funcall.name = cptr;
3868 /* Now parse the argument list. */
3869 ep = &(*expr) -> data.funcall.arglist;
3870 do {
3871 if (!expression_allocate (ep, MDL))
3872 log_fatal ("can't allocate expression");
3873 (*ep) -> op = expr_arg;
3874 if (!parse_expression (&(*ep) -> data.arg.val,
3875 cfile, lose, context_any,
3876 (struct expression **)0,
3877 expr_none)) {
3878 if (!*lose) {
3879 parse_warn (cfile,
3880 "expecting expression.");
3881 *lose = 1;
3883 skip_to_semi (cfile);
3884 expression_dereference (expr, MDL);
3885 return 0;
3887 ep = &((*ep) -> data.arg.next);
3888 token = next_token (&val, (unsigned *)0, cfile);
3889 } while (token == COMMA);
3890 if (token != RPAREN) {
3891 parse_warn (cfile, "Right parenthesis expected.");
3892 skip_to_semi (cfile);
3893 *lose = 1;
3894 expression_dereference (expr, MDL);
3895 return 0;
3897 break;
3899 return 1;
3902 /* Parse an expression. */
3904 int parse_expression (expr, cfile, lose, context, plhs, binop)
3905 struct expression **expr;
3906 struct parse *cfile;
3907 int *lose;
3908 enum expression_context context;
3909 struct expression **plhs;
3910 enum expr_op binop;
3912 enum dhcp_token token;
3913 const char *val;
3914 struct expression *rhs = (struct expression *)0, *tmp;
3915 struct expression *lhs = (struct expression *)0;
3916 enum expr_op next_op;
3917 enum expression_context
3918 lhs_context = context_any,
3919 rhs_context = context_any;
3921 /* Consume the left hand side we were passed. */
3922 if (plhs) {
3923 expression_reference (&lhs, *plhs, MDL);
3924 expression_dereference (plhs, MDL);
3927 new_rhs:
3928 if (!parse_non_binary (&rhs, cfile, lose, context)) {
3929 /* If we already have a left-hand side, then it's not
3930 okay for there not to be a right-hand side here, so
3931 we need to flag it as an error. */
3932 if (lhs) {
3933 if (!*lose) {
3934 parse_warn (cfile,
3935 "expecting right-hand side.");
3936 *lose = 1;
3937 skip_to_semi (cfile);
3939 expression_dereference (&lhs, MDL);
3941 return 0;
3944 /* At this point, rhs contains either an entire subexpression,
3945 or at least a left-hand-side. If we do not see a binary token
3946 as the next token, we're done with the expression. */
3948 token = peek_token (&val, (unsigned *)0, cfile);
3949 switch (token) {
3950 case BANG:
3951 token = next_token (&val, (unsigned *)0, cfile);
3952 token = peek_token (&val, (unsigned *)0, cfile);
3953 if (token != EQUAL) {
3954 parse_warn (cfile, "! in boolean context without =");
3955 *lose = 1;
3956 skip_to_semi (cfile);
3957 if (lhs)
3958 expression_dereference (&lhs, MDL);
3959 return 0;
3961 next_op = expr_not_equal;
3962 context = expression_context (rhs);
3963 break;
3965 case EQUAL:
3966 next_op = expr_equal;
3967 context = expression_context (rhs);
3968 break;
3970 case AND:
3971 next_op = expr_and;
3972 context = expression_context (rhs);
3973 break;
3975 case OR:
3976 next_op = expr_or;
3977 context = expression_context (rhs);
3978 break;
3980 case PLUS:
3981 next_op = expr_add;
3982 context = expression_context (rhs);
3983 break;
3985 case MINUS:
3986 next_op = expr_subtract;
3987 context = expression_context (rhs);
3988 break;
3990 case SLASH:
3991 next_op = expr_divide;
3992 context = expression_context (rhs);
3993 break;
3995 case ASTERISK:
3996 next_op = expr_multiply;
3997 context = expression_context (rhs);
3998 break;
4000 case PERCENT:
4001 next_op = expr_remainder;
4002 context = expression_context (rhs);
4003 break;
4005 case AMPERSAND:
4006 next_op = expr_binary_and;
4007 context = expression_context (rhs);
4008 break;
4010 case PIPE:
4011 next_op = expr_binary_or;
4012 context = expression_context (rhs);
4013 break;
4015 case CARET:
4016 next_op = expr_binary_xor;
4017 context = expression_context (rhs);
4018 break;
4020 default:
4021 next_op = expr_none;
4024 /* If we have no lhs yet, we just parsed it. */
4025 if (!lhs) {
4026 /* If there was no operator following what we just parsed,
4027 then we're done - return it. */
4028 if (next_op == expr_none) {
4029 *expr = rhs;
4030 return 1;
4032 lhs = rhs;
4033 rhs = (struct expression *)0;
4034 binop = next_op;
4035 next_token (&val, (unsigned *)0, cfile);
4036 goto new_rhs;
4039 /* If the next binary operator is of greater precedence than the
4040 * current operator, then rhs we have parsed so far is actually
4041 * the lhs of the next operator. To get this value, we have to
4042 * recurse.
4044 if (binop != expr_none && next_op != expr_none &&
4045 op_precedence (binop, next_op) < 0) {
4047 /* Eat the subexpression operator token, which we pass to
4048 * parse_expression...we only peek()'d earlier.
4050 token = next_token (&val, (unsigned *)0, cfile);
4052 /* Continue parsing of the right hand side with that token. */
4053 tmp = rhs;
4054 rhs = (struct expression *)0;
4055 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
4056 &tmp, next_op)) {
4057 if (!*lose) {
4058 parse_warn (cfile,
4059 "expecting a subexpression");
4060 *lose = 1;
4062 return 0;
4064 next_op = expr_none;
4067 if (binop != expr_none) {
4068 rhs_context = expression_context(rhs);
4069 lhs_context = expression_context(lhs);
4071 if ((rhs_context != context_any) && (lhs_context != context_any) &&
4072 (rhs_context != lhs_context)) {
4073 parse_warn (cfile, "illegal expression relating different types");
4074 skip_to_semi (cfile);
4075 expression_dereference (&rhs, MDL);
4076 expression_dereference (&lhs, MDL);
4077 *lose = 1;
4078 return 0;
4081 switch(binop) {
4082 case expr_not_equal:
4083 case expr_equal:
4084 if ((rhs_context != context_data_or_numeric) &&
4085 (rhs_context != context_data) &&
4086 (rhs_context != context_numeric) &&
4087 (rhs_context != context_any)) {
4088 parse_warn (cfile, "expecting data/numeric expression");
4089 skip_to_semi (cfile);
4090 expression_dereference (&rhs, MDL);
4091 *lose = 1;
4092 return 0;
4094 break;
4096 case expr_and:
4097 case expr_or:
4098 if ((rhs_context != context_boolean) &&
4099 (rhs_context != context_any)) {
4100 parse_warn (cfile, "expecting boolean expressions");
4101 skip_to_semi (cfile);
4102 expression_dereference (&rhs, MDL);
4103 *lose = 1;
4104 return 0;
4106 break;
4108 case expr_add:
4109 case expr_subtract:
4110 case expr_divide:
4111 case expr_multiply:
4112 case expr_remainder:
4113 case expr_binary_and:
4114 case expr_binary_or:
4115 case expr_binary_xor:
4116 if ((rhs_context != context_numeric) &&
4117 (rhs_context != context_any)) {
4118 parse_warn (cfile, "expecting numeric expressions");
4119 skip_to_semi (cfile);
4120 expression_dereference (&rhs, MDL);
4121 *lose = 1;
4122 return 0;
4124 break;
4126 default:
4127 break;
4131 /* Now, if we didn't find a binary operator, we're done parsing
4132 this subexpression, so combine it with the preceding binary
4133 operator and return the result. */
4134 if (next_op == expr_none) {
4135 if (!expression_allocate (expr, MDL))
4136 log_fatal ("Can't allocate expression!");
4138 (*expr) -> op = binop;
4139 /* All the binary operators' data union members
4140 are the same, so we'll cheat and use the member
4141 for the equals operator. */
4142 (*expr) -> data.equal [0] = lhs;
4143 (*expr) -> data.equal [1] = rhs;
4144 return 1;
4147 /* Eat the operator token - we now know it was a binary operator... */
4148 token = next_token (&val, (unsigned *)0, cfile);
4150 /* Now combine the LHS and the RHS using binop. */
4151 tmp = (struct expression *)0;
4152 if (!expression_allocate (&tmp, MDL))
4153 log_fatal ("No memory for equal precedence combination.");
4155 /* Store the LHS and RHS. */
4156 tmp -> data.equal [0] = lhs;
4157 tmp -> data.equal [1] = rhs;
4158 tmp -> op = binop;
4160 lhs = tmp;
4161 tmp = (struct expression *)0;
4162 rhs = (struct expression *)0;
4164 /* Recursions don't return until we have parsed the end of the
4165 expression, so if we recursed earlier, we can now return what
4166 we got. */
4167 if (next_op == expr_none) {
4168 *expr = lhs;
4169 return 1;
4172 binop = next_op;
4173 goto new_rhs;
4176 /* option-statement :== identifier DOT identifier <syntax> SEMI
4177 | identifier <syntax> SEMI
4179 Option syntax is handled specially through format strings, so it
4180 would be painful to come up with BNF for it. However, it always
4181 starts as above and ends in a SEMI. */
4183 int parse_option_statement (result, cfile, lookups, option, op)
4184 struct executable_statement **result;
4185 struct parse *cfile;
4186 int lookups;
4187 struct option *option;
4188 enum statement_op op;
4190 const char *val;
4191 enum dhcp_token token;
4192 const char *fmt = NULL;
4193 struct expression *expr = (struct expression *)0;
4194 struct expression *tmp;
4195 int lose;
4196 struct executable_statement *stmt;
4197 int ftt = 1;
4199 token = peek_token (&val, (unsigned *)0, cfile);
4200 if (token == SEMI) {
4201 /* Eat the semicolon... */
4202 token = next_token (&val, (unsigned *)0, cfile);
4203 goto done;
4206 if (token == EQUAL) {
4207 /* Eat the equals sign. */
4208 token = next_token (&val, (unsigned *)0, cfile);
4210 /* Parse a data expression and use its value for the data. */
4211 if (!parse_data_expression (&expr, cfile, &lose)) {
4212 /* In this context, we must have an executable
4213 statement, so if we found something else, it's
4214 still an error. */
4215 if (!lose) {
4216 parse_warn (cfile,
4217 "expecting a data expression.");
4218 skip_to_semi (cfile);
4220 return 0;
4223 /* We got a valid expression, so use it. */
4224 goto done;
4227 /* Parse the option data... */
4228 do {
4229 /* Set a flag if this is an array of a simple type (i.e.,
4230 not an array of pairs of IP addresses, or something
4231 like that. */
4232 int uniform = option -> format [1] == 'A';
4234 and_again:
4235 /* Set fmt to start of format for 'A' and one char back
4236 for 'a' */
4237 if ((fmt != NULL) &&
4238 (fmt != option -> format) && (*fmt == 'a'))
4239 fmt -= 1;
4240 else
4241 fmt = ((fmt == NULL) ||
4242 (*fmt == 'A')) ? option -> format : fmt;
4244 /* 'a' means always uniform */
4245 uniform |= (fmt [1] == 'a');
4247 for ( ; *fmt; fmt++) {
4248 if ((*fmt == 'A') || (*fmt == 'a'))
4249 break;
4250 if (*fmt == 'o')
4251 continue;
4252 tmp = expr;
4253 expr = (struct expression *)0;
4254 if (!parse_option_token (&expr, cfile, &fmt,
4255 tmp, uniform, lookups)) {
4256 if (fmt [1] != 'o') {
4257 if (tmp)
4258 expression_dereference (&tmp,
4259 MDL);
4260 return 0;
4262 expr = tmp;
4263 tmp = (struct expression *)0;
4265 if (tmp)
4266 expression_dereference (&tmp, MDL);
4268 if ((*fmt == 'A') || (*fmt == 'a')) {
4269 token = peek_token (&val, (unsigned *)0, cfile);
4270 /* Comma means: continue with next element in array */
4271 if (token == COMMA) {
4272 token = next_token (&val,
4273 (unsigned *)0, cfile);
4274 continue;
4276 /* no comma: end of array.
4277 'A' or end of string means: leave the loop */
4278 if ((*fmt == 'A') || (fmt[1] == '\0'))
4279 break;
4280 /* 'a' means: go on with next char */
4281 if (*fmt == 'a') {
4282 fmt++;
4283 goto and_again;
4286 } while ((*fmt == 'A') || (*fmt == 'a'));
4288 done:
4289 if (!parse_semi (cfile))
4290 return 0;
4291 if (!executable_statement_allocate (result, MDL))
4292 log_fatal ("no memory for option statement.");
4293 (*result) -> op = op;
4294 if (expr && !option_cache (&(*result) -> data.option,
4295 (struct data_string *)0, expr, option, MDL))
4296 log_fatal ("no memory for option cache");
4297 if (expr)
4298 expression_dereference (&expr, MDL);
4299 return 1;
4302 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
4303 struct expression **rv;
4304 struct parse *cfile;
4305 const char **fmt;
4306 struct expression *expr;
4307 int uniform;
4308 int lookups;
4310 const char *val;
4311 enum dhcp_token token;
4312 struct expression *t = (struct expression *)0;
4313 unsigned char buf [4];
4314 unsigned len;
4315 unsigned char *ob;
4316 struct iaddr addr;
4317 int num;
4318 const char *f, *g;
4319 struct enumeration_value *e;
4321 switch (**fmt) {
4322 case 'U':
4323 token = peek_token (&val, (unsigned *)0, cfile);
4324 if (!is_identifier (token)) {
4325 if ((*fmt) [1] != 'o') {
4326 parse_warn (cfile, "expecting identifier.");
4327 skip_to_semi (cfile);
4329 return 0;
4331 token = next_token (&val, &len, cfile);
4332 if (!make_const_data (&t, (const unsigned char *)val,
4333 len, 1, 1, MDL))
4334 log_fatal ("No memory for %s", val);
4335 break;
4337 case 'E':
4338 g = strchr (*fmt, '.');
4339 if (!g) {
4340 parse_warn (cfile,
4341 "malformed encapsulation format (bug!)");
4342 skip_to_semi (cfile);
4343 return 0;
4345 *fmt = g;
4346 case 'X':
4347 token = peek_token (&val, (unsigned *)0, cfile);
4348 if (token == NUMBER_OR_NAME || token == NUMBER) {
4349 if (!expression_allocate (&t, MDL))
4350 return 0;
4351 if (!parse_cshl (&t -> data.const_data, cfile)) {
4352 expression_dereference (&t, MDL);
4353 return 0;
4355 t -> op = expr_const_data;
4356 } else if (token == STRING) {
4357 token = next_token (&val, &len, cfile);
4358 if (!make_const_data (&t, (const unsigned char *)val,
4359 len, 1, 1, MDL))
4360 log_fatal ("No memory for \"%s\"", val);
4361 } else {
4362 if ((*fmt) [1] != 'o') {
4363 parse_warn (cfile, "expecting string %s.",
4364 "or hexadecimal data");
4365 skip_to_semi (cfile);
4367 return 0;
4369 break;
4371 case 'd': /* Domain name... */
4372 val = parse_host_name (cfile);
4373 if (!val) {
4374 parse_warn (cfile, "not a valid domain name.");
4375 skip_to_semi (cfile);
4376 return 0;
4378 len = strlen (val);
4379 goto make_string;
4381 case 't': /* Text string... */
4382 token = peek_token (&val, (unsigned *)0, cfile);
4383 if (token != STRING && !is_identifier (token)) {
4384 if ((*fmt) [1] != 'o') {
4385 parse_warn (cfile, "expecting string.");
4386 if (token != SEMI)
4387 skip_to_semi (cfile);
4389 return 0;
4391 token = next_token (&val, &len, cfile);
4392 make_string:
4393 if (!make_const_data (&t, (const unsigned char *)val,
4394 len, 1, 1, MDL))
4395 log_fatal ("No memory for concatenation");
4396 break;
4398 case 'N':
4399 f = (*fmt) + 1;
4400 g = strchr (*fmt, '.');
4401 if (!g) {
4402 parse_warn (cfile, "malformed %s (bug!)",
4403 "enumeration format");
4404 foo:
4405 skip_to_semi (cfile);
4406 return 0;
4408 *fmt = g;
4409 token = next_token (&val, (unsigned *)0, cfile);
4410 if (!is_identifier (token)) {
4411 parse_warn (cfile,
4412 "identifier expected");
4413 goto foo;
4415 e = find_enumeration_value (f, (*fmt) - f, val);
4416 if (!e) {
4417 parse_warn (cfile, "unknown value");
4418 goto foo;
4420 if (!make_const_data (&t, &e -> value, 1, 0, 1, MDL))
4421 return 0;
4422 break;
4424 case 'I': /* IP address or hostname. */
4425 if (lookups) {
4426 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
4427 return 0;
4428 } else {
4429 if (!parse_ip_addr (cfile, &addr))
4430 return 0;
4431 if (!make_const_data (&t, addr.iabuf, addr.len,
4432 0, 1, MDL))
4433 return 0;
4435 break;
4437 case 'T': /* Lease interval. */
4438 token = peek_token (&val, (unsigned *)0, cfile);
4439 if (token != INFINITE)
4440 goto check_number;
4441 token = next_token (&val, (unsigned *)0, cfile);
4442 putLong (buf, -1);
4443 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
4444 return 0;
4445 break;
4447 case 'L': /* Unsigned 32-bit integer... */
4448 case 'l': /* Signed 32-bit integer... */
4449 token = peek_token (&val, (unsigned *)0, cfile);
4450 check_number:
4451 if (token != NUMBER) {
4452 need_number:
4453 if ((*fmt) [1] != 'o') {
4454 parse_warn (cfile, "expecting number.");
4455 if (token != SEMI)
4456 skip_to_semi (cfile);
4458 return 0;
4460 token = next_token (&val, (unsigned *)0, cfile);
4461 convert_num (cfile, buf, val, 0, 32);
4462 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
4463 return 0;
4464 break;
4466 case 's': /* Signed 16-bit integer. */
4467 case 'S': /* Unsigned 16-bit integer. */
4468 token = peek_token (&val, (unsigned *)0, cfile);
4469 if (token != NUMBER)
4470 goto need_number;
4471 token = next_token (&val, (unsigned *)0, cfile);
4472 convert_num (cfile, buf, val, 0, 16);
4473 if (!make_const_data (&t, buf, 2, 0, 1, MDL))
4474 return 0;
4475 break;
4477 case 'b': /* Signed 8-bit integer. */
4478 case 'B': /* Unsigned 8-bit integer. */
4479 token = peek_token (&val, (unsigned *)0, cfile);
4480 if (token != NUMBER)
4481 goto need_number;
4482 token = next_token (&val, (unsigned *)0, cfile);
4483 convert_num (cfile, buf, val, 0, 8);
4484 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
4485 return 0;
4486 break;
4488 case 'f': /* Boolean flag. */
4489 token = peek_token (&val, (unsigned *)0, cfile);
4490 if (!is_identifier (token)) {
4491 if ((*fmt) [1] != 'o')
4492 parse_warn (cfile, "expecting identifier.");
4493 bad_flag:
4494 if ((*fmt) [1] != 'o') {
4495 if (token != SEMI)
4496 skip_to_semi (cfile);
4498 return 0;
4500 if (!strcasecmp (val, "true")
4501 || !strcasecmp (val, "on"))
4502 buf [0] = 1;
4503 else if (!strcasecmp (val, "false")
4504 || !strcasecmp (val, "off"))
4505 buf [0] = 0;
4506 else if (!strcasecmp (val, "ignore"))
4507 buf [0] = 2;
4508 else {
4509 if ((*fmt) [1] != 'o')
4510 parse_warn (cfile, "expecting boolean.");
4511 goto bad_flag;
4513 token = next_token (&val, (unsigned *)0, cfile);
4514 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
4515 return 0;
4516 break;
4518 default:
4519 parse_warn (cfile, "Bad format %c in parse_option_token.",
4520 **fmt);
4521 skip_to_semi (cfile);
4522 return 0;
4524 if (expr) {
4525 if (!make_concat (rv, expr, t))
4526 return 0;
4527 } else
4528 expression_reference (rv, t, MDL);
4529 expression_dereference (&t, MDL);
4530 return 1;
4533 int parse_option_decl (oc, cfile)
4534 struct option_cache **oc;
4535 struct parse *cfile;
4537 const char *val;
4538 int token;
4539 u_int8_t buf [4];
4540 u_int8_t hunkbuf [1024];
4541 unsigned hunkix = 0;
4542 const char *fmt, *f;
4543 struct option *option;
4544 struct iaddr ip_addr;
4545 u_int8_t *dp;
4546 unsigned len;
4547 int nul_term = 0;
4548 struct buffer *bp;
4549 int known = 0;
4550 struct enumeration_value *e;
4552 option = parse_option_name (cfile, 0, &known);
4553 if (!option)
4554 return 0;
4556 /* Parse the option data... */
4557 do {
4558 /* Set a flag if this is an array of a simple type (i.e.,
4559 not an array of pairs of IP addresses, or something
4560 like that. */
4561 int uniform = option -> format [1] == 'A';
4563 for (fmt = option -> format; *fmt; fmt++) {
4564 if (*fmt == 'A')
4565 break;
4566 switch (*fmt) {
4567 case 'E':
4568 fmt = strchr (fmt, '.');
4569 if (!fmt) {
4570 parse_warn (cfile,
4571 "malformed %s (bug!)",
4572 "encapsulation format");
4573 skip_to_semi (cfile);
4574 return 0;
4576 case 'X':
4577 len = parse_X (cfile, &hunkbuf [hunkix],
4578 sizeof hunkbuf - hunkix);
4579 hunkix += len;
4580 break;
4582 case 't': /* Text string... */
4583 token = next_token (&val,
4584 &len, cfile);
4585 if (token != STRING) {
4586 parse_warn (cfile,
4587 "expecting string.");
4588 skip_to_semi (cfile);
4589 return 0;
4591 if (hunkix + len + 1 > sizeof hunkbuf) {
4592 parse_warn (cfile,
4593 "option data buffer %s",
4594 "overflow");
4595 skip_to_semi (cfile);
4596 return 0;
4598 memcpy (&hunkbuf [hunkix], val, len + 1);
4599 nul_term = 1;
4600 hunkix += len;
4601 break;
4603 case 'N':
4604 f = fmt;
4605 fmt = strchr (fmt, '.');
4606 if (!fmt) {
4607 parse_warn (cfile,
4608 "malformed %s (bug!)",
4609 "enumeration format");
4610 foo:
4611 skip_to_semi (cfile);
4612 return 0;
4614 token = next_token (&val,
4615 (unsigned *)0, cfile);
4616 if (!is_identifier (token)) {
4617 parse_warn (cfile,
4618 "identifier expected");
4619 goto foo;
4621 e = find_enumeration_value (f, fmt - f, val);
4622 if (!e) {
4623 parse_warn (cfile,
4624 "unknown value");
4625 goto foo;
4627 len = 1;
4628 dp = &e -> value;
4629 goto alloc;
4631 case 'I': /* IP address. */
4632 if (!parse_ip_addr (cfile, &ip_addr))
4633 return 0;
4634 len = ip_addr.len;
4635 dp = ip_addr.iabuf;
4637 alloc:
4638 if (hunkix + len > sizeof hunkbuf) {
4639 parse_warn (cfile,
4640 "option data buffer %s",
4641 "overflow");
4642 skip_to_semi (cfile);
4643 return 0;
4645 memcpy (&hunkbuf [hunkix], dp, len);
4646 hunkix += len;
4647 break;
4649 case 'L': /* Unsigned 32-bit integer... */
4650 case 'l': /* Signed 32-bit integer... */
4651 token = next_token (&val,
4652 (unsigned *)0, cfile);
4653 if (token != NUMBER) {
4654 need_number:
4655 parse_warn (cfile,
4656 "expecting number.");
4657 if (token != SEMI)
4658 skip_to_semi (cfile);
4659 return 0;
4661 convert_num (cfile, buf, val, 0, 32);
4662 len = 4;
4663 dp = buf;
4664 goto alloc;
4666 case 's': /* Signed 16-bit integer. */
4667 case 'S': /* Unsigned 16-bit integer. */
4668 token = next_token (&val,
4669 (unsigned *)0, cfile);
4670 if (token != NUMBER)
4671 goto need_number;
4672 convert_num (cfile, buf, val, 0, 16);
4673 len = 2;
4674 dp = buf;
4675 goto alloc;
4677 case 'b': /* Signed 8-bit integer. */
4678 case 'B': /* Unsigned 8-bit integer. */
4679 token = next_token (&val,
4680 (unsigned *)0, cfile);
4681 if (token != NUMBER)
4682 goto need_number;
4683 convert_num (cfile, buf, val, 0, 8);
4684 len = 1;
4685 dp = buf;
4686 goto alloc;
4688 case 'f': /* Boolean flag. */
4689 token = next_token (&val,
4690 (unsigned *)0, cfile);
4691 if (!is_identifier (token)) {
4692 parse_warn (cfile,
4693 "expecting identifier.");
4694 bad_flag:
4695 if (token != SEMI)
4696 skip_to_semi (cfile);
4697 return 0;
4699 if (!strcasecmp (val, "true")
4700 || !strcasecmp (val, "on"))
4701 buf [0] = 1;
4702 else if (!strcasecmp (val, "false")
4703 || !strcasecmp (val, "off"))
4704 buf [0] = 0;
4705 else {
4706 parse_warn (cfile,
4707 "expecting boolean.");
4708 goto bad_flag;
4710 len = 1;
4711 dp = buf;
4712 goto alloc;
4714 default:
4715 log_error ("parse_option_param: Bad format %c",
4716 *fmt);
4717 skip_to_semi (cfile);
4718 return 0;
4721 token = next_token (&val, (unsigned *)0, cfile);
4722 } while (*fmt == 'A' && token == COMMA);
4724 if (token != SEMI) {
4725 parse_warn (cfile, "semicolon expected.");
4726 skip_to_semi (cfile);
4727 return 0;
4730 bp = (struct buffer *)0;
4731 if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
4732 log_fatal ("no memory to store option declaration.");
4733 if (!bp -> data)
4734 log_fatal ("out of memory allocating option data.");
4735 memcpy (bp -> data, hunkbuf, hunkix + nul_term);
4737 if (!option_cache_allocate (oc, MDL))
4738 log_fatal ("out of memory allocating option cache.");
4740 (*oc) -> data.buffer = bp;
4741 (*oc) -> data.data = &bp -> data [0];
4742 (*oc) -> data.terminated = nul_term;
4743 (*oc) -> data.len = hunkix;
4744 (*oc) -> option = option;
4745 return 1;
4748 /* Consider merging parse_cshl into this. */
4750 int parse_X (cfile, buf, max)
4751 struct parse *cfile;
4752 u_int8_t *buf;
4753 unsigned max;
4755 int token;
4756 const char *val;
4757 unsigned len;
4758 u_int8_t *s;
4760 token = peek_token (&val, (unsigned *)0, cfile);
4761 if (token == NUMBER_OR_NAME || token == NUMBER) {
4762 len = 0;
4763 do {
4764 token = next_token (&val, (unsigned *)0, cfile);
4765 if (token != NUMBER && token != NUMBER_OR_NAME) {
4766 parse_warn (cfile,
4767 "expecting hexadecimal constant.");
4768 skip_to_semi (cfile);
4769 return 0;
4771 convert_num (cfile, &buf [len], val, 16, 8);
4772 if (len++ > max) {
4773 parse_warn (cfile,
4774 "hexadecimal constant too long.");
4775 skip_to_semi (cfile);
4776 return 0;
4778 token = peek_token (&val, (unsigned *)0, cfile);
4779 if (token == COLON)
4780 token = next_token (&val,
4781 (unsigned *)0, cfile);
4782 } while (token == COLON);
4783 val = (char *)buf;
4784 } else if (token == STRING) {
4785 token = next_token (&val, &len, cfile);
4786 if (len + 1 > max) {
4787 parse_warn (cfile, "string constant too long.");
4788 skip_to_semi (cfile);
4789 return 0;
4791 memcpy (buf, val, len + 1);
4792 } else {
4793 parse_warn (cfile, "expecting string or hexadecimal data");
4794 skip_to_semi (cfile);
4795 return 0;
4797 return len;
4800 int parse_warn (struct parse *cfile, const char *fmt, ...)
4802 va_list list;
4803 char lexbuf [256];
4804 char mbuf [1024];
4805 char fbuf [1024];
4806 unsigned i, lix;
4808 do_percentm (mbuf, fmt);
4809 /* %Audit% This is log output. %2004.06.17,Safe%
4810 * If we truncate we hope the user can get a hint from the log.
4812 snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
4813 cfile -> tlname, cfile -> lexline, mbuf);
4815 va_start (list, fmt);
4816 vsnprintf (mbuf, sizeof mbuf, fbuf, list);
4817 va_end (list);
4819 lix = 0;
4820 for (i = 0;
4821 cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
4822 if (lix < (sizeof lexbuf) - 1)
4823 lexbuf [lix++] = ' ';
4824 if (cfile -> token_line [i] == '\t') {
4825 for (lix;
4826 lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
4827 lexbuf [lix] = ' ';
4830 lexbuf [lix] = 0;
4832 #ifndef DEBUG
4833 syslog (log_priority | LOG_ERR, "%s", mbuf);
4834 syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
4835 if (cfile -> lexchar < 81)
4836 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
4837 #endif
4839 if (log_perror) {
4840 write (STDERR_FILENO, mbuf, strlen (mbuf));
4841 write (STDERR_FILENO, "\n", 1);
4842 write (STDERR_FILENO, cfile -> token_line,
4843 strlen (cfile -> token_line));
4844 write (STDERR_FILENO, "\n", 1);
4845 if (cfile -> lexchar < 81)
4846 write (STDERR_FILENO, lexbuf, lix);
4847 write (STDERR_FILENO, "^\n", 2);
4850 cfile -> warnings_occurred = 1;
4852 return 0;