]> git.ipfire.org Git - thirdparty/dhcp.git/blame - common/parse.c
Define SOCKLEN_T
[thirdparty/dhcp.git] / common / parse.c
CommitLineData
63115431
TL
1/* parse.c
2
3 Common parser code for dhcpd and dhclient. */
4
5/*
49733f31
TL
6 * Copyright (c) 1995-2000 Internet Software Consortium.
7 * All rights reserved.
63115431 8 *
49733f31
TL
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
63115431 12 *
49733f31
TL
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
63115431 21 *
49733f31
TL
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
63115431
TL
42 */
43
44#ifndef lint
45static char copyright[] =
ca5956dc 46"$Id: parse.c,v 1.85 2000/09/21 07:52:19 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n";
63115431
TL
47#endif /* not lint */
48
49#include "dhcpd.h"
63115431
TL
50
51/* Skip to the semicolon ending the current statement. If we encounter
52 braces, the matching closing brace terminates the statement. If we
53 encounter a right brace but haven't encountered a left brace, return
54 leaving the brace in the token buffer for the caller. If we see a
55 semicolon and haven't seen a left brace, return. This lets us skip
56 over:
57
58 statement;
59 statement foo bar { }
60 statement foo bar { statement { } }
61 statement}
62
63 ...et cetera. */
64
65void skip_to_semi (cfile)
4615d498 66 struct parse *cfile;
cea8b5c9
TL
67{
68 skip_to_rbrace (cfile, 0);
69}
70
71void skip_to_rbrace (cfile, brace_count)
4615d498 72 struct parse *cfile;
cea8b5c9 73 int brace_count;
63115431 74{
02a015fb 75 enum dhcp_token token;
b1b7b521 76 const char *val;
63115431 77
f579f39f
TL
78#if defined (DEBUG_TOKEN)
79 log_error ("skip_to_rbrace: %d\n", brace_count);
80#endif
63115431
TL
81 do {
82 token = peek_token (&val, cfile);
83 if (token == RBRACE) {
efc79acb 84 token = next_token (&val, cfile);
63115431 85 if (brace_count) {
63115431
TL
86 if (!--brace_count)
87 return;
88 } else
89 return;
90 } else if (token == LBRACE) {
91 brace_count++;
92 } else if (token == SEMI && !brace_count) {
93 token = next_token (&val, cfile);
94 return;
796ef008
TL
95 } else if (token == EOL) {
96 /* EOL only happens when parsing /etc/resolv.conf,
97 and we treat it like a semicolon because the
98 resolv.conf file is line-oriented. */
99 token = next_token (&val, cfile);
100 return;
63115431
TL
101 }
102 token = next_token (&val, cfile);
103 } while (token != EOF);
104}
105
106int parse_semi (cfile)
4615d498 107 struct parse *cfile;
63115431 108{
02a015fb 109 enum dhcp_token token;
b1b7b521 110 const char *val;
63115431
TL
111
112 token = next_token (&val, cfile);
113 if (token != SEMI) {
4615d498 114 parse_warn (cfile, "semicolon expected.");
63115431
TL
115 skip_to_semi (cfile);
116 return 0;
117 }
118 return 1;
119}
120
121/* string-parameter :== STRING SEMI */
122
123char *parse_string (cfile)
4615d498 124 struct parse *cfile;
63115431 125{
b1b7b521 126 const char *val;
02a015fb 127 enum dhcp_token token;
63115431
TL
128 char *s;
129
130 token = next_token (&val, cfile);
131 if (token != STRING) {
4615d498 132 parse_warn (cfile, "filename must be a string");
63115431
TL
133 skip_to_semi (cfile);
134 return (char *)0;
135 }
fdac15d9 136 s = (char *)dmalloc (strlen (val) + 1, MDL);
63115431 137 if (!s)
8ae2d595 138 log_fatal ("no memory for string %s.", val);
63115431
TL
139 strcpy (s, val);
140
141 if (!parse_semi (cfile))
142 return (char *)0;
143 return s;
144}
145
be6be08d
TL
146/*
147 * hostname :== IDENTIFIER
148 * | IDENTIFIER DOT
149 * | hostname DOT IDENTIFIER
150 */
796ef008
TL
151
152char *parse_host_name (cfile)
4615d498 153 struct parse *cfile;
796ef008 154{
b1b7b521 155 const char *val;
02a015fb 156 enum dhcp_token token;
b1b7b521 157 unsigned len = 0;
796ef008
TL
158 char *s;
159 char *t;
160 pair c = (pair)0;
88ab5737 161 int ltid = 0;
796ef008
TL
162
163 /* Read a dotted hostname... */
164 do {
165 /* Read a token, which should be an identifier. */
68dda014
TL
166 token = peek_token (&val, cfile);
167 if (!is_identifier (token) && token != NUMBER)
168 break;
796ef008 169 token = next_token (&val, cfile);
68dda014 170
796ef008 171 /* Store this identifier... */
fdac15d9 172 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
8ae2d595 173 log_fatal ("can't allocate temp space for hostname.");
796ef008
TL
174 strcpy (s, val);
175 c = cons ((caddr_t)s, c);
176 len += strlen (s) + 1;
177 /* Look for a dot; if it's there, keep going, otherwise
178 we're done. */
179 token = peek_token (&val, cfile);
88ab5737 180 if (token == DOT) {
796ef008 181 token = next_token (&val, cfile);
88ab5737
TL
182 ltid = 1;
183 } else
184 ltid = 0;
796ef008
TL
185 } while (token == DOT);
186
fa392aea
TL
187 /* Should be at least one token. */
188 if (!len)
189 return (char *)0;
190
796ef008 191 /* Assemble the hostname together into a string. */
88ab5737 192 if (!(s = (char *)dmalloc (len + ltid, MDL)))
8ae2d595 193 log_fatal ("can't allocate space for hostname.");
88ab5737 194 t = s + len + ltid;
796ef008 195 *--t = 0;
88ab5737
TL
196 if (ltid)
197 *--t = '.';
796ef008
TL
198 while (c) {
199 pair cdr = c -> cdr;
b1b7b521 200 unsigned l = strlen ((char *)(c -> car));
796ef008
TL
201 t -= l;
202 memcpy (t, (char *)(c -> car), l);
203 /* Free up temp space. */
fdac15d9
TL
204 dfree (c -> car, MDL);
205 dfree (c, MDL);
796ef008
TL
206 c = cdr;
207 if (t != s)
208 *--t = '.';
209 }
210 return s;
211}
212
be6be08d
TL
213/* ip-addr-or-hostname :== ip-address | hostname
214 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
215
216 Parse an ip address or a hostname. If uniform is zero, put in
217 an expr_substring node to limit hostnames that evaluate to more
218 than one IP address. */
219
02a015fb
TL
220int parse_ip_addr_or_hostname (expr, cfile, uniform)
221 struct expression **expr;
4615d498 222 struct parse *cfile;
be6be08d
TL
223 int uniform;
224{
b1b7b521 225 const char *val;
02a015fb 226 enum dhcp_token token;
be6be08d 227 unsigned char addr [4];
b1b7b521 228 unsigned len = sizeof addr;
be6be08d 229 char *name;
02a015fb 230 struct expression *x = (struct expression *)0;
be6be08d
TL
231
232 token = peek_token (&val, cfile);
233 if (is_identifier (token)) {
234 name = parse_host_name (cfile);
235 if (!name)
02a015fb
TL
236 return 0;
237 if (!make_host_lookup (expr, name))
238 return 0;
239 if (!uniform) {
240 if (!make_limit (&x, *expr, 4))
241 return 0;
4bd8800e 242 expression_dereference (expr, MDL);
02a015fb
TL
243 *expr = x;
244 }
be6be08d
TL
245 } else if (token == NUMBER) {
246 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
02a015fb
TL
247 return 0;
248 return make_const_data (expr, addr, len, 0, 1);
be6be08d
TL
249 } else {
250 if (token != RBRACE && token != LBRACE)
251 token = next_token (&val, cfile);
4615d498 252 parse_warn (cfile, "%s (%d): expecting IP address or hostname",
be6be08d
TL
253 val, token);
254 if (token != SEMI)
255 skip_to_semi (cfile);
02a015fb 256 return 0;
be6be08d
TL
257 }
258
02a015fb 259 return 1;
be6be08d
TL
260}
261
262/*
263 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
264 */
265
796ef008 266int parse_ip_addr (cfile, addr)
4615d498 267 struct parse *cfile;
796ef008
TL
268 struct iaddr *addr;
269{
b1b7b521 270 const char *val;
02a015fb 271 enum dhcp_token token;
796ef008
TL
272
273 addr -> len = 4;
274 if (parse_numeric_aggregate (cfile, addr -> iabuf,
275 &addr -> len, DOT, 10, 8))
276 return 1;
277 return 0;
278}
279
be6be08d
TL
280/*
281 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
282 * hardware-type :== ETHERNET | TOKEN_RING
283 */
63115431
TL
284
285void parse_hardware_param (cfile, hardware)
4615d498 286 struct parse *cfile;
63115431
TL
287 struct hardware *hardware;
288{
b1b7b521 289 const char *val;
02a015fb 290 enum dhcp_token token;
e703795d 291 unsigned hlen;
63115431
TL
292 unsigned char *t;
293
294 token = next_token (&val, cfile);
295 switch (token) {
296 case ETHERNET:
9fb2fb28 297 hardware -> hbuf [0] = HTYPE_ETHER;
63115431
TL
298 break;
299 case TOKEN_RING:
9fb2fb28 300 hardware -> hbuf [0] = HTYPE_IEEE802;
63115431 301 break;
cea8b5c9 302 case FDDI:
9fb2fb28 303 hardware -> hbuf [0] = HTYPE_FDDI;
cea8b5c9 304 break;
63115431 305 default:
4615d498 306 parse_warn (cfile, "expecting a network hardware type");
63115431
TL
307 skip_to_semi (cfile);
308 return;
309 }
310
311 /* Parse the hardware address information. Technically,
312 it would make a lot of sense to restrict the length of the
313 data we'll accept here to the length of a particular hardware
314 address type. Unfortunately, there are some broken clients
315 out there that put bogus data in the chaddr buffer, and we accept
316 that data in the lease file rather than simply failing on such
317 clients. Yuck. */
318 hlen = 0;
319 t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen,
320 COLON, 16, 8);
321 if (!t)
322 return;
9fb2fb28 323 if (hlen + 1 > sizeof hardware -> hbuf) {
fdac15d9 324 dfree (t, MDL);
4615d498 325 parse_warn (cfile, "hardware address too long");
63115431 326 } else {
9fb2fb28
TL
327 hardware -> hlen = hlen + 1;
328 memcpy ((unsigned char *)&hardware -> hbuf [1], t, hlen);
329 if (hlen + 1 < sizeof hardware -> hbuf)
330 memset (&hardware -> hbuf [hlen + 1], 0,
331 (sizeof hardware -> hbuf) - hlen - 1);
fdac15d9 332 dfree (t, MDL);
63115431
TL
333 }
334
335 token = next_token (&val, cfile);
336 if (token != SEMI) {
4615d498 337 parse_warn (cfile, "expecting semicolon.");
63115431
TL
338 skip_to_semi (cfile);
339 }
340}
341
342/* lease-time :== NUMBER SEMI */
343
344void parse_lease_time (cfile, timep)
4615d498 345 struct parse *cfile;
63115431
TL
346 TIME *timep;
347{
b1b7b521 348 const char *val;
02a015fb 349 enum dhcp_token token;
63115431
TL
350
351 token = next_token (&val, cfile);
352 if (token != NUMBER) {
4615d498 353 parse_warn (cfile, "Expecting numeric lease time");
63115431
TL
354 skip_to_semi (cfile);
355 return;
356 }
4615d498 357 convert_num (cfile, (unsigned char *)timep, val, 10, 32);
63115431
TL
358 /* Unswap the number - convert_num returns stuff in NBO. */
359 *timep = ntohl (*timep); /* XXX */
360
361 parse_semi (cfile);
362}
363
364/* No BNF for numeric aggregates - that's defined by the caller. What
365 this function does is to parse a sequence of numbers seperated by
366 the token specified in seperator. If max is zero, any number of
367 numbers will be parsed; otherwise, exactly max numbers are
368 expected. Base and size tell us how to internalize the numbers
369 once they've been tokenized. */
370
371unsigned char *parse_numeric_aggregate (cfile, buf,
372 max, seperator, base, size)
4615d498 373 struct parse *cfile;
63115431 374 unsigned char *buf;
b1b7b521 375 unsigned *max;
63115431
TL
376 int seperator;
377 int base;
b1b7b521 378 unsigned size;
63115431 379{
b1b7b521 380 const char *val;
02a015fb 381 enum dhcp_token token;
63115431 382 unsigned char *bufp = buf, *s, *t;
b1b7b521 383 unsigned count = 0;
63115431
TL
384 pair c = (pair)0;
385
386 if (!bufp && *max) {
fdac15d9 387 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
63115431 388 if (!bufp)
1ff8f8ea
TL
389 log_fatal ("no space for numeric aggregate");
390 s = 0;
63115431
TL
391 } else
392 s = bufp;
393
394 do {
395 if (count) {
396 token = peek_token (&val, cfile);
397 if (token != seperator) {
398 if (!*max)
399 break;
400 if (token != RBRACE && token != LBRACE)
401 token = next_token (&val, cfile);
4615d498 402 parse_warn (cfile, "too few numbers.");
63115431
TL
403 if (token != SEMI)
404 skip_to_semi (cfile);
405 return (unsigned char *)0;
406 }
407 token = next_token (&val, cfile);
408 }
409 token = next_token (&val, cfile);
410
411 if (token == EOF) {
4615d498 412 parse_warn (cfile, "unexpected end of file");
63115431
TL
413 break;
414 }
415
416 /* Allow NUMBER_OR_NAME if base is 16. */
417 if (token != NUMBER &&
418 (base != 16 || token != NUMBER_OR_NAME)) {
4615d498 419 parse_warn (cfile, "expecting numeric value.");
63115431
TL
420 skip_to_semi (cfile);
421 return (unsigned char *)0;
422 }
423 /* If we can, convert the number now; otherwise, build
424 a linked list of all the numbers. */
425 if (s) {
4615d498 426 convert_num (cfile, s, val, base, size);
63115431
TL
427 s += size / 8;
428 } else {
fdac15d9 429 t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
63115431 430 if (!t)
8ae2d595 431 log_fatal ("no temp space for number.");
338303a4
TL
432 strcpy ((char *)t, val);
433 c = cons ((caddr_t)t, c);
63115431
TL
434 }
435 } while (++count != *max);
436
437 /* If we had to cons up a list, convert it now. */
438 if (c) {
fdac15d9 439 bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
63115431 440 if (!bufp)
1ff8f8ea 441 log_fatal ("no space for numeric aggregate.");
63115431
TL
442 s = bufp + count - size / 8;
443 *max = count;
444 }
445 while (c) {
446 pair cdr = c -> cdr;
4615d498 447 convert_num (cfile, s, (char *)(c -> car), base, size);
63115431
TL
448 s -= size / 8;
449 /* Free up temp space. */
fdac15d9
TL
450 dfree (c -> car, MDL);
451 dfree (c, MDL);
63115431
TL
452 c = cdr;
453 }
454 return bufp;
455}
456
4615d498
TL
457void convert_num (cfile, buf, str, base, size)
458 struct parse *cfile;
63115431 459 unsigned char *buf;
b1b7b521 460 const char *str;
63115431 461 int base;
b1b7b521 462 unsigned size;
63115431 463{
b1b7b521 464 const char *ptr = str;
63115431
TL
465 int negative = 0;
466 u_int32_t val = 0;
467 int tval;
468 int max;
469
470 if (*ptr == '-') {
471 negative = 1;
472 ++ptr;
473 }
474
475 /* If base wasn't specified, figure it out from the data. */
476 if (!base) {
477 if (ptr [0] == '0') {
478 if (ptr [1] == 'x') {
479 base = 16;
480 ptr += 2;
481 } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
482 base = 8;
483 ptr += 1;
484 } else {
485 base = 10;
486 }
487 } else {
488 base = 10;
489 }
490 }
491
492 do {
493 tval = *ptr++;
494 /* XXX assumes ASCII... */
495 if (tval >= 'a')
496 tval = tval - 'a' + 10;
497 else if (tval >= 'A')
498 tval = tval - 'A' + 10;
499 else if (tval >= '0')
500 tval -= '0';
501 else {
4615d498 502 parse_warn (cfile, "Bogus number: %s.", str);
63115431
TL
503 break;
504 }
505 if (tval >= base) {
4615d498
TL
506 parse_warn (cfile,
507 "Bogus number %s: digit %d not in base %d",
f420e08c 508 str, tval, base);
63115431
TL
509 break;
510 }
511 val = val * base + tval;
512 } while (*ptr);
513
514 if (negative)
515 max = (1 << (size - 1));
516 else
517 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
518 if (val > max) {
519 switch (base) {
520 case 8:
4615d498 521 parse_warn (cfile,
06afba54 522 "%s%lo exceeds max (%d) for precision.",
b3d594dd
TL
523 negative ? "-" : "",
524 (unsigned long)val, max);
63115431
TL
525 break;
526 case 16:
4615d498 527 parse_warn (cfile,
06afba54 528 "%s%lx exceeds max (%d) for precision.",
b3d594dd
TL
529 negative ? "-" : "",
530 (unsigned long)val, max);
63115431
TL
531 break;
532 default:
4615d498 533 parse_warn (cfile,
06afba54 534 "%s%lu exceeds max (%d) for precision.",
b3d594dd
TL
535 negative ? "-" : "",
536 (unsigned long)val, max);
63115431
TL
537 break;
538 }
539 }
540
541 if (negative) {
542 switch (size) {
543 case 8:
544 *buf = -(unsigned long)val;
545 break;
546 case 16:
b1b7b521 547 putShort (buf, -(long)val);
63115431
TL
548 break;
549 case 32:
b1b7b521 550 putLong (buf, -(long)val);
63115431
TL
551 break;
552 default:
4615d498
TL
553 parse_warn (cfile,
554 "Unexpected integer size: %d\n", size);
63115431
TL
555 break;
556 }
557 } else {
558 switch (size) {
559 case 8:
560 *buf = (u_int8_t)val;
561 break;
562 case 16:
563 putUShort (buf, (u_int16_t)val);
564 break;
565 case 32:
566 putULong (buf, val);
567 break;
568 default:
4615d498
TL
569 parse_warn (cfile,
570 "Unexpected integer size: %d\n", size);
63115431
TL
571 break;
572 }
573 }
574}
575
be6be08d
TL
576/*
577 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
a82abfc7
TL
578 * NUMBER COLON NUMBER COLON NUMBER SEMI |
579 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
580 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
be1ee858 581 * NEVER
be6be08d 582 *
a82abfc7
TL
583 * Dates are stored in GMT or with a timezone offset; first number is day
584 * of week; next is year/month/day; next is hours:minutes:seconds on a
585 * 24-hour clock, followed by the timezone offset in seconds, which is
586 * optional.
be6be08d 587 */
63115431
TL
588
589TIME parse_date (cfile)
4615d498 590 struct parse *cfile;
63115431
TL
591{
592 struct tm tm;
593 int guess;
a82abfc7 594 int tzoff, wday, year, mon, mday, hour, min, sec;
b1b7b521 595 const char *val;
02a015fb 596 enum dhcp_token token;
63115431
TL
597 static int months [11] = { 31, 59, 90, 120, 151, 181,
598 212, 243, 273, 304, 334 };
599
be1ee858 600 /* Day of week, or "never"... */
63115431 601 token = next_token (&val, cfile);
be1ee858
TL
602 if (token == NEVER) {
603 if (!parse_semi (cfile))
604 return 0;
605 return MAX_TIME;
606 }
607
63115431 608 if (token != NUMBER) {
4615d498 609 parse_warn (cfile, "numeric day of week expected.");
63115431
TL
610 if (token != SEMI)
611 skip_to_semi (cfile);
612 return (TIME)0;
613 }
a82abfc7 614 wday = atoi (val);
63115431
TL
615
616 /* Year... */
617 token = next_token (&val, cfile);
618 if (token != NUMBER) {
4615d498 619 parse_warn (cfile, "numeric year expected.");
63115431
TL
620 if (token != SEMI)
621 skip_to_semi (cfile);
622 return (TIME)0;
623 }
edca2b1a
TL
624
625 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
626 somebody invents a time machine, I think we can safely disregard
627 it. This actually works around a stupid Y2K bug that was present
628 in a very early beta release of dhcpd. */
a82abfc7
TL
629 year = atoi (val);
630 if (year > 1900)
631 year -= 1900;
63115431
TL
632
633 /* Slash seperating year from month... */
634 token = next_token (&val, cfile);
635 if (token != SLASH) {
4615d498
TL
636 parse_warn (cfile,
637 "expected slash seperating year from month.");
63115431
TL
638 if (token != SEMI)
639 skip_to_semi (cfile);
640 return (TIME)0;
641 }
642
643 /* Month... */
644 token = next_token (&val, cfile);
645 if (token != NUMBER) {
4615d498 646 parse_warn (cfile, "numeric month expected.");
63115431
TL
647 if (token != SEMI)
648 skip_to_semi (cfile);
649 return (TIME)0;
650 }
a82abfc7 651 mon = atoi (val) - 1;
63115431
TL
652
653 /* Slash seperating month from day... */
654 token = next_token (&val, cfile);
655 if (token != SLASH) {
4615d498
TL
656 parse_warn (cfile,
657 "expected slash seperating month from day.");
63115431
TL
658 if (token != SEMI)
659 skip_to_semi (cfile);
660 return (TIME)0;
661 }
662
663 /* Month... */
664 token = next_token (&val, cfile);
665 if (token != NUMBER) {
4615d498 666 parse_warn (cfile, "numeric day of month expected.");
63115431
TL
667 if (token != SEMI)
668 skip_to_semi (cfile);
669 return (TIME)0;
670 }
a82abfc7 671 mday = atoi (val);
63115431
TL
672
673 /* Hour... */
674 token = next_token (&val, cfile);
675 if (token != NUMBER) {
4615d498 676 parse_warn (cfile, "numeric hour expected.");
63115431
TL
677 if (token != SEMI)
678 skip_to_semi (cfile);
679 return (TIME)0;
680 }
a82abfc7 681 hour = atoi (val);
63115431
TL
682
683 /* Colon seperating hour from minute... */
684 token = next_token (&val, cfile);
685 if (token != COLON) {
4615d498
TL
686 parse_warn (cfile,
687 "expected colon seperating hour from minute.");
63115431
TL
688 if (token != SEMI)
689 skip_to_semi (cfile);
690 return (TIME)0;
691 }
692
693 /* Minute... */
694 token = next_token (&val, cfile);
695 if (token != NUMBER) {
4615d498 696 parse_warn (cfile, "numeric minute expected.");
63115431
TL
697 if (token != SEMI)
698 skip_to_semi (cfile);
699 return (TIME)0;
700 }
a82abfc7 701 min = atoi (val);
63115431
TL
702
703 /* Colon seperating minute from second... */
704 token = next_token (&val, cfile);
705 if (token != COLON) {
4615d498
TL
706 parse_warn (cfile,
707 "expected colon seperating hour from minute.");
63115431
TL
708 if (token != SEMI)
709 skip_to_semi (cfile);
710 return (TIME)0;
711 }
712
713 /* Minute... */
714 token = next_token (&val, cfile);
715 if (token != NUMBER) {
4615d498 716 parse_warn (cfile, "numeric minute expected.");
63115431
TL
717 if (token != SEMI)
718 skip_to_semi (cfile);
719 return (TIME)0;
720 }
a82abfc7 721 sec = atoi (val);
63115431 722
a82abfc7
TL
723 token = peek_token (&val, cfile);
724 if (token == NUMBER) {
725 token = next_token (&val, cfile);
726 tzoff = atoi (val);
727 } else
728 tzoff = 0;
63115431
TL
729
730 /* Make sure the date ends in a semicolon... */
25541f2f 731 if (!parse_semi (cfile))
63115431 732 return 0;
63115431
TL
733
734 /* Guess the time value... */
a82abfc7
TL
735 guess = ((((((365 * (year - 70) + /* Days in years since '70 */
736 (year - 69) / 4 + /* Leap days since '70 */
737 (mon /* Days in months this year */
738 ? months [mon - 1]
63115431 739 : 0) +
a82abfc7
TL
740 (mon > 1 && /* Leap day this year */
741 !((year - 72) & 3)) +
742 mday - 1) * 24) + /* Day of month */
743 hour) * 60) +
744 min) * 60) + sec + tzoff;
63115431
TL
745
746 /* This guess could be wrong because of leap seconds or other
747 weirdness we don't know about that the system does. For
748 now, we're just going to accept the guess, but at some point
749 it might be nice to do a successive approximation here to
750 get an exact value. Even if the error is small, if the
751 server is restarted frequently (and thus the lease database
752 is reread), the error could accumulate into something
753 significant. */
754
755 return guess;
756}
4761e04b 757
be6be08d
TL
758/*
759 * option-name :== IDENTIFIER |
760 IDENTIFIER . IDENTIFIER
761 */
762
b1b7b521 763struct option *parse_option_name (cfile, allocate, known)
4615d498 764 struct parse *cfile;
6b4b0ec7 765 int allocate;
b1b7b521 766 int *known;
4761e04b 767{
b1b7b521 768 const char *val;
02a015fb 769 enum dhcp_token token;
6b4b0ec7 770 char *uname;
4761e04b
TL
771 struct universe *universe;
772 struct option *option;
773
774 token = next_token (&val, cfile);
775 if (!is_identifier (token)) {
4615d498
TL
776 parse_warn (cfile,
777 "expecting identifier after option keyword.");
4761e04b
TL
778 if (token != SEMI)
779 skip_to_semi (cfile);
780 return (struct option *)0;
781 }
fdac15d9 782 uname = dmalloc (strlen (val) + 1, MDL);
6b4b0ec7
TL
783 if (!uname)
784 log_fatal ("no memory for uname information.");
785 strcpy (uname, val);
4761e04b
TL
786 token = peek_token (&val, cfile);
787 if (token == DOT) {
788 /* Go ahead and take the DOT token... */
789 token = next_token (&val, cfile);
790
791 /* The next token should be an identifier... */
792 token = next_token (&val, cfile);
793 if (!is_identifier (token)) {
4615d498 794 parse_warn (cfile, "expecting identifier after '.'");
4761e04b
TL
795 if (token != SEMI)
796 skip_to_semi (cfile);
797 return (struct option *)0;
798 }
799
800 /* Look up the option name hash table for the specified
6b4b0ec7 801 uname. */
20916cae
TL
802 universe = (struct universe *)0;
803 if (!universe_hash_lookup (&universe, universe_hash,
804 uname, 0, MDL)) {
4615d498 805 parse_warn (cfile, "no option space named %s.", uname);
4761e04b
TL
806 skip_to_semi (cfile);
807 return (struct option *)0;
808 }
809 } else {
810 /* Use the default hash table, which contains all the
811 standard dhcp option names. */
6b4b0ec7 812 val = uname;
4761e04b
TL
813 universe = &dhcp_universe;
814 }
815
816 /* Look up the actual option info... */
20916cae
TL
817 option = (struct option *)0;
818 option_hash_lookup (&option, universe -> hash, val, 0, MDL);
4761e04b
TL
819
820 /* If we didn't get an option structure, it's an undefined option. */
b1b7b521
TL
821 if (option) {
822 *known = 1;
823 } else {
6b4b0ec7
TL
824 /* If we've been told to allocate, that means that this
825 (might) be an option code definition, so we'll create
826 an option structure just in case. */
827 if (allocate) {
4bd8800e 828 option = new_option (MDL);
6b4b0ec7
TL
829 if (val == uname)
830 option -> name = val;
831 else {
b1b7b521 832 char *s;
fdac15d9
TL
833 dfree (uname, MDL);
834 s = dmalloc (strlen (val) + 1, MDL);
b1b7b521 835 if (!s)
4615d498
TL
836 log_fatal ("no memory for option %s.%s",
837 universe -> name, val);
b1b7b521
TL
838 strcpy (s, val);
839 option -> name = s;
6b4b0ec7
TL
840 }
841 option -> universe = universe;
b1b7b521 842 option -> code = 0;
6b4b0ec7
TL
843 return option;
844 }
845 if (val == uname)
4615d498 846 parse_warn (cfile, "no option named %s", val);
4761e04b 847 else
4615d498 848 parse_warn (cfile, "no option named %s in space %s",
6b4b0ec7 849 val, uname);
4761e04b
TL
850 skip_to_semi (cfile);
851 return (struct option *)0;
852 }
853
854 /* Free the initial identifier token. */
fdac15d9 855 dfree (uname, MDL);
4761e04b
TL
856 return option;
857}
858
52c9d530
TL
859/* IDENTIFIER SEMI */
860
861void parse_option_space_decl (cfile)
4615d498 862 struct parse *cfile;
52c9d530
TL
863{
864 int token;
b1b7b521 865 const char *val;
52c9d530 866 struct universe **ua, *nu;
b1b7b521 867 char *s;
52c9d530
TL
868
869 next_token (&val, cfile); /* Discard the SPACE token, which was
870 checked by the caller. */
871 token = next_token (&val, cfile);
872 if (!is_identifier (token)) {
4615d498 873 parse_warn (cfile, "expecting identifier.");
52c9d530
TL
874 skip_to_semi (cfile);
875 return;
876 }
4bd8800e 877 nu = new_universe (MDL);
52c9d530
TL
878 if (!nu)
879 log_fatal ("No memory for new option space.");
880
881 /* Set up the server option universe... */
fdac15d9 882 s = dmalloc (strlen (val) + 1, MDL);
b1b7b521 883 if (!s)
52c9d530 884 log_fatal ("No memory for new option space name.");
b1b7b521
TL
885 strcpy (s, val);
886 nu -> name = s;
52c9d530
TL
887 nu -> lookup_func = lookup_hashed_option;
888 nu -> option_state_dereference =
889 hashed_option_state_dereference;
890 nu -> get_func = hashed_option_get;
891 nu -> set_func = hashed_option_set;
892 nu -> save_func = save_hashed_option;
893 nu -> delete_func = delete_hashed_option;
894 nu -> encapsulate = hashed_option_space_encapsulate;
895 nu -> length_size = 1;
896 nu -> tag_size = 1;
897 nu -> store_tag = putUChar;
898 nu -> store_length = putUChar;
899 nu -> index = universe_count++;
900 if (nu -> index >= universe_max) {
fdac15d9 901 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
52c9d530
TL
902 if (!ua)
903 log_fatal ("No memory to expand option space array.");
904 memcpy (ua, universes, universe_max * sizeof *ua);
905 universe_max *= 2;
fdac15d9 906 dfree (universes, MDL);
52c9d530
TL
907 universes = ua;
908 }
909 universes [nu -> index] = nu;
7d9784f6 910 nu -> hash = new_hash (0, 0, 1);
52c9d530
TL
911 if (!nu -> hash)
912 log_fatal ("Can't allocate %s option hash table.", nu -> name);
20916cae 913 universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
52c9d530
TL
914 parse_semi (cfile);
915}
916
6b4b0ec7
TL
917/* This is faked up to look good right now. Ideally, this should do a
918 recursive parse and allow arbitrary data structure definitions, but for
919 now it just allows you to specify a single type, an array of single types,
920 a sequence of types, or an array of sequences of types.
921
922 ocd :== NUMBER EQUALS ocsd SEMI
923
924 ocsd :== ocsd_type |
925 ocsd_type_sequence |
d8fc5060 926 ARRAY OF ocsd_simple_type_sequence
6b4b0ec7
TL
927
928 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
929
d8fc5060
TL
930 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
931
932 ocsd_types :== ocsd_type |
933 ocsd_types ocsd_type
934
935 ocsd_type :== ocsd_simple_type |
936 ARRAY OF ocsd_simple_type
937
938 ocsd_simple_types :== ocsd_simple_type |
939 ocsd_simple_types ocsd_simple_type
940
941 ocsd_simple_type :== BOOLEAN |
942 INTEGER NUMBER |
943 SIGNED INTEGER NUMBER |
944 UNSIGNED INTEGER NUMBER |
945 IP-ADDRESS |
946 TEXT |
947 STRING */
6b4b0ec7
TL
948
949int parse_option_code_definition (cfile, option)
4615d498 950 struct parse *cfile;
6b4b0ec7
TL
951 struct option *option;
952{
b1b7b521 953 const char *val;
6b4b0ec7 954 enum dhcp_token token;
b1b7b521 955 unsigned arrayp = 0;
6b4b0ec7
TL
956 int recordp = 0;
957 int no_more_in_record = 0;
958 char tokbuf [128];
b1b7b521 959 unsigned tokix = 0;
6b4b0ec7
TL
960 char type;
961 int code;
962 int is_signed;
b1b7b521 963 char *s;
6b4b0ec7
TL
964
965 /* Parse the option code. */
966 token = next_token (&val, cfile);
967 if (token != NUMBER) {
4615d498 968 parse_warn (cfile, "expecting option code number.");
6b4b0ec7
TL
969 skip_to_semi (cfile);
970 return 0;
971 }
972 option -> code = atoi (val);
973
974 token = next_token (&val, cfile);
975 if (token != EQUAL) {
4615d498 976 parse_warn (cfile, "expecting \"=\"");
6b4b0ec7
TL
977 skip_to_semi (cfile);
978 return 0;
979 }
980
981 /* See if this is an array. */
982 token = next_token (&val, cfile);
983 if (token == ARRAY) {
984 token = next_token (&val, cfile);
985 if (token != OF) {
4615d498 986 parse_warn (cfile, "expecting \"of\".");
6b4b0ec7
TL
987 skip_to_semi (cfile);
988 return 0;
989 }
990 arrayp = 1;
991 token = next_token (&val, cfile);
992 }
993
994 if (token == LBRACE) {
995 recordp = 1;
996 token = next_token (&val, cfile);
997 }
998
999 /* At this point we're expecting a data type. */
1000 next_type:
1001 switch (token) {
d8fc5060
TL
1002 case ARRAY:
1003 if (arrayp) {
1004 parse_warn (cfile, "no nested arrays.");
1005 skip_to_rbrace (cfile, recordp);
1006 if (recordp)
1007 skip_to_semi (cfile);
1008 return 0;
1009 }
1010 token = next_token (&val, cfile);
1011 if (token != OF) {
1012 parse_warn (cfile, "expecting \"of\".");
1013 skip_to_semi (cfile);
1014 return 0;
1015 }
1016 arrayp = recordp + 1;
1017 token = next_token (&val, cfile);
1018 if ((recordp) && (token == LBRACE)) {
1019 parse_warn (cfile,
1020 "only uniform array inside record.");
1021 skip_to_rbrace (cfile, recordp + 1);
1022 skip_to_semi (cfile);
1023 return 0;
1024 }
1025 goto next_type;
6b4b0ec7
TL
1026 case BOOLEAN:
1027 type = 'f';
1028 break;
1029 case INTEGER:
1030 is_signed = 1;
1031 parse_integer:
1032 token = next_token (&val, cfile);
1033 if (token != NUMBER) {
4615d498 1034 parse_warn (cfile, "expecting number.");
6b4b0ec7
TL
1035 skip_to_rbrace (cfile, recordp);
1036 if (recordp)
1037 skip_to_semi (cfile);
1038 return 0;
1039 }
1040 switch (atoi (val)) {
1041 case 8:
1042 type = is_signed ? 'b' : 'B';
1043 break;
1044 case 16:
1045 type = is_signed ? 's' : 'S';
1046 break;
1047 case 32:
1048 type = is_signed ? 'l' : 'L';
1049 break;
1050 default:
4615d498
TL
1051 parse_warn (cfile,
1052 "%s bit precision is not supported.", val);
6b4b0ec7
TL
1053 skip_to_rbrace (cfile, recordp);
1054 if (recordp)
1055 skip_to_semi (cfile);
1056 return 0;
1057 }
1058 break;
1059 case SIGNED:
1060 is_signed = 1;
1061 parse_signed:
1062 token = next_token (&val, cfile);
1063 if (token != INTEGER) {
4615d498 1064 parse_warn (cfile, "expecting \"integer\" keyword.");
6b4b0ec7
TL
1065 skip_to_rbrace (cfile, recordp);
1066 if (recordp)
1067 skip_to_semi (cfile);
1068 return 0;
1069 }
1070 goto parse_integer;
1071 case UNSIGNED:
1072 is_signed = 0;
1073 goto parse_signed;
1074
1075 case IP_ADDRESS:
1076 type = 'I';
1077 break;
1078 case TEXT:
1079 type = 't';
1080 no_arrays:
1081 if (arrayp) {
4615d498 1082 parse_warn (cfile, "arrays of text strings not %s",
6b4b0ec7
TL
1083 "yet supported.");
1084 skip_to_rbrace (cfile, recordp);
1085 if (recordp)
1086 skip_to_semi (cfile);
1087 return 0;
1088 }
1089 no_more_in_record = 1;
1090 break;
ef91cb39 1091 case STRING_TOKEN:
6b4b0ec7
TL
1092 type = 'X';
1093 goto no_arrays;
1094
1095 default:
4615d498 1096 parse_warn (cfile, "unknown data type %s", val);
6b4b0ec7
TL
1097 skip_to_rbrace (cfile, recordp);
1098 if (recordp)
1099 skip_to_semi (cfile);
1100 return 0;
1101 }
1102
1103 if (tokix == sizeof tokbuf) {
4615d498 1104 parse_warn (cfile, "too many types in record.");
6b4b0ec7
TL
1105 skip_to_rbrace (cfile, recordp);
1106 if (recordp)
1107 skip_to_semi (cfile);
1108 return 0;
1109 }
1110 tokbuf [tokix++] = type;
1111
1112 if (recordp) {
1113 token = next_token (&val, cfile);
d8fc5060
TL
1114 if (arrayp > recordp) {
1115 if (tokix == sizeof tokbuf) {
1116 parse_warn (cfile,
1117 "too many types in record.");
1118 skip_to_rbrace (cfile, 1);
1119 skip_to_semi (cfile);
1120 return 0;
1121 }
1122 arrayp = 0;
1123 tokbuf[tokix++] = 'a';
1124 }
6b4b0ec7
TL
1125 if (token == COMMA) {
1126 if (no_more_in_record) {
4615d498
TL
1127 parse_warn (cfile,
1128 "%s must be at end of record.",
6b4b0ec7
TL
1129 type == 't' ? "text" : "string");
1130 skip_to_rbrace (cfile, 1);
1131 if (recordp)
1132 skip_to_semi (cfile);
1133 return 0;
1134 }
1135 token = next_token (&val, cfile);
1136 goto next_type;
1137 }
1138 if (token != RBRACE) {
4615d498 1139 parse_warn (cfile, "expecting right brace.");
6b4b0ec7
TL
1140 skip_to_rbrace (cfile, 1);
1141 if (recordp)
1142 skip_to_semi (cfile);
1143 return 0;
1144 }
1145 }
1146 if (!parse_semi (cfile)) {
4615d498 1147 parse_warn (cfile, "semicolon expected.");
6b4b0ec7
TL
1148 skip_to_semi (cfile);
1149 if (recordp)
1150 skip_to_semi (cfile);
1151 return 0;
1152 }
d8fc5060 1153 s = dmalloc (tokix + ((arrayp) ? 1 : 0) + 1, MDL);
b1b7b521 1154 if (!s)
6b4b0ec7 1155 log_fatal ("no memory for option format.");
b1b7b521 1156 memcpy (s, tokbuf, tokix);
6b4b0ec7 1157 if (arrayp)
d8fc5060 1158 s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
b1b7b521
TL
1159 s [tokix] = 0;
1160 option -> format = s;
6b4b0ec7
TL
1161 if (option -> universe -> options [option -> code]) {
1162 /* XXX Free the option, but we can't do that now because they
1163 XXX may start out static. */
1164 }
1165 option -> universe -> options [option -> code] = option;
20916cae 1166 option_hash_add (option -> universe -> hash,
165bce70 1167 (const char *)option -> name,
20916cae 1168 0, option, MDL);
6b4b0ec7
TL
1169 return 1;
1170}
1171
028b1f6a
TL
1172/*
1173 * base64 :== NUMBER_OR_STRING
1174 */
1175
1176int parse_base64 (data, cfile)
1177 struct data_string *data;
1178 struct parse *cfile;
1179{
1180 enum dhcp_token token;
1181 const char *val;
8f01f9ec 1182 int i, j, k;
028b1f6a 1183 unsigned acc = 0;
6b474b5b
TL
1184 static unsigned char
1185 from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1186 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1187 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1188 60, 61, 64, 64, 64, 64, 64, 64, /* 90:;<=>? */
1189 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1190 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1191 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1192 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1193 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1194 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1195 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1196 59, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
8f01f9ec
TL
1197 struct string_list *bufs = (struct string_list *)0,
1198 *last = (struct string_list *)0,
1199 *t;
1200 int cc = 0;
1201 int terminated = 0;
028b1f6a 1202
8f01f9ec 1203 token = peek_token (&val, cfile);
028b1f6a 1204 if (token == STRING) {
8f01f9ec 1205 token = next_token (&val, cfile);
028b1f6a
TL
1206 data -> len = strlen (val) + 1;
1207 if (!buffer_allocate (&data -> buffer, data -> len, MDL)) {
1208 parse_warn (cfile, "can't allocate string buffer");
1209 return 0;
1210 }
13b0934e 1211 strcpy ((char *)data -> buffer -> data, val);
028b1f6a
TL
1212 data -> terminated = 1;
1213 data -> data = data -> buffer -> data;
1214 return 1;
1215 }
1216
8f01f9ec
TL
1217 /* It's possible for a + or a / to cause a base64 quantity to be
1218 tokenized into more than one token, so we have to parse them all
1219 in before decoding. */
1220 do {
1221 int l;
1222
1223 token = next_token (&val, cfile);
1224 l = strlen (val);
1225 t = dmalloc (l + sizeof *t, MDL);
1226 if (!t)
1227 log_fatal ("no memory for base64 buffer.");
1228 memset (t, 0, (sizeof *t) - 1);
1229 strcpy (t -> string, val);
1230 cc += l;
1231 if (last)
1232 last -> next = t;
1233 else
1234 bufs = t;
1235 last = t;
1236 token = peek_token (&val, cfile);
1237 } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL ||
1238 token == NUMBER || token == PLUS || token == SLASH);
1239
1240 data -> len = cc;
028b1f6a
TL
1241 data -> len = (data -> len * 3) / 4;
1242 if (!buffer_allocate (&data -> buffer, data -> len, MDL)) {
1243 parse_warn (cfile, "can't allocate buffer for base64 data.");
1244 data -> len = 0;
1245 data -> data = (unsigned char *)0;
1246 return 0;
1247 }
1248
8f01f9ec
TL
1249 j = k = 0;
1250 for (t = bufs; t; t = t -> next) {
1251 for (i = 0; t -> string [i]; i++) {
1252 unsigned foo = t -> string [i];
1253 if (terminated && foo != '=') {
1254 parse_warn (cfile,
1255 "stuff after base64 '=' terminator: %s.",
1256 &t -> string [i]);
1257 goto bad;
1258 }
028b1f6a
TL
1259 if (foo < ' ' || foo > 'z') {
1260 bad64:
1261 parse_warn (cfile,
8f01f9ec
TL
1262 "invalid base64 character %d.",
1263 t -> string [i]);
1264 bad:
028b1f6a 1265 data_string_forget (data, MDL);
8f01f9ec 1266 goto out;
028b1f6a 1267 }
8f01f9ec
TL
1268 if (foo == '=')
1269 terminated = 1;
1270 else {
1271 foo = from64 [foo - ' '];
1272 if (foo == 64)
1273 goto bad64;
1274 acc = (acc << 6) + foo;
1275 switch (k % 4) {
1276 case 0:
1277 break;
1278 case 1:
1279 data -> buffer -> data [j++] = (acc >> 4);
1280 acc = acc & 0x0f;
1281 break;
1282
1283 case 2:
1284 data -> buffer -> data [j++] = (acc >> 2);
1285 acc = acc & 0x03;
1286 break;
1287 case 3:
1288 data -> buffer -> data [j++] = acc;
1289 acc = 0;
1290 break;
1291 }
1292 }
1293 k++;
1294 }
1295 }
1296 if (k % 4) {
1297 if (acc) {
1298 parse_warn (cfile,
1299 "partial base64 value left over: %d.",
1300 acc);
028b1f6a
TL
1301 }
1302 }
028b1f6a
TL
1303 data -> len = j;
1304 data -> data = data -> buffer -> data;
8f01f9ec
TL
1305 out:
1306 for (t = bufs; t; t = last) {
1307 last = t -> next;
1308 dfree (t, MDL);
1309 }
1310 if (data -> len)
1311 return 1;
1312 else
1313 return 0;
028b1f6a
TL
1314}
1315
1316
be6be08d
TL
1317/*
1318 * colon-seperated-hex-list :== NUMBER |
1319 * NUMBER COLON colon-seperated-hex-list
1320 */
1321
02a015fb
TL
1322int parse_cshl (data, cfile)
1323 struct data_string *data;
4615d498 1324 struct parse *cfile;
4761e04b 1325{
c5b0f529 1326 u_int8_t ibuf [128];
b1b7b521
TL
1327 unsigned ilen = 0;
1328 unsigned tlen = 0;
4761e04b
TL
1329 struct option_tag *sl = (struct option_tag *)0;
1330 struct option_tag *next, **last = &sl;
02a015fb 1331 enum dhcp_token token;
b1b7b521 1332 const char *val;
02a015fb 1333 unsigned char *rvp;
4761e04b
TL
1334
1335 do {
1336 token = next_token (&val, cfile);
1337 if (token != NUMBER && token != NUMBER_OR_NAME) {
4615d498 1338 parse_warn (cfile, "expecting hexadecimal number.");
4761e04b
TL
1339 skip_to_semi (cfile);
1340 for (; sl; sl = next) {
1341 next = sl -> next;
fdac15d9 1342 dfree (sl, MDL);
4761e04b 1343 }
02a015fb 1344 return 0;
4761e04b
TL
1345 }
1346 if (ilen == sizeof ibuf) {
1347 next = (struct option_tag *)
1348 dmalloc (ilen - 1 +
fdac15d9 1349 sizeof (struct option_tag), MDL);
4761e04b 1350 if (!next)
8ae2d595 1351 log_fatal ("no memory for string list.");
4761e04b
TL
1352 memcpy (next -> data, ibuf, ilen);
1353 *last = next;
1354 last = &next -> next;
1355 tlen += ilen;
1356 ilen = 0;
1357 }
4615d498 1358 convert_num (cfile, &ibuf [ilen++], val, 16, 8);
4761e04b
TL
1359
1360 token = peek_token (&val, cfile);
1361 if (token != COLON)
1362 break;
1363 token = next_token (&val, cfile);
1364 } while (1);
1365
4bd8800e 1366 if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
8ae2d595 1367 log_fatal ("no memory to store octet data.");
02a015fb
TL
1368 data -> data = &data -> buffer -> data [0];
1369 data -> len = tlen + ilen;
1370 data -> terminated = 0;
1371
b1b7b521 1372 rvp = &data -> buffer -> data [0];
4761e04b
TL
1373 while (sl) {
1374 next = sl -> next;
1375 memcpy (rvp, sl -> data, sizeof ibuf);
1376 rvp += sizeof ibuf;
fdac15d9 1377 dfree (sl, MDL);
4761e04b
TL
1378 sl = next;
1379 }
1380
1381 memcpy (rvp, ibuf, ilen);
02a015fb 1382 return 1;
4761e04b 1383}
be6be08d
TL
1384
1385/*
1386 * executable-statements :== executable-statement executable-statements |
1387 * executable-statement
1388 *
1389 * executable-statement :==
1390 * IF if-statement |
1391 * ADD class-name SEMI |
1392 * BREAK SEMI |
1393 * OPTION option-parameter SEMI |
1394 * SUPERSEDE option-parameter SEMI |
1395 * PREPEND option-parameter SEMI |
1396 * APPEND option-parameter SEMI
1397 */
1398
f579f39f 1399int parse_executable_statements (statements, cfile, lose, case_context)
79a65726 1400 struct executable_statement **statements;
4615d498 1401 struct parse *cfile;
be6be08d 1402 int *lose;
f579f39f 1403 enum expression_context case_context;
be6be08d 1404{
79a65726 1405 struct executable_statement **next;
be6be08d 1406
79a65726 1407 next = statements;
f579f39f 1408 while (parse_executable_statement (next, cfile, lose, case_context))
be6be08d 1409 next = &((*next) -> next);
02a015fb 1410 if (!*lose)
79a65726
TL
1411 return 1;
1412 return 0;
be6be08d
TL
1413}
1414
f579f39f 1415int parse_executable_statement (result, cfile, lose, case_context)
79a65726 1416 struct executable_statement **result;
4615d498 1417 struct parse *cfile;
be6be08d 1418 int *lose;
f579f39f 1419 enum expression_context case_context;
be6be08d 1420{
02a015fb 1421 enum dhcp_token token;
b1b7b521 1422 const char *val;
79a65726 1423 struct executable_statement base;
be6be08d
TL
1424 struct class *cta;
1425 struct option *option;
b1013db7 1426 struct option_cache *cache;
b1b7b521 1427 int known;
0776fd12 1428 int flag;
88ab5737 1429 int i;
fa392aea 1430 struct dns_zone *zone;
fa392aea 1431 isc_result_t status;
be6be08d 1432
b1013db7
TL
1433 token = peek_token (&val, cfile);
1434 switch (token) {
be6be08d 1435 case IF:
dce70f9f 1436 next_token (&val, cfile);
79a65726
TL
1437 return parse_if_statement (result, cfile, lose);
1438
eb018e2b 1439 case TOKEN_ADD:
efc79acb 1440 token = next_token (&val, cfile);
be6be08d
TL
1441 token = next_token (&val, cfile);
1442 if (token != STRING) {
4615d498 1443 parse_warn (cfile, "expecting class name.");
be6be08d
TL
1444 skip_to_semi (cfile);
1445 *lose = 1;
79a65726 1446 return 0;
be6be08d 1447 }
20916cae
TL
1448 cta = (struct class *)0;
1449 status = find_class (&cta, val, MDL);
1450 if (status != ISC_R_SUCCESS) {
1451 parse_warn (cfile, "class %s: %s",
1452 val, isc_result_totext (status));
be6be08d
TL
1453 skip_to_semi (cfile);
1454 *lose = 1;
79a65726 1455 return 0;
be6be08d
TL
1456 }
1457 if (!parse_semi (cfile)) {
1458 *lose = 1;
79a65726 1459 return 0;
be6be08d 1460 }
4bd8800e 1461 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1462 log_fatal ("no memory for new statement.");
1463 (*result) -> op = add_statement;
1464 (*result) -> data.add = cta;
be6be08d
TL
1465 break;
1466
1467 case BREAK:
1468 token = next_token (&val, cfile);
1469 if (!parse_semi (cfile)) {
1470 *lose = 1;
79a65726 1471 return 0;
be6be08d 1472 }
4bd8800e 1473 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1474 log_fatal ("no memory for new statement.");
1475 (*result) -> op = break_statement;
be6be08d
TL
1476 break;
1477
25541f2f
TL
1478 case SEND:
1479 *lose = 1;
4615d498 1480 parse_warn (cfile, "send not appropriate here.");
25541f2f 1481 skip_to_semi (cfile);
79a65726 1482 return 0;
25541f2f
TL
1483
1484 case SUPERSEDE:
be6be08d
TL
1485 case OPTION:
1486 token = next_token (&val, cfile);
b1b7b521
TL
1487 known = 0;
1488 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1489 if (!option) {
1490 *lose = 1;
79a65726 1491 return 0;
be6be08d 1492 }
79a65726 1493 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1494 supersede_option_statement);
1495
b1013db7 1496 case ALLOW:
0776fd12
TL
1497 flag = 1;
1498 goto pad;
b1013db7 1499 case DENY:
0776fd12
TL
1500 flag = 0;
1501 goto pad;
1502 case IGNORE:
1503 flag = 2;
1504 pad:
b1013db7
TL
1505 token = next_token (&val, cfile);
1506 cache = (struct option_cache *)0;
2db25842 1507 if (!parse_allow_deny (&cache, cfile, flag))
79a65726 1508 return 0;
4bd8800e 1509 if (!executable_statement_allocate (result, MDL))
79a65726
TL
1510 log_fatal ("no memory for new statement.");
1511 (*result) -> op = supersede_option_statement;
1512 (*result) -> data.option = cache;
b1013db7
TL
1513 break;
1514
be6be08d
TL
1515 case DEFAULT:
1516 token = next_token (&val, cfile);
f579f39f
TL
1517 token = peek_token (&val, cfile);
1518 if (token == COLON)
1519 goto switch_default;
b1b7b521
TL
1520 known = 0;
1521 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1522 if (!option) {
1523 *lose = 1;
79a65726 1524 return 0;
be6be08d 1525 }
79a65726 1526 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1527 default_option_statement);
1528
1529 case PREPEND:
1530 token = next_token (&val, cfile);
b1b7b521
TL
1531 known = 0;
1532 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1533 if (!option) {
1534 *lose = 1;
79a65726 1535 return 0;
be6be08d 1536 }
79a65726 1537 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1538 prepend_option_statement);
1539
1540 case APPEND:
1541 token = next_token (&val, cfile);
b1b7b521
TL
1542 known = 0;
1543 option = parse_option_name (cfile, 0, &known);
be6be08d
TL
1544 if (!option) {
1545 *lose = 1;
79a65726 1546 return 0;
be6be08d 1547 }
79a65726 1548 return parse_option_statement (result, cfile, 1, option,
be6be08d
TL
1549 append_option_statement);
1550
79a65726
TL
1551 case ON:
1552 token = next_token (&val, cfile);
79a65726
TL
1553 return parse_on_statement (result, cfile, lose);
1554
f579f39f
TL
1555 case SWITCH:
1556 token = next_token (&val, cfile);
1557 return parse_switch_statement (result, cfile, lose);
1558
1559 case CASE:
1560 token = next_token (&val, cfile);
1561 if (case_context == context_any) {
1562 parse_warn (cfile,
1563 "case statement in inappropriate scope.");
1564 *lose = 1;
1565 skip_to_semi (cfile);
1566 return 0;
1567 }
1568 return parse_case_statement (result,
1569 cfile, lose, case_context);
1570
1571 switch_default:
1572 token = next_token (&val, cfile);
1573 if (case_context == context_any) {
1574 parse_warn (cfile, "switch default statement in %s",
1575 "inappropriate scope.");
1576
1577 *lose = 1;
1578 return 0;
1579 } else {
4bd8800e 1580 if (!executable_statement_allocate (result, MDL))
f579f39f
TL
1581 log_fatal ("no memory for default statement.");
1582 (*result) -> op = default_statement;
1583 return 1;
1584 }
1585
31cb2a5f 1586 case DEFINE:
f579f39f
TL
1587 case TOKEN_SET:
1588 token = next_token (&val, cfile);
31cb2a5f
TL
1589 if (token == DEFINE)
1590 flag = 1;
1591 else
1592 flag = 0;
f579f39f
TL
1593
1594 token = next_token (&val, cfile);
1595 if (token != NAME && token != NUMBER_OR_NAME) {
1596 parse_warn (cfile,
1597 "%s can't be a variable name", val);
1598 badset:
1599 skip_to_semi (cfile);
1600 *lose = 1;
1601 return 0;
1602 }
1603
4bd8800e 1604 if (!executable_statement_allocate (result, MDL))
f579f39f 1605 log_fatal ("no memory for set statement.");
31cb2a5f 1606 (*result) -> op = flag ? define_statement : set_statement;
fdac15d9 1607 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
f579f39f
TL
1608 if (!(*result)->data.set.name)
1609 log_fatal ("can't allocate variable name");
1610 strcpy ((*result) -> data.set.name, val);
1611 token = next_token (&val, cfile);
f579f39f 1612
31cb2a5f
TL
1613 if (token == LPAREN) {
1614 struct string_list *head, *cur, *new;
1615 struct expression *expr;
1616 head = cur = (struct string_list *)0;
1617 do {
1618 token = next_token (&val, cfile);
1619 if (token == RPAREN)
1620 break;
1621 if (token != NAME && token != NUMBER_OR_NAME) {
1622 parse_warn (cfile,
1623 "expecting argument name");
1624 skip_to_rbrace (cfile, 0);
1625 *lose = 1;
1626 executable_statement_dereference
1627 (result, MDL);
1628 return 0;
1629 }
1630 new = ((struct string_list *)
1631 dmalloc (sizeof (struct string_list) +
1632 strlen (val), MDL));
1633 if (!new)
1634 log_fatal ("can't allocate string.");
1635 memset (new, 0, sizeof *new);
1636 strcpy (new -> string, val);
1637 if (cur) {
1638 cur -> next = new;
1639 cur = new;
1640 } else {
1641 head = cur = new;
1642 }
1643 token = next_token (&val, cfile);
1644 } while (token == COMMA);
1645
1646 if (token != RPAREN) {
1647 parse_warn (cfile, "expecting right paren.");
1648 badx:
1649 skip_to_semi (cfile);
f579f39f 1650 *lose = 1;
31cb2a5f
TL
1651 executable_statement_dereference (result, MDL);
1652 return 0;
1653 }
1654
1655 token = next_token (&val, cfile);
1656 if (token != LBRACE) {
1657 parse_warn (cfile, "expecting left brace.");
1658 goto badx;
1659 }
1660
1661 expr = (struct expression *)0;
1662 if (!(expression_allocate (&expr, MDL)))
1663 log_fatal ("can't allocate expression.");
1664 expr -> op = expr_function;
1665 if (!fundef_allocate (&expr -> data.func, MDL))
1666 log_fatal ("can't allocate fundef.");
1667 expr -> data.func -> args = head;
1668 (*result) -> data.set.expr = expr;
1669
1670 if (!(parse_executable_statements
1671 (&expr -> data.func -> statements, cfile, lose,
1672 case_context))) {
1673 if (*lose)
1674 goto badx;
1675 }
1676
1677 token = next_token (&val, cfile);
1678 if (token != RBRACE) {
1679 parse_warn (cfile, "expecting rigt brace.");
1680 goto badx;
1681 }
1682 } else {
1683 if (token != EQUAL) {
1684 parse_warn (cfile,
1685 "expecting '=' in %s statement.",
1686 flag ? "define" : "set");
1687 goto badset;
1688 }
1689
1690 if (!parse_expression (&(*result) -> data.set.expr,
1691 cfile, lose, context_any,
1692 (struct expression **)0,
1693 expr_none)) {
1694 if (!*lose)
1695 parse_warn (cfile,
1696 "expecting expression.");
1697 else
1698 *lose = 1;
1699 skip_to_semi (cfile);
1700 executable_statement_dereference (result, MDL);
1701 return 0;
1702 }
1703 parse_semi (cfile);
f579f39f 1704 }
f579f39f
TL
1705 break;
1706
fdac15d9
TL
1707 case UNSET:
1708 token = next_token (&val, cfile);
1709
1710 token = next_token (&val, cfile);
1711 if (token != NAME && token != NUMBER_OR_NAME) {
1712 parse_warn (cfile,
1713 "%s can't be a variable name", val);
1714 badunset:
1715 skip_to_semi (cfile);
1716 *lose = 1;
1717 return 0;
1718 }
1719
4bd8800e 1720 if (!executable_statement_allocate (result, MDL))
fdac15d9
TL
1721 log_fatal ("no memory for set statement.");
1722 (*result) -> op = unset_statement;
1723 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
1724 if (!(*result)->data.unset)
1725 log_fatal ("can't allocate variable name");
1726 strcpy ((*result) -> data.unset, val);
1727 parse_semi (cfile);
1728 break;
1729
1730 case EVAL:
1731 token = next_token (&val, cfile);
1732
4bd8800e 1733 if (!executable_statement_allocate (result, MDL))
fdac15d9
TL
1734 log_fatal ("no memory for eval statement.");
1735 (*result) -> op = eval_statement;
1736
1737 if (!parse_expression (&(*result) -> data.eval,
1738 cfile, lose, context_data, /* XXX */
1739 (struct expression **)0, expr_none)) {
1740 if (!*lose)
1741 parse_warn (cfile,
1742 "expecting data expression.");
1743 else
1744 *lose = 1;
1745 skip_to_semi (cfile);
4bd8800e 1746 executable_statement_dereference (result, MDL);
fdac15d9
TL
1747 return 0;
1748 }
1749 parse_semi (cfile);
1750 break;
1751
1b234d44
DN
1752 case RETURN:
1753 token = next_token (&val, cfile);
1754
1755 if (!executable_statement_allocate (result, MDL))
1756 log_fatal ("no memory for return statement.");
1757 (*result) -> op = return_statement;
1758
1759 if (!parse_expression (&(*result) -> data.retval,
1760 cfile, lose, context_data,
1761 (struct expression **)0, expr_none)) {
1762 if (!*lose)
1763 parse_warn (cfile,
1764 "expecting data expression.");
1765 else
1766 *lose = 1;
1767 skip_to_semi (cfile);
1768 executable_statement_dereference (result, MDL);
1769 return 0;
1770 }
1771 parse_semi (cfile);
1772 break;
1773
e7a9c293 1774 case LOG:
e7a9c293
DN
1775 token = next_token (&val, cfile);
1776
1777 if (!executable_statement_allocate (result, MDL))
1778 log_fatal ("no memory for log statement.");
1779 (*result) -> op = log_statement;
1780
1781 token = next_token (&val, cfile);
1782 if (token != LPAREN) {
1783 parse_warn (cfile, "left parenthesis expected.");
1784 skip_to_semi (cfile);
1785 *lose = 1;
1786 return 0;
1787 }
1788
1789 token = peek_token (&val, cfile);
1790 i = 1;
1791 if (token == FATAL) {
1792 (*result) -> data.log.priority = log_priority_fatal;
1793 } else if (token == ERROR) {
1794 (*result) -> data.log.priority = log_priority_error;
1795 } else if (token == TOKEN_DEBUG) {
1796 (*result) -> data.log.priority = log_priority_debug;
1797 } else if (token == INFO) {
1798 (*result) -> data.log.priority = log_priority_info;
1799 } else {
1800 (*result) -> data.log.priority = log_priority_debug;
1801 i = 0;
1802 }
1803 if (i) {
1804 token = next_token (&val, cfile);
1805 token = next_token (&val, cfile);
1806 if (token != COMMA) {
1807 parse_warn (cfile, "comma expected.");
1808 skip_to_semi (cfile);
1809 *lose = 1;
1810 return 0;
1811 }
1812 }
1813
1814 if (!(parse_data_expression
1815 (&(*result) -> data.log.expr, cfile, lose))) {
1816 skip_to_semi (cfile);
1817 *lose = 1;
1818 return 0;
1819 }
1820
1821 token = next_token (&val, cfile);
1822 if (token != RPAREN) {
1823 parse_warn (cfile, "right parenthesis expected.");
1824 skip_to_semi (cfile);
1825 *lose = 1;
1826 return 0;
1827 }
1828
1829 token = next_token (&val, cfile);
1830 if (token != SEMI) {
1831 parse_warn (cfile, "semicolon expected.");
1832 skip_to_semi (cfile);
1833 *lose = 1;
1834 return 0;
1835 }
1836 break;
1837
fa392aea
TL
1838 /* Not really a statement, but we parse it here anyway
1839 because it's appropriate for all DHCP agents with
1840 parsers. */
1841 case ZONE:
1842 token = next_token (&val, cfile);
028b1f6a 1843 zone = (struct dns_zone *)0;
fa392aea
TL
1844 if (!dns_zone_allocate (&zone, MDL))
1845 log_fatal ("no memory for new zone.");
1846 zone -> name = parse_host_name (cfile);
1847 if (!zone -> name) {
1848 badzone:
e7a9c293 1849 parse_warn (cfile, "expecting hostname.");
fa392aea
TL
1850 *lose = 1;
1851 skip_to_semi (cfile);
1852 dns_zone_dereference (&zone, MDL);
1853 return 0;
1854 }
88ab5737
TL
1855 i = strlen (zone -> name);
1856 if (zone -> name [i - 1] != '.') {
1857 parse_warn (cfile,
1858 "zone name must not be relative %s: %s",
1859 "(must end in '.')", zone -> name);
1860 }
fa392aea
TL
1861 if (!parse_zone (zone, cfile))
1862 goto badzone;
fa392aea 1863 status = enter_dns_zone (zone);
fa392aea
TL
1864 if (status != ISC_R_SUCCESS) {
1865 if (parse_semi (cfile))
028b1f6a
TL
1866 parse_warn (cfile, "dns zone key %s: %s",
1867 zone -> name,
fa392aea
TL
1868 isc_result_totext (status));
1869 dns_zone_dereference (&zone, MDL);
1870 return 0;
1871 }
1872 return 1;
1873
1874 /* Also not really a statement, but same idea as above. */
028b1f6a 1875 case KEY:
fa392aea 1876 token = next_token (&val, cfile);
028b1f6a 1877 if (!parse_key (cfile)) {
fa392aea 1878 *lose = 1;
fa392aea
TL
1879 return 0;
1880 }
028b1f6a 1881 return 1;
e7a9c293 1882
be6be08d 1883 default:
588af269 1884 if (config_universe && is_identifier (token)) {
20916cae
TL
1885 option = (struct option *)0;
1886 option_hash_lookup (&option, config_universe -> hash,
1887 val, 0, MDL);
588af269
TL
1888 if (option) {
1889 token = next_token (&val, cfile);
1890 return parse_option_statement
1891 (result, cfile, 1, option,
1892 supersede_option_statement);
1893 }
1894 }
1b234d44
DN
1895
1896 if (token == NUMBER_OR_NAME || token == NAME) {
1897 /* This is rather ugly. Since function calls are
1898 data expressions, fake up an eval statement. */
1899 if (!executable_statement_allocate (result, MDL))
1900 log_fatal ("no memory for eval statement.");
1901 (*result) -> op = eval_statement;
1902
1903 if (!parse_expression (&(*result) -> data.eval,
1904 cfile, lose, context_data,
1905 (struct expression **)0,
1906 expr_none)) {
1907 if (!*lose)
1908 parse_warn (cfile, "expecting "
1909 "function call.");
1910 else
1911 *lose = 1;
1912 skip_to_semi (cfile);
1913 executable_statement_dereference (result, MDL);
1914 return 0;
1915 }
1916 parse_semi (cfile);
1917 break;
1918 }
1919
be6be08d 1920 *lose = 0;
79a65726 1921 return 0;
be6be08d
TL
1922 }
1923
79a65726
TL
1924 return 1;
1925}
1926
fa392aea
TL
1927/* zone-statements :== zone-statement |
1928 zone-statement zone-statements
1929 zone-statement :==
1930 PRIMARY ip-addresses SEMI |
1931 SECONDARY ip-addresses SEMI |
028b1f6a
TL
1932 key-reference SEMI
1933 ip-addresses :== ip-addr-or-hostname |
1934 ip-addr-or-hostname COMMA ip-addresses
1935 key-reference :== KEY STRING |
1936 KEY identifier */
fa392aea
TL
1937
1938int parse_zone (struct dns_zone *zone, struct parse *cfile)
1939{
1940 int token;
1941 const char *val;
1942 struct option_cache *oc;
1943 int done = 0;
1944
028b1f6a
TL
1945 token = next_token (&val, cfile);
1946 if (token != LBRACE) {
1947 parse_warn (cfile, "expecting left brace");
1948 return 0;
1949 }
1950
fa392aea
TL
1951 do {
1952 token = peek_token (&val, cfile);
1953 switch (token) {
1954 case PRIMARY:
1955 if (zone -> primary) {
1956 parse_warn (cfile,
1957 "more than one primary.");
1958 skip_to_semi (cfile);
1959 return 0;
1960 }
1961 if (!option_cache_allocate (&zone -> primary, MDL))
1962 log_fatal ("can't allocate primary option cache.");
1963 oc = zone -> primary;
1964 goto consemup;
1965
1966 case SECONDARY:
1967 if (zone -> secondary) {
1968 parse_warn (cfile, "more than one secondary.");
1969 skip_to_semi (cfile);
1970 return 0;
1971 }
1972 if (!option_cache_allocate (&zone -> secondary, MDL))
1973 log_fatal ("can't allocate secondary.");
1974 oc = zone -> secondary;
1975 consemup:
1976 token = next_token (&val, cfile);
1977 do {
1978 struct expression *expr = (struct expression *)0;
1979 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
1980 parse_warn (cfile,
1981 "expecting IP addr or hostname.");
1982 skip_to_semi (cfile);
1983 return 0;
1984 }
1985 if (oc -> expression) {
1986 struct expression *old =
1987 (struct expression *)0;
1988 expression_reference (&old,
1989 oc -> expression,
1990 MDL);
1991 expression_dereference (&oc -> expression,
1992 MDL);
1993 if (!make_concat (&oc -> expression,
1994 old, expr))
1995 log_fatal ("no memory for concat.");
1996 expression_dereference (&expr, MDL);
1997 expression_dereference (&old, MDL);
1998 } else {
1999 expression_reference (&oc -> expression,
2000 expr, MDL);
2001 expression_dereference (&expr, MDL);
2002 }
2003 token = next_token (&val, cfile);
2004 } while (token == COMMA);
2005 if (token != SEMI) {
2006 parse_warn (cfile, "expecting semicolon.");
2007 skip_to_semi (cfile);
2008 return 0;
2009 }
2010 break;
2011
028b1f6a 2012 case KEY:
fa392aea
TL
2013 token = next_token (&val, cfile);
2014 token = next_token (&val, cfile);
028b1f6a 2015 if (token != STRING && !is_identifier (token)) {
fa392aea
TL
2016 parse_warn (cfile, "expecting key name.");
2017 skip_to_semi (cfile);
2018 return 0;
2019 }
49146f3c
DN
2020 if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2021 ISC_R_SUCCESS)
fa392aea
TL
2022 parse_warn (cfile, "unknown key %s", val);
2023 if (!parse_semi (cfile))
2024 return 0;
2025 break;
2026
2027 default:
2028 done = 1;
2029 break;
2030 }
2031 } while (!done);
2032
028b1f6a
TL
2033 token = next_token (&val, cfile);
2034 if (token != RBRACE) {
2035 parse_warn (cfile, "expecting right brace.");
2036 return 0;
2037 }
fa392aea
TL
2038 return 1;
2039}
2040
028b1f6a
TL
2041/* key-statements :== key-statement |
2042 key-statement key-statements
2043 key-statement :==
2044 ALGORITHM host-name SEMI |
2045 secret-definition SEMI
2046 secret-definition :== SECRET base64val |
2047 SECRET STRING */
2048
2049int parse_key (struct parse *cfile)
2050{
2051 int token;
2052 const char *val;
2053 int done = 0;
49146f3c
DN
2054 struct auth_key *key;
2055 struct data_string ds;
028b1f6a
TL
2056 isc_result_t status;
2057
2058 token = next_token (&val, cfile);
2059 if (token != STRING && !is_identifier (token)) {
2060 parse_warn (cfile, "expecting key name string.");
2061 skip_to_semi (cfile);
2062 return 0;
2063 }
49146f3c
DN
2064 key = (struct auth_key *)0;
2065 if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
028b1f6a
TL
2066 log_fatal ("no memory for tsig key");
2067 key -> name = dmalloc (strlen (val) + 1, MDL);
2068 if (!key -> name)
2069 log_fatal ("no memory for tsig key name.");
2070 strcpy (key -> name, val);
2071
2072 token = next_token (&val, cfile);
2073 if (token != LBRACE) {
2074 parse_warn (cfile, "expecting left brace");
2075 return 0;
2076 }
2077
2078 do {
2079 token = next_token (&val, cfile);
2080 switch (token) {
2081 case ALGORITHM:
2082 if (key -> algorithm) {
2083 parse_warn (cfile,
2084 "key %s: too many algorithms",
2085 key -> name);
2086 goto rbad;
2087 }
2088 key -> algorithm = parse_host_name (cfile);
2089 if (!key -> algorithm) {
2090 parse_warn (cfile,
2091 "expecting key algorithm name.");
2092 goto rbad;
2093 }
2094 if (!parse_semi (cfile))
2095 goto rbad;
2096 break;
2097
2098 case SECRET:
49146f3c 2099 if (key -> key) {
028b1f6a
TL
2100 parse_warn (cfile, "key %s: too many secrets",
2101 key -> name);
2102 goto rbad;
2103 }
49146f3c
DN
2104
2105 memset (&ds, 0, sizeof(ds));
2106 if (!parse_base64 (&ds, cfile))
2107 goto rbad;
2108 status = omapi_data_string_new (&key -> key, ds.len,
2109 MDL);
2110 if (status != ISC_R_SUCCESS)
028b1f6a 2111 goto rbad;
49146f3c
DN
2112 memcpy (key -> key -> value,
2113 ds.buffer -> data, ds.len);
2114 data_string_forget (&ds, MDL);
2115
028b1f6a
TL
2116 if (!parse_semi (cfile))
2117 goto rbad;
2118 break;
2119
2120 default:
2121 done = 1;
2122 break;
2123 }
2124 } while (!done);
2125 if (token != RBRACE) {
2126 parse_warn (cfile, "expecting right brace.");
2127 goto rbad;
2128 }
13b0934e
TL
2129 /* Allow the BIND 8 syntax, which has a semicolon after each
2130 closing brace. */
2131 token = peek_token (&val, cfile);
2132 if (token == SEMI)
2133 token = next_token (&val, cfile);
2134
2135 /* Remember the key. */
49146f3c 2136 status = omapi_auth_key_enter (key);
028b1f6a
TL
2137 if (status != ISC_R_SUCCESS) {
2138 parse_warn (cfile, "tsig key %s: %s",
2139 key -> name, isc_result_totext (status));
2140 goto bad;
2141 }
2142 return 1;
2143
2144 rbad:
2145 skip_to_rbrace (cfile, 1);
2146 bad:
49146f3c 2147 omapi_auth_key_dereference (&key, MDL);
028b1f6a
TL
2148 return 0;
2149}
79a65726 2150/*
f579f39f
TL
2151 * on-statement :== event-types LBRACE executable-statements RBRACE
2152 * event-types :== event-type OR event-types |
2153 * event-type
79a65726
TL
2154 * event-type :== EXPIRY | COMMIT | RELEASE
2155 */
2156
2157int parse_on_statement (result, cfile, lose)
2158 struct executable_statement **result;
4615d498 2159 struct parse *cfile;
79a65726
TL
2160 int *lose;
2161{
2162 enum dhcp_token token;
b1b7b521 2163 const char *val;
79a65726 2164
4bd8800e 2165 if (!executable_statement_allocate (result, MDL))
8ae2d595 2166 log_fatal ("no memory for new statement.");
33500c7d 2167 (*result) -> op = on_statement;
79a65726 2168
f579f39f
TL
2169 do {
2170 token = next_token (&val, cfile);
2171 switch (token) {
2172 case EXPIRY:
2173 (*result) -> data.on.evtypes |= ON_EXPIRY;
2174 break;
79a65726 2175
f579f39f 2176 case COMMIT:
fdac15d9 2177 (*result) -> data.on.evtypes |= ON_COMMIT;
f579f39f
TL
2178 break;
2179
2180 case RELEASE:
fdac15d9 2181 (*result) -> data.on.evtypes |= ON_RELEASE;
f579f39f
TL
2182 break;
2183
2184 default:
2185 parse_warn (cfile, "expecting a lease event type");
2186 skip_to_semi (cfile);
2187 *lose = 1;
4bd8800e 2188 executable_statement_dereference (result, MDL);
fdac15d9 2189 return 0;
f579f39f
TL
2190 }
2191 token = next_token (&val, cfile);
2192 } while (token == OR);
79a65726 2193
f579f39f
TL
2194 /* Semicolon means no statements. */
2195 if (token == SEMI)
2196 return 1;
2197
79a65726 2198 if (token != LBRACE) {
4615d498 2199 parse_warn (cfile, "left brace expected.");
79a65726
TL
2200 skip_to_semi (cfile);
2201 *lose = 1;
4bd8800e 2202 executable_statement_dereference (result, MDL);
79a65726
TL
2203 return 0;
2204 }
2205 if (!parse_executable_statements (&(*result) -> data.on.statements,
f579f39f 2206 cfile, lose, context_any)) {
79a65726
TL
2207 if (*lose) {
2208 /* Try to even things up. */
2209 do {
2210 token = next_token (&val, cfile);
2211 } while (token != EOF && token != RBRACE);
4bd8800e 2212 executable_statement_dereference (result, MDL);
79a65726
TL
2213 return 0;
2214 }
2215 }
2216 token = next_token (&val, cfile);
2217 if (token != RBRACE) {
4615d498 2218 parse_warn (cfile, "right brace expected.");
79a65726
TL
2219 skip_to_semi (cfile);
2220 *lose = 1;
4bd8800e 2221 executable_statement_dereference (result, MDL);
79a65726
TL
2222 return 0;
2223 }
2224 return 1;
be6be08d
TL
2225}
2226
f579f39f
TL
2227/*
2228 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2229 *
2230 */
2231
2232int parse_switch_statement (result, cfile, lose)
2233 struct executable_statement **result;
2234 struct parse *cfile;
2235 int *lose;
2236{
2237 enum dhcp_token token;
2238 const char *val;
2239
4bd8800e 2240 if (!executable_statement_allocate (result, MDL))
f579f39f
TL
2241 log_fatal ("no memory for new statement.");
2242 (*result) -> op = switch_statement;
2243
2244 token = next_token (&val, cfile);
2245 if (token != LPAREN) {
2246 parse_warn (cfile, "expecting left brace.");
2247 pfui:
2248 *lose = 1;
2249 skip_to_semi (cfile);
2250 gnorf:
4bd8800e 2251 executable_statement_dereference (result, MDL);
f579f39f
TL
2252 return 0;
2253 }
2254
2255 if (!parse_expression (&(*result) -> data.s_switch.expr,
2256 cfile, lose, context_data_or_numeric,
2257 (struct expression **)0, expr_none)) {
2258 if (!*lose) {
2259 parse_warn (cfile,
2260 "expecting data or numeric expression.");
2261 goto pfui;
2262 }
2263 goto gnorf;
2264 }
2265
2266 token = next_token (&val, cfile);
2267 if (token != RPAREN) {
2268 parse_warn (cfile, "right paren expected.");
2269 goto pfui;
2270 }
2271
2272 token = next_token (&val, cfile);
2273 if (token != LBRACE) {
2274 parse_warn (cfile, "left brace expected.");
2275 goto pfui;
2276 }
2277 if (!(parse_executable_statements
2278 (&(*result) -> data.s_switch.statements, cfile, lose,
2279 (is_data_expression ((*result) -> data.s_switch.expr)
2280 ? context_data : context_numeric)))) {
2281 if (*lose) {
2282 skip_to_rbrace (cfile, 1);
4bd8800e 2283 executable_statement_dereference (result, MDL);
f579f39f
TL
2284 return 0;
2285 }
2286 }
2287 token = next_token (&val, cfile);
2288 if (token != RBRACE) {
2289 parse_warn (cfile, "right brace expected.");
2290 goto pfui;
2291 }
2292 return 1;
2293}
2294
2295/*
2296 * case-statement :== CASE expr COLON
2297 *
2298 */
2299
2300int parse_case_statement (result, cfile, lose, case_context)
2301 struct executable_statement **result;
2302 struct parse *cfile;
2303 int *lose;
2304 enum expression_context case_context;
2305{
2306 enum dhcp_token token;
2307 const char *val;
2308
4bd8800e 2309 if (!executable_statement_allocate (result, MDL))
f579f39f
TL
2310 log_fatal ("no memory for new statement.");
2311 (*result) -> op = case_statement;
2312
2313 if (!parse_expression (&(*result) -> data.c_case,
2314 cfile, lose, case_context,
2315 (struct expression **)0, expr_none))
2316 {
2317 if (!*lose) {
2318 parse_warn (cfile, "expecting %s expression.",
2319 (case_context == context_data
2320 ? "data" : "numeric"));
2321 }
2322 pfui:
2323 *lose = 1;
2324 skip_to_semi (cfile);
4bd8800e 2325 executable_statement_dereference (result, MDL);
f579f39f
TL
2326 return 0;
2327 }
2328
2329 token = next_token (&val, cfile);
2330 if (token != COLON) {
2331 parse_warn (cfile, "colon expected.");
2332 goto pfui;
2333 }
2334 return 1;
2335}
2336
be6be08d
TL
2337/*
2338 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
2339 * else-statement
2340 *
2341 * else-statement :== <null> |
2342 * ELSE LBRACE executable-statements RBRACE |
2343 * ELSE IF if-statement |
2344 * ELSIF if-statement
2345 */
2346
79a65726
TL
2347int parse_if_statement (result, cfile, lose)
2348 struct executable_statement **result;
4615d498 2349 struct parse *cfile;
be6be08d
TL
2350 int *lose;
2351{
02a015fb 2352 enum dhcp_token token;
b1b7b521 2353 const char *val;
fdac15d9 2354 int parenp;
be6be08d 2355
4bd8800e 2356 if (!executable_statement_allocate (result, MDL))
79a65726
TL
2357 log_fatal ("no memory for if statement.");
2358
2359 (*result) -> op = if_statement;
2360
fdac15d9
TL
2361 token = peek_token (&val, cfile);
2362 if (token == LPAREN) {
2363 parenp = 1;
2364 next_token (&val, cfile);
2365 } else
2366 parenp = 0;
2367
2368
79a65726
TL
2369 if (!parse_boolean_expression (&(*result) -> data.ie.expr,
2370 cfile, lose)) {
be6be08d 2371 if (!*lose)
4615d498 2372 parse_warn (cfile, "boolean expression expected.");
4bd8800e 2373 executable_statement_dereference (result, MDL);
166e63eb 2374 *lose = 1;
79a65726 2375 return 0;
be6be08d 2376 }
02a015fb
TL
2377#if defined (DEBUG_EXPRESSION_PARSE)
2378 print_expression ("if condition", if_condition);
2379#endif
fdac15d9
TL
2380 if (parenp) {
2381 token = next_token (&val, cfile);
2382 if (token != RPAREN) {
2383 parse_warn (cfile, "expecting right paren.");
2384 *lose = 1;
4bd8800e 2385 executable_statement_dereference (result, MDL);
fdac15d9
TL
2386 return 0;
2387 }
2388 }
be6be08d
TL
2389 token = next_token (&val, cfile);
2390 if (token != LBRACE) {
4615d498 2391 parse_warn (cfile, "left brace expected.");
be6be08d
TL
2392 skip_to_semi (cfile);
2393 *lose = 1;
4bd8800e 2394 executable_statement_dereference (result, MDL);
79a65726 2395 return 0;
be6be08d 2396 }
79a65726 2397 if (!parse_executable_statements (&(*result) -> data.ie.true,
f579f39f 2398 cfile, lose, context_any)) {
79a65726
TL
2399 if (*lose) {
2400 /* Try to even things up. */
2401 do {
2402 token = next_token (&val, cfile);
2403 } while (token != EOF && token != RBRACE);
4bd8800e 2404 executable_statement_dereference (result, MDL);
79a65726
TL
2405 return 0;
2406 }
efc79acb 2407 }
79a65726 2408 token = next_token (&val, cfile);
be6be08d 2409 if (token != RBRACE) {
4615d498 2410 parse_warn (cfile, "right brace expected.");
be6be08d
TL
2411 skip_to_semi (cfile);
2412 *lose = 1;
4bd8800e 2413 executable_statement_dereference (result, MDL);
79a65726 2414 return 0;
be6be08d
TL
2415 }
2416 token = peek_token (&val, cfile);
2417 if (token == ELSE) {
2418 token = next_token (&val, cfile);
2419 token = peek_token (&val, cfile);
2420 if (token == IF) {
2421 token = next_token (&val, cfile);
79a65726
TL
2422 if (!parse_if_statement (&(*result) -> data.ie.false,
2423 cfile, lose)) {
166e63eb
TL
2424 if (!*lose)
2425 parse_warn (cfile,
4bd8800e
TL
2426 "expecting if statement");
2427 executable_statement_dereference (result, MDL);
166e63eb
TL
2428 *lose = 1;
2429 return 0;
79a65726 2430 }
be6be08d 2431 } else if (token != LBRACE) {
4615d498 2432 parse_warn (cfile, "left brace or if expected.");
be6be08d
TL
2433 skip_to_semi (cfile);
2434 *lose = 1;
4bd8800e 2435 executable_statement_dereference (result, MDL);
79a65726 2436 return 0;
be6be08d
TL
2437 } else {
2438 token = next_token (&val, cfile);
33500c7d 2439 if (!(parse_executable_statements
f579f39f
TL
2440 (&(*result) -> data.ie.false,
2441 cfile, lose, context_any))) {
4bd8800e 2442 executable_statement_dereference (result, MDL);
79a65726
TL
2443 return 0;
2444 }
25541f2f
TL
2445 token = next_token (&val, cfile);
2446 if (token != RBRACE) {
4615d498 2447 parse_warn (cfile, "right brace expected.");
25541f2f
TL
2448 skip_to_semi (cfile);
2449 *lose = 1;
4bd8800e 2450 executable_statement_dereference (result, MDL);
79a65726 2451 return 0;
25541f2f 2452 }
be6be08d
TL
2453 }
2454 } else if (token == ELSIF) {
2455 token = next_token (&val, cfile);
79a65726
TL
2456 if (!parse_if_statement (&(*result) -> data.ie.false,
2457 cfile, lose)) {
166e63eb
TL
2458 if (!*lose)
2459 parse_warn (cfile,
2460 "expecting conditional.");
4bd8800e 2461 executable_statement_dereference (result, MDL);
166e63eb
TL
2462 *lose = 1;
2463 return 0;
79a65726 2464 }
be6be08d 2465 } else
79a65726 2466 (*result) -> data.ie.false = (struct executable_statement *)0;
be6be08d 2467
79a65726 2468 return 1;
be6be08d
TL
2469}
2470
2471/*
2472 * boolean_expression :== CHECK STRING |
2473 * NOT boolean-expression |
2474 * data-expression EQUAL data-expression |
2b965a44 2475 * data-expression BANG EQUAL data-expression |
be6be08d
TL
2476 * boolean-expression AND boolean-expression |
2477 * boolean-expression OR boolean-expression
02a015fb 2478 * EXISTS OPTION-NAME
be6be08d
TL
2479 */
2480
02a015fb
TL
2481int parse_boolean_expression (expr, cfile, lose)
2482 struct expression **expr;
4615d498 2483 struct parse *cfile;
02a015fb
TL
2484 int *lose;
2485{
2486 /* Parse an expression... */
2487 if (!parse_expression (expr, cfile, lose, context_boolean,
2488 (struct expression **)0, expr_none))
2489 return 0;
2490
08514fb8
TL
2491 if (!is_boolean_expression (*expr) &&
2492 (*expr) -> op != expr_variable_reference &&
2493 (*expr) -> op != expr_funcall) {
4615d498 2494 parse_warn (cfile, "Expecting a boolean expression.");
02a015fb 2495 *lose = 1;
4bd8800e 2496 expression_dereference (expr, MDL);
02a015fb
TL
2497 return 0;
2498 }
2499 return 1;
2500}
2501
2502/*
2503 * data_expression :== SUBSTRING LPAREN data-expression COMMA
2504 * numeric-expression COMMA
2505 * numeric-expression RPAREN |
a82abfc7
TL
2506 * CONCAT LPAREN data-expression COMMA
2507 data-expression RPAREN
02a015fb 2508 * SUFFIX LPAREN data_expression COMMA
a82abfc7 2509 * numeric-expression RPAREN |
02a015fb
TL
2510 * OPTION option_name |
2511 * HARDWARE |
2512 * PACKET LPAREN numeric-expression COMMA
2513 * numeric-expression RPAREN |
2514 * STRING |
2515 * colon_seperated_hex_list
2516 */
2517
2518int parse_data_expression (expr, cfile, lose)
2519 struct expression **expr;
4615d498 2520 struct parse *cfile;
02a015fb
TL
2521 int *lose;
2522{
2523 /* Parse an expression... */
2524 if (!parse_expression (expr, cfile, lose, context_data,
2525 (struct expression **)0, expr_none))
2526 return 0;
2527
08514fb8
TL
2528 if (!is_data_expression (*expr) &&
2529 (*expr) -> op != expr_variable_reference &&
2530 (*expr) -> op != expr_funcall) {
4615d498 2531 parse_warn (cfile, "Expecting a data expression.");
02a015fb
TL
2532 *lose = 1;
2533 return 0;
2534 }
2535 return 1;
2536}
2537
2538/*
2539 * numeric-expression :== EXTRACT_INT LPAREN data-expression
2540 * COMMA number RPAREN |
2541 * NUMBER
2542 */
2543
2544int parse_numeric_expression (expr, cfile, lose)
2545 struct expression **expr;
4615d498 2546 struct parse *cfile;
02a015fb
TL
2547 int *lose;
2548{
2549 /* Parse an expression... */
2550 if (!parse_expression (expr, cfile, lose, context_numeric,
2551 (struct expression **)0, expr_none))
2552 return 0;
2553
08514fb8
TL
2554 if (!is_numeric_expression (*expr) &&
2555 (*expr) -> op != expr_variable_reference &&
2556 (*expr) -> op != expr_funcall) {
4615d498 2557 parse_warn (cfile, "Expecting a numeric expression.");
02a015fb
TL
2558 *lose = 1;
2559 return 0;
2560 }
2561 return 1;
2562}
2563
9fb2fb28
TL
2564/*
2565 * dns-expression :==
2566 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2567 * data-expression COMMA numeric-expression RPAREN
2568 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2569 * data-expression RPAREN
2570 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2571 * data-expression RPAREN
2572 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2573 * data-expression RPAREN
2574 * ns-class :== IN | CHAOS | HS | NUMBER
2575 * ns-type :== A | PTR | MX | TXT | NUMBER
2576 */
2577
2578int parse_dns_expression (expr, cfile, lose)
2579 struct expression **expr;
2580 struct parse *cfile;
2581 int *lose;
2582{
2583 /* Parse an expression... */
2584 if (!parse_expression (expr, cfile, lose, context_dns,
2585 (struct expression **)0, expr_none))
2586 return 0;
2587
08514fb8
TL
2588 if (!is_dns_expression (*expr) &&
2589 (*expr) -> op != expr_variable_reference &&
2590 (*expr) -> op != expr_funcall) {
9fb2fb28
TL
2591 parse_warn (cfile, "Expecting a dns update subexpression.");
2592 *lose = 1;
2593 return 0;
2594 }
2595 return 1;
2596}
2597
02a015fb 2598/* Parse a subexpression that does not contain a binary operator. */
be6be08d 2599
02a015fb
TL
2600int parse_non_binary (expr, cfile, lose, context)
2601 struct expression **expr;
4615d498 2602 struct parse *cfile;
be6be08d 2603 int *lose;
02a015fb 2604 enum expression_context context;
be6be08d 2605{
02a015fb 2606 enum dhcp_token token;
b1b7b521 2607 const char *val;
be6be08d 2608 struct collection *col;
02a015fb 2609 struct option *option;
08514fb8 2610 struct expression *nexp, **ep;
b1b7b521 2611 int known;
9fb2fb28 2612 enum expr_op opcode;
f579f39f 2613 const char *s;
08514fb8 2614 char *cptr;
fdac15d9
TL
2615 struct executable_statement *stmt;
2616 int i;
08514fb8 2617 unsigned long u;
be6be08d
TL
2618
2619 token = peek_token (&val, cfile);
2620
2621 /* Check for unary operators... */
2622 switch (token) {
2623 case CHECK:
2624 token = next_token (&val, cfile);
2625 token = next_token (&val, cfile);
2626 if (token != STRING) {
4615d498 2627 parse_warn (cfile, "string expected.");
be6be08d
TL
2628 skip_to_semi (cfile);
2629 *lose = 1;
02a015fb 2630 return 0;
be6be08d
TL
2631 }
2632 for (col = collections; col; col = col -> next)
2633 if (!strcmp (col -> name, val))
2634 break;
2635 if (!col) {
4615d498 2636 parse_warn (cfile, "unknown collection.");
be6be08d 2637 *lose = 1;
02a015fb 2638 return 0;
be6be08d 2639 }
4bd8800e 2640 if (!expression_allocate (expr, MDL))
8ae2d595 2641 log_fatal ("can't allocate expression");
02a015fb
TL
2642 (*expr) -> op = expr_check;
2643 (*expr) -> data.check = col;
2644 break;
be6be08d 2645
5e6fb153 2646 case TOKEN_NOT:
be6be08d 2647 token = next_token (&val, cfile);
9fb2fb28
TL
2648 if (context == context_dns) {
2649 token = peek_token (&val, cfile);
2650 goto not_exists;
2651 }
4bd8800e 2652 if (!expression_allocate (expr, MDL))
8ae2d595 2653 log_fatal ("can't allocate expression");
02a015fb
TL
2654 (*expr) -> op = expr_not;
2655 if (!parse_non_binary (&(*expr) -> data.not,
2656 cfile, lose, context)) {
be6be08d 2657 if (!*lose) {
4615d498 2658 parse_warn (cfile, "expression expected");
be6be08d
TL
2659 skip_to_semi (cfile);
2660 }
2661 *lose = 1;
4bd8800e 2662 expression_dereference (expr, MDL);
02a015fb 2663 return 0;
be6be08d 2664 }
be6be08d 2665 break;
be6be08d 2666
fcd9651f
TL
2667 case LPAREN:
2668 token = next_token (&val, cfile);
2669 if (!parse_expression (expr, cfile, lose, context,
2670 (struct expression **)0, expr_none)) {
2671 if (!*lose) {
2672 parse_warn (cfile, "expression expected");
2673 skip_to_semi (cfile);
2674 }
2675 *lose = 1;
2676 return 0;
2677 }
2678 token = next_token (&val, cfile);
2679 if (token != RPAREN) {
2680 *lose = 1;
2681 parse_warn (cfile, "right paren expected");
2682 skip_to_semi (cfile);
2683 return 0;
2684 }
2685 break;
2686
02a015fb 2687 case EXISTS:
9fb2fb28
TL
2688 if (context == context_dns)
2689 goto ns_exists;
02a015fb 2690 token = next_token (&val, cfile);
4bd8800e 2691 if (!expression_allocate (expr, MDL))
8ae2d595 2692 log_fatal ("can't allocate expression");
02a015fb 2693 (*expr) -> op = expr_exists;
b1b7b521
TL
2694 known = 0;
2695 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
02a015fb
TL
2696 if (!(*expr) -> data.option) {
2697 *lose = 1;
4bd8800e 2698 expression_dereference (expr, MDL);
02a015fb 2699 return 0;
be6be08d 2700 }
02a015fb 2701 break;
be6be08d 2702
1c5d5731
TL
2703 case STATIC:
2704 token = next_token (&val, cfile);
4bd8800e 2705 if (!expression_allocate (expr, MDL))
1c5d5731
TL
2706 log_fatal ("can't allocate expression");
2707 (*expr) -> op = expr_static;
2708 break;
2709
70330633
TL
2710 case KNOWN:
2711 token = next_token (&val, cfile);
4bd8800e 2712 if (!expression_allocate (expr, MDL))
70330633
TL
2713 log_fatal ("can't allocate expression");
2714 (*expr) -> op = expr_known;
2715 break;
2716
be6be08d
TL
2717 case SUBSTRING:
2718 token = next_token (&val, cfile);
4bd8800e 2719 if (!expression_allocate (expr, MDL))
8ae2d595 2720 log_fatal ("can't allocate expression");
02a015fb 2721 (*expr) -> op = expr_substring;
be6be08d
TL
2722
2723 token = next_token (&val, cfile);
2724 if (token != LPAREN) {
2725 nolparen:
4bd8800e 2726 expression_dereference (expr, MDL);
4615d498 2727 parse_warn (cfile, "left parenthesis expected.");
be6be08d 2728 *lose = 1;
02a015fb 2729 return 0;
be6be08d
TL
2730 }
2731
02a015fb
TL
2732 if (!parse_data_expression (&(*expr) -> data.substring.expr,
2733 cfile, lose)) {
be6be08d 2734 nodata:
4bd8800e 2735 expression_dereference (expr, MDL);
4615d498 2736 parse_warn (cfile, "expecting data expression.");
be6be08d
TL
2737 skip_to_semi (cfile);
2738 *lose = 1;
02a015fb 2739 return 0;
be6be08d
TL
2740 }
2741
2742 token = next_token (&val, cfile);
2743 if (token != COMMA) {
2744 nocomma:
4bd8800e 2745 expression_dereference (expr, MDL);
4615d498 2746 parse_warn (cfile, "comma expected.");
be6be08d 2747 *lose = 1;
02a015fb
TL
2748
2749 return 0;
be6be08d
TL
2750 }
2751
02a015fb
TL
2752 if (!parse_numeric_expression
2753 (&(*expr) -> data.substring.offset,cfile, lose)) {
be6be08d
TL
2754 nonum:
2755 if (!*lose) {
4615d498
TL
2756 parse_warn (cfile,
2757 "expecting numeric expression.");
be6be08d
TL
2758 skip_to_semi (cfile);
2759 *lose = 1;
2760 }
4bd8800e 2761 expression_dereference (expr, MDL);
02a015fb 2762 return 0;
be6be08d
TL
2763 }
2764
2765 token = next_token (&val, cfile);
2766 if (token != COMMA)
2767 goto nocomma;
2768
02a015fb
TL
2769 if (!parse_numeric_expression
2770 (&(*expr) -> data.substring.len, cfile, lose))
be6be08d
TL
2771 goto nonum;
2772
2773 token = next_token (&val, cfile);
2774 if (token != RPAREN) {
2775 norparen:
4615d498 2776 parse_warn (cfile, "right parenthesis expected.");
be6be08d 2777 *lose = 1;
4bd8800e 2778 expression_dereference (expr, MDL);
02a015fb 2779 return 0;
be6be08d 2780 }
02a015fb 2781 break;
be6be08d
TL
2782
2783 case SUFFIX:
2784 token = next_token (&val, cfile);
4bd8800e 2785 if (!expression_allocate (expr, MDL))
8ae2d595 2786 log_fatal ("can't allocate expression");
02a015fb 2787 (*expr) -> op = expr_suffix;
be6be08d
TL
2788
2789 token = next_token (&val, cfile);
2790 if (token != LPAREN)
2791 goto nolparen;
2792
02a015fb
TL
2793 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
2794 cfile, lose))
be6be08d
TL
2795 goto nodata;
2796
2797 token = next_token (&val, cfile);
2798 if (token != COMMA)
2799 goto nocomma;
2800
02a015fb
TL
2801 if (!parse_data_expression (&(*expr) -> data.suffix.len,
2802 cfile, lose))
be6be08d
TL
2803 goto nonum;
2804
2805 token = next_token (&val, cfile);
2806 if (token != RPAREN)
2807 goto norparen;
02a015fb 2808 break;
be6be08d 2809
a82abfc7
TL
2810 case CONCAT:
2811 token = next_token (&val, cfile);
4bd8800e 2812 if (!expression_allocate (expr, MDL))
a82abfc7
TL
2813 log_fatal ("can't allocate expression");
2814 (*expr) -> op = expr_concat;
2815
2816 token = next_token (&val, cfile);
2817 if (token != LPAREN)
2818 goto nolparen;
2819
2820 if (!parse_data_expression (&(*expr) -> data.concat [0],
2821 cfile, lose))
2822 goto nodata;
2823
2824 token = next_token (&val, cfile);
2825 if (token != COMMA)
2826 goto nocomma;
2827
720c8262 2828 concat_another:
a82abfc7
TL
2829 if (!parse_data_expression (&(*expr) -> data.concat [1],
2830 cfile, lose))
2831 goto nodata;
2832
2833 token = next_token (&val, cfile);
720c8262
TL
2834
2835 if (token == COMMA) {
2836 nexp = (struct expression *)0;
4bd8800e 2837 if (!expression_allocate (&nexp, MDL))
720c8262
TL
2838 log_fatal ("can't allocate at CONCAT2");
2839 nexp -> op = expr_concat;
4bd8800e
TL
2840 expression_reference (&nexp -> data.concat [0],
2841 *expr, MDL);
2842 expression_dereference (expr, MDL);
2843 expression_reference (expr, nexp, MDL);
720c8262
TL
2844 goto concat_another;
2845 }
2846
a82abfc7
TL
2847 if (token != RPAREN)
2848 goto norparen;
2849 break;
2850
da38df14
TL
2851 case BINARY_TO_ASCII:
2852 token = next_token (&val, cfile);
4bd8800e 2853 if (!expression_allocate (expr, MDL))
da38df14 2854 log_fatal ("can't allocate expression");
eb42f00e 2855 (*expr) -> op = expr_binary_to_ascii;
da38df14
TL
2856
2857 token = next_token (&val, cfile);
2858 if (token != LPAREN)
2859 goto nolparen;
2860
2861 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
2862 cfile, lose))
2863 goto nodata;
2864
2865 token = next_token (&val, cfile);
2866 if (token != COMMA)
2867 goto nocomma;
2868
2869 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
2870 cfile, lose))
2871 goto nodata;
2872
2873 token = next_token (&val, cfile);
2874 if (token != COMMA)
2875 goto nocomma;
2876
2877 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
2878 cfile, lose))
2879 goto nodata;
2880
2881 token = next_token (&val, cfile);
2882 if (token != COMMA)
2883 goto nocomma;
2884
2885 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
2886 cfile, lose))
2887 goto nodata;
2888
2889 token = next_token (&val, cfile);
2890 if (token != RPAREN)
2891 goto norparen;
2892 break;
2893
2894 case REVERSE:
2895 token = next_token (&val, cfile);
4bd8800e 2896 if (!expression_allocate (expr, MDL))
da38df14 2897 log_fatal ("can't allocate expression");
eb42f00e 2898 (*expr) -> op = expr_reverse;
da38df14
TL
2899
2900 token = next_token (&val, cfile);
2901 if (token != LPAREN)
2902 goto nolparen;
2903
2904 if (!(parse_numeric_expression
2905 (&(*expr) -> data.reverse.width, cfile, lose)))
2906 goto nodata;
2907
2908 token = next_token (&val, cfile);
2909 if (token != COMMA)
2910 goto nocomma;
2911
2912 if (!(parse_data_expression
2913 (&(*expr) -> data.reverse.buffer, cfile, lose)))
2914 goto nodata;
2915
2916 token = next_token (&val, cfile);
2917 if (token != RPAREN)
2918 goto norparen;
2919 break;
2920
fdac15d9 2921 case PICK:
79a65726
TL
2922 /* pick (a, b, c) actually produces an internal representation
2923 that looks like pick (a, pick (b, pick (c, nil))). */
2924 token = next_token (&val, cfile);
4bd8800e 2925 if (!(expression_allocate (expr, MDL)))
79a65726 2926 log_fatal ("can't allocate expression");
79a65726 2927
be6be08d 2928 token = next_token (&val, cfile);
79a65726
TL
2929 if (token != LPAREN)
2930 goto nolparen;
2931
2932 nexp = *expr;
2933 do {
392208d3 2934 nexp -> op = expr_pick_first_value;
79a65726
TL
2935 if (!(parse_data_expression
2936 (&nexp -> data.pick_first_value.car,
2937 cfile, lose)))
2938 goto nodata;
2939
2940 token = next_token (&val, cfile);
2941 if (token == COMMA) {
2942 if (!(expression_allocate
2943 (&nexp -> data.pick_first_value.cdr,
4bd8800e 2944 MDL)))
79a65726
TL
2945 log_fatal ("can't allocate expr");
2946 nexp = nexp -> data.pick_first_value.cdr;
2947 }
2948 } while (token == COMMA);
2949
2950 if (token != RPAREN)
2951 goto norparen;
2952 break;
2953
9fb2fb28
TL
2954 /* dns-update and dns-delete are present for historical
2955 purposes, but are deprecated in favor of ns-update
2956 in combination with update, delete, exists and not
2957 exists. */
069e9f4c 2958 case DNS_UPDATE:
9fb2fb28 2959 case DNS_DELETE:
069e9f4c 2960#if !defined (NSUPDATE)
4615d498
TL
2961 parse_warn (cfile,
2962 "Please rebuild dhcpd with --with-nsupdate.");
069e9f4c 2963#endif
fdac15d9 2964 token = next_token (&val, cfile);
9fb2fb28 2965 if (token == DNS_UPDATE)
f579f39f 2966 opcode = expr_ns_add;
9fb2fb28
TL
2967 else
2968 opcode = expr_ns_delete;
2969
069e9f4c
TL
2970 token = next_token (&val, cfile);
2971 if (token != LPAREN)
2972 goto nolparen;
2973
9fb2fb28
TL
2974 token = next_token (&val, cfile);
2975 if (token != STRING) {
2976 parse_warn (cfile,
2977 "parse_expression: expecting string.");
2978 badnsupdate:
069e9f4c
TL
2979 skip_to_semi (cfile);
2980 *lose = 1;
2981 return 0;
2982 }
9fb2fb28
TL
2983
2984 if (!strcasecmp (val, "a"))
08514fb8 2985 u = T_A;
9fb2fb28 2986 else if (!strcasecmp (val, "ptr"))
08514fb8 2987 u = T_PTR;
9fb2fb28 2988 else if (!strcasecmp (val, "mx"))
08514fb8 2989 u = T_MX;
9fb2fb28 2990 else if (!strcasecmp (val, "cname"))
08514fb8 2991 u = T_CNAME;
9fb2fb28 2992 else if (!strcasecmp (val, "TXT"))
08514fb8 2993 u = T_TXT;
9fb2fb28
TL
2994 else {
2995 parse_warn (cfile, "unexpected rrtype: %s", val);
2996 goto badnsupdate;
2997 }
fdac15d9 2998
08514fb8
TL
2999 s = (opcode == expr_ns_add
3000 ? "old-dns-update"
3001 : "old-dns-delete");
3002 cptr = dmalloc (strlen (s) + 1, MDL);
3003 if (!cptr)
3004 log_fatal ("can't allocate name for %s", s);
3005 strcpy (cptr, s);
4bd8800e 3006 if (!expression_allocate (expr, MDL))
fdac15d9 3007 log_fatal ("can't allocate expression");
fdac15d9 3008 (*expr) -> op = expr_funcall;
08514fb8 3009 (*expr) -> data.funcall.name = cptr;
fdac15d9 3010
08514fb8
TL
3011 /* Fake up a function call. */
3012 ep = &(*expr) -> data.funcall.arglist;
3013 if (!expression_allocate (ep, MDL))
3014 log_fatal ("can't allocate expression");
3015 (*ep) -> op = expr_arg;
3016 if (!make_const_int (&(*ep) -> data.arg.val, u))
fdac15d9 3017 log_fatal ("can't allocate rrtype value.");
069e9f4c
TL
3018
3019 token = next_token (&val, cfile);
3020 if (token != COMMA)
3021 goto nocomma;
08514fb8
TL
3022 ep = &((*ep) -> data.arg.next);
3023 if (!expression_allocate (ep, MDL))
3024 log_fatal ("can't allocate expression");
3025 (*ep) -> op = expr_arg;
3026 if (!(parse_data_expression (&(*ep) -> data.arg.val,
fdac15d9 3027 cfile, lose)))
069e9f4c
TL
3028 goto nodata;
3029
3030 token = next_token (&val, cfile);
3031 if (token != COMMA)
3032 goto nocomma;
3033
08514fb8
TL
3034 ep = &((*ep) -> data.arg.next);
3035 if (!expression_allocate (ep, MDL))
3036 log_fatal ("can't allocate expression");
3037 (*ep) -> op = expr_arg;
3038 if (!(parse_data_expression (&(*ep) -> data.arg.val,
fdac15d9 3039 cfile, lose)))
069e9f4c
TL
3040 goto nodata;
3041
f579f39f 3042 if (opcode == expr_ns_add) {
9fb2fb28
TL
3043 token = next_token (&val, cfile);
3044 if (token != COMMA)
3045 goto nocomma;
3046
08514fb8
TL
3047 ep = &((*ep) -> data.arg.next);
3048 if (!expression_allocate (ep, MDL))
3049 log_fatal ("can't allocate expression");
3050 (*ep) -> op = expr_arg;
3051 if (!(parse_numeric_expression (&(*ep) -> data.arg.val,
3052 cfile, lose))) {
9fb2fb28 3053 parse_warn (cfile,
fdac15d9 3054 "expecting numeric expression.");
9fb2fb28
TL
3055 goto badnsupdate;
3056 }
069e9f4c 3057 }
08514fb8 3058
069e9f4c
TL
3059 token = next_token (&val, cfile);
3060 if (token != RPAREN)
3061 goto norparen;
3062 break;
3063
9fb2fb28 3064 case NS_UPDATE:
88886e12
TL
3065#if !defined (NSUPDATE)
3066 parse_warn (cfile,
3067 "Please rebuild dhcpd with --with-nsupdate.");
3068#endif
3069 token = next_token (&val, cfile);
4bd8800e 3070 if (!expression_allocate (expr, MDL))
88886e12 3071 log_fatal ("can't allocate expression");
88886e12
TL
3072
3073 token = next_token (&val, cfile);
3074 if (token != LPAREN)
3075 goto nolparen;
3076
9fb2fb28
TL
3077 nexp = *expr;
3078 do {
3079 nexp -> op = expr_dns_transaction;
3080 if (!(parse_dns_expression
3081 (&nexp -> data.dns_transaction.car,
3082 cfile, lose)))
3083 {
f579f39f
TL
3084 if (!*lose)
3085 parse_warn
3086 (cfile,
3087 "expecting dns expression.");
9fb2fb28 3088 badnstrans:
4bd8800e 3089 expression_dereference (expr, MDL);
9fb2fb28
TL
3090 *lose = 1;
3091 return 0;
3092 }
3093
3094 token = next_token (&val, cfile);
3095
3096 if (token == COMMA) {
3097 if (!(expression_allocate
3098 (&nexp -> data.dns_transaction.cdr,
4bd8800e 3099 MDL)))
9fb2fb28
TL
3100 log_fatal
3101 ("can't allocate expression");
3102 nexp = nexp -> data.dns_transaction.cdr;
3103 }
3104 } while (token == COMMA);
3105
3106 if (token != RPAREN)
3107 goto norparen;
3108 break;
3109
3110 /* NOT EXISTS is special cased above... */
3111 not_exists:
fdac15d9
TL
3112 token = peek_token (&val, cfile);
3113 if (token != EXISTS) {
3114 parse_warn (cfile, "expecting DNS prerequisite.");
3115 *lose = 1;
3116 return 0;
3117 }
9fb2fb28
TL
3118 opcode = expr_ns_not_exists;
3119 goto nsupdatecode;
f579f39f
TL
3120 case TOKEN_ADD:
3121 opcode = expr_ns_add;
9fb2fb28
TL
3122 goto nsupdatecode;
3123 case TOKEN_DELETE:
3124 opcode = expr_ns_delete;
3125 goto nsupdatecode;
3126 ns_exists:
3127 opcode = expr_ns_exists;
3128 nsupdatecode:
3129 token = next_token (&val, cfile);
3130
3131#if !defined (NSUPDATE)
3132 parse_warn (cfile,
3133 "Please rebuild dhcpd with --with-nsupdate.");
3134#endif
4bd8800e 3135 if (!expression_allocate (expr, MDL))
9fb2fb28
TL
3136 log_fatal ("can't allocate expression");
3137 (*expr) -> op = opcode;
3138
3139 token = next_token (&val, cfile);
3140 if (token != LPAREN)
3141 goto nolparen;
3142
3143 token = next_token (&val, cfile);
3144 if (!is_identifier (token) && token != NUMBER) {
3145 parse_warn (cfile, "expecting identifier or number.");
3146 badnsop:
4bd8800e 3147 expression_dereference (expr, MDL);
88886e12
TL
3148 skip_to_semi (cfile);
3149 *lose = 1;
3150 return 0;
3151 }
9fb2fb28
TL
3152
3153 if (token == NUMBER)
f579f39f 3154 (*expr) -> data.ns_add.rrclass = atoi (val);
9fb2fb28 3155 else if (!strcasecmp (val, "in"))
f579f39f 3156 (*expr) -> data.ns_add.rrclass = C_IN;
9fb2fb28 3157 else if (!strcasecmp (val, "chaos"))
f579f39f 3158 (*expr) -> data.ns_add.rrclass = C_CHAOS;
9fb2fb28 3159 else if (!strcasecmp (val, "hs"))
f579f39f 3160 (*expr) -> data.ns_add.rrclass = C_HS;
9fb2fb28
TL
3161 else {
3162 parse_warn (cfile, "unexpected rrclass: %s", val);
3163 goto badnsop;
3164 }
3165
f579f39f
TL
3166 token = next_token (&val, cfile);
3167 if (token != COMMA)
3168 goto nocomma;
3169
9fb2fb28
TL
3170 token = next_token (&val, cfile);
3171 if (!is_identifier (token) && token != NUMBER) {
3172 parse_warn (cfile, "expecting identifier or number.");
3173 goto badnsop;
3174 }
3175
3176 if (token == NUMBER)
f579f39f 3177 (*expr) -> data.ns_add.rrtype = atoi (val);
9fb2fb28 3178 else if (!strcasecmp (val, "a"))
f579f39f 3179 (*expr) -> data.ns_add.rrtype = T_A;
9fb2fb28 3180 else if (!strcasecmp (val, "ptr"))
f579f39f 3181 (*expr) -> data.ns_add.rrtype = T_PTR;
9fb2fb28 3182 else if (!strcasecmp (val, "mx"))
f579f39f 3183 (*expr) -> data.ns_add.rrtype = T_MX;
9fb2fb28 3184 else if (!strcasecmp (val, "cname"))
f579f39f 3185 (*expr) -> data.ns_add.rrtype = T_CNAME;
9fb2fb28 3186 else if (!strcasecmp (val, "TXT"))
f579f39f 3187 (*expr) -> data.ns_add.rrtype = T_TXT;
9fb2fb28
TL
3188 else {
3189 parse_warn (cfile, "unexpected rrtype: %s", val);
3190 goto badnsop;
3191 }
88886e12
TL
3192
3193 token = next_token (&val, cfile);
3194 if (token != COMMA)
3195 goto nocomma;
3196
3197 if (!(parse_data_expression
f579f39f 3198 (&(*expr) -> data.ns_add.rrname, cfile, lose)))
88886e12
TL
3199 goto nodata;
3200
3201 token = next_token (&val, cfile);
3202 if (token != COMMA)
3203 goto nocomma;
3204
3205 if (!(parse_data_expression
f579f39f 3206 (&(*expr) -> data.ns_add.rrdata, cfile, lose)))
88886e12
TL
3207 goto nodata;
3208
f579f39f 3209 if (opcode == expr_ns_add) {
9fb2fb28
TL
3210 token = next_token (&val, cfile);
3211 if (token != COMMA)
3212 goto nocomma;
3213
3214 if (!(parse_numeric_expression
f579f39f
TL
3215 (&(*expr) -> data.ns_add.ttl, cfile,
3216 lose))) {
9fb2fb28
TL
3217 parse_warn (cfile,
3218 "expecting data expression.");
3219 goto badnsupdate;
3220 }
3221 }
3222
88886e12
TL
3223 token = next_token (&val, cfile);
3224 if (token != RPAREN)
3225 goto norparen;
3226 break;
3227
79a65726
TL
3228 case OPTION:
3229 case CONFIG_OPTION:
4bd8800e 3230 if (!expression_allocate (expr, MDL))
8ae2d595 3231 log_fatal ("can't allocate expression");
cd31814f
TL
3232 (*expr) -> op = (token == OPTION
3233 ? expr_option
3234 : expr_config_option);
79a65726 3235 token = next_token (&val, cfile);
b1b7b521
TL
3236 known = 0;
3237 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
02a015fb 3238 if (!(*expr) -> data.option) {
be6be08d 3239 *lose = 1;
4bd8800e 3240 expression_dereference (expr, MDL);
02a015fb 3241 return 0;
be6be08d 3242 }
02a015fb 3243 break;
be6be08d
TL
3244
3245 case HARDWARE:
3246 token = next_token (&val, cfile);
4bd8800e 3247 if (!expression_allocate (expr, MDL))
8ae2d595 3248 log_fatal ("can't allocate expression");
02a015fb
TL
3249 (*expr) -> op = expr_hardware;
3250 break;
be6be08d 3251
da38df14
TL
3252 case LEASED_ADDRESS:
3253 token = next_token (&val, cfile);
4bd8800e 3254 if (!expression_allocate (expr, MDL))
da38df14
TL
3255 log_fatal ("can't allocate expression");
3256 (*expr) -> op = expr_leased_address;
3257 break;
3258
fdac15d9
TL
3259 case FILENAME:
3260 token = next_token (&val, cfile);
4bd8800e 3261 if (!expression_allocate (expr, MDL))
fdac15d9
TL
3262 log_fatal ("can't allocate expression");
3263 (*expr) -> op = expr_filename;
3264 break;
3265
3266 case SERVER_NAME:
3267 token = next_token (&val, cfile);
4bd8800e 3268 if (!expression_allocate (expr, MDL))
fdac15d9
TL
3269 log_fatal ("can't allocate expression");
3270 (*expr) -> op = expr_sname;
3271 break;
3272
069e9f4c
TL
3273 case LEASE_TIME:
3274 token = next_token (&val, cfile);
4bd8800e 3275 if (!expression_allocate (expr, MDL))
069e9f4c
TL
3276 log_fatal ("can't allocate expression");
3277 (*expr) -> op = expr_lease_time;
3278 break;
3279
f579f39f
TL
3280 case TOKEN_NULL:
3281 token = next_token (&val, cfile);
4bd8800e 3282 if (!expression_allocate (expr, MDL))
f579f39f
TL
3283 log_fatal ("can't allocate expression");
3284 (*expr) -> op = expr_null;
3285 break;
3286
79a65726
TL
3287 case HOST_DECL_NAME:
3288 token = next_token (&val, cfile);
4bd8800e 3289 if (!expression_allocate (expr, MDL))
79a65726
TL
3290 log_fatal ("can't allocate expression");
3291 (*expr) -> op = expr_host_decl_name;
3292 break;
3293
846d7d54 3294 case UPDATED_DNS_RR:
06a8567c 3295 token = next_token (&val, cfile);
06a8567c 3296
06a8567c 3297 token = next_token (&val, cfile);
846d7d54
TL
3298 if (token != LPAREN)
3299 goto nolparen;
f579f39f
TL
3300
3301 token = next_token (&val, cfile);
3302 if (token != STRING) {
3303 parse_warn (cfile, "expecting string.");
3304 bad_rrtype:
3305 *lose = 1;
3306 return 0;
3307 }
3308 if (!strcasecmp (val, "a"))
3309 s = "ddns-fwd-name";
3310 else if (!strcasecmp (val, "ptr"))
3311 s = "ddns-rev-name";
3312 else {
3313 parse_warn (cfile, "invalid DNS rrtype: %s", val);
3314 goto bad_rrtype;
3315 }
846d7d54
TL
3316
3317 token = next_token (&val, cfile);
3318 if (token != RPAREN)
3319 goto norparen;
3320
4bd8800e 3321 if (!expression_allocate (expr, MDL))
f579f39f
TL
3322 log_fatal ("can't allocate expression");
3323 (*expr) -> op = expr_variable_reference;
3324 (*expr) -> data.variable =
fdac15d9 3325 dmalloc (strlen (s) + 1, MDL);
f579f39f
TL
3326 if (!(*expr) -> data.variable)
3327 log_fatal ("can't allocate variable name.");
3328 strcpy ((*expr) -> data.variable, s);
06a8567c
TL
3329 break;
3330
be6be08d
TL
3331 case PACKET:
3332 token = next_token (&val, cfile);
4bd8800e 3333 if (!expression_allocate (expr, MDL))
8ae2d595 3334 log_fatal ("can't allocate expression");
02a015fb 3335 (*expr) -> op = expr_packet;
be6be08d
TL
3336
3337 token = next_token (&val, cfile);
3338 if (token != LPAREN)
3339 goto nolparen;
3340
02a015fb
TL
3341 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
3342 cfile, lose))
be6be08d
TL
3343 goto nonum;
3344
3345 token = next_token (&val, cfile);
3346 if (token != COMMA)
3347 goto nocomma;
3348
02a015fb
TL
3349 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
3350 cfile, lose))
be6be08d
TL
3351 goto nonum;
3352
3353 token = next_token (&val, cfile);
3354 if (token != RPAREN)
3355 goto norparen;
02a015fb 3356 break;
be6be08d
TL
3357
3358 case STRING:
3359 token = next_token (&val, cfile);
b1b7b521 3360 if (!make_const_data (expr, (const unsigned char *)val,
c5b0f529 3361 strlen (val), 1, 1))
8ae2d595 3362 log_fatal ("can't make constant string expression.");
02a015fb 3363 break;
be6be08d 3364
be6be08d
TL
3365 case EXTRACT_INT:
3366 token = next_token (&val, cfile);
be6be08d
TL
3367 token = next_token (&val, cfile);
3368 if (token != LPAREN) {
4615d498 3369 parse_warn (cfile, "left parenthesis expected.");
be6be08d 3370 *lose = 1;
02a015fb 3371 return 0;
be6be08d
TL
3372 }
3373
4bd8800e 3374 if (!expression_allocate (expr, MDL))
8ae2d595 3375 log_fatal ("can't allocate expression");
02a015fb
TL
3376
3377 if (!parse_data_expression (&(*expr) -> data.extract_int,
3378 cfile, lose)) {
4615d498 3379 parse_warn (cfile, "expecting data expression.");
be6be08d
TL
3380 skip_to_semi (cfile);
3381 *lose = 1;
4bd8800e 3382 expression_dereference (expr, MDL);
02a015fb 3383 return 0;
be6be08d
TL
3384 }
3385
3386 token = next_token (&val, cfile);
3387 if (token != COMMA) {
4615d498 3388 parse_warn (cfile, "comma expected.");
be6be08d 3389 *lose = 1;
4bd8800e 3390 expression_dereference (expr, MDL);
02a015fb 3391 return 0;
be6be08d
TL
3392 }
3393
3394 token = next_token (&val, cfile);
3395 if (token != NUMBER) {
4615d498 3396 parse_warn (cfile, "number expected.");
be6be08d 3397 *lose = 1;
4bd8800e 3398 expression_dereference (expr, MDL);
02a015fb 3399 return 0;
be6be08d 3400 }
be6be08d
TL
3401 switch (atoi (val)) {
3402 case 8:
02a015fb 3403 (*expr) -> op = expr_extract_int8;
be6be08d
TL
3404 break;
3405
3406 case 16:
02a015fb 3407 (*expr) -> op = expr_extract_int16;
be6be08d
TL
3408 break;
3409
3410 case 32:
02a015fb 3411 (*expr) -> op = expr_extract_int32;
be6be08d
TL
3412 break;
3413
3414 default:
4615d498
TL
3415 parse_warn (cfile,
3416 "unsupported integer size %d", atoi (val));
be6be08d
TL
3417 *lose = 1;
3418 skip_to_semi (cfile);
4bd8800e 3419 expression_dereference (expr, MDL);
02a015fb 3420 return 0;
be6be08d
TL
3421 }
3422
3423 token = next_token (&val, cfile);
3424 if (token != RPAREN) {
4615d498 3425 parse_warn (cfile, "right parenthesis expected.");
be6be08d 3426 *lose = 1;
4bd8800e 3427 expression_dereference (expr, MDL);
02a015fb 3428 return 0;
be6be08d 3429 }
02a015fb 3430 break;
be6be08d 3431
20c4e94d
TL
3432 case ENCODE_INT:
3433 token = next_token (&val, cfile);
3434 token = next_token (&val, cfile);
3435 if (token != LPAREN) {
4615d498 3436 parse_warn (cfile, "left parenthesis expected.");
20c4e94d
TL
3437 *lose = 1;
3438 return 0;
3439 }
3440
4bd8800e 3441 if (!expression_allocate (expr, MDL))
20c4e94d
TL
3442 log_fatal ("can't allocate expression");
3443
3444 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
3445 cfile, lose)) {
4615d498 3446 parse_warn (cfile, "expecting numeric expression.");
20c4e94d
TL
3447 skip_to_semi (cfile);
3448 *lose = 1;
4bd8800e 3449 expression_dereference (expr, MDL);
20c4e94d
TL
3450 return 0;
3451 }
3452
3453 token = next_token (&val, cfile);
3454 if (token != COMMA) {
4615d498 3455 parse_warn (cfile, "comma expected.");
20c4e94d 3456 *lose = 1;
4bd8800e 3457 expression_dereference (expr, MDL);
20c4e94d
TL
3458 return 0;
3459 }
3460
3461 token = next_token (&val, cfile);
3462 if (token != NUMBER) {
4615d498 3463 parse_warn (cfile, "number expected.");
20c4e94d 3464 *lose = 1;
4bd8800e 3465 expression_dereference (expr, MDL);
20c4e94d
TL
3466 return 0;
3467 }
3468 switch (atoi (val)) {
3469 case 8:
3470 (*expr) -> op = expr_encode_int8;
3471 break;
3472
3473 case 16:
3474 (*expr) -> op = expr_encode_int16;
3475 break;
3476
3477 case 32:
3478 (*expr) -> op = expr_encode_int32;
3479 break;
3480
3481 default:
4615d498
TL
3482 parse_warn (cfile,
3483 "unsupported integer size %d", atoi (val));
20c4e94d
TL
3484 *lose = 1;
3485 skip_to_semi (cfile);
4bd8800e 3486 expression_dereference (expr, MDL);
20c4e94d
TL
3487 return 0;
3488 }
3489
3490 token = next_token (&val, cfile);
3491 if (token != RPAREN) {
4615d498 3492 parse_warn (cfile, "right parenthesis expected.");
20c4e94d 3493 *lose = 1;
4bd8800e 3494 expression_dereference (expr, MDL);
20c4e94d
TL
3495 return 0;
3496 }
3497 break;
3498
be6be08d 3499 case NUMBER:
02a015fb
TL
3500 /* If we're in a numeric context, this should just be a
3501 number, by itself. */
f579f39f
TL
3502 if (context == context_numeric ||
3503 context == context_data_or_numeric) {
02a015fb 3504 next_token (&val, cfile); /* Eat the number. */
4bd8800e 3505 if (!expression_allocate (expr, MDL))
be19167d 3506 log_fatal ("can't allocate expression");
02a015fb
TL
3507 (*expr) -> op = expr_const_int;
3508 (*expr) -> data.const_int = atoi (val);
3509 break;
3510 }
be6be08d 3511
02a015fb 3512 case NUMBER_OR_NAME:
4bd8800e 3513 if (!expression_allocate (expr, MDL))
be19167d
TL
3514 log_fatal ("can't allocate expression");
3515
02a015fb
TL
3516 (*expr) -> op = expr_const_data;
3517 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
4bd8800e 3518 expression_dereference (expr, MDL);
02a015fb
TL
3519 return 0;
3520 }
3521 break;
3522
f579f39f
TL
3523 case NS_FORMERR:
3524 known = FORMERR;
3525 ns_const:
3526 token = next_token (&val, cfile);
4bd8800e 3527 if (!expression_allocate (expr, MDL))
f579f39f
TL
3528 log_fatal ("can't allocate expression");
3529 (*expr) -> op = expr_const_int;
3530 (*expr) -> data.const_int = known;
3531 break;
3532
3533 case NS_NOERROR:
3534 known = NOERROR;
3535 goto ns_const;
3536
3537 case NS_NOTAUTH:
3538 known = NOTAUTH;
3539 goto ns_const;
3540
3541 case NS_NOTIMP:
3542 known = NOTIMP;
3543 goto ns_const;
3544
3545 case NS_NOTZONE:
3546 known = NOTZONE;
3547 goto ns_const;
3548
3549 case NS_NXDOMAIN:
3550 known = NXDOMAIN;
3551 goto ns_const;
3552
3553 case NS_NXRRSET:
3554 known = NXRRSET;
3555 goto ns_const;
3556
3557 case NS_REFUSED:
3558 known = REFUSED;
3559 goto ns_const;
3560
3561 case NS_SERVFAIL:
3562 known = SERVFAIL;
3563 goto ns_const;
3564
3565 case NS_YXDOMAIN:
3566 known = YXDOMAIN;
3567 goto ns_const;
3568
3569 case NS_YXRRSET:
3570 known = YXRRSET;
3571 goto ns_const;
3572
3573 case DEFINED:
3574 token = next_token (&val, cfile);
3575 token = next_token (&val, cfile);
3576 if (token != LPAREN)
3577 goto nolparen;
3578
3579 token = next_token (&val, cfile);
3580 if (token != NAME && token != NUMBER_OR_NAME) {
3581 parse_warn (cfile, "%s can't be a variable name", val);
3582 skip_to_semi (cfile);
3583 *lose = 1;
3584 return 0;
3585 }
3586
4bd8800e 3587 if (!expression_allocate (expr, MDL))
f579f39f
TL
3588 log_fatal ("can't allocate expression");
3589 (*expr) -> op = expr_variable_exists;
fdac15d9 3590 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
f579f39f
TL
3591 if (!(*expr)->data.variable)
3592 log_fatal ("can't allocate variable name");
3593 strcpy ((*expr) -> data.variable, val);
3594 token = next_token (&val, cfile);
3595 if (token != RPAREN)
3596 goto norparen;
3597 break;
3598
02a015fb 3599 /* Not a valid start to an expression... */
be6be08d 3600 default:
f579f39f
TL
3601 if (token != NAME && token != NUMBER_OR_NAME)
3602 return 0;
3603
08514fb8
TL
3604 token = next_token (&val, cfile);
3605
3606 /* Save the name of the variable being referenced. */
3607 cptr = dmalloc (strlen (val) + 1, MDL);
3608 if (!cptr)
3609 log_fatal ("can't allocate variable name");
3610 strcpy (cptr, val);
3611
3612 /* Simple variable reference, as far as we can tell. */
3613 token = peek_token (&val, cfile);
3614 if (token != LPAREN) {
3615 if (!expression_allocate (expr, MDL))
3616 log_fatal ("can't allocate expression");
3617 (*expr) -> op = expr_variable_reference;
3618 (*expr) -> data.variable = cptr;
3619 break;
3620 }
3621
f579f39f 3622 token = next_token (&val, cfile);
4bd8800e 3623 if (!expression_allocate (expr, MDL))
f579f39f 3624 log_fatal ("can't allocate expression");
08514fb8
TL
3625 (*expr) -> op = expr_funcall;
3626 (*expr) -> data.funcall.name = cptr;
3627
3628 /* Now parse the argument list. */
3629 ep = &(*expr) -> data.funcall.arglist;
3630 do {
3631 if (!expression_allocate (ep, MDL))
3632 log_fatal ("can't allocate expression");
3633 (*ep) -> op = expr_arg;
3634 if (!parse_expression (&(*ep) -> data.arg.val,
3635 cfile, lose, context_any,
3636 (struct expression **)0,
3637 expr_none)) {
3638 if (!*lose) {
3639 parse_warn (cfile,
3640 "expecting expression.");
3641 *lose = 1;
3642 }
3643 skip_to_semi (cfile);
3644 expression_dereference (expr, MDL);
3645 return 0;
3646 }
3647 ep = &((*ep) -> data.arg.next);
3648 token = next_token (&val, cfile);
3649 } while (token == COMMA);
3650 if (token != RPAREN) {
3651 parse_warn (cfile, "Right parenthesis expected.");
3652 skip_to_semi (cfile);
3653 *lose = 1;
3654 expression_dereference (expr, MDL);
3655 return 0;
3656 }
f579f39f 3657 break;
be6be08d 3658 }
02a015fb 3659 return 1;
be6be08d
TL
3660}
3661
02a015fb
TL
3662/* Parse an expression. */
3663
3664int parse_expression (expr, cfile, lose, context, plhs, binop)
3665 struct expression **expr;
4615d498 3666 struct parse *cfile;
02a015fb
TL
3667 int *lose;
3668 enum expression_context context;
3669 struct expression **plhs;
3670 enum expr_op binop;
3671{
3672 enum dhcp_token token;
b1b7b521 3673 const char *val;
02a015fb
TL
3674 struct expression *rhs = (struct expression *)0, *tmp;
3675 struct expression *lhs;
3676 enum expr_op next_op;
3677
3678 /* Consume the left hand side we were passed. */
3679 if (plhs) {
3680 lhs = *plhs;
3681 *plhs = (struct expression *)0;
3682 } else
3683 lhs = (struct expression *)0;
3684
3685 new_rhs:
3686 if (!parse_non_binary (&rhs, cfile, lose, context)) {
3687 /* If we already have a left-hand side, then it's not
3688 okay for there not to be a right-hand side here, so
3689 we need to flag it as an error. */
3690 if (lhs) {
3691 if (!*lose) {
4615d498
TL
3692 parse_warn (cfile,
3693 "expecting right-hand side.");
02a015fb
TL
3694 *lose = 1;
3695 skip_to_semi (cfile);
3696 }
4bd8800e 3697 expression_dereference (&lhs, MDL);
02a015fb
TL
3698 }
3699 return 0;
3700 }
3701
3702 /* At this point, rhs contains either an entire subexpression,
3703 or at least a left-hand-side. If we do not see a binary token
3704 as the next token, we're done with the expression. */
3705
3706 token = peek_token (&val, cfile);
3707 switch (token) {
2b965a44
TL
3708 case BANG:
3709 token = next_token (&val, cfile);
3710 token = peek_token (&val, cfile);
3711 if (token != EQUAL) {
3712 parse_warn (cfile, "! in boolean context without =");
3713 *lose = 1;
3714 skip_to_semi (cfile);
3715 if (lhs)
4bd8800e 3716 expression_dereference (&lhs, MDL);
2b965a44
TL
3717 return 0;
3718 }
3719 next_op = expr_not_equal;
3720 break;
3721
02a015fb
TL
3722 case EQUAL:
3723 next_op = expr_equal;
3724 break;
3725
3726 case AND:
3727 next_op = expr_and;
3728 break;
3729
3730 case OR:
3731 next_op = expr_or;
3732 break;
3733
31cb2a5f
TL
3734 case PLUS:
3735 next_op = expr_add;
3736 break;
3737
3738 case MINUS:
3739 next_op = expr_subtract;
3740 break;
3741
3742 case SLASH:
3743 next_op = expr_divide;
3744 break;
3745
3746 case ASTERISK:
3747 next_op = expr_multiply;
3748 break;
3749
3750 case PERCENT:
3751 next_op = expr_remainder;
3752 break;
3753
3c98e80b
DN
3754 case AMPERSAND:
3755 next_op = expr_binary_and;
3756 break;
3757
3758 case PIPE:
3759 next_op = expr_binary_or;
3760 break;
3761
3762 case CARET:
3763 next_op = expr_binary_xor;
3764 break;
3765
02a015fb
TL
3766 default:
3767 next_op = expr_none;
3768 }
3769
3770 /* If we have no lhs yet, we just parsed it. */
3771 if (!lhs) {
3772 /* If there was no operator following what we just parsed,
3773 then we're done - return it. */
3774 if (next_op == expr_none) {
3775 *expr = rhs;
3776 return 1;
3777 }
3778 lhs = rhs;
3779 rhs = (struct expression *)0;
3780 binop = next_op;
3781 next_token (&val, cfile); /* Consume the operator. */
3782 goto new_rhs;
3783 }
3784
3785 /* Now, if we didn't find a binary operator, we're done parsing
3786 this subexpression, so combine it with the preceding binary
3787 operator and return the result. */
3788 if (next_op == expr_none) {
4bd8800e 3789 if (!expression_allocate (expr, MDL))
8ae2d595 3790 log_fatal ("Can't allocate expression!");
02a015fb
TL
3791
3792 (*expr) -> op = binop;
3793 /* All the binary operators' data union members
3794 are the same, so we'll cheat and use the member
3795 for the equals operator. */
3796 (*expr) -> data.equal [0] = lhs;
3797 (*expr) -> data.equal [1] = rhs;
3798 return 1;
3799 }
3800
3801 /* Eat the operator token - we now know it was a binary operator... */
3802 token = next_token (&val, cfile);
3803
3804 /* If the binary operator we saw previously has a lower precedence
3805 than the next operator, then the rhs we just parsed for that
3806 operator is actually the lhs of the operator with the higher
3807 precedence - to get the real rhs, we need to recurse on the
3808 new operator. */
3809 if (binop != expr_none &&
3810 op_precedence (binop, next_op) < 0) {
3811 tmp = rhs;
3812 rhs = (struct expression *)0;
3813 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
3814 &tmp, next_op)) {
3815 if (!*lose) {
4615d498
TL
3816 parse_warn (cfile,
3817 "expecting a subexpression");
02a015fb
TL
3818 *lose = 1;
3819 }
3820 return 0;
3821 }
3822 next_op = expr_none;
3823 }
3824
3825 /* Now combine the LHS and the RHS using binop. */
3826 tmp = (struct expression *)0;
4bd8800e 3827 if (!expression_allocate (&tmp, MDL))
8ae2d595 3828 log_fatal ("No memory for equal precedence combination.");
02a015fb
TL
3829
3830 /* Store the LHS and RHS. */
3831 tmp -> data.equal [0] = lhs;
3832 tmp -> data.equal [1] = rhs;
3833 tmp -> op = binop;
3834
3835 lhs = tmp;
3836 tmp = (struct expression *)0;
3837 rhs = (struct expression *)0;
3838
3839 /* Recursions don't return until we have parsed the end of the
3840 expression, so if we recursed earlier, we can now return what
3841 we got. */
3842 if (next_op == expr_none) {
3843 *expr = lhs;
3844 return 1;
3845 }
3846
3847 binop = next_op;
3848 goto new_rhs;
3849}
3850
be6be08d
TL
3851/* option-statement :== identifier DOT identifier <syntax> SEMI
3852 | identifier <syntax> SEMI
3853
3854 Option syntax is handled specially through format strings, so it
3855 would be painful to come up with BNF for it. However, it always
3856 starts as above and ends in a SEMI. */
3857
79a65726
TL
3858int parse_option_statement (result, cfile, lookups, option, op)
3859 struct executable_statement **result;
4615d498 3860 struct parse *cfile;
be6be08d
TL
3861 int lookups;
3862 struct option *option;
3863 enum statement_op op;
3864{
b1b7b521 3865 const char *val;
02a015fb 3866 enum dhcp_token token;
d8fc5060 3867 const char *fmt = NULL;
be6be08d 3868 struct expression *expr = (struct expression *)0;
02a015fb 3869 struct expression *tmp;
be6be08d
TL
3870 int lose;
3871 struct executable_statement *stmt;
02a015fb 3872 int ftt = 1;
be6be08d
TL
3873
3874 token = peek_token (&val, cfile);
3875 if (token == SEMI) {
3876 /* Eat the semicolon... */
3877 token = next_token (&val, cfile);
be6be08d
TL
3878 goto done;
3879 }
3880
a82abfc7
TL
3881 if (token == EQUAL) {
3882 /* Eat the equals sign. */
3883 token = next_token (&val, cfile);
3884
3885 /* Parse a data expression and use its value for the data. */
3886 if (!parse_data_expression (&expr, cfile, &lose)) {
3887 /* In this context, we must have an executable
3888 statement, so if we found something else, it's
3889 still an error. */
3890 if (!lose) {
4615d498
TL
3891 parse_warn (cfile,
3892 "expecting a data expression.");
a82abfc7
TL
3893 skip_to_semi (cfile);
3894 }
79a65726 3895 return 0;
a82abfc7
TL
3896 }
3897
3898 /* We got a valid expression, so use it. */
3899 goto done;
3900 }
3901
be6be08d
TL
3902 /* Parse the option data... */
3903 do {
3904 /* Set a flag if this is an array of a simple type (i.e.,
3905 not an array of pairs of IP addresses, or something
3906 like that. */
3907 int uniform = option -> format [1] == 'A';
3908
d8fc5060
TL
3909 and_again:
3910 /* Set fmt to start of format for 'A' and one char back
3911 for 'a' */
3912 if ((fmt != NULL) &&
3913 (fmt != option -> format) && (*fmt == 'a'))
3914 fmt -= 1;
3915 else
3916 fmt = ((fmt == NULL) ||
3917 (*fmt == 'A')) ? option -> format : fmt;
3918
3919 /* 'a' means always uniform */
3920 uniform |= (fmt [1] == 'a');
3921
3922 for ( ; *fmt; fmt++) {
3923 if ((*fmt == 'A') || (*fmt == 'a'))
be6be08d 3924 break;
d8fc5060
TL
3925 if (*fmt == 'o')
3926 continue;
02a015fb 3927 tmp = expr;
44aa67f6 3928 expr = (struct expression *)0;
02a015fb
TL
3929 if (!parse_option_token (&expr, cfile, fmt,
3930 tmp, uniform, lookups)) {
d8fc5060
TL
3931 if (fmt [1] != 'o') {
3932 if (tmp)
3933 expression_dereference (&tmp,
3934 MDL);
3935 return 0;
3936 }
3937 expr = tmp;
3938 tmp = (struct expression *)0;
02a015fb
TL
3939 }
3940 if (tmp)
4bd8800e 3941 expression_dereference (&tmp, MDL);
be6be08d 3942 }
d8fc5060 3943 if ((*fmt == 'A') || (*fmt == 'a')) {
be6be08d 3944 token = peek_token (&val, cfile);
d8fc5060 3945 /* Comma means: continue with next element in array */
be6be08d
TL
3946 if (token == COMMA) {
3947 token = next_token (&val, cfile);
3948 continue;
3949 }
d8fc5060
TL
3950 /* no comma: end of array.
3951 'A' or end of string means: leave the loop */
3952 if ((*fmt == 'A') || (fmt[1] == '\0'))
3953 break;
3954 /* 'a' means: go on with next char */
3955 if (*fmt == 'a') {
3956 fmt++;
3957 goto and_again;
3958 }
be6be08d 3959 }
d8fc5060 3960 } while ((*fmt == 'A') || (*fmt == 'a'));
be6be08d
TL
3961
3962 done:
25541f2f 3963 if (!parse_semi (cfile))
79a65726 3964 return 0;
4bd8800e 3965 if (!executable_statement_allocate (result, MDL))
79a65726
TL
3966 log_fatal ("no memory for option statement.");
3967 (*result) -> op = op;
3968 if (expr && !option_cache (&(*result) -> data.option,
02a015fb 3969 (struct data_string *)0, expr, option))
52c9d530 3970 log_fatal ("no memory for option cache");
79a65726 3971 return 1;
be6be08d
TL
3972}
3973
02a015fb
TL
3974int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
3975 struct expression **rv;
4615d498 3976 struct parse *cfile;
b1b7b521 3977 const char *fmt;
be6be08d
TL
3978 struct expression *expr;
3979 int uniform;
3980 int lookups;
3981{
b1b7b521 3982 const char *val;
02a015fb
TL
3983 enum dhcp_token token;
3984 struct expression *t = (struct expression *)0;
be6be08d
TL
3985 unsigned char buf [4];
3986 int len;
3987 unsigned char *ob;
3988 struct iaddr addr;
fdac15d9 3989 int num;
be6be08d
TL
3990
3991 switch (*fmt) {
52c9d530 3992 case 'U':
d8fc5060 3993 token = peek_token (&val, cfile);
52c9d530 3994 if (!is_identifier (token)) {
d8fc5060
TL
3995 if (fmt [1] != 'o') {
3996 parse_warn (cfile, "expecting identifier.");
3997 skip_to_semi (cfile);
3998 }
52c9d530
TL
3999 return 0;
4000 }
d8fc5060 4001 token = next_token (&val, cfile);
b1b7b521 4002 if (!make_const_data (&t, (const unsigned char *)val,
52c9d530
TL
4003 strlen (val), 1, 1))
4004 log_fatal ("No memory for %s", val);
4005 break;
4006
be6be08d
TL
4007 case 'X':
4008 token = peek_token (&val, cfile);
4009 if (token == NUMBER_OR_NAME || token == NUMBER) {
4bd8800e 4010 if (!expression_allocate (&t, MDL))
02a015fb 4011 return 0;
8cc4d857 4012 if (!parse_cshl (&t -> data.const_data, cfile)) {
4bd8800e 4013 expression_dereference (&t, MDL);
01e20b9e 4014 return 0;
8cc4d857 4015 }
efc79acb 4016 t -> op = expr_const_data;
be6be08d
TL
4017 } else if (token == STRING) {
4018 token = next_token (&val, cfile);
b1b7b521 4019 if (!make_const_data (&t, (const unsigned char *)val,
02a015fb 4020 strlen (val), 1, 1))
52c9d530 4021 log_fatal ("No memory for \"%s\"", val);
be6be08d 4022 } else {
d8fc5060
TL
4023 if (fmt [1] != 'o') {
4024 parse_warn (cfile, "expecting string %s.",
4025 "or hexadecimal data");
4026 skip_to_semi (cfile);
4027 }
02a015fb 4028 return 0;
be6be08d
TL
4029 }
4030 break;
4031
4032 case 't': /* Text string... */
d8fc5060 4033 token = peek_token (&val, cfile);
be6be08d 4034 if (token != STRING && !is_identifier (token)) {
d8fc5060
TL
4035 if (fmt [1] != 'o') {
4036 parse_warn (cfile, "expecting string.");
4037 if (token != SEMI)
4038 skip_to_semi (cfile);
4039 }
02a015fb 4040 return 0;
be6be08d 4041 }
d8fc5060 4042 token = next_token (&val, cfile);
b1b7b521 4043 if (!make_const_data (&t, (const unsigned char *)val,
02a015fb 4044 strlen (val), 1, 1))
8ae2d595 4045 log_fatal ("No memory for concatenation");
be6be08d
TL
4046 break;
4047
4048 case 'I': /* IP address or hostname. */
02a015fb
TL
4049 if (lookups) {
4050 if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
4051 return 0;
4052 } else {
be6be08d 4053 if (!parse_ip_addr (cfile, &addr))
02a015fb
TL
4054 return 0;
4055 if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1))
4056 return 0;
be6be08d 4057 }
be6be08d
TL
4058 break;
4059
fdac15d9 4060 case 'T': /* Lease interval. */
d8fc5060 4061 token = peek_token (&val, cfile);
fdac15d9
TL
4062 if (token != INFINITE)
4063 goto check_number;
d8fc5060 4064 token = next_token (&val, cfile);
fdac15d9
TL
4065 putLong (buf, -1);
4066 if (!make_const_data (&t, buf, 4, 0, 1))
4067 return 0;
4068 break;
4069
be6be08d
TL
4070 case 'L': /* Unsigned 32-bit integer... */
4071 case 'l': /* Signed 32-bit integer... */
d8fc5060 4072 token = peek_token (&val, cfile);
fdac15d9 4073 check_number:
be6be08d
TL
4074 if (token != NUMBER) {
4075 need_number:
d8fc5060
TL
4076 if (fmt [1] != 'o') {
4077 parse_warn (cfile, "expecting number.");
4078 if (token != SEMI)
4079 skip_to_semi (cfile);
4080 }
02a015fb 4081 return 0;
be6be08d 4082 }
d8fc5060 4083 token = next_token (&val, cfile);
4615d498 4084 convert_num (cfile, buf, val, 0, 32);
02a015fb
TL
4085 if (!make_const_data (&t, buf, 4, 0, 1))
4086 return 0;
be6be08d 4087 break;
02a015fb 4088
be6be08d
TL
4089 case 's': /* Signed 16-bit integer. */
4090 case 'S': /* Unsigned 16-bit integer. */
d8fc5060 4091 token = peek_token (&val, cfile);
be6be08d
TL
4092 if (token != NUMBER)
4093 goto need_number;
d8fc5060 4094 token = next_token (&val, cfile);
4615d498 4095 convert_num (cfile, buf, val, 0, 16);
02a015fb
TL
4096 if (!make_const_data (&t, buf, 2, 0, 1))
4097 return 0;
be6be08d 4098 break;
02a015fb 4099
be6be08d
TL
4100 case 'b': /* Signed 8-bit integer. */
4101 case 'B': /* Unsigned 8-bit integer. */
d8fc5060 4102 token = peek_token (&val, cfile);
be6be08d
TL
4103 if (token != NUMBER)
4104 goto need_number;
d8fc5060 4105 token = next_token (&val, cfile);
4615d498 4106 convert_num (cfile, buf, val, 0, 8);
02a015fb
TL
4107 if (!make_const_data (&t, buf, 1, 0, 1))
4108 return 0;
be6be08d 4109 break;
02a015fb 4110
be6be08d 4111 case 'f': /* Boolean flag. */
d8fc5060 4112 token = peek_token (&val, cfile);
be6be08d 4113 if (!is_identifier (token)) {
d8fc5060
TL
4114 if (fmt [1] != 'o')
4115 parse_warn (cfile, "expecting identifier.");
be6be08d 4116 bad_flag:
d8fc5060
TL
4117 if (fmt [1] != 'o') {
4118 if (token != SEMI)
4119 skip_to_semi (cfile);
4120 }
02a015fb 4121 return 0;
be6be08d
TL
4122 }
4123 if (!strcasecmp (val, "true")
4124 || !strcasecmp (val, "on"))
4125 buf [0] = 1;
4126 else if (!strcasecmp (val, "false")
4127 || !strcasecmp (val, "off"))
4128 buf [0] = 0;
0776fd12
TL
4129 else if (!strcasecmp (val, "ignore"))
4130 buf [0] = 2;
be6be08d 4131 else {
d8fc5060
TL
4132 if (fmt [1] != 'o')
4133 parse_warn (cfile, "expecting boolean.");
be6be08d
TL
4134 goto bad_flag;
4135 }
d8fc5060 4136 token = next_token (&val, cfile);
02a015fb
TL
4137 if (!make_const_data (&t, buf, 1, 0, 1))
4138 return 0;
be6be08d 4139 break;
02a015fb 4140
be6be08d 4141 default:
4615d498 4142 parse_warn (cfile, "Bad format %c in parse_option_param.",
f420e08c 4143 *fmt);
be6be08d 4144 skip_to_semi (cfile);
02a015fb 4145 return 0;
be6be08d 4146 }
02a015fb
TL
4147 if (expr) {
4148 if (!make_concat (rv, expr, t))
4149 return 0;
4bd8800e 4150 expression_dereference (&t, MDL);
02a015fb
TL
4151 } else
4152 *rv = t;
4153 return 1;
be6be08d 4154}
74f45f96 4155
cfdfb9f1 4156int parse_warn (struct parse *cfile, const char *fmt, ...)
4bd8800e
TL
4157{
4158 va_list list;
4bd8800e
TL
4159 char lexbuf [256];
4160 char mbuf [1024];
4161 char fbuf [1024];
4162 unsigned i, lix;
4163
4164 do_percentm (mbuf, fmt);
4165#ifndef NO_SNPRINTF
4166 snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
4167 cfile -> tlname, cfile -> lexline, mbuf);
4168#else
4169 sprintf (fbuf, "%s line %d: %s",
4170 cfile -> tlname, cfile -> lexline, mbuf);
4171#endif
4172
cfdfb9f1 4173 va_start (list, fmt);
4bd8800e
TL
4174 vsnprintf (mbuf, sizeof mbuf, fbuf, list);
4175 va_end (list);
4176
4177 lix = 0;
4178 for (i = 0;
4179 cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
4180 if (lix < (sizeof lexbuf) - 1)
4181 lexbuf [lix++] = ' ';
4182 if (cfile -> token_line [i] == '\t') {
4183 for (lix;
4184 lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
4185 lexbuf [lix] = ' ';
4186 }
4187 }
4188 lexbuf [lix] = 0;
4189
4190#ifndef DEBUG
4f9e9f47
TL
4191 syslog (log_priority | LOG_ERR, "%s", mbuf);
4192 syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
4bd8800e
TL
4193 if (cfile -> lexchar < 81)
4194 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
4195#endif
4196
4197 if (log_perror) {
4198 write (2, mbuf, strlen (mbuf));
4199 write (2, "\n", 1);
4200 write (2, cfile -> token_line, strlen (cfile -> token_line));
4201 write (2, "\n", 1);
4202 if (cfile -> lexchar < 81)
4203 write (2, lexbuf, lix);
4204 write (2, "^\n", 2);
4205 }
4206
4207 cfile -> warnings_occurred = 1;
4208
4209 return 0;
4210}