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