ISC DHCP  4.3.0
A reference DHCPv4 and DHCPv6 implementation
parse.c
Go to the documentation of this file.
1 /* parse.c
2 
3  Common parser code for dhcpd and dhclient. */
4 
5 /*
6  * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  * Internet Systems Consortium, Inc.
22  * 950 Charter Street
23  * Redwood City, CA 94063
24  * <info@isc.org>
25  * https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 #include <syslog.h>
31 
32 /* Enumerations can be specified in option formats, and are used for
33  parsing, so we define the routines that manage them here. */
34 
36 
38 {
39  enumeration -> next = enumerations;
40  enumerations = enumeration;
41 }
42 
43 struct enumeration *find_enumeration (const char *name, int length)
44 {
45  struct enumeration *e;
46 
47  for (e = enumerations; e; e = e -> next)
48  if (strlen (e -> name) == length &&
49  !memcmp (e -> name, name, (unsigned)length))
50  return e;
51  return (struct enumeration *)0;
52 }
53 
55  int length,
56  unsigned *widthp,
57  const char *value)
58 {
59  struct enumeration *e;
60  int i;
61 
62  e = find_enumeration (name, length);
63  if (e) {
64  if (widthp != NULL)
65  *widthp = e->width;
66  for (i = 0; e -> values [i].name; i++) {
67  if (!strcmp (value, e -> values [i].name))
68  return &e -> values [i];
69  }
70  }
71  return (struct enumeration_value *)0;
72 }
73 
74 /* Skip to the semicolon ending the current statement. If we encounter
75  braces, the matching closing brace terminates the statement. 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)
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, (unsigned *)0, cfile);
2914  token = peek_token (&val, (unsigned *)0, cfile);
2915  if (token == STRING) {
2916  skip_token(&val, (unsigned *)0, cfile);
2917  key_name = (char *)0;
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 definition for zone %s.",
2929  zone->name);
2930  if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2931  ISC_R_SUCCESS)
2932  parse_warn (cfile, "unknown key %s", val);
2933  if (key_name)
2934  dfree (key_name, MDL);
2935  if (!parse_semi (cfile))
2936  return 0;
2937  break;
2938 
2939  default:
2940  done = 1;
2941  break;
2942  }
2943  } while (!done);
2944 
2945  token = next_token (&val, (unsigned *)0, cfile);
2946  if (token != RBRACE) {
2947  parse_warn (cfile, "expecting right brace.");
2948  return 0;
2949  }
2950  return 1;
2951 }
2952 
2953 /* key-statements :== key-statement |
2954  key-statement key-statements
2955  key-statement :==
2956  ALGORITHM host-name SEMI |
2957  secret-definition SEMI
2958  secret-definition :== SECRET base64val |
2959  SECRET STRING */
2960 
2961 int parse_key (struct parse *cfile)
2962 {
2963  int token;
2964  const char *val;
2965  int done = 0;
2966  struct auth_key *key;
2967  struct data_string ds;
2968  isc_result_t status;
2969  char *s;
2970 
2971  key = (struct auth_key *)0;
2972  if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2973  log_fatal ("no memory for key");
2974 
2975  token = peek_token (&val, (unsigned *)0, cfile);
2976  if (token == STRING) {
2977  skip_token(&val, (unsigned *)0, cfile);
2978  key -> name = dmalloc (strlen (val) + 1, MDL);
2979  if (!key -> name)
2980  log_fatal ("no memory for key name.");
2981  strcpy (key -> name, val);
2982 
2983  } else {
2984  key -> name = parse_host_name (cfile);
2985  if (!key -> name) {
2986  parse_warn (cfile, "expecting key name.");
2987  skip_to_semi (cfile);
2988  goto bad;
2989  }
2990  }
2991 
2992  token = next_token (&val, (unsigned *)0, cfile);
2993  if (token != LBRACE) {
2994  parse_warn (cfile, "expecting left brace");
2995  goto bad;
2996  }
2997 
2998  do {
2999  token = next_token (&val, (unsigned *)0, cfile);
3000  switch (token) {
3001  case ALGORITHM:
3002  if (key -> algorithm) {
3003  parse_warn (cfile,
3004  "key %s: too many algorithms",
3005  key -> name);
3006  goto rbad;
3007  }
3008  key -> algorithm = parse_host_name (cfile);
3009  if (!key -> algorithm) {
3010  parse_warn (cfile,
3011  "expecting key algorithm name.");
3012  goto rbad;
3013  }
3014  if (!parse_semi (cfile))
3015  goto rbad;
3016  /* If the algorithm name isn't an FQDN, tack on
3017  the .SIG-ALG.REG.NET. domain. */
3018  s = strrchr (key -> algorithm, '.');
3019  if (!s) {
3020  static char add [] = ".SIG-ALG.REG.INT.";
3021  s = dmalloc (strlen (key -> algorithm) +
3022  sizeof (add), MDL);
3023  if (!s) {
3024  log_error ("no memory for key %s.",
3025  "algorithm");
3026  goto rbad;
3027  }
3028  strcpy (s, key -> algorithm);
3029  strcat (s, add);
3030  dfree (key -> algorithm, MDL);
3031  key -> algorithm = s;
3032  } else if (s [1]) {
3033  /* If there is no trailing '.', hack one in. */
3034  s = dmalloc (strlen (key -> algorithm) + 2, MDL);
3035  if (!s) {
3036  log_error ("no memory for key %s.",
3037  key -> algorithm);
3038  goto rbad;
3039  }
3040  strcpy (s, key -> algorithm);
3041  strcat (s, ".");
3042  dfree (key -> algorithm, MDL);
3043  key -> algorithm = s;
3044  }
3045  break;
3046 
3047  case SECRET:
3048  if (key -> key) {
3049  parse_warn (cfile, "key %s: too many secrets",
3050  key -> name);
3051  goto rbad;
3052  }
3053 
3054  memset (&ds, 0, sizeof(ds));
3055  if (!parse_base64 (&ds, cfile))
3056  goto rbad;
3057  status = omapi_data_string_new (&key -> key, ds.len,
3058  MDL);
3059  if (status != ISC_R_SUCCESS)
3060  goto rbad;
3061  memcpy (key -> key -> value,
3062  ds.buffer -> data, ds.len);
3063  data_string_forget (&ds, MDL);
3064 
3065  if (!parse_semi (cfile))
3066  goto rbad;
3067  break;
3068 
3069  default:
3070  done = 1;
3071  break;
3072  }
3073  } while (!done);
3074  if (token != RBRACE) {
3075  parse_warn (cfile, "expecting right brace.");
3076  goto rbad;
3077  }
3078  /* Allow the BIND 8 syntax, which has a semicolon after each
3079  closing brace. */
3080  token = peek_token (&val, (unsigned *)0, cfile);
3081  if (token == SEMI) {
3082  skip_token(&val, (unsigned *)0, cfile);
3083  }
3084 
3085  /* Remember the key. */
3086  status = omapi_auth_key_enter (key);
3087  if (status != ISC_R_SUCCESS) {
3088  parse_warn (cfile, "tsig key %s: %s",
3089  key -> name, isc_result_totext (status));
3090  goto bad;
3091  }
3092  omapi_auth_key_dereference (&key, MDL);
3093  return 1;
3094 
3095  rbad:
3096  skip_to_rbrace (cfile, 1);
3097  bad:
3098  omapi_auth_key_dereference (&key, MDL);
3099  return 0;
3100 }
3101 
3102 /*
3103  * on-statement :== event-types LBRACE executable-statements RBRACE
3104  * event-types :== event-type OR event-types |
3105  * event-type
3106  * event-type :== EXPIRY | COMMIT | RELEASE
3107  */
3108 
3109 int parse_on_statement (result, cfile, lose)
3110  struct executable_statement **result;
3111  struct parse *cfile;
3112  int *lose;
3113 {
3114  enum dhcp_token token;
3115  const char *val;
3116 
3117  if (!executable_statement_allocate (result, MDL))
3118  log_fatal ("no memory for new statement.");
3119  (*result) -> op = on_statement;
3120 
3121  do {
3122  token = next_token (&val, (unsigned *)0, cfile);
3123  switch (token) {
3124  case EXPIRY:
3125  (*result) -> data.on.evtypes |= ON_EXPIRY;
3126  break;
3127 
3128  case COMMIT:
3129  (*result) -> data.on.evtypes |= ON_COMMIT;
3130  break;
3131 
3132  case RELEASE:
3133  (*result) -> data.on.evtypes |= ON_RELEASE;
3134  break;
3135 
3136  case TRANSMISSION:
3137  (*result) -> data.on.evtypes |= ON_TRANSMISSION;
3138  break;
3139 
3140  default:
3141  parse_warn (cfile, "expecting a lease event type");
3142  skip_to_semi (cfile);
3143  *lose = 1;
3145  return 0;
3146  }
3147  token = next_token (&val, (unsigned *)0, cfile);
3148  } while (token == OR);
3149 
3150  /* Semicolon means no statements. */
3151  if (token == SEMI)
3152  return 1;
3153 
3154  if (token != LBRACE) {
3155  parse_warn (cfile, "left brace expected.");
3156  skip_to_semi (cfile);
3157  *lose = 1;
3159  return 0;
3160  }
3161  if (!parse_executable_statements (&(*result) -> data.on.statements,
3162  cfile, lose, context_any)) {
3163  if (*lose) {
3164  /* Try to even things up. */
3165  do {
3166  token = next_token (&val,
3167  (unsigned *)0, cfile);
3168  } while (token != END_OF_FILE && token != RBRACE);
3170  return 0;
3171  }
3172  }
3173  token = next_token (&val, (unsigned *)0, cfile);
3174  if (token != RBRACE) {
3175  parse_warn (cfile, "right brace expected.");
3176  skip_to_semi (cfile);
3177  *lose = 1;
3179  return 0;
3180  }
3181  return 1;
3182 }
3183 
3184 /*
3185  * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3186  *
3187  */
3188 
3189 int parse_switch_statement (result, cfile, lose)
3190  struct executable_statement **result;
3191  struct parse *cfile;
3192  int *lose;
3193 {
3194  enum dhcp_token token;
3195  const char *val;
3196 
3197  if (!executable_statement_allocate (result, MDL))
3198  log_fatal ("no memory for new statement.");
3199  (*result) -> op = switch_statement;
3200 
3201  token = next_token (&val, (unsigned *)0, cfile);
3202  if (token != LPAREN) {
3203  parse_warn (cfile, "expecting left brace.");
3204  pfui:
3205  *lose = 1;
3206  skip_to_semi (cfile);
3207  gnorf:
3209  return 0;
3210  }
3211 
3212  if (!parse_expression (&(*result) -> data.s_switch.expr,
3213  cfile, lose, context_data_or_numeric,
3214  (struct expression **)0, expr_none)) {
3215  if (!*lose) {
3216  parse_warn (cfile,
3217  "expecting data or numeric expression.");
3218  goto pfui;
3219  }
3220  goto gnorf;
3221  }
3222 
3223  token = next_token (&val, (unsigned *)0, cfile);
3224  if (token != RPAREN) {
3225  parse_warn (cfile, "right paren expected.");
3226  goto pfui;
3227  }
3228 
3229  token = next_token (&val, (unsigned *)0, cfile);
3230  if (token != LBRACE) {
3231  parse_warn (cfile, "left brace expected.");
3232  goto pfui;
3233  }
3235  (&(*result) -> data.s_switch.statements, cfile, lose,
3236  (is_data_expression ((*result) -> data.s_switch.expr)
3237  ? context_data : context_numeric)))) {
3238  if (*lose) {
3239  skip_to_rbrace (cfile, 1);
3241  return 0;
3242  }
3243  }
3244  token = next_token (&val, (unsigned *)0, cfile);
3245  if (token != RBRACE) {
3246  parse_warn (cfile, "right brace expected.");
3247  goto pfui;
3248  }
3249  return 1;
3250 }
3251 
3252 /*
3253  * case-statement :== CASE expr COLON
3254  *
3255  */
3256 
3257 int parse_case_statement (result, cfile, lose, case_context)
3258  struct executable_statement **result;
3259  struct parse *cfile;
3260  int *lose;
3261  enum expression_context case_context;
3262 {
3263  enum dhcp_token token;
3264  const char *val;
3265 
3266  if (!executable_statement_allocate (result, MDL))
3267  log_fatal ("no memory for new statement.");
3268  (*result) -> op = case_statement;
3269 
3270  if (!parse_expression (&(*result) -> data.c_case,
3271  cfile, lose, case_context,
3272  (struct expression **)0, expr_none))
3273  {
3274  if (!*lose) {
3275  parse_warn (cfile, "expecting %s expression.",
3276  (case_context == context_data
3277  ? "data" : "numeric"));
3278  }
3279  pfui:
3280  *lose = 1;
3281  skip_to_semi (cfile);
3283  return 0;
3284  }
3285 
3286  token = next_token (&val, (unsigned *)0, cfile);
3287  if (token != COLON) {
3288  parse_warn (cfile, "colon expected.");
3289  goto pfui;
3290  }
3291  return 1;
3292 }
3293 
3294 /*
3295  * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3296  * else-statement
3297  *
3298  * else-statement :== <null> |
3299  * ELSE LBRACE executable-statements RBRACE |
3300  * ELSE IF if-statement |
3301  * ELSIF if-statement
3302  */
3303 
3304 int parse_if_statement (result, cfile, lose)
3305  struct executable_statement **result;
3306  struct parse *cfile;
3307  int *lose;
3308 {
3309  enum dhcp_token token;
3310  const char *val;
3311  int parenp;
3312 
3313  if (!executable_statement_allocate (result, MDL))
3314  log_fatal ("no memory for if statement.");
3315 
3316  (*result) -> op = if_statement;
3317 
3318  token = peek_token (&val, (unsigned *)0, cfile);
3319  if (token == LPAREN) {
3320  parenp = 1;
3321  skip_token(&val, (unsigned *)0, cfile);
3322  } else
3323  parenp = 0;
3324 
3325 
3326  if (!parse_boolean_expression (&(*result) -> data.ie.expr,
3327  cfile, lose)) {
3328  if (!*lose)
3329  parse_warn (cfile, "boolean expression expected.");
3331  *lose = 1;
3332  return 0;
3333  }
3334 #if defined (DEBUG_EXPRESSION_PARSE)
3335  print_expression ("if condition", (*result) -> data.ie.expr);
3336 #endif
3337  if (parenp) {
3338  token = next_token (&val, (unsigned *)0, cfile);
3339  if (token != RPAREN) {
3340  parse_warn (cfile, "expecting right paren.");
3341  *lose = 1;
3343  return 0;
3344  }
3345  }
3346  token = next_token (&val, (unsigned *)0, cfile);
3347  if (token != LBRACE) {
3348  parse_warn (cfile, "left brace expected.");
3349  skip_to_semi (cfile);
3350  *lose = 1;
3352  return 0;
3353  }
3354  if (!parse_executable_statements (&(*result) -> data.ie.tc,
3355  cfile, lose, context_any)) {
3356  if (*lose) {
3357  /* Try to even things up. */
3358  do {
3359  token = next_token (&val,
3360  (unsigned *)0, cfile);
3361  } while (token != END_OF_FILE && token != RBRACE);
3363  return 0;
3364  }
3365  }
3366  token = next_token (&val, (unsigned *)0, cfile);
3367  if (token != RBRACE) {
3368  parse_warn (cfile, "right brace expected.");
3369  skip_to_semi (cfile);
3370  *lose = 1;
3372  return 0;
3373  }
3374  token = peek_token (&val, (unsigned *)0, cfile);
3375  if (token == ELSE) {
3376  skip_token(&val, (unsigned *)0, cfile);
3377  token = peek_token (&val, (unsigned *)0, cfile);
3378  if (token == IF) {
3379  skip_token(&val, (unsigned *)0, cfile);
3380  if (!parse_if_statement (&(*result) -> data.ie.fc,
3381  cfile, lose)) {
3382  if (!*lose)
3383  parse_warn (cfile,
3384  "expecting if statement");
3386  *lose = 1;
3387  return 0;
3388  }
3389  } else if (token != LBRACE) {
3390  parse_warn (cfile, "left brace or if expected.");
3391  skip_to_semi (cfile);
3392  *lose = 1;
3394  return 0;
3395  } else {
3396  skip_token(&val, (unsigned *)0, cfile);
3398  (&(*result) -> data.ie.fc,
3399  cfile, lose, context_any))) {
3401  return 0;
3402  }
3403  token = next_token (&val, (unsigned *)0, cfile);
3404  if (token != RBRACE) {
3405  parse_warn (cfile, "right brace expected.");
3406  skip_to_semi (cfile);
3407  *lose = 1;
3409  return 0;
3410  }
3411  }
3412  } else if (token == ELSIF) {
3413  skip_token(&val, (unsigned *)0, cfile);
3414  if (!parse_if_statement (&(*result) -> data.ie.fc,
3415  cfile, lose)) {
3416  if (!*lose)
3417  parse_warn (cfile,
3418  "expecting conditional.");
3420  *lose = 1;
3421  return 0;
3422  }
3423  } else
3424  (*result) -> data.ie.fc = (struct executable_statement *)0;
3425 
3426  return 1;
3427 }
3428 
3429 /*
3430  * boolean_expression :== CHECK STRING |
3431  * NOT boolean-expression |
3432  * data-expression EQUAL data-expression |
3433  * data-expression BANG EQUAL data-expression |
3434  * data-expression REGEX_MATCH data-expression |
3435  * boolean-expression AND boolean-expression |
3436  * boolean-expression OR boolean-expression
3437  * EXISTS OPTION-NAME
3438  */
3439 
3440 int parse_boolean_expression (expr, cfile, lose)
3441  struct expression **expr;
3442  struct parse *cfile;
3443  int *lose;
3444 {
3445  /* Parse an expression... */
3446  if (!parse_expression (expr, cfile, lose, context_boolean,
3447  (struct expression **)0, expr_none))
3448  return 0;
3449 
3450  if (!is_boolean_expression (*expr) &&
3451  (*expr) -> op != expr_variable_reference &&
3452  (*expr) -> op != expr_funcall) {
3453  parse_warn (cfile, "Expecting a boolean expression.");
3454  *lose = 1;
3455  expression_dereference (expr, MDL);
3456  return 0;
3457  }
3458  return 1;
3459 }
3460 
3461 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3462 
3463 int parse_boolean (cfile)
3464  struct parse *cfile;
3465 {
3466  const char *val;
3467  int rv;
3468 
3469  (void)next_token(&val, NULL, cfile);
3470  if (!strcasecmp (val, "true")
3471  || !strcasecmp (val, "on"))
3472  rv = 1;
3473  else if (!strcasecmp (val, "false")
3474  || !strcasecmp (val, "off"))
3475  rv = 0;
3476  else {
3477  parse_warn (cfile,
3478  "boolean value (true/false/on/off) expected");
3479  skip_to_semi (cfile);
3480  return 0;
3481  }
3482  parse_semi (cfile);
3483  return rv;
3484 }
3485 
3486 
3487 /*
3488  * data_expression :== SUBSTRING LPAREN data-expression COMMA
3489  * numeric-expression COMMA
3490  * numeric-expression RPAREN |
3491  * CONCAT LPAREN data-expression COMMA
3492  * data-expression RPAREN
3493  * SUFFIX LPAREN data_expression COMMA
3494  * numeric-expression RPAREN |
3495  * LCASE LPAREN data_expression RPAREN |
3496  * UCASE LPAREN data_expression RPAREN |
3497  * OPTION option_name |
3498  * HARDWARE |
3499  * PACKET LPAREN numeric-expression COMMA
3500  * numeric-expression RPAREN |
3501  * V6RELAY LPAREN numeric-expression COMMA
3502  * data-expression RPAREN |
3503  * STRING |
3504  * colon_separated_hex_list
3505  */
3506 
3507 int parse_data_expression (expr, cfile, lose)
3508  struct expression **expr;
3509  struct parse *cfile;
3510  int *lose;
3511 {
3512  /* Parse an expression... */
3513  if (!parse_expression (expr, cfile, lose, context_data,
3514  (struct expression **)0, expr_none))
3515  return 0;
3516 
3517  if (!is_data_expression (*expr) &&
3518  (*expr) -> op != expr_variable_reference &&
3519  (*expr) -> op != expr_funcall) {
3520  expression_dereference (expr, MDL);
3521  parse_warn (cfile, "Expecting a data expression.");
3522  *lose = 1;
3523  return 0;
3524  }
3525  return 1;
3526 }
3527 
3528 /*
3529  * numeric-expression :== EXTRACT_INT LPAREN data-expression
3530  * COMMA number RPAREN |
3531  * NUMBER
3532  */
3533 
3534 int parse_numeric_expression (expr, cfile, lose)
3535  struct expression **expr;
3536  struct parse *cfile;
3537  int *lose;
3538 {
3539  /* Parse an expression... */
3540  if (!parse_expression (expr, cfile, lose, context_numeric,
3541  (struct expression **)0, expr_none))
3542  return 0;
3543 
3544  if (!is_numeric_expression (*expr) &&
3545  (*expr) -> op != expr_variable_reference &&
3546  (*expr) -> op != expr_funcall) {
3547  expression_dereference (expr, MDL);
3548  parse_warn (cfile, "Expecting a numeric expression.");
3549  *lose = 1;
3550  return 0;
3551  }
3552  return 1;
3553 }
3554 
3555 /* Parse a subexpression that does not contain a binary operator. */
3556 
3557 int parse_non_binary (expr, cfile, lose, context)
3558  struct expression **expr;
3559  struct parse *cfile;
3560  int *lose;
3561  enum expression_context context;
3562 {
3563  enum dhcp_token token;
3564  const char *val;
3565  struct collection *col;
3566  struct expression *nexp, **ep;
3567  int known;
3568  char *cptr;
3569  isc_result_t status;
3570  unsigned len;
3571 
3572  token = peek_token (&val, (unsigned *)0, cfile);
3573 
3574  /* Check for unary operators... */
3575  switch (token) {
3576  case CHECK:
3577  skip_token(&val, (unsigned *)0, cfile);
3578  token = next_token (&val, (unsigned *)0, cfile);
3579  if (token != STRING) {
3580  parse_warn (cfile, "string expected.");
3581  skip_to_semi (cfile);
3582  *lose = 1;
3583  return 0;
3584  }
3585  for (col = collections; col; col = col -> next)
3586  if (!strcmp (col -> name, val))
3587  break;
3588  if (!col) {
3589  parse_warn (cfile, "unknown collection.");
3590  *lose = 1;
3591  return 0;
3592  }
3593  if (!expression_allocate (expr, MDL))
3594  log_fatal ("can't allocate expression");
3595  (*expr) -> op = expr_check;
3596  (*expr) -> data.check = col;
3597  break;
3598 
3599  case TOKEN_NOT:
3600  skip_token(&val, NULL, cfile);
3601  if (!expression_allocate (expr, MDL))
3602  log_fatal ("can't allocate expression");
3603  (*expr)->op = expr_not;
3604  if (!parse_non_binary (&(*expr)->data.not,
3605  cfile, lose, context_boolean)) {
3606  if (!*lose) {
3607  parse_warn (cfile, "expression expected");
3608  skip_to_semi (cfile);
3609  }
3610  *lose = 1;
3611  expression_dereference (expr, MDL);
3612  return (0);
3613  }
3614  if (!is_boolean_expression ((*expr) -> data.not)) {
3615  *lose = 1;
3616  parse_warn (cfile, "boolean expression expected");
3617  skip_to_semi (cfile);
3618  expression_dereference (expr, MDL);
3619  return 0;
3620  }
3621  break;
3622 
3623  case LPAREN:
3624  skip_token(&val, (unsigned *)0, cfile);
3625  if (!parse_expression (expr, cfile, lose, context,
3626  (struct expression **)0, expr_none)) {
3627  if (!*lose) {
3628  parse_warn (cfile, "expression expected");
3629  skip_to_semi (cfile);
3630  }
3631  *lose = 1;
3632  return 0;
3633  }
3634  token = next_token (&val, (unsigned *)0, cfile);
3635  if (token != RPAREN) {
3636  *lose = 1;
3637  parse_warn (cfile, "right paren expected");
3638  skip_to_semi (cfile);
3639  return 0;
3640  }
3641  break;
3642 
3643  case EXISTS:
3644  skip_token(&val, NULL, cfile);
3645  if (!expression_allocate (expr, MDL))
3646  log_fatal ("can't allocate expression");
3647  (*expr)->op = expr_exists;
3648  known = 0;
3649  /* Pass reference directly to expression structure. */
3650  status = parse_option_name(cfile, 0, &known,
3651  &(*expr)->data.option);
3652  if (status != ISC_R_SUCCESS ||
3653  (*expr)->data.option == NULL) {
3654  *lose = 1;
3655  expression_dereference (expr, MDL);
3656  return (0);
3657  }
3658  break;
3659 
3660  case STATIC:
3661  skip_token(&val, (unsigned *)0, cfile);
3662  if (!expression_allocate (expr, MDL))
3663  log_fatal ("can't allocate expression");
3664  (*expr) -> op = expr_static;
3665  break;
3666 
3667  case KNOWN:
3668  skip_token(&val, (unsigned *)0, cfile);
3669  if (!expression_allocate (expr, MDL))
3670  log_fatal ("can't allocate expression");
3671  (*expr) -> op = expr_known;
3672  break;
3673 
3674  case SUBSTRING:
3675  skip_token(&val, (unsigned *)0, cfile);
3676  if (!expression_allocate (expr, MDL))
3677  log_fatal ("can't allocate expression");
3678  (*expr) -> op = expr_substring;
3679 
3680  token = next_token (&val, (unsigned *)0, cfile);
3681  if (token != LPAREN) {
3682  nolparen:
3683  expression_dereference (expr, MDL);
3684  parse_warn (cfile, "left parenthesis expected.");
3685  *lose = 1;
3686  return 0;
3687  }
3688 
3689  if (!parse_data_expression (&(*expr) -> data.substring.expr,
3690  cfile, lose)) {
3691  nodata:
3692  expression_dereference (expr, MDL);
3693  if (!*lose) {
3694  parse_warn (cfile,
3695  "expecting data expression.");
3696  skip_to_semi (cfile);
3697  *lose = 1;
3698  }
3699  return 0;
3700  }
3701 
3702  token = next_token (&val, (unsigned *)0, cfile);
3703  if (token != COMMA) {
3704  nocomma:
3705  expression_dereference (expr, MDL);
3706  parse_warn (cfile, "comma expected.");
3707  *lose = 1;
3708 
3709  return 0;
3710  }
3711 
3713  (&(*expr) -> data.substring.offset,cfile, lose)) {
3714  nonum:
3715  if (!*lose) {
3716  parse_warn (cfile,
3717  "expecting numeric expression.");
3718  skip_to_semi (cfile);
3719  *lose = 1;
3720  }
3721  expression_dereference (expr, MDL);
3722  return 0;
3723  }
3724 
3725  token = next_token (&val, (unsigned *)0, cfile);
3726  if (token != COMMA)
3727  goto nocomma;
3728 
3730  (&(*expr) -> data.substring.len, cfile, lose))
3731  goto nonum;
3732 
3733  token = next_token (&val, (unsigned *)0, cfile);
3734  if (token != RPAREN) {
3735  norparen:
3736  parse_warn (cfile, "right parenthesis expected.");
3737  *lose = 1;
3738  expression_dereference (expr, MDL);
3739  return 0;
3740  }
3741  break;
3742 
3743  case SUFFIX:
3744  skip_token(&val, (unsigned *)0, cfile);
3745  if (!expression_allocate (expr, MDL))
3746  log_fatal ("can't allocate expression");
3747  (*expr) -> op = expr_suffix;
3748 
3749  token = next_token (&val, (unsigned *)0, cfile);
3750  if (token != LPAREN)
3751  goto nolparen;
3752 
3753  if (!parse_data_expression (&(*expr) -> data.suffix.expr,
3754  cfile, lose))
3755  goto nodata;
3756 
3757  token = next_token (&val, (unsigned *)0, cfile);
3758  if (token != COMMA)
3759  goto nocomma;
3760 
3761  if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
3762  cfile, lose))
3763  goto nonum;
3764 
3765  token = next_token (&val, (unsigned *)0, cfile);
3766  if (token != RPAREN)
3767  goto norparen;
3768  break;
3769 
3770  case LCASE:
3771  skip_token(&val, (unsigned *)0, cfile);
3772  if (!expression_allocate(expr, MDL))
3773  log_fatal ("can't allocate expression");
3774  (*expr)->op = expr_lcase;
3775 
3776  token = next_token(&val, (unsigned *)0, cfile);
3777  if (token != LPAREN)
3778  goto nolparen;
3779 
3780  if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose))
3781  goto nodata;
3782 
3783  token = next_token(&val, (unsigned *)0, cfile);
3784  if (token != RPAREN)
3785  goto norparen;
3786  break;
3787 
3788  case UCASE:
3789  skip_token(&val, (unsigned *)0, cfile);
3790  if (!expression_allocate(expr, MDL))
3791  log_fatal ("can't allocate expression");
3792  (*expr)->op = expr_ucase;
3793 
3794  token = next_token (&val, (unsigned *)0, cfile);
3795  if (token != LPAREN)
3796  goto nolparen;
3797 
3798  if (!parse_data_expression(&(*expr)->data.ucase,
3799  cfile, lose))
3800  goto nodata;
3801 
3802  token = next_token(&val, (unsigned *)0, cfile);
3803  if (token != RPAREN)
3804  goto norparen;
3805  break;
3806 
3807  case CONCAT:
3808  skip_token(&val, (unsigned *)0, cfile);
3809  if (!expression_allocate (expr, MDL))
3810  log_fatal ("can't allocate expression");
3811  (*expr) -> op = expr_concat;
3812 
3813  token = next_token (&val, (unsigned *)0, cfile);
3814  if (token != LPAREN)
3815  goto nolparen;
3816 
3817  if (!parse_data_expression (&(*expr) -> data.concat [0],
3818  cfile, lose))
3819  goto nodata;
3820 
3821  token = next_token (&val, (unsigned *)0, cfile);
3822  if (token != COMMA)
3823  goto nocomma;
3824 
3825  concat_another:
3826  if (!parse_data_expression (&(*expr) -> data.concat [1],
3827  cfile, lose))
3828  goto nodata;
3829 
3830  token = next_token (&val, (unsigned *)0, cfile);
3831 
3832  if (token == COMMA) {
3833  nexp = (struct expression *)0;
3834  if (!expression_allocate (&nexp, MDL))
3835  log_fatal ("can't allocate at CONCAT2");
3836  nexp -> op = expr_concat;
3837  expression_reference (&nexp -> data.concat [0],
3838  *expr, MDL);
3839  expression_dereference (expr, MDL);
3840  expression_reference (expr, nexp, MDL);
3841  expression_dereference (&nexp, MDL);
3842  goto concat_another;
3843  }
3844 
3845  if (token != RPAREN)
3846  goto norparen;
3847  break;
3848 
3849  case BINARY_TO_ASCII:
3850  skip_token(&val, (unsigned *)0, cfile);
3851  if (!expression_allocate (expr, MDL))
3852  log_fatal ("can't allocate expression");
3853  (*expr) -> op = expr_binary_to_ascii;
3854 
3855  token = next_token (&val, (unsigned *)0, cfile);
3856  if (token != LPAREN)
3857  goto nolparen;
3858 
3859  if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3860  cfile, lose))
3861  goto nodata;
3862 
3863  token = next_token (&val, (unsigned *)0, cfile);
3864  if (token != COMMA)
3865  goto nocomma;
3866 
3867  if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3868  cfile, lose))
3869  goto nodata;
3870 
3871  token = next_token (&val, (unsigned *)0, cfile);
3872  if (token != COMMA)
3873  goto nocomma;
3874 
3875  if (!parse_data_expression (&(*expr) -> data.b2a.separator,
3876  cfile, lose))
3877  goto nodata;
3878 
3879  token = next_token (&val, (unsigned *)0, cfile);
3880  if (token != COMMA)
3881  goto nocomma;
3882 
3883  if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3884  cfile, lose))
3885  goto nodata;
3886 
3887  token = next_token (&val, (unsigned *)0, cfile);
3888  if (token != RPAREN)
3889  goto norparen;
3890  break;
3891 
3892  case REVERSE:
3893  skip_token(&val, (unsigned *)0, cfile);
3894  if (!expression_allocate (expr, MDL))
3895  log_fatal ("can't allocate expression");
3896  (*expr) -> op = expr_reverse;
3897 
3898  token = next_token (&val, (unsigned *)0, cfile);
3899  if (token != LPAREN)
3900  goto nolparen;
3901 
3903  (&(*expr) -> data.reverse.width, cfile, lose)))
3904  goto nodata;
3905 
3906  token = next_token (&val, (unsigned *)0, cfile);
3907  if (token != COMMA)
3908  goto nocomma;
3909 
3910  if (!(parse_data_expression
3911  (&(*expr) -> data.reverse.buffer, cfile, lose)))
3912  goto nodata;
3913 
3914  token = next_token (&val, (unsigned *)0, cfile);
3915  if (token != RPAREN)
3916  goto norparen;
3917  break;
3918 
3919  case PICK:
3920  /* pick (a, b, c) actually produces an internal representation
3921  that looks like pick (a, pick (b, pick (c, nil))). */
3922  skip_token(&val, (unsigned *)0, cfile);
3923  if (!(expression_allocate (expr, MDL)))
3924  log_fatal ("can't allocate expression");
3925 
3926  token = next_token (&val, (unsigned *)0, cfile);
3927  if (token != LPAREN)
3928  goto nolparen;
3929 
3930  nexp = (struct expression *)0;
3931  expression_reference (&nexp, *expr, MDL);
3932  do {
3933  nexp -> op = expr_pick_first_value;
3934  if (!(parse_data_expression
3935  (&nexp -> data.pick_first_value.car,
3936  cfile, lose)))
3937  goto nodata;
3938 
3939  token = next_token (&val, (unsigned *)0, cfile);
3940  if (token == COMMA) {
3941  struct expression *foo = (struct expression *)0;
3942  if (!expression_allocate (&foo, MDL))
3943  log_fatal ("can't allocate expr");
3945  (&nexp -> data.pick_first_value.cdr, foo, MDL);
3946  expression_dereference (&nexp, MDL);
3947  expression_reference (&nexp, foo, MDL);
3948  expression_dereference (&foo, MDL);
3949  }
3950  } while (token == COMMA);
3951  expression_dereference (&nexp, MDL);
3952 
3953  if (token != RPAREN)
3954  goto norparen;
3955  break;
3956 
3957  case OPTION:
3958  case CONFIG_OPTION:
3959  if (!expression_allocate (expr, MDL))
3960  log_fatal ("can't allocate expression");
3961  (*expr) -> op = (token == OPTION
3962  ? expr_option
3963  : expr_config_option);
3964  skip_token(&val, (unsigned *)0, cfile);
3965  known = 0;
3966  /* Pass reference directly to expression structure. */
3967  status = parse_option_name(cfile, 0, &known,
3968  &(*expr)->data.option);
3969  if (status != ISC_R_SUCCESS ||
3970  (*expr)->data.option == NULL) {
3971  *lose = 1;
3972  expression_dereference (expr, MDL);
3973  return 0;
3974  }
3975  break;
3976 
3977  case HARDWARE:
3978  skip_token(&val, (unsigned *)0, cfile);
3979  if (!expression_allocate (expr, MDL))
3980  log_fatal ("can't allocate expression");
3981  (*expr) -> op = expr_hardware;
3982  break;
3983 
3984  case LEASED_ADDRESS:
3985  skip_token(&val, (unsigned *)0, cfile);
3986  if (!expression_allocate (expr, MDL))
3987  log_fatal ("can't allocate expression");
3988  (*expr) -> op = expr_leased_address;
3989  break;
3990 
3991  case CLIENT_STATE:
3992  skip_token(&val, (unsigned *)0, cfile);
3993  if (!expression_allocate (expr, MDL))
3994  log_fatal ("can't allocate expression");
3995  (*expr) -> op = expr_client_state;
3996  break;
3997 
3998  case FILENAME:
3999  skip_token(&val, (unsigned *)0, cfile);
4000  if (!expression_allocate (expr, MDL))
4001  log_fatal ("can't allocate expression");
4002  (*expr) -> op = expr_filename;
4003  break;
4004 
4005  case SERVER_NAME:
4006  skip_token(&val, (unsigned *)0, cfile);
4007  if (!expression_allocate (expr, MDL))
4008  log_fatal ("can't allocate expression");
4009  (*expr) -> op = expr_sname;
4010  break;
4011 
4012  case LEASE_TIME:
4013  skip_token(&val, (unsigned *)0, cfile);
4014  if (!expression_allocate (expr, MDL))
4015  log_fatal ("can't allocate expression");
4016  (*expr) -> op = expr_lease_time;
4017  break;
4018 
4019  case TOKEN_NULL:
4020  skip_token(&val, (unsigned *)0, cfile);
4021  if (!expression_allocate (expr, MDL))
4022  log_fatal ("can't allocate expression");
4023  (*expr) -> op = expr_null;
4024  break;
4025 
4026  case HOST_DECL_NAME:
4027  skip_token(&val, (unsigned *)0, cfile);
4028  if (!expression_allocate (expr, MDL))
4029  log_fatal ("can't allocate expression");
4030  (*expr) -> op = expr_host_decl_name;
4031  break;
4032 
4033  case PACKET:
4034  skip_token(&val, (unsigned *)0, cfile);
4035  if (!expression_allocate (expr, MDL))
4036  log_fatal ("can't allocate expression");
4037  (*expr) -> op = expr_packet;
4038 
4039  token = next_token (&val, (unsigned *)0, cfile);
4040  if (token != LPAREN)
4041  goto nolparen;
4042 
4043  if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
4044  cfile, lose))
4045  goto nonum;
4046 
4047  token = next_token (&val, (unsigned *)0, cfile);
4048  if (token != COMMA)
4049  goto nocomma;
4050 
4051  if (!parse_numeric_expression (&(*expr) -> data.packet.len,
4052  cfile, lose))
4053  goto nonum;
4054 
4055  token = next_token (&val, (unsigned *)0, cfile);
4056  if (token != RPAREN)
4057  goto norparen;
4058  break;
4059 
4060  case STRING:
4061  skip_token(&val, &len, cfile);
4062  if (!make_const_data (expr, (const unsigned char *)val,
4063  len, 1, 1, MDL))
4064  log_fatal ("can't make constant string expression.");
4065  break;
4066 
4067  case EXTRACT_INT:
4068  skip_token(&val, (unsigned *)0, cfile);
4069  token = next_token (&val, (unsigned *)0, cfile);
4070  if (token != LPAREN) {
4071  parse_warn (cfile, "left parenthesis expected.");
4072  *lose = 1;
4073  return 0;
4074  }
4075 
4076  if (!expression_allocate (expr, MDL))
4077  log_fatal ("can't allocate expression");
4078 
4079  if (!parse_data_expression (&(*expr) -> data.extract_int,
4080  cfile, lose)) {
4081  if (!*lose) {
4082  parse_warn (cfile,
4083  "expecting data expression.");
4084  skip_to_semi (cfile);
4085  *lose = 1;
4086  }
4087  expression_dereference (expr, MDL);
4088  return 0;
4089  }
4090 
4091  token = next_token (&val, (unsigned *)0, cfile);
4092  if (token != COMMA) {
4093  parse_warn (cfile, "comma expected.");
4094  *lose = 1;
4095  expression_dereference (expr, MDL);
4096  return 0;
4097  }
4098 
4099  token = next_token (&val, (unsigned *)0, cfile);
4100  if (token != NUMBER) {
4101  parse_warn (cfile, "number expected.");
4102  *lose = 1;
4103  expression_dereference (expr, MDL);
4104  return 0;
4105  }
4106  switch (atoi (val)) {
4107  case 8:
4108  (*expr) -> op = expr_extract_int8;
4109  break;
4110 
4111  case 16:
4112  (*expr) -> op = expr_extract_int16;
4113  break;
4114 
4115  case 32:
4116  (*expr) -> op = expr_extract_int32;
4117  break;
4118 
4119  default:
4120  parse_warn (cfile,
4121  "unsupported integer size %d", atoi (val));
4122  *lose = 1;
4123  skip_to_semi (cfile);
4124  expression_dereference (expr, MDL);
4125  return 0;
4126  }
4127 
4128  token = next_token (&val, (unsigned *)0, cfile);
4129  if (token != RPAREN) {
4130  parse_warn (cfile, "right parenthesis expected.");
4131  *lose = 1;
4132  expression_dereference (expr, MDL);
4133  return 0;
4134  }
4135  break;
4136 
4137  case ENCODE_INT:
4138  skip_token(&val, (unsigned *)0, cfile);
4139  token = next_token (&val, (unsigned *)0, cfile);
4140  if (token != LPAREN) {
4141  parse_warn (cfile, "left parenthesis expected.");
4142  *lose = 1;
4143  return 0;
4144  }
4145 
4146  if (!expression_allocate (expr, MDL))
4147  log_fatal ("can't allocate expression");
4148 
4149  if (!parse_numeric_expression (&(*expr) -> data.encode_int,
4150  cfile, lose)) {
4151  parse_warn (cfile, "expecting numeric expression.");
4152  skip_to_semi (cfile);
4153  *lose = 1;
4154  expression_dereference (expr, MDL);
4155  return 0;
4156  }
4157 
4158  token = next_token (&val, (unsigned *)0, cfile);
4159  if (token != COMMA) {
4160  parse_warn (cfile, "comma expected.");
4161  *lose = 1;
4162  expression_dereference (expr, MDL);
4163  return 0;
4164  }
4165 
4166  token = next_token (&val, (unsigned *)0, cfile);
4167  if (token != NUMBER) {
4168  parse_warn (cfile, "number expected.");
4169  *lose = 1;
4170  expression_dereference (expr, MDL);
4171  return 0;
4172  }
4173  switch (atoi (val)) {
4174  case 8:
4175  (*expr) -> op = expr_encode_int8;
4176  break;
4177 
4178  case 16:
4179  (*expr) -> op = expr_encode_int16;
4180  break;
4181 
4182  case 32:
4183  (*expr) -> op = expr_encode_int32;
4184  break;
4185 
4186  default:
4187  parse_warn (cfile,
4188  "unsupported integer size %d", atoi (val));
4189  *lose = 1;
4190  skip_to_semi (cfile);
4191  expression_dereference (expr, MDL);
4192  return 0;
4193  }
4194 
4195  token = next_token (&val, (unsigned *)0, cfile);
4196  if (token != RPAREN) {
4197  parse_warn (cfile, "right parenthesis expected.");
4198  *lose = 1;
4199  expression_dereference (expr, MDL);
4200  return 0;
4201  }
4202  break;
4203 
4204  case NUMBER:
4205  /* If we're in a numeric context, this should just be a
4206  number, by itself. */
4207  if (context == context_numeric ||
4208  context == context_data_or_numeric) {
4209  skip_token(&val, (unsigned *)0, cfile);
4210  if (!expression_allocate (expr, MDL))
4211  log_fatal ("can't allocate expression");
4212  (*expr) -> op = expr_const_int;
4213  (*expr) -> data.const_int = atoi (val);
4214  break;
4215  }
4216 
4217  case NUMBER_OR_NAME:
4218  if (!expression_allocate (expr, MDL))
4219  log_fatal ("can't allocate expression");
4220 
4221  (*expr) -> op = expr_const_data;
4222  if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
4223  expression_dereference (expr, MDL);
4224  return 0;
4225  }
4226  break;
4227 
4228  case NS_FORMERR:
4229  known = FORMERR;
4230  goto ns_const;
4231  ns_const:
4232  skip_token(&val, (unsigned *)0, cfile);
4233  if (!expression_allocate (expr, MDL))
4234  log_fatal ("can't allocate expression");
4235  (*expr) -> op = expr_const_int;
4236  (*expr) -> data.const_int = known;
4237  break;
4238 
4239  case NS_NOERROR:
4240  known = ISC_R_SUCCESS;
4241  goto ns_const;
4242 
4243  case NS_NOTAUTH:
4244  known = DHCP_R_NOTAUTH;
4245  goto ns_const;
4246 
4247  case NS_NOTIMP:
4248  known = ISC_R_NOTIMPLEMENTED;
4249  goto ns_const;
4250 
4251  case NS_NOTZONE:
4252  known = DHCP_R_NOTZONE;
4253  goto ns_const;
4254 
4255  case NS_NXDOMAIN:
4256  known = DHCP_R_NXDOMAIN;
4257  goto ns_const;
4258 
4259  case NS_NXRRSET:
4260  known = DHCP_R_NXRRSET;
4261  goto ns_const;
4262 
4263  case NS_REFUSED:
4264  known = DHCP_R_REFUSED;
4265  goto ns_const;
4266 
4267  case NS_SERVFAIL:
4268  known = DHCP_R_SERVFAIL;
4269  goto ns_const;
4270 
4271  case NS_YXDOMAIN:
4272  known = DHCP_R_YXDOMAIN;
4273  goto ns_const;
4274 
4275  case NS_YXRRSET:
4276  known = DHCP_R_YXRRSET;
4277  goto ns_const;
4278 
4279  case BOOTING:
4280  known = S_INIT;
4281  goto ns_const;
4282 
4283  case REBOOT:
4284  known = S_REBOOTING;
4285  goto ns_const;
4286 
4287  case SELECT:
4288  known = S_SELECTING;
4289  goto ns_const;
4290 
4291  case REQUEST:
4292  known = S_REQUESTING;
4293  goto ns_const;
4294 
4295  case BOUND:
4296  known = S_BOUND;
4297  goto ns_const;
4298 
4299  case RENEW:
4300  known = S_RENEWING;
4301  goto ns_const;
4302 
4303  case REBIND:
4304  known = S_REBINDING;
4305  goto ns_const;
4306 
4307  case DEFINED:
4308  skip_token(&val, (unsigned *)0, cfile);
4309  token = next_token (&val, (unsigned *)0, cfile);
4310  if (token != LPAREN)
4311  goto nolparen;
4312 
4313  token = next_token (&val, (unsigned *)0, cfile);
4314  if (token != NAME && token != NUMBER_OR_NAME) {
4315  parse_warn (cfile, "%s can't be a variable name", val);
4316  skip_to_semi (cfile);
4317  *lose = 1;
4318  return 0;
4319  }
4320 
4321  if (!expression_allocate (expr, MDL))
4322  log_fatal ("can't allocate expression");
4323  (*expr) -> op = expr_variable_exists;
4324  (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
4325  if (!(*expr)->data.variable)
4326  log_fatal ("can't allocate variable name");
4327  strcpy ((*expr) -> data.variable, val);
4328  token = next_token (&val, (unsigned *)0, cfile);
4329  if (token != RPAREN)
4330  goto norparen;
4331  break;
4332 
4333  /* This parses 'gethostname()'. */
4334  case GETHOSTNAME:
4335  skip_token(&val, NULL, cfile);
4336  if (!expression_allocate(expr, MDL))
4337  log_fatal("can't allocate expression");
4338  (*expr)->op = expr_gethostname;
4339 
4340  token = next_token(NULL, NULL, cfile);
4341  if (token != LPAREN)
4342  goto nolparen;
4343 
4344  token = next_token(NULL, NULL, cfile);
4345  if (token != RPAREN)
4346  goto norparen;
4347  break;
4348 
4349  case GETHOSTBYNAME:
4350  skip_token(&val, NULL, cfile);
4351  token = next_token(NULL, NULL, cfile);
4352  if (token != LPAREN)
4353  goto nolparen;
4354 
4355  /* The argument is a quoted string. */
4356  token = next_token(&val, NULL, cfile);
4357  if (token != STRING) {
4358  parse_warn(cfile, "Expecting quoted literal: "
4359  "\"foo.example.com\"");
4360  skip_to_semi(cfile);
4361  *lose = 1;
4362  return 0;
4363  }
4364  if (!make_host_lookup(expr, val))
4365  log_fatal("Error creating gethostbyname() internal "
4366  "record. (%s:%d)", MDL);
4367 
4368  token = next_token(NULL, NULL, cfile);
4369  if (token != RPAREN)
4370  goto norparen;
4371  break;
4372 
4373  case V6RELAY:
4374  skip_token(&val, NULL, cfile);
4375  if (!expression_allocate (expr, MDL))
4376  log_fatal ("can't allocate expression");
4377  (*expr)->op = expr_v6relay;
4378 
4379  token = next_token (&val, NULL, cfile);
4380  if (token != LPAREN)
4381  goto nolparen;
4382 
4383  if (!parse_numeric_expression (&(*expr)->data.v6relay.relay,
4384  cfile, lose))
4385  goto nodata;
4386 
4387  token = next_token (&val, NULL, cfile);
4388  if (token != COMMA)
4389  goto nocomma;
4390 
4391  if (!parse_data_expression (&(*expr)->data.v6relay.roption,
4392  cfile, lose))
4393  goto nodata;
4394 
4395  token = next_token (&val, NULL, cfile);
4396 
4397  if (token != RPAREN)
4398  goto norparen;
4399  break;
4400 
4401  /* Not a valid start to an expression... */
4402  default:
4403  if (token != NAME && token != NUMBER_OR_NAME)
4404  return 0;
4405 
4406  skip_token(&val, (unsigned *)0, cfile);
4407 
4408  /* Save the name of the variable being referenced. */
4409  cptr = dmalloc (strlen (val) + 1, MDL);
4410  if (!cptr)
4411  log_fatal ("can't allocate variable name");
4412  strcpy (cptr, val);
4413 
4414  /* Simple variable reference, as far as we can tell. */
4415  token = peek_token (&val, (unsigned *)0, cfile);
4416  if (token != LPAREN) {
4417  if (!expression_allocate (expr, MDL))
4418  log_fatal ("can't allocate expression");
4419  (*expr) -> op = expr_variable_reference;
4420  (*expr) -> data.variable = cptr;
4421  break;
4422  }
4423 
4424  skip_token(&val, (unsigned *)0, cfile);
4425  if (!expression_allocate (expr, MDL))
4426  log_fatal ("can't allocate expression");
4427  (*expr) -> op = expr_funcall;
4428  (*expr) -> data.funcall.name = cptr;
4429 
4430  /* Now parse the argument list. */
4431  ep = &(*expr) -> data.funcall.arglist;
4432  do {
4433  if (!expression_allocate (ep, MDL))
4434  log_fatal ("can't allocate expression");
4435  (*ep) -> op = expr_arg;
4436  if (!parse_expression (&(*ep) -> data.arg.val,
4437  cfile, lose, context_any,
4438  (struct expression **)0,
4439  expr_none)) {
4440  if (!*lose) {
4441  parse_warn (cfile,
4442  "expecting expression.");
4443  *lose = 1;
4444  }
4445  skip_to_semi (cfile);
4446  expression_dereference (expr, MDL);
4447  return 0;
4448  }
4449  ep = &((*ep) -> data.arg.next);
4450  token = next_token (&val, (unsigned *)0, cfile);
4451  } while (token == COMMA);
4452  if (token != RPAREN) {
4453  parse_warn (cfile, "Right parenthesis expected.");
4454  skip_to_semi (cfile);
4455  *lose = 1;
4456  expression_dereference (expr, MDL);
4457  return 0;
4458  }
4459  break;
4460  }
4461  return 1;
4462 }
4463 
4464 /* Parse an expression. */
4465 
4466 int parse_expression (expr, cfile, lose, context, plhs, binop)
4467  struct expression **expr;
4468  struct parse *cfile;
4469  int *lose;
4470  enum expression_context context;
4471  struct expression **plhs;
4472  enum expr_op binop;
4473 {
4474  enum dhcp_token token;
4475  const char *val;
4476  struct expression *rhs = (struct expression *)0, *tmp;
4477  struct expression *lhs = (struct expression *)0;
4478  enum expr_op next_op;
4479  enum expression_context
4480  lhs_context = context_any,
4481  rhs_context = context_any;
4482 
4483  /* Consume the left hand side we were passed. */
4484  if (plhs) {
4485  expression_reference (&lhs, *plhs, MDL);
4486  expression_dereference (plhs, MDL);
4487  }
4488 
4489  new_rhs:
4490  if (!parse_non_binary (&rhs, cfile, lose, context)) {
4491  /* If we already have a left-hand side, then it's not
4492  okay for there not to be a right-hand side here, so
4493  we need to flag it as an error. */
4494  if (lhs) {
4495  if (!*lose) {
4496  parse_warn (cfile,
4497  "expecting right-hand side.");
4498  *lose = 1;
4499  skip_to_semi (cfile);
4500  }
4501  expression_dereference (&lhs, MDL);
4502  }
4503  return 0;
4504  }
4505 
4506  /* At this point, rhs contains either an entire subexpression,
4507  or at least a left-hand-side. If we do not see a binary token
4508  as the next token, we're done with the expression. */
4509 
4510  token = peek_token (&val, (unsigned *)0, cfile);
4511  switch (token) {
4512  case BANG:
4513  skip_token(&val, (unsigned *)0, cfile);
4514  token = peek_token (&val, (unsigned *)0, cfile);
4515  if (token != EQUAL) {
4516  parse_warn (cfile, "! in boolean context without =");
4517  *lose = 1;
4518  skip_to_semi (cfile);
4519  if (lhs)
4520  expression_dereference (&lhs, MDL);
4521  return 0;
4522  }
4523  next_op = expr_not_equal;
4524  context = expression_context (rhs);
4525  break;
4526 
4527  case EQUAL:
4528  next_op = expr_equal;
4529  context = expression_context (rhs);
4530  break;
4531 
4532  case TILDE:
4533 #ifdef HAVE_REGEX_H
4534  skip_token(&val, NULL, cfile);
4535  token = peek_token(&val, NULL, cfile);
4536 
4537  if (token == TILDE)
4538  next_op = expr_iregex_match;
4539  else if (token == EQUAL)
4540  next_op = expr_regex_match;
4541  else {
4542  parse_warn(cfile, "expecting ~= or ~~ operator");
4543  *lose = 1;
4544  skip_to_semi(cfile);
4545  if (lhs)
4546  expression_dereference(&lhs, MDL);
4547  return 0;
4548  }
4549 
4550  context = expression_context(rhs);
4551 #else
4552  parse_warn(cfile, "No support for regex operator.");
4553  *lose = 1;
4554  skip_to_semi(cfile);
4555  if (lhs != NULL)
4556  expression_dereference(&lhs, MDL);
4557  return 0;
4558 #endif
4559  break;
4560 
4561  case AND:
4562  next_op = expr_and;
4563  context = expression_context (rhs);
4564  break;
4565 
4566  case OR:
4567  next_op = expr_or;
4568  context = expression_context (rhs);
4569  break;
4570 
4571  case PLUS:
4572  next_op = expr_add;
4573  context = expression_context (rhs);
4574  break;
4575 
4576  case MINUS:
4577  next_op = expr_subtract;
4578  context = expression_context (rhs);
4579  break;
4580 
4581  case SLASH:
4582  next_op = expr_divide;
4583  context = expression_context (rhs);
4584  break;
4585 
4586  case ASTERISK:
4587  next_op = expr_multiply;
4588  context = expression_context (rhs);
4589  break;
4590 
4591  case PERCENT:
4592  next_op = expr_remainder;
4593  context = expression_context (rhs);
4594  break;
4595 
4596  case AMPERSAND:
4597  next_op = expr_binary_and;
4598  context = expression_context (rhs);
4599  break;
4600 
4601  case PIPE:
4602  next_op = expr_binary_or;
4603  context = expression_context (rhs);
4604  break;
4605 
4606  case CARET:
4607  next_op = expr_binary_xor;
4608  context = expression_context (rhs);
4609  break;
4610 
4611  default:
4612  next_op = expr_none;
4613  }
4614 
4615  /* If we have no lhs yet, we just parsed it. */
4616  if (!lhs) {
4617  /* If there was no operator following what we just parsed,
4618  then we're done - return it. */
4619  if (next_op == expr_none) {
4620  *expr = rhs;
4621  return 1;
4622  }
4623  lhs = rhs;
4624  rhs = (struct expression *)0;
4625  binop = next_op;
4626  skip_token(&val, (unsigned *)0, cfile);
4627  goto new_rhs;
4628  }
4629 
4630  /* If the next binary operator is of greater precedence than the
4631  * current operator, then rhs we have parsed so far is actually
4632  * the lhs of the next operator. To get this value, we have to
4633  * recurse.
4634  */
4635  if (binop != expr_none && next_op != expr_none &&
4636  op_precedence (binop, next_op) < 0) {
4637 
4638  /* Eat the subexpression operator token, which we pass to
4639  * parse_expression...we only peek()'d earlier.
4640  */
4641  skip_token(&val, (unsigned *)0, cfile);
4642 
4643  /* Continue parsing of the right hand side with that token. */
4644  tmp = rhs;
4645  rhs = (struct expression *)0;
4646  if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
4647  &tmp, next_op)) {
4648  if (!*lose) {
4649  parse_warn (cfile,
4650  "expecting a subexpression");
4651  *lose = 1;
4652  }
4653  return 0;
4654  }
4655  next_op = expr_none;
4656  }
4657 
4658  if (binop != expr_none) {
4659  rhs_context = expression_context(rhs);
4660  lhs_context = expression_context(lhs);
4661 
4662  if ((rhs_context != context_any) && (lhs_context != context_any) &&
4663  (rhs_context != lhs_context)) {
4664  parse_warn (cfile, "illegal expression relating different types");
4665  skip_to_semi (cfile);
4666  expression_dereference (&rhs, MDL);
4667  expression_dereference (&lhs, MDL);
4668  *lose = 1;
4669  return 0;
4670  }
4671 
4672  switch(binop) {
4673  case expr_not_equal:
4674  case expr_equal:
4675  if ((rhs_context != context_data_or_numeric) &&
4676  (rhs_context != context_data) &&
4677  (rhs_context != context_numeric) &&
4678  (rhs_context != context_any)) {
4679  parse_warn (cfile, "expecting data/numeric expression");
4680  skip_to_semi (cfile);
4681  expression_dereference (&rhs, MDL);
4682  *lose = 1;
4683  return 0;
4684  }
4685  break;
4686 
4687  case expr_regex_match:
4688 #ifdef HAVE_REGEX_H
4689  if (expression_context(rhs) != context_data) {
4690  parse_warn(cfile, "expecting data expression");
4691  skip_to_semi(cfile);
4692  expression_dereference(&rhs, MDL);
4693  *lose = 1;
4694  return 0;
4695  }
4696 #else
4697  /* It should not be possible to attempt to parse the right
4698  * hand side of an operator there is no support for.
4699  */
4700  log_fatal("Impossible condition at %s:%d.", MDL);
4701 #endif
4702  break;
4703 
4704  case expr_and:
4705  case expr_or:
4706  if ((rhs_context != context_boolean) &&
4707  (rhs_context != context_any)) {
4708  parse_warn (cfile, "expecting boolean expressions");
4709  skip_to_semi (cfile);
4710  expression_dereference (&rhs, MDL);
4711  *lose = 1;
4712  return 0;
4713  }
4714  break;
4715 
4716  case expr_add:
4717  case expr_subtract:
4718  case expr_divide:
4719  case expr_multiply:
4720  case expr_remainder:
4721  case expr_binary_and:
4722  case expr_binary_or:
4723  case expr_binary_xor:
4724  if ((rhs_context != context_numeric) &&
4725  (rhs_context != context_any)) {
4726  parse_warn (cfile, "expecting numeric expressions");
4727  skip_to_semi (cfile);
4728  expression_dereference (&rhs, MDL);
4729  *lose = 1;
4730  return 0;
4731  }
4732  break;
4733 
4734  default:
4735  break;
4736  }
4737  }
4738 
4739  /* Now, if we didn't find a binary operator, we're done parsing
4740  this subexpression, so combine it with the preceding binary
4741  operator and return the result. */
4742  if (next_op == expr_none) {
4743  if (!expression_allocate (expr, MDL))
4744  log_fatal ("Can't allocate expression!");
4745 
4746  (*expr) -> op = binop;
4747  /* All the binary operators' data union members
4748  are the same, so we'll cheat and use the member
4749  for the equals operator. */
4750  (*expr) -> data.equal [0] = lhs;
4751  (*expr) -> data.equal [1] = rhs;
4752  return 1;
4753  }
4754 
4755  /* Eat the operator token - we now know it was a binary operator... */
4756  skip_token(&val, (unsigned *)0, cfile);
4757 
4758  /* Now combine the LHS and the RHS using binop. */
4759  tmp = (struct expression *)0;
4760  if (!expression_allocate (&tmp, MDL))
4761  log_fatal ("No memory for equal precedence combination.");
4762 
4763  /* Store the LHS and RHS. */
4764  tmp -> data.equal [0] = lhs;
4765  tmp -> data.equal [1] = rhs;
4766  tmp -> op = binop;
4767 
4768  lhs = tmp;
4769  tmp = (struct expression *)0;
4770  rhs = (struct expression *)0;
4771 
4772  /* Recursions don't return until we have parsed the end of the
4773  expression, so if we recursed earlier, we can now return what
4774  we got. */
4775  if (next_op == expr_none) {
4776  *expr = lhs;
4777  return 1;
4778  }
4779 
4780  binop = next_op;
4781  goto new_rhs;
4782 }
4783 
4784 
4785 int parse_option_data (expr, cfile, lookups, option)
4786 struct expression **expr;
4787 struct parse *cfile;
4788 int lookups;
4789 struct option *option;
4790 {
4791  const char *val;
4792  const char *fmt = NULL;
4793  struct expression *tmp;
4794  enum dhcp_token token;
4795 
4796  do {
4797  /*
4798  * Set a flag if this is an array of a simple type (i.e.,
4799  * not an array of pairs of IP addresses, or something like
4800  * that.
4801  */
4802  int uniform = 0;
4803 
4804  and_again:
4805  /* Set fmt to start of format for 'A' and one char back
4806  * for 'a'.
4807  */
4808  if ((fmt != NULL) && (fmt != option->format) && (*fmt == 'a'))
4809  fmt -= 1;
4810  else if ((fmt == NULL) || (*fmt == 'A'))
4811  fmt = option->format;
4812 
4813  /* 'a' means always uniform */
4814  if ((fmt[0] != 'Z') && (tolower((unsigned char)fmt[1]) == 'a'))
4815  uniform = 1;
4816 
4817  do {
4818  if ((*fmt == 'A') || (*fmt == 'a'))
4819  break;
4820  if (*fmt == 'o') {
4821  /* consume the optional flag */
4822  fmt++;
4823  continue;
4824  }
4825 
4826  if (fmt[1] == 'o') {
4827  /*
4828  * A value for the current format is
4829  * optional - check to see if the next
4830  * token is a semi-colon if so we don't
4831  * need to parse it and doing so would
4832  * consume the semi-colon which our
4833  * caller is expecting to parse
4834  */
4835  token = peek_token(&val, (unsigned *)0,
4836  cfile);
4837  if (token == SEMI) {
4838  fmt++;
4839  continue;
4840  }
4841  }
4842 
4843  tmp = *expr;
4844  *expr = NULL;
4845 
4846  if (!parse_option_token(expr, cfile, &fmt, tmp,
4847  uniform, lookups)) {
4848  if (fmt [1] != 'o') {
4849  if (tmp)
4850  expression_dereference (&tmp,
4851  MDL);
4852  return 0;
4853  }
4854  *expr = tmp;
4855  tmp = NULL;
4856  }
4857  if (tmp)
4858  expression_dereference (&tmp, MDL);
4859 
4860  fmt++;
4861  } while (*fmt != '\0');
4862 
4863  if ((*fmt == 'A') || (*fmt == 'a')) {
4864  token = peek_token (&val, (unsigned *)0, cfile);
4865  /* Comma means: continue with next element in array */
4866  if (token == COMMA) {
4867  skip_token(&val, (unsigned *)0, cfile);
4868  continue;
4869  }
4870  /* no comma: end of array.
4871  'A' or end of string means: leave the loop */
4872  if ((*fmt == 'A') || (fmt[1] == '\0'))
4873  break;
4874  /* 'a' means: go on with next char */
4875  if (*fmt == 'a') {
4876  fmt++;
4877  goto and_again;
4878  }
4879  }
4880  } while ((*fmt == 'A') || (*fmt == 'a'));
4881 
4882  return 1;
4883 }
4884 
4885 /* option-statement :== identifier DOT identifier <syntax> SEMI
4886  | identifier <syntax> SEMI
4887 
4888  Option syntax is handled specially through format strings, so it
4889  would be painful to come up with BNF for it. However, it always
4890  starts as above and ends in a SEMI. */
4891 
4892 int parse_option_statement (result, cfile, lookups, option, op)
4893  struct executable_statement **result;
4894  struct parse *cfile;
4895  int lookups;
4896  struct option *option;
4897  enum statement_op op;
4898 {
4899  const char *val;
4900  enum dhcp_token token;
4901  struct expression *expr = (struct expression *)0;
4902  int lose;
4903 
4904  token = peek_token (&val, (unsigned *)0, cfile);
4905  if ((token == SEMI) && (option->format[0] != 'Z')) {
4906  /* Eat the semicolon... */
4907  /*
4908  * XXXSK: I'm not sure why we should ever get here, but we
4909  * do during our startup. This confuses things if
4910  * we are parsing a zero-length option, so don't
4911  * eat the semicolon token in that case.
4912  */
4913  skip_token(&val, (unsigned *)0, cfile);
4914  } else if (token == EQUAL) {
4915  /* Eat the equals sign. */
4916  skip_token(&val, (unsigned *)0, cfile);
4917 
4918  /* Parse a data expression and use its value for the data. */
4919  if (!parse_data_expression (&expr, cfile, &lose)) {
4920  /* In this context, we must have an executable
4921  statement, so if we found something else, it's
4922  still an error. */
4923  if (!lose) {
4924  parse_warn (cfile,
4925  "expecting a data expression.");
4926  skip_to_semi (cfile);
4927  }
4928  return 0;
4929  }
4930  } else {
4931  if (! parse_option_data(&expr, cfile, lookups, option))
4932  return 0;
4933  }
4934 
4935  if (!parse_semi (cfile))
4936  return 0;
4937  if (!executable_statement_allocate (result, MDL))
4938  log_fatal ("no memory for option statement.");
4939 
4940  (*result)->op = op;
4941  if (expr && !option_cache (&(*result)->data.option,
4942  NULL, expr, option, MDL))
4943  log_fatal ("no memory for option cache");
4944 
4945  if (expr)
4946  expression_dereference (&expr, MDL);
4947 
4948  return 1;
4949 }
4950 
4951 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
4952  struct expression **rv;
4953  struct parse *cfile;
4954  const char **fmt;
4955  struct expression *expr;
4956  int uniform;
4957  int lookups;
4958 {
4959  const char *val;
4960  enum dhcp_token token;
4961  struct expression *t = (struct expression *)0;
4962  unsigned char buf [4];
4963  unsigned len;
4964  struct iaddr addr;
4965  int compress;
4966  isc_boolean_t freeval = ISC_FALSE;
4967  const char *f, *g;
4968  struct enumeration_value *e;
4969 
4970  switch (**fmt) {
4971  case 'U':
4972  token = next_token (&val, &len, cfile);
4973  if (!is_identifier (token)) {
4974  if ((*fmt) [1] != 'o') {
4975  parse_warn (cfile, "expecting identifier.");
4976  if (token != SEMI)
4977  skip_to_semi (cfile);
4978  }
4979  return 0;
4980  }
4981  if (!make_const_data (&t, (const unsigned char *)val,
4982  len, 1, 1, MDL))
4983  log_fatal ("No memory for %s", val);
4984  break;
4985 
4986  case 'E':
4987  g = strchr (*fmt, '.');
4988  if (!g) {
4989  parse_warn (cfile,
4990  "malformed encapsulation format (bug!)");
4991  skip_to_semi (cfile);
4992  return 0;
4993  }
4994  *fmt = g;
4995  /* FALL THROUGH */
4996  /* to get string value for the option */
4997  case 'X':
4998  token = peek_token (&val, (unsigned *)0, cfile);
4999  if (token == NUMBER_OR_NAME || token == NUMBER) {
5000  if (!expression_allocate (&t, MDL))
5001  return 0;
5002  if (!parse_cshl (&t -> data.const_data, cfile)) {
5004  return 0;
5005  }
5006  t -> op = expr_const_data;
5007  } else {
5008  token = next_token (&val, &len, cfile);
5009 
5010  if(token == STRING) {
5011  if (!make_const_data (&t,
5012  (const unsigned char *)val,
5013  len, 1, 1, MDL))
5014  log_fatal ("No memory for \"%s\"", val);
5015  } else {
5016  if ((*fmt) [1] != 'o') {
5017  parse_warn (cfile, "expecting string "
5018  "or hexadecimal data.");
5019  skip_to_semi (cfile);
5020  }
5021  return 0;
5022  }
5023  }
5024  break;
5025 
5026  case 'D': /* Domain list... */
5027  if ((*fmt)[1] == 'c') {
5028  compress = 1;
5029  /* Skip the compress-flag atom. */
5030  (*fmt)++;
5031  } else
5032  compress = 0;
5033 
5034  t = parse_domain_list(cfile, compress);
5035 
5036  if (!t) {
5037  if ((*fmt)[1] != 'o')
5038  skip_to_semi(cfile);
5039  return 0;
5040  }
5041 
5042  break;
5043 
5044  case 'd': /* Domain name... */
5045  val = parse_host_name (cfile);
5046  if (!val) {
5047  parse_warn (cfile, "not a valid domain name.");
5048  skip_to_semi (cfile);
5049  return 0;
5050  }
5051  len = strlen (val);
5052  freeval = ISC_TRUE;
5053  goto make_string;
5054 
5055  case 't': /* Text string... */
5056  token = next_token (&val, &len, cfile);
5057  if (token != STRING && !is_identifier (token)) {
5058  if ((*fmt) [1] != 'o') {
5059  parse_warn (cfile, "expecting string.");
5060  if (token != SEMI)
5061  skip_to_semi (cfile);
5062  }
5063  return 0;
5064  }
5065  make_string:
5066  if (!make_const_data (&t, (const unsigned char *)val,
5067  len, 1, 1, MDL))
5068  log_fatal ("No memory for concatenation");
5069  if (freeval == ISC_TRUE) {
5070  dfree((char *)val, MDL);
5071  freeval = ISC_FALSE;
5072  POST(freeval);
5073  }
5074  break;
5075 
5076  case 'N':
5077  f = (*fmt) + 1;
5078  g = strchr (*fmt, '.');
5079  if (!g) {
5080  parse_warn (cfile, "malformed %s (bug!)",
5081  "enumeration format");
5082  foo:
5083  skip_to_semi (cfile);
5084  return 0;
5085  }
5086  *fmt = g;
5087  token = next_token (&val, (unsigned *)0, cfile);
5088  if (!is_identifier (token)) {
5089  parse_warn (cfile,
5090  "identifier expected");
5091  goto foo;
5092  }
5093  e = find_enumeration_value (f, (*fmt) - f, &len, val);
5094  if (!e) {
5095  parse_warn (cfile, "unknown value");
5096  goto foo;
5097  }
5098  if (!make_const_data (&t, &e -> value, len, 0, 1, MDL))
5099  return 0;
5100  break;
5101 
5102  case 'I': /* IP address or hostname. */
5103  if (lookups) {
5104  if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
5105  return 0;
5106  } else {
5107  if (!parse_ip_addr (cfile, &addr))
5108  return 0;
5109  if (!make_const_data (&t, addr.iabuf, addr.len,
5110  0, 1, MDL))
5111  return 0;
5112  }
5113  break;
5114 
5115  case 'R': /* destination descriptor */
5116  if (!parse_destination_descriptor (cfile, &addr)) {
5117  return 0;
5118  }
5119  if (!make_const_data (&t, addr.iabuf, addr.len, 0, 1, MDL)) {
5120  return 0;
5121  }
5122  break;
5123 
5124  case '6': /* IPv6 address. */
5125  if (!parse_ip6_addr(cfile, &addr)) {
5126  return 0;
5127  }
5128  if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) {
5129  return 0;
5130  }
5131  break;
5132 
5133  case 'T': /* Lease interval. */
5134  token = next_token (&val, (unsigned *)0, cfile);
5135  if (token != INFINITE)
5136  goto check_number;
5137  putLong (buf, -1);
5138  if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5139  return 0;
5140  break;
5141 
5142  case 'L': /* Unsigned 32-bit integer... */
5143  case 'l': /* Signed 32-bit integer... */
5144  token = next_token (&val, (unsigned *)0, cfile);
5145  check_number:
5146  if ((token != NUMBER) && (token != NUMBER_OR_NAME)) {
5147  need_number:
5148  if ((*fmt) [1] != 'o') {
5149  parse_warn (cfile, "expecting number.");
5150  if (token != SEMI)
5151  skip_to_semi (cfile);
5152  }
5153  return 0;
5154  }
5155  convert_num (cfile, buf, val, 0, 32);
5156  if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5157  return 0;
5158  break;
5159 
5160  case 's': /* Signed 16-bit integer. */
5161  case 'S': /* Unsigned 16-bit integer. */
5162  token = next_token (&val, (unsigned *)0, cfile);
5163  if ((token != NUMBER) && (token != NUMBER_OR_NAME))
5164  goto need_number;
5165  convert_num (cfile, buf, val, 0, 16);
5166  if (!make_const_data (&t, buf, 2, 0, 1, MDL))
5167  return 0;
5168  break;
5169 
5170  case 'b': /* Signed 8-bit integer. */
5171  case 'B': /* Unsigned 8-bit integer. */
5172  token = next_token (&val, (unsigned *)0, cfile);
5173  if ((token != NUMBER) && (token != NUMBER_OR_NAME))
5174  goto need_number;
5175  convert_num (cfile, buf, val, 0, 8);
5176  if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5177  return 0;
5178  break;
5179 
5180  case 'f': /* Boolean flag. */
5181  token = next_token (&val, (unsigned *)0, cfile);
5182  if (!is_identifier (token)) {
5183  if ((*fmt) [1] != 'o')
5184  parse_warn (cfile, "expecting identifier.");
5185  bad_flag:
5186  if ((*fmt) [1] != 'o') {
5187  if (token != SEMI)
5188  skip_to_semi (cfile);
5189  }
5190  return 0;
5191  }
5192  if (!strcasecmp (val, "true")
5193  || !strcasecmp (val, "on"))
5194  buf [0] = 1;
5195  else if (!strcasecmp (val, "false")
5196  || !strcasecmp (val, "off"))
5197  buf [0] = 0;
5198  else if (!strcasecmp (val, "ignore"))
5199  buf [0] = 2;
5200  else {
5201  if ((*fmt) [1] != 'o')
5202  parse_warn (cfile, "expecting boolean.");
5203  goto bad_flag;
5204  }
5205  if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5206  return 0;
5207  break;
5208 
5209  case 'Z': /* Zero-length option. */
5210  token = peek_token (&val, (unsigned *)0, cfile);
5211  if (token != SEMI) {
5212  parse_warn(cfile, "semicolon expected.");
5213  skip_to_semi(cfile);
5214  }
5215  buf[0] = '\0';
5216  if (!make_const_data(&t, /* expression */
5217  buf, /* buffer */
5218  0, /* length */
5219  0, /* terminated */
5220  1, /* allocate */
5221  MDL))
5222  return 0;
5223  break;
5224 
5225  default:
5226  parse_warn (cfile, "Bad format '%c' in parse_option_token.",
5227  **fmt);
5228  skip_to_semi (cfile);
5229  return 0;
5230  }
5231  if (expr) {
5232  if (!make_concat (rv, expr, t))
5233  return 0;
5234  } else
5235  expression_reference (rv, t, MDL);
5237  return 1;
5238 }
5239 
5240 int parse_option_decl (oc, cfile)
5241  struct option_cache **oc;
5242  struct parse *cfile;
5243 {
5244  const char *val;
5245  int token;
5246  u_int8_t buf [4];
5247  u_int8_t hunkbuf [1024];
5248  unsigned hunkix = 0;
5249  const char *fmt, *f;
5250  struct option *option=NULL;
5251  struct iaddr ip_addr;
5252  u_int8_t *dp;
5253  const u_int8_t *cdp;
5254  unsigned len;
5255  int nul_term = 0;
5256  struct buffer *bp;
5257  int known = 0;
5258  int compress;
5259  struct expression *express = NULL;
5260  struct enumeration_value *e;
5261  isc_result_t status;
5262 
5263  status = parse_option_name (cfile, 0, &known, &option);
5264  if (status != ISC_R_SUCCESS || option == NULL)
5265  return 0;
5266 
5267  fmt = option->format;
5268 
5269  /* Parse the option data... */
5270  do {
5271  for (; *fmt; fmt++) {
5272  if (*fmt == 'A') {
5273  /* 'A' is an array of records, start at
5274  * the beginning
5275  */
5276  fmt = option->format;
5277  break;
5278  }
5279 
5280  if (*fmt == 'a') {
5281  /* 'a' is an array of the last field,
5282  * back up one format character
5283  */
5284  fmt--;
5285  break;
5286  }
5287  if (*fmt == 'o' && fmt != option -> format)
5288  continue;
5289  switch (*fmt) {
5290  case 'E':
5291  fmt = strchr (fmt, '.');
5292  if (!fmt) {
5293  parse_warn (cfile,
5294  "malformed %s (bug!)",
5295  "encapsulation format");
5296  goto parse_exit;
5297  }
5298  /* FALL THROUGH */
5299  /* to get string value for the option */
5300  case 'X':
5301  len = parse_X (cfile, &hunkbuf [hunkix],
5302  sizeof hunkbuf - hunkix);
5303  hunkix += len;
5304  break;
5305 
5306  case 't': /* Text string... */
5307  token = peek_token (&val,
5308  &len, cfile);
5309  if (token == SEMI && fmt[1] == 'o') {
5310  fmt++;
5311  break;
5312  }
5313  token = next_token (&val,
5314  &len, cfile);
5315  if (token != STRING) {
5316  parse_warn (cfile,
5317  "expecting string.");
5318  goto parse_exit;
5319  }
5320  if (hunkix + len + 1 > sizeof hunkbuf) {
5321  parse_warn (cfile,
5322  "option data buffer %s",
5323  "overflow");
5324  goto parse_exit;
5325  }
5326  memcpy (&hunkbuf [hunkix], val, len + 1);
5327  nul_term = 1;
5328  hunkix += len;
5329  break;
5330 
5331  case 'D':
5332  if (fmt[1] == 'c') {
5333  compress = 1;
5334  fmt++;
5335  } else
5336  compress = 0;
5337 
5338  express = parse_domain_list(cfile, compress);
5339 
5340  if (express == NULL)
5341  goto exit;
5342 
5343  if (express->op != expr_const_data) {
5344  parse_warn(cfile, "unexpected "
5345  "expression");
5346  goto parse_exit;
5347  }
5348 
5349  len = express->data.const_data.len;
5350  cdp = express->data.const_data.data;
5351 
5352  if ((hunkix + len) > sizeof(hunkbuf)) {
5353  parse_warn(cfile, "option data buffer "
5354  "overflow");
5355  goto parse_exit;
5356  }
5357  memcpy(&hunkbuf[hunkix], cdp, len);
5358  hunkix += len;
5359 
5360  expression_dereference(&express, MDL);
5361  break;
5362 
5363  case 'N':
5364  f = fmt + 1;
5365  fmt = strchr (fmt, '.');
5366  if (!fmt) {
5367  parse_warn (cfile,
5368  "malformed %s (bug!)",
5369  "enumeration format");
5370  goto parse_exit;
5371  }
5372  token = next_token (&val,
5373  (unsigned *)0, cfile);
5374  if (!is_identifier (token)) {
5375  parse_warn (cfile,
5376  "identifier expected");
5377  goto parse_exit;
5378  }
5379  e = find_enumeration_value (f, fmt - f,
5380  &len, val);
5381  if (!e) {
5382  parse_warn (cfile,
5383  "unknown value");
5384  goto parse_exit;
5385  }
5386  dp = &e -> value;
5387  goto alloc;
5388 
5389  case '6':
5390  if (!parse_ip6_addr(cfile, &ip_addr))
5391  goto exit;
5392  len = ip_addr.len;
5393  dp = ip_addr.iabuf;
5394  goto alloc;
5395 
5396  case 'I': /* IP address. */
5397  if (!parse_ip_addr (cfile, &ip_addr))
5398  goto exit;
5399  len = ip_addr.len;
5400  dp = ip_addr.iabuf;
5401  goto alloc;
5402 
5403  case 'R': /* destination descriptor */
5404  if (!parse_destination_descriptor (cfile, &ip_addr))
5405  goto exit;
5406  len = ip_addr.len;
5407  dp = ip_addr.iabuf;
5408 
5409  alloc:
5410  if (hunkix + len > sizeof hunkbuf) {
5411  parse_warn (cfile,
5412  "option data buffer %s",
5413  "overflow");
5414  goto parse_exit;
5415  }
5416  memcpy (&hunkbuf [hunkix], dp, len);
5417  hunkix += len;
5418  break;
5419 
5420  case 'L': /* Unsigned 32-bit integer... */
5421  case 'l': /* Signed 32-bit integer... */
5422  token = next_token (&val,
5423  (unsigned *)0, cfile);
5424  if ((token != NUMBER) &&
5425  (token != NUMBER_OR_NAME)) {
5426  need_number:
5427  parse_warn (cfile,
5428  "expecting number.");
5429  if (token != SEMI)
5430  goto parse_exit;
5431  else
5432  goto exit;
5433  }
5434  convert_num (cfile, buf, val, 0, 32);
5435  len = 4;
5436  dp = buf;
5437  goto alloc;
5438 
5439  case 's': /* Signed 16-bit integer. */
5440  case 'S': /* Unsigned 16-bit integer. */
5441  token = next_token (&val,
5442  (unsigned *)0, cfile);
5443  if ((token != NUMBER) &&
5444  (token != NUMBER_OR_NAME))
5445  goto need_number;
5446  convert_num (cfile, buf, val, 0, 16);
5447  len = 2;
5448  dp = buf;
5449  goto alloc;
5450 
5451  case 'b': /* Signed 8-bit integer. */
5452  case 'B': /* Unsigned 8-bit integer. */
5453  token = next_token (&val,
5454  (unsigned *)0, cfile);
5455  if ((token != NUMBER) &&
5456  (token != NUMBER_OR_NAME))
5457  goto need_number;
5458  convert_num (cfile, buf, val, 0, 8);
5459  len = 1;
5460  dp = buf;
5461  goto alloc;
5462 
5463  case 'f': /* Boolean flag. */
5464  token = next_token (&val,
5465  (unsigned *)0, cfile);
5466  if (!is_identifier (token)) {
5467  parse_warn (cfile,
5468  "expecting identifier.");
5469  bad_flag:
5470  if (token != SEMI)
5471  goto parse_exit;
5472  else
5473  goto exit;
5474  }
5475  if (!strcasecmp (val, "true")
5476  || !strcasecmp (val, "on"))
5477  buf [0] = 1;
5478  else if (!strcasecmp (val, "false")
5479  || !strcasecmp (val, "off"))
5480  buf [0] = 0;
5481  else {
5482  parse_warn (cfile,
5483  "expecting boolean.");
5484  goto bad_flag;
5485  }
5486  len = 1;
5487  dp = buf;
5488  goto alloc;
5489 
5490  case 'Z': /* Zero-length option */
5491  token = peek_token(&val, (unsigned *)0, cfile);
5492  if (token != SEMI) {
5493  parse_warn(cfile,
5494  "semicolon expected.");
5495  goto parse_exit;
5496  }
5497  len = 0;
5498  buf[0] = '\0';
5499  break;
5500 
5501  default:
5502  log_error ("parse_option_param: Bad format %c",
5503  *fmt);
5504  goto parse_exit;
5505  }
5506  }
5507  token = next_token (&val, (unsigned *)0, cfile);
5508  } while (*fmt && token == COMMA);
5509 
5510  if (token != SEMI) {
5511  parse_warn (cfile, "semicolon expected.");
5512  goto parse_exit;
5513  }
5514 
5515  bp = (struct buffer *)0;
5516  if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
5517  log_fatal ("no memory to store option declaration.");
5518  memcpy (bp -> data, hunkbuf, hunkix + nul_term);
5519 
5520  if (!option_cache_allocate (oc, MDL))
5521  log_fatal ("out of memory allocating option cache.");
5522 
5523  (*oc) -> data.buffer = bp;
5524  (*oc) -> data.data = &bp -> data [0];
5525  (*oc) -> data.terminated = nul_term;
5526  (*oc) -> data.len = hunkix;
5527  option_reference(&(*oc)->option, option, MDL);
5528  option_dereference(&option, MDL);
5529  return 1;
5530 
5531 parse_exit:
5532  if (express != NULL)
5533  expression_dereference(&express, MDL);
5534  skip_to_semi (cfile);
5535 exit:
5536  option_dereference(&option, MDL);
5537 
5538  return 0;
5539 }
5540 
5541 /* Consider merging parse_cshl into this. */
5542 
5543 int parse_X (cfile, buf, max)
5544  struct parse *cfile;
5545  u_int8_t *buf;
5546  unsigned max;
5547 {
5548  int token;
5549  const char *val;
5550  unsigned len;
5551 
5552  token = peek_token (&val, (unsigned *)0, cfile);
5553  if (token == NUMBER_OR_NAME || token == NUMBER) {
5554  len = 0;
5555  do {
5556  token = next_token (&val, (unsigned *)0, cfile);
5557  if (token != NUMBER && token != NUMBER_OR_NAME) {
5558  parse_warn (cfile,
5559  "expecting hexadecimal constant.");
5560  skip_to_semi (cfile);
5561  return 0;
5562  }
5563  convert_num (cfile, &buf [len], val, 16, 8);
5564  if (len++ > max) {
5565  parse_warn (cfile,
5566  "hexadecimal constant too long.");
5567  skip_to_semi (cfile);
5568  return 0;
5569  }
5570  token = peek_token (&val, (unsigned *)0, cfile);
5571  if (token == COLON)
5572  token = next_token (&val,
5573  (unsigned *)0, cfile);
5574  } while (token == COLON);
5575  val = (char *)buf;
5576  } else if (token == STRING) {
5577  skip_token(&val, &len, cfile);
5578  if (len + 1 > max) {
5579  parse_warn (cfile, "string constant too long.");
5580  skip_to_semi (cfile);
5581  return 0;
5582  }
5583  memcpy (buf, val, len + 1);
5584  } else {
5585  parse_warn (cfile, "expecting string or hexadecimal data");
5586  skip_to_semi (cfile);
5587  return 0;
5588  }
5589  return len;
5590 }
5591 
5592 int parse_warn (struct parse *cfile, const char *fmt, ...)
5593 {
5594  va_list list;
5595  char lexbuf [256];
5596  char mbuf [1024];
5597  char fbuf [1024];
5598  unsigned i, lix;
5599 
5600  do_percentm (mbuf, fmt);
5601  /* %Audit% This is log output. %2004.06.17,Safe%
5602  * If we truncate we hope the user can get a hint from the log.
5603  */
5604  snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
5605  cfile -> tlname, cfile -> lexline, mbuf);
5606 
5607  va_start (list, fmt);
5608  vsnprintf (mbuf, sizeof mbuf, fbuf, list);
5609  va_end (list);
5610 
5611  lix = 0;
5612  for (i = 0;
5613  cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
5614  if (lix < (sizeof lexbuf) - 1)
5615  lexbuf [lix++] = ' ';
5616  if (cfile -> token_line [i] == '\t') {
5617  for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
5618  lexbuf [lix] = ' ';
5619  }
5620  }
5621  lexbuf [lix] = 0;
5622 
5623 #ifndef DEBUG
5624  syslog (log_priority | LOG_ERR, "%s", mbuf);
5625  syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
5626  if (cfile -> lexchar < 81)
5627  syslog (log_priority | LOG_ERR, "%s^", lexbuf);
5628 #endif
5629 
5630  if (log_perror) {
5631  IGNORE_RET (write (STDERR_FILENO, mbuf, strlen (mbuf)));
5632  IGNORE_RET (write (STDERR_FILENO, "\n", 1));
5633  IGNORE_RET (write (STDERR_FILENO, cfile -> token_line,
5634  strlen (cfile -> token_line)));
5635  IGNORE_RET (write (STDERR_FILENO, "\n", 1));
5636  if (cfile -> lexchar < 81)
5637  IGNORE_RET (write (STDERR_FILENO, lexbuf, lix));
5638  IGNORE_RET (write (STDERR_FILENO, "^\n", 2));
5639  }
5640 
5641  cfile -> warnings_occurred = 1;
5642 
5643  return 0;
5644 }
5645 
5646 struct expression *
5647 parse_domain_list(struct parse *cfile, int compress)
5648 {
5649  const char *val;
5650  enum dhcp_token token = SEMI;
5651  struct expression *t = NULL;
5652  unsigned len, clen = 0;
5653  int result;
5654  unsigned char compbuf[256 * NS_MAXCDNAME];
5655  const unsigned char *dnptrs[256], **lastdnptr;
5656 
5657  memset(compbuf, 0, sizeof(compbuf));
5658  memset(dnptrs, 0, sizeof(dnptrs));
5659  dnptrs[0] = compbuf;
5660  lastdnptr = &dnptrs[255];
5661 
5662  do {
5663  /* Consume the COMMA token if peeked. */
5664  if (token == COMMA)
5665  skip_token(&val, NULL, cfile);
5666 
5667  /* Get next (or first) value. */
5668  token = next_token(&val, &len, cfile);
5669 
5670  if (token != STRING) {
5671  parse_warn(cfile, "Expecting a domain string.");
5672  return NULL;
5673  }
5674 
5675  /* If compression pointers are enabled, compress. If not,
5676  * just pack the names in series into the buffer.
5677  */
5678  if (compress) {
5679  result = MRns_name_compress(val, compbuf + clen,
5680  sizeof(compbuf) - clen,
5681  dnptrs, lastdnptr);
5682 
5683  if (result < 0) {
5684  parse_warn(cfile, "Error compressing domain "
5685  "list: %m");
5686  return NULL;
5687  }
5688 
5689  clen += result;
5690  } else {
5691  result = MRns_name_pton(val, compbuf + clen,
5692  sizeof(compbuf) - clen);
5693 
5694  /* result == 1 means the input was fully qualified.
5695  * result == 0 means the input wasn't.
5696  * result == -1 means bad things.
5697  */
5698  if (result < 0) {
5699  parse_warn(cfile, "Error assembling domain "
5700  "list: %m");
5701  return NULL;
5702  }
5703 
5704  /*
5705  * We need to figure out how many bytes to increment
5706  * our buffer pointer since pton doesn't tell us.
5707  */
5708  while (compbuf[clen] != 0)
5709  clen += compbuf[clen] + 1;
5710 
5711  /* Count the last label (0). */
5712  clen++;
5713  }
5714 
5715  if (clen > sizeof(compbuf))
5716  log_fatal("Impossible error at %s:%d", MDL);
5717 
5718  token = peek_token(&val, NULL, cfile);
5719  } while (token == COMMA);
5720 
5721  if (!make_const_data(&t, compbuf, clen, 1, 1, MDL))
5722  log_fatal("No memory for domain list object.");
5723 
5724  return t;
5725 }
5726 
struct option_cache * lookup_hashed_option(struct universe *universe, struct option_state *options, unsigned code)
Definition: options.c:2264
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
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:5543
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:959
Definition: tree.h:31
struct _pair * cdr
Definition: tree.h:33
#define NS_MAXCDNAME
Definition: nameser.h:75
Definition: dhctoken.h:250
#define DHCP_R_NXDOMAIN
Definition: result.h:60
isc_result_t parse_option_name(struct parse *cfile, int allocate, int *known, struct option **opt)
Definition: parse.c: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
void(* save_func)(struct universe *, struct option_state *, struct option_cache *, isc_boolean_t)
Definition: tree.h:306
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
u_int32_t(* get_length)(const unsigned char *)
Definition: tree.h:332
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
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:2995
int parse_key(struct parse *cfile)
Definition: parse.c:2961
int tag_size
Definition: tree.h:334
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
enum dhcp_token token
Definition: dhcpd.h:284
int expression_allocate(struct expression **cptr, const char *file, int line)
Definition: alloc.c:427
#define FORMERR
#define STDERR_FILENO
Definition: osdep.h:288
int parse_data_expression(struct expression **expr, struct parse *cfile, int *lose)
Definition: parse.c:3507
#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:1079
#define DHCP_R_INVALIDARG
Definition: result.h:48
#define is_identifier(x)
Definition: dhctoken.h:375
struct expression * arglist
Definition: tree.h:274
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
void(* delete_func)(struct universe *universe, struct option_state *, int)
Definition: tree.h:318
int parse_numeric_expression(struct expression **expr, struct parse *cfile, int *lose)
Definition: parse.c:3534
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:2269
int log_error(const char *,...) __attribute__((__format__(__printf__
void putLong(unsigned char *, int32_t)
Definition: convert.c:78
struct collection * collections
Definition: dhcpd.h:3005
enum expression_context op_context(enum expr_op op)
Definition: tree.c:3154
struct option_cache *(* lookup_func)(struct universe *, struct option_state *, unsigned)
Definition: tree.h:303
int parse_semi(struct parse *cfile)
Definition: parse.c:129
Definition: tree.h:177
struct option_cache * secondary6
Definition: dhcpd.h:1385
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
caddr_t car
Definition: tree.h:32
int(* decode)(struct option_state *, const unsigned char *, unsigned, struct universe *)
Definition: tree.h:323
int terminated
Definition: tree.h:81
#define LOCAL_TIME_FORMAT
Definition: dhcpd.h:2387
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:4951
int parse_string(struct parse *cfile, char **sptr, unsigned *lptr)
Definition: parse.c:146
Definition: tree.h:301
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
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:506
Definition: dhctoken.h:50
Definition: dhctoken.h:114
union expression::expr_union data
universe_hash_t * universe_hash
Definition: tables.c:916
#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:1381
#define DHCP_R_SERVFAIL
Definition: result.h:59
void delete_hashed_option(struct universe *universe, struct option_state *options, int code)
Definition: options.c:2664
void(* store_length)(unsigned char *, u_int32_t)
Definition: tree.h:333
#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:1386
int parse_if_statement(struct executable_statement **result, struct parse *cfile, int *lose)
Definition: parse.c:3304
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:1969
void save_hashed_option(struct universe *universe, struct option_state *options, struct option_cache *oc, isc_boolean_t appendp)
Definition: options.c:2585
int parse_boolean_expression(struct expression **expr, struct parse *cfile, int *lose)
Definition: parse.c:3440
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
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:2749
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
void putShort(unsigned char *, int32_t)
Definition: convert.c:94
#define DEFAULT_TIME_FORMAT
Definition: dhcpd.h:2386
int tlen
Definition: dhcpd.h:287
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:3557
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 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:5240
int int log_info(const char *,...) __attribute__((__format__(__printf__
void skip_to_semi(struct parse *cfile)
Definition: parse.c:88
Definition: dhctoken.h:40
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:3109
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:4892
Definition: tree.h:143
int log_priority
Definition: errwarn.c:46
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:4785
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:3189
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
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:4466
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
#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
int warnings_occurred
Definition: dhcpd.h:290
struct string_list * next
Definition: dhcpd.h:312
struct expression * parse_domain_list(struct parse *cfile, int compress)
Definition: parse.c:5647
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:145
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:1220
time_t TIME
Definition: dhcpd.h:85
int make_limit(struct expression **new, struct expression *expr, int limit)
Definition: tree.c:332
int parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen)
Definition: parse.c:468
struct option_cache * primary6
Definition: dhcpd.h:1384
#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:177
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:3463
int length_size
Definition: tree.h:334
#define DHCP_R_REFUSED
Definition: result.h:62
struct iaddr mask
Definition: inet.h:55
int expression_reference(struct expression **ptr, struct expression *src, const char *file, int line)
Definition: alloc.c:447
int(* encapsulate)(struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *)
Definition: tree.h:325
u_int32_t(* get_tag)(const unsigned char *)
Definition: tree.h:330
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:1488
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:3576
#define DHCP_R_YXRRSET
Definition: result.h:64
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
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:975
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:3257
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
void(* store_tag)(unsigned char *, u_int32_t)
Definition: tree.h:331
void parse_hardware_param(struct parse *cfile, struct hardware *hardware)
Definition: parse.c:604
#define QUAD_NAME_HASH_SIZE
Definition: dhcpd.h:133
int parse_warn(struct parse *cfile, const char *fmt,...)
Definition: parse.c:5592
char * token_line
Definition: dhcrelay.c:52
char * tval
Definition: dhcpd.h:286
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
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