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