]> git.ipfire.org Git - thirdparty/dhcp.git/blame - common/parse.c
Get rid of dprintf.
[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[] =
cfdfb9f1 25"$Id: parse.c,v 1.61 2000/02/01 03:19:39 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"
63115431
TL
29
30/* Skip to the semicolon ending the current statement. If we encounter
31 braces, the matching closing brace terminates the statement. If we
32 encounter a right brace but haven't encountered a left brace, return
33 leaving the brace in the token buffer for the caller. If we see a
34 semicolon and haven't seen a left brace, return. This lets us skip
35 over:
36
37 statement;
38 statement foo bar { }
39 statement foo bar { statement { } }
40 statement}
41
42 ...et cetera. */
43
44void skip_to_semi (cfile)
4615d498 45 struct parse *cfile;
cea8b5c9
TL
46{
47 skip_to_rbrace (cfile, 0);
48}
49
50void skip_to_rbrace (cfile, brace_count)
4615d498 51 struct parse *cfile;
cea8b5c9 52 int brace_count;
63115431 53{
02a015fb 54 enum dhcp_token token;
b1b7b521 55 const char *val;
63115431 56
f579f39f
TL
57#if defined (DEBUG_TOKEN)
58 log_error ("skip_to_rbrace: %d\n", brace_count);
59#endif
63115431
TL
60 do {
61 token = peek_token (&val, cfile);
62 if (token == RBRACE) {
efc79acb 63 token = next_token (&val, cfile);
63115431 64 if (brace_count) {
63115431
TL
65 if (!--brace_count)
66 return;
67 } else
68 return;
69 } else if (token == LBRACE) {
70 brace_count++;
71 } else if (token == SEMI && !brace_count) {
72 token = next_token (&val, cfile);
73 return;
796ef008
TL
74 } else if (token == EOL) {
75 /* EOL only happens when parsing /etc/resolv.conf,
76 and we treat it like a semicolon because the
77 resolv.conf file is line-oriented. */
78 token = next_token (&val, cfile);
79 return;
63115431
TL
80 }
81 token = next_token (&val, cfile);
82 } while (token != EOF);
83}
84
85int parse_semi (cfile)
4615d498 86 struct parse *cfile;
63115431 87{
02a015fb 88 enum dhcp_token token;
b1b7b521 89 const char *val;
63115431
TL
90
91 token = next_token (&val, cfile);
92 if (token != SEMI) {
4615d498 93 parse_warn (cfile, "semicolon expected.");
63115431
TL
94 skip_to_semi (cfile);
95 return 0;
96 }
97 return 1;
98}
99
100/* string-parameter :== STRING SEMI */
101
102char *parse_string (cfile)
4615d498 103 struct parse *cfile;
63115431 104{
b1b7b521 105 const char *val;
02a015fb 106 enum dhcp_token token;
63115431
TL
107 char *s;
108
109 token = next_token (&val, cfile);
110 if (token != STRING) {
4615d498 111 parse_warn (cfile, "filename must be a string");
63115431
TL
112 skip_to_semi (cfile);
113 return (char *)0;
114 }
fdac15d9 115 s = (char *)dmalloc (strlen (val) + 1, MDL);
63115431 116 if (!s)
8ae2d595 117 log_fatal ("no memory for string %s.", val);
63115431
TL
118 strcpy (s, val);
119
120 if (!parse_semi (cfile))
121 return (char *)0;
122 return s;
123}
124
be6be08d
TL
125/*
126 * hostname :== IDENTIFIER
127 * | IDENTIFIER DOT
128 * | hostname DOT IDENTIFIER
129 */
796ef008
TL
130
131char *parse_host_name (cfile)
4615d498 132 struct parse *cfile;
796ef008 133{
b1b7b521 134 const char *val;
02a015fb 135 enum dhcp_token token;
b1b7b521 136 unsigned len = 0;
796ef008
TL
137 char *s;
138 char *t;
139 pair c = (pair)0;
140
141 /* Read a dotted hostname... */
142 do {
143 /* Read a token, which should be an identifier. */
68dda014
TL
144 token = peek_token (&val, cfile);
145 if (!is_identifier (token) && token != NUMBER)
146 break;
796ef008 147 token = next_token (&val, cfile);
68dda014 148
796ef008 149 /* Store this identifier... */
fdac15d9 150 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
8ae2d595 151 log_fatal ("can't allocate temp space for hostname.");
796ef008
TL
152 strcpy (s, val);
153 c = cons ((caddr_t)s, c);
154 len += strlen (s) + 1;
155 /* Look for a dot; if it's there, keep going, otherwise
156 we're done. */
157 token = peek_token (&val, cfile);
158 if (token == DOT)
159 token = next_token (&val, cfile);
160 } while (token == DOT);
161
162 /* Assemble the hostname together into a string. */
fdac15d9 163 if (!(s = (char *)dmalloc (len, MDL)))
8ae2d595 164 log_fatal ("can't allocate space for hostname.");
796ef008
TL
165 t = s + len;
166 *--t = 0;
167 while (c) {
168 pair cdr = c -> cdr;
b1b7b521 169 unsigned l = strlen ((char *)(c -> car));
796ef008
TL
170 t -= l;
171 memcpy (t, (char *)(c -> car), l);
172 /* Free up temp space. */
fdac15d9
TL
173 dfree (c -> car, MDL);
174 dfree (c, MDL);
796ef008
TL
175 c = cdr;
176 if (t != s)
177 *--t = '.';
178 }
179 return s;
180}
181
be6be08d
TL
182/* ip-addr-or-hostname :== ip-address | hostname
183 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
184
185 Parse an ip address or a hostname. If uniform is zero, put in
186 an expr_substring node to limit hostnames that evaluate to more
187 than one IP address. */
188
02a015fb
TL
189int parse_ip_addr_or_hostname (expr, cfile, uniform)
190 struct expression **expr;
4615d498 191 struct parse *cfile;
be6be08d
TL
192 int uniform;
193{
b1b7b521 194 const char *val;
02a015fb 195 enum dhcp_token token;
be6be08d 196 unsigned char addr [4];
b1b7b521 197 unsigned len = sizeof addr;
be6be08d 198 char *name;
02a015fb 199 struct expression *x = (struct expression *)0;
be6be08d
TL
200
201 token = peek_token (&val, cfile);
202 if (is_identifier (token)) {
203 name = parse_host_name (cfile);
204 if (!name)
02a015fb
TL
205 return 0;
206 if (!make_host_lookup (expr, name))
207 return 0;
208 if (!uniform) {
209 if (!make_limit (&x, *expr, 4))
210 return 0;
4bd8800e 211 expression_dereference (expr, MDL);
02a015fb
TL
212 *expr = x;
213 }
be6be08d
TL
214 } else if (token == NUMBER) {
215 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
02a015fb
TL
216 return 0;
217 return make_const_data (expr, addr, len, 0, 1);
be6be08d
TL
218 } else {
219 if (token != RBRACE && token != LBRACE)
220 token = next_token (&val, cfile);
4615d498 221 parse_warn (cfile, "%s (%d): expecting IP address or hostname",
be6be08d
TL
222 val, token);
223 if (token != SEMI)
224 skip_to_semi (cfile);
02a015fb 225 return 0;
be6be08d
TL
226 }
227
02a015fb 228 return 1;
be6be08d
TL
229}
230
231/*
232 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
233 */
234
796ef008 235int parse_ip_addr (cfile, addr)
4615d498 236 struct parse *cfile;
796ef008
TL
237 struct iaddr *addr;
238{
b1b7b521 239 const char *val;
02a015fb 240 enum dhcp_token token;
796ef008
TL
241
242 addr -> len = 4;
243 if (parse_numeric_aggregate (cfile, addr -> iabuf,
244 &addr -> len, DOT, 10, 8))
245 return 1;
246 return 0;
247}
248
be6be08d
TL
249/*
250 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
251 * hardware-type :== ETHERNET | TOKEN_RING
252 */
63115431
TL
253
254void parse_hardware_param (cfile, hardware)
4615d498 255 struct parse *cfile;
63115431
TL
256 struct hardware *hardware;
257{
b1b7b521 258 const char *val;
02a015fb 259 enum dhcp_token token;
e703795d 260 unsigned hlen;
63115431
TL
261 unsigned char *t;
262
263 token = next_token (&val, cfile);
264 switch (token) {
265 case ETHERNET:
9fb2fb28 266 hardware -> hbuf [0] = HTYPE_ETHER;
63115431
TL
267 break;
268 case TOKEN_RING:
9fb2fb28 269 hardware -> hbuf [0] = HTYPE_IEEE802;
63115431 270 break;
cea8b5c9 271 case FDDI:
9fb2fb28 272 hardware -> hbuf [0] = HTYPE_FDDI;
cea8b5c9 273 break;
63115431 274 default:
4615d498 275 parse_warn (cfile, "expecting a network hardware type");
63115431
TL
276 skip_to_semi (cfile);
277 return;
278 }
279
280 /* Parse the hardware address information. Technically,
281 it would make a lot of sense to restrict the length of the
282 data we'll accept here to the length of a particular hardware
283 address type. Unfortunately, there are some broken clients
284 out there that put bogus data in the chaddr buffer, and we accept
285 that data in the lease file rather than simply failing on such
286 clients. Yuck. */
287 hlen = 0;
288 t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen,
289 COLON, 16, 8);
290 if (!t)
291 return;
9fb2fb28 292 if (hlen + 1 > sizeof hardware -> hbuf) {
fdac15d9 293 dfree (t, MDL);
4615d498 294 parse_warn (cfile, "hardware address too long");
63115431 295 } else {
9fb2fb28
TL
296 hardware -> hlen = hlen + 1;
297 memcpy ((unsigned char *)&hardware -> hbuf [1], t, hlen);
298 if (hlen + 1 < sizeof hardware -> hbuf)
299 memset (&hardware -> hbuf [hlen + 1], 0,
300 (sizeof hardware -> hbuf) - hlen - 1);
fdac15d9 301 dfree (t, MDL);
63115431
TL
302 }
303
304 token = next_token (&val, cfile);
305 if (token != SEMI) {
4615d498 306 parse_warn (cfile, "expecting semicolon.");
63115431
TL
307 skip_to_semi (cfile);
308 }
309}
310
311/* lease-time :== NUMBER SEMI */
312
313void parse_lease_time (cfile, timep)
4615d498 314 struct parse *cfile;
63115431
TL
315 TIME *timep;
316{
b1b7b521 317 const char *val;
02a015fb 318 enum dhcp_token token;
63115431
TL
319
320 token = next_token (&val, cfile);
321 if (token != NUMBER) {
4615d498 322 parse_warn (cfile, "Expecting numeric lease time");
63115431
TL
323 skip_to_semi (cfile);
324 return;
325 }
4615d498 326 convert_num (cfile, (unsigned char *)timep, val, 10, 32);
63115431
TL
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)
4615d498 342 struct parse *cfile;
63115431 343 unsigned char *buf;
b1b7b521 344 unsigned *max;
63115431
TL
345 int seperator;
346 int base;
b1b7b521 347 unsigned size;
63115431 348{
b1b7b521 349 const char *val;
02a015fb 350 enum dhcp_token token;
63115431 351 unsigned char *bufp = buf, *s, *t;
b1b7b521 352 unsigned count = 0;
63115431
TL
353 pair c = (pair)0;
354
355 if (!bufp && *max) {
fdac15d9 356 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
63115431 357 if (!bufp)
1ff8f8ea
TL
358 log_fatal ("no space for numeric aggregate");
359 s = 0;
63115431
TL
360 } else
361 s = bufp;
362
363 do {
364 if (count) {
365 token = peek_token (&val, cfile);
366 if (token != seperator) {
367 if (!*max)
368 break;
369 if (token != RBRACE && token != LBRACE)
370 token = next_token (&val, cfile);
4615d498 371 parse_warn (cfile, "too few numbers.");
63115431
TL
372 if (token != SEMI)
373 skip_to_semi (cfile);
374 return (unsigned char *)0;
375 }
376 token = next_token (&val, cfile);
377 }
378 token = next_token (&val, cfile);
379
380 if (token == EOF) {
4615d498 381 parse_warn (cfile, "unexpected end of file");
63115431
TL
382 break;
383 }
384
385 /* Allow NUMBER_OR_NAME if base is 16. */
386 if (token != NUMBER &&
387 (base != 16 || token != NUMBER_OR_NAME)) {
4615d498 388 parse_warn (cfile, "expecting numeric value.");
63115431
TL
389 skip_to_semi (cfile);
390 return (unsigned char *)0;
391 }
392 /* If we can, convert the number now; otherwise, build
393 a linked list of all the numbers. */
394 if (s) {
4615d498 395 convert_num (cfile, s, val, base, size);
63115431
TL
396 s += size / 8;
397 } else {
fdac15d9 398 t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
63115431 399 if (!t)
8ae2d595 400 log_fatal ("no temp space for number.");
338303a4
TL
401 strcpy ((char *)t, val);
402 c = cons ((caddr_t)t, c);
63115431
TL
403 }
404 } while (++count != *max);
405
406 /* If we had to cons up a list, convert it now. */
407 if (c) {
fdac15d9 408 bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
63115431 409 if (!bufp)
1ff8f8ea 410 log_fatal ("no space for numeric aggregate.");
63115431
TL
411 s = bufp + count - size / 8;
412 *max = count;
413 }
414 while (c) {
415 pair cdr = c -> cdr;
4615d498 416 convert_num (cfile, s, (char *)(c -> car), base, size);
63115431
TL
417 s -= size / 8;
418 /* Free up temp space. */
fdac15d9
TL
419 dfree (c -> car, MDL);
420 dfree (c, MDL);
63115431
TL
421 c = cdr;
422 }
423 return bufp;
424}
425
4615d498
TL
426void convert_num (cfile, buf, str, base, size)
427 struct parse *cfile;
63115431 428 unsigned char *buf;
b1b7b521 429 const char *str;
63115431 430 int base;
b1b7b521 431 unsigned size;
63115431 432{
b1b7b521 433 const char *ptr = str;
63115431
TL
434 int negative = 0;
435 u_int32_t val = 0;
436 int tval;
437 int max;
438
439 if (*ptr == '-') {
440 negative = 1;
441 ++ptr;
442 }
443
444 /* If base wasn't specified, figure it out from the data. */
445 if (!base) {
446 if (ptr [0] == '0') {
447 if (ptr [1] == 'x') {
448 base = 16;
449 ptr += 2;
450 } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
451 base = 8;
452 ptr += 1;
453 } else {
454 base = 10;
455 }
456 } else {
457 base = 10;
458 }
459 }
460
461 do {
462 tval = *ptr++;
463 /* XXX assumes ASCII... */
464 if (tval >= 'a')
465 tval = tval - 'a' + 10;
466 else if (tval >= 'A')
467 tval = tval - 'A' + 10;
468 else if (tval >= '0')
469 tval -= '0';
470 else {
4615d498 471 parse_warn (cfile, "Bogus number: %s.", str);
63115431
TL
472 break;
473 }
474 if (tval >= base) {
4615d498
TL
475 parse_warn (cfile,
476 "Bogus number %s: digit %d not in base %d",
f420e08c 477 str, tval, base);
63115431
TL
478 break;
479 }
480 val = val * base + tval;
481 } while (*ptr);
482
483 if (negative)
484 max = (1 << (size - 1));
485 else
486 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
487 if (val > max) {
488 switch (base) {
489 case 8:
4615d498 490 parse_warn (cfile,
06afba54 491 "%s%lo exceeds max (%d) for precision.",
b3d594dd
TL
492 negative ? "-" : "",
493 (unsigned long)val, max);
63115431
TL
494 break;
495 case 16:
4615d498 496 parse_warn (cfile,
06afba54 497 "%s%lx exceeds max (%d) for precision.",
b3d594dd
TL
498 negative ? "-" : "",
499 (unsigned long)val, max);
63115431
TL
500 break;
501 default:
4615d498 502 parse_warn (cfile,
06afba54 503 "%s%lu exceeds max (%d) for precision.",
b3d594dd
TL
504 negative ? "-" : "",
505 (unsigned long)val, max);
63115431
TL
506 break;
507 }
508 }
509
510 if (negative) {
511 switch (size) {
512 case 8:
513 *buf = -(unsigned long)val;
514 break;
515 case 16:
b1b7b521 516 putShort (buf, -(long)val);
63115431
TL
517 break;
518 case 32:
b1b7b521 519 putLong (buf, -(long)val);
63115431
TL
520 break;
521 default:
4615d498
TL
522 parse_warn (cfile,
523 "Unexpected integer size: %d\n", size);
63115431
TL
524 break;
525 }
526 } else {
527 switch (size) {
528 case 8:
529 *buf = (u_int8_t)val;
530 break;
531 case 16:
532 putUShort (buf, (u_int16_t)val);
533 break;
534 case 32:
535 putULong (buf, val);
536 break;
537 default:
4615d498
TL
538 parse_warn (cfile,
539 "Unexpected integer size: %d\n", size);
63115431
TL
540 break;
541 }
542 }
543}
544
be6be08d
TL
545/*
546 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
a82abfc7
TL
547 * NUMBER COLON NUMBER COLON NUMBER SEMI |
548 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
549 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
be1ee858 550 * NEVER
be6be08d 551 *
a82abfc7
TL
552 * Dates are stored in GMT or with a timezone offset; first number is day
553 * of week; next is year/month/day; next is hours:minutes:seconds on a
554 * 24-hour clock, followed by the timezone offset in seconds, which is
555 * optional.
be6be08d 556 */
63115431
TL
557
558TIME parse_date (cfile)
4615d498 559 struct parse *cfile;
63115431
TL
560{
561 struct tm tm;
562 int guess;
a82abfc7 563 int tzoff, wday, year, mon, mday, hour, min, sec;
b1b7b521 564 const char *val;
02a015fb 565 enum dhcp_token token;
63115431
TL
566 static int months [11] = { 31, 59, 90, 120, 151, 181,
567 212, 243, 273, 304, 334 };
568
be1ee858 569 /* Day of week, or "never"... */
63115431 570 token = next_token (&val, cfile);
be1ee858
TL
571 if (token == NEVER) {
572 if (!parse_semi (cfile))
573 return 0;
574 return MAX_TIME;
575 }
576
63115431 577 if (token != NUMBER) {
4615d498 578 parse_warn (cfile, "numeric day of week expected.");
63115431
TL
579 if (token != SEMI)
580 skip_to_semi (cfile);
581 return (TIME)0;
582 }
a82abfc7 583 wday = atoi (val);
63115431
TL
584
585 /* Year... */
586 token = next_token (&val, cfile);
587 if (token != NUMBER) {
4615d498 588 parse_warn (cfile, "numeric year expected.");
63115431
TL
589 if (token != SEMI)
590 skip_to_semi (cfile);
591 return (TIME)0;
592 }
edca2b1a
TL
593
594 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
595 somebody invents a time machine, I think we can safely disregard
596 it. This actually works around a stupid Y2K bug that was present
597 in a very early beta release of dhcpd. */
a82abfc7
TL
598 year = atoi (val);
599 if (year > 1900)
600 year -= 1900;
63115431
TL
601
602 /* Slash seperating year from month... */
603 token = next_token (&val, cfile);
604 if (token != SLASH) {
4615d498
TL
605 parse_warn (cfile,
606 "expected slash seperating year from month.");
63115431
TL
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) {
4615d498 615 parse_warn (cfile, "numeric month expected.");
63115431
TL
616 if (token != SEMI)
617 skip_to_semi (cfile);
618 return (TIME)0;
619 }
a82abfc7 620 mon = atoi (val) - 1;
63115431
TL
621
622 /* Slash seperating month from day... */
623 token = next_token (&val, cfile);
624 if (token != SLASH) {
4615d498
TL
625 parse_warn (cfile,
626 "expected slash seperating month from day.");
63115431
TL
627 if (token != SEMI)
628 skip_to_semi (cfile);
629 return (TIME)0;
630 }
631
632 /* Month... */
633 token = next_token (&val, cfile);
634 if (token != NUMBER) {
4615d498 635 parse_warn (cfile, "numeric day of month expected.");
63115431
TL
636 if (token != SEMI)
637 skip_to_semi (cfile);
638 return (TIME)0;
639 }
a82abfc7 640 mday = atoi (val);
63115431
TL
641
642 /* Hour... */
643 token = next_token (&val, cfile);
644 if (token != NUMBER) {
4615d498 645 parse_warn (cfile, "numeric hour expected.");
63115431
TL
646 if (token != SEMI)
647 skip_to_semi (cfile);
648 return (TIME)0;
649 }
a82abfc7 650 hour = atoi (val);
63115431
TL
651
652 /* Colon seperating hour from minute... */
653 token = next_token (&val, cfile);
654 if (token != COLON) {
4615d498
TL
655 parse_warn (cfile,
656 "expected colon seperating hour from minute.");
63115431
TL
657 if (token != SEMI)
658 skip_to_semi (cfile);
659 return (TIME)0;
660 }
661
662 /* Minute... */
663 token = next_token (&val, cfile);
664 if (token != NUMBER) {
4615d498 665 parse_warn (cfile, "numeric minute expected.");
63115431
TL
666 if (token != SEMI)
667 skip_to_semi (cfile);
668 return (TIME)0;
669 }
a82abfc7 670 min = atoi (val);
63115431
TL
671
672 /* Colon seperating minute from second... */
673 token = next_token (&val, cfile);
674 if (token != COLON) {
4615d498
TL
675 parse_warn (cfile,
676 "expected colon seperating hour from minute.");
63115431
TL
677 if (token != SEMI)
678 skip_to_semi (cfile);
679 return (TIME)0;
680 }
681
682 /* Minute... */
683 token = next_token (&val, cfile);
684 if (token != NUMBER) {
4615d498 685 parse_warn (cfile, "numeric minute expected.");
63115431
TL
686 if (token != SEMI)
687 skip_to_semi (cfile);
688 return (TIME)0;
689 }
a82abfc7 690 sec = atoi (val);
63115431 691
a82abfc7
TL
692 token = peek_token (&val, cfile);
693 if (token == NUMBER) {
694 token = next_token (&val, cfile);
695 tzoff = atoi (val);
696 } else
697 tzoff = 0;
63115431
TL
698
699 /* Make sure the date ends in a semicolon... */
25541f2f 700 if (!parse_semi (cfile))
63115431 701 return 0;
63115431
TL
702
703 /* Guess the time value... */
a82abfc7
TL
704 guess = ((((((365 * (year - 70) + /* Days in years since '70 */
705 (year - 69) / 4 + /* Leap days since '70 */
706 (mon /* Days in months this year */
707 ? months [mon - 1]
63115431 708 : 0) +
a82abfc7
TL
709 (mon > 1 && /* Leap day this year */
710 !((year - 72) & 3)) +
711 mday - 1) * 24) + /* Day of month */
712 hour) * 60) +
713 min) * 60) + sec + tzoff;
63115431
TL
714
715 /* This guess could be wrong because of leap seconds or other
716 weirdness we don't know about that the system does. For
717 now, we're just going to accept the guess, but at some point
718 it might be nice to do a successive approximation here to
719 get an exact value. Even if the error is small, if the
720 server is restarted frequently (and thus the lease database
721 is reread), the error could accumulate into something
722 significant. */
723
724 return guess;
725}
4761e04b 726
be6be08d
TL
727/*
728 * option-name :== IDENTIFIER |
729 IDENTIFIER . IDENTIFIER
730 */
731
b1b7b521 732struct option *parse_option_name (cfile, allocate, known)
4615d498 733 struct parse *cfile;
6b4b0ec7 734 int allocate;
b1b7b521 735 int *known;
4761e04b 736{
b1b7b521 737 const char *val;
02a015fb 738 enum dhcp_token token;
6b4b0ec7 739 char *uname;
4761e04b
TL
740 struct universe *universe;
741 struct option *option;
742
743 token = next_token (&val, cfile);
744 if (!is_identifier (token)) {
4615d498
TL
745 parse_warn (cfile,
746 "expecting identifier after option keyword.");
4761e04b
TL
747 if (token != SEMI)
748 skip_to_semi (cfile);
749 return (struct option *)0;
750 }
fdac15d9 751 uname = dmalloc (strlen (val) + 1, MDL);
6b4b0ec7
TL
752 if (!uname)
753 log_fatal ("no memory for uname information.");
754 strcpy (uname, val);
4761e04b
TL
755 token = peek_token (&val, cfile);
756 if (token == DOT) {
757 /* Go ahead and take the DOT token... */
758 token = next_token (&val, cfile);
759
760 /* The next token should be an identifier... */
761 token = next_token (&val, cfile);
762 if (!is_identifier (token)) {
4615d498 763 parse_warn (cfile, "expecting identifier after '.'");
4761e04b
TL
764 if (token != SEMI)
765 skip_to_semi (cfile);
766 return (struct option *)0;
767 }
768
769 /* Look up the option name hash table for the specified
6b4b0ec7 770 uname. */
4761e04b
TL
771 universe = ((struct universe *)
772 hash_lookup (&universe_hash,
6b4b0ec7 773 (unsigned char *)uname, 0));
4761e04b
TL
774 /* If it's not there, we can't parse the rest of the
775 declaration. */
776 if (!universe) {
4615d498 777 parse_warn (cfile, "no option space named %s.", uname);
4761e04b
TL
778 skip_to_semi (cfile);
779 return (struct option *)0;
780 }
781 } else {
782 /* Use the default hash table, which contains all the
783 standard dhcp option names. */
6b4b0ec7 784 val = uname;
4761e04b
TL
785 universe = &dhcp_universe;
786 }
787
788 /* Look up the actual option info... */
789 option = (struct option *)hash_lookup (universe -> hash,
b1b7b521 790 (const unsigned char *)val, 0);
4761e04b
TL
791
792 /* If we didn't get an option structure, it's an undefined option. */
b1b7b521
TL
793 if (option) {
794 *known = 1;
795 } else {
6b4b0ec7
TL
796 /* If we've been told to allocate, that means that this
797 (might) be an option code definition, so we'll create
798 an option structure just in case. */
799 if (allocate) {
4bd8800e 800 option = new_option (MDL);
6b4b0ec7
TL
801 if (val == uname)
802 option -> name = val;
803 else {
b1b7b521 804 char *s;
fdac15d9
TL
805 dfree (uname, MDL);
806 s = dmalloc (strlen (val) + 1, MDL);
b1b7b521 807 if (!s)
4615d498
TL
808 log_fatal ("no memory for option %s.%s",
809 universe -> name, val);
b1b7b521
TL
810 strcpy (s, val);
811 option -> name = s;
6b4b0ec7
TL
812 }
813 option -> universe = universe;
b1b7b521 814 option -> code = 0;
6b4b0ec7
TL
815 return option;
816 }
817 if (val == uname)
4615d498 818 parse_warn (cfile, "no option named %s", val);
4761e04b 819 else
4615d498 820 parse_warn (cfile, "no option named %s in space %s",
6b4b0ec7 821 val, uname);
4761e04b
TL
822 skip_to_semi (cfile);
823 return (struct option *)0;
824 }
825
826 /* Free the initial identifier token. */
fdac15d9 827 dfree (uname, MDL);
4761e04b
TL
828 return option;
829}
830
52c9d530
TL
831/* IDENTIFIER SEMI */
832
833void parse_option_space_decl (cfile)
4615d498 834 struct parse *cfile;
52c9d530
TL
835{
836 int token;
b1b7b521 837 const char *val;
52c9d530 838 struct universe **ua, *nu;
b1b7b521 839 char *s;
52c9d530
TL
840
841 next_token (&val, cfile); /* Discard the SPACE token, which was
842 checked by the caller. */
843 token = next_token (&val, cfile);
844 if (!is_identifier (token)) {
4615d498 845 parse_warn (cfile, "expecting identifier.");
52c9d530
TL
846 skip_to_semi (cfile);
847 return;
848 }
4bd8800e 849 nu = new_universe (MDL);
52c9d530
TL
850 if (!nu)
851 log_fatal ("No memory for new option space.");
852
853 /* Set up the server option universe... */
fdac15d9 854 s = dmalloc (strlen (val) + 1, MDL);
b1b7b521 855 if (!s)
52c9d530 856 log_fatal ("No memory for new option space name.");
b1b7b521
TL
857 strcpy (s, val);
858 nu -> name = s;
52c9d530
TL
859 nu -> lookup_func = lookup_hashed_option;
860 nu -> option_state_dereference =
861 hashed_option_state_dereference;
862 nu -> get_func = hashed_option_get;
863 nu -> set_func = hashed_option_set;
864 nu -> save_func = save_hashed_option;
865 nu -> delete_func = delete_hashed_option;
866 nu -> encapsulate = hashed_option_space_encapsulate;
867 nu -> length_size = 1;
868 nu -> tag_size = 1;
869 nu -> store_tag = putUChar;
870 nu -> store_length = putUChar;
871 nu -> index = universe_count++;
872 if (nu -> index >= universe_max) {
fdac15d9 873 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
52c9d530
TL
874 if (!ua)
875 log_fatal ("No memory to expand option space array.");
876 memcpy (ua, universes, universe_max * sizeof *ua);
877 universe_max *= 2;
fdac15d9 878 dfree (universes, MDL);
52c9d530
TL
879 universes = ua;
880 }
881 universes [nu -> index] = nu;
882 nu -> hash = new_hash ();
883 if (!nu -> hash)
884 log_fatal ("Can't allocate %s option hash table.", nu -> name);
885 add_hash (&universe_hash,
b1b7b521 886 (const unsigned char *)nu -> name, 0, (unsigned char *)nu);
52c9d530
TL
887 parse_semi (cfile);
888}
889
6b4b0ec7
TL
890/* This is faked up to look good right now. Ideally, this should do a
891 recursive parse and allow arbitrary data structure definitions, but for
892 now it just allows you to specify a single type, an array of single types,
893 a sequence of types, or an array of sequences of types.
894
895 ocd :== NUMBER EQUALS ocsd SEMI
896
897 ocsd :== ocsd_type |
898 ocsd_type_sequence |
899 ARRAY OF ocsd_type |
900 ARRAY OF ocsd_type_sequence
901
902 ocsd_type :== BOOLEAN |
903 INTEGER NUMBER |
904 SIGNED INTEGER NUMBER |
905 UNSIGNED INTEGER NUMBER |
906 IP-ADDRESS |
907 TEXT |
908 STRING
909
910 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
911
912 ocsd_type :== ocsd_type |
913 ocsd_types ocsd_type */
914
915int parse_option_code_definition (cfile, option)
4615d498 916 struct parse *cfile;
6b4b0ec7
TL
917 struct option *option;
918{
b1b7b521 919 const char *val;
6b4b0ec7 920 enum dhcp_token token;
b1b7b521 921 unsigned arrayp = 0;
6b4b0ec7
TL
922 int recordp = 0;
923 int no_more_in_record = 0;
924 char tokbuf [128];
b1b7b521 925 unsigned tokix = 0;
6b4b0ec7
TL
926 char type;
927 int code;
928 int is_signed;
b1b7b521 929 char *s;
6b4b0ec7
TL
930
931 /* Parse the option code. */
932 token = next_token (&val, cfile);
933 if (token != NUMBER) {
4615d498 934 parse_warn (cfile, "expecting option code number.");
6b4b0ec7
TL
935 skip_to_semi (cfile);
936 return 0;
937 }
938 option -> code = atoi (val);
939
940 token = next_token (&val, cfile);
941 if (token != EQUAL) {
4615d498 942 parse_warn (cfile, "expecting \"=\"");
6b4b0ec7
TL
943 skip_to_semi (cfile);
944 return 0;
945 }
946
947 /* See if this is an array. */
948 token = next_token (&val, cfile);
949 if (token == ARRAY) {
950 token = next_token (&val, cfile);
951 if (token != OF) {
4615d498 952 parse_warn (cfile, "expecting \"of\".");
6b4b0ec7
TL
953 skip_to_semi (cfile);
954 return 0;
955 }
956 arrayp = 1;
957 token = next_token (&val, cfile);
958 }
959
960 if (token == LBRACE) {
961 recordp = 1;
962 token = next_token (&val, cfile);
963 }
964
965 /* At this point we're expecting a data type. */
966 next_type:
967 switch (token) {
968 case BOOLEAN:
969 type = 'f';
970 break;
971 case INTEGER:
972 is_signed = 1;
973 parse_integer:
974 token = next_token (&val, cfile);
975 if (token != NUMBER) {
4615d498 976 parse_warn (cfile, "expecting number.");
6b4b0ec7
TL
977 skip_to_rbrace (cfile, recordp);
978 if (recordp)
979 skip_to_semi (cfile);
980 return 0;
981 }
982 switch (atoi (val)) {
983 case 8:
984 type = is_signed ? 'b' : 'B';
985 break;
986 case 16:
987 type = is_signed ? 's' : 'S';
988 break;
989 case 32:
990 type = is_signed ? 'l' : 'L';
991 break;
992 default:
4615d498
TL
993 parse_warn (cfile,
994 "%s bit precision is not supported.", val);
6b4b0ec7
TL
995 skip_to_rbrace (cfile, recordp);
996 if (recordp)
997 skip_to_semi (cfile);
998 return 0;
999 }
1000 break;
1001 case SIGNED:
1002 is_signed = 1;
1003 parse_signed:
1004 token = next_token (&val, cfile);
1005 if (token != INTEGER) {
4615d498 1006 parse_warn (cfile, "expecting \"integer\" keyword.");
6b4b0ec7
TL
1007 skip_to_rbrace (cfile, recordp);
1008 if (recordp)
1009 skip_to_semi (cfile);
1010 return 0;
1011 }
1012 goto parse_integer;
1013 case UNSIGNED:
1014 is_signed = 0;
1015 goto parse_signed;
1016
1017 case IP_ADDRESS:
1018 type = 'I';
1019 break;
1020 case TEXT:
1021 type = 't';
1022 no_arrays:
1023 if (arrayp) {
4615d498 1024 parse_warn (cfile, "arrays of text strings not %s",
6b4b0ec7
TL
1025 "yet supported.");
1026 skip_to_rbrace (cfile, recordp);
1027 if (recordp)
1028 skip_to_semi (cfile);
1029 return 0;
1030 }
1031 no_more_in_record = 1;
1032 break;
1033 case STRING:
1034 type = 'X';
1035 goto no_arrays;
1036
1037 default:
4615d498 1038 parse_warn (cfile, "unknown data type %s", val);
6b4b0ec7
TL
1039 skip_to_rbrace (cfile, recordp);
1040 if (recordp)
1041 skip_to_semi (cfile);
1042 return 0;
1043 }
1044
1045 if (tokix == sizeof tokbuf) {
4615d498 1046 parse_warn (cfile, "too many types in record.");
6b4b0ec7
TL
1047 skip_to_rbrace (cfile, recordp);
1048 if (recordp)
1049 skip_to_semi (cfile);
1050 return 0;
1051 }
1052 tokbuf [tokix++] = type;
1053
1054 if (recordp) {
1055 token = next_token (&val, cfile);
1056 if (token == COMMA) {
1057 if (no_more_in_record) {
4615d498
TL
1058 parse_warn (cfile,
1059 "%s must be at end of record.",
6b4b0ec7
TL
1060 type == 't' ? "text" : "string");
1061 skip_to_rbrace (cfile, 1);
1062 if (recordp)
1063 skip_to_semi (cfile);
1064 return 0;
1065 }
1066 token = next_token (&val, cfile);
1067 goto next_type;
1068 }
1069 if (token != RBRACE) {
4615d498 1070 parse_warn (cfile, "expecting right brace.");
6b4b0ec7
TL
1071 skip_to_rbrace (cfile, 1);
1072 if (recordp)
1073 skip_to_semi (cfile);
1074 return 0;
1075 }
1076 }
1077 if (!parse_semi (cfile)) {
4615d498 1078 parse_warn (cfile, "semicolon expected.");
6b4b0ec7
TL
1079 skip_to_semi (cfile);
1080 if (recordp)
1081 skip_to_semi (cfile);
1082 return 0;
1083 }
fdac15d9 1084 s = dmalloc (tokix + arrayp + 1, MDL);
b1b7b521 1085 if (!s)
6b4b0ec7 1086 log_fatal ("no memory for option format.");
b1b7b521 1087 memcpy (s, tokbuf, tokix);
6b4b0ec7 1088 if (arrayp)
b1b7b521
TL
1089 s [tokix++] = 'A';
1090 s [tokix] = 0;
1091 option -> format = s;
6b4b0ec7
TL
1092 if (option -> universe -> options [option -> code]) {
1093 /* XXX Free the option, but we can't do that now because they
1094 XXX may start out static. */
1095 }
1096 option -> universe -> options [option -> code] = option;
1097 add_hash (option -> universe -> hash,
b1b7b521
TL
1098 (const unsigned char *)option -> name,
1099 0, (unsigned char *)option);
6b4b0ec7
TL
1100 return 1;
1101}
1102
be6be08d
TL
1103/*
1104 * colon-seperated-hex-list :== NUMBER |
1105 * NUMBER COLON colon-seperated-hex-list
1106 */
1107
02a015fb
TL
1108int parse_cshl (data, cfile)
1109 struct data_string *data;
4615d498 1110 struct parse *cfile;
4761e04b 1111{
c5b0f529 1112 u_int8_t ibuf [128];
b1b7b521
TL
1113 unsigned ilen = 0;
1114 unsigned tlen = 0;
4761e04b
TL
1115 struct option_tag *sl = (struct option_tag *)0;
1116 struct option_tag *next, **last = &sl;
02a015fb 1117 enum dhcp_token token;
b1b7b521 1118 const char *val;
02a015fb 1119 unsigned char *rvp;
4761e04b
TL
1120
1121 do {
1122 token = next_token (&val, cfile);
1123 if (token != NUMBER && token != NUMBER_OR_NAME) {
4615d498 1124 parse_warn (cfile, "expecting hexadecimal number.");
4761e04b
TL
1125 skip_to_semi (cfile);
1126 for (; sl; sl = next) {
1127 next = sl -> next;
fdac15d9 1128 dfree (sl, MDL);
4761e04b 1129 }
02a015fb 1130 return 0;
4761e04b
TL
1131 }
1132 if (ilen == sizeof ibuf) {
1133 next = (struct option_tag *)
1134 dmalloc (ilen - 1 +
fdac15d9 1135 sizeof (struct option_tag), MDL);
4761e04b 1136 if (!next)
8ae2d595 1137 log_fatal ("no memory for string list.");
4761e04b
TL
1138 memcpy (next -> data, ibuf, ilen);
1139 *last = next;
1140 last = &next -> next;
1141 tlen += ilen;
1142 ilen = 0;
1143 }
4615d498 1144 convert_num (cfile, &ibuf [ilen++], val, 16, 8);
4761e04b
TL
1145
1146 token = peek_token (&val, cfile);
1147 if (token != COLON)
1148 break;
1149 token = next_token (&val, cfile);
1150 } while (1);
1151
4bd8800e 1152 if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
8ae2d595 1153 log_fatal ("no memory to store octet data.");
02a015fb
TL
1154 data -> data = &data -> buffer -> data [0];
1155 data -> len = tlen + ilen;
1156 data -> terminated = 0;
1157
b1b7b521 1158 rvp = &data -> buffer -> data [0];
4761e04b
TL
1159 while (sl) {
1160 next = sl -> next;
1161 memcpy (rvp, sl -> data, sizeof ibuf);
1162 rvp += sizeof ibuf;
fdac15d9 1163 dfree (sl, MDL);
4761e04b
TL
1164 sl = next;
1165 }
1166
1167 memcpy (rvp, ibuf, ilen);
02a015fb 1168 return 1;
4761e04b 1169}
be6be08d
TL
1170
1171/*
1172 * executable-statements :== executable-statement executable-statements |
1173 * executable-statement
1174 *
1175 * executable-statement :==
1176 * IF if-statement |
1177 * ADD class-name SEMI |
1178 * BREAK SEMI |
1179 * OPTION option-parameter SEMI |
1180 * SUPERSEDE option-parameter SEMI |
1181 * PREPEND option-parameter SEMI |
1182 * APPEND option-parameter SEMI
1183 */
1184
f579f39f 1185int parse_executable_statements (statements, cfile, lose, case_context)
79a65726 1186 struct executable_statement **statements;
4615d498 1187 struct parse *cfile;
be6be08d 1188 int *lose;
f579f39f 1189 enum expression_context case_context;
be6be08d 1190{
79a65726 1191 struct executable_statement **next;
be6be08d 1192
79a65726 1193 next = statements;
f579f39f 1194 while (parse_executable_statement (next, cfile, lose, case_context))
be6be08d 1195 next = &((*next) -> next);
02a015fb 1196 if (!*lose)
79a65726
TL
1197 return 1;
1198 return 0;
be6be08d
TL
1199}
1200
f579f39f 1201int parse_executable_statement (result, cfile, lose, case_context)
79a65726 1202 struct executable_statement **result;
4615d498 1203 struct parse *cfile;
be6be08d 1204 int *lose;
f579f39f 1205 enum expression_context case_context;
be6be08d 1206{
02a015fb 1207 enum dhcp_token token;
b1b7b521 1208 const char *val;
79a65726 1209 struct executable_statement base;
be6be08d
TL
1210 struct class *cta;
1211 struct option *option;
b1013db7 1212 struct option_cache *cache;
b1b7b521 1213 int known;
0776fd12 1214 int flag;
be6be08d 1215
b1013db7
TL
1216 token = peek_token (&val, cfile);
1217 switch (token) {
be6be08d 1218 case IF:
dce70f9f 1219 next_token (&val, cfile);
79a65726
TL
1220 return parse_if_statement (result, cfile, lose);
1221
eb018e2b 1222 case TOKEN_ADD:
efc79acb 1223 token = next_token (&val, cfile);
be6be08d
TL
1224 token = next_token (&val, cfile);
1225 if (token != STRING) {
4615d498 1226 parse_warn (cfile, "expecting class name.");
be6be08d
TL
1227 skip_to_semi (cfile);
1228 *lose = 1;
79a65726 1229 return 0;
be6be08d
TL
1230 }
1231 cta = find_class (val);
1232 if (!cta) {
4615d498 1233 parse_warn (cfile, "unknown class %s.", val);
be6be08d
TL
1234 skip_to_semi (cfile);
1235 *lose = 1;
79a65726 1236 return 0;
be6be08d
TL
1237 }
1238 if (!parse_semi (cfile)) {
1239 *lose = 1;
79a65726 1240 return 0;
be6be08d 1241 }
4bd8800e 1242 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1243 log_fatal ("no memory for new statement.");
1244 (*result) -> op = add_statement;
1245 (*result) -> data.add = cta;
be6be08d
TL
1246 break;
1247
1248 case BREAK:
1249 token = next_token (&val, cfile);
1250 if (!parse_semi (cfile)) {
1251 *lose = 1;
79a65726 1252 return 0;
be6be08d 1253 }
4bd8800e 1254 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1255 log_fatal ("no memory for new statement.");
1256 (*result) -> op = break_statement;
be6be08d
TL
1257 break;
1258
25541f2f
TL
1259 case SEND:
1260 *lose = 1;
4615d498 1261 parse_warn (cfile, "send not appropriate here.");
25541f2f 1262 skip_to_semi (cfile);
79a65726 1263 return 0;
25541f2f
TL
1264
1265 case SUPERSEDE:
be6be08d
TL
1266 case OPTION:
1267 token = next_token (&val, cfile);
b1b7b521
TL
1268 known = 0;
1269 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1270 if (!option) {
1271 *lose = 1;
79a65726 1272 return 0;
be6be08d 1273 }
79a65726 1274 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1275 supersede_option_statement);
1276
b1013db7 1277 case ALLOW:
0776fd12
TL
1278 flag = 1;
1279 goto pad;
b1013db7 1280 case DENY:
0776fd12
TL
1281 flag = 0;
1282 goto pad;
1283 case IGNORE:
1284 flag = 2;
1285 pad:
b1013db7
TL
1286 token = next_token (&val, cfile);
1287 cache = (struct option_cache *)0;
2db25842 1288 if (!parse_allow_deny (&cache, cfile, flag))
79a65726 1289 return 0;
4bd8800e 1290 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1291 log_fatal ("no memory for new statement.");
1292 (*result) -> op = supersede_option_statement;
1293 (*result) -> data.option = cache;
b1013db7
TL
1294 break;
1295
be6be08d
TL
1296 case DEFAULT:
1297 token = next_token (&val, cfile);
f579f39f
TL
1298 token = peek_token (&val, cfile);
1299 if (token == COLON)
1300 goto switch_default;
b1b7b521
TL
1301 known = 0;
1302 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1303 if (!option) {
1304 *lose = 1;
79a65726 1305 return 0;
be6be08d 1306 }
79a65726 1307 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1308 default_option_statement);
1309
1310 case PREPEND:
1311 token = next_token (&val, cfile);
b1b7b521
TL
1312 known = 0;
1313 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1314 if (!option) {
1315 *lose = 1;
79a65726 1316 return 0;
be6be08d 1317 }
79a65726 1318 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1319 prepend_option_statement);
1320
1321 case APPEND:
1322 token = next_token (&val, cfile);
b1b7b521
TL
1323 known = 0;
1324 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1325 if (!option) {
1326 *lose = 1;
79a65726 1327 return 0;
be6be08d 1328 }
79a65726 1329 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1330 append_option_statement);
1331
79a65726
TL
1332 case ON:
1333 token = next_token (&val, cfile);
79a65726
TL
1334 return parse_on_statement (result, cfile, lose);
1335
f579f39f
TL
1336 case SWITCH:
1337 token = next_token (&val, cfile);
1338 return parse_switch_statement (result, cfile, lose);
1339
1340 case CASE:
1341 token = next_token (&val, cfile);
1342 if (case_context == context_any) {
1343 parse_warn (cfile,
1344 "case statement in inappropriate scope.");
1345 *lose = 1;
1346 skip_to_semi (cfile);
1347 return 0;
1348 }
1349 return parse_case_statement (result,
1350 cfile, lose, case_context);
1351
1352 switch_default:
1353 token = next_token (&val, cfile);
1354 if (case_context == context_any) {
1355 parse_warn (cfile, "switch default statement in %s",
1356 "inappropriate scope.");
1357
1358 *lose = 1;
1359 return 0;
1360 } else {
4bd8800e 1361 if (!executable_statement_allocate (result, MDL))
f579f39f
TL
1362 log_fatal ("no memory for default statement.");
1363 (*result) -> op = default_statement;
1364 return 1;
1365 }
1366
1367 case TOKEN_SET:
1368 token = next_token (&val, cfile);
f579f39f
TL
1369
1370 token = next_token (&val, cfile);
1371 if (token != NAME && token != NUMBER_OR_NAME) {
1372 parse_warn (cfile,
1373 "%s can't be a variable name", val);
1374 badset:
1375 skip_to_semi (cfile);
1376 *lose = 1;
1377 return 0;
1378 }
1379
4bd8800e 1380 if (!executable_statement_allocate (result, MDL))
f579f39f 1381 log_fatal ("no memory for set statement.");
fdac15d9
TL
1382 (*result) -> op = set_statement;
1383 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
f579f39f
TL
1384 if (!(*result)->data.set.name)
1385 log_fatal ("can't allocate variable name");
1386 strcpy ((*result) -> data.set.name, val);
1387 token = next_token (&val, cfile);
1388 if (token != EQUAL) {
1389 parse_warn (cfile, "expecting '=' in set statement.");
1390 goto badset;
1391 }
1392
1393 if (!parse_expression (&(*result) -> data.set.expr,
1394 cfile, lose, context_data, /* XXX */
1395 (struct expression **)0, expr_none)) {
1396 if (!*lose)
1397 parse_warn (cfile,
1398 "expecting data expression.");
1399 else
1400 *lose = 1;
1401 skip_to_semi (cfile);
4bd8800e 1402 executable_statement_dereference (result, MDL);
f579f39f
TL
1403 return 0;
1404 }
1405 parse_semi (cfile);
1406 break;
1407
fdac15d9
TL
1408 case UNSET:
1409 token = next_token (&val, cfile);
1410
1411 token = next_token (&val, cfile);
1412 if (token != NAME && token != NUMBER_OR_NAME) {
1413 parse_warn (cfile,
1414 "%s can't be a variable name", val);
1415 badunset:
1416 skip_to_semi (cfile);
1417 *lose = 1;
1418 return 0;
1419 }
1420
4bd8800e 1421 if (!executable_statement_allocate (result, MDL))
fdac15d9
TL
1422 log_fatal ("no memory for set statement.");
1423 (*result) -> op = unset_statement;
1424 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
1425 if (!(*result)->data.unset)
1426 log_fatal ("can't allocate variable name");
1427 strcpy ((*result) -> data.unset, val);
1428 parse_semi (cfile);
1429 break;
1430
1431 case EVAL:
1432 token = next_token (&val, cfile);
1433
4bd8800e 1434 if (!executable_statement_allocate (result, MDL))
fdac15d9
TL
1435 log_fatal ("no memory for eval statement.");
1436 (*result) -> op = eval_statement;
1437
1438 if (!parse_expression (&(*result) -> data.eval,
1439 cfile, lose, context_data, /* XXX */
1440 (struct expression **)0, expr_none)) {
1441 if (!*lose)
1442 parse_warn (cfile,
1443 "expecting data expression.");
1444 else
1445 *lose = 1;
1446 skip_to_semi (cfile);
4bd8800e 1447 executable_statement_dereference (result, MDL);
fdac15d9
TL
1448 return 0;
1449 }
1450 parse_semi (cfile);
1451 break;
1452
be6be08d
TL
1453 default:
1454 *lose = 0;
79a65726 1455 return 0;
be6be08d
TL
1456 }
1457
79a65726
TL
1458 return 1;
1459}
1460
1461/*
f579f39f
TL
1462 * on-statement :== event-types LBRACE executable-statements RBRACE
1463 * event-types :== event-type OR event-types |
1464 * event-type
79a65726
TL
1465 * event-type :== EXPIRY | COMMIT | RELEASE
1466 */
1467
1468int parse_on_statement (result, cfile, lose)
1469 struct executable_statement **result;
4615d498 1470 struct parse *cfile;
79a65726
TL
1471 int *lose;
1472{
1473 enum dhcp_token token;
b1b7b521 1474 const char *val;
79a65726 1475
4bd8800e 1476 if (!executable_statement_allocate (result, MDL))
8ae2d595 1477 log_fatal ("no memory for new statement.");
33500c7d 1478 (*result) -> op = on_statement;
79a65726 1479
f579f39f
TL
1480 do {
1481 token = next_token (&val, cfile);
1482 switch (token) {
1483 case EXPIRY:
1484 (*result) -> data.on.evtypes |= ON_EXPIRY;
1485 break;
79a65726 1486
f579f39f 1487 case COMMIT:
fdac15d9 1488 (*result) -> data.on.evtypes |= ON_COMMIT;
f579f39f
TL
1489 break;
1490
1491 case RELEASE:
fdac15d9 1492 (*result) -> data.on.evtypes |= ON_RELEASE;
f579f39f
TL
1493 break;
1494
1495 default:
1496 parse_warn (cfile, "expecting a lease event type");
1497 skip_to_semi (cfile);
1498 *lose = 1;
4bd8800e 1499 executable_statement_dereference (result, MDL);
fdac15d9 1500 return 0;
f579f39f
TL
1501 }
1502 token = next_token (&val, cfile);
1503 } while (token == OR);
79a65726 1504
f579f39f
TL
1505 /* Semicolon means no statements. */
1506 if (token == SEMI)
1507 return 1;
1508
79a65726 1509 if (token != LBRACE) {
4615d498 1510 parse_warn (cfile, "left brace expected.");
79a65726
TL
1511 skip_to_semi (cfile);
1512 *lose = 1;
4bd8800e 1513 executable_statement_dereference (result, MDL);
79a65726
TL
1514 return 0;
1515 }
1516 if (!parse_executable_statements (&(*result) -> data.on.statements,
f579f39f 1517 cfile, lose, context_any)) {
79a65726
TL
1518 if (*lose) {
1519 /* Try to even things up. */
1520 do {
1521 token = next_token (&val, cfile);
1522 } while (token != EOF && token != RBRACE);
4bd8800e 1523 executable_statement_dereference (result, MDL);
79a65726
TL
1524 return 0;
1525 }
1526 }
1527 token = next_token (&val, cfile);
1528 if (token != RBRACE) {
4615d498 1529 parse_warn (cfile, "right brace expected.");
79a65726
TL
1530 skip_to_semi (cfile);
1531 *lose = 1;
4bd8800e 1532 executable_statement_dereference (result, MDL);
79a65726
TL
1533 return 0;
1534 }
1535 return 1;
be6be08d
TL
1536}
1537
f579f39f
TL
1538/*
1539 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
1540 *
1541 */
1542
1543int parse_switch_statement (result, cfile, lose)
1544 struct executable_statement **result;
1545 struct parse *cfile;
1546 int *lose;
1547{
1548 enum dhcp_token token;
1549 const char *val;
1550
4bd8800e 1551 if (!executable_statement_allocate (result, MDL))
f579f39f
TL
1552 log_fatal ("no memory for new statement.");
1553 (*result) -> op = switch_statement;
1554
1555 token = next_token (&val, cfile);
1556 if (token != LPAREN) {
1557 parse_warn (cfile, "expecting left brace.");
1558 pfui:
1559 *lose = 1;
1560 skip_to_semi (cfile);
1561 gnorf:
4bd8800e 1562 executable_statement_dereference (result, MDL);
f579f39f
TL
1563 return 0;
1564 }
1565
1566 if (!parse_expression (&(*result) -> data.s_switch.expr,
1567 cfile, lose, context_data_or_numeric,
1568 (struct expression **)0, expr_none)) {
1569 if (!*lose) {
1570 parse_warn (cfile,
1571 "expecting data or numeric expression.");
1572 goto pfui;
1573 }
1574 goto gnorf;
1575 }
1576
1577 token = next_token (&val, cfile);
1578 if (token != RPAREN) {
1579 parse_warn (cfile, "right paren expected.");
1580 goto pfui;
1581 }
1582
1583 token = next_token (&val, cfile);
1584 if (token != LBRACE) {
1585 parse_warn (cfile, "left brace expected.");
1586 goto pfui;
1587 }
1588 if (!(parse_executable_statements
1589 (&(*result) -> data.s_switch.statements, cfile, lose,
1590 (is_data_expression ((*result) -> data.s_switch.expr)
1591 ? context_data : context_numeric)))) {
1592 if (*lose) {
1593 skip_to_rbrace (cfile, 1);
4bd8800e 1594 executable_statement_dereference (result, MDL);
f579f39f
TL
1595 return 0;
1596 }
1597 }
1598 token = next_token (&val, cfile);
1599 if (token != RBRACE) {
1600 parse_warn (cfile, "right brace expected.");
1601 goto pfui;
1602 }
1603 return 1;
1604}
1605
1606/*
1607 * case-statement :== CASE expr COLON
1608 *
1609 */
1610
1611int parse_case_statement (result, cfile, lose, case_context)
1612 struct executable_statement **result;
1613 struct parse *cfile;
1614 int *lose;
1615 enum expression_context case_context;
1616{
1617 enum dhcp_token token;
1618 const char *val;
1619
4bd8800e 1620 if (!executable_statement_allocate (result, MDL))
f579f39f
TL
1621 log_fatal ("no memory for new statement.");
1622 (*result) -> op = case_statement;
1623
1624 if (!parse_expression (&(*result) -> data.c_case,
1625 cfile, lose, case_context,
1626 (struct expression **)0, expr_none))
1627 {
1628 if (!*lose) {
1629 parse_warn (cfile, "expecting %s expression.",
1630 (case_context == context_data
1631 ? "data" : "numeric"));
1632 }
1633 pfui:
1634 *lose = 1;
1635 skip_to_semi (cfile);
4bd8800e 1636 executable_statement_dereference (result, MDL);
f579f39f
TL
1637 return 0;
1638 }
1639
1640 token = next_token (&val, cfile);
1641 if (token != COLON) {
1642 parse_warn (cfile, "colon expected.");
1643 goto pfui;
1644 }
1645 return 1;
1646}
1647
be6be08d
TL
1648/*
1649 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
1650 * else-statement
1651 *
1652 * else-statement :== <null> |
1653 * ELSE LBRACE executable-statements RBRACE |
1654 * ELSE IF if-statement |
1655 * ELSIF if-statement
1656 */
1657
79a65726
TL
1658int parse_if_statement (result, cfile, lose)
1659 struct executable_statement **result;
4615d498 1660 struct parse *cfile;
be6be08d
TL
1661 int *lose;
1662{
02a015fb 1663 enum dhcp_token token;
b1b7b521 1664 const char *val;
fdac15d9 1665 int parenp;
be6be08d 1666
4bd8800e 1667 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1668 log_fatal ("no memory for if statement.");
1669
1670 (*result) -> op = if_statement;
1671
fdac15d9
TL
1672 token = peek_token (&val, cfile);
1673 if (token == LPAREN) {
1674 parenp = 1;
1675 next_token (&val, cfile);
1676 } else
1677 parenp = 0;
1678
1679
79a65726
TL
1680 if (!parse_boolean_expression (&(*result) -> data.ie.expr,
1681 cfile, lose)) {
be6be08d 1682 if (!*lose)
4615d498 1683 parse_warn (cfile, "boolean expression expected.");
4bd8800e 1684 executable_statement_dereference (result, MDL);
166e63eb 1685 *lose = 1;
79a65726 1686 return 0;
be6be08d 1687 }
02a015fb
TL
1688#if defined (DEBUG_EXPRESSION_PARSE)
1689 print_expression ("if condition", if_condition);
1690#endif
fdac15d9
TL
1691 if (parenp) {
1692 token = next_token (&val, cfile);
1693 if (token != RPAREN) {
1694 parse_warn (cfile, "expecting right paren.");
1695 *lose = 1;
4bd8800e 1696 executable_statement_dereference (result, MDL);
fdac15d9
TL
1697 return 0;
1698 }
1699 }
be6be08d
TL
1700 token = next_token (&val, cfile);
1701 if (token != LBRACE) {
4615d498 1702 parse_warn (cfile, "left brace expected.");
be6be08d
TL
1703 skip_to_semi (cfile);
1704 *lose = 1;
4bd8800e 1705 executable_statement_dereference (result, MDL);
79a65726 1706 return 0;
be6be08d 1707 }
79a65726 1708 if (!parse_executable_statements (&(*result) -> data.ie.true,
f579f39f 1709 cfile, lose, context_any)) {
79a65726
TL
1710 if (*lose) {
1711 /* Try to even things up. */
1712 do {
1713 token = next_token (&val, cfile);
1714 } while (token != EOF && token != RBRACE);
4bd8800e 1715 executable_statement_dereference (result, MDL);
79a65726
TL
1716 return 0;
1717 }
efc79acb 1718 }
79a65726 1719 token = next_token (&val, cfile);
be6be08d 1720 if (token != RBRACE) {
4615d498 1721 parse_warn (cfile, "right brace expected.");
be6be08d
TL
1722 skip_to_semi (cfile);
1723 *lose = 1;
4bd8800e 1724 executable_statement_dereference (result, MDL);
79a65726 1725 return 0;
be6be08d
TL
1726 }
1727 token = peek_token (&val, cfile);
1728 if (token == ELSE) {
1729 token = next_token (&val, cfile);
1730 token = peek_token (&val, cfile);
1731 if (token == IF) {
1732 token = next_token (&val, cfile);
79a65726
TL
1733 if (!parse_if_statement (&(*result) -> data.ie.false,
1734 cfile, lose)) {
166e63eb
TL
1735 if (!*lose)
1736 parse_warn (cfile,
4bd8800e
TL
1737 "expecting if statement");
1738 executable_statement_dereference (result, MDL);
166e63eb
TL
1739 *lose = 1;
1740 return 0;
79a65726 1741 }
be6be08d 1742 } else if (token != LBRACE) {
4615d498 1743 parse_warn (cfile, "left brace or if expected.");
be6be08d
TL
1744 skip_to_semi (cfile);
1745 *lose = 1;
4bd8800e 1746 executable_statement_dereference (result, MDL);
79a65726 1747 return 0;
be6be08d
TL
1748 } else {
1749 token = next_token (&val, cfile);
33500c7d 1750 if (!(parse_executable_statements
f579f39f
TL
1751 (&(*result) -> data.ie.false,
1752 cfile, lose, context_any))) {
4bd8800e 1753 executable_statement_dereference (result, MDL);
79a65726
TL
1754 return 0;
1755 }
25541f2f
TL
1756 token = next_token (&val, cfile);
1757 if (token != RBRACE) {
4615d498 1758 parse_warn (cfile, "right brace expected.");
25541f2f
TL
1759 skip_to_semi (cfile);
1760 *lose = 1;
4bd8800e 1761 executable_statement_dereference (result, MDL);
79a65726 1762 return 0;
25541f2f 1763 }
be6be08d
TL
1764 }
1765 } else if (token == ELSIF) {
1766 token = next_token (&val, cfile);
79a65726
TL
1767 if (!parse_if_statement (&(*result) -> data.ie.false,
1768 cfile, lose)) {
166e63eb
TL
1769 if (!*lose)
1770 parse_warn (cfile,
1771 "expecting conditional.");
4bd8800e 1772 executable_statement_dereference (result, MDL);
166e63eb
TL
1773 *lose = 1;
1774 return 0;
79a65726 1775 }
be6be08d 1776 } else
79a65726 1777 (*result) -> data.ie.false = (struct executable_statement *)0;
be6be08d 1778
79a65726 1779 return 1;
be6be08d
TL
1780}
1781
1782/*
1783 * boolean_expression :== CHECK STRING |
1784 * NOT boolean-expression |
1785 * data-expression EQUAL data-expression |
2b965a44 1786 * data-expression BANG EQUAL data-expression |
be6be08d
TL
1787 * boolean-expression AND boolean-expression |
1788 * boolean-expression OR boolean-expression
02a015fb 1789 * EXISTS OPTION-NAME
be6be08d
TL
1790 */
1791
02a015fb
TL
1792int parse_boolean_expression (expr, cfile, lose)
1793 struct expression **expr;
4615d498 1794 struct parse *cfile;
02a015fb
TL
1795 int *lose;
1796{
1797 /* Parse an expression... */
1798 if (!parse_expression (expr, cfile, lose, context_boolean,
1799 (struct expression **)0, expr_none))
1800 return 0;
1801
1802 if (!is_boolean_expression (*expr)) {
4615d498 1803 parse_warn (cfile, "Expecting a boolean expression.");
02a015fb 1804 *lose = 1;
4bd8800e 1805 expression_dereference (expr, MDL);
02a015fb
TL
1806 return 0;
1807 }
1808 return 1;
1809}
1810
1811/*
1812 * data_expression :== SUBSTRING LPAREN data-expression COMMA
1813 * numeric-expression COMMA
1814 * numeric-expression RPAREN |
a82abfc7
TL
1815 * CONCAT LPAREN data-expression COMMA
1816 data-expression RPAREN
02a015fb 1817 * SUFFIX LPAREN data_expression COMMA
a82abfc7 1818 * numeric-expression RPAREN |
02a015fb
TL
1819 * OPTION option_name |
1820 * HARDWARE |
1821 * PACKET LPAREN numeric-expression COMMA
1822 * numeric-expression RPAREN |
1823 * STRING |
1824 * colon_seperated_hex_list
1825 */
1826
1827int parse_data_expression (expr, cfile, lose)
1828 struct expression **expr;
4615d498 1829 struct parse *cfile;
02a015fb
TL
1830 int *lose;
1831{
1832 /* Parse an expression... */
1833 if (!parse_expression (expr, cfile, lose, context_data,
1834 (struct expression **)0, expr_none))
1835 return 0;
1836
1837 if (!is_data_expression (*expr)) {
4615d498 1838 parse_warn (cfile, "Expecting a data expression.");
02a015fb
TL
1839 *lose = 1;
1840 return 0;
1841 }
1842 return 1;
1843}
1844
1845/*
1846 * numeric-expression :== EXTRACT_INT LPAREN data-expression
1847 * COMMA number RPAREN |
1848 * NUMBER
1849 */
1850
1851int parse_numeric_expression (expr, cfile, lose)
1852 struct expression **expr;
4615d498 1853 struct parse *cfile;
02a015fb
TL
1854 int *lose;
1855{
1856 /* Parse an expression... */
1857 if (!parse_expression (expr, cfile, lose, context_numeric,
1858 (struct expression **)0, expr_none))
1859 return 0;
1860
1861 if (!is_numeric_expression (*expr)) {
4615d498 1862 parse_warn (cfile, "Expecting a numeric expression.");
02a015fb
TL
1863 *lose = 1;
1864 return 0;
1865 }
1866 return 1;
1867}
1868
9fb2fb28
TL
1869/*
1870 * dns-expression :==
1871 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
1872 * data-expression COMMA numeric-expression RPAREN
1873 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
1874 * data-expression RPAREN
1875 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
1876 * data-expression RPAREN
1877 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
1878 * data-expression RPAREN
1879 * ns-class :== IN | CHAOS | HS | NUMBER
1880 * ns-type :== A | PTR | MX | TXT | NUMBER
1881 */
1882
1883int parse_dns_expression (expr, cfile, lose)
1884 struct expression **expr;
1885 struct parse *cfile;
1886 int *lose;
1887{
1888 /* Parse an expression... */
1889 if (!parse_expression (expr, cfile, lose, context_dns,
1890 (struct expression **)0, expr_none))
1891 return 0;
1892
1893 if (!is_dns_expression (*expr)) {
1894 parse_warn (cfile, "Expecting a dns update subexpression.");
1895 *lose = 1;
1896 return 0;
1897 }
1898 return 1;
1899}
1900
02a015fb 1901/* Parse a subexpression that does not contain a binary operator. */
be6be08d 1902
02a015fb
TL
1903int parse_non_binary (expr, cfile, lose, context)
1904 struct expression **expr;
4615d498 1905 struct parse *cfile;
be6be08d 1906 int *lose;
02a015fb 1907 enum expression_context context;
be6be08d 1908{
02a015fb 1909 enum dhcp_token token;
b1b7b521 1910 const char *val;
be6be08d 1911 struct collection *col;
02a015fb 1912 struct option *option;
79a65726 1913 struct expression *nexp;
b1b7b521 1914 int known;
9fb2fb28 1915 enum expr_op opcode;
f579f39f 1916 const char *s;
fdac15d9
TL
1917 struct executable_statement *stmt;
1918 int i;
be6be08d
TL
1919
1920 token = peek_token (&val, cfile);
1921
1922 /* Check for unary operators... */
1923 switch (token) {
1924 case CHECK:
1925 token = next_token (&val, cfile);
1926 token = next_token (&val, cfile);
1927 if (token != STRING) {
4615d498 1928 parse_warn (cfile, "string expected.");
be6be08d
TL
1929 skip_to_semi (cfile);
1930 *lose = 1;
02a015fb 1931 return 0;
be6be08d
TL
1932 }
1933 for (col = collections; col; col = col -> next)
1934 if (!strcmp (col -> name, val))
1935 break;
1936 if (!col) {
4615d498 1937 parse_warn (cfile, "unknown collection.");
be6be08d 1938 *lose = 1;
02a015fb 1939 return 0;
be6be08d 1940 }
4bd8800e 1941 if (!expression_allocate (expr, MDL))
8ae2d595 1942 log_fatal ("can't allocate expression");
02a015fb
TL
1943 (*expr) -> op = expr_check;
1944 (*expr) -> data.check = col;
1945 break;
be6be08d 1946
5e6fb153 1947 case TOKEN_NOT:
be6be08d 1948 token = next_token (&val, cfile);
9fb2fb28
TL
1949 if (context == context_dns) {
1950 token = peek_token (&val, cfile);
1951 goto not_exists;
1952 }
4bd8800e 1953 if (!expression_allocate (expr, MDL))
8ae2d595 1954 log_fatal ("can't allocate expression");
02a015fb
TL
1955 (*expr) -> op = expr_not;
1956 if (!parse_non_binary (&(*expr) -> data.not,
1957 cfile, lose, context)) {
be6be08d 1958 if (!*lose) {
4615d498 1959 parse_warn (cfile, "expression expected");
be6be08d
TL
1960 skip_to_semi (cfile);
1961 }
1962 *lose = 1;
4bd8800e 1963 expression_dereference (expr, MDL);
02a015fb 1964 return 0;
be6be08d 1965 }
be6be08d 1966 break;
be6be08d 1967
02a015fb 1968 case EXISTS:
9fb2fb28
TL
1969 if (context == context_dns)
1970 goto ns_exists;
02a015fb 1971 token = next_token (&val, cfile);
4bd8800e 1972 if (!expression_allocate (expr, MDL))
8ae2d595 1973 log_fatal ("can't allocate expression");
02a015fb 1974 (*expr) -> op = expr_exists;
b1b7b521
TL
1975 known = 0;
1976 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
02a015fb
TL
1977 if (!(*expr) -> data.option) {
1978 *lose = 1;
4bd8800e 1979 expression_dereference (expr, MDL);
02a015fb 1980 return 0;
be6be08d 1981 }
02a015fb 1982 break;
be6be08d 1983
1c5d5731
TL
1984 case STATIC:
1985 token = next_token (&val, cfile);
4bd8800e 1986 if (!expression_allocate (expr, MDL))
1c5d5731
TL
1987 log_fatal ("can't allocate expression");
1988 (*expr) -> op = expr_static;
1989 break;
1990
70330633
TL
1991 case KNOWN:
1992 token = next_token (&val, cfile);
4bd8800e 1993 if (!expression_allocate (expr, MDL))
70330633
TL
1994 log_fatal ("can't allocate expression");
1995 (*expr) -> op = expr_known;
1996 break;
1997
be6be08d
TL
1998 case SUBSTRING:
1999 token = next_token (&val, cfile);
4bd8800e 2000 if (!expression_allocate (expr, MDL))
8ae2d595 2001 log_fatal ("can't allocate expression");
02a015fb 2002 (*expr) -> op = expr_substring;
be6be08d
TL
2003
2004 token = next_token (&val, cfile);
2005 if (token != LPAREN) {
2006 nolparen:
4bd8800e 2007 expression_dereference (expr, MDL);
4615d498 2008 parse_warn (cfile, "left parenthesis expected.");
be6be08d 2009 *lose = 1;
02a015fb 2010 return 0;
be6be08d
TL
2011 }
2012
02a015fb
TL
2013 if (!parse_data_expression (&(*expr) -> data.substring.expr,
2014 cfile, lose)) {
be6be08d 2015 nodata:
4bd8800e 2016 expression_dereference (expr, MDL);
4615d498 2017 parse_warn (cfile, "expecting data expression.");
be6be08d
TL
2018 skip_to_semi (cfile);
2019 *lose = 1;
02a015fb 2020 return 0;
be6be08d
TL
2021 }
2022
2023 token = next_token (&val, cfile);
2024 if (token != COMMA) {
2025 nocomma:
4bd8800e 2026 expression_dereference (expr, MDL);
4615d498 2027 parse_warn (cfile, "comma expected.");
be6be08d 2028 *lose = 1;
02a015fb
TL
2029
2030 return 0;
be6be08d
TL
2031 }
2032
02a015fb
TL
2033 if (!parse_numeric_expression
2034 (&(*expr) -> data.substring.offset,cfile, lose)) {
be6be08d
TL
2035 nonum:
2036 if (!*lose) {
4615d498
TL
2037 parse_warn (cfile,
2038 "expecting numeric expression.");
be6be08d
TL
2039 skip_to_semi (cfile);
2040 *lose = 1;
2041 }
4bd8800e 2042 expression_dereference (expr, MDL);
02a015fb 2043 return 0;
be6be08d
TL
2044 }
2045
2046 token = next_token (&val, cfile);
2047 if (token != COMMA)
2048 goto nocomma;
2049
02a015fb
TL
2050 if (!parse_numeric_expression
2051 (&(*expr) -> data.substring.len, cfile, lose))
be6be08d
TL
2052 goto nonum;
2053
2054 token = next_token (&val, cfile);
2055 if (token != RPAREN) {
2056 norparen:
4615d498 2057 parse_warn (cfile, "right parenthesis expected.");
be6be08d 2058 *lose = 1;
4bd8800e 2059 expression_dereference (expr, MDL);
02a015fb 2060 return 0;
be6be08d 2061 }
02a015fb 2062 break;
be6be08d
TL
2063
2064 case SUFFIX:
2065 token = next_token (&val, cfile);
4bd8800e 2066 if (!expression_allocate (expr, MDL))
8ae2d595 2067 log_fatal ("can't allocate expression");
02a015fb 2068 (*expr) -> op = expr_suffix;
be6be08d
TL
2069
2070 token = next_token (&val, cfile);
2071 if (token != LPAREN)
2072 goto nolparen;
2073
02a015fb
TL
2074 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
2075 cfile, lose))
be6be08d
TL
2076 goto nodata;
2077
2078 token = next_token (&val, cfile);
2079 if (token != COMMA)
2080 goto nocomma;
2081
02a015fb
TL
2082 if (!parse_data_expression (&(*expr) -> data.suffix.len,
2083 cfile, lose))
be6be08d
TL
2084 goto nonum;
2085
2086 token = next_token (&val, cfile);
2087 if (token != RPAREN)
2088 goto norparen;
02a015fb 2089 break;
be6be08d 2090
a82abfc7
TL
2091 case CONCAT:
2092 token = next_token (&val, cfile);
4bd8800e 2093 if (!expression_allocate (expr, MDL))
a82abfc7
TL
2094 log_fatal ("can't allocate expression");
2095 (*expr) -> op = expr_concat;
2096
2097 token = next_token (&val, cfile);
2098 if (token != LPAREN)
2099 goto nolparen;
2100
2101 if (!parse_data_expression (&(*expr) -> data.concat [0],
2102 cfile, lose))
2103 goto nodata;
2104
2105 token = next_token (&val, cfile);
2106 if (token != COMMA)
2107 goto nocomma;
2108
720c8262 2109 concat_another:
a82abfc7
TL
2110 if (!parse_data_expression (&(*expr) -> data.concat [1],
2111 cfile, lose))
2112 goto nodata;
2113
2114 token = next_token (&val, cfile);
720c8262
TL
2115
2116 if (token == COMMA) {
2117 nexp = (struct expression *)0;
4bd8800e 2118 if (!expression_allocate (&nexp, MDL))
720c8262
TL
2119 log_fatal ("can't allocate at CONCAT2");
2120 nexp -> op = expr_concat;
4bd8800e
TL
2121 expression_reference (&nexp -> data.concat [0],
2122 *expr, MDL);
2123 expression_dereference (expr, MDL);
2124 expression_reference (expr, nexp, MDL);
720c8262
TL
2125 goto concat_another;
2126 }
2127
a82abfc7
TL
2128 if (token != RPAREN)
2129 goto norparen;
2130 break;
2131
da38df14
TL
2132 case BINARY_TO_ASCII:
2133 token = next_token (&val, cfile);
4bd8800e 2134 if (!expression_allocate (expr, MDL))
da38df14 2135 log_fatal ("can't allocate expression");
eb42f00e 2136 (*expr) -> op = expr_binary_to_ascii;
da38df14
TL
2137
2138 token = next_token (&val, cfile);
2139 if (token != LPAREN)
2140 goto nolparen;
2141
2142 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
2143 cfile, lose))
2144 goto nodata;
2145
2146 token = next_token (&val, cfile);
2147 if (token != COMMA)
2148 goto nocomma;
2149
2150 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
2151 cfile, lose))
2152 goto nodata;
2153
2154 token = next_token (&val, cfile);
2155 if (token != COMMA)
2156 goto nocomma;
2157
2158 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
2159 cfile, lose))
2160 goto nodata;
2161
2162 token = next_token (&val, cfile);
2163 if (token != COMMA)
2164 goto nocomma;
2165
2166 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
2167 cfile, lose))
2168 goto nodata;
2169
2170 token = next_token (&val, cfile);
2171 if (token != RPAREN)
2172 goto norparen;
2173 break;
2174
2175 case REVERSE:
2176 token = next_token (&val, cfile);
4bd8800e 2177 if (!expression_allocate (expr, MDL))
da38df14 2178 log_fatal ("can't allocate expression");
eb42f00e 2179 (*expr) -> op = expr_reverse;
da38df14
TL
2180
2181 token = next_token (&val, cfile);
2182 if (token != LPAREN)
2183 goto nolparen;
2184
2185 if (!(parse_numeric_expression
2186 (&(*expr) -> data.reverse.width, cfile, lose)))
2187 goto nodata;
2188
2189 token = next_token (&val, cfile);
2190 if (token != COMMA)
2191 goto nocomma;
2192
2193 if (!(parse_data_expression
2194 (&(*expr) -> data.reverse.buffer, cfile, lose)))
2195 goto nodata;
2196
2197 token = next_token (&val, cfile);
2198 if (token != RPAREN)
2199 goto norparen;
2200 break;
2201
fdac15d9 2202 case PICK:
79a65726
TL
2203 /* pick (a, b, c) actually produces an internal representation
2204 that looks like pick (a, pick (b, pick (c, nil))). */
2205 token = next_token (&val, cfile);
4bd8800e 2206 if (!(expression_allocate (expr, MDL)))
79a65726 2207 log_fatal ("can't allocate expression");
79a65726 2208
be6be08d 2209 token = next_token (&val, cfile);
79a65726
TL
2210 if (token != LPAREN)
2211 goto nolparen;
2212
2213 nexp = *expr;
2214 do {
392208d3 2215 nexp -> op = expr_pick_first_value;
79a65726
TL
2216 if (!(parse_data_expression
2217 (&nexp -> data.pick_first_value.car,
2218 cfile, lose)))
2219 goto nodata;
2220
2221 token = next_token (&val, cfile);
2222 if (token == COMMA) {
2223 if (!(expression_allocate
2224 (&nexp -> data.pick_first_value.cdr,
4bd8800e 2225 MDL)))
79a65726
TL
2226 log_fatal ("can't allocate expr");
2227 nexp = nexp -> data.pick_first_value.cdr;
2228 }
2229 } while (token == COMMA);
2230
2231 if (token != RPAREN)
2232 goto norparen;
2233 break;
2234
9fb2fb28
TL
2235 /* dns-update and dns-delete are present for historical
2236 purposes, but are deprecated in favor of ns-update
2237 in combination with update, delete, exists and not
2238 exists. */
069e9f4c 2239 case DNS_UPDATE:
9fb2fb28 2240 case DNS_DELETE:
069e9f4c 2241#if !defined (NSUPDATE)
4615d498
TL
2242 parse_warn (cfile,
2243 "Please rebuild dhcpd with --with-nsupdate.");
069e9f4c 2244#endif
fdac15d9 2245 token = next_token (&val, cfile);
9fb2fb28 2246 if (token == DNS_UPDATE)
f579f39f 2247 opcode = expr_ns_add;
9fb2fb28
TL
2248 else
2249 opcode = expr_ns_delete;
2250
069e9f4c
TL
2251 token = next_token (&val, cfile);
2252 if (token != LPAREN)
2253 goto nolparen;
2254
9fb2fb28
TL
2255 token = next_token (&val, cfile);
2256 if (token != STRING) {
2257 parse_warn (cfile,
2258 "parse_expression: expecting string.");
2259 badnsupdate:
069e9f4c
TL
2260 skip_to_semi (cfile);
2261 *lose = 1;
2262 return 0;
2263 }
9fb2fb28
TL
2264
2265 if (!strcasecmp (val, "a"))
fdac15d9 2266 i = T_A;
9fb2fb28 2267 else if (!strcasecmp (val, "ptr"))
fdac15d9 2268 i = T_PTR;
9fb2fb28 2269 else if (!strcasecmp (val, "mx"))
fdac15d9 2270 i = T_MX;
9fb2fb28 2271 else if (!strcasecmp (val, "cname"))
fdac15d9 2272 i = T_CNAME;
9fb2fb28 2273 else if (!strcasecmp (val, "TXT"))
fdac15d9 2274 i = T_TXT;
9fb2fb28
TL
2275 else {
2276 parse_warn (cfile, "unexpected rrtype: %s", val);
2277 goto badnsupdate;
2278 }
fdac15d9 2279
4bd8800e 2280 if (!expression_allocate (expr, MDL))
fdac15d9
TL
2281 log_fatal ("can't allocate expression");
2282#if 0
2283 (*expr) -> op = expr_funcall;
2284 (*expr) -> data.funcall.context = context_boolean;
2285 (*expr) -> data.funcall.name =
2286
2287 if (!make_let (&(*expr) -> data.funcall.statements, "rrtype"))
2288 log_fatal ("can't allocate rrtype let.");
2289 stmt = (*expr) -> data.funcall.statements;
2290 if (!make_const_int (stmt -> data.let.value, i))
2291 log_fatal ("can't allocate rrtype value.");
069e9f4c
TL
2292
2293 token = next_token (&val, cfile);
2294 if (token != COMMA)
2295 goto nocomma;
2296
fdac15d9
TL
2297 if (!make_let (&stmt -> data.let.statements, "rrname"))
2298 log_fatal ("can't allocate rrname let.");
2299 stmt = stmt -> data.let.statements;
2300 if (!(parse_data_expression (&stmt -> data.let.expr,
2301 cfile, lose)))
069e9f4c
TL
2302 goto nodata;
2303
2304 token = next_token (&val, cfile);
2305 if (token != COMMA)
2306 goto nocomma;
2307
fdac15d9
TL
2308 if (!make_let (&stmt -> data.let.statements, "rrdata"))
2309 log_fatal ("can't allocate rrname let.");
2310 stmt = stmt -> data.let.statements;
2311 if (!(parse_data_expression (&stmt -> data.let.expr,
2312 cfile, lose)))
069e9f4c
TL
2313 goto nodata;
2314
f579f39f 2315 if (opcode == expr_ns_add) {
9fb2fb28
TL
2316 token = next_token (&val, cfile);
2317 if (token != COMMA)
2318 goto nocomma;
2319
fdac15d9
TL
2320 if (!make_let (&stmt -> data.let.statements, "ttl"))
2321 log_fatal ("can't allocate rrname let.");
2322 stmt = stmt -> data.let.statements;
2323
9fb2fb28 2324 if (!(parse_numeric_expression
fdac15d9 2325 (&stmt -> data.let.expr, cfile, lose))) {
9fb2fb28 2326 parse_warn (cfile,
fdac15d9 2327 "expecting numeric expression.");
9fb2fb28
TL
2328 goto badnsupdate;
2329 }
069e9f4c 2330 }
fdac15d9 2331#endif
069e9f4c
TL
2332 token = next_token (&val, cfile);
2333 if (token != RPAREN)
2334 goto norparen;
2335 break;
2336
9fb2fb28 2337 case NS_UPDATE:
88886e12
TL
2338#if !defined (NSUPDATE)
2339 parse_warn (cfile,
2340 "Please rebuild dhcpd with --with-nsupdate.");
2341#endif
2342 token = next_token (&val, cfile);
4bd8800e 2343 if (!expression_allocate (expr, MDL))
88886e12 2344 log_fatal ("can't allocate expression");
88886e12
TL
2345
2346 token = next_token (&val, cfile);
2347 if (token != LPAREN)
2348 goto nolparen;
2349
9fb2fb28
TL
2350 nexp = *expr;
2351 do {
2352 nexp -> op = expr_dns_transaction;
2353 if (!(parse_dns_expression
2354 (&nexp -> data.dns_transaction.car,
2355 cfile, lose)))
2356 {
f579f39f
TL
2357 if (!*lose)
2358 parse_warn
2359 (cfile,
2360 "expecting dns expression.");
9fb2fb28 2361 badnstrans:
4bd8800e 2362 expression_dereference (expr, MDL);
9fb2fb28
TL
2363 *lose = 1;
2364 return 0;
2365 }
2366
2367 token = next_token (&val, cfile);
2368
2369 if (token == COMMA) {
2370 if (!(expression_allocate
2371 (&nexp -> data.dns_transaction.cdr,
4bd8800e 2372 MDL)))
9fb2fb28
TL
2373 log_fatal
2374 ("can't allocate expression");
2375 nexp = nexp -> data.dns_transaction.cdr;
2376 }
2377 } while (token == COMMA);
2378
2379 if (token != RPAREN)
2380 goto norparen;
2381 break;
2382
2383 /* NOT EXISTS is special cased above... */
2384 not_exists:
fdac15d9
TL
2385 token = peek_token (&val, cfile);
2386 if (token != EXISTS) {
2387 parse_warn (cfile, "expecting DNS prerequisite.");
2388 *lose = 1;
2389 return 0;
2390 }
9fb2fb28
TL
2391 opcode = expr_ns_not_exists;
2392 goto nsupdatecode;
f579f39f
TL
2393 case TOKEN_ADD:
2394 opcode = expr_ns_add;
9fb2fb28
TL
2395 goto nsupdatecode;
2396 case TOKEN_DELETE:
2397 opcode = expr_ns_delete;
2398 goto nsupdatecode;
2399 ns_exists:
2400 opcode = expr_ns_exists;
2401 nsupdatecode:
2402 token = next_token (&val, cfile);
2403
2404#if !defined (NSUPDATE)
2405 parse_warn (cfile,
2406 "Please rebuild dhcpd with --with-nsupdate.");
2407#endif
4bd8800e 2408 if (!expression_allocate (expr, MDL))
9fb2fb28
TL
2409 log_fatal ("can't allocate expression");
2410 (*expr) -> op = opcode;
2411
2412 token = next_token (&val, cfile);
2413 if (token != LPAREN)
2414 goto nolparen;
2415
2416 token = next_token (&val, cfile);
2417 if (!is_identifier (token) && token != NUMBER) {
2418 parse_warn (cfile, "expecting identifier or number.");
2419 badnsop:
4bd8800e 2420 expression_dereference (expr, MDL);
88886e12
TL
2421 skip_to_semi (cfile);
2422 *lose = 1;
2423 return 0;
2424 }
9fb2fb28
TL
2425
2426 if (token == NUMBER)
f579f39f 2427 (*expr) -> data.ns_add.rrclass = atoi (val);
9fb2fb28 2428 else if (!strcasecmp (val, "in"))
f579f39f 2429 (*expr) -> data.ns_add.rrclass = C_IN;
9fb2fb28 2430 else if (!strcasecmp (val, "chaos"))
f579f39f 2431 (*expr) -> data.ns_add.rrclass = C_CHAOS;
9fb2fb28 2432 else if (!strcasecmp (val, "hs"))
f579f39f 2433 (*expr) -> data.ns_add.rrclass = C_HS;
9fb2fb28
TL
2434 else {
2435 parse_warn (cfile, "unexpected rrclass: %s", val);
2436 goto badnsop;
2437 }
2438
f579f39f
TL
2439 token = next_token (&val, cfile);
2440 if (token != COMMA)
2441 goto nocomma;
2442
9fb2fb28
TL
2443 token = next_token (&val, cfile);
2444 if (!is_identifier (token) && token != NUMBER) {
2445 parse_warn (cfile, "expecting identifier or number.");
2446 goto badnsop;
2447 }
2448
2449 if (token == NUMBER)
f579f39f 2450 (*expr) -> data.ns_add.rrtype = atoi (val);
9fb2fb28 2451 else if (!strcasecmp (val, "a"))
f579f39f 2452 (*expr) -> data.ns_add.rrtype = T_A;
9fb2fb28 2453 else if (!strcasecmp (val, "ptr"))
f579f39f 2454 (*expr) -> data.ns_add.rrtype = T_PTR;
9fb2fb28 2455 else if (!strcasecmp (val, "mx"))
f579f39f 2456 (*expr) -> data.ns_add.rrtype = T_MX;
9fb2fb28 2457 else if (!strcasecmp (val, "cname"))
f579f39f 2458 (*expr) -> data.ns_add.rrtype = T_CNAME;
9fb2fb28 2459 else if (!strcasecmp (val, "TXT"))
f579f39f 2460 (*expr) -> data.ns_add.rrtype = T_TXT;
9fb2fb28
TL
2461 else {
2462 parse_warn (cfile, "unexpected rrtype: %s", val);
2463 goto badnsop;
2464 }
88886e12
TL
2465
2466 token = next_token (&val, cfile);
2467 if (token != COMMA)
2468 goto nocomma;
2469
2470 if (!(parse_data_expression
f579f39f 2471 (&(*expr) -> data.ns_add.rrname, cfile, lose)))
88886e12
TL
2472 goto nodata;
2473
2474 token = next_token (&val, cfile);
2475 if (token != COMMA)
2476 goto nocomma;
2477
2478 if (!(parse_data_expression
f579f39f 2479 (&(*expr) -> data.ns_add.rrdata, cfile, lose)))
88886e12
TL
2480 goto nodata;
2481
f579f39f 2482 if (opcode == expr_ns_add) {
9fb2fb28
TL
2483 token = next_token (&val, cfile);
2484 if (token != COMMA)
2485 goto nocomma;
2486
2487 if (!(parse_numeric_expression
f579f39f
TL
2488 (&(*expr) -> data.ns_add.ttl, cfile,
2489 lose))) {
9fb2fb28
TL
2490 parse_warn (cfile,
2491 "expecting data expression.");
2492 goto badnsupdate;
2493 }
2494 }
2495
88886e12
TL
2496 token = next_token (&val, cfile);
2497 if (token != RPAREN)
2498 goto norparen;
2499 break;
2500
79a65726
TL
2501 case OPTION:
2502 case CONFIG_OPTION:
4bd8800e 2503 if (!expression_allocate (expr, MDL))
8ae2d595 2504 log_fatal ("can't allocate expression");
cd31814f
TL
2505 (*expr) -> op = (token == OPTION
2506 ? expr_option
2507 : expr_config_option);
79a65726 2508 token = next_token (&val, cfile);
b1b7b521
TL
2509 known = 0;
2510 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
02a015fb 2511 if (!(*expr) -> data.option) {
be6be08d 2512 *lose = 1;
4bd8800e 2513 expression_dereference (expr, MDL);
02a015fb 2514 return 0;
be6be08d 2515 }
02a015fb 2516 break;
be6be08d
TL
2517
2518 case HARDWARE:
2519 token = next_token (&val, cfile);
4bd8800e 2520 if (!expression_allocate (expr, MDL))
8ae2d595 2521 log_fatal ("can't allocate expression");
02a015fb
TL
2522 (*expr) -> op = expr_hardware;
2523 break;
be6be08d 2524
da38df14
TL
2525 case LEASED_ADDRESS:
2526 token = next_token (&val, cfile);
4bd8800e 2527 if (!expression_allocate (expr, MDL))
da38df14
TL
2528 log_fatal ("can't allocate expression");
2529 (*expr) -> op = expr_leased_address;
2530 break;
2531
fdac15d9
TL
2532 case FILENAME:
2533 token = next_token (&val, cfile);
4bd8800e 2534 if (!expression_allocate (expr, MDL))
fdac15d9
TL
2535 log_fatal ("can't allocate expression");
2536 (*expr) -> op = expr_filename;
2537 break;
2538
2539 case SERVER_NAME:
2540 token = next_token (&val, cfile);
4bd8800e 2541 if (!expression_allocate (expr, MDL))
fdac15d9
TL
2542 log_fatal ("can't allocate expression");
2543 (*expr) -> op = expr_sname;
2544 break;
2545
069e9f4c
TL
2546 case LEASE_TIME:
2547 token = next_token (&val, cfile);
4bd8800e 2548 if (!expression_allocate (expr, MDL))
069e9f4c
TL
2549 log_fatal ("can't allocate expression");
2550 (*expr) -> op = expr_lease_time;
2551 break;
2552
f579f39f
TL
2553 case TOKEN_NULL:
2554 token = next_token (&val, cfile);
4bd8800e 2555 if (!expression_allocate (expr, MDL))
f579f39f
TL
2556 log_fatal ("can't allocate expression");
2557 (*expr) -> op = expr_null;
2558 break;
2559
79a65726
TL
2560 case HOST_DECL_NAME:
2561 token = next_token (&val, cfile);
4bd8800e 2562 if (!expression_allocate (expr, MDL))
79a65726
TL
2563 log_fatal ("can't allocate expression");
2564 (*expr) -> op = expr_host_decl_name;
2565 break;
2566
846d7d54 2567 case UPDATED_DNS_RR:
06a8567c 2568 token = next_token (&val, cfile);
06a8567c 2569
06a8567c 2570 token = next_token (&val, cfile);
846d7d54
TL
2571 if (token != LPAREN)
2572 goto nolparen;
f579f39f
TL
2573
2574 token = next_token (&val, cfile);
2575 if (token != STRING) {
2576 parse_warn (cfile, "expecting string.");
2577 bad_rrtype:
2578 *lose = 1;
2579 return 0;
2580 }
2581 if (!strcasecmp (val, "a"))
2582 s = "ddns-fwd-name";
2583 else if (!strcasecmp (val, "ptr"))
2584 s = "ddns-rev-name";
2585 else {
2586 parse_warn (cfile, "invalid DNS rrtype: %s", val);
2587 goto bad_rrtype;
2588 }
846d7d54
TL
2589
2590 token = next_token (&val, cfile);
2591 if (token != RPAREN)
2592 goto norparen;
2593
4bd8800e 2594 if (!expression_allocate (expr, MDL))
f579f39f
TL
2595 log_fatal ("can't allocate expression");
2596 (*expr) -> op = expr_variable_reference;
2597 (*expr) -> data.variable =
fdac15d9 2598 dmalloc (strlen (s) + 1, MDL);
f579f39f
TL
2599 if (!(*expr) -> data.variable)
2600 log_fatal ("can't allocate variable name.");
2601 strcpy ((*expr) -> data.variable, s);
06a8567c
TL
2602 break;
2603
be6be08d
TL
2604 case PACKET:
2605 token = next_token (&val, cfile);
4bd8800e 2606 if (!expression_allocate (expr, MDL))
8ae2d595 2607 log_fatal ("can't allocate expression");
02a015fb 2608 (*expr) -> op = expr_packet;
be6be08d
TL
2609
2610 token = next_token (&val, cfile);
2611 if (token != LPAREN)
2612 goto nolparen;
2613
02a015fb
TL
2614 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
2615 cfile, lose))
be6be08d
TL
2616 goto nonum;
2617
2618 token = next_token (&val, cfile);
2619 if (token != COMMA)
2620 goto nocomma;
2621
02a015fb
TL
2622 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
2623 cfile, lose))
be6be08d
TL
2624 goto nonum;
2625
2626 token = next_token (&val, cfile);
2627 if (token != RPAREN)
2628 goto norparen;
02a015fb 2629 break;
be6be08d
TL
2630
2631 case STRING:
2632 token = next_token (&val, cfile);
b1b7b521 2633 if (!make_const_data (expr, (const unsigned char *)val,
c5b0f529 2634 strlen (val), 1, 1))
8ae2d595 2635 log_fatal ("can't make constant string expression.");
02a015fb 2636 break;
be6be08d 2637
be6be08d
TL
2638 case EXTRACT_INT:
2639 token = next_token (&val, cfile);
be6be08d
TL
2640 token = next_token (&val, cfile);
2641 if (token != LPAREN) {
4615d498 2642 parse_warn (cfile, "left parenthesis expected.");
be6be08d 2643 *lose = 1;
02a015fb 2644 return 0;
be6be08d
TL
2645 }
2646
4bd8800e 2647 if (!expression_allocate (expr, MDL))
8ae2d595 2648 log_fatal ("can't allocate expression");
02a015fb
TL
2649
2650 if (!parse_data_expression (&(*expr) -> data.extract_int,
2651 cfile, lose)) {
4615d498 2652 parse_warn (cfile, "expecting data expression.");
be6be08d
TL
2653 skip_to_semi (cfile);
2654 *lose = 1;
4bd8800e 2655 expression_dereference (expr, MDL);
02a015fb 2656 return 0;
be6be08d
TL
2657 }
2658
2659 token = next_token (&val, cfile);
2660 if (token != COMMA) {
4615d498 2661 parse_warn (cfile, "comma expected.");
be6be08d 2662 *lose = 1;
4bd8800e 2663 expression_dereference (expr, MDL);
02a015fb 2664 return 0;
be6be08d
TL
2665 }
2666
2667 token = next_token (&val, cfile);
2668 if (token != NUMBER) {
4615d498 2669 parse_warn (cfile, "number expected.");
be6be08d 2670 *lose = 1;
4bd8800e 2671 expression_dereference (expr, MDL);
02a015fb 2672 return 0;
be6be08d 2673 }
be6be08d
TL
2674 switch (atoi (val)) {
2675 case 8:
02a015fb 2676 (*expr) -> op = expr_extract_int8;
be6be08d
TL
2677 break;
2678
2679 case 16:
02a015fb 2680 (*expr) -> op = expr_extract_int16;
be6be08d
TL
2681 break;
2682
2683 case 32:
02a015fb 2684 (*expr) -> op = expr_extract_int32;
be6be08d
TL
2685 break;
2686
2687 default:
4615d498
TL
2688 parse_warn (cfile,
2689 "unsupported integer size %d", atoi (val));
be6be08d
TL
2690 *lose = 1;
2691 skip_to_semi (cfile);
4bd8800e 2692 expression_dereference (expr, MDL);
02a015fb 2693 return 0;
be6be08d
TL
2694 }
2695
2696 token = next_token (&val, cfile);
2697 if (token != RPAREN) {
4615d498 2698 parse_warn (cfile, "right parenthesis expected.");
be6be08d 2699 *lose = 1;
4bd8800e 2700 expression_dereference (expr, MDL);
02a015fb 2701 return 0;
be6be08d 2702 }
02a015fb 2703 break;
be6be08d 2704
20c4e94d
TL
2705 case ENCODE_INT:
2706 token = next_token (&val, cfile);
2707 token = next_token (&val, cfile);
2708 if (token != LPAREN) {
4615d498 2709 parse_warn (cfile, "left parenthesis expected.");
20c4e94d
TL
2710 *lose = 1;
2711 return 0;
2712 }
2713
4bd8800e 2714 if (!expression_allocate (expr, MDL))
20c4e94d
TL
2715 log_fatal ("can't allocate expression");
2716
2717 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
2718 cfile, lose)) {
4615d498 2719 parse_warn (cfile, "expecting numeric expression.");
20c4e94d
TL
2720 skip_to_semi (cfile);
2721 *lose = 1;
4bd8800e 2722 expression_dereference (expr, MDL);
20c4e94d
TL
2723 return 0;
2724 }
2725
2726 token = next_token (&val, cfile);
2727 if (token != COMMA) {
4615d498 2728 parse_warn (cfile, "comma expected.");
20c4e94d 2729 *lose = 1;
4bd8800e 2730 expression_dereference (expr, MDL);
20c4e94d
TL
2731 return 0;
2732 }
2733
2734 token = next_token (&val, cfile);
2735 if (token != NUMBER) {
4615d498 2736 parse_warn (cfile, "number expected.");
20c4e94d 2737 *lose = 1;
4bd8800e 2738 expression_dereference (expr, MDL);
20c4e94d
TL
2739 return 0;
2740 }
2741 switch (atoi (val)) {
2742 case 8:
2743 (*expr) -> op = expr_encode_int8;
2744 break;
2745
2746 case 16:
2747 (*expr) -> op = expr_encode_int16;
2748 break;
2749
2750 case 32:
2751 (*expr) -> op = expr_encode_int32;
2752 break;
2753
2754 default:
4615d498
TL
2755 parse_warn (cfile,
2756 "unsupported integer size %d", atoi (val));
20c4e94d
TL
2757 *lose = 1;
2758 skip_to_semi (cfile);
4bd8800e 2759 expression_dereference (expr, MDL);
20c4e94d
TL
2760 return 0;
2761 }
2762
2763 token = next_token (&val, cfile);
2764 if (token != RPAREN) {
4615d498 2765 parse_warn (cfile, "right parenthesis expected.");
20c4e94d 2766 *lose = 1;
4bd8800e 2767 expression_dereference (expr, MDL);
20c4e94d
TL
2768 return 0;
2769 }
2770 break;
2771
be6be08d 2772 case NUMBER:
02a015fb
TL
2773 /* If we're in a numeric context, this should just be a
2774 number, by itself. */
f579f39f
TL
2775 if (context == context_numeric ||
2776 context == context_data_or_numeric) {
02a015fb 2777 next_token (&val, cfile); /* Eat the number. */
4bd8800e 2778 if (!expression_allocate (expr, MDL))
be19167d 2779 log_fatal ("can't allocate expression");
02a015fb
TL
2780 (*expr) -> op = expr_const_int;
2781 (*expr) -> data.const_int = atoi (val);
2782 break;
2783 }
be6be08d 2784
02a015fb 2785 case NUMBER_OR_NAME:
4bd8800e 2786 if (!expression_allocate (expr, MDL))
be19167d
TL
2787 log_fatal ("can't allocate expression");
2788
02a015fb
TL
2789 (*expr) -> op = expr_const_data;
2790 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
4bd8800e 2791 expression_dereference (expr, MDL);
02a015fb
TL
2792 return 0;
2793 }
2794 break;
2795
f579f39f
TL
2796 case NS_FORMERR:
2797 known = FORMERR;
2798 ns_const:
2799 token = next_token (&val, cfile);
4bd8800e 2800 if (!expression_allocate (expr, MDL))
f579f39f
TL
2801 log_fatal ("can't allocate expression");
2802 (*expr) -> op = expr_const_int;
2803 (*expr) -> data.const_int = known;
2804 break;
2805
2806 case NS_NOERROR:
2807 known = NOERROR;
2808 goto ns_const;
2809
2810 case NS_NOTAUTH:
2811 known = NOTAUTH;
2812 goto ns_const;
2813
2814 case NS_NOTIMP:
2815 known = NOTIMP;
2816 goto ns_const;
2817
2818 case NS_NOTZONE:
2819 known = NOTZONE;
2820 goto ns_const;
2821
2822 case NS_NXDOMAIN:
2823 known = NXDOMAIN;
2824 goto ns_const;
2825
2826 case NS_NXRRSET:
2827 known = NXRRSET;
2828 goto ns_const;
2829
2830 case NS_REFUSED:
2831 known = REFUSED;
2832 goto ns_const;
2833
2834 case NS_SERVFAIL:
2835 known = SERVFAIL;
2836 goto ns_const;
2837
2838 case NS_YXDOMAIN:
2839 known = YXDOMAIN;
2840 goto ns_const;
2841
2842 case NS_YXRRSET:
2843 known = YXRRSET;
2844 goto ns_const;
2845
2846 case DEFINED:
2847 token = next_token (&val, cfile);
2848 token = next_token (&val, cfile);
2849 if (token != LPAREN)
2850 goto nolparen;
2851
2852 token = next_token (&val, cfile);
2853 if (token != NAME && token != NUMBER_OR_NAME) {
2854 parse_warn (cfile, "%s can't be a variable name", val);
2855 skip_to_semi (cfile);
2856 *lose = 1;
2857 return 0;
2858 }
2859
4bd8800e 2860 if (!expression_allocate (expr, MDL))
f579f39f
TL
2861 log_fatal ("can't allocate expression");
2862 (*expr) -> op = expr_variable_exists;
fdac15d9 2863 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
f579f39f
TL
2864 if (!(*expr)->data.variable)
2865 log_fatal ("can't allocate variable name");
2866 strcpy ((*expr) -> data.variable, val);
2867 token = next_token (&val, cfile);
2868 if (token != RPAREN)
2869 goto norparen;
2870 break;
2871
02a015fb 2872 /* Not a valid start to an expression... */
be6be08d 2873 default:
f579f39f
TL
2874 if (token != NAME && token != NUMBER_OR_NAME)
2875 return 0;
2876
2877 token = next_token (&val, cfile);
4bd8800e 2878 if (!expression_allocate (expr, MDL))
f579f39f
TL
2879 log_fatal ("can't allocate expression");
2880 (*expr) -> op = expr_variable_reference;
fdac15d9 2881 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
f579f39f
TL
2882 if (!(*expr)->data.variable)
2883 log_fatal ("can't allocate variable name");
2884 strcpy ((*expr) -> data.variable, val);
2885 break;
be6be08d 2886 }
02a015fb 2887 return 1;
be6be08d
TL
2888}
2889
02a015fb
TL
2890/* Parse an expression. */
2891
2892int parse_expression (expr, cfile, lose, context, plhs, binop)
2893 struct expression **expr;
4615d498 2894 struct parse *cfile;
02a015fb
TL
2895 int *lose;
2896 enum expression_context context;
2897 struct expression **plhs;
2898 enum expr_op binop;
2899{
2900 enum dhcp_token token;
b1b7b521 2901 const char *val;
02a015fb
TL
2902 struct expression *rhs = (struct expression *)0, *tmp;
2903 struct expression *lhs;
2904 enum expr_op next_op;
2905
2906 /* Consume the left hand side we were passed. */
2907 if (plhs) {
2908 lhs = *plhs;
2909 *plhs = (struct expression *)0;
2910 } else
2911 lhs = (struct expression *)0;
2912
2913 new_rhs:
2914 if (!parse_non_binary (&rhs, cfile, lose, context)) {
2915 /* If we already have a left-hand side, then it's not
2916 okay for there not to be a right-hand side here, so
2917 we need to flag it as an error. */
2918 if (lhs) {
2919 if (!*lose) {
4615d498
TL
2920 parse_warn (cfile,
2921 "expecting right-hand side.");
02a015fb
TL
2922 *lose = 1;
2923 skip_to_semi (cfile);
2924 }
4bd8800e 2925 expression_dereference (&lhs, MDL);
02a015fb
TL
2926 }
2927 return 0;
2928 }
2929
2930 /* At this point, rhs contains either an entire subexpression,
2931 or at least a left-hand-side. If we do not see a binary token
2932 as the next token, we're done with the expression. */
2933
2934 token = peek_token (&val, cfile);
2935 switch (token) {
2b965a44
TL
2936 case BANG:
2937 token = next_token (&val, cfile);
2938 token = peek_token (&val, cfile);
2939 if (token != EQUAL) {
2940 parse_warn (cfile, "! in boolean context without =");
2941 *lose = 1;
2942 skip_to_semi (cfile);
2943 if (lhs)
4bd8800e 2944 expression_dereference (&lhs, MDL);
2b965a44
TL
2945 return 0;
2946 }
2947 next_op = expr_not_equal;
2948 break;
2949
02a015fb
TL
2950 case EQUAL:
2951 next_op = expr_equal;
2952 break;
2953
2954 case AND:
2955 next_op = expr_and;
2956 break;
2957
2958 case OR:
2959 next_op = expr_or;
2960 break;
2961
2962 default:
2963 next_op = expr_none;
2964 }
2965
2966 /* If we have no lhs yet, we just parsed it. */
2967 if (!lhs) {
2968 /* If there was no operator following what we just parsed,
2969 then we're done - return it. */
2970 if (next_op == expr_none) {
2971 *expr = rhs;
2972 return 1;
2973 }
2974 lhs = rhs;
2975 rhs = (struct expression *)0;
2976 binop = next_op;
2977 next_token (&val, cfile); /* Consume the operator. */
2978 goto new_rhs;
2979 }
2980
2981 /* Now, if we didn't find a binary operator, we're done parsing
2982 this subexpression, so combine it with the preceding binary
2983 operator and return the result. */
2984 if (next_op == expr_none) {
4bd8800e 2985 if (!expression_allocate (expr, MDL))
8ae2d595 2986 log_fatal ("Can't allocate expression!");
02a015fb
TL
2987
2988 (*expr) -> op = binop;
2989 /* All the binary operators' data union members
2990 are the same, so we'll cheat and use the member
2991 for the equals operator. */
2992 (*expr) -> data.equal [0] = lhs;
2993 (*expr) -> data.equal [1] = rhs;
2994 return 1;
2995 }
2996
2997 /* Eat the operator token - we now know it was a binary operator... */
2998 token = next_token (&val, cfile);
2999
3000 /* If the binary operator we saw previously has a lower precedence
3001 than the next operator, then the rhs we just parsed for that
3002 operator is actually the lhs of the operator with the higher
3003 precedence - to get the real rhs, we need to recurse on the
3004 new operator. */
3005 if (binop != expr_none &&
3006 op_precedence (binop, next_op) < 0) {
3007 tmp = rhs;
3008 rhs = (struct expression *)0;
3009 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
3010 &tmp, next_op)) {
3011 if (!*lose) {
4615d498
TL
3012 parse_warn (cfile,
3013 "expecting a subexpression");
02a015fb
TL
3014 *lose = 1;
3015 }
3016 return 0;
3017 }
3018 next_op = expr_none;
3019 }
3020
3021 /* Now combine the LHS and the RHS using binop. */
3022 tmp = (struct expression *)0;
4bd8800e 3023 if (!expression_allocate (&tmp, MDL))
8ae2d595 3024 log_fatal ("No memory for equal precedence combination.");
02a015fb
TL
3025
3026 /* Store the LHS and RHS. */
3027 tmp -> data.equal [0] = lhs;
3028 tmp -> data.equal [1] = rhs;
3029 tmp -> op = binop;
3030
3031 lhs = tmp;
3032 tmp = (struct expression *)0;
3033 rhs = (struct expression *)0;
3034
3035 /* Recursions don't return until we have parsed the end of the
3036 expression, so if we recursed earlier, we can now return what
3037 we got. */
3038 if (next_op == expr_none) {
3039 *expr = lhs;
3040 return 1;
3041 }
3042
3043 binop = next_op;
3044 goto new_rhs;
3045}
3046
be6be08d
TL
3047/* option-statement :== identifier DOT identifier <syntax> SEMI
3048 | identifier <syntax> SEMI
3049
3050 Option syntax is handled specially through format strings, so it
3051 would be painful to come up with BNF for it. However, it always
3052 starts as above and ends in a SEMI. */
3053
79a65726
TL
3054int parse_option_statement (result, cfile, lookups, option, op)
3055 struct executable_statement **result;
4615d498 3056 struct parse *cfile;
be6be08d
TL
3057 int lookups;
3058 struct option *option;
3059 enum statement_op op;
3060{
b1b7b521 3061 const char *val;
02a015fb 3062 enum dhcp_token token;
b1b7b521 3063 const char *fmt;
be6be08d 3064 struct expression *expr = (struct expression *)0;
02a015fb 3065 struct expression *tmp;
be6be08d
TL
3066 int lose;
3067 struct executable_statement *stmt;
02a015fb 3068 int ftt = 1;
be6be08d
TL
3069
3070 token = peek_token (&val, cfile);
3071 if (token == SEMI) {
3072 /* Eat the semicolon... */
3073 token = next_token (&val, cfile);
be6be08d
TL
3074 goto done;
3075 }
3076
a82abfc7
TL
3077 if (token == EQUAL) {
3078 /* Eat the equals sign. */
3079 token = next_token (&val, cfile);
3080
3081 /* Parse a data expression and use its value for the data. */
3082 if (!parse_data_expression (&expr, cfile, &lose)) {
3083 /* In this context, we must have an executable
3084 statement, so if we found something else, it's
3085 still an error. */
3086 if (!lose) {
4615d498
TL
3087 parse_warn (cfile,
3088 "expecting a data expression.");
a82abfc7
TL
3089 skip_to_semi (cfile);
3090 }
79a65726 3091 return 0;
a82abfc7
TL
3092 }
3093
3094 /* We got a valid expression, so use it. */
3095 goto done;
3096 }
3097
be6be08d
TL
3098 /* Parse the option data... */
3099 do {
3100 /* Set a flag if this is an array of a simple type (i.e.,
3101 not an array of pairs of IP addresses, or something
3102 like that. */
3103 int uniform = option -> format [1] == 'A';
3104
3105 for (fmt = option -> format; *fmt; fmt++) {
3106 if (*fmt == 'A')
3107 break;
02a015fb 3108 tmp = expr;
44aa67f6 3109 expr = (struct expression *)0;
02a015fb
TL
3110 if (!parse_option_token (&expr, cfile, fmt,
3111 tmp, uniform, lookups)) {
4615d498 3112 if (tmp)
4bd8800e 3113 expression_dereference (&tmp, MDL);
79a65726 3114 return 0;
02a015fb
TL
3115 }
3116 if (tmp)
4bd8800e 3117 expression_dereference (&tmp, MDL);
be6be08d
TL
3118 }
3119 if (*fmt == 'A') {
3120 token = peek_token (&val, cfile);
3121 if (token == COMMA) {
3122 token = next_token (&val, cfile);
3123 continue;
3124 }
3125 break;
3126 }
3127 } while (*fmt == 'A');
3128
3129 done:
25541f2f 3130 if (!parse_semi (cfile))
79a65726 3131 return 0;
4bd8800e 3132 if (!executable_statement_allocate (result, MDL))
79a65726
TL
3133 log_fatal ("no memory for option statement.");
3134 (*result) -> op = op;
3135 if (expr && !option_cache (&(*result) -> data.option,
02a015fb 3136 (struct data_string *)0, expr, option))
52c9d530 3137 log_fatal ("no memory for option cache");
79a65726 3138 return 1;
be6be08d
TL
3139}
3140
02a015fb
TL
3141int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
3142 struct expression **rv;
4615d498 3143 struct parse *cfile;
b1b7b521 3144 const char *fmt;
be6be08d
TL
3145 struct expression *expr;
3146 int uniform;
3147 int lookups;
3148{
b1b7b521 3149 const char *val;
02a015fb
TL
3150 enum dhcp_token token;
3151 struct expression *t = (struct expression *)0;
be6be08d
TL
3152 unsigned char buf [4];
3153 int len;
3154 unsigned char *ob;
3155 struct iaddr addr;
fdac15d9 3156 int num;
be6be08d
TL
3157
3158 switch (*fmt) {
52c9d530
TL
3159 case 'U':
3160 token = next_token (&val, cfile);
3161 if (!is_identifier (token)) {
4615d498 3162 parse_warn (cfile, "expecting identifier.");
52c9d530
TL
3163 skip_to_semi (cfile);
3164 return 0;
3165 }
b1b7b521 3166 if (!make_const_data (&t, (const unsigned char *)val,
52c9d530
TL
3167 strlen (val), 1, 1))
3168 log_fatal ("No memory for %s", val);
3169 break;
3170
be6be08d
TL
3171 case 'X':
3172 token = peek_token (&val, cfile);
3173 if (token == NUMBER_OR_NAME || token == NUMBER) {
4bd8800e 3174 if (!expression_allocate (&t, MDL))
02a015fb 3175 return 0;
8cc4d857 3176 if (!parse_cshl (&t -> data.const_data, cfile)) {
4bd8800e 3177 expression_dereference (&t, MDL);
01e20b9e 3178 return 0;
8cc4d857 3179 }
efc79acb 3180 t -> op = expr_const_data;
be6be08d
TL
3181 } else if (token == STRING) {
3182 token = next_token (&val, cfile);
b1b7b521 3183 if (!make_const_data (&t, (const unsigned char *)val,
02a015fb 3184 strlen (val), 1, 1))
52c9d530 3185 log_fatal ("No memory for \"%s\"", val);
be6be08d 3186 } else {
4615d498 3187 parse_warn (cfile, "expecting string %s.",
be6be08d
TL
3188 "or hexadecimal data");
3189 skip_to_semi (cfile);
02a015fb 3190 return 0;
be6be08d
TL
3191 }
3192 break;
3193
3194 case 't': /* Text string... */
3195 token = next_token (&val, cfile);
3196 if (token != STRING && !is_identifier (token)) {
4615d498 3197 parse_warn (cfile, "expecting string.");
be6be08d
TL
3198 if (token != SEMI)
3199 skip_to_semi (cfile);
02a015fb 3200 return 0;
be6be08d 3201 }
b1b7b521 3202 if (!make_const_data (&t, (const unsigned char *)val,
02a015fb 3203 strlen (val), 1, 1))
8ae2d595 3204 log_fatal ("No memory for concatenation");
be6be08d
TL
3205 break;
3206
3207 case 'I': /* IP address or hostname. */
02a015fb
TL
3208 if (lookups) {
3209 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
3210 return 0;
3211 } else {
be6be08d 3212 if (!parse_ip_addr (cfile, &addr))
02a015fb
TL
3213 return 0;
3214 if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1))
3215 return 0;
be6be08d 3216 }
be6be08d
TL
3217 break;
3218
fdac15d9
TL
3219 case 'T': /* Lease interval. */
3220 token = next_token (&val, cfile);
3221 if (token != INFINITE)
3222 goto check_number;
3223 putLong (buf, -1);
3224 if (!make_const_data (&t, buf, 4, 0, 1))
3225 return 0;
3226 break;
3227
be6be08d
TL
3228 case 'L': /* Unsigned 32-bit integer... */
3229 case 'l': /* Signed 32-bit integer... */
3230 token = next_token (&val, cfile);
fdac15d9 3231 check_number:
be6be08d
TL
3232 if (token != NUMBER) {
3233 need_number:
4615d498 3234 parse_warn (cfile, "expecting number.");
be6be08d
TL
3235 if (token != SEMI)
3236 skip_to_semi (cfile);
02a015fb 3237 return 0;
be6be08d 3238 }
4615d498 3239 convert_num (cfile, buf, val, 0, 32);
02a015fb
TL
3240 if (!make_const_data (&t, buf, 4, 0, 1))
3241 return 0;
be6be08d 3242 break;
02a015fb 3243
be6be08d
TL
3244 case 's': /* Signed 16-bit integer. */
3245 case 'S': /* Unsigned 16-bit integer. */
3246 token = next_token (&val, cfile);
3247 if (token != NUMBER)
3248 goto need_number;
4615d498 3249 convert_num (cfile, buf, val, 0, 16);
02a015fb
TL
3250 if (!make_const_data (&t, buf, 2, 0, 1))
3251 return 0;
be6be08d 3252 break;
02a015fb 3253
be6be08d
TL
3254 case 'b': /* Signed 8-bit integer. */
3255 case 'B': /* Unsigned 8-bit integer. */
3256 token = next_token (&val, cfile);
3257 if (token != NUMBER)
3258 goto need_number;
4615d498 3259 convert_num (cfile, buf, val, 0, 8);
02a015fb
TL
3260 if (!make_const_data (&t, buf, 1, 0, 1))
3261 return 0;
be6be08d 3262 break;
02a015fb 3263
be6be08d
TL
3264 case 'f': /* Boolean flag. */
3265 token = next_token (&val, cfile);
3266 if (!is_identifier (token)) {
4615d498 3267 parse_warn (cfile, "expecting identifier.");
be6be08d
TL
3268 bad_flag:
3269 if (token != SEMI)
3270 skip_to_semi (cfile);
02a015fb 3271 return 0;
be6be08d
TL
3272 }
3273 if (!strcasecmp (val, "true")
3274 || !strcasecmp (val, "on"))
3275 buf [0] = 1;
3276 else if (!strcasecmp (val, "false")
3277 || !strcasecmp (val, "off"))
3278 buf [0] = 0;
0776fd12
TL
3279 else if (!strcasecmp (val, "ignore"))
3280 buf [0] = 2;
be6be08d 3281 else {
4615d498 3282 parse_warn (cfile, "expecting boolean.");
be6be08d
TL
3283 goto bad_flag;
3284 }
02a015fb
TL
3285 if (!make_const_data (&t, buf, 1, 0, 1))
3286 return 0;
be6be08d 3287 break;
02a015fb 3288
be6be08d 3289 default:
4615d498 3290 parse_warn (cfile, "Bad format %c in parse_option_param.",
f420e08c 3291 *fmt);
be6be08d 3292 skip_to_semi (cfile);
02a015fb 3293 return 0;
be6be08d 3294 }
02a015fb
TL
3295 if (expr) {
3296 if (!make_concat (rv, expr, t))
3297 return 0;
4bd8800e 3298 expression_dereference (&t, MDL);
02a015fb
TL
3299 } else
3300 *rv = t;
3301 return 1;
be6be08d 3302}
74f45f96
TL
3303
3304int parse_auth_key (key_id, cfile)
3305 struct data_string *key_id;
4615d498 3306 struct parse *cfile;
74f45f96
TL
3307{
3308 struct data_string key_data;
b1b7b521 3309 const char *val;
74f45f96 3310 enum dhcp_token token;
b1b7b521
TL
3311 const struct auth_key *key, *old_key = (struct auth_key *)0;
3312 struct auth_key *new_key;
74f45f96
TL
3313
3314 memset (&key_data, 0, sizeof key_data);
3315
3316 if (!parse_cshl (key_id, cfile))
3317 return 0;
3318
3319 key = auth_key_lookup (key_id);
3320
3321 token = peek_token (&val, cfile);
3322 if (token == SEMI) {
3323 if (!key)
4615d498 3324 parse_warn (cfile, "reference to undefined key %s",
74f45f96
TL
3325 print_hex_1 (key_id -> len,
3326 key_id -> data,
3327 key_id -> len));
4bd8800e 3328 data_string_forget (key_id, MDL);
74f45f96
TL
3329 } else {
3330 if (!parse_cshl (&key_data, cfile))
3331 return 0;
3332 if (key) {
4615d498 3333 parse_warn (cfile, "redefinition of key %s",
74f45f96
TL
3334 print_hex_1 (key_id -> len,
3335 key_id -> data,
3336 key_id -> len));
3337 old_key = key;
3338 }
4bd8800e 3339 new_key = new_auth_key (key_data.len, MDL);
b1b7b521 3340 if (!new_key)
74f45f96
TL
3341 log_fatal ("No memory for key %s",
3342 print_hex_1 (key_id -> len,
3343 key_id -> data,
3344 key_id -> len));
b1b7b521
TL
3345 new_key -> length = key_data.len;
3346 memcpy (new_key -> data, key_data.data, key_data.len);
3347 enter_auth_key (key_id, new_key);
4bd8800e 3348 data_string_forget (&key_data, MDL);
74f45f96
TL
3349 }
3350
3351 parse_semi (cfile);
3352 return key_id -> len ? 1 : 0;
3353}
4bd8800e 3354
cfdfb9f1 3355int parse_warn (struct parse *cfile, const char *fmt, ...)
4bd8800e
TL
3356{
3357 va_list list;
3358 static char spaces [] = " ";
3359 char lexbuf [256];
3360 char mbuf [1024];
3361 char fbuf [1024];
3362 unsigned i, lix;
3363
3364 do_percentm (mbuf, fmt);
3365#ifndef NO_SNPRINTF
3366 snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
3367 cfile -> tlname, cfile -> lexline, mbuf);
3368#else
3369 sprintf (fbuf, "%s line %d: %s",
3370 cfile -> tlname, cfile -> lexline, mbuf);
3371#endif
3372
cfdfb9f1 3373 va_start (list, fmt);
4bd8800e
TL
3374 vsnprintf (mbuf, sizeof mbuf, fbuf, list);
3375 va_end (list);
3376
3377 lix = 0;
3378 for (i = 0;
3379 cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
3380 if (lix < (sizeof lexbuf) - 1)
3381 lexbuf [lix++] = ' ';
3382 if (cfile -> token_line [i] == '\t') {
3383 for (lix;
3384 lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
3385 lexbuf [lix] = ' ';
3386 }
3387 }
3388 lexbuf [lix] = 0;
3389
3390#ifndef DEBUG
3391 syslog (log_priority | LOG_ERR, mbuf);
3392 syslog (log_priority | LOG_ERR, cfile -> token_line);
3393 if (cfile -> lexchar < 81)
3394 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
3395#endif
3396
3397 if (log_perror) {
3398 write (2, mbuf, strlen (mbuf));
3399 write (2, "\n", 1);
3400 write (2, cfile -> token_line, strlen (cfile -> token_line));
3401 write (2, "\n", 1);
3402 if (cfile -> lexchar < 81)
3403 write (2, lexbuf, lix);
3404 write (2, "^\n", 2);
3405 }
3406
3407 cfile -> warnings_occurred = 1;
3408
3409 return 0;
3410}