tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / network / stacks / AROSTCP / dhcp / common / parse.c
blob847d58ecfc97e1c63da8a26cbd6bb83bf7e28783
1 /* parse.c
3 Common parser code for dhcpd and dhclient. */
5 /*
6 * Copyright (c) 2004-2005 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 #if 0
36 static char copyright[] =
37 "$Id$ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
38 #endif
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, 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 /* We completely ignore wday */
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 /* Day of 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 skip_to_semi (cfile);
1817 *lose = 1;
1818 return 0;
1821 if (!executable_statement_allocate (result, MDL))
1822 log_fatal ("no memory for set statement.");
1823 (*result) -> op = unset_statement;
1824 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
1825 if (!(*result)->data.unset)
1826 log_fatal ("can't allocate variable name");
1827 strcpy ((*result) -> data.unset, val);
1828 if (!parse_semi (cfile)) {
1829 *lose = 1;
1830 executable_statement_dereference (result, MDL);
1831 return 0;
1833 break;
1835 case EVAL:
1836 token = next_token (&val, (unsigned *)0, cfile);
1838 if (!executable_statement_allocate (result, MDL))
1839 log_fatal ("no memory for eval statement.");
1840 (*result) -> op = eval_statement;
1842 if (!parse_expression (&(*result) -> data.eval,
1843 cfile, lose, context_data, /* XXX */
1844 (struct expression **)0, expr_none)) {
1845 if (!*lose)
1846 parse_warn (cfile,
1847 "expecting data expression.");
1848 else
1849 *lose = 1;
1850 skip_to_semi (cfile);
1851 executable_statement_dereference (result, MDL);
1852 return 0;
1854 if (!parse_semi (cfile)) {
1855 *lose = 1;
1856 executable_statement_dereference (result, MDL);
1858 break;
1860 case RETURN:
1861 token = next_token (&val, (unsigned *)0, cfile);
1863 if (!executable_statement_allocate (result, MDL))
1864 log_fatal ("no memory for return statement.");
1865 (*result) -> op = return_statement;
1867 if (!parse_expression (&(*result) -> data.retval,
1868 cfile, lose, context_data,
1869 (struct expression **)0, expr_none)) {
1870 if (!*lose)
1871 parse_warn (cfile,
1872 "expecting data expression.");
1873 else
1874 *lose = 1;
1875 skip_to_semi (cfile);
1876 executable_statement_dereference (result, MDL);
1877 return 0;
1879 if (!parse_semi (cfile)) {
1880 *lose = 1;
1881 executable_statement_dereference (result, MDL);
1882 return 0;
1884 break;
1886 case LOG:
1887 token = next_token (&val, (unsigned *)0, cfile);
1889 if (!executable_statement_allocate (result, MDL))
1890 log_fatal ("no memory for log statement.");
1891 (*result) -> op = log_statement;
1893 token = next_token (&val, (unsigned *)0, cfile);
1894 if (token != LPAREN) {
1895 parse_warn (cfile, "left parenthesis expected.");
1896 skip_to_semi (cfile);
1897 *lose = 1;
1898 return 0;
1901 token = peek_token (&val, (unsigned *)0, cfile);
1902 i = 1;
1903 if (token == FATAL) {
1904 (*result) -> data.log.priority = log_priority_fatal;
1905 } else if (token == ERROR) {
1906 (*result) -> data.log.priority = log_priority_error;
1907 } else if (token == TOKEN_DEBUG) {
1908 (*result) -> data.log.priority = log_priority_debug;
1909 } else if (token == INFO) {
1910 (*result) -> data.log.priority = log_priority_info;
1911 } else {
1912 (*result) -> data.log.priority = log_priority_debug;
1913 i = 0;
1915 if (i) {
1916 token = next_token (&val, (unsigned *)0, cfile);
1917 token = next_token (&val, (unsigned *)0, cfile);
1918 if (token != COMMA) {
1919 parse_warn (cfile, "comma expected.");
1920 skip_to_semi (cfile);
1921 *lose = 1;
1922 return 0;
1926 if (!(parse_data_expression
1927 (&(*result) -> data.log.expr, cfile, lose))) {
1928 skip_to_semi (cfile);
1929 *lose = 1;
1930 return 0;
1933 token = next_token (&val, (unsigned *)0, cfile);
1934 if (token != RPAREN) {
1935 parse_warn (cfile, "right parenthesis expected.");
1936 skip_to_semi (cfile);
1937 *lose = 1;
1938 return 0;
1941 token = next_token (&val, (unsigned *)0, cfile);
1942 if (token != SEMI) {
1943 parse_warn (cfile, "semicolon expected.");
1944 skip_to_semi (cfile);
1945 *lose = 1;
1946 return 0;
1948 break;
1950 /* Not really a statement, but we parse it here anyway
1951 because it's appropriate for all DHCP agents with
1952 parsers. */
1953 case ZONE:
1954 token = next_token (&val, (unsigned *)0, cfile);
1955 zone = (struct dns_zone *)0;
1956 if (!dns_zone_allocate (&zone, MDL))
1957 log_fatal ("no memory for new zone.");
1958 zone -> name = parse_host_name (cfile);
1959 if (!zone -> name) {
1960 parse_warn (cfile, "expecting hostname.");
1961 badzone:
1962 *lose = 1;
1963 skip_to_semi (cfile);
1964 dns_zone_dereference (&zone, MDL);
1965 return 0;
1967 i = strlen (zone -> name);
1968 if (zone -> name [i - 1] != '.') {
1969 s = dmalloc ((unsigned)i + 2, MDL);
1970 if (!s) {
1971 parse_warn (cfile, "no trailing '.' on zone");
1972 goto badzone;
1974 strcpy (s, zone -> name);
1975 s [i] = '.';
1976 s [i + 1] = 0;
1977 dfree (zone -> name, MDL);
1978 zone -> name = s;
1980 if (!parse_zone (zone, cfile))
1981 goto badzone;
1982 status = enter_dns_zone (zone);
1983 if (status != ISC_R_SUCCESS) {
1984 parse_warn (cfile, "dns zone key %s: %s",
1985 zone -> name, isc_result_totext (status));
1986 dns_zone_dereference (&zone, MDL);
1987 return 0;
1989 dns_zone_dereference (&zone, MDL);
1990 return 1;
1992 /* Also not really a statement, but same idea as above. */
1993 case KEY:
1994 token = next_token (&val, (unsigned *)0, cfile);
1995 if (!parse_key (cfile)) {
1996 *lose = 1;
1997 return 0;
1999 return 1;
2001 default:
2002 if (config_universe && is_identifier (token)) {
2003 option = (struct option *)0;
2004 option_hash_lookup (&option, config_universe -> hash,
2005 val, 0, MDL);
2006 if (option) {
2007 token = next_token (&val,
2008 (unsigned *)0, cfile);
2009 return parse_option_statement
2010 (result, cfile, 1, option,
2011 supersede_option_statement);
2015 if (token == NUMBER_OR_NAME || token == NAME) {
2016 /* This is rather ugly. Since function calls are
2017 data expressions, fake up an eval statement. */
2018 if (!executable_statement_allocate (result, MDL))
2019 log_fatal ("no memory for eval statement.");
2020 (*result) -> op = eval_statement;
2022 if (!parse_expression (&(*result) -> data.eval,
2023 cfile, lose, context_data,
2024 (struct expression **)0,
2025 expr_none)) {
2026 if (!*lose)
2027 parse_warn (cfile, "expecting "
2028 "function call.");
2029 else
2030 *lose = 1;
2031 skip_to_semi (cfile);
2032 executable_statement_dereference (result, MDL);
2033 return 0;
2035 if (!parse_semi (cfile)) {
2036 *lose = 1;
2037 executable_statement_dereference (result, MDL);
2038 return 0;
2040 break;
2043 *lose = 0;
2044 return 0;
2047 return 1;
2050 /* zone-statements :== zone-statement |
2051 zone-statement zone-statements
2052 zone-statement :==
2053 PRIMARY ip-addresses SEMI |
2054 SECONDARY ip-addresses SEMI |
2055 key-reference SEMI
2056 ip-addresses :== ip-addr-or-hostname |
2057 ip-addr-or-hostname COMMA ip-addresses
2058 key-reference :== KEY STRING |
2059 KEY identifier */
2061 int parse_zone (struct dns_zone *zone, struct parse *cfile)
2063 int token;
2064 const char *val;
2065 char *key_name;
2066 struct option_cache *oc;
2067 int done = 0;
2069 token = next_token (&val, (unsigned *)0, cfile);
2070 if (token != LBRACE) {
2071 parse_warn (cfile, "expecting left brace");
2072 return 0;
2075 do {
2076 token = peek_token (&val, (unsigned *)0, cfile);
2077 switch (token) {
2078 case PRIMARY:
2079 if (zone -> primary) {
2080 parse_warn (cfile,
2081 "more than one primary.");
2082 skip_to_semi (cfile);
2083 return 0;
2085 if (!option_cache_allocate (&zone -> primary, MDL))
2086 log_fatal ("can't allocate primary option cache.");
2087 oc = zone -> primary;
2088 goto consemup;
2090 case SECONDARY:
2091 if (zone -> secondary) {
2092 parse_warn (cfile, "more than one secondary.");
2093 skip_to_semi (cfile);
2094 return 0;
2096 if (!option_cache_allocate (&zone -> secondary, MDL))
2097 log_fatal ("can't allocate secondary.");
2098 oc = zone -> secondary;
2099 consemup:
2100 token = next_token (&val, (unsigned *)0, cfile);
2101 do {
2102 struct expression *expr = (struct expression *)0;
2103 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
2104 parse_warn (cfile,
2105 "expecting IP addr or hostname.");
2106 skip_to_semi (cfile);
2107 return 0;
2109 if (oc -> expression) {
2110 struct expression *old =
2111 (struct expression *)0;
2112 expression_reference (&old,
2113 oc -> expression,
2114 MDL);
2115 expression_dereference (&oc -> expression,
2116 MDL);
2117 if (!make_concat (&oc -> expression,
2118 old, expr))
2119 log_fatal ("no memory for concat.");
2120 expression_dereference (&expr, MDL);
2121 expression_dereference (&old, MDL);
2122 } else {
2123 expression_reference (&oc -> expression,
2124 expr, MDL);
2125 expression_dereference (&expr, MDL);
2127 token = next_token (&val, (unsigned *)0, cfile);
2128 } while (token == COMMA);
2129 if (token != SEMI) {
2130 parse_warn (cfile, "expecting semicolon.");
2131 skip_to_semi (cfile);
2132 return 0;
2134 break;
2136 case KEY:
2137 token = next_token (&val, (unsigned *)0, cfile);
2138 token = peek_token (&val, (unsigned *)0, cfile);
2139 if (token == STRING) {
2140 token = next_token (&val, (unsigned *)0, cfile);
2141 key_name = (char *)0;
2142 } else {
2143 key_name = parse_host_name (cfile);
2144 if (!key_name) {
2145 parse_warn (cfile, "expecting key name.");
2146 skip_to_semi (cfile);
2147 return 0;
2149 val = key_name;
2151 if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2152 ISC_R_SUCCESS)
2153 parse_warn (cfile, "unknown key %s", val);
2154 if (key_name)
2155 dfree (key_name, MDL);
2156 if (!parse_semi (cfile))
2157 return 0;
2158 break;
2160 default:
2161 done = 1;
2162 break;
2164 } while (!done);
2166 token = next_token (&val, (unsigned *)0, cfile);
2167 if (token != RBRACE) {
2168 parse_warn (cfile, "expecting right brace.");
2169 return 0;
2171 return 1;
2174 /* key-statements :== key-statement |
2175 key-statement key-statements
2176 key-statement :==
2177 ALGORITHM host-name SEMI |
2178 secret-definition SEMI
2179 secret-definition :== SECRET base64val |
2180 SECRET STRING */
2182 int parse_key (struct parse *cfile)
2184 int token;
2185 const char *val;
2186 int done = 0;
2187 struct auth_key *key;
2188 struct data_string ds;
2189 isc_result_t status;
2190 char *s;
2192 key = (struct auth_key *)0;
2193 if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2194 log_fatal ("no memory for key");
2196 token = peek_token (&val, (unsigned *)0, cfile);
2197 if (token == STRING) {
2198 token = next_token (&val, (unsigned *)0, cfile);
2199 key -> name = dmalloc (strlen (val) + 1, MDL);
2200 if (!key -> name)
2201 log_fatal ("no memory for key name.");
2202 strcpy (key -> name, val);
2204 } else {
2205 key -> name = parse_host_name (cfile);
2206 if (!key -> name) {
2207 parse_warn (cfile, "expecting key name.");
2208 skip_to_semi (cfile);
2209 goto bad;
2213 token = next_token (&val, (unsigned *)0, cfile);
2214 if (token != LBRACE) {
2215 parse_warn (cfile, "expecting left brace");
2216 goto bad;
2219 do {
2220 token = next_token (&val, (unsigned *)0, cfile);
2221 switch (token) {
2222 case ALGORITHM:
2223 if (key -> algorithm) {
2224 parse_warn (cfile,
2225 "key %s: too many algorithms",
2226 key -> name);
2227 goto rbad;
2229 key -> algorithm = parse_host_name (cfile);
2230 if (!key -> algorithm) {
2231 parse_warn (cfile,
2232 "expecting key algorithm name.");
2233 goto rbad;
2235 if (!parse_semi (cfile))
2236 goto rbad;
2237 /* If the algorithm name isn't an FQDN, tack on
2238 the .SIG-ALG.REG.NET. domain. */
2239 s = strrchr (key -> algorithm, '.');
2240 if (!s) {
2241 static char add [] = ".SIG-ALG.REG.INT.";
2242 s = dmalloc (strlen (key -> algorithm) +
2243 sizeof (add), MDL);
2244 if (!s) {
2245 log_error ("no memory for key %s.",
2246 "algorithm");
2247 goto rbad;
2249 strcpy (s, key -> algorithm);
2250 strcat (s, add);
2251 dfree (key -> algorithm, MDL);
2252 key -> algorithm = s;
2253 } else if (s [1]) {
2254 /* If there is no trailing '.', hack one in. */
2255 s = dmalloc (strlen (key -> algorithm) + 2, MDL);
2256 if (!s) {
2257 log_error ("no memory for key %s.",
2258 key -> algorithm);
2259 goto rbad;
2261 strcpy (s, key -> algorithm);
2262 strcat (s, ".");
2263 dfree (key -> algorithm, MDL);
2264 key -> algorithm = s;
2266 break;
2268 case SECRET:
2269 if (key -> key) {
2270 parse_warn (cfile, "key %s: too many secrets",
2271 key -> name);
2272 goto rbad;
2275 memset (&ds, 0, sizeof(ds));
2276 if (!parse_base64 (&ds, cfile))
2277 goto rbad;
2278 status = omapi_data_string_new (&key -> key, ds.len,
2279 MDL);
2280 if (status != ISC_R_SUCCESS)
2281 goto rbad;
2282 memcpy (key -> key -> value,
2283 ds.buffer -> data, ds.len);
2284 data_string_forget (&ds, MDL);
2286 if (!parse_semi (cfile))
2287 goto rbad;
2288 break;
2290 default:
2291 done = 1;
2292 break;
2294 } while (!done);
2295 if (token != RBRACE) {
2296 parse_warn (cfile, "expecting right brace.");
2297 goto rbad;
2299 /* Allow the BIND 8 syntax, which has a semicolon after each
2300 closing brace. */
2301 token = peek_token (&val, (unsigned *)0, cfile);
2302 if (token == SEMI)
2303 token = next_token (&val, (unsigned *)0, cfile);
2305 /* Remember the key. */
2306 status = omapi_auth_key_enter (key);
2307 if (status != ISC_R_SUCCESS) {
2308 parse_warn (cfile, "tsig key %s: %s",
2309 key -> name, isc_result_totext (status));
2310 goto bad;
2312 omapi_auth_key_dereference (&key, MDL);
2313 return 1;
2315 rbad:
2316 skip_to_rbrace (cfile, 1);
2317 bad:
2318 omapi_auth_key_dereference (&key, MDL);
2319 return 0;
2323 * on-statement :== event-types LBRACE executable-statements RBRACE
2324 * event-types :== event-type OR event-types |
2325 * event-type
2326 * event-type :== EXPIRY | COMMIT | RELEASE
2329 int parse_on_statement (result, cfile, lose)
2330 struct executable_statement **result;
2331 struct parse *cfile;
2332 int *lose;
2334 enum dhcp_token token;
2335 const char *val;
2337 if (!executable_statement_allocate (result, MDL))
2338 log_fatal ("no memory for new statement.");
2339 (*result) -> op = on_statement;
2341 do {
2342 token = next_token (&val, (unsigned *)0, cfile);
2343 switch (token) {
2344 case EXPIRY:
2345 (*result) -> data.on.evtypes |= ON_EXPIRY;
2346 break;
2348 case COMMIT:
2349 (*result) -> data.on.evtypes |= ON_COMMIT;
2350 break;
2352 case RELEASE:
2353 (*result) -> data.on.evtypes |= ON_RELEASE;
2354 break;
2356 case TRANSMISSION:
2357 (*result) -> data.on.evtypes |= ON_TRANSMISSION;
2358 break;
2360 default:
2361 parse_warn (cfile, "expecting a lease event type");
2362 skip_to_semi (cfile);
2363 *lose = 1;
2364 executable_statement_dereference (result, MDL);
2365 return 0;
2367 token = next_token (&val, (unsigned *)0, cfile);
2368 } while (token == OR);
2370 /* Semicolon means no statements. */
2371 if (token == SEMI)
2372 return 1;
2374 if (token != LBRACE) {
2375 parse_warn (cfile, "left brace expected.");
2376 skip_to_semi (cfile);
2377 *lose = 1;
2378 executable_statement_dereference (result, MDL);
2379 return 0;
2381 if (!parse_executable_statements (&(*result) -> data.on.statements,
2382 cfile, lose, context_any)) {
2383 if (*lose) {
2384 /* Try to even things up. */
2385 do {
2386 token = next_token (&val,
2387 (unsigned *)0, cfile);
2388 } while (token != END_OF_FILE && token != RBRACE);
2389 executable_statement_dereference (result, MDL);
2390 return 0;
2393 token = next_token (&val, (unsigned *)0, cfile);
2394 if (token != RBRACE) {
2395 parse_warn (cfile, "right brace expected.");
2396 skip_to_semi (cfile);
2397 *lose = 1;
2398 executable_statement_dereference (result, MDL);
2399 return 0;
2401 return 1;
2405 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2409 int parse_switch_statement (result, cfile, lose)
2410 struct executable_statement **result;
2411 struct parse *cfile;
2412 int *lose;
2414 enum dhcp_token token;
2415 const char *val;
2417 if (!executable_statement_allocate (result, MDL))
2418 log_fatal ("no memory for new statement.");
2419 (*result) -> op = switch_statement;
2421 token = next_token (&val, (unsigned *)0, cfile);
2422 if (token != LPAREN) {
2423 parse_warn (cfile, "expecting left brace.");
2424 pfui:
2425 *lose = 1;
2426 skip_to_semi (cfile);
2427 gnorf:
2428 executable_statement_dereference (result, MDL);
2429 return 0;
2432 if (!parse_expression (&(*result) -> data.s_switch.expr,
2433 cfile, lose, context_data_or_numeric,
2434 (struct expression **)0, expr_none)) {
2435 if (!*lose) {
2436 parse_warn (cfile,
2437 "expecting data or numeric expression.");
2438 goto pfui;
2440 goto gnorf;
2443 token = next_token (&val, (unsigned *)0, cfile);
2444 if (token != RPAREN) {
2445 parse_warn (cfile, "right paren expected.");
2446 goto pfui;
2449 token = next_token (&val, (unsigned *)0, cfile);
2450 if (token != LBRACE) {
2451 parse_warn (cfile, "left brace expected.");
2452 goto pfui;
2454 if (!(parse_executable_statements
2455 (&(*result) -> data.s_switch.statements, cfile, lose,
2456 (is_data_expression ((*result) -> data.s_switch.expr)
2457 ? context_data : context_numeric)))) {
2458 if (*lose) {
2459 skip_to_rbrace (cfile, 1);
2460 executable_statement_dereference (result, MDL);
2461 return 0;
2464 token = next_token (&val, (unsigned *)0, cfile);
2465 if (token != RBRACE) {
2466 parse_warn (cfile, "right brace expected.");
2467 goto pfui;
2469 return 1;
2473 * case-statement :== CASE expr COLON
2477 int parse_case_statement (result, cfile, lose, case_context)
2478 struct executable_statement **result;
2479 struct parse *cfile;
2480 int *lose;
2481 enum expression_context case_context;
2483 enum dhcp_token token;
2484 const char *val;
2486 if (!executable_statement_allocate (result, MDL))
2487 log_fatal ("no memory for new statement.");
2488 (*result) -> op = case_statement;
2490 if (!parse_expression (&(*result) -> data.c_case,
2491 cfile, lose, case_context,
2492 (struct expression **)0, expr_none))
2494 if (!*lose) {
2495 parse_warn (cfile, "expecting %s expression.",
2496 (case_context == context_data
2497 ? "data" : "numeric"));
2499 pfui:
2500 *lose = 1;
2501 skip_to_semi (cfile);
2502 executable_statement_dereference (result, MDL);
2503 return 0;
2506 token = next_token (&val, (unsigned *)0, cfile);
2507 if (token != COLON) {
2508 parse_warn (cfile, "colon expected.");
2509 goto pfui;
2511 return 1;
2515 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
2516 * else-statement
2518 * else-statement :== <null> |
2519 * ELSE LBRACE executable-statements RBRACE |
2520 * ELSE IF if-statement |
2521 * ELSIF if-statement
2524 int parse_if_statement (result, cfile, lose)
2525 struct executable_statement **result;
2526 struct parse *cfile;
2527 int *lose;
2529 enum dhcp_token token;
2530 const char *val;
2531 int parenp;
2533 if (!executable_statement_allocate (result, MDL))
2534 log_fatal ("no memory for if statement.");
2536 (*result) -> op = if_statement;
2538 token = peek_token (&val, (unsigned *)0, cfile);
2539 if (token == LPAREN) {
2540 parenp = 1;
2541 next_token (&val, (unsigned *)0, cfile);
2542 } else
2543 parenp = 0;
2546 if (!parse_boolean_expression (&(*result) -> data.ie.expr,
2547 cfile, lose)) {
2548 if (!*lose)
2549 parse_warn (cfile, "boolean expression expected.");
2550 executable_statement_dereference (result, MDL);
2551 *lose = 1;
2552 return 0;
2554 #if defined (DEBUG_EXPRESSION_PARSE)
2555 print_expression ("if condition", (*result) -> data.ie.expr);
2556 #endif
2557 if (parenp) {
2558 token = next_token (&val, (unsigned *)0, cfile);
2559 if (token != RPAREN) {
2560 parse_warn (cfile, "expecting right paren.");
2561 *lose = 1;
2562 executable_statement_dereference (result, MDL);
2563 return 0;
2566 token = next_token (&val, (unsigned *)0, cfile);
2567 if (token != LBRACE) {
2568 parse_warn (cfile, "left brace expected.");
2569 skip_to_semi (cfile);
2570 *lose = 1;
2571 executable_statement_dereference (result, MDL);
2572 return 0;
2574 if (!parse_executable_statements (&(*result) -> data.ie.tc,
2575 cfile, lose, context_any)) {
2576 if (*lose) {
2577 /* Try to even things up. */
2578 do {
2579 token = next_token (&val,
2580 (unsigned *)0, cfile);
2581 } while (token != END_OF_FILE && token != RBRACE);
2582 executable_statement_dereference (result, MDL);
2583 return 0;
2586 token = next_token (&val, (unsigned *)0, cfile);
2587 if (token != RBRACE) {
2588 parse_warn (cfile, "right brace expected.");
2589 skip_to_semi (cfile);
2590 *lose = 1;
2591 executable_statement_dereference (result, MDL);
2592 return 0;
2594 token = peek_token (&val, (unsigned *)0, cfile);
2595 if (token == ELSE) {
2596 token = next_token (&val, (unsigned *)0, cfile);
2597 token = peek_token (&val, (unsigned *)0, cfile);
2598 if (token == IF) {
2599 token = next_token (&val, (unsigned *)0, cfile);
2600 if (!parse_if_statement (&(*result) -> data.ie.fc,
2601 cfile, lose)) {
2602 if (!*lose)
2603 parse_warn (cfile,
2604 "expecting if statement");
2605 executable_statement_dereference (result, MDL);
2606 *lose = 1;
2607 return 0;
2609 } else if (token != LBRACE) {
2610 parse_warn (cfile, "left brace or if expected.");
2611 skip_to_semi (cfile);
2612 *lose = 1;
2613 executable_statement_dereference (result, MDL);
2614 return 0;
2615 } else {
2616 token = next_token (&val, (unsigned *)0, cfile);
2617 if (!(parse_executable_statements
2618 (&(*result) -> data.ie.fc,
2619 cfile, lose, context_any))) {
2620 executable_statement_dereference (result, MDL);
2621 return 0;
2623 token = next_token (&val, (unsigned *)0, cfile);
2624 if (token != RBRACE) {
2625 parse_warn (cfile, "right brace expected.");
2626 skip_to_semi (cfile);
2627 *lose = 1;
2628 executable_statement_dereference (result, MDL);
2629 return 0;
2632 } else if (token == ELSIF) {
2633 token = next_token (&val, (unsigned *)0, cfile);
2634 if (!parse_if_statement (&(*result) -> data.ie.fc,
2635 cfile, lose)) {
2636 if (!*lose)
2637 parse_warn (cfile,
2638 "expecting conditional.");
2639 executable_statement_dereference (result, MDL);
2640 *lose = 1;
2641 return 0;
2643 } else
2644 (*result) -> data.ie.fc = (struct executable_statement *)0;
2646 return 1;
2650 * boolean_expression :== CHECK STRING |
2651 * NOT boolean-expression |
2652 * data-expression EQUAL data-expression |
2653 * data-expression BANG EQUAL data-expression |
2654 * boolean-expression AND boolean-expression |
2655 * boolean-expression OR boolean-expression
2656 * EXISTS OPTION-NAME
2659 int parse_boolean_expression (expr, cfile, lose)
2660 struct expression **expr;
2661 struct parse *cfile;
2662 int *lose;
2664 /* Parse an expression... */
2665 if (!parse_expression (expr, cfile, lose, context_boolean,
2666 (struct expression **)0, expr_none))
2667 return 0;
2669 if (!is_boolean_expression (*expr) &&
2670 (*expr) -> op != expr_variable_reference &&
2671 (*expr) -> op != expr_funcall) {
2672 parse_warn (cfile, "Expecting a boolean expression.");
2673 *lose = 1;
2674 expression_dereference (expr, MDL);
2675 return 0;
2677 return 1;
2681 * data_expression :== SUBSTRING LPAREN data-expression COMMA
2682 * numeric-expression COMMA
2683 * numeric-expression RPAREN |
2684 * CONCAT LPAREN data-expression COMMA
2685 data-expression RPAREN
2686 * SUFFIX LPAREN data_expression COMMA
2687 * numeric-expression RPAREN |
2688 * OPTION option_name |
2689 * HARDWARE |
2690 * PACKET LPAREN numeric-expression COMMA
2691 * numeric-expression RPAREN |
2692 * STRING |
2693 * colon_seperated_hex_list
2696 int parse_data_expression (expr, cfile, lose)
2697 struct expression **expr;
2698 struct parse *cfile;
2699 int *lose;
2701 /* Parse an expression... */
2702 if (!parse_expression (expr, cfile, lose, context_data,
2703 (struct expression **)0, expr_none))
2704 return 0;
2706 if (!is_data_expression (*expr) &&
2707 (*expr) -> op != expr_variable_reference &&
2708 (*expr) -> op != expr_funcall) {
2709 expression_dereference (expr, MDL);
2710 parse_warn (cfile, "Expecting a data expression.");
2711 *lose = 1;
2712 return 0;
2714 return 1;
2718 * numeric-expression :== EXTRACT_INT LPAREN data-expression
2719 * COMMA number RPAREN |
2720 * NUMBER
2723 int parse_numeric_expression (expr, cfile, lose)
2724 struct expression **expr;
2725 struct parse *cfile;
2726 int *lose;
2728 /* Parse an expression... */
2729 if (!parse_expression (expr, cfile, lose, context_numeric,
2730 (struct expression **)0, expr_none))
2731 return 0;
2733 if (!is_numeric_expression (*expr) &&
2734 (*expr) -> op != expr_variable_reference &&
2735 (*expr) -> op != expr_funcall) {
2736 expression_dereference (expr, MDL);
2737 parse_warn (cfile, "Expecting a numeric expression.");
2738 *lose = 1;
2739 return 0;
2741 return 1;
2745 * dns-expression :==
2746 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2747 * data-expression COMMA numeric-expression RPAREN
2748 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2749 * data-expression RPAREN
2750 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2751 * data-expression RPAREN
2752 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2753 * data-expression RPAREN
2754 * ns-class :== IN | CHAOS | HS | NUMBER
2755 * ns-type :== A | PTR | MX | TXT | NUMBER
2758 int parse_dns_expression (expr, cfile, lose)
2759 struct expression **expr;
2760 struct parse *cfile;
2761 int *lose;
2763 /* Parse an expression... */
2764 if (!parse_expression (expr, cfile, lose, context_dns,
2765 (struct expression **)0, expr_none))
2766 return 0;
2768 if (!is_dns_expression (*expr) &&
2769 (*expr) -> op != expr_variable_reference &&
2770 (*expr) -> op != expr_funcall) {
2771 expression_dereference (expr, MDL);
2772 parse_warn (cfile, "Expecting a dns update subexpression.");
2773 *lose = 1;
2774 return 0;
2776 return 1;
2779 /* Parse a subexpression that does not contain a binary operator. */
2781 int parse_non_binary (expr, cfile, lose, context)
2782 struct expression **expr;
2783 struct parse *cfile;
2784 int *lose;
2785 enum expression_context context;
2787 enum dhcp_token token;
2788 const char *val;
2789 struct collection *col;
2790 // struct option *option;
2791 struct expression *nexp, **ep;
2792 int known;
2793 enum expr_op opcode;
2794 const char *s;
2795 char *cptr;
2796 // struct executable_statement *stmt;
2797 // int i;
2798 unsigned long u;
2799 // isc_result_t status, code;
2800 unsigned len;
2802 token = peek_token (&val, (unsigned *)0, cfile);
2804 /* Check for unary operators... */
2805 switch (token) {
2806 case CHECK:
2807 token = next_token (&val, (unsigned *)0, cfile);
2808 token = next_token (&val, (unsigned *)0, cfile);
2809 if (token != STRING) {
2810 parse_warn (cfile, "string expected.");
2811 skip_to_semi (cfile);
2812 *lose = 1;
2813 return 0;
2815 for (col = collections; col; col = col -> next)
2816 if (!strcmp (col -> name, val))
2817 break;
2818 if (!col) {
2819 parse_warn (cfile, "unknown collection.");
2820 *lose = 1;
2821 return 0;
2823 if (!expression_allocate (expr, MDL))
2824 log_fatal ("can't allocate expression");
2825 (*expr) -> op = expr_check;
2826 (*expr) -> data.check = col;
2827 break;
2829 case TOKEN_NOT:
2830 token = next_token (&val, (unsigned *)0, cfile);
2831 if (context == context_dns) {
2832 token = peek_token (&val, (unsigned *)0, cfile);
2833 goto not_exists;
2835 if (!expression_allocate (expr, MDL))
2836 log_fatal ("can't allocate expression");
2837 (*expr) -> op = expr_not;
2838 if (!parse_non_binary (&(*expr) -> data.not,
2839 cfile, lose, context_boolean)) {
2840 if (!*lose) {
2841 parse_warn (cfile, "expression expected");
2842 skip_to_semi (cfile);
2844 *lose = 1;
2845 expression_dereference (expr, MDL);
2846 return 0;
2848 if (!is_boolean_expression ((*expr) -> data.not)) {
2849 *lose = 1;
2850 parse_warn (cfile, "boolean expression expected");
2851 skip_to_semi (cfile);
2852 expression_dereference (expr, MDL);
2853 return 0;
2855 break;
2857 case LPAREN:
2858 token = next_token (&val, (unsigned *)0, cfile);
2859 if (!parse_expression (expr, cfile, lose, context,
2860 (struct expression **)0, expr_none)) {
2861 if (!*lose) {
2862 parse_warn (cfile, "expression expected");
2863 skip_to_semi (cfile);
2865 *lose = 1;
2866 return 0;
2868 token = next_token (&val, (unsigned *)0, cfile);
2869 if (token != RPAREN) {
2870 *lose = 1;
2871 parse_warn (cfile, "right paren expected");
2872 skip_to_semi (cfile);
2873 return 0;
2875 break;
2877 case EXISTS:
2878 if (context == context_dns)
2879 goto ns_exists;
2880 token = next_token (&val, (unsigned *)0, cfile);
2881 if (!expression_allocate (expr, MDL))
2882 log_fatal ("can't allocate expression");
2883 (*expr) -> op = expr_exists;
2884 known = 0;
2885 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
2886 if (!(*expr) -> data.option) {
2887 *lose = 1;
2888 expression_dereference (expr, MDL);
2889 return 0;
2891 break;
2893 case _STATIC:
2894 token = next_token (&val, (unsigned *)0, cfile);
2895 if (!expression_allocate (expr, MDL))
2896 log_fatal ("can't allocate expression");
2897 (*expr) -> op = expr_static;
2898 break;
2900 case KNOWN:
2901 token = next_token (&val, (unsigned *)0, cfile);
2902 if (!expression_allocate (expr, MDL))
2903 log_fatal ("can't allocate expression");
2904 (*expr) -> op = expr_known;
2905 break;
2907 case SUBSTRING:
2908 token = next_token (&val, (unsigned *)0, cfile);
2909 if (!expression_allocate (expr, MDL))
2910 log_fatal ("can't allocate expression");
2911 (*expr) -> op = expr_substring;
2913 token = next_token (&val, (unsigned *)0, cfile);
2914 if (token != LPAREN) {
2915 nolparen:
2916 expression_dereference (expr, MDL);
2917 parse_warn (cfile, "left parenthesis expected.");
2918 *lose = 1;
2919 return 0;
2922 if (!parse_data_expression (&(*expr) -> data.substring.expr,
2923 cfile, lose)) {
2924 nodata:
2925 expression_dereference (expr, MDL);
2926 if (!*lose) {
2927 parse_warn (cfile,
2928 "expecting data expression.");
2929 skip_to_semi (cfile);
2930 *lose = 1;
2932 return 0;
2935 token = next_token (&val, (unsigned *)0, cfile);
2936 if (token != COMMA) {
2937 nocomma:
2938 expression_dereference (expr, MDL);
2939 parse_warn (cfile, "comma expected.");
2940 *lose = 1;
2942 return 0;
2945 if (!parse_numeric_expression
2946 (&(*expr) -> data.substring.offset,cfile, lose)) {
2947 nonum:
2948 if (!*lose) {
2949 parse_warn (cfile,
2950 "expecting numeric expression.");
2951 skip_to_semi (cfile);
2952 *lose = 1;
2954 expression_dereference (expr, MDL);
2955 return 0;
2958 token = next_token (&val, (unsigned *)0, cfile);
2959 if (token != COMMA)
2960 goto nocomma;
2962 if (!parse_numeric_expression
2963 (&(*expr) -> data.substring.len, cfile, lose))
2964 goto nonum;
2966 token = next_token (&val, (unsigned *)0, cfile);
2967 if (token != RPAREN) {
2968 norparen:
2969 parse_warn (cfile, "right parenthesis expected.");
2970 *lose = 1;
2971 expression_dereference (expr, MDL);
2972 return 0;
2974 break;
2976 case SUFFIX:
2977 token = next_token (&val, (unsigned *)0, cfile);
2978 if (!expression_allocate (expr, MDL))
2979 log_fatal ("can't allocate expression");
2980 (*expr) -> op = expr_suffix;
2982 token = next_token (&val, (unsigned *)0, cfile);
2983 if (token != LPAREN)
2984 goto nolparen;
2986 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
2987 cfile, lose))
2988 goto nodata;
2990 token = next_token (&val, (unsigned *)0, cfile);
2991 if (token != COMMA)
2992 goto nocomma;
2994 if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
2995 cfile, lose))
2996 goto nonum;
2998 token = next_token (&val, (unsigned *)0, cfile);
2999 if (token != RPAREN)
3000 goto norparen;
3001 break;
3003 case CONCAT:
3004 token = next_token (&val, (unsigned *)0, cfile);
3005 if (!expression_allocate (expr, MDL))
3006 log_fatal ("can't allocate expression");
3007 (*expr) -> op = expr_concat;
3009 token = next_token (&val, (unsigned *)0, cfile);
3010 if (token != LPAREN)
3011 goto nolparen;
3013 if (!parse_data_expression (&(*expr) -> data.concat [0],
3014 cfile, lose))
3015 goto nodata;
3017 token = next_token (&val, (unsigned *)0, cfile);
3018 if (token != COMMA)
3019 goto nocomma;
3021 concat_another:
3022 if (!parse_data_expression (&(*expr) -> data.concat [1],
3023 cfile, lose))
3024 goto nodata;
3026 token = next_token (&val, (unsigned *)0, cfile);
3028 if (token == COMMA) {
3029 nexp = (struct expression *)0;
3030 if (!expression_allocate (&nexp, MDL))
3031 log_fatal ("can't allocate at CONCAT2");
3032 nexp -> op = expr_concat;
3033 expression_reference (&nexp -> data.concat [0],
3034 *expr, MDL);
3035 expression_dereference (expr, MDL);
3036 expression_reference (expr, nexp, MDL);
3037 expression_dereference (&nexp, MDL);
3038 goto concat_another;
3041 if (token != RPAREN)
3042 goto norparen;
3043 break;
3045 case BINARY_TO_ASCII:
3046 token = next_token (&val, (unsigned *)0, cfile);
3047 if (!expression_allocate (expr, MDL))
3048 log_fatal ("can't allocate expression");
3049 (*expr) -> op = expr_binary_to_ascii;
3051 token = next_token (&val, (unsigned *)0, cfile);
3052 if (token != LPAREN)
3053 goto nolparen;
3055 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3056 cfile, lose))
3057 goto nodata;
3059 token = next_token (&val, (unsigned *)0, cfile);
3060 if (token != COMMA)
3061 goto nocomma;
3063 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3064 cfile, lose))
3065 goto nodata;
3067 token = next_token (&val, (unsigned *)0, cfile);
3068 if (token != COMMA)
3069 goto nocomma;
3071 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
3072 cfile, lose))
3073 goto nodata;
3075 token = next_token (&val, (unsigned *)0, cfile);
3076 if (token != COMMA)
3077 goto nocomma;
3079 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3080 cfile, lose))
3081 goto nodata;
3083 token = next_token (&val, (unsigned *)0, cfile);
3084 if (token != RPAREN)
3085 goto norparen;
3086 break;
3088 case REVERSE:
3089 token = next_token (&val, (unsigned *)0, cfile);
3090 if (!expression_allocate (expr, MDL))
3091 log_fatal ("can't allocate expression");
3092 (*expr) -> op = expr_reverse;
3094 token = next_token (&val, (unsigned *)0, cfile);
3095 if (token != LPAREN)
3096 goto nolparen;
3098 if (!(parse_numeric_expression
3099 (&(*expr) -> data.reverse.width, cfile, lose)))
3100 goto nodata;
3102 token = next_token (&val, (unsigned *)0, cfile);
3103 if (token != COMMA)
3104 goto nocomma;
3106 if (!(parse_data_expression
3107 (&(*expr) -> data.reverse.buffer, cfile, lose)))
3108 goto nodata;
3110 token = next_token (&val, (unsigned *)0, cfile);
3111 if (token != RPAREN)
3112 goto norparen;
3113 break;
3115 case PICK:
3116 /* pick (a, b, c) actually produces an internal representation
3117 that looks like pick (a, pick (b, pick (c, nil))). */
3118 token = next_token (&val, (unsigned *)0, cfile);
3119 if (!(expression_allocate (expr, MDL)))
3120 log_fatal ("can't allocate expression");
3122 token = next_token (&val, (unsigned *)0, cfile);
3123 if (token != LPAREN)
3124 goto nolparen;
3126 nexp = (struct expression *)0;
3127 expression_reference (&nexp, *expr, MDL);
3128 do {
3129 nexp -> op = expr_pick_first_value;
3130 if (!(parse_data_expression
3131 (&nexp -> data.pick_first_value.car,
3132 cfile, lose)))
3133 goto nodata;
3135 token = next_token (&val, (unsigned *)0, cfile);
3136 if (token == COMMA) {
3137 struct expression *foo = (struct expression *)0;
3138 if (!expression_allocate (&foo, MDL))
3139 log_fatal ("can't allocate expr");
3140 expression_reference
3141 (&nexp -> data.pick_first_value.cdr, foo, MDL);
3142 expression_dereference (&nexp, MDL);
3143 expression_reference (&nexp, foo, MDL);
3144 expression_dereference (&foo, MDL);
3146 } while (token == COMMA);
3147 expression_dereference (&nexp, MDL);
3149 if (token != RPAREN)
3150 goto norparen;
3151 break;
3153 /* dns-update and dns-delete are present for historical
3154 purposes, but are deprecated in favor of ns-update
3155 in combination with update, delete, exists and not
3156 exists. */
3157 case DNS_UPDATE:
3158 case DNS_DELETE:
3159 #if !defined (NSUPDATE)
3160 parse_warn (cfile,
3161 "Please rebuild dhcpd with --with-nsupdate.");
3162 #endif
3163 token = next_token (&val, (unsigned *)0, cfile);
3164 if (token == DNS_UPDATE)
3165 opcode = expr_ns_add;
3166 else
3167 opcode = expr_ns_delete;
3169 token = next_token (&val, (unsigned *)0, cfile);
3170 if (token != LPAREN)
3171 goto nolparen;
3173 token = next_token (&val, (unsigned *)0, cfile);
3174 if (token != STRING) {
3175 parse_warn (cfile,
3176 "parse_expression: expecting string.");
3177 badnsupdate:
3178 skip_to_semi (cfile);
3179 *lose = 1;
3180 return 0;
3183 if (!strcasecmp (val, "a"))
3184 u = T_A;
3185 else if (!strcasecmp (val, "ptr"))
3186 u = T_PTR;
3187 else if (!strcasecmp (val, "mx"))
3188 u = T_MX;
3189 else if (!strcasecmp (val, "cname"))
3190 u = T_CNAME;
3191 else if (!strcasecmp (val, "TXT"))
3192 u = T_TXT;
3193 else {
3194 parse_warn (cfile, "unexpected rrtype: %s", val);
3195 goto badnsupdate;
3198 s = (opcode == expr_ns_add
3199 ? "old-dns-update"
3200 : "old-dns-delete");
3201 cptr = dmalloc (strlen (s) + 1, MDL);
3202 if (!cptr)
3203 log_fatal ("can't allocate name for %s", s);
3204 strcpy (cptr, s);
3205 if (!expression_allocate (expr, MDL))
3206 log_fatal ("can't allocate expression");
3207 (*expr) -> op = expr_funcall;
3208 (*expr) -> data.funcall.name = cptr;
3210 /* Fake up a function call. */
3211 ep = &(*expr) -> data.funcall.arglist;
3212 if (!expression_allocate (ep, MDL))
3213 log_fatal ("can't allocate expression");
3214 (*ep) -> op = expr_arg;
3215 if (!make_const_int (&(*ep) -> data.arg.val, u))
3216 log_fatal ("can't allocate rrtype value.");
3218 token = next_token (&val, (unsigned *)0, cfile);
3219 if (token != COMMA)
3220 goto nocomma;
3221 ep = &((*ep) -> data.arg.next);
3222 if (!expression_allocate (ep, MDL))
3223 log_fatal ("can't allocate expression");
3224 (*ep) -> op = expr_arg;
3225 if (!(parse_data_expression (&(*ep) -> data.arg.val,
3226 cfile, lose)))
3227 goto nodata;
3229 token = next_token (&val, (unsigned *)0, cfile);
3230 if (token != COMMA)
3231 goto nocomma;
3233 ep = &((*ep) -> data.arg.next);
3234 if (!expression_allocate (ep, MDL))
3235 log_fatal ("can't allocate expression");
3236 (*ep) -> op = expr_arg;
3237 if (!(parse_data_expression (&(*ep) -> data.arg.val,
3238 cfile, lose)))
3239 goto nodata;
3241 if (opcode == expr_ns_add) {
3242 token = next_token (&val, (unsigned *)0, cfile);
3243 if (token != COMMA)
3244 goto nocomma;
3246 ep = &((*ep) -> data.arg.next);
3247 if (!expression_allocate (ep, MDL))
3248 log_fatal ("can't allocate expression");
3249 (*ep) -> op = expr_arg;
3250 if (!(parse_numeric_expression (&(*ep) -> data.arg.val,
3251 cfile, lose))) {
3252 parse_warn (cfile,
3253 "expecting numeric expression.");
3254 goto badnsupdate;
3258 token = next_token (&val, (unsigned *)0, cfile);
3259 if (token != RPAREN)
3260 goto norparen;
3261 break;
3263 case NS_UPDATE:
3264 #if !defined (NSUPDATE)
3265 parse_warn (cfile,
3266 "Please rebuild dhcpd with --with-nsupdate.");
3267 #endif
3268 token = next_token (&val, (unsigned *)0, cfile);
3269 if (!expression_allocate (expr, MDL))
3270 log_fatal ("can't allocate expression");
3272 token = next_token (&val, (unsigned *)0, cfile);
3273 if (token != LPAREN)
3274 goto nolparen;
3276 nexp = *expr;
3277 do {
3278 nexp -> op = expr_dns_transaction;
3279 if (!(parse_dns_expression
3280 (&nexp -> data.dns_transaction.car,
3281 cfile, lose)))
3283 if (!*lose)
3284 parse_warn
3285 (cfile,
3286 "expecting dns expression.");
3287 expression_dereference (expr, MDL);
3288 *lose = 1;
3289 return 0;
3292 token = next_token (&val, (unsigned *)0, cfile);
3294 if (token == COMMA) {
3295 if (!(expression_allocate
3296 (&nexp -> data.dns_transaction.cdr,
3297 MDL)))
3298 log_fatal
3299 ("can't allocate expression");
3300 nexp = nexp -> data.dns_transaction.cdr;
3302 } while (token == COMMA);
3304 if (token != RPAREN)
3305 goto norparen;
3306 break;
3308 /* NOT EXISTS is special cased above... */
3309 not_exists:
3310 token = peek_token (&val, (unsigned *)0, cfile);
3311 if (token != EXISTS) {
3312 parse_warn (cfile, "expecting DNS prerequisite.");
3313 *lose = 1;
3314 return 0;
3316 opcode = expr_ns_not_exists;
3317 goto nsupdatecode;
3318 case TOKEN_ADD:
3319 opcode = expr_ns_add;
3320 goto nsupdatecode;
3321 case TOKEN_DELETE:
3322 opcode = expr_ns_delete;
3323 goto nsupdatecode;
3324 ns_exists:
3325 opcode = expr_ns_exists;
3326 nsupdatecode:
3327 token = next_token (&val, (unsigned *)0, cfile);
3329 #if !defined (NSUPDATE)
3330 parse_warn (cfile,
3331 "Please rebuild dhcpd with --with-nsupdate.");
3332 #endif
3333 if (!expression_allocate (expr, MDL))
3334 log_fatal ("can't allocate expression");
3335 (*expr) -> op = opcode;
3337 token = next_token (&val, (unsigned *)0, cfile);
3338 if (token != LPAREN)
3339 goto nolparen;
3341 token = next_token (&val, (unsigned *)0, cfile);
3342 if (!is_identifier (token) && token != NUMBER) {
3343 parse_warn (cfile, "expecting identifier or number.");
3344 badnsop:
3345 expression_dereference (expr, MDL);
3346 skip_to_semi (cfile);
3347 *lose = 1;
3348 return 0;
3351 if (token == NUMBER)
3352 (*expr) -> data.ns_add.rrclass = atoi (val);
3353 else if (!strcasecmp (val, "in"))
3354 (*expr) -> data.ns_add.rrclass = C_IN;
3355 else if (!strcasecmp (val, "chaos"))
3356 (*expr) -> data.ns_add.rrclass = C_CHAOS;
3357 else if (!strcasecmp (val, "hs"))
3358 (*expr) -> data.ns_add.rrclass = C_HS;
3359 else {
3360 parse_warn (cfile, "unexpected rrclass: %s", val);
3361 goto badnsop;
3364 token = next_token (&val, (unsigned *)0, cfile);
3365 if (token != COMMA)
3366 goto nocomma;
3368 token = next_token (&val, (unsigned *)0, cfile);
3369 if (!is_identifier (token) && token != NUMBER) {
3370 parse_warn (cfile, "expecting identifier or number.");
3371 goto badnsop;
3374 if (token == NUMBER)
3375 (*expr) -> data.ns_add.rrtype = atoi (val);
3376 else if (!strcasecmp (val, "a"))
3377 (*expr) -> data.ns_add.rrtype = T_A;
3378 else if (!strcasecmp (val, "ptr"))
3379 (*expr) -> data.ns_add.rrtype = T_PTR;
3380 else if (!strcasecmp (val, "mx"))
3381 (*expr) -> data.ns_add.rrtype = T_MX;
3382 else if (!strcasecmp (val, "cname"))
3383 (*expr) -> data.ns_add.rrtype = T_CNAME;
3384 else if (!strcasecmp (val, "TXT"))
3385 (*expr) -> data.ns_add.rrtype = T_TXT;
3386 else {
3387 parse_warn (cfile, "unexpected rrtype: %s", val);
3388 goto badnsop;
3391 token = next_token (&val, (unsigned *)0, cfile);
3392 if (token != COMMA)
3393 goto nocomma;
3395 if (!(parse_data_expression
3396 (&(*expr) -> data.ns_add.rrname, cfile, lose)))
3397 goto nodata;
3399 token = next_token (&val, (unsigned *)0, cfile);
3400 if (token != COMMA)
3401 goto nocomma;
3403 if (!(parse_data_expression
3404 (&(*expr) -> data.ns_add.rrdata, cfile, lose)))
3405 goto nodata;
3407 if (opcode == expr_ns_add) {
3408 token = next_token (&val, (unsigned *)0, cfile);
3409 if (token != COMMA)
3410 goto nocomma;
3412 if (!(parse_numeric_expression
3413 (&(*expr) -> data.ns_add.ttl, cfile,
3414 lose))) {
3415 if (!*lose)
3416 parse_warn (cfile,
3417 "expecting numeric expression.");
3418 goto badnsupdate;
3422 token = next_token (&val, (unsigned *)0, cfile);
3423 if (token != RPAREN)
3424 goto norparen;
3425 break;
3427 case OPTION:
3428 case CONFIG_OPTION:
3429 if (!expression_allocate (expr, MDL))
3430 log_fatal ("can't allocate expression");
3431 (*expr) -> op = (token == OPTION
3432 ? expr_option
3433 : expr_config_option);
3434 token = next_token (&val, (unsigned *)0, cfile);
3435 known = 0;
3436 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
3437 if (!(*expr) -> data.option) {
3438 *lose = 1;
3439 expression_dereference (expr, MDL);
3440 return 0;
3442 break;
3444 case HARDWARE:
3445 token = next_token (&val, (unsigned *)0, cfile);
3446 if (!expression_allocate (expr, MDL))
3447 log_fatal ("can't allocate expression");
3448 (*expr) -> op = expr_hardware;
3449 break;
3451 case LEASED_ADDRESS:
3452 token = next_token (&val, (unsigned *)0, cfile);
3453 if (!expression_allocate (expr, MDL))
3454 log_fatal ("can't allocate expression");
3455 (*expr) -> op = expr_leased_address;
3456 break;
3458 case CLIENT_STATE:
3459 token = next_token (&val, (unsigned *)0, cfile);
3460 if (!expression_allocate (expr, MDL))
3461 log_fatal ("can't allocate expression");
3462 (*expr) -> op = expr_client_state;
3463 break;
3465 case FILENAME:
3466 token = next_token (&val, (unsigned *)0, cfile);
3467 if (!expression_allocate (expr, MDL))
3468 log_fatal ("can't allocate expression");
3469 (*expr) -> op = expr_filename;
3470 break;
3472 case SERVER_NAME:
3473 token = next_token (&val, (unsigned *)0, cfile);
3474 if (!expression_allocate (expr, MDL))
3475 log_fatal ("can't allocate expression");
3476 (*expr) -> op = expr_sname;
3477 break;
3479 case LEASE_TIME:
3480 token = next_token (&val, (unsigned *)0, cfile);
3481 if (!expression_allocate (expr, MDL))
3482 log_fatal ("can't allocate expression");
3483 (*expr) -> op = expr_lease_time;
3484 break;
3486 case TOKEN_NULL:
3487 token = next_token (&val, (unsigned *)0, cfile);
3488 if (!expression_allocate (expr, MDL))
3489 log_fatal ("can't allocate expression");
3490 (*expr) -> op = expr_null;
3491 break;
3493 case HOST_DECL_NAME:
3494 token = next_token (&val, (unsigned *)0, cfile);
3495 if (!expression_allocate (expr, MDL))
3496 log_fatal ("can't allocate expression");
3497 (*expr) -> op = expr_host_decl_name;
3498 break;
3500 case UPDATED_DNS_RR:
3501 token = next_token (&val, (unsigned *)0, cfile);
3503 token = next_token (&val, (unsigned *)0, cfile);
3504 if (token != LPAREN)
3505 goto nolparen;
3507 token = next_token (&val, (unsigned *)0, cfile);
3508 if (token != STRING) {
3509 parse_warn (cfile, "expecting string.");
3510 bad_rrtype:
3511 *lose = 1;
3512 return 0;
3514 if (!strcasecmp (val, "a"))
3515 s = "ddns-fwd-name";
3516 else if (!strcasecmp (val, "ptr"))
3517 s = "ddns-rev-name";
3518 else {
3519 parse_warn (cfile, "invalid DNS rrtype: %s", val);
3520 goto bad_rrtype;
3523 token = next_token (&val, (unsigned *)0, cfile);
3524 if (token != RPAREN)
3525 goto norparen;
3527 if (!expression_allocate (expr, MDL))
3528 log_fatal ("can't allocate expression");
3529 (*expr) -> op = expr_variable_reference;
3530 (*expr) -> data.variable =
3531 dmalloc (strlen (s) + 1, MDL);
3532 if (!(*expr) -> data.variable)
3533 log_fatal ("can't allocate variable name.");
3534 strcpy ((*expr) -> data.variable, s);
3535 break;
3537 case PACKET:
3538 token = next_token (&val, (unsigned *)0, cfile);
3539 if (!expression_allocate (expr, MDL))
3540 log_fatal ("can't allocate expression");
3541 (*expr) -> op = expr_packet;
3543 token = next_token (&val, (unsigned *)0, cfile);
3544 if (token != LPAREN)
3545 goto nolparen;
3547 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
3548 cfile, lose))
3549 goto nonum;
3551 token = next_token (&val, (unsigned *)0, cfile);
3552 if (token != COMMA)
3553 goto nocomma;
3555 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
3556 cfile, lose))
3557 goto nonum;
3559 token = next_token (&val, (unsigned *)0, cfile);
3560 if (token != RPAREN)
3561 goto norparen;
3562 break;
3564 case STRING:
3565 token = next_token (&val, &len, cfile);
3566 if (!make_const_data (expr, (const unsigned char *)val,
3567 len, 1, 1, MDL))
3568 log_fatal ("can't make constant string expression.");
3569 break;
3571 case EXTRACT_INT:
3572 token = next_token (&val, (unsigned *)0, cfile);
3573 token = next_token (&val, (unsigned *)0, cfile);
3574 if (token != LPAREN) {
3575 parse_warn (cfile, "left parenthesis expected.");
3576 *lose = 1;
3577 return 0;
3580 if (!expression_allocate (expr, MDL))
3581 log_fatal ("can't allocate expression");
3583 if (!parse_data_expression (&(*expr) -> data.extract_int,
3584 cfile, lose)) {
3585 if (!*lose) {
3586 parse_warn (cfile,
3587 "expecting data expression.");
3588 skip_to_semi (cfile);
3589 *lose = 1;
3591 expression_dereference (expr, MDL);
3592 return 0;
3595 token = next_token (&val, (unsigned *)0, cfile);
3596 if (token != COMMA) {
3597 parse_warn (cfile, "comma expected.");
3598 *lose = 1;
3599 expression_dereference (expr, MDL);
3600 return 0;
3603 token = next_token (&val, (unsigned *)0, cfile);
3604 if (token != NUMBER) {
3605 parse_warn (cfile, "number expected.");
3606 *lose = 1;
3607 expression_dereference (expr, MDL);
3608 return 0;
3610 switch (atoi (val)) {
3611 case 8:
3612 (*expr) -> op = expr_extract_int8;
3613 break;
3615 case 16:
3616 (*expr) -> op = expr_extract_int16;
3617 break;
3619 case 32:
3620 (*expr) -> op = expr_extract_int32;
3621 break;
3623 default:
3624 parse_warn (cfile,
3625 "unsupported integer size %d", atoi (val));
3626 *lose = 1;
3627 skip_to_semi (cfile);
3628 expression_dereference (expr, MDL);
3629 return 0;
3632 token = next_token (&val, (unsigned *)0, cfile);
3633 if (token != RPAREN) {
3634 parse_warn (cfile, "right parenthesis expected.");
3635 *lose = 1;
3636 expression_dereference (expr, MDL);
3637 return 0;
3639 break;
3641 case ENCODE_INT:
3642 token = next_token (&val, (unsigned *)0, cfile);
3643 token = next_token (&val, (unsigned *)0, cfile);
3644 if (token != LPAREN) {
3645 parse_warn (cfile, "left parenthesis expected.");
3646 *lose = 1;
3647 return 0;
3650 if (!expression_allocate (expr, MDL))
3651 log_fatal ("can't allocate expression");
3653 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
3654 cfile, lose)) {
3655 parse_warn (cfile, "expecting numeric expression.");
3656 skip_to_semi (cfile);
3657 *lose = 1;
3658 expression_dereference (expr, MDL);
3659 return 0;
3662 token = next_token (&val, (unsigned *)0, cfile);
3663 if (token != COMMA) {
3664 parse_warn (cfile, "comma expected.");
3665 *lose = 1;
3666 expression_dereference (expr, MDL);
3667 return 0;
3670 token = next_token (&val, (unsigned *)0, cfile);
3671 if (token != NUMBER) {
3672 parse_warn (cfile, "number expected.");
3673 *lose = 1;
3674 expression_dereference (expr, MDL);
3675 return 0;
3677 switch (atoi (val)) {
3678 case 8:
3679 (*expr) -> op = expr_encode_int8;
3680 break;
3682 case 16:
3683 (*expr) -> op = expr_encode_int16;
3684 break;
3686 case 32:
3687 (*expr) -> op = expr_encode_int32;
3688 break;
3690 default:
3691 parse_warn (cfile,
3692 "unsupported integer size %d", atoi (val));
3693 *lose = 1;
3694 skip_to_semi (cfile);
3695 expression_dereference (expr, MDL);
3696 return 0;
3699 token = next_token (&val, (unsigned *)0, cfile);
3700 if (token != RPAREN) {
3701 parse_warn (cfile, "right parenthesis expected.");
3702 *lose = 1;
3703 expression_dereference (expr, MDL);
3704 return 0;
3706 break;
3708 case NUMBER:
3709 /* If we're in a numeric context, this should just be a
3710 number, by itself. */
3711 if (context == context_numeric ||
3712 context == context_data_or_numeric) {
3713 next_token (&val, (unsigned *)0, cfile);
3714 if (!expression_allocate (expr, MDL))
3715 log_fatal ("can't allocate expression");
3716 (*expr) -> op = expr_const_int;
3717 (*expr) -> data.const_int = atoi (val);
3718 break;
3721 case NUMBER_OR_NAME:
3722 if (!expression_allocate (expr, MDL))
3723 log_fatal ("can't allocate expression");
3725 (*expr) -> op = expr_const_data;
3726 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
3727 expression_dereference (expr, MDL);
3728 return 0;
3730 break;
3732 case NS_FORMERR:
3733 known = FORMERR;
3734 goto ns_const;
3735 ns_const:
3736 token = next_token (&val, (unsigned *)0, cfile);
3737 if (!expression_allocate (expr, MDL))
3738 log_fatal ("can't allocate expression");
3739 (*expr) -> op = expr_const_int;
3740 (*expr) -> data.const_int = known;
3741 break;
3743 case NS_NOERROR:
3744 known = ISC_R_SUCCESS;
3745 goto ns_const;
3747 case NS_NOTAUTH:
3748 known = ISC_R_NOTAUTH;
3749 goto ns_const;
3751 case NS_NOTIMP:
3752 known = ISC_R_NOTIMPLEMENTED;
3753 goto ns_const;
3755 case NS_NOTZONE:
3756 known = ISC_R_NOTZONE;
3757 goto ns_const;
3759 case NS_NXDOMAIN:
3760 known = ISC_R_NXDOMAIN;
3761 goto ns_const;
3763 case NS_NXRRSET:
3764 known = ISC_R_NXRRSET;
3765 goto ns_const;
3767 case NS_REFUSED:
3768 known = ISC_R_REFUSED;
3769 goto ns_const;
3771 case NS_SERVFAIL:
3772 known = ISC_R_SERVFAIL;
3773 goto ns_const;
3775 case NS_YXDOMAIN:
3776 known = ISC_R_YXDOMAIN;
3777 goto ns_const;
3779 case NS_YXRRSET:
3780 known = ISC_R_YXRRSET;
3781 goto ns_const;
3783 case BOOTING:
3784 known = S_INIT;
3785 goto ns_const;
3787 case REBOOT:
3788 known = S_REBOOTING;
3789 goto ns_const;
3791 case SELECT:
3792 known = S_SELECTING;
3793 goto ns_const;
3795 case REQUEST:
3796 known = S_REQUESTING;
3797 goto ns_const;
3799 case BOUND:
3800 known = S_BOUND;
3801 goto ns_const;
3803 case RENEW:
3804 known = S_RENEWING;
3805 goto ns_const;
3807 case REBIND:
3808 known = S_REBINDING;
3809 goto ns_const;
3811 case DEFINED:
3812 token = next_token (&val, (unsigned *)0, cfile);
3813 token = next_token (&val, (unsigned *)0, cfile);
3814 if (token != LPAREN)
3815 goto nolparen;
3817 token = next_token (&val, (unsigned *)0, cfile);
3818 if (token != NAME && token != NUMBER_OR_NAME) {
3819 parse_warn (cfile, "%s can't be a variable name", val);
3820 skip_to_semi (cfile);
3821 *lose = 1;
3822 return 0;
3825 if (!expression_allocate (expr, MDL))
3826 log_fatal ("can't allocate expression");
3827 (*expr) -> op = expr_variable_exists;
3828 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
3829 if (!(*expr)->data.variable)
3830 log_fatal ("can't allocate variable name");
3831 strcpy ((*expr) -> data.variable, val);
3832 token = next_token (&val, (unsigned *)0, cfile);
3833 if (token != RPAREN)
3834 goto norparen;
3835 break;
3837 /* Not a valid start to an expression... */
3838 default:
3839 if (token != NAME && token != NUMBER_OR_NAME)
3840 return 0;
3842 token = next_token (&val, (unsigned *)0, cfile);
3844 /* Save the name of the variable being referenced. */
3845 cptr = dmalloc (strlen (val) + 1, MDL);
3846 if (!cptr)
3847 log_fatal ("can't allocate variable name");
3848 strcpy (cptr, val);
3850 /* Simple variable reference, as far as we can tell. */
3851 token = peek_token (&val, (unsigned *)0, cfile);
3852 if (token != LPAREN) {
3853 if (!expression_allocate (expr, MDL))
3854 log_fatal ("can't allocate expression");
3855 (*expr) -> op = expr_variable_reference;
3856 (*expr) -> data.variable = cptr;
3857 break;
3860 token = next_token (&val, (unsigned *)0, cfile);
3861 if (!expression_allocate (expr, MDL))
3862 log_fatal ("can't allocate expression");
3863 (*expr) -> op = expr_funcall;
3864 (*expr) -> data.funcall.name = cptr;
3866 /* Now parse the argument list. */
3867 ep = &(*expr) -> data.funcall.arglist;
3868 do {
3869 if (!expression_allocate (ep, MDL))
3870 log_fatal ("can't allocate expression");
3871 (*ep) -> op = expr_arg;
3872 if (!parse_expression (&(*ep) -> data.arg.val,
3873 cfile, lose, context_any,
3874 (struct expression **)0,
3875 expr_none)) {
3876 if (!*lose) {
3877 parse_warn (cfile,
3878 "expecting expression.");
3879 *lose = 1;
3881 skip_to_semi (cfile);
3882 expression_dereference (expr, MDL);
3883 return 0;
3885 ep = &((*ep) -> data.arg.next);
3886 token = next_token (&val, (unsigned *)0, cfile);
3887 } while (token == COMMA);
3888 if (token != RPAREN) {
3889 parse_warn (cfile, "Right parenthesis expected.");
3890 skip_to_semi (cfile);
3891 *lose = 1;
3892 expression_dereference (expr, MDL);
3893 return 0;
3895 break;
3897 return 1;
3900 /* Parse an expression. */
3902 int parse_expression (expr, cfile, lose, context, plhs, binop)
3903 struct expression **expr;
3904 struct parse *cfile;
3905 int *lose;
3906 enum expression_context context;
3907 struct expression **plhs;
3908 enum expr_op binop;
3910 enum dhcp_token token;
3911 const char *val;
3912 struct expression *rhs = (struct expression *)0, *tmp;
3913 struct expression *lhs = (struct expression *)0;
3914 enum expr_op next_op;
3915 enum expression_context
3916 lhs_context = context_any,
3917 rhs_context = context_any;
3919 /* Consume the left hand side we were passed. */
3920 if (plhs) {
3921 expression_reference (&lhs, *plhs, MDL);
3922 expression_dereference (plhs, MDL);
3925 new_rhs:
3926 if (!parse_non_binary (&rhs, cfile, lose, context)) {
3927 /* If we already have a left-hand side, then it's not
3928 okay for there not to be a right-hand side here, so
3929 we need to flag it as an error. */
3930 if (lhs) {
3931 if (!*lose) {
3932 parse_warn (cfile,
3933 "expecting right-hand side.");
3934 *lose = 1;
3935 skip_to_semi (cfile);
3937 expression_dereference (&lhs, MDL);
3939 return 0;
3942 /* At this point, rhs contains either an entire subexpression,
3943 or at least a left-hand-side. If we do not see a binary token
3944 as the next token, we're done with the expression. */
3946 token = peek_token (&val, (unsigned *)0, cfile);
3947 switch (token) {
3948 case BANG:
3949 token = next_token (&val, (unsigned *)0, cfile);
3950 token = peek_token (&val, (unsigned *)0, cfile);
3951 if (token != EQUAL) {
3952 parse_warn (cfile, "! in boolean context without =");
3953 *lose = 1;
3954 skip_to_semi (cfile);
3955 if (lhs)
3956 expression_dereference (&lhs, MDL);
3957 return 0;
3959 next_op = expr_not_equal;
3960 context = expression_context (rhs);
3961 break;
3963 case EQUAL:
3964 next_op = expr_equal;
3965 context = expression_context (rhs);
3966 break;
3968 case AND:
3969 next_op = expr_and;
3970 context = expression_context (rhs);
3971 break;
3973 case OR:
3974 next_op = expr_or;
3975 context = expression_context (rhs);
3976 break;
3978 case PLUS:
3979 next_op = expr_add;
3980 context = expression_context (rhs);
3981 break;
3983 case MINUS:
3984 next_op = expr_subtract;
3985 context = expression_context (rhs);
3986 break;
3988 case SLASH:
3989 next_op = expr_divide;
3990 context = expression_context (rhs);
3991 break;
3993 case ASTERISK:
3994 next_op = expr_multiply;
3995 context = expression_context (rhs);
3996 break;
3998 case PERCENT:
3999 next_op = expr_remainder;
4000 context = expression_context (rhs);
4001 break;
4003 case AMPERSAND:
4004 next_op = expr_binary_and;
4005 context = expression_context (rhs);
4006 break;
4008 case PIPE:
4009 next_op = expr_binary_or;
4010 context = expression_context (rhs);
4011 break;
4013 case CARET:
4014 next_op = expr_binary_xor;
4015 context = expression_context (rhs);
4016 break;
4018 default:
4019 next_op = expr_none;
4022 /* If we have no lhs yet, we just parsed it. */
4023 if (!lhs) {
4024 /* If there was no operator following what we just parsed,
4025 then we're done - return it. */
4026 if (next_op == expr_none) {
4027 *expr = rhs;
4028 return 1;
4030 lhs = rhs;
4031 rhs = (struct expression *)0;
4032 binop = next_op;
4033 next_token (&val, (unsigned *)0, cfile);
4034 goto new_rhs;
4037 /* If the next binary operator is of greater precedence than the
4038 * current operator, then rhs we have parsed so far is actually
4039 * the lhs of the next operator. To get this value, we have to
4040 * recurse.
4042 if (binop != expr_none && next_op != expr_none &&
4043 op_precedence (binop, next_op) < 0) {
4045 /* Eat the subexpression operator token, which we pass to
4046 * parse_expression...we only peek()'d earlier.
4048 token = next_token (&val, (unsigned *)0, cfile);
4050 /* Continue parsing of the right hand side with that token. */
4051 tmp = rhs;
4052 rhs = (struct expression *)0;
4053 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
4054 &tmp, next_op)) {
4055 if (!*lose) {
4056 parse_warn (cfile,
4057 "expecting a subexpression");
4058 *lose = 1;
4060 return 0;
4062 next_op = expr_none;
4065 if (binop != expr_none) {
4066 rhs_context = expression_context(rhs);
4067 lhs_context = expression_context(lhs);
4069 if ((rhs_context != context_any) && (lhs_context != context_any) &&
4070 (rhs_context != lhs_context)) {
4071 parse_warn (cfile, "illegal expression relating different types");
4072 skip_to_semi (cfile);
4073 expression_dereference (&rhs, MDL);
4074 expression_dereference (&lhs, MDL);
4075 *lose = 1;
4076 return 0;
4079 switch(binop) {
4080 case expr_not_equal:
4081 case expr_equal:
4082 if ((rhs_context != context_data_or_numeric) &&
4083 (rhs_context != context_data) &&
4084 (rhs_context != context_numeric) &&
4085 (rhs_context != context_any)) {
4086 parse_warn (cfile, "expecting data/numeric expression");
4087 skip_to_semi (cfile);
4088 expression_dereference (&rhs, MDL);
4089 *lose = 1;
4090 return 0;
4092 break;
4094 case expr_and:
4095 case expr_or:
4096 if ((rhs_context != context_boolean) &&
4097 (rhs_context != context_any)) {
4098 parse_warn (cfile, "expecting boolean expressions");
4099 skip_to_semi (cfile);
4100 expression_dereference (&rhs, MDL);
4101 *lose = 1;
4102 return 0;
4104 break;
4106 case expr_add:
4107 case expr_subtract:
4108 case expr_divide:
4109 case expr_multiply:
4110 case expr_remainder:
4111 case expr_binary_and:
4112 case expr_binary_or:
4113 case expr_binary_xor:
4114 if ((rhs_context != context_numeric) &&
4115 (rhs_context != context_any)) {
4116 parse_warn (cfile, "expecting numeric expressions");
4117 skip_to_semi (cfile);
4118 expression_dereference (&rhs, MDL);
4119 *lose = 1;
4120 return 0;
4122 break;
4124 default:
4125 break;
4129 /* Now, if we didn't find a binary operator, we're done parsing
4130 this subexpression, so combine it with the preceding binary
4131 operator and return the result. */
4132 if (next_op == expr_none) {
4133 if (!expression_allocate (expr, MDL))
4134 log_fatal ("Can't allocate expression!");
4136 (*expr) -> op = binop;
4137 /* All the binary operators' data union members
4138 are the same, so we'll cheat and use the member
4139 for the equals operator. */
4140 (*expr) -> data.equal [0] = lhs;
4141 (*expr) -> data.equal [1] = rhs;
4142 return 1;
4145 /* Eat the operator token - we now know it was a binary operator... */
4146 token = next_token (&val, (unsigned *)0, cfile);
4148 /* Now combine the LHS and the RHS using binop. */
4149 tmp = (struct expression *)0;
4150 if (!expression_allocate (&tmp, MDL))
4151 log_fatal ("No memory for equal precedence combination.");
4153 /* Store the LHS and RHS. */
4154 tmp -> data.equal [0] = lhs;
4155 tmp -> data.equal [1] = rhs;
4156 tmp -> op = binop;
4158 lhs = tmp;
4159 tmp = (struct expression *)0;
4160 rhs = (struct expression *)0;
4162 /* Recursions don't return until we have parsed the end of the
4163 expression, so if we recursed earlier, we can now return what
4164 we got. */
4165 if (next_op == expr_none) {
4166 *expr = lhs;
4167 return 1;
4170 binop = next_op;
4171 goto new_rhs;
4174 /* option-statement :== identifier DOT identifier <syntax> SEMI
4175 | identifier <syntax> SEMI
4177 Option syntax is handled specially through format strings, so it
4178 would be painful to come up with BNF for it. However, it always
4179 starts as above and ends in a SEMI. */
4181 int parse_option_statement (result, cfile, lookups, option, op)
4182 struct executable_statement **result;
4183 struct parse *cfile;
4184 int lookups;
4185 struct option *option;
4186 enum statement_op op;
4188 const char *val;
4189 enum dhcp_token token;
4190 const char *fmt = NULL;
4191 struct expression *expr = (struct expression *)0;
4192 struct expression *tmp;
4193 int lose;
4194 // struct executable_statement *stmt;
4195 // int ftt = 1;
4197 token = peek_token (&val, (unsigned *)0, cfile);
4198 if (token == SEMI) {
4199 /* Eat the semicolon... */
4200 token = next_token (&val, (unsigned *)0, cfile);
4201 goto done;
4204 if (token == EQUAL) {
4205 /* Eat the equals sign. */
4206 token = next_token (&val, (unsigned *)0, cfile);
4208 /* Parse a data expression and use its value for the data. */
4209 if (!parse_data_expression (&expr, cfile, &lose)) {
4210 /* In this context, we must have an executable
4211 statement, so if we found something else, it's
4212 still an error. */
4213 if (!lose) {
4214 parse_warn (cfile,
4215 "expecting a data expression.");
4216 skip_to_semi (cfile);
4218 return 0;
4221 /* We got a valid expression, so use it. */
4222 goto done;
4225 /* Parse the option data... */
4226 do {
4227 /* Set a flag if this is an array of a simple type (i.e.,
4228 not an array of pairs of IP addresses, or something
4229 like that. */
4230 int uniform = option -> format [1] == 'A';
4232 and_again:
4233 /* Set fmt to start of format for 'A' and one char back
4234 for 'a' */
4235 if ((fmt != NULL) &&
4236 (fmt != option -> format) && (*fmt == 'a'))
4237 fmt -= 1;
4238 else
4239 fmt = ((fmt == NULL) ||
4240 (*fmt == 'A')) ? option -> format : fmt;
4242 /* 'a' means always uniform */
4243 uniform |= (fmt [1] == 'a');
4245 for ( ; *fmt; fmt++) {
4246 if ((*fmt == 'A') || (*fmt == 'a'))
4247 break;
4248 if (*fmt == 'o')
4249 continue;
4250 tmp = expr;
4251 expr = (struct expression *)0;
4252 if (!parse_option_token (&expr, cfile, &fmt,
4253 tmp, uniform, lookups)) {
4254 if (fmt [1] != 'o') {
4255 if (tmp)
4256 expression_dereference (&tmp,
4257 MDL);
4258 return 0;
4260 expr = tmp;
4261 tmp = (struct expression *)0;
4263 if (tmp)
4264 expression_dereference (&tmp, MDL);
4266 if ((*fmt == 'A') || (*fmt == 'a')) {
4267 token = peek_token (&val, (unsigned *)0, cfile);
4268 /* Comma means: continue with next element in array */
4269 if (token == COMMA) {
4270 token = next_token (&val,
4271 (unsigned *)0, cfile);
4272 continue;
4274 /* no comma: end of array.
4275 'A' or end of string means: leave the loop */
4276 if ((*fmt == 'A') || (fmt[1] == '\0'))
4277 break;
4278 /* 'a' means: go on with next char */
4279 if (*fmt == 'a') {
4280 fmt++;
4281 goto and_again;
4284 } while ((*fmt == 'A') || (*fmt == 'a'));
4286 done:
4287 if (!parse_semi (cfile))
4288 return 0;
4289 if (!executable_statement_allocate (result, MDL))
4290 log_fatal ("no memory for option statement.");
4291 (*result) -> op = op;
4292 if (expr && !option_cache (&(*result) -> data.option,
4293 (struct data_string *)0, expr, option, MDL))
4294 log_fatal ("no memory for option cache");
4295 if (expr)
4296 expression_dereference (&expr, MDL);
4297 return 1;
4300 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
4301 struct expression **rv;
4302 struct parse *cfile;
4303 const char **fmt;
4304 struct expression *expr;
4305 int uniform;
4306 int lookups;
4308 const char *val;
4309 enum dhcp_token token;
4310 struct expression *t = (struct expression *)0;
4311 unsigned char buf [4];
4312 unsigned len;
4313 // unsigned char *ob;
4314 struct iaddr addr;
4315 // int num;
4316 const char *f, *g;
4317 struct enumeration_value *e;
4319 switch (**fmt) {
4320 case 'U':
4321 token = next_token (&val, &len, cfile);
4322 if (!is_identifier (token)) {
4323 if ((*fmt) [1] != 'o') {
4324 parse_warn (cfile, "expecting identifier.");
4325 if (token != SEMI)
4326 skip_to_semi (cfile);
4328 return 0;
4330 if (!make_const_data (&t, (const unsigned char *)val,
4331 len, 1, 1, MDL))
4332 log_fatal ("No memory for %s", val);
4333 break;
4335 case 'E':
4336 g = strchr (*fmt, '.');
4337 if (!g) {
4338 parse_warn (cfile,
4339 "malformed encapsulation format (bug!)");
4340 skip_to_semi (cfile);
4341 return 0;
4343 *fmt = g;
4344 case 'X':
4345 token = peek_token (&val, (unsigned *)0, cfile);
4346 if (token == NUMBER_OR_NAME || token == NUMBER) {
4347 if (!expression_allocate (&t, MDL))
4348 return 0;
4349 if (!parse_cshl (&t -> data.const_data, cfile)) {
4350 expression_dereference (&t, MDL);
4351 return 0;
4353 t -> op = expr_const_data;
4354 } else {
4355 token = next_token (&val, &len, cfile);
4357 if(token == STRING) {
4358 if (!make_const_data (&t,
4359 (const unsigned char *)val,
4360 len, 1, 1, MDL))
4361 log_fatal ("No memory for \"%s\"", val);
4362 } else if ((*fmt) [1] != 'o') {
4363 parse_warn (cfile, "expecting string %s.",
4364 "or hexadecimal data");
4365 skip_to_semi (cfile);
4366 } else {
4367 return 0;
4370 break;
4372 case 'd': /* Domain name... */
4373 val = parse_host_name (cfile);
4374 if (!val) {
4375 parse_warn (cfile, "not a valid domain name.");
4376 skip_to_semi (cfile);
4377 return 0;
4379 len = strlen (val);
4380 goto make_string;
4382 case 't': /* Text string... */
4383 token = next_token (&val, &len, cfile);
4384 if (token != STRING && !is_identifier (token)) {
4385 if ((*fmt) [1] != 'o') {
4386 parse_warn (cfile, "expecting string.");
4387 if (token != SEMI)
4388 skip_to_semi (cfile);
4390 return 0;
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 = next_token (&val, (unsigned *)0, cfile);
4439 if (token != INFINITE)
4440 goto check_number;
4441 putLong (buf, -1);
4442 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
4443 return 0;
4444 break;
4446 case 'L': /* Unsigned 32-bit integer... */
4447 case 'l': /* Signed 32-bit integer... */
4448 token = next_token (&val, (unsigned *)0, cfile);
4449 check_number:
4450 if ((token != NUMBER) && (token != NUMBER_OR_NAME)) {
4451 need_number:
4452 if ((*fmt) [1] != 'o') {
4453 parse_warn (cfile, "expecting number.");
4454 if (token != SEMI)
4455 skip_to_semi (cfile);
4457 return 0;
4459 convert_num (cfile, buf, val, 0, 32);
4460 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
4461 return 0;
4462 break;
4464 case 's': /* Signed 16-bit integer. */
4465 case 'S': /* Unsigned 16-bit integer. */
4466 token = next_token (&val, (unsigned *)0, cfile);
4467 if ((token != NUMBER) && (token != NUMBER_OR_NAME))
4468 goto need_number;
4469 convert_num (cfile, buf, val, 0, 16);
4470 if (!make_const_data (&t, buf, 2, 0, 1, MDL))
4471 return 0;
4472 break;
4474 case 'b': /* Signed 8-bit integer. */
4475 case 'B': /* Unsigned 8-bit integer. */
4476 token = next_token (&val, (unsigned *)0, cfile);
4477 if ((token != NUMBER) && (token != NUMBER_OR_NAME))
4478 goto need_number;
4479 convert_num (cfile, buf, val, 0, 8);
4480 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
4481 return 0;
4482 break;
4484 case 'f': /* Boolean flag. */
4485 token = next_token (&val, (unsigned *)0, cfile);
4486 if (!is_identifier (token)) {
4487 if ((*fmt) [1] != 'o')
4488 parse_warn (cfile, "expecting identifier.");
4489 bad_flag:
4490 if ((*fmt) [1] != 'o') {
4491 if (token != SEMI)
4492 skip_to_semi (cfile);
4494 return 0;
4496 if (!strcasecmp (val, "true")
4497 || !strcasecmp (val, "on"))
4498 buf [0] = 1;
4499 else if (!strcasecmp (val, "false")
4500 || !strcasecmp (val, "off"))
4501 buf [0] = 0;
4502 else if (!strcasecmp (val, "ignore"))
4503 buf [0] = 2;
4504 else {
4505 if ((*fmt) [1] != 'o')
4506 parse_warn (cfile, "expecting boolean.");
4507 goto bad_flag;
4509 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
4510 return 0;
4511 break;
4513 default:
4514 parse_warn (cfile, "Bad format %c in parse_option_token.",
4515 **fmt);
4516 skip_to_semi (cfile);
4517 return 0;
4519 if (expr) {
4520 if (!make_concat (rv, expr, t))
4521 return 0;
4522 } else
4523 expression_reference (rv, t, MDL);
4524 expression_dereference (&t, MDL);
4525 return 1;
4528 int parse_option_decl (oc, cfile)
4529 struct option_cache **oc;
4530 struct parse *cfile;
4532 const char *val;
4533 int token;
4534 u_int8_t buf [4];
4535 u_int8_t hunkbuf [1024];
4536 unsigned hunkix = 0;
4537 const char *fmt, *f;
4538 struct option *option;
4539 struct iaddr ip_addr;
4540 u_int8_t *dp;
4541 unsigned len;
4542 int nul_term = 0;
4543 struct buffer *bp;
4544 int known = 0;
4545 struct enumeration_value *e;
4547 option = parse_option_name (cfile, 0, &known);
4548 if (!option)
4549 return 0;
4551 /* Parse the option data... */
4552 do {
4553 /* Set a flag if this is an array of a simple type (i.e.,
4554 not an array of pairs of IP addresses, or something
4555 like that. */
4556 // int uniform = option -> format [1] == 'A';
4558 for (fmt = option -> format; *fmt; fmt++) {
4559 if (*fmt == 'A')
4560 break;
4561 switch (*fmt) {
4562 case 'E':
4563 fmt = strchr (fmt, '.');
4564 if (!fmt) {
4565 parse_warn (cfile,
4566 "malformed %s (bug!)",
4567 "encapsulation format");
4568 skip_to_semi (cfile);
4569 return 0;
4571 case 'X':
4572 len = parse_X (cfile, &hunkbuf [hunkix],
4573 sizeof hunkbuf - hunkix);
4574 hunkix += len;
4575 break;
4577 case 't': /* Text string... */
4578 token = next_token (&val,
4579 &len, cfile);
4580 if (token != STRING) {
4581 parse_warn (cfile,
4582 "expecting string.");
4583 skip_to_semi (cfile);
4584 return 0;
4586 if (hunkix + len + 1 > sizeof hunkbuf) {
4587 parse_warn (cfile,
4588 "option data buffer %s",
4589 "overflow");
4590 skip_to_semi (cfile);
4591 return 0;
4593 memcpy (&hunkbuf [hunkix], val, len + 1);
4594 nul_term = 1;
4595 hunkix += len;
4596 break;
4598 case 'N':
4599 f = fmt;
4600 fmt = strchr (fmt, '.');
4601 if (!fmt) {
4602 parse_warn (cfile,
4603 "malformed %s (bug!)",
4604 "enumeration format");
4605 foo:
4606 skip_to_semi (cfile);
4607 return 0;
4609 token = next_token (&val,
4610 (unsigned *)0, cfile);
4611 if (!is_identifier (token)) {
4612 parse_warn (cfile,
4613 "identifier expected");
4614 goto foo;
4616 e = find_enumeration_value (f, fmt - f, val);
4617 if (!e) {
4618 parse_warn (cfile,
4619 "unknown value");
4620 goto foo;
4622 len = 1;
4623 dp = &e -> value;
4624 goto alloc;
4626 case 'I': /* IP address. */
4627 if (!parse_ip_addr (cfile, &ip_addr))
4628 return 0;
4629 len = ip_addr.len;
4630 dp = ip_addr.iabuf;
4632 alloc:
4633 if (hunkix + len > sizeof hunkbuf) {
4634 parse_warn (cfile,
4635 "option data buffer %s",
4636 "overflow");
4637 skip_to_semi (cfile);
4638 return 0;
4640 memcpy (&hunkbuf [hunkix], dp, len);
4641 hunkix += len;
4642 break;
4644 case 'L': /* Unsigned 32-bit integer... */
4645 case 'l': /* Signed 32-bit integer... */
4646 token = next_token (&val,
4647 (unsigned *)0, cfile);
4648 if ((token != NUMBER) &&
4649 (token != NUMBER_OR_NAME)) {
4650 need_number:
4651 parse_warn (cfile,
4652 "expecting number.");
4653 if (token != SEMI)
4654 skip_to_semi (cfile);
4655 return 0;
4657 convert_num (cfile, buf, val, 0, 32);
4658 len = 4;
4659 dp = buf;
4660 goto alloc;
4662 case 's': /* Signed 16-bit integer. */
4663 case 'S': /* Unsigned 16-bit integer. */
4664 token = next_token (&val,
4665 (unsigned *)0, cfile);
4666 if ((token != NUMBER) &&
4667 (token != NUMBER_OR_NAME))
4668 goto need_number;
4669 convert_num (cfile, buf, val, 0, 16);
4670 len = 2;
4671 dp = buf;
4672 goto alloc;
4674 case 'b': /* Signed 8-bit integer. */
4675 case 'B': /* Unsigned 8-bit integer. */
4676 token = next_token (&val,
4677 (unsigned *)0, cfile);
4678 if ((token != NUMBER) &&
4679 (token != NUMBER_OR_NAME))
4680 goto need_number;
4681 convert_num (cfile, buf, val, 0, 8);
4682 len = 1;
4683 dp = buf;
4684 goto alloc;
4686 case 'f': /* Boolean flag. */
4687 token = next_token (&val,
4688 (unsigned *)0, cfile);
4689 if (!is_identifier (token)) {
4690 parse_warn (cfile,
4691 "expecting identifier.");
4692 bad_flag:
4693 if (token != SEMI)
4694 skip_to_semi (cfile);
4695 return 0;
4697 if (!strcasecmp (val, "true")
4698 || !strcasecmp (val, "on"))
4699 buf [0] = 1;
4700 else if (!strcasecmp (val, "false")
4701 || !strcasecmp (val, "off"))
4702 buf [0] = 0;
4703 else {
4704 parse_warn (cfile,
4705 "expecting boolean.");
4706 goto bad_flag;
4708 len = 1;
4709 dp = buf;
4710 goto alloc;
4712 default:
4713 log_error ("parse_option_param: Bad format %c",
4714 *fmt);
4715 skip_to_semi (cfile);
4716 return 0;
4719 token = next_token (&val, (unsigned *)0, cfile);
4720 } while (*fmt == 'A' && token == COMMA);
4722 if (token != SEMI) {
4723 parse_warn (cfile, "semicolon expected.");
4724 skip_to_semi (cfile);
4725 return 0;
4728 bp = (struct buffer *)0;
4729 if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
4730 log_fatal ("no memory to store option declaration.");
4731 if (!bp -> data)
4732 log_fatal ("out of memory allocating option data.");
4733 memcpy (bp -> data, hunkbuf, hunkix + nul_term);
4735 if (!option_cache_allocate (oc, MDL))
4736 log_fatal ("out of memory allocating option cache.");
4738 (*oc) -> data.buffer = bp;
4739 (*oc) -> data.data = &bp -> data [0];
4740 (*oc) -> data.terminated = nul_term;
4741 (*oc) -> data.len = hunkix;
4742 (*oc) -> option = option;
4743 return 1;
4746 /* Consider merging parse_cshl into this. */
4748 int parse_X (cfile, buf, max)
4749 struct parse *cfile;
4750 u_int8_t *buf;
4751 unsigned max;
4753 int token;
4754 const char *val;
4755 unsigned len;
4756 // u_int8_t *s;
4758 token = peek_token (&val, (unsigned *)0, cfile);
4759 if (token == NUMBER_OR_NAME || token == NUMBER) {
4760 len = 0;
4761 do {
4762 token = next_token (&val, (unsigned *)0, cfile);
4763 if (token != NUMBER && token != NUMBER_OR_NAME) {
4764 parse_warn (cfile,
4765 "expecting hexadecimal constant.");
4766 skip_to_semi (cfile);
4767 return 0;
4769 convert_num (cfile, &buf [len], val, 16, 8);
4770 if (len++ > max) {
4771 parse_warn (cfile,
4772 "hexadecimal constant too long.");
4773 skip_to_semi (cfile);
4774 return 0;
4776 token = peek_token (&val, (unsigned *)0, cfile);
4777 if (token == COLON)
4778 token = next_token (&val,
4779 (unsigned *)0, cfile);
4780 } while (token == COLON);
4781 val = (char *)buf;
4782 } else if (token == STRING) {
4783 token = next_token (&val, &len, cfile);
4784 if (len + 1 > max) {
4785 parse_warn (cfile, "string constant too long.");
4786 skip_to_semi (cfile);
4787 return 0;
4789 memcpy (buf, val, len + 1);
4790 } else {
4791 parse_warn (cfile, "expecting string or hexadecimal data");
4792 skip_to_semi (cfile);
4793 return 0;
4795 return len;
4798 int parse_warn (struct parse *cfile, const char *fmt, ...)
4800 va_list list;
4801 char lexbuf [256];
4802 char mbuf [1024];
4803 char fbuf [1024];
4804 unsigned i, lix;
4806 do_percentm (mbuf, fmt);
4807 /* %Audit% This is log output. %2004.06.17,Safe%
4808 * If we truncate we hope the user can get a hint from the log.
4810 snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
4811 cfile -> tlname, cfile -> lexline, mbuf);
4813 va_start (list, fmt);
4814 vsnprintf (mbuf, sizeof mbuf, fbuf, list);
4815 va_end (list);
4817 lix = 0;
4818 for (i = 0;
4819 cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
4820 if (lix < (sizeof lexbuf) - 1)
4821 lexbuf [lix++] = ' ';
4822 if (cfile -> token_line [i] == '\t') {
4823 for ( ;
4824 lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
4825 lexbuf [lix] = ' ';
4828 lexbuf [lix] = 0;
4830 #ifndef DEBUG
4831 syslog (log_priority | LOG_ERR, "%s", mbuf);
4832 syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
4833 if (cfile -> lexchar < 81)
4834 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
4835 #endif
4837 if (log_perror) {
4838 write (STDERR_FILENO, mbuf, strlen (mbuf));
4839 write (STDERR_FILENO, "\n", 1);
4840 write (STDERR_FILENO, cfile -> token_line,
4841 strlen (cfile -> token_line));
4842 write (STDERR_FILENO, "\n", 1);
4843 if (cfile -> lexchar < 81)
4844 write (STDERR_FILENO, lexbuf, lix);
4845 write (STDERR_FILENO, "^\n", 2);
4848 cfile -> warnings_occurred = 1;
4850 return 0;