]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/parse.c
Update license.
[thirdparty/dhcp.git] / common / parse.c
1 /* parse.c
2
3 Common parser code for dhcpd and dhclient. */
4
5 /*
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:
12 *
13 * http://www.isc.org/isc-license-1.0.html.
14 *
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.
18 *
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
21 */
22
23 #ifndef lint
24 static char copyright[] =
25 "$Id: parse.c,v 1.16 1999/03/16 05:50:36 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
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
45 void skip_to_semi (cfile)
46 FILE *cfile;
47 {
48 skip_to_rbrace (cfile, 0);
49 }
50
51 void skip_to_rbrace (cfile, brace_count)
52 FILE *cfile;
53 int brace_count;
54 {
55 enum dhcp_token token;
56 char *val;
57
58 do {
59 token = peek_token (&val, cfile);
60 if (token == RBRACE) {
61 token = next_token (&val, cfile);
62 if (brace_count) {
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;
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;
78 }
79 token = next_token (&val, cfile);
80 } while (token != EOF);
81 }
82
83 int parse_semi (cfile)
84 FILE *cfile;
85 {
86 enum dhcp_token token;
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
100 char *parse_string (cfile)
101 FILE *cfile;
102 {
103 char *val;
104 enum dhcp_token token;
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)
115 log_fatal ("no memory for string %s.", val);
116 strcpy (s, val);
117
118 if (!parse_semi (cfile))
119 return (char *)0;
120 return s;
121 }
122
123 /*
124 * hostname :== IDENTIFIER
125 * | IDENTIFIER DOT
126 * | hostname DOT IDENTIFIER
127 */
128
129 char *parse_host_name (cfile)
130 FILE *cfile;
131 {
132 char *val;
133 enum dhcp_token token;
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. */
142 token = peek_token (&val, cfile);
143 if (!is_identifier (token) && token != NUMBER)
144 break;
145 token = next_token (&val, cfile);
146
147 /* Store this identifier... */
148 if (!(s = (char *)malloc (strlen (val) + 1)))
149 log_fatal ("can't allocate temp space for hostname.");
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)))
162 log_fatal ("can't allocate space for hostname.");
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
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
187 int parse_ip_addr_or_hostname (expr, cfile, uniform)
188 struct expression **expr;
189 FILE *cfile;
190 int uniform;
191 {
192 char *val;
193 enum dhcp_token token;
194 unsigned char addr [4];
195 int len = sizeof addr;
196 char *name;
197 struct expression *x = (struct expression *)0;
198
199 token = peek_token (&val, cfile);
200 if (is_identifier (token)) {
201 name = parse_host_name (cfile);
202 if (!name)
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 }
213 } else if (token == NUMBER) {
214 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
215 return 0;
216 return make_const_data (expr, addr, len, 0, 1);
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);
224 return 0;
225 }
226
227 return 1;
228 }
229
230 /*
231 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
232 */
233
234 int parse_ip_addr (cfile, addr)
235 FILE *cfile;
236 struct iaddr *addr;
237 {
238 char *val;
239 enum dhcp_token token;
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
248 /*
249 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
250 * hardware-type :== ETHERNET | TOKEN_RING
251 */
252
253 void parse_hardware_param (cfile, hardware)
254 FILE *cfile;
255 struct hardware *hardware;
256 {
257 char *val;
258 enum dhcp_token token;
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;
270 case FDDI:
271 hardware -> htype = HTYPE_FDDI;
272 break;
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);
298 if (hlen < sizeof hardware -> haddr)
299 memset (&hardware -> haddr [hlen], 0,
300 (sizeof hardware -> haddr) - hlen);
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
313 void parse_lease_time (cfile, timep)
314 FILE *cfile;
315 TIME *timep;
316 {
317 char *val;
318 enum dhcp_token token;
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
340 unsigned 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;
350 enum dhcp_token token;
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)
358 log_fatal ("can't allocate space for numeric aggregate");
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)
399 log_fatal ("no temp space for number.");
400 strcpy ((char *)t, val);
401 c = cons ((caddr_t)t, c);
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)
409 log_fatal ("can't allocate space for numeric aggregate.");
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
425 void 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 {
469 log_error ("Bogus number: %s.", str);
470 break;
471 }
472 if (tval >= base) {
473 log_error ("Bogus number: %s: digit %d not in base %d\n",
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:
487 log_error ("value %s%o exceeds max (%d) for precision.",
488 negative ? "-" : "", val, max);
489 break;
490 case 16:
491 log_error ("value %s%x exceeds max (%d) for precision.",
492 negative ? "-" : "", val, max);
493 break;
494 default:
495 log_error ("value %s%u exceeds max (%d) for precision.",
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:
513 log_error ("Unexpected integer size: %d\n", size);
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:
528 log_error ("Unexpected integer size: %d\n", size);
529 break;
530 }
531 }
532 }
533
534 /*
535 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
536 * NUMBER COLON NUMBER COLON NUMBER SEMI
537 *
538 * Dates are always in GMT; first number is day of week; next is
539 * year/month/day; next is hours:minutes:seconds on a 24-hour
540 * clock.
541 */
542
543 TIME parse_date (cfile)
544 FILE *cfile;
545 {
546 struct tm tm;
547 int guess;
548 char *val;
549 enum dhcp_token token;
550 static int months [11] = { 31, 59, 90, 120, 151, 181,
551 212, 243, 273, 304, 334 };
552
553 /* Day of week... */
554 token = next_token (&val, cfile);
555 if (token != NUMBER) {
556 parse_warn ("numeric day of week expected.");
557 if (token != SEMI)
558 skip_to_semi (cfile);
559 return (TIME)0;
560 }
561 tm.tm_wday = atoi (val);
562
563 /* Year... */
564 token = next_token (&val, cfile);
565 if (token != NUMBER) {
566 parse_warn ("numeric year expected.");
567 if (token != SEMI)
568 skip_to_semi (cfile);
569 return (TIME)0;
570 }
571
572 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
573 somebody invents a time machine, I think we can safely disregard
574 it. This actually works around a stupid Y2K bug that was present
575 in a very early beta release of dhcpd. */
576 tm.tm_year = atoi (val);
577 if (tm.tm_year > 1900)
578 tm.tm_year -= 1900;
579
580 /* Slash seperating year from month... */
581 token = next_token (&val, cfile);
582 if (token != SLASH) {
583 parse_warn ("expected slash seperating year from month.");
584 if (token != SEMI)
585 skip_to_semi (cfile);
586 return (TIME)0;
587 }
588
589 /* Month... */
590 token = next_token (&val, cfile);
591 if (token != NUMBER) {
592 parse_warn ("numeric month expected.");
593 if (token != SEMI)
594 skip_to_semi (cfile);
595 return (TIME)0;
596 }
597 tm.tm_mon = atoi (val) - 1;
598
599 /* Slash seperating month from day... */
600 token = next_token (&val, cfile);
601 if (token != SLASH) {
602 parse_warn ("expected slash seperating month from day.");
603 if (token != SEMI)
604 skip_to_semi (cfile);
605 return (TIME)0;
606 }
607
608 /* Month... */
609 token = next_token (&val, cfile);
610 if (token != NUMBER) {
611 parse_warn ("numeric day of month expected.");
612 if (token != SEMI)
613 skip_to_semi (cfile);
614 return (TIME)0;
615 }
616 tm.tm_mday = atoi (val);
617
618 /* Hour... */
619 token = next_token (&val, cfile);
620 if (token != NUMBER) {
621 parse_warn ("numeric hour expected.");
622 if (token != SEMI)
623 skip_to_semi (cfile);
624 return (TIME)0;
625 }
626 tm.tm_hour = atoi (val);
627
628 /* Colon seperating hour from minute... */
629 token = next_token (&val, cfile);
630 if (token != COLON) {
631 parse_warn ("expected colon seperating hour from minute.");
632 if (token != SEMI)
633 skip_to_semi (cfile);
634 return (TIME)0;
635 }
636
637 /* Minute... */
638 token = next_token (&val, cfile);
639 if (token != NUMBER) {
640 parse_warn ("numeric minute expected.");
641 if (token != SEMI)
642 skip_to_semi (cfile);
643 return (TIME)0;
644 }
645 tm.tm_min = atoi (val);
646
647 /* Colon seperating minute from second... */
648 token = next_token (&val, cfile);
649 if (token != COLON) {
650 parse_warn ("expected colon seperating hour from minute.");
651 if (token != SEMI)
652 skip_to_semi (cfile);
653 return (TIME)0;
654 }
655
656 /* Minute... */
657 token = next_token (&val, cfile);
658 if (token != NUMBER) {
659 parse_warn ("numeric minute expected.");
660 if (token != SEMI)
661 skip_to_semi (cfile);
662 return (TIME)0;
663 }
664 tm.tm_sec = atoi (val);
665 tm.tm_isdst = 0;
666
667 /* XXX */ /* We assume that mktime does not use tm_yday. */
668 tm.tm_yday = 0;
669
670 /* Make sure the date ends in a semicolon... */
671 if (!parse_semi (cfile))
672 return 0;
673
674 /* Guess the time value... */
675 guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */
676 (tm.tm_year - 69) / 4 + /* Leap days since '70 */
677 (tm.tm_mon /* Days in months this year */
678 ? months [tm.tm_mon - 1]
679 : 0) +
680 (tm.tm_mon > 1 && /* Leap day this year */
681 !((tm.tm_year - 72) & 3)) +
682 tm.tm_mday - 1) * 24) + /* Day of month */
683 tm.tm_hour) * 60) +
684 tm.tm_min) * 60) + tm.tm_sec;
685
686 /* This guess could be wrong because of leap seconds or other
687 weirdness we don't know about that the system does. For
688 now, we're just going to accept the guess, but at some point
689 it might be nice to do a successive approximation here to
690 get an exact value. Even if the error is small, if the
691 server is restarted frequently (and thus the lease database
692 is reread), the error could accumulate into something
693 significant. */
694
695 return guess;
696 }
697
698 /*
699 * option-name :== IDENTIFIER |
700 IDENTIFIER . IDENTIFIER
701 */
702
703 struct option *parse_option_name (cfile)
704 FILE *cfile;
705 {
706 char *val;
707 enum dhcp_token token;
708 char *vendor;
709 struct universe *universe;
710 struct option *option;
711
712 token = next_token (&val, cfile);
713 if (!is_identifier (token)) {
714 parse_warn ("expecting identifier after option keyword.");
715 if (token != SEMI)
716 skip_to_semi (cfile);
717 return (struct option *)0;
718 }
719 vendor = malloc (strlen (val) + 1);
720 if (!vendor)
721 log_fatal ("no memory for vendor information.");
722 strcpy (vendor, val);
723 token = peek_token (&val, cfile);
724 if (token == DOT) {
725 /* Go ahead and take the DOT token... */
726 token = next_token (&val, cfile);
727
728 /* The next token should be an identifier... */
729 token = next_token (&val, cfile);
730 if (!is_identifier (token)) {
731 parse_warn ("expecting identifier after '.'");
732 if (token != SEMI)
733 skip_to_semi (cfile);
734 return (struct option *)0;
735 }
736
737 /* Look up the option name hash table for the specified
738 vendor. */
739 universe = ((struct universe *)
740 hash_lookup (&universe_hash,
741 (unsigned char *)vendor, 0));
742 /* If it's not there, we can't parse the rest of the
743 declaration. */
744 if (!universe) {
745 parse_warn ("no vendor named %s.", vendor);
746 skip_to_semi (cfile);
747 return (struct option *)0;
748 }
749 } else {
750 /* Use the default hash table, which contains all the
751 standard dhcp option names. */
752 val = vendor;
753 universe = &dhcp_universe;
754 }
755
756 /* Look up the actual option info... */
757 option = (struct option *)hash_lookup (universe -> hash,
758 (unsigned char *)val, 0);
759
760 /* If we didn't get an option structure, it's an undefined option. */
761 if (!option) {
762 if (val == vendor)
763 parse_warn ("no option named %s", val);
764 else
765 parse_warn ("no option named %s for vendor %s",
766 val, vendor);
767 skip_to_semi (cfile);
768 return (struct option *)0;
769 }
770
771 /* Free the initial identifier token. */
772 free (vendor);
773 return option;
774 }
775
776 /*
777 * colon-seperated-hex-list :== NUMBER |
778 * NUMBER COLON colon-seperated-hex-list
779 */
780
781 int parse_cshl (data, cfile)
782 struct data_string *data;
783 FILE *cfile;
784 {
785 char ibuf [128];
786 int ilen = 0;
787 int tlen = 0;
788 struct option_tag *sl = (struct option_tag *)0;
789 struct option_tag *next, **last = &sl;
790 enum dhcp_token token;
791 char *val;
792 unsigned char *rvp;
793
794 do {
795 token = next_token (&val, cfile);
796 if (token != NUMBER && token != NUMBER_OR_NAME) {
797 parse_warn ("expecting hexadecimal number.");
798 skip_to_semi (cfile);
799 for (; sl; sl = next) {
800 next = sl -> next;
801 dfree (sl, "parse_cshl");
802 }
803 return 0;
804 }
805 if (ilen == sizeof ibuf) {
806 next = (struct option_tag *)
807 dmalloc (ilen - 1 +
808 sizeof (struct option_tag),
809 "parse_cshl");
810 if (!next)
811 log_fatal ("no memory for string list.");
812 memcpy (next -> data, ibuf, ilen);
813 *last = next;
814 last = &next -> next;
815 tlen += ilen;
816 ilen = 0;
817 }
818 convert_num (&ibuf [ilen++], val, 16, 8);
819
820 token = peek_token (&val, cfile);
821 if (token != COLON)
822 break;
823 token = next_token (&val, cfile);
824 } while (1);
825
826 if (!buffer_allocate (&data -> buffer, tlen + ilen, "parse_cshl"))
827 log_fatal ("no memory to store octet data.");
828 data -> data = &data -> buffer -> data [0];
829 data -> len = tlen + ilen;
830 data -> terminated = 0;
831
832 rvp = &data -> data [0];
833 while (sl) {
834 next = sl -> next;
835 memcpy (rvp, sl -> data, sizeof ibuf);
836 rvp += sizeof ibuf;
837 dfree (sl, "parse_cshl");
838 sl = next;
839 }
840
841 memcpy (rvp, ibuf, ilen);
842 return 1;
843 }
844
845 /*
846 * executable-statements :== executable-statement executable-statements |
847 * executable-statement
848 *
849 * executable-statement :==
850 * IF if-statement |
851 * ADD class-name SEMI |
852 * BREAK SEMI |
853 * OPTION option-parameter SEMI |
854 * SUPERSEDE option-parameter SEMI |
855 * PREPEND option-parameter SEMI |
856 * APPEND option-parameter SEMI
857 */
858
859 struct executable_statement *parse_executable_statements (cfile, lose)
860 FILE *cfile;
861 int *lose;
862 {
863 struct executable_statement *head, **next;
864
865 next = &head;
866 while ((*next = parse_executable_statement (cfile, lose)))
867 next = &((*next) -> next);
868 if (!*lose)
869 return head;
870 return (struct executable_statement *)0;
871 }
872
873 struct executable_statement *parse_executable_statement (cfile, lose)
874 FILE *cfile;
875 int *lose;
876 {
877 enum dhcp_token token;
878 char *val;
879 struct executable_statement *stmt, base;
880 struct class *cta;
881 struct option *option;
882
883 switch (peek_token (&val, cfile)) {
884 case IF:
885 next_token (&val, cfile);
886 stmt = parse_if_statement (cfile, lose);
887 return stmt;
888 case ADD:
889 token = next_token (&val, cfile);
890 token = next_token (&val, cfile);
891 if (token != STRING) {
892 parse_warn ("expecting class name.");
893 skip_to_semi (cfile);
894 *lose = 1;
895 return (struct executable_statement *)0;
896 }
897 cta = find_class (val);
898 if (!cta) {
899 parse_warn ("unknown class %s.", val);
900 skip_to_semi (cfile);
901 *lose = 1;
902 return (struct executable_statement *)0;
903 }
904 if (!parse_semi (cfile)) {
905 *lose = 1;
906 return (struct executable_statement *)0;
907 }
908 memset (&base, 0, sizeof base);
909 base.op = add_statement;
910 base.data.add = cta;
911 break;
912
913 case BREAK:
914 token = next_token (&val, cfile);
915 if (!parse_semi (cfile)) {
916 *lose = 1;
917 return (struct executable_statement *)0;
918 }
919 memset (&base, 0, sizeof base);
920 base.op = break_statement;
921 break;
922
923 case SEND:
924 *lose = 1;
925 parse_warn ("send not appropriate here.");
926 skip_to_semi (cfile);
927 return (struct executable_statement *)0;
928
929 case SUPERSEDE:
930 case OPTION:
931 token = next_token (&val, cfile);
932 option = parse_option_name (cfile);
933 if (!option) {
934 *lose = 1;
935 return (struct executable_statement *)0;
936 }
937 return parse_option_statement (cfile, 1, option,
938 supersede_option_statement);
939
940 case DEFAULT:
941 token = next_token (&val, cfile);
942 option = parse_option_name (cfile);
943 if (!option) {
944 *lose = 1;
945 return (struct executable_statement *)0;
946 }
947 return parse_option_statement (cfile, 1, option,
948 default_option_statement);
949
950 case PREPEND:
951 token = next_token (&val, cfile);
952 option = parse_option_name (cfile);
953 if (!option) {
954 *lose = 1;
955 return (struct executable_statement *)0;
956 }
957 return parse_option_statement (cfile, 1, option,
958 prepend_option_statement);
959
960 case APPEND:
961 token = next_token (&val, cfile);
962 option = parse_option_name (cfile);
963 if (!option) {
964 *lose = 1;
965 return (struct executable_statement *)0;
966 }
967 return parse_option_statement (cfile, 1, option,
968 append_option_statement);
969
970 default:
971 *lose = 0;
972 return (struct executable_statement *)0;
973 }
974
975 stmt = ((struct executable_statement *)
976 dmalloc (sizeof (struct executable_statement),
977 "parse_executable_statement"));
978 if (!stmt)
979 log_fatal ("no memory for new statement.");
980 *stmt = base;
981 return stmt;
982 }
983
984 /*
985 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
986 * else-statement
987 *
988 * else-statement :== <null> |
989 * ELSE LBRACE executable-statements RBRACE |
990 * ELSE IF if-statement |
991 * ELSIF if-statement
992 */
993
994 struct executable_statement *parse_if_statement (cfile, lose)
995 FILE *cfile;
996 int *lose;
997 {
998 enum dhcp_token token;
999 char *val;
1000 struct executable_statement *stmt;
1001 struct expression *if_condition;
1002 struct executable_statement *true, *false;
1003
1004 if_condition = (struct expression *)0;
1005 if (!parse_boolean_expression (&if_condition, cfile, lose)) {
1006 if (!*lose)
1007 parse_warn ("boolean expression expected.");
1008 return (struct executable_statement *)0;
1009 }
1010 #if defined (DEBUG_EXPRESSION_PARSE)
1011 print_expression ("if condition", if_condition);
1012 #endif
1013 token = next_token (&val, cfile);
1014 if (token != LBRACE) {
1015 parse_warn ("left brace expected.");
1016 skip_to_semi (cfile);
1017 *lose = 1;
1018 return (struct executable_statement *)0;
1019 }
1020 true = parse_executable_statements (cfile, lose);
1021 token = next_token (&val, cfile);
1022 if (*lose) {
1023 /* Try to even things up. */
1024 do {
1025 token = next_token (&val, cfile);
1026 } while (token != EOF && token != RBRACE);
1027 return (struct executable_statement *)0;
1028 }
1029 if (token != RBRACE) {
1030 parse_warn ("right brace expected.");
1031 skip_to_semi (cfile);
1032 *lose = 1;
1033 return (struct executable_statement *)0;
1034 }
1035 token = peek_token (&val, cfile);
1036 if (token == ELSE) {
1037 token = next_token (&val, cfile);
1038 token = peek_token (&val, cfile);
1039 if (token == IF) {
1040 token = next_token (&val, cfile);
1041 false = parse_if_statement (cfile, lose);
1042 if (*lose)
1043 return (struct executable_statement *)0;
1044 } else if (token != LBRACE) {
1045 parse_warn ("left brace or if expected.");
1046 skip_to_semi (cfile);
1047 *lose = 1;
1048 return (struct executable_statement *)0;
1049 } else {
1050 token = next_token (&val, cfile);
1051 false = parse_executable_statements (cfile, lose);
1052 if (*lose)
1053 return (struct executable_statement *)0;
1054 token = next_token (&val, cfile);
1055 if (token != RBRACE) {
1056 parse_warn ("right brace expected.");
1057 skip_to_semi (cfile);
1058 *lose = 1;
1059 return (struct executable_statement *)0;
1060 }
1061 }
1062 } else if (token == ELSIF) {
1063 token = next_token (&val, cfile);
1064 false = parse_if_statement (cfile, lose);
1065 if (*lose)
1066 return (struct executable_statement *)0;
1067 } else
1068 false = (struct executable_statement *)0;
1069
1070 stmt = ((struct executable_statement *)
1071 dmalloc (sizeof (struct executable_statement),
1072 "parse_if_statement"));
1073 if (!stmt)
1074 log_fatal ("no memory for if statement.");
1075 memset (stmt, 0, sizeof *stmt);
1076 stmt -> op = if_statement;
1077 stmt -> data.ie.expr = if_condition;
1078 stmt -> data.ie.true = true;
1079 stmt -> data.ie.false = false;
1080 return stmt;
1081 }
1082
1083 /*
1084 * boolean_expression :== CHECK STRING |
1085 * NOT boolean-expression |
1086 * data-expression EQUAL data-expression |
1087 * boolean-expression AND boolean-expression |
1088 * boolean-expression OR boolean-expression
1089 * EXISTS OPTION-NAME
1090 */
1091
1092 int parse_boolean_expression (expr, cfile, lose)
1093 struct expression **expr;
1094 FILE *cfile;
1095 int *lose;
1096 {
1097 /* Parse an expression... */
1098 if (!parse_expression (expr, cfile, lose, context_boolean,
1099 (struct expression **)0, expr_none))
1100 return 0;
1101
1102 if (!is_boolean_expression (*expr)) {
1103 parse_warn ("Expecting a boolean expression.");
1104 *lose = 1;
1105 return 0;
1106 }
1107 return 1;
1108 }
1109
1110 /*
1111 * data_expression :== SUBSTRING LPAREN data-expression COMMA
1112 * numeric-expression COMMA
1113 * numeric-expression RPAREN |
1114 * SUFFIX LPAREN data_expression COMMA
1115 * numeric-expression |
1116 * OPTION option_name |
1117 * HARDWARE |
1118 * PACKET LPAREN numeric-expression COMMA
1119 * numeric-expression RPAREN |
1120 * STRING |
1121 * colon_seperated_hex_list
1122 */
1123
1124 int parse_data_expression (expr, cfile, lose)
1125 struct expression **expr;
1126 FILE *cfile;
1127 int *lose;
1128 {
1129 /* Parse an expression... */
1130 if (!parse_expression (expr, cfile, lose, context_data,
1131 (struct expression **)0, expr_none))
1132 return 0;
1133
1134 if (!is_data_expression (*expr)) {
1135 parse_warn ("Expecting a data expression.");
1136 *lose = 1;
1137 return 0;
1138 }
1139 return 1;
1140 }
1141
1142 /*
1143 * numeric-expression :== EXTRACT_INT LPAREN data-expression
1144 * COMMA number RPAREN |
1145 * NUMBER
1146 */
1147
1148 int parse_numeric_expression (expr, cfile, lose)
1149 struct expression **expr;
1150 FILE *cfile;
1151 int *lose;
1152 {
1153 /* Parse an expression... */
1154 if (!parse_expression (expr, cfile, lose, context_numeric,
1155 (struct expression **)0, expr_none))
1156 return 0;
1157
1158 if (!is_numeric_expression (*expr)) {
1159 parse_warn ("Expecting a numeric expression.");
1160 *lose = 1;
1161 return 0;
1162 }
1163 return 1;
1164 }
1165
1166 /* Parse a subexpression that does not contain a binary operator. */
1167
1168 int parse_non_binary (expr, cfile, lose, context)
1169 struct expression **expr;
1170 FILE *cfile;
1171 int *lose;
1172 enum expression_context context;
1173 {
1174 enum dhcp_token token;
1175 char *val;
1176 struct collection *col;
1177 struct option *option;
1178
1179 token = peek_token (&val, cfile);
1180
1181 /* Check for unary operators... */
1182 switch (token) {
1183 case CHECK:
1184 token = next_token (&val, cfile);
1185 token = next_token (&val, cfile);
1186 if (token != STRING) {
1187 parse_warn ("string expected.");
1188 skip_to_semi (cfile);
1189 *lose = 1;
1190 return 0;
1191 }
1192 for (col = collections; col; col = col -> next)
1193 if (!strcmp (col -> name, val))
1194 break;
1195 if (!col) {
1196 parse_warn ("unknown collection.");
1197 *lose = 1;
1198 return 0;
1199 }
1200 if (!expression_allocate (expr, "parse_expression: CHECK"))
1201 log_fatal ("can't allocate expression");
1202 (*expr) -> op = expr_check;
1203 (*expr) -> data.check = col;
1204 break;
1205
1206 case NOT:
1207 token = next_token (&val, cfile);
1208 if (!expression_allocate (expr, "parse_expression: NOT"))
1209 log_fatal ("can't allocate expression");
1210 (*expr) -> op = expr_not;
1211 if (!parse_non_binary (&(*expr) -> data.not,
1212 cfile, lose, context)) {
1213 if (!*lose) {
1214 parse_warn ("expression expected");
1215 skip_to_semi (cfile);
1216 }
1217 *lose = 1;
1218 expression_dereference (expr, "parse_expression: NOT");
1219 return 0;
1220 }
1221 break;
1222
1223 case EXISTS:
1224 token = next_token (&val, cfile);
1225 if (!expression_allocate (expr, "parse_expression: EXISTS"))
1226 log_fatal ("can't allocate expression");
1227 (*expr) -> op = expr_exists;
1228 (*expr) -> data.option = parse_option_name (cfile);
1229 if (!(*expr) -> data.option) {
1230 *lose = 1;
1231 expression_dereference (expr,
1232 "parse_expression: EXISTS");
1233 return 0;
1234 }
1235 break;
1236
1237 case SUBSTRING:
1238 token = next_token (&val, cfile);
1239 if (!expression_allocate (expr, "parse_expression: SUBSTRING"))
1240 log_fatal ("can't allocate expression");
1241 (*expr) -> op = expr_substring;
1242
1243 token = next_token (&val, cfile);
1244 if (token != LPAREN) {
1245 nolparen:
1246 expression_dereference (expr,
1247 "parse_expression: nolparen");
1248 parse_warn ("left parenthesis expected.");
1249 *lose = 1;
1250 return 0;
1251 }
1252
1253 if (!parse_data_expression (&(*expr) -> data.substring.expr,
1254 cfile, lose)) {
1255 nodata:
1256 expression_dereference (expr,
1257 "parse_expression: nodata");
1258 parse_warn ("expecting data expression.");
1259 skip_to_semi (cfile);
1260 *lose = 1;
1261 return 0;
1262 }
1263
1264 token = next_token (&val, cfile);
1265 if (token != COMMA) {
1266 nocomma:
1267 expression_dereference (expr,
1268 "parse_expression: nocomma1");
1269 parse_warn ("comma expected.");
1270 *lose = 1;
1271
1272 return 0;
1273 }
1274
1275 if (!parse_numeric_expression
1276 (&(*expr) -> data.substring.offset,cfile, lose)) {
1277 nonum:
1278 if (!*lose) {
1279 parse_warn ("expecting numeric expression.");
1280 skip_to_semi (cfile);
1281 *lose = 1;
1282 }
1283 expression_dereference (expr,
1284 "parse_expression: nonum");
1285 return 0;
1286 }
1287
1288 token = next_token (&val, cfile);
1289 if (token != COMMA)
1290 goto nocomma;
1291
1292 if (!parse_numeric_expression
1293 (&(*expr) -> data.substring.len, cfile, lose))
1294 goto nonum;
1295
1296 token = next_token (&val, cfile);
1297 if (token != RPAREN) {
1298 norparen:
1299 parse_warn ("right parenthesis expected.");
1300 *lose = 1;
1301 expression_dereference (expr,
1302 "parse_expression: norparen");
1303 return 0;
1304 }
1305 break;
1306
1307 case SUFFIX:
1308 token = next_token (&val, cfile);
1309 if (!expression_allocate (expr, "parse_expression: SUFFIX"))
1310 log_fatal ("can't allocate expression");
1311 (*expr) -> op = expr_suffix;
1312
1313 token = next_token (&val, cfile);
1314 if (token != LPAREN)
1315 goto nolparen;
1316
1317 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
1318 cfile, lose))
1319 goto nodata;
1320
1321 token = next_token (&val, cfile);
1322 if (token != COMMA)
1323 goto nocomma;
1324
1325 if (!parse_data_expression (&(*expr) -> data.suffix.len,
1326 cfile, lose))
1327 goto nonum;
1328
1329 token = next_token (&val, cfile);
1330 if (token != RPAREN)
1331 goto norparen;
1332 break;
1333
1334 case OPTION:
1335 token = next_token (&val, cfile);
1336 if (!expression_allocate (expr, "parse_expression: OPTION"))
1337 log_fatal ("can't allocate expression");
1338 (*expr) -> op = expr_option;
1339 (*expr) -> data.option = parse_option_name (cfile);
1340 if (!(*expr) -> data.option) {
1341 *lose = 1;
1342 expression_dereference (expr,
1343 "parse_expression: OPTION");
1344 return 0;
1345 }
1346 break;
1347
1348 case HARDWARE:
1349 token = next_token (&val, cfile);
1350 if (!expression_allocate (expr, "parse_expression: HARDWARE"))
1351 log_fatal ("can't allocate expression");
1352 (*expr) -> op = expr_hardware;
1353 break;
1354
1355 case PACKET:
1356 token = next_token (&val, cfile);
1357 if (!expression_allocate (expr, "parse_expression: PACKET"))
1358 log_fatal ("can't allocate expression");
1359 (*expr) -> op = expr_packet;
1360
1361 token = next_token (&val, cfile);
1362 if (token != LPAREN)
1363 goto nolparen;
1364
1365 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
1366 cfile, lose))
1367 goto nonum;
1368
1369 token = next_token (&val, cfile);
1370 if (token != COMMA)
1371 goto nocomma;
1372
1373 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
1374 cfile, lose))
1375 goto nonum;
1376
1377 token = next_token (&val, cfile);
1378 if (token != RPAREN)
1379 goto norparen;
1380 break;
1381
1382 case STRING:
1383 token = next_token (&val, cfile);
1384 if (!make_const_data (expr, val, strlen (val), 1, 1))
1385 log_fatal ("can't make constant string expression.");
1386 break;
1387
1388 case EXTRACT_INT:
1389 token = next_token (&val, cfile);
1390 token = next_token (&val, cfile);
1391 if (token != LPAREN) {
1392 parse_warn ("left parenthesis expected.");
1393 *lose = 1;
1394 return 0;
1395 }
1396
1397 if (!expression_allocate (expr,
1398 "parse_expression: EXTRACT_INT"))
1399 log_fatal ("can't allocate expression");
1400
1401 if (!parse_data_expression (&(*expr) -> data.extract_int,
1402 cfile, lose)) {
1403 parse_warn ("expecting data expression.");
1404 skip_to_semi (cfile);
1405 *lose = 1;
1406 expression_dereference
1407 (expr, "parse_expression: EXTRACT_INT");
1408 return 0;
1409 }
1410
1411 token = next_token (&val, cfile);
1412 if (token != COMMA) {
1413 parse_warn ("comma expected.");
1414 *lose = 1;
1415 return 0;
1416 }
1417
1418 token = next_token (&val, cfile);
1419 if (token != NUMBER) {
1420 parse_warn ("number expected.");
1421 *lose = 1;
1422 return 0;
1423 }
1424 switch (atoi (val)) {
1425 case 8:
1426 (*expr) -> op = expr_extract_int8;
1427 break;
1428
1429 case 16:
1430 (*expr) -> op = expr_extract_int16;
1431 break;
1432
1433 case 32:
1434 (*expr) -> op = expr_extract_int32;
1435 break;
1436
1437 default:
1438 parse_warn ("unsupported integer size %d", atoi (val));
1439 *lose = 1;
1440 skip_to_semi (cfile);
1441 expression_dereference
1442 (expr, "parse_expression: EXTRACT_INT");
1443 return 0;
1444 }
1445
1446 token = next_token (&val, cfile);
1447 if (token != RPAREN) {
1448 parse_warn ("right parenthesis expected.");
1449 *lose = 1;
1450 return 0;
1451 }
1452 break;
1453
1454 case NUMBER:
1455 if (!expression_allocate (expr,
1456 "parse_expression: NUMBER"))
1457 log_fatal ("can't allocate expression");
1458
1459 /* If we're in a numeric context, this should just be a
1460 number, by itself. */
1461 if (context == context_numeric) {
1462 next_token (&val, cfile); /* Eat the number. */
1463 (*expr) -> op = expr_const_int;
1464 (*expr) -> data.const_int = atoi (val);
1465 break;
1466 }
1467
1468 case NUMBER_OR_NAME:
1469 (*expr) -> op = expr_const_data;
1470 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
1471 expression_dereference (expr,
1472 "parse_expression: cshl");
1473 return 0;
1474 }
1475 break;
1476
1477 /* Not a valid start to an expression... */
1478 default:
1479 return 0;
1480 }
1481 return 1;
1482 }
1483
1484 /* Parse an expression. */
1485
1486 int parse_expression (expr, cfile, lose, context, plhs, binop)
1487 struct expression **expr;
1488 FILE *cfile;
1489 int *lose;
1490 enum expression_context context;
1491 struct expression **plhs;
1492 enum expr_op binop;
1493 {
1494 enum dhcp_token token;
1495 char *val;
1496 struct expression *rhs = (struct expression *)0, *tmp;
1497 struct expression *lhs;
1498 enum expr_op next_op;
1499
1500 /* Consume the left hand side we were passed. */
1501 if (plhs) {
1502 lhs = *plhs;
1503 *plhs = (struct expression *)0;
1504 } else
1505 lhs = (struct expression *)0;
1506
1507 new_rhs:
1508 if (!parse_non_binary (&rhs, cfile, lose, context)) {
1509 /* If we already have a left-hand side, then it's not
1510 okay for there not to be a right-hand side here, so
1511 we need to flag it as an error. */
1512 if (lhs) {
1513 if (!*lose) {
1514 parse_warn ("expecting right-hand side.");
1515 *lose = 1;
1516 skip_to_semi (cfile);
1517 }
1518 expression_dereference (&lhs, "parse_expression");
1519 }
1520 return 0;
1521 }
1522
1523 /* At this point, rhs contains either an entire subexpression,
1524 or at least a left-hand-side. If we do not see a binary token
1525 as the next token, we're done with the expression. */
1526
1527 token = peek_token (&val, cfile);
1528 switch (token) {
1529 case EQUAL:
1530 next_op = expr_equal;
1531 break;
1532
1533 case AND:
1534 next_op = expr_and;
1535 break;
1536
1537 case OR:
1538 next_op = expr_or;
1539 break;
1540
1541 default:
1542 next_op = expr_none;
1543 }
1544
1545 /* If we have no lhs yet, we just parsed it. */
1546 if (!lhs) {
1547 /* If there was no operator following what we just parsed,
1548 then we're done - return it. */
1549 if (next_op == expr_none) {
1550 *expr = rhs;
1551 return 1;
1552 }
1553 lhs = rhs;
1554 rhs = (struct expression *)0;
1555 binop = next_op;
1556 next_token (&val, cfile); /* Consume the operator. */
1557 goto new_rhs;
1558 }
1559
1560 /* Now, if we didn't find a binary operator, we're done parsing
1561 this subexpression, so combine it with the preceding binary
1562 operator and return the result. */
1563 if (next_op == expr_none) {
1564 if (!expression_allocate (expr,
1565 "parse_expression: COMBINE"))
1566 log_fatal ("Can't allocate expression!");
1567
1568 (*expr) -> op = binop;
1569 /* All the binary operators' data union members
1570 are the same, so we'll cheat and use the member
1571 for the equals operator. */
1572 (*expr) -> data.equal [0] = lhs;
1573 (*expr) -> data.equal [1] = rhs;
1574 return 1;
1575 }
1576
1577 /* Eat the operator token - we now know it was a binary operator... */
1578 token = next_token (&val, cfile);
1579
1580 /* If the binary operator we saw previously has a lower precedence
1581 than the next operator, then the rhs we just parsed for that
1582 operator is actually the lhs of the operator with the higher
1583 precedence - to get the real rhs, we need to recurse on the
1584 new operator. */
1585 if (binop != expr_none &&
1586 op_precedence (binop, next_op) < 0) {
1587 tmp = rhs;
1588 rhs = (struct expression *)0;
1589 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
1590 &tmp, next_op)) {
1591 if (!*lose) {
1592 parse_warn ("expecting a subexpression");
1593 *lose = 1;
1594 }
1595 return 0;
1596 }
1597 next_op = expr_none;
1598 }
1599
1600 /* Now combine the LHS and the RHS using binop. */
1601 tmp = (struct expression *)0;
1602 if (!expression_allocate (&tmp, "parse_expression: COMBINE2"))
1603 log_fatal ("No memory for equal precedence combination.");
1604
1605 /* Store the LHS and RHS. */
1606 tmp -> data.equal [0] = lhs;
1607 tmp -> data.equal [1] = rhs;
1608 tmp -> op = binop;
1609
1610 lhs = tmp;
1611 tmp = (struct expression *)0;
1612 rhs = (struct expression *)0;
1613
1614 /* Recursions don't return until we have parsed the end of the
1615 expression, so if we recursed earlier, we can now return what
1616 we got. */
1617 if (next_op == expr_none) {
1618 *expr = lhs;
1619 return 1;
1620 }
1621
1622 binop = next_op;
1623 goto new_rhs;
1624 }
1625
1626 /* option-statement :== identifier DOT identifier <syntax> SEMI
1627 | identifier <syntax> SEMI
1628
1629 Option syntax is handled specially through format strings, so it
1630 would be painful to come up with BNF for it. However, it always
1631 starts as above and ends in a SEMI. */
1632
1633 struct executable_statement *parse_option_statement (cfile, lookups,
1634 option, op)
1635 FILE *cfile;
1636 int lookups;
1637 struct option *option;
1638 enum statement_op op;
1639 {
1640 char *val;
1641 enum dhcp_token token;
1642 char *fmt;
1643 struct expression *expr = (struct expression *)0;
1644 struct expression *tmp;
1645 int lose;
1646 struct executable_statement *stmt;
1647 int ftt = 1;
1648
1649 token = peek_token (&val, cfile);
1650 if (token == SEMI) {
1651 /* Eat the semicolon... */
1652 token = next_token (&val, cfile);
1653 goto done;
1654 }
1655
1656 /* Parse the option data... */
1657 do {
1658 /* Set a flag if this is an array of a simple type (i.e.,
1659 not an array of pairs of IP addresses, or something
1660 like that. */
1661 int uniform = option -> format [1] == 'A';
1662
1663 for (fmt = option -> format; *fmt; fmt++) {
1664 if (*fmt == 'A')
1665 break;
1666 tmp = expr;
1667 expr = (struct expression *)0;
1668 if (!parse_option_token (&expr, cfile, fmt,
1669 tmp, uniform, lookups)) {
1670 expression_dereference
1671 (&tmp, "parse_option_statement");
1672 return (struct executable_statement *)0;
1673 }
1674 if (tmp)
1675 expression_dereference
1676 (&tmp, "parse_option_statement");
1677 }
1678 if (*fmt == 'A') {
1679 token = peek_token (&val, cfile);
1680 if (token == COMMA) {
1681 token = next_token (&val, cfile);
1682 continue;
1683 }
1684 break;
1685 }
1686 } while (*fmt == 'A');
1687
1688 #if 0
1689 goto done;
1690
1691 try_expr:
1692 /* See if there's a data expression, and if so, use it rather than
1693 the standard format. */
1694 expr = parse_data_expression (cfile, &lose);
1695
1696 /* Found a data expression, but it was bogus? */
1697 if (lose)
1698 return (struct executable_statement *)0;
1699
1700 #endif /* 0 */
1701 done:
1702 if (!parse_semi (cfile))
1703 return (struct executable_statement *)0;
1704 stmt = ((struct executable_statement *)
1705 dmalloc (sizeof *stmt, "parse_option_statement"));
1706 memset (stmt, 0, sizeof *stmt);
1707 stmt -> op = op;
1708 if (expr && !option_cache (&stmt -> data.option,
1709 (struct data_string *)0, expr, option))
1710 log_fatal ("no memory for option cache in parse_option_statement");
1711 return stmt;
1712 }
1713
1714 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
1715 struct expression **rv;
1716 FILE *cfile;
1717 char *fmt;
1718 struct expression *expr;
1719 int uniform;
1720 int lookups;
1721 {
1722 char *val;
1723 enum dhcp_token token;
1724 struct expression *t = (struct expression *)0;
1725 unsigned char buf [4];
1726 int len;
1727 unsigned char *ob;
1728 struct iaddr addr;
1729
1730 switch (*fmt) {
1731 case 'X':
1732 token = peek_token (&val, cfile);
1733 if (token == NUMBER_OR_NAME || token == NUMBER) {
1734 if (!expression_allocate (&t, "parse_option_token"))
1735 return 0;
1736 if (!parse_cshl (&t -> data.const_data, cfile))
1737 return 0;
1738 t -> op = expr_const_data;
1739 } else if (token == STRING) {
1740 token = next_token (&val, cfile);
1741 if (!make_const_data (&t, (unsigned char *) val,
1742 strlen (val), 1, 1))
1743 log_fatal ("No memory for concatenation");
1744 } else {
1745 parse_warn ("expecting string %s.",
1746 "or hexadecimal data");
1747 skip_to_semi (cfile);
1748 return 0;
1749 }
1750 break;
1751
1752 case 't': /* Text string... */
1753 token = next_token (&val, cfile);
1754 if (token != STRING && !is_identifier (token)) {
1755 parse_warn ("expecting string.");
1756 if (token != SEMI)
1757 skip_to_semi (cfile);
1758 return 0;
1759 }
1760 if (!make_const_data (&t, (unsigned char *)val,
1761 strlen (val), 1, 1))
1762 log_fatal ("No memory for concatenation");
1763 break;
1764
1765 case 'I': /* IP address or hostname. */
1766 if (lookups) {
1767 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
1768 return 0;
1769 } else {
1770 if (!parse_ip_addr (cfile, &addr))
1771 return 0;
1772 if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1))
1773 return 0;
1774 }
1775 break;
1776
1777 case 'L': /* Unsigned 32-bit integer... */
1778 case 'l': /* Signed 32-bit integer... */
1779 token = next_token (&val, cfile);
1780 if (token != NUMBER) {
1781 need_number:
1782 parse_warn ("expecting number.");
1783 if (token != SEMI)
1784 skip_to_semi (cfile);
1785 return 0;
1786 }
1787 convert_num (buf, val, 0, 32);
1788 if (!make_const_data (&t, buf, 4, 0, 1))
1789 return 0;
1790 break;
1791
1792 case 's': /* Signed 16-bit integer. */
1793 case 'S': /* Unsigned 16-bit integer. */
1794 token = next_token (&val, cfile);
1795 if (token != NUMBER)
1796 goto need_number;
1797 convert_num (buf, val, 0, 16);
1798 if (!make_const_data (&t, buf, 2, 0, 1))
1799 return 0;
1800 break;
1801
1802 case 'b': /* Signed 8-bit integer. */
1803 case 'B': /* Unsigned 8-bit integer. */
1804 token = next_token (&val, cfile);
1805 if (token != NUMBER)
1806 goto need_number;
1807 convert_num (buf, val, 0, 8);
1808 if (!make_const_data (&t, buf, 1, 0, 1))
1809 return 0;
1810 break;
1811
1812 case 'f': /* Boolean flag. */
1813 token = next_token (&val, cfile);
1814 if (!is_identifier (token)) {
1815 parse_warn ("expecting identifier.");
1816 bad_flag:
1817 if (token != SEMI)
1818 skip_to_semi (cfile);
1819 return 0;
1820 }
1821 if (!strcasecmp (val, "true")
1822 || !strcasecmp (val, "on"))
1823 buf [0] = 1;
1824 else if (!strcasecmp (val, "false")
1825 || !strcasecmp (val, "off"))
1826 buf [0] = 0;
1827 else {
1828 parse_warn ("expecting boolean.");
1829 goto bad_flag;
1830 }
1831 if (!make_const_data (&t, buf, 1, 0, 1))
1832 return 0;
1833 break;
1834
1835 default:
1836 log_error ("Bad format %c in parse_option_param.",
1837 *fmt);
1838 skip_to_semi (cfile);
1839 return 0;
1840 }
1841 if (expr) {
1842 if (!make_concat (rv, expr, t))
1843 return 0;
1844 expression_dereference (&t, "parse_option_token");
1845 } else
1846 *rv = t;
1847 return 1;
1848 }
1849
1850 int parse_auth_key (key_id, cfile)
1851 struct data_string *key_id;
1852 FILE *cfile;
1853 {
1854 struct data_string key_data;
1855 char *val;
1856 enum dhcp_token token;
1857 struct auth_key *key, *old_key = (struct auth_key *)0;
1858
1859 memset (&key_data, 0, sizeof key_data);
1860
1861 if (!parse_cshl (key_id, cfile))
1862 return 0;
1863
1864 key = auth_key_lookup (key_id);
1865
1866 token = peek_token (&val, cfile);
1867 if (token == SEMI) {
1868 if (!key)
1869 parse_warn ("reference to undefined key %s",
1870 print_hex_1 (key_id -> len,
1871 key_id -> data,
1872 key_id -> len));
1873 data_string_forget (key_id, "parse_auth_key");
1874 } else {
1875 if (!parse_cshl (&key_data, cfile))
1876 return 0;
1877 if (key) {
1878 parse_warn ("redefinition of key %s",
1879 print_hex_1 (key_id -> len,
1880 key_id -> data,
1881 key_id -> len));
1882 old_key = key;
1883 }
1884 key = new_auth_key (key_data.len, "parse_auth_key");
1885 if (!key)
1886 log_fatal ("No memory for key %s",
1887 print_hex_1 (key_id -> len,
1888 key_id -> data,
1889 key_id -> len));
1890 key -> length = key_data.len;
1891 memcpy (key -> data, key_data.data, key_data.len);
1892 enter_auth_key (key_id, key);
1893 data_string_forget (&key_data, "parse_auth_key");
1894 }
1895
1896 parse_semi (cfile);
1897 return key_id -> len ? 1 : 0;
1898 }