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