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