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