]> git.ipfire.org Git - thirdparty/dhcp.git/blame - common/parse.c
- Compute max-lease-time outside of conditional so that we always have
[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[] =
eb42f00e 25"$Id: parse.c,v 1.27 1999/07/06 16:57:05 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
1154struct executable_statement *parse_executable_statements (cfile, lose)
1155 FILE *cfile;
1156 int *lose;
1157{
1158 struct executable_statement *head, **next;
1159
1160 next = &head;
1161 while ((*next = parse_executable_statement (cfile, lose)))
1162 next = &((*next) -> next);
02a015fb 1163 if (!*lose)
be6be08d
TL
1164 return head;
1165 return (struct executable_statement *)0;
1166}
1167
1168struct executable_statement *parse_executable_statement (cfile, lose)
1169 FILE *cfile;
1170 int *lose;
1171{
02a015fb 1172 enum dhcp_token token;
be6be08d
TL
1173 char *val;
1174 struct executable_statement *stmt, base;
1175 struct class *cta;
1176 struct option *option;
b1013db7 1177 struct option_cache *cache;
be6be08d 1178
b1013db7
TL
1179 token = peek_token (&val, cfile);
1180 switch (token) {
be6be08d 1181 case IF:
dce70f9f 1182 next_token (&val, cfile);
be6be08d
TL
1183 stmt = parse_if_statement (cfile, lose);
1184 return stmt;
eb018e2b 1185 case TOKEN_ADD:
efc79acb 1186 token = next_token (&val, cfile);
be6be08d
TL
1187 token = next_token (&val, cfile);
1188 if (token != STRING) {
1189 parse_warn ("expecting class name.");
1190 skip_to_semi (cfile);
1191 *lose = 1;
1192 return (struct executable_statement *)0;
1193 }
1194 cta = find_class (val);
1195 if (!cta) {
1196 parse_warn ("unknown class %s.", val);
1197 skip_to_semi (cfile);
1198 *lose = 1;
1199 return (struct executable_statement *)0;
1200 }
1201 if (!parse_semi (cfile)) {
1202 *lose = 1;
1203 return (struct executable_statement *)0;
1204 }
1205 memset (&base, 0, sizeof base);
1206 base.op = add_statement;
1207 base.data.add = cta;
1208 break;
1209
1210 case BREAK:
1211 token = next_token (&val, cfile);
1212 if (!parse_semi (cfile)) {
1213 *lose = 1;
1214 return (struct executable_statement *)0;
1215 }
1216 memset (&base, 0, sizeof base);
1217 base.op = break_statement;
1218 break;
1219
25541f2f
TL
1220 case SEND:
1221 *lose = 1;
1222 parse_warn ("send not appropriate here.");
1223 skip_to_semi (cfile);
1224 return (struct executable_statement *)0;
1225
1226 case SUPERSEDE:
be6be08d
TL
1227 case OPTION:
1228 token = next_token (&val, cfile);
6b4b0ec7 1229 option = parse_option_name (cfile, 0);
be6be08d
TL
1230 if (!option) {
1231 *lose = 1;
1232 return (struct executable_statement *)0;
1233 }
1234 return parse_option_statement (cfile, 1, option,
1235 supersede_option_statement);
1236
b1013db7
TL
1237 case ALLOW:
1238 case DENY:
1239 token = next_token (&val, cfile);
1240 cache = (struct option_cache *)0;
1241 if (!parse_allow_deny (&cache, cfile,
1242 token == ALLOW ? 1 : 0))
1243 return (struct executable_statement *)0;
1244 memset (&base, 0, sizeof base);
1245 base.op = supersede_option_statement;
1246 base.data.option = cache;
1247 break;
1248
be6be08d
TL
1249 case DEFAULT:
1250 token = next_token (&val, cfile);
6b4b0ec7 1251 option = parse_option_name (cfile, 0);
be6be08d
TL
1252 if (!option) {
1253 *lose = 1;
1254 return (struct executable_statement *)0;
1255 }
1256 return parse_option_statement (cfile, 1, option,
1257 default_option_statement);
1258
1259 case PREPEND:
1260 token = next_token (&val, cfile);
6b4b0ec7 1261 option = parse_option_name (cfile, 0);
be6be08d
TL
1262 if (!option) {
1263 *lose = 1;
1264 return (struct executable_statement *)0;
1265 }
1266 return parse_option_statement (cfile, 1, option,
1267 prepend_option_statement);
1268
1269 case APPEND:
1270 token = next_token (&val, cfile);
6b4b0ec7 1271 option = parse_option_name (cfile, 0);
be6be08d
TL
1272 if (!option) {
1273 *lose = 1;
1274 return (struct executable_statement *)0;
1275 }
1276 return parse_option_statement (cfile, 1, option,
1277 append_option_statement);
1278
1279 default:
1280 *lose = 0;
1281 return (struct executable_statement *)0;
1282 }
1283
1284 stmt = ((struct executable_statement *)
1285 dmalloc (sizeof (struct executable_statement),
1286 "parse_executable_statement"));
1287 if (!stmt)
8ae2d595 1288 log_fatal ("no memory for new statement.");
be6be08d
TL
1289 *stmt = base;
1290 return stmt;
1291}
1292
1293/*
1294 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
1295 * else-statement
1296 *
1297 * else-statement :== <null> |
1298 * ELSE LBRACE executable-statements RBRACE |
1299 * ELSE IF if-statement |
1300 * ELSIF if-statement
1301 */
1302
1303struct executable_statement *parse_if_statement (cfile, lose)
1304 FILE *cfile;
1305 int *lose;
1306{
02a015fb 1307 enum dhcp_token token;
be6be08d
TL
1308 char *val;
1309 struct executable_statement *stmt;
1310 struct expression *if_condition;
1311 struct executable_statement *true, *false;
1312
02a015fb
TL
1313 if_condition = (struct expression *)0;
1314 if (!parse_boolean_expression (&if_condition, cfile, lose)) {
be6be08d
TL
1315 if (!*lose)
1316 parse_warn ("boolean expression expected.");
1317 return (struct executable_statement *)0;
1318 }
02a015fb
TL
1319#if defined (DEBUG_EXPRESSION_PARSE)
1320 print_expression ("if condition", if_condition);
1321#endif
be6be08d
TL
1322 token = next_token (&val, cfile);
1323 if (token != LBRACE) {
1324 parse_warn ("left brace expected.");
1325 skip_to_semi (cfile);
1326 *lose = 1;
1327 return (struct executable_statement *)0;
1328 }
1329 true = parse_executable_statements (cfile, lose);
be6be08d 1330 token = next_token (&val, cfile);
efc79acb
TL
1331 if (*lose) {
1332 /* Try to even things up. */
1333 do {
1334 token = next_token (&val, cfile);
1335 } while (token != EOF && token != RBRACE);
1336 return (struct executable_statement *)0;
1337 }
be6be08d
TL
1338 if (token != RBRACE) {
1339 parse_warn ("right brace expected.");
1340 skip_to_semi (cfile);
1341 *lose = 1;
1342 return (struct executable_statement *)0;
1343 }
1344 token = peek_token (&val, cfile);
1345 if (token == ELSE) {
1346 token = next_token (&val, cfile);
1347 token = peek_token (&val, cfile);
1348 if (token == IF) {
1349 token = next_token (&val, cfile);
1350 false = parse_if_statement (cfile, lose);
1351 if (*lose)
1352 return (struct executable_statement *)0;
1353 } else if (token != LBRACE) {
1354 parse_warn ("left brace or if expected.");
1355 skip_to_semi (cfile);
1356 *lose = 1;
1357 return (struct executable_statement *)0;
1358 } else {
1359 token = next_token (&val, cfile);
25541f2f 1360 false = parse_executable_statements (cfile, lose);
be6be08d
TL
1361 if (*lose)
1362 return (struct executable_statement *)0;
25541f2f
TL
1363 token = next_token (&val, cfile);
1364 if (token != RBRACE) {
1365 parse_warn ("right brace expected.");
1366 skip_to_semi (cfile);
1367 *lose = 1;
1368 return (struct executable_statement *)0;
1369 }
be6be08d
TL
1370 }
1371 } else if (token == ELSIF) {
1372 token = next_token (&val, cfile);
1373 false = parse_if_statement (cfile, lose);
1374 if (*lose)
1375 return (struct executable_statement *)0;
1376 } else
1377 false = (struct executable_statement *)0;
1378
1379 stmt = ((struct executable_statement *)
1380 dmalloc (sizeof (struct executable_statement),
1381 "parse_if_statement"));
1382 if (!stmt)
8ae2d595 1383 log_fatal ("no memory for if statement.");
be6be08d
TL
1384 memset (stmt, 0, sizeof *stmt);
1385 stmt -> op = if_statement;
1386 stmt -> data.ie.expr = if_condition;
1387 stmt -> data.ie.true = true;
1388 stmt -> data.ie.false = false;
1389 return stmt;
1390}
1391
1392/*
1393 * boolean_expression :== CHECK STRING |
1394 * NOT boolean-expression |
1395 * data-expression EQUAL data-expression |
1396 * boolean-expression AND boolean-expression |
1397 * boolean-expression OR boolean-expression
02a015fb 1398 * EXISTS OPTION-NAME
be6be08d
TL
1399 */
1400
02a015fb
TL
1401int parse_boolean_expression (expr, cfile, lose)
1402 struct expression **expr;
1403 FILE *cfile;
1404 int *lose;
1405{
1406 /* Parse an expression... */
1407 if (!parse_expression (expr, cfile, lose, context_boolean,
1408 (struct expression **)0, expr_none))
1409 return 0;
1410
1411 if (!is_boolean_expression (*expr)) {
1412 parse_warn ("Expecting a boolean expression.");
1413 *lose = 1;
1414 return 0;
1415 }
1416 return 1;
1417}
1418
1419/*
1420 * data_expression :== SUBSTRING LPAREN data-expression COMMA
1421 * numeric-expression COMMA
1422 * numeric-expression RPAREN |
a82abfc7
TL
1423 * CONCAT LPAREN data-expression COMMA
1424 data-expression RPAREN
02a015fb 1425 * SUFFIX LPAREN data_expression COMMA
a82abfc7 1426 * numeric-expression RPAREN |
02a015fb
TL
1427 * OPTION option_name |
1428 * HARDWARE |
1429 * PACKET LPAREN numeric-expression COMMA
1430 * numeric-expression RPAREN |
1431 * STRING |
1432 * colon_seperated_hex_list
1433 */
1434
1435int parse_data_expression (expr, cfile, lose)
1436 struct expression **expr;
1437 FILE *cfile;
1438 int *lose;
1439{
1440 /* Parse an expression... */
1441 if (!parse_expression (expr, cfile, lose, context_data,
1442 (struct expression **)0, expr_none))
1443 return 0;
1444
1445 if (!is_data_expression (*expr)) {
1446 parse_warn ("Expecting a data expression.");
1447 *lose = 1;
1448 return 0;
1449 }
1450 return 1;
1451}
1452
1453/*
1454 * numeric-expression :== EXTRACT_INT LPAREN data-expression
1455 * COMMA number RPAREN |
1456 * NUMBER
1457 */
1458
1459int parse_numeric_expression (expr, cfile, lose)
1460 struct expression **expr;
1461 FILE *cfile;
1462 int *lose;
1463{
1464 /* Parse an expression... */
1465 if (!parse_expression (expr, cfile, lose, context_numeric,
1466 (struct expression **)0, expr_none))
1467 return 0;
1468
1469 if (!is_numeric_expression (*expr)) {
1470 parse_warn ("Expecting a numeric expression.");
1471 *lose = 1;
1472 return 0;
1473 }
1474 return 1;
1475}
1476
1477/* Parse a subexpression that does not contain a binary operator. */
be6be08d 1478
02a015fb
TL
1479int parse_non_binary (expr, cfile, lose, context)
1480 struct expression **expr;
be6be08d
TL
1481 FILE *cfile;
1482 int *lose;
02a015fb 1483 enum expression_context context;
be6be08d 1484{
02a015fb 1485 enum dhcp_token token;
be6be08d
TL
1486 char *val;
1487 struct collection *col;
02a015fb 1488 struct option *option;
be6be08d
TL
1489
1490 token = peek_token (&val, cfile);
1491
1492 /* Check for unary operators... */
1493 switch (token) {
1494 case CHECK:
1495 token = next_token (&val, cfile);
1496 token = next_token (&val, cfile);
1497 if (token != STRING) {
1498 parse_warn ("string expected.");
1499 skip_to_semi (cfile);
1500 *lose = 1;
02a015fb 1501 return 0;
be6be08d
TL
1502 }
1503 for (col = collections; col; col = col -> next)
1504 if (!strcmp (col -> name, val))
1505 break;
1506 if (!col) {
1507 parse_warn ("unknown collection.");
1508 *lose = 1;
02a015fb 1509 return 0;
be6be08d 1510 }
02a015fb 1511 if (!expression_allocate (expr, "parse_expression: CHECK"))
8ae2d595 1512 log_fatal ("can't allocate expression");
02a015fb
TL
1513 (*expr) -> op = expr_check;
1514 (*expr) -> data.check = col;
1515 break;
be6be08d
TL
1516
1517 case NOT:
1518 token = next_token (&val, cfile);
02a015fb 1519 if (!expression_allocate (expr, "parse_expression: NOT"))
8ae2d595 1520 log_fatal ("can't allocate expression");
02a015fb
TL
1521 (*expr) -> op = expr_not;
1522 if (!parse_non_binary (&(*expr) -> data.not,
1523 cfile, lose, context)) {
be6be08d 1524 if (!*lose) {
02a015fb 1525 parse_warn ("expression expected");
be6be08d
TL
1526 skip_to_semi (cfile);
1527 }
1528 *lose = 1;
02a015fb
TL
1529 expression_dereference (expr, "parse_expression: NOT");
1530 return 0;
be6be08d 1531 }
be6be08d 1532 break;
be6be08d 1533
02a015fb
TL
1534 case EXISTS:
1535 token = next_token (&val, cfile);
1536 if (!expression_allocate (expr, "parse_expression: EXISTS"))
8ae2d595 1537 log_fatal ("can't allocate expression");
02a015fb 1538 (*expr) -> op = expr_exists;
6b4b0ec7 1539 (*expr) -> data.option = parse_option_name (cfile, 0);
02a015fb
TL
1540 if (!(*expr) -> data.option) {
1541 *lose = 1;
1542 expression_dereference (expr,
1543 "parse_expression: EXISTS");
1544 return 0;
be6be08d 1545 }
02a015fb 1546 break;
be6be08d 1547
70330633
TL
1548 case KNOWN:
1549 token = next_token (&val, cfile);
1550 if (!expression_allocate (expr, "parse_expression: EXISTS"))
1551 log_fatal ("can't allocate expression");
1552 (*expr) -> op = expr_known;
1553 break;
1554
be6be08d
TL
1555 case SUBSTRING:
1556 token = next_token (&val, cfile);
02a015fb 1557 if (!expression_allocate (expr, "parse_expression: SUBSTRING"))
8ae2d595 1558 log_fatal ("can't allocate expression");
02a015fb 1559 (*expr) -> op = expr_substring;
be6be08d
TL
1560
1561 token = next_token (&val, cfile);
1562 if (token != LPAREN) {
1563 nolparen:
02a015fb
TL
1564 expression_dereference (expr,
1565 "parse_expression: nolparen");
be6be08d
TL
1566 parse_warn ("left parenthesis expected.");
1567 *lose = 1;
02a015fb 1568 return 0;
be6be08d
TL
1569 }
1570
02a015fb
TL
1571 if (!parse_data_expression (&(*expr) -> data.substring.expr,
1572 cfile, lose)) {
be6be08d 1573 nodata:
02a015fb
TL
1574 expression_dereference (expr,
1575 "parse_expression: nodata");
be6be08d
TL
1576 parse_warn ("expecting data expression.");
1577 skip_to_semi (cfile);
1578 *lose = 1;
02a015fb 1579 return 0;
be6be08d
TL
1580 }
1581
1582 token = next_token (&val, cfile);
1583 if (token != COMMA) {
1584 nocomma:
02a015fb
TL
1585 expression_dereference (expr,
1586 "parse_expression: nocomma1");
be6be08d
TL
1587 parse_warn ("comma expected.");
1588 *lose = 1;
02a015fb
TL
1589
1590 return 0;
be6be08d
TL
1591 }
1592
02a015fb
TL
1593 if (!parse_numeric_expression
1594 (&(*expr) -> data.substring.offset,cfile, lose)) {
be6be08d
TL
1595 nonum:
1596 if (!*lose) {
1597 parse_warn ("expecting numeric expression.");
1598 skip_to_semi (cfile);
1599 *lose = 1;
1600 }
02a015fb
TL
1601 expression_dereference (expr,
1602 "parse_expression: nonum");
1603 return 0;
be6be08d
TL
1604 }
1605
1606 token = next_token (&val, cfile);
1607 if (token != COMMA)
1608 goto nocomma;
1609
02a015fb
TL
1610 if (!parse_numeric_expression
1611 (&(*expr) -> data.substring.len, cfile, lose))
be6be08d
TL
1612 goto nonum;
1613
1614 token = next_token (&val, cfile);
1615 if (token != RPAREN) {
1616 norparen:
1617 parse_warn ("right parenthesis expected.");
1618 *lose = 1;
02a015fb
TL
1619 expression_dereference (expr,
1620 "parse_expression: norparen");
1621 return 0;
be6be08d 1622 }
02a015fb 1623 break;
be6be08d
TL
1624
1625 case SUFFIX:
1626 token = next_token (&val, cfile);
02a015fb 1627 if (!expression_allocate (expr, "parse_expression: SUFFIX"))
8ae2d595 1628 log_fatal ("can't allocate expression");
02a015fb 1629 (*expr) -> op = expr_suffix;
be6be08d
TL
1630
1631 token = next_token (&val, cfile);
1632 if (token != LPAREN)
1633 goto nolparen;
1634
02a015fb
TL
1635 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
1636 cfile, lose))
be6be08d
TL
1637 goto nodata;
1638
1639 token = next_token (&val, cfile);
1640 if (token != COMMA)
1641 goto nocomma;
1642
02a015fb
TL
1643 if (!parse_data_expression (&(*expr) -> data.suffix.len,
1644 cfile, lose))
be6be08d
TL
1645 goto nonum;
1646
1647 token = next_token (&val, cfile);
1648 if (token != RPAREN)
1649 goto norparen;
02a015fb 1650 break;
be6be08d 1651
a82abfc7
TL
1652 case CONCAT:
1653 token = next_token (&val, cfile);
1654 if (!expression_allocate (expr, "parse_expression: CONCAT"))
1655 log_fatal ("can't allocate expression");
1656 (*expr) -> op = expr_concat;
1657
1658 token = next_token (&val, cfile);
1659 if (token != LPAREN)
1660 goto nolparen;
1661
1662 if (!parse_data_expression (&(*expr) -> data.concat [0],
1663 cfile, lose))
1664 goto nodata;
1665
1666 token = next_token (&val, cfile);
1667 if (token != COMMA)
1668 goto nocomma;
1669
1670 if (!parse_data_expression (&(*expr) -> data.concat [1],
1671 cfile, lose))
1672 goto nodata;
1673
1674 token = next_token (&val, cfile);
1675 if (token != RPAREN)
1676 goto norparen;
1677 break;
1678
da38df14
TL
1679 case BINARY_TO_ASCII:
1680 token = next_token (&val, cfile);
1681 if (!expression_allocate (expr, "parse_expression: B2A"))
1682 log_fatal ("can't allocate expression");
eb42f00e 1683 (*expr) -> op = expr_binary_to_ascii;
da38df14
TL
1684
1685 token = next_token (&val, cfile);
1686 if (token != LPAREN)
1687 goto nolparen;
1688
1689 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
1690 cfile, lose))
1691 goto nodata;
1692
1693 token = next_token (&val, cfile);
1694 if (token != COMMA)
1695 goto nocomma;
1696
1697 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
1698 cfile, lose))
1699 goto nodata;
1700
1701 token = next_token (&val, cfile);
1702 if (token != COMMA)
1703 goto nocomma;
1704
1705 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
1706 cfile, lose))
1707 goto nodata;
1708
1709 token = next_token (&val, cfile);
1710 if (token != COMMA)
1711 goto nocomma;
1712
1713 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
1714 cfile, lose))
1715 goto nodata;
1716
1717 token = next_token (&val, cfile);
1718 if (token != RPAREN)
1719 goto norparen;
1720 break;
1721
1722 case REVERSE:
1723 token = next_token (&val, cfile);
1724 if (!expression_allocate (expr, "parse_expression: REVERSE"))
1725 log_fatal ("can't allocate expression");
eb42f00e 1726 (*expr) -> op = expr_reverse;
da38df14
TL
1727
1728 token = next_token (&val, cfile);
1729 if (token != LPAREN)
1730 goto nolparen;
1731
1732 if (!(parse_numeric_expression
1733 (&(*expr) -> data.reverse.width, cfile, lose)))
1734 goto nodata;
1735
1736 token = next_token (&val, cfile);
1737 if (token != COMMA)
1738 goto nocomma;
1739
1740 if (!(parse_data_expression
1741 (&(*expr) -> data.reverse.buffer, cfile, lose)))
1742 goto nodata;
1743
1744 token = next_token (&val, cfile);
1745 if (token != RPAREN)
1746 goto norparen;
1747 break;
1748
be6be08d
TL
1749 case OPTION:
1750 token = next_token (&val, cfile);
02a015fb 1751 if (!expression_allocate (expr, "parse_expression: OPTION"))
8ae2d595 1752 log_fatal ("can't allocate expression");
02a015fb 1753 (*expr) -> op = expr_option;
6b4b0ec7 1754 (*expr) -> data.option = parse_option_name (cfile, 0);
02a015fb 1755 if (!(*expr) -> data.option) {
be6be08d 1756 *lose = 1;
02a015fb
TL
1757 expression_dereference (expr,
1758 "parse_expression: OPTION");
1759 return 0;
be6be08d 1760 }
02a015fb 1761 break;
be6be08d
TL
1762
1763 case HARDWARE:
1764 token = next_token (&val, cfile);
02a015fb 1765 if (!expression_allocate (expr, "parse_expression: HARDWARE"))
8ae2d595 1766 log_fatal ("can't allocate expression");
02a015fb
TL
1767 (*expr) -> op = expr_hardware;
1768 break;
be6be08d 1769
da38df14
TL
1770 case LEASED_ADDRESS:
1771 token = next_token (&val, cfile);
1772 if (!expression_allocate (expr,
1773 "parse_expression: LEASED_ADDRESS"))
1774 log_fatal ("can't allocate expression");
1775 (*expr) -> op = expr_leased_address;
1776 break;
1777
be6be08d
TL
1778 case PACKET:
1779 token = next_token (&val, cfile);
02a015fb 1780 if (!expression_allocate (expr, "parse_expression: PACKET"))
8ae2d595 1781 log_fatal ("can't allocate expression");
02a015fb 1782 (*expr) -> op = expr_packet;
be6be08d
TL
1783
1784 token = next_token (&val, cfile);
1785 if (token != LPAREN)
1786 goto nolparen;
1787
02a015fb
TL
1788 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
1789 cfile, lose))
be6be08d
TL
1790 goto nonum;
1791
1792 token = next_token (&val, cfile);
1793 if (token != COMMA)
1794 goto nocomma;
1795
02a015fb
TL
1796 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
1797 cfile, lose))
be6be08d
TL
1798 goto nonum;
1799
1800 token = next_token (&val, cfile);
1801 if (token != RPAREN)
1802 goto norparen;
02a015fb 1803 break;
be6be08d
TL
1804
1805 case STRING:
1806 token = next_token (&val, cfile);
c5b0f529
TL
1807 if (!make_const_data (expr, (unsigned char *)val,
1808 strlen (val), 1, 1))
8ae2d595 1809 log_fatal ("can't make constant string expression.");
02a015fb 1810 break;
be6be08d 1811
be6be08d
TL
1812 case EXTRACT_INT:
1813 token = next_token (&val, cfile);
be6be08d
TL
1814 token = next_token (&val, cfile);
1815 if (token != LPAREN) {
1816 parse_warn ("left parenthesis expected.");
1817 *lose = 1;
02a015fb 1818 return 0;
be6be08d
TL
1819 }
1820
02a015fb
TL
1821 if (!expression_allocate (expr,
1822 "parse_expression: EXTRACT_INT"))
8ae2d595 1823 log_fatal ("can't allocate expression");
02a015fb
TL
1824
1825 if (!parse_data_expression (&(*expr) -> data.extract_int,
1826 cfile, lose)) {
be6be08d
TL
1827 parse_warn ("expecting data expression.");
1828 skip_to_semi (cfile);
1829 *lose = 1;
02a015fb
TL
1830 expression_dereference
1831 (expr, "parse_expression: EXTRACT_INT");
1832 return 0;
be6be08d
TL
1833 }
1834
1835 token = next_token (&val, cfile);
1836 if (token != COMMA) {
1837 parse_warn ("comma expected.");
1838 *lose = 1;
02a015fb 1839 return 0;
be6be08d
TL
1840 }
1841
1842 token = next_token (&val, cfile);
1843 if (token != NUMBER) {
1844 parse_warn ("number expected.");
1845 *lose = 1;
02a015fb 1846 return 0;
be6be08d 1847 }
be6be08d
TL
1848 switch (atoi (val)) {
1849 case 8:
02a015fb 1850 (*expr) -> op = expr_extract_int8;
be6be08d
TL
1851 break;
1852
1853 case 16:
02a015fb 1854 (*expr) -> op = expr_extract_int16;
be6be08d
TL
1855 break;
1856
1857 case 32:
02a015fb 1858 (*expr) -> op = expr_extract_int32;
be6be08d
TL
1859 break;
1860
1861 default:
1862 parse_warn ("unsupported integer size %d", atoi (val));
1863 *lose = 1;
1864 skip_to_semi (cfile);
02a015fb
TL
1865 expression_dereference
1866 (expr, "parse_expression: EXTRACT_INT");
1867 return 0;
be6be08d
TL
1868 }
1869
1870 token = next_token (&val, cfile);
1871 if (token != RPAREN) {
1872 parse_warn ("right parenthesis expected.");
1873 *lose = 1;
02a015fb 1874 return 0;
be6be08d 1875 }
02a015fb 1876 break;
be6be08d 1877
20c4e94d
TL
1878 case ENCODE_INT:
1879 token = next_token (&val, cfile);
1880 token = next_token (&val, cfile);
1881 if (token != LPAREN) {
1882 parse_warn ("left parenthesis expected.");
1883 *lose = 1;
1884 return 0;
1885 }
1886
1887 if (!expression_allocate (expr,
1888 "parse_expression: ENCODE_INT"))
1889 log_fatal ("can't allocate expression");
1890
1891 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
1892 cfile, lose)) {
1893 parse_warn ("expecting numeric expression.");
1894 skip_to_semi (cfile);
1895 *lose = 1;
1896 expression_dereference
1897 (expr, "parse_expression: ENCODE_INT");
1898 return 0;
1899 }
1900
1901 token = next_token (&val, cfile);
1902 if (token != COMMA) {
1903 parse_warn ("comma expected.");
1904 *lose = 1;
1905 return 0;
1906 }
1907
1908 token = next_token (&val, cfile);
1909 if (token != NUMBER) {
1910 parse_warn ("number expected.");
1911 *lose = 1;
1912 return 0;
1913 }
1914 switch (atoi (val)) {
1915 case 8:
1916 (*expr) -> op = expr_encode_int8;
1917 break;
1918
1919 case 16:
1920 (*expr) -> op = expr_encode_int16;
1921 break;
1922
1923 case 32:
1924 (*expr) -> op = expr_encode_int32;
1925 break;
1926
1927 default:
1928 parse_warn ("unsupported integer size %d", atoi (val));
1929 *lose = 1;
1930 skip_to_semi (cfile);
1931 expression_dereference
1932 (expr, "parse_expression: ENCODE_INT");
1933 return 0;
1934 }
1935
1936 token = next_token (&val, cfile);
1937 if (token != RPAREN) {
1938 parse_warn ("right parenthesis expected.");
1939 *lose = 1;
1940 return 0;
1941 }
1942 break;
1943
be6be08d 1944 case NUMBER:
02a015fb
TL
1945 /* If we're in a numeric context, this should just be a
1946 number, by itself. */
1947 if (context == context_numeric) {
1948 next_token (&val, cfile); /* Eat the number. */
be19167d
TL
1949 if (!expression_allocate (expr,
1950 "parse_expression: NUMBER"))
1951 log_fatal ("can't allocate expression");
02a015fb
TL
1952 (*expr) -> op = expr_const_int;
1953 (*expr) -> data.const_int = atoi (val);
1954 break;
1955 }
be6be08d 1956
02a015fb 1957 case NUMBER_OR_NAME:
be19167d
TL
1958 if (!expression_allocate (expr,
1959 "parse_expression: NUMBER_OR_NAME"))
1960 log_fatal ("can't allocate expression");
1961
02a015fb
TL
1962 (*expr) -> op = expr_const_data;
1963 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
1964 expression_dereference (expr,
1965 "parse_expression: cshl");
1966 return 0;
1967 }
1968 break;
1969
1970 /* Not a valid start to an expression... */
be6be08d 1971 default:
02a015fb 1972 return 0;
be6be08d 1973 }
02a015fb 1974 return 1;
be6be08d
TL
1975}
1976
02a015fb
TL
1977/* Parse an expression. */
1978
1979int parse_expression (expr, cfile, lose, context, plhs, binop)
1980 struct expression **expr;
1981 FILE *cfile;
1982 int *lose;
1983 enum expression_context context;
1984 struct expression **plhs;
1985 enum expr_op binop;
1986{
1987 enum dhcp_token token;
1988 char *val;
1989 struct expression *rhs = (struct expression *)0, *tmp;
1990 struct expression *lhs;
1991 enum expr_op next_op;
1992
1993 /* Consume the left hand side we were passed. */
1994 if (plhs) {
1995 lhs = *plhs;
1996 *plhs = (struct expression *)0;
1997 } else
1998 lhs = (struct expression *)0;
1999
2000 new_rhs:
2001 if (!parse_non_binary (&rhs, cfile, lose, context)) {
2002 /* If we already have a left-hand side, then it's not
2003 okay for there not to be a right-hand side here, so
2004 we need to flag it as an error. */
2005 if (lhs) {
2006 if (!*lose) {
2007 parse_warn ("expecting right-hand side.");
2008 *lose = 1;
2009 skip_to_semi (cfile);
2010 }
2011 expression_dereference (&lhs, "parse_expression");
2012 }
2013 return 0;
2014 }
2015
2016 /* At this point, rhs contains either an entire subexpression,
2017 or at least a left-hand-side. If we do not see a binary token
2018 as the next token, we're done with the expression. */
2019
2020 token = peek_token (&val, cfile);
2021 switch (token) {
2022 case EQUAL:
2023 next_op = expr_equal;
2024 break;
2025
2026 case AND:
2027 next_op = expr_and;
2028 break;
2029
2030 case OR:
2031 next_op = expr_or;
2032 break;
2033
2034 default:
2035 next_op = expr_none;
2036 }
2037
2038 /* If we have no lhs yet, we just parsed it. */
2039 if (!lhs) {
2040 /* If there was no operator following what we just parsed,
2041 then we're done - return it. */
2042 if (next_op == expr_none) {
2043 *expr = rhs;
2044 return 1;
2045 }
2046 lhs = rhs;
2047 rhs = (struct expression *)0;
2048 binop = next_op;
2049 next_token (&val, cfile); /* Consume the operator. */
2050 goto new_rhs;
2051 }
2052
2053 /* Now, if we didn't find a binary operator, we're done parsing
2054 this subexpression, so combine it with the preceding binary
2055 operator and return the result. */
2056 if (next_op == expr_none) {
2057 if (!expression_allocate (expr,
2058 "parse_expression: COMBINE"))
8ae2d595 2059 log_fatal ("Can't allocate expression!");
02a015fb
TL
2060
2061 (*expr) -> op = binop;
2062 /* All the binary operators' data union members
2063 are the same, so we'll cheat and use the member
2064 for the equals operator. */
2065 (*expr) -> data.equal [0] = lhs;
2066 (*expr) -> data.equal [1] = rhs;
2067 return 1;
2068 }
2069
2070 /* Eat the operator token - we now know it was a binary operator... */
2071 token = next_token (&val, cfile);
2072
2073 /* If the binary operator we saw previously has a lower precedence
2074 than the next operator, then the rhs we just parsed for that
2075 operator is actually the lhs of the operator with the higher
2076 precedence - to get the real rhs, we need to recurse on the
2077 new operator. */
2078 if (binop != expr_none &&
2079 op_precedence (binop, next_op) < 0) {
2080 tmp = rhs;
2081 rhs = (struct expression *)0;
2082 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
2083 &tmp, next_op)) {
2084 if (!*lose) {
2085 parse_warn ("expecting a subexpression");
2086 *lose = 1;
2087 }
2088 return 0;
2089 }
2090 next_op = expr_none;
2091 }
2092
2093 /* Now combine the LHS and the RHS using binop. */
2094 tmp = (struct expression *)0;
2095 if (!expression_allocate (&tmp, "parse_expression: COMBINE2"))
8ae2d595 2096 log_fatal ("No memory for equal precedence combination.");
02a015fb
TL
2097
2098 /* Store the LHS and RHS. */
2099 tmp -> data.equal [0] = lhs;
2100 tmp -> data.equal [1] = rhs;
2101 tmp -> op = binop;
2102
2103 lhs = tmp;
2104 tmp = (struct expression *)0;
2105 rhs = (struct expression *)0;
2106
2107 /* Recursions don't return until we have parsed the end of the
2108 expression, so if we recursed earlier, we can now return what
2109 we got. */
2110 if (next_op == expr_none) {
2111 *expr = lhs;
2112 return 1;
2113 }
2114
2115 binop = next_op;
2116 goto new_rhs;
2117}
2118
be6be08d
TL
2119/* option-statement :== identifier DOT identifier <syntax> SEMI
2120 | identifier <syntax> SEMI
2121
2122 Option syntax is handled specially through format strings, so it
2123 would be painful to come up with BNF for it. However, it always
2124 starts as above and ends in a SEMI. */
2125
2126struct executable_statement *parse_option_statement (cfile, lookups,
2127 option, op)
2128 FILE *cfile;
2129 int lookups;
2130 struct option *option;
2131 enum statement_op op;
2132{
2133 char *val;
02a015fb 2134 enum dhcp_token token;
be6be08d
TL
2135 char *fmt;
2136 struct expression *expr = (struct expression *)0;
02a015fb 2137 struct expression *tmp;
be6be08d
TL
2138 int lose;
2139 struct executable_statement *stmt;
02a015fb 2140 int ftt = 1;
be6be08d
TL
2141
2142 token = peek_token (&val, cfile);
2143 if (token == SEMI) {
2144 /* Eat the semicolon... */
2145 token = next_token (&val, cfile);
be6be08d
TL
2146 goto done;
2147 }
2148
a82abfc7
TL
2149 if (token == EQUAL) {
2150 /* Eat the equals sign. */
2151 token = next_token (&val, cfile);
2152
2153 /* Parse a data expression and use its value for the data. */
2154 if (!parse_data_expression (&expr, cfile, &lose)) {
2155 /* In this context, we must have an executable
2156 statement, so if we found something else, it's
2157 still an error. */
2158 if (!lose) {
2159 parse_warn ("expecting a data expression.");
2160 skip_to_semi (cfile);
2161 }
2162 return (struct executable_statement *)0;
2163 }
2164
2165 /* We got a valid expression, so use it. */
2166 goto done;
2167 }
2168
be6be08d
TL
2169 /* Parse the option data... */
2170 do {
2171 /* Set a flag if this is an array of a simple type (i.e.,
2172 not an array of pairs of IP addresses, or something
2173 like that. */
2174 int uniform = option -> format [1] == 'A';
2175
2176 for (fmt = option -> format; *fmt; fmt++) {
2177 if (*fmt == 'A')
2178 break;
02a015fb 2179 tmp = expr;
44aa67f6 2180 expr = (struct expression *)0;
02a015fb
TL
2181 if (!parse_option_token (&expr, cfile, fmt,
2182 tmp, uniform, lookups)) {
2183 expression_dereference
2184 (&tmp, "parse_option_statement");
2185 return (struct executable_statement *)0;
2186 }
2187 if (tmp)
2188 expression_dereference
2189 (&tmp, "parse_option_statement");
be6be08d
TL
2190 }
2191 if (*fmt == 'A') {
2192 token = peek_token (&val, cfile);
2193 if (token == COMMA) {
2194 token = next_token (&val, cfile);
2195 continue;
2196 }
2197 break;
2198 }
2199 } while (*fmt == 'A');
2200
2201 done:
25541f2f 2202 if (!parse_semi (cfile))
be6be08d 2203 return (struct executable_statement *)0;
be6be08d
TL
2204 stmt = ((struct executable_statement *)
2205 dmalloc (sizeof *stmt, "parse_option_statement"));
02a015fb 2206 memset (stmt, 0, sizeof *stmt);
be6be08d 2207 stmt -> op = op;
02a015fb
TL
2208 if (expr && !option_cache (&stmt -> data.option,
2209 (struct data_string *)0, expr, option))
52c9d530 2210 log_fatal ("no memory for option cache");
be6be08d
TL
2211 return stmt;
2212}
2213
02a015fb
TL
2214int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
2215 struct expression **rv;
be6be08d
TL
2216 FILE *cfile;
2217 char *fmt;
2218 struct expression *expr;
2219 int uniform;
2220 int lookups;
2221{
2222 char *val;
02a015fb
TL
2223 enum dhcp_token token;
2224 struct expression *t = (struct expression *)0;
be6be08d
TL
2225 unsigned char buf [4];
2226 int len;
2227 unsigned char *ob;
2228 struct iaddr addr;
2229
2230 switch (*fmt) {
52c9d530
TL
2231 case 'U':
2232 token = next_token (&val, cfile);
2233 if (!is_identifier (token)) {
2234 parse_warn ("expecting identifier.");
2235 skip_to_semi (cfile);
2236 return 0;
2237 }
2238 if (!make_const_data (&t, (unsigned char *)val,
2239 strlen (val), 1, 1))
2240 log_fatal ("No memory for %s", val);
2241 break;
2242
be6be08d
TL
2243 case 'X':
2244 token = peek_token (&val, cfile);
2245 if (token == NUMBER_OR_NAME || token == NUMBER) {
02a015fb
TL
2246 if (!expression_allocate (&t, "parse_option_token"))
2247 return 0;
2248 if (!parse_cshl (&t -> data.const_data, cfile))
2249 return 0;
efc79acb 2250 t -> op = expr_const_data;
be6be08d
TL
2251 } else if (token == STRING) {
2252 token = next_token (&val, cfile);
52c9d530 2253 if (!make_const_data (&t, (unsigned char *)val,
02a015fb 2254 strlen (val), 1, 1))
52c9d530 2255 log_fatal ("No memory for \"%s\"", val);
be6be08d
TL
2256 } else {
2257 parse_warn ("expecting string %s.",
2258 "or hexadecimal data");
2259 skip_to_semi (cfile);
02a015fb 2260 return 0;
be6be08d
TL
2261 }
2262 break;
2263
2264 case 't': /* Text string... */
2265 token = next_token (&val, cfile);
2266 if (token != STRING && !is_identifier (token)) {
2267 parse_warn ("expecting string.");
2268 if (token != SEMI)
2269 skip_to_semi (cfile);
02a015fb 2270 return 0;
be6be08d 2271 }
02a015fb
TL
2272 if (!make_const_data (&t, (unsigned char *)val,
2273 strlen (val), 1, 1))
8ae2d595 2274 log_fatal ("No memory for concatenation");
be6be08d
TL
2275 break;
2276
2277 case 'I': /* IP address or hostname. */
02a015fb
TL
2278 if (lookups) {
2279 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
2280 return 0;
2281 } else {
be6be08d 2282 if (!parse_ip_addr (cfile, &addr))
02a015fb
TL
2283 return 0;
2284 if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1))
2285 return 0;
be6be08d 2286 }
be6be08d
TL
2287 break;
2288
2289 case 'L': /* Unsigned 32-bit integer... */
2290 case 'l': /* Signed 32-bit integer... */
2291 token = next_token (&val, cfile);
2292 if (token != NUMBER) {
2293 need_number:
2294 parse_warn ("expecting number.");
2295 if (token != SEMI)
2296 skip_to_semi (cfile);
02a015fb 2297 return 0;
be6be08d
TL
2298 }
2299 convert_num (buf, val, 0, 32);
02a015fb
TL
2300 if (!make_const_data (&t, buf, 4, 0, 1))
2301 return 0;
be6be08d 2302 break;
02a015fb 2303
be6be08d
TL
2304 case 's': /* Signed 16-bit integer. */
2305 case 'S': /* Unsigned 16-bit integer. */
2306 token = next_token (&val, cfile);
2307 if (token != NUMBER)
2308 goto need_number;
2309 convert_num (buf, val, 0, 16);
02a015fb
TL
2310 if (!make_const_data (&t, buf, 2, 0, 1))
2311 return 0;
be6be08d 2312 break;
02a015fb 2313
be6be08d
TL
2314 case 'b': /* Signed 8-bit integer. */
2315 case 'B': /* Unsigned 8-bit integer. */
2316 token = next_token (&val, cfile);
2317 if (token != NUMBER)
2318 goto need_number;
2319 convert_num (buf, val, 0, 8);
02a015fb
TL
2320 if (!make_const_data (&t, buf, 1, 0, 1))
2321 return 0;
be6be08d 2322 break;
02a015fb 2323
be6be08d
TL
2324 case 'f': /* Boolean flag. */
2325 token = next_token (&val, cfile);
2326 if (!is_identifier (token)) {
2327 parse_warn ("expecting identifier.");
2328 bad_flag:
2329 if (token != SEMI)
2330 skip_to_semi (cfile);
02a015fb 2331 return 0;
be6be08d
TL
2332 }
2333 if (!strcasecmp (val, "true")
2334 || !strcasecmp (val, "on"))
2335 buf [0] = 1;
2336 else if (!strcasecmp (val, "false")
2337 || !strcasecmp (val, "off"))
2338 buf [0] = 0;
2339 else {
2340 parse_warn ("expecting boolean.");
2341 goto bad_flag;
2342 }
02a015fb
TL
2343 if (!make_const_data (&t, buf, 1, 0, 1))
2344 return 0;
be6be08d 2345 break;
02a015fb 2346
be6be08d 2347 default:
8ae2d595 2348 log_error ("Bad format %c in parse_option_param.",
be6be08d
TL
2349 *fmt);
2350 skip_to_semi (cfile);
02a015fb 2351 return 0;
be6be08d 2352 }
02a015fb
TL
2353 if (expr) {
2354 if (!make_concat (rv, expr, t))
2355 return 0;
2356 expression_dereference (&t, "parse_option_token");
2357 } else
2358 *rv = t;
2359 return 1;
be6be08d 2360}
74f45f96 2361
b1013db7
TL
2362/* allow-deny-keyword :== BOOTP
2363 | BOOTING
2364 | DYNAMIC_BOOTP
2365 | UNKNOWN_CLIENTS */
2366
2367int parse_allow_deny (oc, cfile, flag)
2368 struct option_cache **oc;
2369 FILE *cfile;
2370 int flag;
2371{
2372 enum dhcp_token token;
2373 char *val;
2374 unsigned char rf = flag;
2375 struct expression *data = (struct expression *)0;
2376 int status;
2377
2378 if (!make_const_data (&data, &rf, 1, 0, 1))
2379 return 0;
2380
2381 token = next_token (&val, cfile);
2382 switch (token) {
2383 case BOOTP:
2384 status = option_cache (oc, (struct data_string *)0, data,
2385 &server_options [SV_ALLOW_BOOTP]);
2386 break;
2387
2388 case BOOTING:
2389 status = option_cache (oc, (struct data_string *)0, data,
2390 &server_options [SV_ALLOW_BOOTING]);
2391 break;
2392
2393 case DYNAMIC_BOOTP:
2394 status = option_cache (oc, (struct data_string *)0, data,
2395 &server_options [SV_DYNAMIC_BOOTP]);
2396 break;
2397
2398 case UNKNOWN_CLIENTS:
2399 status = (option_cache
2400 (oc, (struct data_string *)0, data,
2401 &server_options [SV_BOOT_UNKNOWN_CLIENTS]));
2402 break;
2403
2404 default:
2405 parse_warn ("expecting allow/deny key");
2406 skip_to_semi (cfile);
2407 return 0;
2408 }
2409 parse_semi (cfile);
2410 return status;
2411}
2412
74f45f96
TL
2413int parse_auth_key (key_id, cfile)
2414 struct data_string *key_id;
2415 FILE *cfile;
2416{
2417 struct data_string key_data;
2418 char *val;
2419 enum dhcp_token token;
2420 struct auth_key *key, *old_key = (struct auth_key *)0;
2421
2422 memset (&key_data, 0, sizeof key_data);
2423
2424 if (!parse_cshl (key_id, cfile))
2425 return 0;
2426
2427 key = auth_key_lookup (key_id);
2428
2429 token = peek_token (&val, cfile);
2430 if (token == SEMI) {
2431 if (!key)
2432 parse_warn ("reference to undefined key %s",
2433 print_hex_1 (key_id -> len,
2434 key_id -> data,
2435 key_id -> len));
2436 data_string_forget (key_id, "parse_auth_key");
2437 } else {
2438 if (!parse_cshl (&key_data, cfile))
2439 return 0;
2440 if (key) {
2441 parse_warn ("redefinition of key %s",
2442 print_hex_1 (key_id -> len,
2443 key_id -> data,
2444 key_id -> len));
2445 old_key = key;
2446 }
2447 key = new_auth_key (key_data.len, "parse_auth_key");
2448 if (!key)
2449 log_fatal ("No memory for key %s",
2450 print_hex_1 (key_id -> len,
2451 key_id -> data,
2452 key_id -> len));
2453 key -> length = key_data.len;
2454 memcpy (key -> data, key_data.data, key_data.len);
2455 enter_auth_key (key_id, key);
2456 data_string_forget (&key_data, "parse_auth_key");
2457 }
2458
2459 parse_semi (cfile);
2460 return key_id -> len ? 1 : 0;
2461}