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