]> git.ipfire.org Git - thirdparty/dhcp.git/blame - common/parse.c
Add a section documenting event support.
[thirdparty/dhcp.git] / common / parse.c
CommitLineData
63115431
TL
1/* parse.c
2
3 Common parser code for dhcpd and dhclient. */
4
5/*
f39b6e00
TL
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
63115431 12 *
f39b6e00 13 * http://www.isc.org/isc-license-1.0.html.
63115431 14 *
f39b6e00
TL
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
63115431 18 *
f39b6e00
TL
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
63115431
TL
21 */
22
23#ifndef lint
24static char copyright[] =
79a65726 25"$Id: parse.c,v 1.29 1999/07/16 21:33:59 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
63115431
TL
26#endif /* not lint */
27
28#include "dhcpd.h"
29#include "dhctoken.h"
30
31/* Skip to the semicolon ending the current statement. If we encounter
32 braces, the matching closing brace terminates the statement. If we
33 encounter a right brace but haven't encountered a left brace, return
34 leaving the brace in the token buffer for the caller. If we see a
35 semicolon and haven't seen a left brace, return. This lets us skip
36 over:
37
38 statement;
39 statement foo bar { }
40 statement foo bar { statement { } }
41 statement}
42
43 ...et cetera. */
44
45void skip_to_semi (cfile)
46 FILE *cfile;
cea8b5c9
TL
47{
48 skip_to_rbrace (cfile, 0);
49}
50
51void skip_to_rbrace (cfile, brace_count)
52 FILE *cfile;
53 int brace_count;
63115431 54{
02a015fb 55 enum dhcp_token token;
63115431 56 char *val;
63115431
TL
57
58 do {
59 token = peek_token (&val, cfile);
60 if (token == RBRACE) {
efc79acb 61 token = next_token (&val, cfile);
63115431 62 if (brace_count) {
63115431
TL
63 if (!--brace_count)
64 return;
65 } else
66 return;
67 } else if (token == LBRACE) {
68 brace_count++;
69 } else if (token == SEMI && !brace_count) {
70 token = next_token (&val, cfile);
71 return;
796ef008
TL
72 } else if (token == EOL) {
73 /* EOL only happens when parsing /etc/resolv.conf,
74 and we treat it like a semicolon because the
75 resolv.conf file is line-oriented. */
76 token = next_token (&val, cfile);
77 return;
63115431
TL
78 }
79 token = next_token (&val, cfile);
80 } while (token != EOF);
81}
82
83int parse_semi (cfile)
84 FILE *cfile;
85{
02a015fb 86 enum dhcp_token token;
63115431
TL
87 char *val;
88
89 token = next_token (&val, cfile);
90 if (token != SEMI) {
91 parse_warn ("semicolon expected.");
92 skip_to_semi (cfile);
93 return 0;
94 }
95 return 1;
96}
97
98/* string-parameter :== STRING SEMI */
99
100char *parse_string (cfile)
101 FILE *cfile;
102{
103 char *val;
02a015fb 104 enum dhcp_token token;
63115431
TL
105 char *s;
106
107 token = next_token (&val, cfile);
108 if (token != STRING) {
109 parse_warn ("filename must be a string");
110 skip_to_semi (cfile);
111 return (char *)0;
112 }
113 s = (char *)malloc (strlen (val) + 1);
114 if (!s)
8ae2d595 115 log_fatal ("no memory for string %s.", val);
63115431
TL
116 strcpy (s, val);
117
118 if (!parse_semi (cfile))
119 return (char *)0;
120 return s;
121}
122
be6be08d
TL
123/*
124 * hostname :== IDENTIFIER
125 * | IDENTIFIER DOT
126 * | hostname DOT IDENTIFIER
127 */
796ef008
TL
128
129char *parse_host_name (cfile)
130 FILE *cfile;
131{
132 char *val;
02a015fb 133 enum dhcp_token token;
796ef008
TL
134 int len = 0;
135 char *s;
136 char *t;
137 pair c = (pair)0;
138
139 /* Read a dotted hostname... */
140 do {
141 /* Read a token, which should be an identifier. */
68dda014
TL
142 token = peek_token (&val, cfile);
143 if (!is_identifier (token) && token != NUMBER)
144 break;
796ef008 145 token = next_token (&val, cfile);
68dda014 146
796ef008
TL
147 /* Store this identifier... */
148 if (!(s = (char *)malloc (strlen (val) + 1)))
8ae2d595 149 log_fatal ("can't allocate temp space for hostname.");
796ef008
TL
150 strcpy (s, val);
151 c = cons ((caddr_t)s, c);
152 len += strlen (s) + 1;
153 /* Look for a dot; if it's there, keep going, otherwise
154 we're done. */
155 token = peek_token (&val, cfile);
156 if (token == DOT)
157 token = next_token (&val, cfile);
158 } while (token == DOT);
159
160 /* Assemble the hostname together into a string. */
161 if (!(s = (char *)malloc (len)))
8ae2d595 162 log_fatal ("can't allocate space for hostname.");
796ef008
TL
163 t = s + len;
164 *--t = 0;
165 while (c) {
166 pair cdr = c -> cdr;
167 int l = strlen ((char *)(c -> car));
168 t -= l;
169 memcpy (t, (char *)(c -> car), l);
170 /* Free up temp space. */
171 free (c -> car);
172 free (c);
173 c = cdr;
174 if (t != s)
175 *--t = '.';
176 }
177 return s;
178}
179
be6be08d
TL
180/* ip-addr-or-hostname :== ip-address | hostname
181 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
182
183 Parse an ip address or a hostname. If uniform is zero, put in
184 an expr_substring node to limit hostnames that evaluate to more
185 than one IP address. */
186
02a015fb
TL
187int parse_ip_addr_or_hostname (expr, cfile, uniform)
188 struct expression **expr;
be6be08d
TL
189 FILE *cfile;
190 int uniform;
191{
192 char *val;
02a015fb 193 enum dhcp_token token;
be6be08d
TL
194 unsigned char addr [4];
195 int len = sizeof addr;
196 char *name;
02a015fb 197 struct expression *x = (struct expression *)0;
be6be08d
TL
198
199 token = peek_token (&val, cfile);
200 if (is_identifier (token)) {
201 name = parse_host_name (cfile);
202 if (!name)
02a015fb
TL
203 return 0;
204 if (!make_host_lookup (expr, name))
205 return 0;
206 if (!uniform) {
207 if (!make_limit (&x, *expr, 4))
208 return 0;
209 expression_dereference (expr,
210 "parse_ip_addr_or_hostname");
211 *expr = x;
212 }
be6be08d
TL
213 } else if (token == NUMBER) {
214 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
02a015fb
TL
215 return 0;
216 return make_const_data (expr, addr, len, 0, 1);
be6be08d
TL
217 } else {
218 if (token != RBRACE && token != LBRACE)
219 token = next_token (&val, cfile);
220 parse_warn ("%s (%d): expecting IP address or hostname",
221 val, token);
222 if (token != SEMI)
223 skip_to_semi (cfile);
02a015fb 224 return 0;
be6be08d
TL
225 }
226
02a015fb 227 return 1;
be6be08d
TL
228}
229
230/*
231 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
232 */
233
796ef008
TL
234int parse_ip_addr (cfile, addr)
235 FILE *cfile;
236 struct iaddr *addr;
237{
238 char *val;
02a015fb 239 enum dhcp_token token;
796ef008
TL
240
241 addr -> len = 4;
242 if (parse_numeric_aggregate (cfile, addr -> iabuf,
243 &addr -> len, DOT, 10, 8))
244 return 1;
245 return 0;
246}
247
be6be08d
TL
248/*
249 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
250 * hardware-type :== ETHERNET | TOKEN_RING
251 */
63115431
TL
252
253void parse_hardware_param (cfile, hardware)
254 FILE *cfile;
255 struct hardware *hardware;
256{
257 char *val;
02a015fb 258 enum dhcp_token token;
63115431
TL
259 int hlen;
260 unsigned char *t;
261
262 token = next_token (&val, cfile);
263 switch (token) {
264 case ETHERNET:
265 hardware -> htype = HTYPE_ETHER;
266 break;
267 case TOKEN_RING:
268 hardware -> htype = HTYPE_IEEE802;
269 break;
cea8b5c9
TL
270 case FDDI:
271 hardware -> htype = HTYPE_FDDI;
272 break;
63115431
TL
273 default:
274 parse_warn ("expecting a network hardware type");
275 skip_to_semi (cfile);
276 return;
277 }
278
279 /* Parse the hardware address information. Technically,
280 it would make a lot of sense to restrict the length of the
281 data we'll accept here to the length of a particular hardware
282 address type. Unfortunately, there are some broken clients
283 out there that put bogus data in the chaddr buffer, and we accept
284 that data in the lease file rather than simply failing on such
285 clients. Yuck. */
286 hlen = 0;
287 t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen,
288 COLON, 16, 8);
289 if (!t)
290 return;
291 if (hlen > sizeof hardware -> haddr) {
292 free (t);
293 parse_warn ("hardware address too long");
294 } else {
295 hardware -> hlen = hlen;
296 memcpy ((unsigned char *)&hardware -> haddr [0],
297 t, hardware -> hlen);
cea8b5c9
TL
298 if (hlen < sizeof hardware -> haddr)
299 memset (&hardware -> haddr [hlen], 0,
300 (sizeof hardware -> haddr) - hlen);
63115431
TL
301 free (t);
302 }
303
304 token = next_token (&val, cfile);
305 if (token != SEMI) {
306 parse_warn ("expecting semicolon.");
307 skip_to_semi (cfile);
308 }
309}
310
311/* lease-time :== NUMBER SEMI */
312
313void parse_lease_time (cfile, timep)
314 FILE *cfile;
315 TIME *timep;
316{
317 char *val;
02a015fb 318 enum dhcp_token token;
63115431
TL
319
320 token = next_token (&val, cfile);
321 if (token != NUMBER) {
322 parse_warn ("Expecting numeric lease time");
323 skip_to_semi (cfile);
324 return;
325 }
326 convert_num ((unsigned char *)timep, val, 10, 32);
327 /* Unswap the number - convert_num returns stuff in NBO. */
328 *timep = ntohl (*timep); /* XXX */
329
330 parse_semi (cfile);
331}
332
333/* No BNF for numeric aggregates - that's defined by the caller. What
334 this function does is to parse a sequence of numbers seperated by
335 the token specified in seperator. If max is zero, any number of
336 numbers will be parsed; otherwise, exactly max numbers are
337 expected. Base and size tell us how to internalize the numbers
338 once they've been tokenized. */
339
340unsigned char *parse_numeric_aggregate (cfile, buf,
341 max, seperator, base, size)
342 FILE *cfile;
343 unsigned char *buf;
344 int *max;
345 int seperator;
346 int base;
347 int size;
348{
349 char *val;
02a015fb 350 enum dhcp_token token;
63115431
TL
351 unsigned char *bufp = buf, *s, *t;
352 int count = 0;
353 pair c = (pair)0;
354
355 if (!bufp && *max) {
356 bufp = (unsigned char *)malloc (*max * size / 8);
357 if (!bufp)
8ae2d595 358 log_fatal ("can't allocate space for numeric aggregate");
63115431
TL
359 } else
360 s = bufp;
361
362 do {
363 if (count) {
364 token = peek_token (&val, cfile);
365 if (token != seperator) {
366 if (!*max)
367 break;
368 if (token != RBRACE && token != LBRACE)
369 token = next_token (&val, cfile);
370 parse_warn ("too few numbers.");
371 if (token != SEMI)
372 skip_to_semi (cfile);
373 return (unsigned char *)0;
374 }
375 token = next_token (&val, cfile);
376 }
377 token = next_token (&val, cfile);
378
379 if (token == EOF) {
380 parse_warn ("unexpected end of file");
381 break;
382 }
383
384 /* Allow NUMBER_OR_NAME if base is 16. */
385 if (token != NUMBER &&
386 (base != 16 || token != NUMBER_OR_NAME)) {
387 parse_warn ("expecting numeric value.");
388 skip_to_semi (cfile);
389 return (unsigned char *)0;
390 }
391 /* If we can, convert the number now; otherwise, build
392 a linked list of all the numbers. */
393 if (s) {
394 convert_num (s, val, base, size);
395 s += size / 8;
396 } else {
397 t = (unsigned char *)malloc (strlen (val) + 1);
398 if (!t)
8ae2d595 399 log_fatal ("no temp space for number.");
338303a4
TL
400 strcpy ((char *)t, val);
401 c = cons ((caddr_t)t, c);
63115431
TL
402 }
403 } while (++count != *max);
404
405 /* If we had to cons up a list, convert it now. */
406 if (c) {
407 bufp = (unsigned char *)malloc (count * size / 8);
408 if (!bufp)
8ae2d595 409 log_fatal ("can't allocate space for numeric aggregate.");
63115431
TL
410 s = bufp + count - size / 8;
411 *max = count;
412 }
413 while (c) {
414 pair cdr = c -> cdr;
415 convert_num (s, (char *)(c -> car), base, size);
416 s -= size / 8;
417 /* Free up temp space. */
418 free (c -> car);
419 free (c);
420 c = cdr;
421 }
422 return bufp;
423}
424
425void convert_num (buf, str, base, size)
426 unsigned char *buf;
427 char *str;
428 int base;
429 int size;
430{
431 char *ptr = str;
432 int negative = 0;
433 u_int32_t val = 0;
434 int tval;
435 int max;
436
437 if (*ptr == '-') {
438 negative = 1;
439 ++ptr;
440 }
441
442 /* If base wasn't specified, figure it out from the data. */
443 if (!base) {
444 if (ptr [0] == '0') {
445 if (ptr [1] == 'x') {
446 base = 16;
447 ptr += 2;
448 } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
449 base = 8;
450 ptr += 1;
451 } else {
452 base = 10;
453 }
454 } else {
455 base = 10;
456 }
457 }
458
459 do {
460 tval = *ptr++;
461 /* XXX assumes ASCII... */
462 if (tval >= 'a')
463 tval = tval - 'a' + 10;
464 else if (tval >= 'A')
465 tval = tval - 'A' + 10;
466 else if (tval >= '0')
467 tval -= '0';
468 else {
8ae2d595 469 log_error ("Bogus number: %s.", str);
63115431
TL
470 break;
471 }
472 if (tval >= base) {
8ae2d595 473 log_error ("Bogus number: %s: digit %d not in base %d\n",
63115431
TL
474 str, tval, base);
475 break;
476 }
477 val = val * base + tval;
478 } while (*ptr);
479
480 if (negative)
481 max = (1 << (size - 1));
482 else
483 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
484 if (val > max) {
485 switch (base) {
486 case 8:
8ae2d595 487 log_error ("value %s%o exceeds max (%d) for precision.",
63115431
TL
488 negative ? "-" : "", val, max);
489 break;
490 case 16:
8ae2d595 491 log_error ("value %s%x exceeds max (%d) for precision.",
63115431
TL
492 negative ? "-" : "", val, max);
493 break;
494 default:
8ae2d595 495 log_error ("value %s%u exceeds max (%d) for precision.",
63115431
TL
496 negative ? "-" : "", val, max);
497 break;
498 }
499 }
500
501 if (negative) {
502 switch (size) {
503 case 8:
504 *buf = -(unsigned long)val;
505 break;
506 case 16:
507 putShort (buf, -(unsigned long)val);
508 break;
509 case 32:
510 putLong (buf, -(unsigned long)val);
511 break;
512 default:
8ae2d595 513 log_error ("Unexpected integer size: %d\n", size);
63115431
TL
514 break;
515 }
516 } else {
517 switch (size) {
518 case 8:
519 *buf = (u_int8_t)val;
520 break;
521 case 16:
522 putUShort (buf, (u_int16_t)val);
523 break;
524 case 32:
525 putULong (buf, val);
526 break;
527 default:
8ae2d595 528 log_error ("Unexpected integer size: %d\n", size);
63115431
TL
529 break;
530 }
531 }
532}
533
be6be08d
TL
534/*
535 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
a82abfc7
TL
536 * NUMBER COLON NUMBER COLON NUMBER SEMI |
537 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
538 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
be6be08d 539 *
a82abfc7
TL
540 * Dates are stored in GMT or with a timezone offset; first number is day
541 * of week; next is year/month/day; next is hours:minutes:seconds on a
542 * 24-hour clock, followed by the timezone offset in seconds, which is
543 * optional.
be6be08d 544 */
63115431
TL
545
546TIME parse_date (cfile)
547 FILE *cfile;
548{
549 struct tm tm;
550 int guess;
a82abfc7 551 int tzoff, wday, year, mon, mday, hour, min, sec;
63115431 552 char *val;
02a015fb 553 enum dhcp_token token;
63115431
TL
554 static int months [11] = { 31, 59, 90, 120, 151, 181,
555 212, 243, 273, 304, 334 };
556
557 /* Day of week... */
558 token = next_token (&val, cfile);
559 if (token != NUMBER) {
560 parse_warn ("numeric day of week expected.");
561 if (token != SEMI)
562 skip_to_semi (cfile);
563 return (TIME)0;
564 }
a82abfc7 565 wday = atoi (val);
63115431
TL
566
567 /* Year... */
568 token = next_token (&val, cfile);
569 if (token != NUMBER) {
570 parse_warn ("numeric year expected.");
571 if (token != SEMI)
572 skip_to_semi (cfile);
573 return (TIME)0;
574 }
edca2b1a
TL
575
576 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
577 somebody invents a time machine, I think we can safely disregard
578 it. This actually works around a stupid Y2K bug that was present
579 in a very early beta release of dhcpd. */
a82abfc7
TL
580 year = atoi (val);
581 if (year > 1900)
582 year -= 1900;
63115431
TL
583
584 /* Slash seperating year from month... */
585 token = next_token (&val, cfile);
586 if (token != SLASH) {
587 parse_warn ("expected slash seperating year from month.");
588 if (token != SEMI)
589 skip_to_semi (cfile);
590 return (TIME)0;
591 }
592
593 /* Month... */
594 token = next_token (&val, cfile);
595 if (token != NUMBER) {
596 parse_warn ("numeric month expected.");
597 if (token != SEMI)
598 skip_to_semi (cfile);
599 return (TIME)0;
600 }
a82abfc7 601 mon = atoi (val) - 1;
63115431
TL
602
603 /* Slash seperating month from day... */
604 token = next_token (&val, cfile);
605 if (token != SLASH) {
606 parse_warn ("expected slash seperating month from day.");
607 if (token != SEMI)
608 skip_to_semi (cfile);
609 return (TIME)0;
610 }
611
612 /* Month... */
613 token = next_token (&val, cfile);
614 if (token != NUMBER) {
615 parse_warn ("numeric day of month expected.");
616 if (token != SEMI)
617 skip_to_semi (cfile);
618 return (TIME)0;
619 }
a82abfc7 620 mday = atoi (val);
63115431
TL
621
622 /* Hour... */
623 token = next_token (&val, cfile);
624 if (token != NUMBER) {
625 parse_warn ("numeric hour expected.");
626 if (token != SEMI)
627 skip_to_semi (cfile);
628 return (TIME)0;
629 }
a82abfc7 630 hour = atoi (val);
63115431
TL
631
632 /* Colon seperating hour from minute... */
633 token = next_token (&val, cfile);
634 if (token != COLON) {
635 parse_warn ("expected colon seperating hour from minute.");
636 if (token != SEMI)
637 skip_to_semi (cfile);
638 return (TIME)0;
639 }
640
641 /* Minute... */
642 token = next_token (&val, cfile);
643 if (token != NUMBER) {
644 parse_warn ("numeric minute expected.");
645 if (token != SEMI)
646 skip_to_semi (cfile);
647 return (TIME)0;
648 }
a82abfc7 649 min = atoi (val);
63115431
TL
650
651 /* Colon seperating minute from second... */
652 token = next_token (&val, cfile);
653 if (token != COLON) {
654 parse_warn ("expected colon seperating hour from minute.");
655 if (token != SEMI)
656 skip_to_semi (cfile);
657 return (TIME)0;
658 }
659
660 /* Minute... */
661 token = next_token (&val, cfile);
662 if (token != NUMBER) {
663 parse_warn ("numeric minute expected.");
664 if (token != SEMI)
665 skip_to_semi (cfile);
666 return (TIME)0;
667 }
a82abfc7 668 sec = atoi (val);
63115431 669
a82abfc7
TL
670 token = peek_token (&val, cfile);
671 if (token == NUMBER) {
672 token = next_token (&val, cfile);
673 tzoff = atoi (val);
674 } else
675 tzoff = 0;
63115431
TL
676
677 /* Make sure the date ends in a semicolon... */
25541f2f 678 if (!parse_semi (cfile))
63115431 679 return 0;
63115431
TL
680
681 /* Guess the time value... */
a82abfc7
TL
682 guess = ((((((365 * (year - 70) + /* Days in years since '70 */
683 (year - 69) / 4 + /* Leap days since '70 */
684 (mon /* Days in months this year */
685 ? months [mon - 1]
63115431 686 : 0) +
a82abfc7
TL
687 (mon > 1 && /* Leap day this year */
688 !((year - 72) & 3)) +
689 mday - 1) * 24) + /* Day of month */
690 hour) * 60) +
691 min) * 60) + sec + tzoff;
63115431
TL
692
693 /* This guess could be wrong because of leap seconds or other
694 weirdness we don't know about that the system does. For
695 now, we're just going to accept the guess, but at some point
696 it might be nice to do a successive approximation here to
697 get an exact value. Even if the error is small, if the
698 server is restarted frequently (and thus the lease database
699 is reread), the error could accumulate into something
700 significant. */
701
702 return guess;
703}
4761e04b 704
be6be08d
TL
705/*
706 * option-name :== IDENTIFIER |
707 IDENTIFIER . IDENTIFIER
708 */
709
6b4b0ec7 710struct option *parse_option_name (cfile, allocate)
4761e04b 711 FILE *cfile;
6b4b0ec7 712 int allocate;
4761e04b
TL
713{
714 char *val;
02a015fb 715 enum dhcp_token token;
6b4b0ec7 716 char *uname;
4761e04b
TL
717 struct universe *universe;
718 struct option *option;
719
720 token = next_token (&val, cfile);
721 if (!is_identifier (token)) {
722 parse_warn ("expecting identifier after option keyword.");
723 if (token != SEMI)
724 skip_to_semi (cfile);
725 return (struct option *)0;
726 }
6b4b0ec7
TL
727 uname = malloc (strlen (val) + 1);
728 if (!uname)
729 log_fatal ("no memory for uname information.");
730 strcpy (uname, val);
4761e04b
TL
731 token = peek_token (&val, cfile);
732 if (token == DOT) {
733 /* Go ahead and take the DOT token... */
734 token = next_token (&val, cfile);
735
736 /* The next token should be an identifier... */
737 token = next_token (&val, cfile);
738 if (!is_identifier (token)) {
739 parse_warn ("expecting identifier after '.'");
740 if (token != SEMI)
741 skip_to_semi (cfile);
742 return (struct option *)0;
743 }
744
745 /* Look up the option name hash table for the specified
6b4b0ec7 746 uname. */
4761e04b
TL
747 universe = ((struct universe *)
748 hash_lookup (&universe_hash,
6b4b0ec7 749 (unsigned char *)uname, 0));
4761e04b
TL
750 /* If it's not there, we can't parse the rest of the
751 declaration. */
752 if (!universe) {
6b4b0ec7 753 parse_warn ("no option space named %s.", uname);
4761e04b
TL
754 skip_to_semi (cfile);
755 return (struct option *)0;
756 }
757 } else {
758 /* Use the default hash table, which contains all the
759 standard dhcp option names. */
6b4b0ec7 760 val = uname;
4761e04b
TL
761 universe = &dhcp_universe;
762 }
763
764 /* Look up the actual option info... */
765 option = (struct option *)hash_lookup (universe -> hash,
766 (unsigned char *)val, 0);
767
768 /* If we didn't get an option structure, it's an undefined option. */
769 if (!option) {
6b4b0ec7
TL
770 /* If we've been told to allocate, that means that this
771 (might) be an option code definition, so we'll create
772 an option structure just in case. */
773 if (allocate) {
774 option = new_option ("parse_option_name");
775 if (val == uname)
776 option -> name = val;
777 else {
778 free (uname);
779 option -> name = dmalloc (strlen (val) + 1,
780 "parse_option_name");
781 if (!option -> name)
782 log_fatal ("no memory for option %s.%s",
783 universe -> name, val);
784 strcpy (option -> name, val);
785 }
786 option -> universe = universe;
787 option -> code = -1;
788 return option;
789 }
790 if (val == uname)
4761e04b
TL
791 parse_warn ("no option named %s", val);
792 else
6b4b0ec7
TL
793 parse_warn ("no option named %s in space %s",
794 val, uname);
4761e04b
TL
795 skip_to_semi (cfile);
796 return (struct option *)0;
797 }
798
799 /* Free the initial identifier token. */
6b4b0ec7 800 free (uname);
4761e04b
TL
801 return option;
802}
803
52c9d530
TL
804/* IDENTIFIER SEMI */
805
806void parse_option_space_decl (cfile)
807 FILE *cfile;
808{
809 int token;
810 char *val;
811 struct universe **ua, *nu;
812
813 next_token (&val, cfile); /* Discard the SPACE token, which was
814 checked by the caller. */
815 token = next_token (&val, cfile);
816 if (!is_identifier (token)) {
817 parse_warn ("expecting identifier.");
818 skip_to_semi (cfile);
819 return;
820 }
821 nu = new_universe ("parse_option_space_decl");
822 if (!nu)
823 log_fatal ("No memory for new option space.");
824
825 /* Set up the server option universe... */
826 nu -> name = dmalloc (strlen (val) + 1, "parse_option_space_decl");
827 if (!nu -> name)
828 log_fatal ("No memory for new option space name.");
829 strcpy (nu -> name, val);
830 nu -> lookup_func = lookup_hashed_option;
831 nu -> option_state_dereference =
832 hashed_option_state_dereference;
833 nu -> get_func = hashed_option_get;
834 nu -> set_func = hashed_option_set;
835 nu -> save_func = save_hashed_option;
836 nu -> delete_func = delete_hashed_option;
837 nu -> encapsulate = hashed_option_space_encapsulate;
838 nu -> length_size = 1;
839 nu -> tag_size = 1;
840 nu -> store_tag = putUChar;
841 nu -> store_length = putUChar;
842 nu -> index = universe_count++;
843 if (nu -> index >= universe_max) {
844 ua = dmalloc (universe_max * 2 * sizeof *ua,
845 "parse_option_space_decl");
846 if (!ua)
847 log_fatal ("No memory to expand option space array.");
848 memcpy (ua, universes, universe_max * sizeof *ua);
849 universe_max *= 2;
850 dfree (universes, "parse_option_space_decl");
851 universes = ua;
852 }
853 universes [nu -> index] = nu;
854 nu -> hash = new_hash ();
855 if (!nu -> hash)
856 log_fatal ("Can't allocate %s option hash table.", nu -> name);
857 add_hash (&universe_hash,
858 (unsigned char *)nu -> name, 0, (unsigned char *)nu);
859 parse_semi (cfile);
860}
861
6b4b0ec7
TL
862/* This is faked up to look good right now. Ideally, this should do a
863 recursive parse and allow arbitrary data structure definitions, but for
864 now it just allows you to specify a single type, an array of single types,
865 a sequence of types, or an array of sequences of types.
866
867 ocd :== NUMBER EQUALS ocsd SEMI
868
869 ocsd :== ocsd_type |
870 ocsd_type_sequence |
871 ARRAY OF ocsd_type |
872 ARRAY OF ocsd_type_sequence
873
874 ocsd_type :== BOOLEAN |
875 INTEGER NUMBER |
876 SIGNED INTEGER NUMBER |
877 UNSIGNED INTEGER NUMBER |
878 IP-ADDRESS |
879 TEXT |
880 STRING
881
882 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
883
884 ocsd_type :== ocsd_type |
885 ocsd_types ocsd_type */
886
887int parse_option_code_definition (cfile, option)
888 FILE *cfile;
889 struct option *option;
890{
891 char *val;
892 enum dhcp_token token;
893 int arrayp = 0;
894 int recordp = 0;
895 int no_more_in_record = 0;
896 char tokbuf [128];
897 int tokix = 0;
898 char type;
899 int code;
900 int is_signed;
901
902 /* Parse the option code. */
903 token = next_token (&val, cfile);
904 if (token != NUMBER) {
905 parse_warn ("expecting option code number.");
906 skip_to_semi (cfile);
907 return 0;
908 }
909 option -> code = atoi (val);
910
911 token = next_token (&val, cfile);
912 if (token != EQUAL) {
913 parse_warn ("expecting \"=\"");
914 skip_to_semi (cfile);
915 return 0;
916 }
917
918 /* See if this is an array. */
919 token = next_token (&val, cfile);
920 if (token == ARRAY) {
921 token = next_token (&val, cfile);
922 if (token != OF) {
923 parse_warn ("expecting \"of\".");
924 skip_to_semi (cfile);
925 return 0;
926 }
927 arrayp = 1;
928 token = next_token (&val, cfile);
929 }
930
931 if (token == LBRACE) {
932 recordp = 1;
933 token = next_token (&val, cfile);
934 }
935
936 /* At this point we're expecting a data type. */
937 next_type:
938 switch (token) {
939 case BOOLEAN:
940 type = 'f';
941 break;
942 case INTEGER:
943 is_signed = 1;
944 parse_integer:
945 token = next_token (&val, cfile);
946 if (token != NUMBER) {
947 parse_warn ("expecting number.");
948 skip_to_rbrace (cfile, recordp);
949 if (recordp)
950 skip_to_semi (cfile);
951 return 0;
952 }
953 switch (atoi (val)) {
954 case 8:
955 type = is_signed ? 'b' : 'B';
956 break;
957 case 16:
958 type = is_signed ? 's' : 'S';
959 break;
960 case 32:
961 type = is_signed ? 'l' : 'L';
962 break;
963 default:
964 parse_warn ("%s bit precision is not supported.", val);
965 skip_to_rbrace (cfile, recordp);
966 if (recordp)
967 skip_to_semi (cfile);
968 return 0;
969 }
970 break;
971 case SIGNED:
972 is_signed = 1;
973 parse_signed:
974 token = next_token (&val, cfile);
975 if (token != INTEGER) {
976 parse_warn ("expecting \"integer\" keyword.");
977 skip_to_rbrace (cfile, recordp);
978 if (recordp)
979 skip_to_semi (cfile);
980 return 0;
981 }
982 goto parse_integer;
983 case UNSIGNED:
984 is_signed = 0;
985 goto parse_signed;
986
987 case IP_ADDRESS:
988 type = 'I';
989 break;
990 case TEXT:
991 type = 't';
992 no_arrays:
993 if (arrayp) {
994 parse_warn ("arrays of text strings not %s",
995 "yet supported.");
996 skip_to_rbrace (cfile, recordp);
997 if (recordp)
998 skip_to_semi (cfile);
999 return 0;
1000 }
1001 no_more_in_record = 1;
1002 break;
1003 case STRING:
1004 type = 'X';
1005 goto no_arrays;
1006
1007 default:
1008 parse_warn ("unknown data type %s", val);
1009 skip_to_rbrace (cfile, recordp);
1010 if (recordp)
1011 skip_to_semi (cfile);
1012 return 0;
1013 }
1014
1015 if (tokix == sizeof tokbuf) {
1016 parse_warn ("too many types in record.");
1017 skip_to_rbrace (cfile, recordp);
1018 if (recordp)
1019 skip_to_semi (cfile);
1020 return 0;
1021 }
1022 tokbuf [tokix++] = type;
1023
1024 if (recordp) {
1025 token = next_token (&val, cfile);
1026 if (token == COMMA) {
1027 if (no_more_in_record) {
1028 parse_warn ("%s must be at end of record.",
1029 type == 't' ? "text" : "string");
1030 skip_to_rbrace (cfile, 1);
1031 if (recordp)
1032 skip_to_semi (cfile);
1033 return 0;
1034 }
1035 token = next_token (&val, cfile);
1036 goto next_type;
1037 }
1038 if (token != RBRACE) {
1039 parse_warn ("expecting right brace.");
1040 skip_to_rbrace (cfile, 1);
1041 if (recordp)
1042 skip_to_semi (cfile);
1043 return 0;
1044 }
1045 }
1046 if (!parse_semi (cfile)) {
1047 parse_warn ("semicolon expected.");
1048 skip_to_semi (cfile);
1049 if (recordp)
1050 skip_to_semi (cfile);
1051 return 0;
1052 }
1053 option -> format = dmalloc (tokix + arrayp + 1,
1054 "parse_option_code_definition");
1055 if (!option -> format)
1056 log_fatal ("no memory for option format.");
1057 memcpy (option -> format, tokbuf, tokix);
1058 if (arrayp)
1059 option -> format [tokix++] = 'A';
1060 option -> format [tokix] = 0;
1061 if (option -> universe -> options [option -> code]) {
1062 /* XXX Free the option, but we can't do that now because they
1063 XXX may start out static. */
1064 }
1065 option -> universe -> options [option -> code] = option;
1066 add_hash (option -> universe -> hash,
1067 (unsigned char *)option -> name, 0, (unsigned char *)option);
1068 return 1;
1069}
1070
be6be08d
TL
1071/*
1072 * colon-seperated-hex-list :== NUMBER |
1073 * NUMBER COLON colon-seperated-hex-list
1074 */
1075
02a015fb
TL
1076int parse_cshl (data, cfile)
1077 struct data_string *data;
4761e04b 1078 FILE *cfile;
4761e04b 1079{
c5b0f529 1080 u_int8_t ibuf [128];
4761e04b
TL
1081 int ilen = 0;
1082 int tlen = 0;
1083 struct option_tag *sl = (struct option_tag *)0;
1084 struct option_tag *next, **last = &sl;
02a015fb 1085 enum dhcp_token token;
4761e04b 1086 char *val;
02a015fb 1087 unsigned char *rvp;
4761e04b
TL
1088
1089 do {
1090 token = next_token (&val, cfile);
1091 if (token != NUMBER && token != NUMBER_OR_NAME) {
1092 parse_warn ("expecting hexadecimal number.");
1093 skip_to_semi (cfile);
1094 for (; sl; sl = next) {
1095 next = sl -> next;
1096 dfree (sl, "parse_cshl");
1097 }
02a015fb 1098 return 0;
4761e04b
TL
1099 }
1100 if (ilen == sizeof ibuf) {
1101 next = (struct option_tag *)
1102 dmalloc (ilen - 1 +
1103 sizeof (struct option_tag),
1104 "parse_cshl");
1105 if (!next)
8ae2d595 1106 log_fatal ("no memory for string list.");
4761e04b
TL
1107 memcpy (next -> data, ibuf, ilen);
1108 *last = next;
1109 last = &next -> next;
1110 tlen += ilen;
1111 ilen = 0;
1112 }
1113 convert_num (&ibuf [ilen++], val, 16, 8);
1114
1115 token = peek_token (&val, cfile);
1116 if (token != COLON)
1117 break;
1118 token = next_token (&val, cfile);
1119 } while (1);
1120
02a015fb 1121 if (!buffer_allocate (&data -> buffer, tlen + ilen, "parse_cshl"))
8ae2d595 1122 log_fatal ("no memory to store octet data.");
02a015fb
TL
1123 data -> data = &data -> buffer -> data [0];
1124 data -> len = tlen + ilen;
1125 data -> terminated = 0;
1126
1127 rvp = &data -> data [0];
4761e04b
TL
1128 while (sl) {
1129 next = sl -> next;
1130 memcpy (rvp, sl -> data, sizeof ibuf);
1131 rvp += sizeof ibuf;
1132 dfree (sl, "parse_cshl");
1133 sl = next;
1134 }
1135
1136 memcpy (rvp, ibuf, ilen);
02a015fb 1137 return 1;
4761e04b 1138}
be6be08d
TL
1139
1140/*
1141 * executable-statements :== executable-statement executable-statements |
1142 * executable-statement
1143 *
1144 * executable-statement :==
1145 * IF if-statement |
1146 * ADD class-name SEMI |
1147 * BREAK SEMI |
1148 * OPTION option-parameter SEMI |
1149 * SUPERSEDE option-parameter SEMI |
1150 * PREPEND option-parameter SEMI |
1151 * APPEND option-parameter SEMI
1152 */
1153
79a65726
TL
1154int parse_executable_statements (statements, cfile, lose)
1155 struct executable_statement **statements;
be6be08d
TL
1156 FILE *cfile;
1157 int *lose;
1158{
79a65726 1159 struct executable_statement **next;
be6be08d 1160
79a65726
TL
1161 next = statements;
1162 while (parse_executable_statement (next, cfile, lose))
be6be08d 1163 next = &((*next) -> next);
02a015fb 1164 if (!*lose)
79a65726
TL
1165 return 1;
1166 return 0;
be6be08d
TL
1167}
1168
79a65726
TL
1169int parse_executable_statement (result, cfile, lose)
1170 struct executable_statement **result;
be6be08d
TL
1171 FILE *cfile;
1172 int *lose;
1173{
02a015fb 1174 enum dhcp_token token;
be6be08d 1175 char *val;
79a65726 1176 struct executable_statement base;
be6be08d
TL
1177 struct class *cta;
1178 struct option *option;
b1013db7 1179 struct option_cache *cache;
be6be08d 1180
b1013db7
TL
1181 token = peek_token (&val, cfile);
1182 switch (token) {
be6be08d 1183 case IF:
dce70f9f 1184 next_token (&val, cfile);
79a65726
TL
1185 return parse_if_statement (result, cfile, lose);
1186
eb018e2b 1187 case TOKEN_ADD:
efc79acb 1188 token = next_token (&val, cfile);
be6be08d
TL
1189 token = next_token (&val, cfile);
1190 if (token != STRING) {
1191 parse_warn ("expecting class name.");
1192 skip_to_semi (cfile);
1193 *lose = 1;
79a65726 1194 return 0;
be6be08d
TL
1195 }
1196 cta = find_class (val);
1197 if (!cta) {
1198 parse_warn ("unknown class %s.", val);
1199 skip_to_semi (cfile);
1200 *lose = 1;
79a65726 1201 return 0;
be6be08d
TL
1202 }
1203 if (!parse_semi (cfile)) {
1204 *lose = 1;
79a65726 1205 return 0;
be6be08d 1206 }
79a65726
TL
1207 if (!executable_statement_allocate
1208 (result, "parse_executable_statement"))
1209 log_fatal ("no memory for new statement.");
1210 (*result) -> op = add_statement;
1211 (*result) -> data.add = cta;
be6be08d
TL
1212 break;
1213
1214 case BREAK:
1215 token = next_token (&val, cfile);
1216 if (!parse_semi (cfile)) {
1217 *lose = 1;
79a65726 1218 return 0;
be6be08d 1219 }
79a65726
TL
1220 if (!executable_statement_allocate
1221 (result, "parse_executable_statement"))
1222 log_fatal ("no memory for new statement.");
1223 (*result) -> op = break_statement;
be6be08d
TL
1224 break;
1225
25541f2f
TL
1226 case SEND:
1227 *lose = 1;
1228 parse_warn ("send not appropriate here.");
1229 skip_to_semi (cfile);
79a65726 1230 return 0;
25541f2f
TL
1231
1232 case SUPERSEDE:
be6be08d
TL
1233 case OPTION:
1234 token = next_token (&val, cfile);
6b4b0ec7 1235 option = parse_option_name (cfile, 0);
be6be08d
TL
1236 if (!option) {
1237 *lose = 1;
79a65726 1238 return 0;
be6be08d 1239 }
79a65726 1240 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1241 supersede_option_statement);
1242
b1013db7
TL
1243 case ALLOW:
1244 case DENY:
1245 token = next_token (&val, cfile);
1246 cache = (struct option_cache *)0;
1247 if (!parse_allow_deny (&cache, cfile,
1248 token == ALLOW ? 1 : 0))
79a65726
TL
1249 return 0;
1250 if (!executable_statement_allocate
1251 (result, "parse_executable_statement"))
1252 log_fatal ("no memory for new statement.");
1253 (*result) -> op = supersede_option_statement;
1254 (*result) -> data.option = cache;
b1013db7
TL
1255 break;
1256
be6be08d
TL
1257 case DEFAULT:
1258 token = next_token (&val, cfile);
6b4b0ec7 1259 option = parse_option_name (cfile, 0);
be6be08d
TL
1260 if (!option) {
1261 *lose = 1;
79a65726 1262 return 0;
be6be08d 1263 }
79a65726 1264 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1265 default_option_statement);
1266
1267 case PREPEND:
1268 token = next_token (&val, cfile);
6b4b0ec7 1269 option = parse_option_name (cfile, 0);
be6be08d
TL
1270 if (!option) {
1271 *lose = 1;
79a65726 1272 return 0;
be6be08d 1273 }
79a65726 1274 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1275 prepend_option_statement);
1276
1277 case APPEND:
1278 token = next_token (&val, cfile);
6b4b0ec7 1279 option = parse_option_name (cfile, 0);
be6be08d
TL
1280 if (!option) {
1281 *lose = 1;
79a65726 1282 return 0;
be6be08d 1283 }
79a65726 1284 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1285 append_option_statement);
1286
79a65726
TL
1287 case ON:
1288 token = next_token (&val, cfile);
1289
1290 return parse_on_statement (result, cfile, lose);
1291
be6be08d
TL
1292 default:
1293 *lose = 0;
79a65726 1294 return 0;
be6be08d
TL
1295 }
1296
79a65726
TL
1297 return 1;
1298}
1299
1300/*
1301 * on-statement :== event-type LBRACE executable-statements RBRACE
1302 *
1303 * event-type :== EXPIRY | COMMIT | RELEASE
1304 */
1305
1306int parse_on_statement (result, cfile, lose)
1307 struct executable_statement **result;
1308 FILE *cfile;
1309 int *lose;
1310{
1311 enum dhcp_token token;
1312 char *val;
1313
1314 if (!executable_statement_allocate (result,
1315 "parse_executable_statement"))
8ae2d595 1316 log_fatal ("no memory for new statement.");
79a65726
TL
1317
1318 token = next_token (&val, cfile);
1319 switch (token) {
1320 case EXPIRY:
1321 (*result) -> data.on.evtype = expiry;
1322 break;
1323
1324 case COMMIT:
1325 (*result) -> data.on.evtype = expiry;
1326 break;
1327
1328 case RELEASE:
1329 (*result) -> data.on.evtype = expiry;
1330 break;
1331
1332 default:
1333 parse_warn ("expecting a lease event type");
1334 skip_to_semi (cfile);
1335 *lose = 1;
1336 executable_statement_dereference
1337 (result, "parse_on_statement");
1338 break;
1339 }
1340
1341 token = next_token (&val, cfile);
1342 if (token != LBRACE) {
1343 parse_warn ("left brace expected.");
1344 skip_to_semi (cfile);
1345 *lose = 1;
1346 executable_statement_dereference (result,
1347 "parse_on_statement");
1348 return 0;
1349 }
1350 if (!parse_executable_statements (&(*result) -> data.on.statements,
1351 cfile, lose)) {
1352 if (*lose) {
1353 /* Try to even things up. */
1354 do {
1355 token = next_token (&val, cfile);
1356 } while (token != EOF && token != RBRACE);
1357 executable_statement_dereference
1358 (result, "parse_on_statement");
1359 return 0;
1360 }
1361 }
1362 token = next_token (&val, cfile);
1363 if (token != RBRACE) {
1364 parse_warn ("right brace expected.");
1365 skip_to_semi (cfile);
1366 *lose = 1;
1367 executable_statement_dereference
1368 (result, "parse_on_statement");
1369 return 0;
1370 }
1371 return 1;
be6be08d
TL
1372}
1373
1374/*
1375 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
1376 * else-statement
1377 *
1378 * else-statement :== <null> |
1379 * ELSE LBRACE executable-statements RBRACE |
1380 * ELSE IF if-statement |
1381 * ELSIF if-statement
1382 */
1383
79a65726
TL
1384int parse_if_statement (result, cfile, lose)
1385 struct executable_statement **result;
be6be08d
TL
1386 FILE *cfile;
1387 int *lose;
1388{
02a015fb 1389 enum dhcp_token token;
be6be08d 1390 char *val;
be6be08d 1391
79a65726
TL
1392 if (!executable_statement_allocate (result, "parse_if_statement"))
1393 log_fatal ("no memory for if statement.");
1394
1395 (*result) -> op = if_statement;
1396
1397 if (!parse_boolean_expression (&(*result) -> data.ie.expr,
1398 cfile, lose)) {
be6be08d
TL
1399 if (!*lose)
1400 parse_warn ("boolean expression expected.");
79a65726
TL
1401 executable_statement_dereference (result,
1402 "parse_if_statement");
1403 return 0;
be6be08d 1404 }
02a015fb
TL
1405#if defined (DEBUG_EXPRESSION_PARSE)
1406 print_expression ("if condition", if_condition);
1407#endif
be6be08d
TL
1408 token = next_token (&val, cfile);
1409 if (token != LBRACE) {
1410 parse_warn ("left brace expected.");
1411 skip_to_semi (cfile);
1412 *lose = 1;
79a65726
TL
1413 executable_statement_dereference (result,
1414 "parse_if_statement");
1415 return 0;
be6be08d 1416 }
79a65726
TL
1417 if (!parse_executable_statements (&(*result) -> data.ie.true,
1418 cfile, lose)) {
1419 if (*lose) {
1420 /* Try to even things up. */
1421 do {
1422 token = next_token (&val, cfile);
1423 } while (token != EOF && token != RBRACE);
1424 executable_statement_dereference
1425 (result, "parse_if_statement");
1426 return 0;
1427 }
efc79acb 1428 }
79a65726 1429 token = next_token (&val, cfile);
be6be08d
TL
1430 if (token != RBRACE) {
1431 parse_warn ("right brace expected.");
1432 skip_to_semi (cfile);
1433 *lose = 1;
79a65726
TL
1434 executable_statement_dereference
1435 (result, "parse_if_statement");
1436 return 0;
be6be08d
TL
1437 }
1438 token = peek_token (&val, cfile);
1439 if (token == ELSE) {
1440 token = next_token (&val, cfile);
1441 token = peek_token (&val, cfile);
1442 if (token == IF) {
1443 token = next_token (&val, cfile);
79a65726
TL
1444 if (!parse_if_statement (&(*result) -> data.ie.false,
1445 cfile, lose)) {
1446 if (*lose) {
1447 return 0;
1448 executable_statement_dereference
1449 (result, "parse_if_statement");
1450 }
1451 }
be6be08d
TL
1452 } else if (token != LBRACE) {
1453 parse_warn ("left brace or if expected.");
1454 skip_to_semi (cfile);
1455 *lose = 1;
79a65726
TL
1456 executable_statement_dereference
1457 (result, "parse_if_statement");
1458 return 0;
be6be08d
TL
1459 } else {
1460 token = next_token (&val, cfile);
79a65726
TL
1461 if (!parse_if_statement (&(*result) -> data.ie.false,
1462 cfile, lose)) {
1463 executable_statement_dereference
1464 (result, "parse_if_statement");
1465 return 0;
1466 }
25541f2f
TL
1467 token = next_token (&val, cfile);
1468 if (token != RBRACE) {
1469 parse_warn ("right brace expected.");
1470 skip_to_semi (cfile);
1471 *lose = 1;
79a65726
TL
1472 executable_statement_dereference
1473 (result, "parse_if_statement");
1474 return 0;
25541f2f 1475 }
be6be08d
TL
1476 }
1477 } else if (token == ELSIF) {
1478 token = next_token (&val, cfile);
79a65726
TL
1479 if (!parse_if_statement (&(*result) -> data.ie.false,
1480 cfile, lose)) {
1481 if (*lose) {
1482 return 0;
1483 executable_statement_dereference
1484 (result, "parse_if_statement");
1485 }
1486 }
be6be08d 1487 } else
79a65726 1488 (*result) -> data.ie.false = (struct executable_statement *)0;
be6be08d 1489
79a65726 1490 return 1;
be6be08d
TL
1491}
1492
1493/*
1494 * boolean_expression :== CHECK STRING |
1495 * NOT boolean-expression |
1496 * data-expression EQUAL data-expression |
1497 * boolean-expression AND boolean-expression |
1498 * boolean-expression OR boolean-expression
02a015fb 1499 * EXISTS OPTION-NAME
be6be08d
TL
1500 */
1501
02a015fb
TL
1502int parse_boolean_expression (expr, cfile, lose)
1503 struct expression **expr;
1504 FILE *cfile;
1505 int *lose;
1506{
1507 /* Parse an expression... */
1508 if (!parse_expression (expr, cfile, lose, context_boolean,
1509 (struct expression **)0, expr_none))
1510 return 0;
1511
1512 if (!is_boolean_expression (*expr)) {
1513 parse_warn ("Expecting a boolean expression.");
1514 *lose = 1;
1515 return 0;
1516 }
1517 return 1;
1518}
1519
1520/*
1521 * data_expression :== SUBSTRING LPAREN data-expression COMMA
1522 * numeric-expression COMMA
1523 * numeric-expression RPAREN |
a82abfc7
TL
1524 * CONCAT LPAREN data-expression COMMA
1525 data-expression RPAREN
02a015fb 1526 * SUFFIX LPAREN data_expression COMMA
a82abfc7 1527 * numeric-expression RPAREN |
02a015fb
TL
1528 * OPTION option_name |
1529 * HARDWARE |
1530 * PACKET LPAREN numeric-expression COMMA
1531 * numeric-expression RPAREN |
1532 * STRING |
1533 * colon_seperated_hex_list
1534 */
1535
1536int parse_data_expression (expr, cfile, lose)
1537 struct expression **expr;
1538 FILE *cfile;
1539 int *lose;
1540{
1541 /* Parse an expression... */
1542 if (!parse_expression (expr, cfile, lose, context_data,
1543 (struct expression **)0, expr_none))
1544 return 0;
1545
1546 if (!is_data_expression (*expr)) {
1547 parse_warn ("Expecting a data expression.");
1548 *lose = 1;
1549 return 0;
1550 }
1551 return 1;
1552}
1553
1554/*
1555 * numeric-expression :== EXTRACT_INT LPAREN data-expression
1556 * COMMA number RPAREN |
1557 * NUMBER
1558 */
1559
1560int parse_numeric_expression (expr, cfile, lose)
1561 struct expression **expr;
1562 FILE *cfile;
1563 int *lose;
1564{
1565 /* Parse an expression... */
1566 if (!parse_expression (expr, cfile, lose, context_numeric,
1567 (struct expression **)0, expr_none))
1568 return 0;
1569
1570 if (!is_numeric_expression (*expr)) {
1571 parse_warn ("Expecting a numeric expression.");
1572 *lose = 1;
1573 return 0;
1574 }
1575 return 1;
1576}
1577
1578/* Parse a subexpression that does not contain a binary operator. */
be6be08d 1579
02a015fb
TL
1580int parse_non_binary (expr, cfile, lose, context)
1581 struct expression **expr;
be6be08d
TL
1582 FILE *cfile;
1583 int *lose;
02a015fb 1584 enum expression_context context;
be6be08d 1585{
02a015fb 1586 enum dhcp_token token;
be6be08d
TL
1587 char *val;
1588 struct collection *col;
02a015fb 1589 struct option *option;
79a65726 1590 struct expression *nexp;
be6be08d
TL
1591
1592 token = peek_token (&val, cfile);
1593
1594 /* Check for unary operators... */
1595 switch (token) {
1596 case CHECK:
1597 token = next_token (&val, cfile);
1598 token = next_token (&val, cfile);
1599 if (token != STRING) {
1600 parse_warn ("string expected.");
1601 skip_to_semi (cfile);
1602 *lose = 1;
02a015fb 1603 return 0;
be6be08d
TL
1604 }
1605 for (col = collections; col; col = col -> next)
1606 if (!strcmp (col -> name, val))
1607 break;
1608 if (!col) {
1609 parse_warn ("unknown collection.");
1610 *lose = 1;
02a015fb 1611 return 0;
be6be08d 1612 }
02a015fb 1613 if (!expression_allocate (expr, "parse_expression: CHECK"))
8ae2d595 1614 log_fatal ("can't allocate expression");
02a015fb
TL
1615 (*expr) -> op = expr_check;
1616 (*expr) -> data.check = col;
1617 break;
be6be08d 1618
5e6fb153 1619 case TOKEN_NOT:
be6be08d 1620 token = next_token (&val, cfile);
02a015fb 1621 if (!expression_allocate (expr, "parse_expression: NOT"))
8ae2d595 1622 log_fatal ("can't allocate expression");
02a015fb
TL
1623 (*expr) -> op = expr_not;
1624 if (!parse_non_binary (&(*expr) -> data.not,
1625 cfile, lose, context)) {
be6be08d 1626 if (!*lose) {
02a015fb 1627 parse_warn ("expression expected");
be6be08d
TL
1628 skip_to_semi (cfile);
1629 }
1630 *lose = 1;
02a015fb
TL
1631 expression_dereference (expr, "parse_expression: NOT");
1632 return 0;
be6be08d 1633 }
be6be08d 1634 break;
be6be08d 1635
02a015fb
TL
1636 case EXISTS:
1637 token = next_token (&val, cfile);
1638 if (!expression_allocate (expr, "parse_expression: EXISTS"))
8ae2d595 1639 log_fatal ("can't allocate expression");
02a015fb 1640 (*expr) -> op = expr_exists;
6b4b0ec7 1641 (*expr) -> data.option = parse_option_name (cfile, 0);
02a015fb
TL
1642 if (!(*expr) -> data.option) {
1643 *lose = 1;
1644 expression_dereference (expr,
1645 "parse_expression: EXISTS");
1646 return 0;
be6be08d 1647 }
02a015fb 1648 break;
be6be08d 1649
70330633
TL
1650 case KNOWN:
1651 token = next_token (&val, cfile);
1652 if (!expression_allocate (expr, "parse_expression: EXISTS"))
1653 log_fatal ("can't allocate expression");
1654 (*expr) -> op = expr_known;
1655 break;
1656
be6be08d
TL
1657 case SUBSTRING:
1658 token = next_token (&val, cfile);
02a015fb 1659 if (!expression_allocate (expr, "parse_expression: SUBSTRING"))
8ae2d595 1660 log_fatal ("can't allocate expression");
02a015fb 1661 (*expr) -> op = expr_substring;
be6be08d
TL
1662
1663 token = next_token (&val, cfile);
1664 if (token != LPAREN) {
1665 nolparen:
02a015fb
TL
1666 expression_dereference (expr,
1667 "parse_expression: nolparen");
be6be08d
TL
1668 parse_warn ("left parenthesis expected.");
1669 *lose = 1;
02a015fb 1670 return 0;
be6be08d
TL
1671 }
1672
02a015fb
TL
1673 if (!parse_data_expression (&(*expr) -> data.substring.expr,
1674 cfile, lose)) {
be6be08d 1675 nodata:
02a015fb
TL
1676 expression_dereference (expr,
1677 "parse_expression: nodata");
be6be08d
TL
1678 parse_warn ("expecting data expression.");
1679 skip_to_semi (cfile);
1680 *lose = 1;
02a015fb 1681 return 0;
be6be08d
TL
1682 }
1683
1684 token = next_token (&val, cfile);
1685 if (token != COMMA) {
1686 nocomma:
02a015fb
TL
1687 expression_dereference (expr,
1688 "parse_expression: nocomma1");
be6be08d
TL
1689 parse_warn ("comma expected.");
1690 *lose = 1;
02a015fb
TL
1691
1692 return 0;
be6be08d
TL
1693 }
1694
02a015fb
TL
1695 if (!parse_numeric_expression
1696 (&(*expr) -> data.substring.offset,cfile, lose)) {
be6be08d
TL
1697 nonum:
1698 if (!*lose) {
1699 parse_warn ("expecting numeric expression.");
1700 skip_to_semi (cfile);
1701 *lose = 1;
1702 }
02a015fb
TL
1703 expression_dereference (expr,
1704 "parse_expression: nonum");
1705 return 0;
be6be08d
TL
1706 }
1707
1708 token = next_token (&val, cfile);
1709 if (token != COMMA)
1710 goto nocomma;
1711
02a015fb
TL
1712 if (!parse_numeric_expression
1713 (&(*expr) -> data.substring.len, cfile, lose))
be6be08d
TL
1714 goto nonum;
1715
1716 token = next_token (&val, cfile);
1717 if (token != RPAREN) {
1718 norparen:
1719 parse_warn ("right parenthesis expected.");
1720 *lose = 1;
02a015fb
TL
1721 expression_dereference (expr,
1722 "parse_expression: norparen");
1723 return 0;
be6be08d 1724 }
02a015fb 1725 break;
be6be08d
TL
1726
1727 case SUFFIX:
1728 token = next_token (&val, cfile);
02a015fb 1729 if (!expression_allocate (expr, "parse_expression: SUFFIX"))
8ae2d595 1730 log_fatal ("can't allocate expression");
02a015fb 1731 (*expr) -> op = expr_suffix;
be6be08d
TL
1732
1733 token = next_token (&val, cfile);
1734 if (token != LPAREN)
1735 goto nolparen;
1736
02a015fb
TL
1737 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
1738 cfile, lose))
be6be08d
TL
1739 goto nodata;
1740
1741 token = next_token (&val, cfile);
1742 if (token != COMMA)
1743 goto nocomma;
1744
02a015fb
TL
1745 if (!parse_data_expression (&(*expr) -> data.suffix.len,
1746 cfile, lose))
be6be08d
TL
1747 goto nonum;
1748
1749 token = next_token (&val, cfile);
1750 if (token != RPAREN)
1751 goto norparen;
02a015fb 1752 break;
be6be08d 1753
a82abfc7
TL
1754 case CONCAT:
1755 token = next_token (&val, cfile);
1756 if (!expression_allocate (expr, "parse_expression: CONCAT"))
1757 log_fatal ("can't allocate expression");
1758 (*expr) -> op = expr_concat;
1759
1760 token = next_token (&val, cfile);
1761 if (token != LPAREN)
1762 goto nolparen;
1763
1764 if (!parse_data_expression (&(*expr) -> data.concat [0],
1765 cfile, lose))
1766 goto nodata;
1767
1768 token = next_token (&val, cfile);
1769 if (token != COMMA)
1770 goto nocomma;
1771
1772 if (!parse_data_expression (&(*expr) -> data.concat [1],
1773 cfile, lose))
1774 goto nodata;
1775
1776 token = next_token (&val, cfile);
1777 if (token != RPAREN)
1778 goto norparen;
1779 break;
1780
da38df14
TL
1781 case BINARY_TO_ASCII:
1782 token = next_token (&val, cfile);
1783 if (!expression_allocate (expr, "parse_expression: B2A"))
1784 log_fatal ("can't allocate expression");
eb42f00e 1785 (*expr) -> op = expr_binary_to_ascii;
da38df14
TL
1786
1787 token = next_token (&val, cfile);
1788 if (token != LPAREN)
1789 goto nolparen;
1790
1791 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
1792 cfile, lose))
1793 goto nodata;
1794
1795 token = next_token (&val, cfile);
1796 if (token != COMMA)
1797 goto nocomma;
1798
1799 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
1800 cfile, lose))
1801 goto nodata;
1802
1803 token = next_token (&val, cfile);
1804 if (token != COMMA)
1805 goto nocomma;
1806
1807 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
1808 cfile, lose))
1809 goto nodata;
1810
1811 token = next_token (&val, cfile);
1812 if (token != COMMA)
1813 goto nocomma;
1814
1815 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
1816 cfile, lose))
1817 goto nodata;
1818
1819 token = next_token (&val, cfile);
1820 if (token != RPAREN)
1821 goto norparen;
1822 break;
1823
1824 case REVERSE:
1825 token = next_token (&val, cfile);
1826 if (!expression_allocate (expr, "parse_expression: REVERSE"))
1827 log_fatal ("can't allocate expression");
eb42f00e 1828 (*expr) -> op = expr_reverse;
da38df14
TL
1829
1830 token = next_token (&val, cfile);
1831 if (token != LPAREN)
1832 goto nolparen;
1833
1834 if (!(parse_numeric_expression
1835 (&(*expr) -> data.reverse.width, cfile, lose)))
1836 goto nodata;
1837
1838 token = next_token (&val, cfile);
1839 if (token != COMMA)
1840 goto nocomma;
1841
1842 if (!(parse_data_expression
1843 (&(*expr) -> data.reverse.buffer, cfile, lose)))
1844 goto nodata;
1845
1846 token = next_token (&val, cfile);
1847 if (token != RPAREN)
1848 goto norparen;
1849 break;
1850
79a65726
TL
1851 case PICK_FIRST_VALUE:
1852 /* pick (a, b, c) actually produces an internal representation
1853 that looks like pick (a, pick (b, pick (c, nil))). */
1854 token = next_token (&val, cfile);
1855 if (!(expression_allocate
1856 (expr, "parse_expression: PICK_FIRST_VALUE")))
1857 log_fatal ("can't allocate expression");
1858 (*expr) -> op = expr_reverse;
1859
be6be08d 1860 token = next_token (&val, cfile);
79a65726
TL
1861 if (token != LPAREN)
1862 goto nolparen;
1863
1864 nexp = *expr;
1865 do {
1866 struct expression *tmp = (struct expression *)0;
1867 if (!(parse_data_expression
1868 (&nexp -> data.pick_first_value.car,
1869 cfile, lose)))
1870 goto nodata;
1871
1872 token = next_token (&val, cfile);
1873 if (token == COMMA) {
1874 if (!(expression_allocate
1875 (&nexp -> data.pick_first_value.cdr,
1876 "parse_expression: PICK_FIRST_VALUE")))
1877 log_fatal ("can't allocate expr");
1878 nexp = nexp -> data.pick_first_value.cdr;
1879 }
1880 } while (token == COMMA);
1881
1882 if (token != RPAREN)
1883 goto norparen;
1884 break;
1885
1886 case OPTION:
1887 case CONFIG_OPTION:
02a015fb 1888 if (!expression_allocate (expr, "parse_expression: OPTION"))
8ae2d595 1889 log_fatal ("can't allocate expression");
79a65726
TL
1890 (*expr) -> op = token == (OPTION
1891 ? expr_option
1892 : expr_config_option);
1893 token = next_token (&val, cfile);
6b4b0ec7 1894 (*expr) -> data.option = parse_option_name (cfile, 0);
02a015fb 1895 if (!(*expr) -> data.option) {
be6be08d 1896 *lose = 1;
02a015fb
TL
1897 expression_dereference (expr,
1898 "parse_expression: OPTION");
1899 return 0;
be6be08d 1900 }
02a015fb 1901 break;
be6be08d
TL
1902
1903 case HARDWARE:
1904 token = next_token (&val, cfile);
02a015fb 1905 if (!expression_allocate (expr, "parse_expression: HARDWARE"))
8ae2d595 1906 log_fatal ("can't allocate expression");
02a015fb
TL
1907 (*expr) -> op = expr_hardware;
1908 break;
be6be08d 1909
da38df14
TL
1910 case LEASED_ADDRESS:
1911 token = next_token (&val, cfile);
1912 if (!expression_allocate (expr,
1913 "parse_expression: LEASED_ADDRESS"))
1914 log_fatal ("can't allocate expression");
1915 (*expr) -> op = expr_leased_address;
1916 break;
1917
79a65726
TL
1918 case HOST_DECL_NAME:
1919 token = next_token (&val, cfile);
1920 if (!expression_allocate (expr,
1921 "parse_expression: HOST_DECL_NAME"))
1922 log_fatal ("can't allocate expression");
1923 (*expr) -> op = expr_host_decl_name;
1924 break;
1925
be6be08d
TL
1926 case PACKET:
1927 token = next_token (&val, cfile);
02a015fb 1928 if (!expression_allocate (expr, "parse_expression: PACKET"))
8ae2d595 1929 log_fatal ("can't allocate expression");
02a015fb 1930 (*expr) -> op = expr_packet;
be6be08d
TL
1931
1932 token = next_token (&val, cfile);
1933 if (token != LPAREN)
1934 goto nolparen;
1935
02a015fb
TL
1936 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
1937 cfile, lose))
be6be08d
TL
1938 goto nonum;
1939
1940 token = next_token (&val, cfile);
1941 if (token != COMMA)
1942 goto nocomma;
1943
02a015fb
TL
1944 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
1945 cfile, lose))
be6be08d
TL
1946 goto nonum;
1947
1948 token = next_token (&val, cfile);
1949 if (token != RPAREN)
1950 goto norparen;
02a015fb 1951 break;
be6be08d
TL
1952
1953 case STRING:
1954 token = next_token (&val, cfile);
c5b0f529
TL
1955 if (!make_const_data (expr, (unsigned char *)val,
1956 strlen (val), 1, 1))
8ae2d595 1957 log_fatal ("can't make constant string expression.");
02a015fb 1958 break;
be6be08d 1959
be6be08d
TL
1960 case EXTRACT_INT:
1961 token = next_token (&val, cfile);
be6be08d
TL
1962 token = next_token (&val, cfile);
1963 if (token != LPAREN) {
1964 parse_warn ("left parenthesis expected.");
1965 *lose = 1;
02a015fb 1966 return 0;
be6be08d
TL
1967 }
1968
02a015fb
TL
1969 if (!expression_allocate (expr,
1970 "parse_expression: EXTRACT_INT"))
8ae2d595 1971 log_fatal ("can't allocate expression");
02a015fb
TL
1972
1973 if (!parse_data_expression (&(*expr) -> data.extract_int,
1974 cfile, lose)) {
be6be08d
TL
1975 parse_warn ("expecting data expression.");
1976 skip_to_semi (cfile);
1977 *lose = 1;
02a015fb
TL
1978 expression_dereference
1979 (expr, "parse_expression: EXTRACT_INT");
1980 return 0;
be6be08d
TL
1981 }
1982
1983 token = next_token (&val, cfile);
1984 if (token != COMMA) {
1985 parse_warn ("comma expected.");
1986 *lose = 1;
02a015fb 1987 return 0;
be6be08d
TL
1988 }
1989
1990 token = next_token (&val, cfile);
1991 if (token != NUMBER) {
1992 parse_warn ("number expected.");
1993 *lose = 1;
02a015fb 1994 return 0;
be6be08d 1995 }
be6be08d
TL
1996 switch (atoi (val)) {
1997 case 8:
02a015fb 1998 (*expr) -> op = expr_extract_int8;
be6be08d
TL
1999 break;
2000
2001 case 16:
02a015fb 2002 (*expr) -> op = expr_extract_int16;
be6be08d
TL
2003 break;
2004
2005 case 32:
02a015fb 2006 (*expr) -> op = expr_extract_int32;
be6be08d
TL
2007 break;
2008
2009 default:
2010 parse_warn ("unsupported integer size %d", atoi (val));
2011 *lose = 1;
2012 skip_to_semi (cfile);
02a015fb
TL
2013 expression_dereference
2014 (expr, "parse_expression: EXTRACT_INT");
2015 return 0;
be6be08d
TL
2016 }
2017
2018 token = next_token (&val, cfile);
2019 if (token != RPAREN) {
2020 parse_warn ("right parenthesis expected.");
2021 *lose = 1;
02a015fb 2022 return 0;
be6be08d 2023 }
02a015fb 2024 break;
be6be08d 2025
20c4e94d
TL
2026 case ENCODE_INT:
2027 token = next_token (&val, cfile);
2028 token = next_token (&val, cfile);
2029 if (token != LPAREN) {
2030 parse_warn ("left parenthesis expected.");
2031 *lose = 1;
2032 return 0;
2033 }
2034
2035 if (!expression_allocate (expr,
2036 "parse_expression: ENCODE_INT"))
2037 log_fatal ("can't allocate expression");
2038
2039 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
2040 cfile, lose)) {
2041 parse_warn ("expecting numeric expression.");
2042 skip_to_semi (cfile);
2043 *lose = 1;
2044 expression_dereference
2045 (expr, "parse_expression: ENCODE_INT");
2046 return 0;
2047 }
2048
2049 token = next_token (&val, cfile);
2050 if (token != COMMA) {
2051 parse_warn ("comma expected.");
2052 *lose = 1;
2053 return 0;
2054 }
2055
2056 token = next_token (&val, cfile);
2057 if (token != NUMBER) {
2058 parse_warn ("number expected.");
2059 *lose = 1;
2060 return 0;
2061 }
2062 switch (atoi (val)) {
2063 case 8:
2064 (*expr) -> op = expr_encode_int8;
2065 break;
2066
2067 case 16:
2068 (*expr) -> op = expr_encode_int16;
2069 break;
2070
2071 case 32:
2072 (*expr) -> op = expr_encode_int32;
2073 break;
2074
2075 default:
2076 parse_warn ("unsupported integer size %d", atoi (val));
2077 *lose = 1;
2078 skip_to_semi (cfile);
2079 expression_dereference
2080 (expr, "parse_expression: ENCODE_INT");
2081 return 0;
2082 }
2083
2084 token = next_token (&val, cfile);
2085 if (token != RPAREN) {
2086 parse_warn ("right parenthesis expected.");
2087 *lose = 1;
2088 return 0;
2089 }
2090 break;
2091
be6be08d 2092 case NUMBER:
02a015fb
TL
2093 /* If we're in a numeric context, this should just be a
2094 number, by itself. */
2095 if (context == context_numeric) {
2096 next_token (&val, cfile); /* Eat the number. */
be19167d
TL
2097 if (!expression_allocate (expr,
2098 "parse_expression: NUMBER"))
2099 log_fatal ("can't allocate expression");
02a015fb
TL
2100 (*expr) -> op = expr_const_int;
2101 (*expr) -> data.const_int = atoi (val);
2102 break;
2103 }
be6be08d 2104
02a015fb 2105 case NUMBER_OR_NAME:
be19167d
TL
2106 if (!expression_allocate (expr,
2107 "parse_expression: NUMBER_OR_NAME"))
2108 log_fatal ("can't allocate expression");
2109
02a015fb
TL
2110 (*expr) -> op = expr_const_data;
2111 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
2112 expression_dereference (expr,
2113 "parse_expression: cshl");
2114 return 0;
2115 }
2116 break;
2117
2118 /* Not a valid start to an expression... */
be6be08d 2119 default:
02a015fb 2120 return 0;
be6be08d 2121 }
02a015fb 2122 return 1;
be6be08d
TL
2123}
2124
02a015fb
TL
2125/* Parse an expression. */
2126
2127int parse_expression (expr, cfile, lose, context, plhs, binop)
2128 struct expression **expr;
2129 FILE *cfile;
2130 int *lose;
2131 enum expression_context context;
2132 struct expression **plhs;
2133 enum expr_op binop;
2134{
2135 enum dhcp_token token;
2136 char *val;
2137 struct expression *rhs = (struct expression *)0, *tmp;
2138 struct expression *lhs;
2139 enum expr_op next_op;
2140
2141 /* Consume the left hand side we were passed. */
2142 if (plhs) {
2143 lhs = *plhs;
2144 *plhs = (struct expression *)0;
2145 } else
2146 lhs = (struct expression *)0;
2147
2148 new_rhs:
2149 if (!parse_non_binary (&rhs, cfile, lose, context)) {
2150 /* If we already have a left-hand side, then it's not
2151 okay for there not to be a right-hand side here, so
2152 we need to flag it as an error. */
2153 if (lhs) {
2154 if (!*lose) {
2155 parse_warn ("expecting right-hand side.");
2156 *lose = 1;
2157 skip_to_semi (cfile);
2158 }
2159 expression_dereference (&lhs, "parse_expression");
2160 }
2161 return 0;
2162 }
2163
2164 /* At this point, rhs contains either an entire subexpression,
2165 or at least a left-hand-side. If we do not see a binary token
2166 as the next token, we're done with the expression. */
2167
2168 token = peek_token (&val, cfile);
2169 switch (token) {
2170 case EQUAL:
2171 next_op = expr_equal;
2172 break;
2173
2174 case AND:
2175 next_op = expr_and;
2176 break;
2177
2178 case OR:
2179 next_op = expr_or;
2180 break;
2181
2182 default:
2183 next_op = expr_none;
2184 }
2185
2186 /* If we have no lhs yet, we just parsed it. */
2187 if (!lhs) {
2188 /* If there was no operator following what we just parsed,
2189 then we're done - return it. */
2190 if (next_op == expr_none) {
2191 *expr = rhs;
2192 return 1;
2193 }
2194 lhs = rhs;
2195 rhs = (struct expression *)0;
2196 binop = next_op;
2197 next_token (&val, cfile); /* Consume the operator. */
2198 goto new_rhs;
2199 }
2200
2201 /* Now, if we didn't find a binary operator, we're done parsing
2202 this subexpression, so combine it with the preceding binary
2203 operator and return the result. */
2204 if (next_op == expr_none) {
2205 if (!expression_allocate (expr,
2206 "parse_expression: COMBINE"))
8ae2d595 2207 log_fatal ("Can't allocate expression!");
02a015fb
TL
2208
2209 (*expr) -> op = binop;
2210 /* All the binary operators' data union members
2211 are the same, so we'll cheat and use the member
2212 for the equals operator. */
2213 (*expr) -> data.equal [0] = lhs;
2214 (*expr) -> data.equal [1] = rhs;
2215 return 1;
2216 }
2217
2218 /* Eat the operator token - we now know it was a binary operator... */
2219 token = next_token (&val, cfile);
2220
2221 /* If the binary operator we saw previously has a lower precedence
2222 than the next operator, then the rhs we just parsed for that
2223 operator is actually the lhs of the operator with the higher
2224 precedence - to get the real rhs, we need to recurse on the
2225 new operator. */
2226 if (binop != expr_none &&
2227 op_precedence (binop, next_op) < 0) {
2228 tmp = rhs;
2229 rhs = (struct expression *)0;
2230 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
2231 &tmp, next_op)) {
2232 if (!*lose) {
2233 parse_warn ("expecting a subexpression");
2234 *lose = 1;
2235 }
2236 return 0;
2237 }
2238 next_op = expr_none;
2239 }
2240
2241 /* Now combine the LHS and the RHS using binop. */
2242 tmp = (struct expression *)0;
2243 if (!expression_allocate (&tmp, "parse_expression: COMBINE2"))
8ae2d595 2244 log_fatal ("No memory for equal precedence combination.");
02a015fb
TL
2245
2246 /* Store the LHS and RHS. */
2247 tmp -> data.equal [0] = lhs;
2248 tmp -> data.equal [1] = rhs;
2249 tmp -> op = binop;
2250
2251 lhs = tmp;
2252 tmp = (struct expression *)0;
2253 rhs = (struct expression *)0;
2254
2255 /* Recursions don't return until we have parsed the end of the
2256 expression, so if we recursed earlier, we can now return what
2257 we got. */
2258 if (next_op == expr_none) {
2259 *expr = lhs;
2260 return 1;
2261 }
2262
2263 binop = next_op;
2264 goto new_rhs;
2265}
2266
be6be08d
TL
2267/* option-statement :== identifier DOT identifier <syntax> SEMI
2268 | identifier <syntax> SEMI
2269
2270 Option syntax is handled specially through format strings, so it
2271 would be painful to come up with BNF for it. However, it always
2272 starts as above and ends in a SEMI. */
2273
79a65726
TL
2274int parse_option_statement (result, cfile, lookups, option, op)
2275 struct executable_statement **result;
be6be08d
TL
2276 FILE *cfile;
2277 int lookups;
2278 struct option *option;
2279 enum statement_op op;
2280{
2281 char *val;
02a015fb 2282 enum dhcp_token token;
be6be08d
TL
2283 char *fmt;
2284 struct expression *expr = (struct expression *)0;
02a015fb 2285 struct expression *tmp;
be6be08d
TL
2286 int lose;
2287 struct executable_statement *stmt;
02a015fb 2288 int ftt = 1;
be6be08d
TL
2289
2290 token = peek_token (&val, cfile);
2291 if (token == SEMI) {
2292 /* Eat the semicolon... */
2293 token = next_token (&val, cfile);
be6be08d
TL
2294 goto done;
2295 }
2296
a82abfc7
TL
2297 if (token == EQUAL) {
2298 /* Eat the equals sign. */
2299 token = next_token (&val, cfile);
2300
2301 /* Parse a data expression and use its value for the data. */
2302 if (!parse_data_expression (&expr, cfile, &lose)) {
2303 /* In this context, we must have an executable
2304 statement, so if we found something else, it's
2305 still an error. */
2306 if (!lose) {
2307 parse_warn ("expecting a data expression.");
2308 skip_to_semi (cfile);
2309 }
79a65726 2310 return 0;
a82abfc7
TL
2311 }
2312
2313 /* We got a valid expression, so use it. */
2314 goto done;
2315 }
2316
be6be08d
TL
2317 /* Parse the option data... */
2318 do {
2319 /* Set a flag if this is an array of a simple type (i.e.,
2320 not an array of pairs of IP addresses, or something
2321 like that. */
2322 int uniform = option -> format [1] == 'A';
2323
2324 for (fmt = option -> format; *fmt; fmt++) {
2325 if (*fmt == 'A')
2326 break;
02a015fb 2327 tmp = expr;
44aa67f6 2328 expr = (struct expression *)0;
02a015fb
TL
2329 if (!parse_option_token (&expr, cfile, fmt,
2330 tmp, uniform, lookups)) {
2331 expression_dereference
2332 (&tmp, "parse_option_statement");
79a65726 2333 return 0;
02a015fb
TL
2334 }
2335 if (tmp)
2336 expression_dereference
2337 (&tmp, "parse_option_statement");
be6be08d
TL
2338 }
2339 if (*fmt == 'A') {
2340 token = peek_token (&val, cfile);
2341 if (token == COMMA) {
2342 token = next_token (&val, cfile);
2343 continue;
2344 }
2345 break;
2346 }
2347 } while (*fmt == 'A');
2348
2349 done:
25541f2f 2350 if (!parse_semi (cfile))
79a65726
TL
2351 return 0;
2352 if (!executable_statement_allocate (result, "parse_option_statement"))
2353 log_fatal ("no memory for option statement.");
2354 (*result) -> op = op;
2355 if (expr && !option_cache (&(*result) -> data.option,
02a015fb 2356 (struct data_string *)0, expr, option))
52c9d530 2357 log_fatal ("no memory for option cache");
79a65726 2358 return 1;
be6be08d
TL
2359}
2360
02a015fb
TL
2361int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
2362 struct expression **rv;
be6be08d
TL
2363 FILE *cfile;
2364 char *fmt;
2365 struct expression *expr;
2366 int uniform;
2367 int lookups;
2368{
2369 char *val;
02a015fb
TL
2370 enum dhcp_token token;
2371 struct expression *t = (struct expression *)0;
be6be08d
TL
2372 unsigned char buf [4];
2373 int len;
2374 unsigned char *ob;
2375 struct iaddr addr;
2376
2377 switch (*fmt) {
52c9d530
TL
2378 case 'U':
2379 token = next_token (&val, cfile);
2380 if (!is_identifier (token)) {
2381 parse_warn ("expecting identifier.");
2382 skip_to_semi (cfile);
2383 return 0;
2384 }
2385 if (!make_const_data (&t, (unsigned char *)val,
2386 strlen (val), 1, 1))
2387 log_fatal ("No memory for %s", val);
2388 break;
2389
be6be08d
TL
2390 case 'X':
2391 token = peek_token (&val, cfile);
2392 if (token == NUMBER_OR_NAME || token == NUMBER) {
02a015fb
TL
2393 if (!expression_allocate (&t, "parse_option_token"))
2394 return 0;
2395 if (!parse_cshl (&t -> data.const_data, cfile))
2396 return 0;
efc79acb 2397 t -> op = expr_const_data;
be6be08d
TL
2398 } else if (token == STRING) {
2399 token = next_token (&val, cfile);
52c9d530 2400 if (!make_const_data (&t, (unsigned char *)val,
02a015fb 2401 strlen (val), 1, 1))
52c9d530 2402 log_fatal ("No memory for \"%s\"", val);
be6be08d
TL
2403 } else {
2404 parse_warn ("expecting string %s.",
2405 "or hexadecimal data");
2406 skip_to_semi (cfile);
02a015fb 2407 return 0;
be6be08d
TL
2408 }
2409 break;
2410
2411 case 't': /* Text string... */
2412 token = next_token (&val, cfile);
2413 if (token != STRING && !is_identifier (token)) {
2414 parse_warn ("expecting string.");
2415 if (token != SEMI)
2416 skip_to_semi (cfile);
02a015fb 2417 return 0;
be6be08d 2418 }
02a015fb
TL
2419 if (!make_const_data (&t, (unsigned char *)val,
2420 strlen (val), 1, 1))
8ae2d595 2421 log_fatal ("No memory for concatenation");
be6be08d
TL
2422 break;
2423
2424 case 'I': /* IP address or hostname. */
02a015fb
TL
2425 if (lookups) {
2426 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
2427 return 0;
2428 } else {
be6be08d 2429 if (!parse_ip_addr (cfile, &addr))
02a015fb
TL
2430 return 0;
2431 if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1))
2432 return 0;
be6be08d 2433 }
be6be08d
TL
2434 break;
2435
2436 case 'L': /* Unsigned 32-bit integer... */
2437 case 'l': /* Signed 32-bit integer... */
2438 token = next_token (&val, cfile);
2439 if (token != NUMBER) {
2440 need_number:
2441 parse_warn ("expecting number.");
2442 if (token != SEMI)
2443 skip_to_semi (cfile);
02a015fb 2444 return 0;
be6be08d
TL
2445 }
2446 convert_num (buf, val, 0, 32);
02a015fb
TL
2447 if (!make_const_data (&t, buf, 4, 0, 1))
2448 return 0;
be6be08d 2449 break;
02a015fb 2450
be6be08d
TL
2451 case 's': /* Signed 16-bit integer. */
2452 case 'S': /* Unsigned 16-bit integer. */
2453 token = next_token (&val, cfile);
2454 if (token != NUMBER)
2455 goto need_number;
2456 convert_num (buf, val, 0, 16);
02a015fb
TL
2457 if (!make_const_data (&t, buf, 2, 0, 1))
2458 return 0;
be6be08d 2459 break;
02a015fb 2460
be6be08d
TL
2461 case 'b': /* Signed 8-bit integer. */
2462 case 'B': /* Unsigned 8-bit integer. */
2463 token = next_token (&val, cfile);
2464 if (token != NUMBER)
2465 goto need_number;
2466 convert_num (buf, val, 0, 8);
02a015fb
TL
2467 if (!make_const_data (&t, buf, 1, 0, 1))
2468 return 0;
be6be08d 2469 break;
02a015fb 2470
be6be08d
TL
2471 case 'f': /* Boolean flag. */
2472 token = next_token (&val, cfile);
2473 if (!is_identifier (token)) {
2474 parse_warn ("expecting identifier.");
2475 bad_flag:
2476 if (token != SEMI)
2477 skip_to_semi (cfile);
02a015fb 2478 return 0;
be6be08d
TL
2479 }
2480 if (!strcasecmp (val, "true")
2481 || !strcasecmp (val, "on"))
2482 buf [0] = 1;
2483 else if (!strcasecmp (val, "false")
2484 || !strcasecmp (val, "off"))
2485 buf [0] = 0;
2486 else {
2487 parse_warn ("expecting boolean.");
2488 goto bad_flag;
2489 }
02a015fb
TL
2490 if (!make_const_data (&t, buf, 1, 0, 1))
2491 return 0;
be6be08d 2492 break;
02a015fb 2493
be6be08d 2494 default:
8ae2d595 2495 log_error ("Bad format %c in parse_option_param.",
be6be08d
TL
2496 *fmt);
2497 skip_to_semi (cfile);
02a015fb 2498 return 0;
be6be08d 2499 }
02a015fb
TL
2500 if (expr) {
2501 if (!make_concat (rv, expr, t))
2502 return 0;
2503 expression_dereference (&t, "parse_option_token");
2504 } else
2505 *rv = t;
2506 return 1;
be6be08d 2507}
74f45f96 2508
b1013db7
TL
2509/* allow-deny-keyword :== BOOTP
2510 | BOOTING
2511 | DYNAMIC_BOOTP
2512 | UNKNOWN_CLIENTS */
2513
2514int parse_allow_deny (oc, cfile, flag)
2515 struct option_cache **oc;
2516 FILE *cfile;
2517 int flag;
2518{
2519 enum dhcp_token token;
2520 char *val;
2521 unsigned char rf = flag;
2522 struct expression *data = (struct expression *)0;
2523 int status;
2524
2525 if (!make_const_data (&data, &rf, 1, 0, 1))
2526 return 0;
2527
2528 token = next_token (&val, cfile);
2529 switch (token) {
2530 case BOOTP:
2531 status = option_cache (oc, (struct data_string *)0, data,
2532 &server_options [SV_ALLOW_BOOTP]);
2533 break;
2534
2535 case BOOTING:
2536 status = option_cache (oc, (struct data_string *)0, data,
2537 &server_options [SV_ALLOW_BOOTING]);
2538 break;
2539
2540 case DYNAMIC_BOOTP:
2541 status = option_cache (oc, (struct data_string *)0, data,
2542 &server_options [SV_DYNAMIC_BOOTP]);
2543 break;
2544
2545 case UNKNOWN_CLIENTS:
2546 status = (option_cache
2547 (oc, (struct data_string *)0, data,
2548 &server_options [SV_BOOT_UNKNOWN_CLIENTS]));
2549 break;
2550
2551 default:
2552 parse_warn ("expecting allow/deny key");
2553 skip_to_semi (cfile);
2554 return 0;
2555 }
2556 parse_semi (cfile);
2557 return status;
2558}
2559
74f45f96
TL
2560int parse_auth_key (key_id, cfile)
2561 struct data_string *key_id;
2562 FILE *cfile;
2563{
2564 struct data_string key_data;
2565 char *val;
2566 enum dhcp_token token;
2567 struct auth_key *key, *old_key = (struct auth_key *)0;
2568
2569 memset (&key_data, 0, sizeof key_data);
2570
2571 if (!parse_cshl (key_id, cfile))
2572 return 0;
2573
2574 key = auth_key_lookup (key_id);
2575
2576 token = peek_token (&val, cfile);
2577 if (token == SEMI) {
2578 if (!key)
2579 parse_warn ("reference to undefined key %s",
2580 print_hex_1 (key_id -> len,
2581 key_id -> data,
2582 key_id -> len));
2583 data_string_forget (key_id, "parse_auth_key");
2584 } else {
2585 if (!parse_cshl (&key_data, cfile))
2586 return 0;
2587 if (key) {
2588 parse_warn ("redefinition of key %s",
2589 print_hex_1 (key_id -> len,
2590 key_id -> data,
2591 key_id -> len));
2592 old_key = key;
2593 }
2594 key = new_auth_key (key_data.len, "parse_auth_key");
2595 if (!key)
2596 log_fatal ("No memory for key %s",
2597 print_hex_1 (key_id -> len,
2598 key_id -> data,
2599 key_id -> len));
2600 key -> length = key_data.len;
2601 memcpy (key -> data, key_data.data, key_data.len);
2602 enter_auth_key (key_id, key);
2603 data_string_forget (&key_data, "parse_auth_key");
2604 }
2605
2606 parse_semi (cfile);
2607 return key_id -> len ? 1 : 0;
2608}