ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
conflex.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 by Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Internet Systems Consortium, Inc.
17  * 950 Charter Street
18  * Redwood City, CA 94063
19  * <info@isc.org>
20  * https://www.isc.org/
21  *
22  */
23 
24 /* From common/conflex.c */
25 
26 #include "keama.h"
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/mman.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <fcntl.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 static int get_char(struct parse *);
39 static void unget_char(struct parse *, int);
40 static void skip_to_eol(struct parse *);
41 static enum dhcp_token read_whitespace(int c, struct parse *cfile);
42 static enum dhcp_token read_string(struct parse *);
43 static enum dhcp_token read_number(int, struct parse *);
44 static enum dhcp_token read_num_or_name(int, struct parse *);
45 static enum dhcp_token intern(char *, enum dhcp_token);
46 
47 struct parse *
48 new_parse(int file, char *inbuf, size_t buflen, const char *name, int eolp)
49 {
50  struct parse *tmp;
51 
52  tmp = (struct parse *)malloc(sizeof(struct parse));
53  assert(tmp != NULL);
54  memset(tmp, 0, sizeof(struct parse));
55 
56  TAILQ_INSERT_TAIL(&parses, tmp);
57 
58  tmp->tlname = name;
59  tmp->lpos = tmp->line = 1;
60  tmp->cur_line = tmp->line1;
61  tmp->prev_line = tmp->line2;
62  tmp->token_line = tmp->cur_line;
63  tmp->cur_line[0] = tmp->prev_line[0] = 0;
64  tmp->file = file;
65  tmp->eol_token = eolp;
66  TAILQ_INIT(&tmp->comments);
67 
68  if (inbuf != NULL) {
69  tmp->inbuf = inbuf;
70  tmp->buflen = buflen;
71  tmp->bufsiz = 0;
72  } else {
73  struct stat sb;
74 
75  if (fstat(file, &sb) < 0) {
76  fprintf(stderr, "can't stat input\n");
77  exit(1);
78  }
79 
80  if (sb.st_size == 0)
81  return tmp;
82 
83  tmp->bufsiz = tmp->buflen = (size_t) sb.st_size;
84  tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED,
85  file, 0);
86 
87  if (tmp->inbuf == MAP_FAILED) {
88  fprintf(stderr, "can't map input\n");
89  exit(1);
90  }
91  }
92 
93  return tmp;
94 }
95 
96 void
97 end_parse(struct parse *cfile)
98 {
99  /* "Memory" config files have no file. */
100  if (cfile->file != -1) {
101  munmap(cfile->inbuf, cfile->bufsiz);
102  close(cfile->file);
103  }
104 
105  while (TAILQ_NEXT(cfile) != NULL) {
106  struct parse *saved_state;
107 
108  saved_state = TAILQ_NEXT(cfile);
109  TAILQ_REMOVE(&parses, saved_state);
110  free(saved_state);
111  }
112 
113  cfile->stack_size = 0;
114  if (cfile->stack != NULL)
115  free(cfile->stack);
116  cfile->stack = NULL;
117  TAILQ_REMOVE(&parses, cfile);
118  free(cfile);
119 }
120 
121 /*
122  * Save the current state of the parser.
123  *
124  * Only one state may be saved. Any previous saved state is
125  * lost.
126  */
127 void
128 save_parse_state(struct parse *cfile) {
129  struct parse *tmp;
130 
131  /*
132  * Free any previous saved states.
133  */
134  while (TAILQ_NEXT(cfile) != NULL) {
135  struct parse *saved_state;
136 
137  saved_state = TAILQ_NEXT(cfile);
138  TAILQ_REMOVE(&parses, saved_state);
139  free(saved_state);
140  }
141 
142  /*
143  * Save our current state.
144  */
145  tmp = (struct parse *)malloc(sizeof(struct parse));
146  if (tmp == NULL)
147  parse_error(cfile, "can't allocate state to be saved");
148  memset(tmp, 0, sizeof(struct parse));
149  /* save up to comments field */
150  memcpy(tmp, cfile, (size_t)&(((struct parse *)0)->comments));
151  TAILQ_INSERT_AFTER(&parses, cfile, tmp);
152 }
153 
154 /*
155  * Return the parser to the previous saved state.
156  *
157  * You must call save_parse_state() every time before calling
158  * restore_parse_state().
159  */
160 void
161 restore_parse_state(struct parse *cfile) {
162  struct parse *saved_state;
163 
164  if (TAILQ_NEXT(cfile) == NULL)
165  parse_error(cfile, "can't find saved state");
166 
167  saved_state = TAILQ_NEXT(cfile);
168  TAILQ_REMOVE(&parses, saved_state);
169  /* restore up to comments field */
170  memcpy(cfile, saved_state, (size_t)&(((struct parse *)0)->comments));
171  free(saved_state);
172 }
173 
174 static int
175 get_char(struct parse *cfile)
176 {
177  /* My kingdom for WITH... */
178  int c;
179 
180  if (cfile->bufix == cfile->buflen) {
181  c = EOF;
182  } else {
183  c = cfile->inbuf[cfile->bufix];
184  cfile->bufix++;
185  }
186 
187  if (!cfile->ugflag) {
188  if (c == EOL) {
189  if (cfile->cur_line == cfile->line1) {
190  cfile->cur_line = cfile->line2;
191  cfile->prev_line = cfile->line1;
192  } else {
193  cfile->cur_line = cfile->line1;
194  cfile->prev_line = cfile->line2;
195  }
196  cfile->line++;
197  cfile->lpos = 1;
198  cfile->cur_line[0] = 0;
199  } else if (c != EOF) {
200  if (cfile->lpos <= 80) {
201  cfile->cur_line[cfile->lpos - 1] = c;
202  cfile->cur_line[cfile->lpos] = 0;
203  }
204  cfile->lpos++;
205  }
206  } else
207  cfile->ugflag = 0;
208  return c;
209 }
210 
211 /*
212  * Return a character to our input buffer.
213  */
214 static void
215 unget_char(struct parse *cfile, int c) {
216  if (c != EOF) {
217  cfile->bufix--;
218  cfile->ugflag = 1; /* do not put characters into
219  our error buffer on the next
220  call to get_char() */
221  }
222 }
223 
224 /*
225  * GENERAL NOTE ABOUT TOKENS
226  *
227  * We normally only want non-whitespace tokens. There are some
228  * circumstances where we *do* want to see whitespace (for example
229  * when parsing IPv6 addresses).
230  *
231  * Generally we use the next_token() function to read tokens. This
232  * in turn calls get_next_token, which does *not* return tokens for
233  * whitespace. Rather, it skips these.
234  *
235  * When we need to see whitespace, we us next_raw_token(), which also
236  * returns the WHITESPACE token.
237  *
238  * The peek_token() and peek_raw_token() functions work as expected.
239  *
240  * Warning: if you invoke peek_token(), then if there is a whitespace
241  * token, it will be lost, and subsequent use of next_raw_token() or
242  * peek_raw_token() will NOT see it.
243  */
244 
245 static enum dhcp_token
246 get_raw_token(struct parse *cfile) {
247  int c;
248  enum dhcp_token ttok;
249  static char tb[2];
250  int l, p;
251 
252  for (;;) {
253  l = cfile->line;
254  p = cfile->lpos;
255 
256  c = get_char(cfile);
257  if (!((c == '\n') && cfile->eol_token) &&
258  isascii(c) && isspace(c)) {
259  ttok = read_whitespace(c, cfile);
260  break;
261  }
262  if (c == '#') {
263  skip_to_eol(cfile);
264  continue;
265  }
266  if (c == '"') {
267  cfile->lexline = l;
268  cfile->lexchar = p;
269  ttok = read_string(cfile);
270  break;
271  }
272  if ((isascii(c) && isdigit(c)) || c == '-') {
273  cfile->lexline = l;
274  cfile->lexchar = p;
275  ttok = read_number(c, cfile);
276  break;
277  } else if (isascii(c) && isalpha(c)) {
278  cfile->lexline = l;
279  cfile->lexchar = p;
280  ttok = read_num_or_name(c, cfile);
281  break;
282  } else if (c == EOF) {
283  ttok = END_OF_FILE;
284  cfile->tlen = 0;
285  break;
286  } else {
287  cfile->lexline = l;
288  cfile->lexchar = p;
289  tb[0] = c;
290  tb[1] = 0;
291  cfile->tval = tb;
292  cfile->tlen = 1;
293  ttok = c;
294  break;
295  }
296  }
297  return ttok;
298 }
299 
300 /*
301  * The get_next_token() function consumes the next token and
302  * returns it to the caller.
303  *
304  * Since the code is almost the same for "normal" and "raw"
305  * input, we pass a flag to alter the way it works.
306  */
307 
308 static enum dhcp_token
309 get_next_token(const char **rval, unsigned *rlen,
310  struct parse *cfile, isc_boolean_t raw) {
311  int rv;
312 
313  if (cfile->token) {
314  if (cfile->lexline != cfile->tline)
315  cfile->token_line = cfile->cur_line;
316  cfile->lexchar = cfile->tlpos;
317  cfile->lexline = cfile->tline;
318  rv = cfile->token;
319  cfile->token = 0;
320  } else {
321  rv = get_raw_token(cfile);
322  cfile->token_line = cfile->cur_line;
323  }
324 
325  if (!raw) {
326  while (rv == WHITESPACE) {
327  rv = get_raw_token(cfile);
328  cfile->token_line = cfile->cur_line;
329  }
330  }
331 
332  if (rval)
333  *rval = cfile->tval;
334  if (rlen)
335  *rlen = cfile->tlen;
336  return rv;
337 }
338 
339 /*
340  * Get the next token from cfile and return it.
341  *
342  * If rval is non-NULL, set the pointer it contains to
343  * the contents of the token.
344  *
345  * If rlen is non-NULL, set the integer it contains to
346  * the length of the token.
347  */
348 
349 enum dhcp_token
350 next_token(const char **rval, unsigned *rlen, struct parse *cfile) {
351  return get_next_token(rval, rlen, cfile, ISC_FALSE);
352 }
353 
354 
355 /*
356  * The same as the next_token() function above, but will return space
357  * as the WHITESPACE token.
358  */
359 
360 enum dhcp_token
361 next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
362  return get_next_token(rval, rlen, cfile, ISC_TRUE);
363 }
364 
365 
366 /*
367  * The do_peek_token() function checks the next token without
368  * consuming it, and returns it to the caller.
369  *
370  * Since the code is almost the same for "normal" and "raw"
371  * input, we pass a flag to alter the way it works. (See the
372  * warning in the GENERAL NOTES ABOUT TOKENS above though.)
373  */
374 
375 enum dhcp_token
376 do_peek_token(const char **rval, unsigned int *rlen,
377  struct parse *cfile, isc_boolean_t raw) {
378  int x;
379 
380  if (!cfile->token || (!raw && (cfile->token == WHITESPACE))) {
381  cfile->tlpos = cfile->lexchar;
382  cfile->tline = cfile->lexline;
383 
384  do {
385  cfile->token = get_raw_token(cfile);
386  } while (!raw && (cfile->token == WHITESPACE));
387 
388  if (cfile->lexline != cfile->tline)
389  cfile->token_line = cfile->prev_line;
390 
391  x = cfile->lexchar;
392  cfile->lexchar = cfile->tlpos;
393  cfile->tlpos = x;
394 
395  x = cfile->lexline;
396  cfile->lexline = cfile->tline;
397  cfile->tline = x;
398  }
399  if (rval)
400  *rval = cfile->tval;
401  if (rlen)
402  *rlen = cfile->tlen;
403  return cfile->token;
404 }
405 
406 
407 /*
408  * Get the next token from cfile and return it, leaving it for a
409  * subsequent call to next_token().
410  *
411  * Note that it WILL consume whitespace tokens.
412  *
413  * If rval is non-NULL, set the pointer it contains to
414  * the contents of the token.
415  *
416  * If rlen is non-NULL, set the integer it contains to
417  * the length of the token.
418  */
419 
420 enum dhcp_token
421 peek_token(const char **rval, unsigned *rlen, struct parse *cfile) {
422  return do_peek_token(rval, rlen, cfile, ISC_FALSE);
423 }
424 
425 
426 /*
427  * The same as the peek_token() function above, but will return space
428  * as the WHITESPACE token.
429  */
430 
431 enum dhcp_token
432 peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
433  return do_peek_token(rval, rlen, cfile, ISC_TRUE);
434 }
435 
436 /*
437  * The comment up to but not including EOL is saved.
438  */
439 
440 static void
441 skip_to_eol(struct parse *cfile)
442 {
443  char buf[128];
444  unsigned cc = 0;
445  struct comment *comment;
446 
447  memset(buf, 0, sizeof(buf));
448  buf[0] = '#';
449  for (;;) {
450  int c;
451 
452  c = get_char(cfile);
453  if (c == EOF)
454  break;
455  if (c == EOL) {
456  break;
457  }
458  if (++cc < sizeof(buf) - 1)
459  buf[cc] = c;
460  }
461  comment = createComment(buf);
463 }
464 
465 static enum dhcp_token
466 read_whitespace(int c, struct parse *cfile) {
467  int ofs;
468 
469  /*
470  * Read as much whitespace as we have available.
471  */
472  ofs = 0;
473  do {
474  if (ofs >= (sizeof(cfile->tokbuf) - 1)) {
475  /*
476  * As the file includes a huge amount of whitespace,
477  * it's probably broken.
478  * Print out a warning and bail out.
479  */
480  parse_error(cfile,
481  "whitespace too long, buffer overflow.");
482  }
483  cfile->tokbuf[ofs++] = c;
484  c = get_char(cfile);
485  if (c == EOF)
486  return END_OF_FILE;
487  } while (!((c == '\n') && cfile->eol_token) &&
488  isascii(c) && isspace(c));
489 
490  /*
491  * Put the last (non-whitespace) character back.
492  */
493  unget_char(cfile, c);
494 
495  /*
496  * Return our token.
497  */
498  cfile->tokbuf[ofs] = '\0';
499  cfile->tlen = ofs;
500  cfile->tval = cfile->tokbuf;
501  return WHITESPACE;
502 }
503 
504 static enum dhcp_token
505 read_string(struct parse *cfile)
506 {
507  unsigned i;
508  int bs = 0;
509  int c;
510  int value = 0;
511  int hex = 0;
512 
513  for (i = 0; i < sizeof(cfile->tokbuf); i++) {
514  again:
515  c = get_char(cfile);
516  if (c == EOF)
517  parse_error(cfile, "eof in string constant");
518  if (bs == 1) {
519  switch (c) {
520  case 't':
521  cfile->tokbuf[i] = '\t';
522  break;
523  case 'r':
524  cfile->tokbuf[i] = '\r';
525  break;
526  case 'n':
527  cfile->tokbuf[i] = '\n';
528  break;
529  case 'b':
530  cfile->tokbuf[i] = '\b';
531  break;
532  case '0':
533  case '1':
534  case '2':
535  case '3':
536  hex = 0;
537  value = c - '0';
538  ++bs;
539  goto again;
540  case 'x':
541  hex = 1;
542  value = 0;
543  ++bs;
544  goto again;
545  default:
546  cfile->tokbuf[i] = c;
547  break;
548  }
549  bs = 0;
550  } else if (bs > 1) {
551  if (hex) {
552  if (c >= '0' && c <= '9') {
553  value = value * 16 + (c - '0');
554  } else if (c >= 'a' && c <= 'f') {
555  value = value * 16 + (c - 'a' + 10);
556  } else if (c >= 'A' && c <= 'F') {
557  value = value * 16 + (c - 'A' + 10);
558  } else
559  parse_error(cfile,
560  "invalid hex digit: %x",
561  c);
562  if (++bs == 4) {
563  cfile->tokbuf[i] = value;
564  bs = 0;
565  } else
566  goto again;
567  } else {
568  if (c >= '0' && c <= '7') {
569  value = value * 8 + (c - '0');
570  } else {
571  if (value != 0)
572  parse_error(cfile,
573  "invalid octal digit %x",
574  c);
575  else
576  cfile->tokbuf[i] = 0;
577  bs = 0;
578  }
579  if (++bs == 4) {
580  cfile->tokbuf[i] = value;
581  bs = 0;
582  } else
583  goto again;
584  }
585  } else if (c == '\\') {
586  bs = 1;
587  goto again;
588  } else if (c == '"')
589  break;
590  else
591  cfile->tokbuf[i] = c;
592  }
593  /* Normally, I'd feel guilty about this, but we're talking about
594  strings that'll fit in a DHCP packet here... */
595  if (i == sizeof(cfile->tokbuf))
596  parse_error(cfile,
597  "string constant larger than internal buffer");
598  cfile->tokbuf[i] = 0;
599  cfile->tlen = i;
600  cfile->tval = cfile->tokbuf;
601  return STRING;
602 }
603 
604 static enum dhcp_token
605 read_number(int c, struct parse *cfile)
606 {
607  unsigned i = 0;
608  int token = NUMBER;
609 
610  cfile->tokbuf[i++] = c;
611  for (; i < sizeof(cfile->tokbuf); i++) {
612  c = get_char(cfile);
613 
614  /* Promote NUMBER->NUMBER_OR_NAME->NAME, never demote.
615  * Except in the case of '0x' syntax hex, which gets called
616  * a NAME at '0x', and returned to NUMBER_OR_NAME once it's
617  * verified to be at least 0xf or less.
618  */
619  switch (isascii(c) ? token : BREAK) {
620  case NUMBER:
621  if (isdigit(c))
622  break;
623  /* FALLTHROUGH */
624  case NUMBER_OR_NAME:
625  if (isxdigit(c)) {
626  token = NUMBER_OR_NAME;
627  break;
628  }
629  /* FALLTHROUGH */
630  case NAME:
631  if ((i == 2) && isxdigit(c) &&
632  (cfile->tokbuf[0] == '0') &&
633  ((cfile->tokbuf[1] == 'x') ||
634  (cfile->tokbuf[1] == 'X'))) {
635  token = NUMBER_OR_NAME;
636  break;
637  } else if (((c == '-') || (c == '_') || isalnum(c))) {
638  token = NAME;
639  break;
640  }
641  /* FALLTHROUGH */
642  case BREAK:
643  /* At this point c is either EOF or part of the next
644  * token. If not EOF, rewind the file one byte so
645  * the next token is read from there.
646  */
647  unget_char(cfile, c);
648  goto end_read;
649 
650  default:
651  parse_error(cfile,
652  "read_number(): impossible case");
653  }
654 
655  cfile->tokbuf[i] = c;
656  }
657 
658  if (i == sizeof(cfile->tokbuf))
659  parse_error(cfile,
660  "numeric token larger than internal buffer");
661 
662  end_read:
663  cfile->tokbuf[i] = 0;
664  cfile->tlen = i;
665  cfile->tval = cfile->tokbuf;
666 
667  /*
668  * If this entire token from start to finish was "-", such as
669  * the middle parameter in "42 - 7", return just the MINUS token.
670  */
671  if ((i == 1) && (cfile->tokbuf[i] == '-'))
672  return MINUS;
673  else
674  return token;
675 }
676 
677 static enum dhcp_token
678 read_num_or_name(int c, struct parse *cfile)
679 {
680  unsigned i = 0;
681  enum dhcp_token rv = NUMBER_OR_NAME;
682 
683  cfile->tokbuf[i++] = c;
684  for (; i < sizeof(cfile->tokbuf); i++) {
685  c = get_char(cfile);
686  if (!isascii(c) ||
687  (c != '-' && c != '_' && !isalnum(c))) {
688  unget_char(cfile, c);
689  break;
690  }
691  if (!isxdigit(c))
692  rv = NAME;
693  cfile->tokbuf[i] = c;
694  }
695  if (i == sizeof(cfile->tokbuf))
696  parse_error(cfile, "token larger than internal buffer");
697  cfile->tokbuf[i] = 0;
698  cfile->tlen = i;
699  cfile->tval = cfile->tokbuf;
700  return intern(cfile->tval, rv);
701 }
702 
703 static enum dhcp_token
704 intern(char *atom, enum dhcp_token dfv) {
705  if (!isascii(atom[0]))
706  return dfv;
707 
708  switch (tolower((unsigned char)atom[0])) {
709  case '-':
710  if (atom [1] == 0)
711  return MINUS;
712  break;
713 
714  case 'a':
715  if (!strcasecmp(atom + 1, "bandoned"))
716  return TOKEN_ABANDONED;
717  if (!strcasecmp(atom + 1, "ctive"))
718  return TOKEN_ACTIVE;
719  if (!strncasecmp(atom + 1, "dd", 2)) {
720  if (atom[3] == '\0')
721  return TOKEN_ADD;
722  else if (!strcasecmp(atom + 3, "ress"))
723  return ADDRESS;
724  break;
725  }
726  if (!strcasecmp(atom + 1, "fter"))
727  return AFTER;
728  if (isascii(atom[1]) &&
729  (tolower((unsigned char)atom[1]) == 'l')) {
730  if (!strcasecmp(atom + 2, "gorithm"))
731  return ALGORITHM;
732  if (!strcasecmp(atom + 2, "ias"))
733  return ALIAS;
734  if (isascii(atom[2]) &&
735  (tolower((unsigned char)atom[2]) == 'l')) {
736  if (atom[3] == '\0')
737  return ALL;
738  else if (!strcasecmp(atom + 3, "ow"))
739  return ALLOW;
740  break;
741  }
742  if (!strcasecmp(atom + 2, "so"))
743  return TOKEN_ALSO;
744  break;
745  }
746  if (isascii(atom[1]) &&
747  (tolower((unsigned char)atom[1]) == 'n')) {
748  if (!strcasecmp(atom + 2, "d"))
749  return AND;
750  if (!strcasecmp(atom + 2, "ycast-mac"))
751  return ANYCAST_MAC;
752  break;
753  }
754  if (!strcasecmp(atom + 1, "ppend"))
755  return APPEND;
756  if (!strcasecmp(atom + 1, "rray"))
757  return ARRAY;
758  if (isascii(atom[1]) &&
759  (tolower((unsigned char)atom[1]) == 't')) {
760  if (atom[2] == '\0')
761  return AT;
762  if (!strcasecmp(atom + 2, "sfp"))
763  return ATSFP;
764  break;
765  }
766  if (!strcasecmp(atom + 1, "uthoring-byte-order"))
767  return AUTHORING_BYTE_ORDER;
768  if (!strncasecmp(atom + 1, "ut", 2)) {
769  if (isascii(atom[3]) &&
770  (tolower((unsigned char)atom[3]) == 'h')) {
771  if (!strncasecmp(atom + 4, "enticat", 7)) {
772  if (!strcasecmp(atom + 11, "ed"))
773  return AUTHENTICATED;
774  if (!strcasecmp(atom + 11, "ion"))
775  return AUTHENTICATION;
776  break;
777  }
778  if (!strcasecmp(atom + 4, "oritative"))
779  return AUTHORITATIVE;
780  break;
781  }
782  if (!strcasecmp(atom + 3, "o-partner-down"))
783  return AUTO_PARTNER_DOWN;
784  break;
785  }
786  break;
787  case 'b':
788  if (!strcasecmp(atom + 1, "ackup"))
789  return TOKEN_BACKUP;
790  if (!strcasecmp(atom + 1, "ootp"))
791  return TOKEN_BOOTP;
792  if (!strcasecmp(atom + 1, "inding"))
793  return BINDING;
794  if (!strcasecmp(atom + 1, "inary-to-ascii"))
795  return BINARY_TO_ASCII;
796  if (!strcasecmp(atom + 1, "ackoff-cutoff"))
797  return BACKOFF_CUTOFF;
798  if (!strcasecmp(atom + 1, "ooting"))
799  return BOOTING;
800  if (!strcasecmp(atom + 1, "oot-unknown-clients"))
801  return BOOT_UNKNOWN_CLIENTS;
802  if (!strcasecmp(atom + 1, "reak"))
803  return BREAK;
804  if (!strcasecmp(atom + 1, "illing"))
805  return BILLING;
806  if (!strcasecmp(atom + 1, "oolean"))
807  return BOOLEAN;
808  if (!strcasecmp(atom + 1, "alance"))
809  return BALANCE;
810  if (!strcasecmp(atom + 1, "ound"))
811  return BOUND;
812  if (!strcasecmp(atom+1, "ig-endian")) {
813  return TOKEN_BIG_ENDIAN;
814  }
815  break;
816  case 'c':
817  if (!strcasecmp(atom + 1, "ase"))
818  return CASE;
819  if (!strcasecmp(atom + 1, "heck"))
820  return CHECK;
821  if (!strcasecmp(atom + 1, "iaddr"))
822  return CIADDR;
823  if (isascii(atom[1]) &&
824  tolower((unsigned char)atom[1]) == 'l') {
825  if (!strcasecmp(atom + 2, "ass"))
826  return CLASS;
827  if (!strncasecmp(atom + 2, "ient", 4)) {
828  if (!strcasecmp(atom + 6, "s"))
829  return CLIENTS;
830  if (atom[6] == '-') {
831  if (!strcasecmp(atom + 7, "hostname"))
832  return CLIENT_HOSTNAME;
833  if (!strcasecmp(atom + 7, "identifier"))
834  return CLIENT_IDENTIFIER;
835  if (!strcasecmp(atom + 7, "state"))
836  return CLIENT_STATE;
837  if (!strcasecmp(atom + 7, "updates"))
838  return CLIENT_UPDATES;
839  break;
840  }
841  break;
842  }
843  if (!strcasecmp(atom + 2, "ose"))
844  return TOKEN_CLOSE;
845  if (!strcasecmp(atom + 2, "tt"))
846  return CLTT;
847  break;
848  }
849  if (isascii(atom[1]) &&
850  tolower((unsigned char)atom[1]) == 'o') {
851  if (!strcasecmp(atom + 2, "de"))
852  return CODE;
853  if (isascii(atom[2]) &&
854  tolower((unsigned char)atom[2]) == 'm') {
855  if (!strcasecmp(atom + 3, "mit"))
856  return COMMIT;
857  if (!strcasecmp(atom + 3,
858  "munications-interrupted"))
860  if (!strcasecmp(atom + 3, "pressed"))
861  return COMPRESSED;
862  break;
863  }
864  if (isascii(atom[2]) &&
865  tolower((unsigned char)atom[2]) == 'n') {
866  if (!strcasecmp(atom + 3, "cat"))
867  return CONCAT;
868  if (!strcasecmp(atom + 3, "fig-option"))
869  return CONFIG_OPTION;
870  if (!strcasecmp(atom + 3, "flict-done"))
871  return CONFLICT_DONE;
872  if (!strcasecmp(atom + 3, "nect"))
873  return CONNECT;
874  break;
875  }
876  break;
877  }
878  if (!strcasecmp(atom + 1, "reate"))
879  return TOKEN_CREATE;
880  break;
881  case 'd':
882  if (!strcasecmp(atom + 1, "b-time-format"))
883  return DB_TIME_FORMAT;
884  if (!strcasecmp(atom + 1, "omain"))
885  return DOMAIN;
886  if (!strncasecmp(atom + 1, "omain-", 6)) {
887  if (!strcasecmp(atom + 7, "name"))
888  return DOMAIN_NAME;
889  if (!strcasecmp(atom + 7, "list"))
890  return DOMAIN_LIST;
891  }
892  if (!strcasecmp(atom + 1, "o-forward-updates"))
893  return DO_FORWARD_UPDATE;
894  /* do-forward-update is included for historical reasons */
895  if (!strcasecmp(atom + 1, "o-forward-update"))
896  return DO_FORWARD_UPDATE;
897  if (!strcasecmp(atom + 1, "ebug"))
898  return TOKEN_DEBUG;
899  if (!strcasecmp(atom + 1, "eny"))
900  return DENY;
901  if (!strcasecmp(atom + 1, "eleted"))
902  return TOKEN_DELETED;
903  if (!strcasecmp(atom + 1, "elete"))
904  return TOKEN_DELETE;
905  if (!strncasecmp(atom + 1, "efault", 6)) {
906  if (!atom [7])
907  return DEFAULT;
908  if (!strcasecmp(atom + 7, "-duid"))
909  return DEFAULT_DUID;
910  if (!strcasecmp(atom + 7, "-lease-time"))
911  return DEFAULT_LEASE_TIME;
912  break;
913  }
914  if (!strncasecmp(atom + 1, "ynamic", 6)) {
915  if (!atom [7])
916  return DYNAMIC;
917  if (!strncasecmp(atom + 7, "-bootp", 6)) {
918  if (!atom [13])
919  return DYNAMIC_BOOTP;
920  if (!strcasecmp(atom + 13, "-lease-cutoff"))
922  if (!strcasecmp(atom + 13, "-lease-length"))
924  break;
925  }
926  }
927  if (!strcasecmp(atom + 1, "uplicates"))
928  return DUPLICATES;
929  if (!strcasecmp(atom + 1, "eclines"))
930  return DECLINES;
931  if (!strncasecmp(atom + 1, "efine", 5)) {
932  if (!strcasecmp(atom + 6, "d"))
933  return DEFINED;
934  if (!atom [6])
935  return DEFINE;
936  }
937  break;
938  case 'e':
939  if (isascii(atom [1]) &&
940  tolower((unsigned char)atom[1]) == 'x') {
941  if (!strcasecmp(atom + 2, "tract-int"))
942  return EXTRACT_INT;
943  if (!strcasecmp(atom + 2, "ists"))
944  return EXISTS;
945  if (!strcasecmp(atom + 2, "piry"))
946  return EXPIRY;
947  if (!strcasecmp(atom + 2, "pire"))
948  return EXPIRE;
949  if (!strcasecmp(atom + 2, "pired"))
950  return TOKEN_EXPIRED;
951  }
952  if (!strcasecmp(atom + 1, "ncode-int"))
953  return ENCODE_INT;
954  if (!strcasecmp(atom + 1, "poch"))
955  return EPOCH;
956  if (!strcasecmp(atom + 1, "thernet"))
957  return ETHERNET;
958  if (!strcasecmp(atom + 1, "nds"))
959  return ENDS;
960  if (!strncasecmp(atom + 1, "ls", 2)) {
961  if (!strcasecmp(atom + 3, "e"))
962  return ELSE;
963  if (!strcasecmp(atom + 3, "if"))
964  return ELSIF;
965  break;
966  }
967  if (!strcasecmp(atom + 1, "rror"))
968  return ERROR;
969  if (!strcasecmp(atom + 1, "val"))
970  return EVAL;
971  if (!strcasecmp(atom + 1, "ncapsulate"))
972  return ENCAPSULATE;
973  if (!strcasecmp(atom + 1, "xecute"))
974  return EXECUTE;
975  if (!strcasecmp(atom+1, "n")) {
976  return EN;
977  }
978  break;
979  case 'f':
980  if (!strcasecmp(atom + 1, "atal"))
981  return FATAL;
982  if (!strcasecmp(atom + 1, "ilename"))
983  return FILENAME;
984  if (!strcasecmp(atom + 1, "ixed-address"))
985  return FIXED_ADDR;
986  if (!strcasecmp(atom + 1, "ixed-address6"))
987  return FIXED_ADDR6;
988  if (!strcasecmp(atom + 1, "ixed-prefix6"))
989  return FIXED_PREFIX6;
990  if (!strcasecmp(atom + 1, "ddi"))
991  return TOKEN_FDDI;
992  if (!strcasecmp(atom + 1, "ormerr"))
993  return NS_FORMERR;
994  if (!strcasecmp(atom + 1, "unction"))
995  return FUNCTION;
996  if (!strcasecmp(atom + 1, "ailover"))
997  return FAILOVER;
998  if (!strcasecmp(atom + 1, "ree"))
999  return TOKEN_FREE;
1000  break;
1001  case 'g':
1002  if (!strncasecmp(atom + 1, "et", 2)) {
1003  if (!strcasecmp(atom + 3, "-lease-hostnames"))
1004  return GET_LEASE_HOSTNAMES;
1005  if (!strcasecmp(atom + 3, "hostbyname"))
1006  return GETHOSTBYNAME;
1007  if (!strcasecmp(atom + 3, "hostname"))
1008  return GETHOSTNAME;
1009  break;
1010  }
1011  if (!strcasecmp(atom + 1, "iaddr"))
1012  return GIADDR;
1013  if (!strcasecmp(atom + 1, "roup"))
1014  return GROUP;
1015  break;
1016  case 'h':
1017  if (!strcasecmp(atom + 1, "ash"))
1018  return HASH;
1019  if (!strcasecmp(atom + 1, "ba"))
1020  return HBA;
1021  if (!strcasecmp(atom + 1, "ost"))
1022  return HOST;
1023  if (!strcasecmp(atom + 1, "ost-decl-name"))
1024  return HOST_DECL_NAME;
1025  if (!strcasecmp(atom + 1, "ost-identifier"))
1026  return HOST_IDENTIFIER;
1027  if (!strcasecmp(atom + 1, "ardware"))
1028  return HARDWARE;
1029  if (!strcasecmp(atom + 1, "ostname"))
1030  return HOSTNAME;
1031  if (!strcasecmp(atom + 1, "elp"))
1032  return TOKEN_HELP;
1033  if (!strcasecmp(atom + 1, "ex")) {
1034  return TOKEN_HEX;
1035  }
1036  break;
1037  case 'i':
1038  if (!strcasecmp(atom+1, "a-na"))
1039  return IA_NA;
1040  if (!strcasecmp(atom+1, "a-ta"))
1041  return IA_TA;
1042  if (!strcasecmp(atom+1, "a-pd"))
1043  return IA_PD;
1044  if (!strcasecmp(atom+1, "aaddr"))
1045  return IAADDR;
1046  if (!strcasecmp(atom+1, "aprefix"))
1047  return IAPREFIX;
1048  if (!strcasecmp(atom + 1, "nclude"))
1049  return INCLUDE;
1050  if (!strcasecmp(atom + 1, "nteger"))
1051  return INTEGER;
1052  if (!strcasecmp(atom + 1, "nfiniband"))
1053  return TOKEN_INFINIBAND;
1054  if (!strcasecmp(atom + 1, "nfinite"))
1055  return INFINITE;
1056  if (!strcasecmp(atom + 1, "nfo"))
1057  return INFO;
1058  if (!strcasecmp(atom + 1, "p-address"))
1059  return IP_ADDRESS;
1060  if (!strcasecmp(atom + 1, "p6-address"))
1061  return IP6_ADDRESS;
1062  if (!strcasecmp(atom + 1, "nitial-interval"))
1063  return INITIAL_INTERVAL;
1064  if (!strcasecmp(atom + 1, "nitial-delay"))
1065  return INITIAL_DELAY;
1066  if (!strcasecmp(atom + 1, "nterface"))
1067  return INTERFACE;
1068  if (!strcasecmp(atom + 1, "dentifier"))
1069  return IDENTIFIER;
1070  if (!strcasecmp(atom + 1, "f"))
1071  return IF;
1072  if (!strcasecmp(atom + 1, "s"))
1073  return IS;
1074  if (!strcasecmp(atom + 1, "gnore"))
1075  return IGNORE;
1076  break;
1077  case 'k':
1078  if (!strncasecmp(atom + 1, "nown", 4)) {
1079  if (!strcasecmp(atom + 5, "-clients"))
1080  return KNOWN_CLIENTS;
1081  if (!atom[5])
1082  return KNOWN;
1083  break;
1084  }
1085  if (!strcasecmp(atom + 1, "ey"))
1086  return KEY;
1087  if (!strcasecmp (atom + 1, "ey-algorithm"))
1088  return KEY_ALGORITHM;
1089  break;
1090  case 'l':
1091  if (!strcasecmp(atom + 1, "case"))
1092  return LCASE;
1093  if (!strcasecmp(atom + 1, "ease"))
1094  return LEASE;
1095  if (!strcasecmp(atom + 1, "ease6"))
1096  return LEASE6;
1097  if (!strcasecmp(atom + 1, "eased-address"))
1098  return LEASED_ADDRESS;
1099  if (!strcasecmp(atom + 1, "ease-time"))
1100  return LEASE_TIME;
1101  if (!strcasecmp(atom + 1, "easequery"))
1102  return LEASEQUERY;
1103  if (!strcasecmp(atom + 1, "ength"))
1104  return LENGTH;
1105  if (!strcasecmp(atom + 1, "imit"))
1106  return LIMIT;
1107  if (!strcasecmp(atom + 1, "et"))
1108  return LET;
1109  if (!strcasecmp(atom + 1, "oad"))
1110  return LOAD;
1111  if (!strcasecmp(atom + 1, "ocal"))
1112  return LOCAL;
1113  if (!strcasecmp(atom + 1, "og"))
1114  return LOG;
1115  if (!strcasecmp(atom+1, "lt")) {
1116  return LLT;
1117  }
1118  if (!strcasecmp(atom+1, "l")) {
1119  return LL;
1120  }
1121  if (!strcasecmp(atom+1, "ittle-endian")) {
1122  return TOKEN_LITTLE_ENDIAN;
1123  }
1124  if (!strcasecmp(atom + 1, "ease-id-format")) {
1125  return LEASE_ID_FORMAT;
1126  }
1127  break;
1128  case 'm':
1129  if (!strncasecmp(atom + 1, "ax", 2)) {
1130  if (!atom [3])
1131  return TOKEN_MAX;
1132  if (!strcasecmp(atom + 3, "-balance"))
1133  return MAX_BALANCE;
1134  if (!strncasecmp(atom + 3, "-lease-", 7)) {
1135  if (!strcasecmp(atom + 10, "misbalance"))
1136  return MAX_LEASE_MISBALANCE;
1137  if (!strcasecmp(atom + 10, "ownership"))
1138  return MAX_LEASE_OWNERSHIP;
1139  if (!strcasecmp(atom + 10, "time"))
1140  return MAX_LEASE_TIME;
1141  }
1142  if (!strcasecmp(atom + 3, "-life"))
1143  return MAX_LIFE;
1144  if (!strcasecmp(atom + 3, "-transmit-idle"))
1145  return MAX_TRANSMIT_IDLE;
1146  if (!strcasecmp(atom + 3, "-response-delay"))
1147  return MAX_RESPONSE_DELAY;
1148  if (!strcasecmp(atom + 3, "-unacked-updates"))
1149  return MAX_UNACKED_UPDATES;
1150  }
1151  if (!strncasecmp(atom + 1, "in-", 3)) {
1152  if (!strcasecmp(atom + 4, "balance"))
1153  return MIN_BALANCE;
1154  if (!strcasecmp(atom + 4, "lease-time"))
1155  return MIN_LEASE_TIME;
1156  if (!strcasecmp(atom + 4, "secs"))
1157  return MIN_SECS;
1158  break;
1159  }
1160  if (!strncasecmp(atom + 1, "edi", 3)) {
1161  if (!strcasecmp(atom + 4, "a"))
1162  return MEDIA;
1163  if (!strcasecmp(atom + 4, "um"))
1164  return MEDIUM;
1165  break;
1166  }
1167  if (!strcasecmp(atom + 1, "atch"))
1168  return MATCH;
1169  if (!strcasecmp(atom + 1, "embers"))
1170  return MEMBERS;
1171  if (!strcasecmp(atom + 1, "y"))
1172  return MY;
1173  if (!strcasecmp(atom + 1, "clt"))
1174  return MCLT;
1175  break;
1176  case 'n':
1177  if (!strcasecmp(atom + 1, "ormal"))
1178  return NORMAL;
1179  if (!strcasecmp(atom + 1, "ameserver"))
1180  return NAMESERVER;
1181  if (!strcasecmp(atom + 1, "etmask"))
1182  return NETMASK;
1183  if (!strcasecmp(atom + 1, "ever"))
1184  return NEVER;
1185  if (!strcasecmp(atom + 1, "ext-server"))
1186  return NEXT_SERVER;
1187  if (!strcasecmp(atom + 1, "ot"))
1188  return TOKEN_NOT;
1189  if (!strcasecmp(atom + 1, "o"))
1190  return TOKEN_NO;
1191  if (!strcasecmp(atom + 1, "oerror"))
1192  return NS_NOERROR;
1193  if (!strcasecmp(atom + 1, "otauth"))
1194  return NS_NOTAUTH;
1195  if (!strcasecmp(atom + 1, "otimp"))
1196  return NS_NOTIMP;
1197  if (!strcasecmp(atom + 1, "otzone"))
1198  return NS_NOTZONE;
1199  if (!strcasecmp(atom + 1, "xdomain"))
1200  return NS_NXDOMAIN;
1201  if (!strcasecmp(atom + 1, "xrrset"))
1202  return NS_NXRRSET;
1203  if (!strcasecmp(atom + 1, "ull"))
1204  return TOKEN_NULL;
1205  if (!strcasecmp(atom + 1, "ext"))
1206  return TOKEN_NEXT;
1207  if (!strcasecmp(atom + 1, "ew"))
1208  return TOKEN_NEW;
1209  break;
1210  case 'o':
1211  if (!strcasecmp(atom + 1, "mapi"))
1212  return OMAPI;
1213  if (!strcasecmp(atom + 1, "r"))
1214  return OR;
1215  if (!strcasecmp(atom + 1, "n"))
1216  return ON;
1217  if (!strcasecmp(atom + 1, "pen"))
1218  return TOKEN_OPEN;
1219  if (!strcasecmp(atom + 1, "ption"))
1220  return OPTION;
1221  if (!strcasecmp(atom + 1, "ne-lease-per-client"))
1222  return ONE_LEASE_PER_CLIENT;
1223  if (!strcasecmp(atom + 1, "f"))
1224  return OF;
1225  if (!strcasecmp(atom + 1, "wner"))
1226  return OWNER;
1227  if (!strcasecmp(atom + 1, "ctal")) {
1228  return TOKEN_OCTAL;
1229  }
1230  break;
1231  case 'p':
1232  if (!strcasecmp(atom + 1, "arse-vendor-option"))
1233  return PARSE_VENDOR_OPT;
1234  if (!strcasecmp(atom + 1, "repend"))
1235  return PREPEND;
1236  if (!strcasecmp(atom + 1, "referred-life"))
1237  return PREFERRED_LIFE;
1238  if (!strcasecmp(atom + 1, "acket"))
1239  return PACKET;
1240  if (!strcasecmp(atom + 1, "ool"))
1241  return POOL;
1242  if (!strcasecmp(atom + 1, "ool6"))
1243  return POOL6;
1244  if (!strcasecmp(atom + 1, "refix6"))
1245  return PREFIX6;
1246  if (!strcasecmp(atom + 1, "seudo"))
1247  return PSEUDO;
1248  if (!strcasecmp(atom + 1, "eer"))
1249  return PEER;
1250  if (!strcasecmp(atom + 1, "rimary"))
1251  return PRIMARY;
1252  if (!strcasecmp(atom + 1, "rimary6"))
1253  return PRIMARY6;
1254  if (!strncasecmp(atom + 1, "artner", 6)) {
1255  if (!atom [7])
1256  return PARTNER;
1257  if (!strcasecmp(atom + 7, "-down"))
1258  return PARTNER_DOWN;
1259  }
1260  if (!strcasecmp(atom + 1, "ort"))
1261  return PORT;
1262  if (!strcasecmp(atom + 1, "otential-conflict"))
1263  return POTENTIAL_CONFLICT;
1264  if (!strcasecmp(atom + 1, "ick-first-value") ||
1265  !strcasecmp(atom + 1, "ick"))
1266  return PICK;
1267  if (!strcasecmp(atom + 1, "aused"))
1268  return PAUSED;
1269  break;
1270  case 'r':
1271  if (!strcasecmp(atom + 1, "ange"))
1272  return RANGE;
1273  if (!strcasecmp(atom + 1, "ange6"))
1274  return RANGE6;
1275  if (isascii(atom[1]) &&
1276  (tolower((unsigned char)atom[1]) == 'e')) {
1277  if (!strcasecmp(atom + 2, "bind"))
1278  return REBIND;
1279  if (!strcasecmp(atom + 2, "boot"))
1280  return REBOOT;
1281  if (!strcasecmp(atom + 2, "contact-interval"))
1282  return RECONTACT_INTERVAL;
1283  if (!strncasecmp(atom + 2, "cover", 5)) {
1284  if (atom[7] == '\0')
1285  return RECOVER;
1286  if (!strcasecmp(atom + 7, "-done"))
1287  return RECOVER_DONE;
1288  if (!strcasecmp(atom + 7, "-wait"))
1289  return RECOVER_WAIT;
1290  break;
1291  }
1292  if (!strcasecmp(atom + 2, "fresh"))
1293  return REFRESH;
1294  if (!strcasecmp(atom + 2, "fused"))
1295  return NS_REFUSED;
1296  if (!strcasecmp(atom + 2, "ject"))
1297  return REJECT;
1298  if (!strcasecmp(atom + 2, "lease"))
1299  return RELEASE;
1300  if (!strcasecmp(atom + 2, "leased"))
1301  return TOKEN_RELEASED;
1302  if (!strcasecmp(atom + 2, "move"))
1303  return REMOVE;
1304  if (!strcasecmp(atom + 2, "new"))
1305  return RENEW;
1306  if (!strcasecmp(atom + 2, "quest"))
1307  return REQUEST;
1308  if (!strcasecmp(atom + 2, "quire"))
1309  return REQUIRE;
1310  if (isascii(atom[2]) &&
1311  (tolower((unsigned char)atom[2]) == 's')) {
1312  if (!strcasecmp(atom + 3, "erved"))
1313  return TOKEN_RESERVED;
1314  if (!strcasecmp(atom + 3, "et"))
1315  return TOKEN_RESET;
1316  if (!strcasecmp(atom + 3,
1317  "olution-interrupted"))
1318  return RESOLUTION_INTERRUPTED;
1319  break;
1320  }
1321  if (!strcasecmp(atom + 2, "try"))
1322  return RETRY;
1323  if (!strcasecmp(atom + 2, "turn"))
1324  return RETURN;
1325  if (!strcasecmp(atom + 2, "verse"))
1326  return REVERSE;
1327  if (!strcasecmp(atom + 2, "wind"))
1328  return REWIND;
1329  break;
1330  }
1331  break;
1332  case 's':
1333  if (!strcasecmp(atom + 1, "cript"))
1334  return SCRIPT;
1335  if (isascii(atom[1]) &&
1336  tolower((unsigned char)atom[1]) == 'e') {
1337  if (!strcasecmp(atom + 2, "arch"))
1338  return SEARCH;
1339  if (isascii(atom[2]) &&
1340  tolower((unsigned char)atom[2]) == 'c') {
1341  if (!strncasecmp(atom + 3, "ond", 3)) {
1342  if (!strcasecmp(atom + 6, "ary"))
1343  return SECONDARY;
1344  if (!strcasecmp(atom + 6, "ary6"))
1345  return SECONDARY6;
1346  if (!strcasecmp(atom + 6, "s"))
1347  return SECONDS;
1348  break;
1349  }
1350  if (!strcasecmp(atom + 3, "ret"))
1351  return SECRET;
1352  break;
1353  }
1354  if (!strncasecmp(atom + 2, "lect", 4)) {
1355  if (atom[6] == '\0')
1356  return SELECT;
1357  if (!strcasecmp(atom + 6, "-timeout"))
1358  return SELECT_TIMEOUT;
1359  break;
1360  }
1361  if (!strcasecmp(atom + 2, "nd"))
1362  return SEND;
1363  if (!strncasecmp(atom + 2, "rv", 2)) {
1364  if (!strncasecmp(atom + 4, "er", 2)) {
1365  if (atom[6] == '\0')
1366  return TOKEN_SERVER;
1367  if (atom[6] == '-') {
1368  if (!strcasecmp(atom + 7,
1369  "duid"))
1370  return SERVER_DUID;
1371  if (!strcasecmp(atom + 7,
1372  "name"))
1373  return SERVER_NAME;
1374  if (!strcasecmp(atom + 7,
1375  "identifier"))
1376  return SERVER_IDENTIFIER;
1377  break;
1378  }
1379  break;
1380  }
1381  if (!strcasecmp(atom + 4, "fail"))
1382  return NS_SERVFAIL;
1383  break;
1384  }
1385  if (!strcasecmp(atom + 2, "t"))
1386  return TOKEN_SET;
1387  break;
1388  }
1389  if (isascii(atom[1]) &&
1390  tolower((unsigned char)atom[1]) == 'h') {
1391  if (!strcasecmp(atom + 2, "ared-network"))
1392  return SHARED_NETWORK;
1393  if (!strcasecmp(atom + 2, "utdown"))
1394  return SHUTDOWN;
1395  break;
1396  }
1397  if (isascii(atom[1]) &&
1398  tolower((unsigned char)atom[1]) == 'i') {
1399  if (!strcasecmp(atom + 2, "addr"))
1400  return SIADDR;
1401  if (!strcasecmp(atom + 2, "gned"))
1402  return SIGNED;
1403  if (!strcasecmp(atom + 2, "ze"))
1404  return SIZE;
1405  break;
1406  }
1407  if (isascii(atom[1]) &&
1408  tolower((unsigned char)atom[1]) == 'p') {
1409  if (isascii(atom[2]) &&
1410  tolower((unsigned char)atom[2]) == 'a') {
1411  if (!strcasecmp(atom + 3, "ce"))
1412  return SPACE;
1413  if (!strcasecmp(atom + 3, "wn"))
1414  return SPAWN;
1415  break;
1416  }
1417  if (!strcasecmp(atom + 2, "lit"))
1418  return SPLIT;
1419  break;
1420  }
1421  if (isascii(atom[1]) &&
1422  tolower((unsigned char)atom[1]) == 't') {
1423  if (isascii(atom[2]) &&
1424  tolower((unsigned char)atom[2]) == 'a') {
1425  if (!strncasecmp(atom + 3, "rt", 2)) {
1426  if (!strcasecmp(atom + 5, "s"))
1427  return STARTS;
1428  if (!strcasecmp(atom + 5, "up"))
1429  return STARTUP;
1430  break;
1431  }
1432  if (isascii(atom[3]) &&
1433  tolower((unsigned char)atom[3]) == 't') {
1434  if (!strcasecmp(atom + 4, "e"))
1435  return STATE;
1436  if (!strcasecmp(atom + 4, "ic"))
1437  return STATIC;
1438  break;
1439  }
1440  }
1441  if (!strcasecmp(atom + 2, "ring"))
1442  return STRING_TOKEN;
1443  break;
1444  }
1445  if (!strncasecmp(atom + 1, "ub", 2)) {
1446  if (!strcasecmp(atom + 3, "class"))
1447  return SUBCLASS;
1448  if (!strcasecmp(atom + 3, "net"))
1449  return SUBNET;
1450  if (!strcasecmp(atom + 3, "net6"))
1451  return SUBNET6;
1452  if (!strcasecmp(atom + 3, "string"))
1453  return SUBSTRING;
1454  break;
1455  }
1456  if (isascii(atom[1]) &&
1457  tolower((unsigned char)atom[1]) == 'u') {
1458  if (!strcasecmp(atom + 2, "ffix"))
1459  return SUFFIX;
1460  if (!strcasecmp(atom + 2, "persede"))
1461  return SUPERSEDE;
1462  }
1463  if (!strcasecmp(atom + 1, "witch"))
1464  return SWITCH;
1465  break;
1466  case 't':
1467  if (!strcasecmp(atom + 1, "imestamp"))
1468  return TIMESTAMP;
1469  if (!strcasecmp(atom + 1, "imeout"))
1470  return TIMEOUT;
1471  if (!strcasecmp(atom + 1, "oken-ring"))
1472  return TOKEN_RING;
1473  if (!strcasecmp(atom + 1, "ext"))
1474  return TEXT;
1475  if (!strcasecmp(atom + 1, "stp"))
1476  return TSTP;
1477  if (!strcasecmp(atom + 1, "sfp"))
1478  return TSFP;
1479  if (!strcasecmp(atom + 1, "ransmission"))
1480  return TRANSMISSION;
1481  if (!strcasecmp(atom + 1, "emporary"))
1482  return TEMPORARY;
1483  break;
1484  case 'u':
1485  if (!strcasecmp(atom + 1, "case"))
1486  return UCASE;
1487  if (!strcasecmp(atom + 1, "nset"))
1488  return UNSET;
1489  if (!strcasecmp(atom + 1, "nsigned"))
1490  return UNSIGNED;
1491  if (!strcasecmp(atom + 1, "id"))
1492  return UID;
1493  if (!strncasecmp(atom + 1, "se", 2)) {
1494  if (!strcasecmp(atom + 3, "r-class"))
1495  return USER_CLASS;
1496  if (!strcasecmp(atom + 3, "-host-decl-names"))
1497  return USE_HOST_DECL_NAMES;
1498  if (!strcasecmp(atom + 3,
1499  "-lease-addr-for-default-route"))
1501  break;
1502  }
1503  if (!strncasecmp(atom + 1, "nknown", 6)) {
1504  if (!strcasecmp(atom + 7, "-clients"))
1505  return UNKNOWN_CLIENTS;
1506  if (!strcasecmp(atom + 7, "-state"))
1507  return UNKNOWN_STATE;
1508  if (!atom [7])
1509  return UNKNOWN;
1510  break;
1511  }
1512  if (!strcasecmp(atom + 1, "nauthenticated"))
1513  return UNAUTHENTICATED;
1514  if (!strcasecmp(atom + 1, "pdate"))
1515  return UPDATE;
1516  break;
1517  case 'v':
1518  if (!strcasecmp(atom + 1, "6relay"))
1519  return V6RELAY;
1520  if (!strcasecmp(atom + 1, "6relopt"))
1521  return V6RELOPT;
1522  if (!strcasecmp(atom + 1, "endor-class"))
1523  return VENDOR_CLASS;
1524  if (!strcasecmp(atom + 1, "endor"))
1525  return VENDOR;
1526  break;
1527  case 'w':
1528  if (!strcasecmp(atom + 1, "ith"))
1529  return WITH;
1530  if (!strcasecmp(atom + 1, "idth"))
1531  return WIDTH;
1532  break;
1533  case 'y':
1534  if (!strcasecmp(atom + 1, "iaddr"))
1535  return YIADDR;
1536  if (!strcasecmp(atom + 1, "xdomain"))
1537  return NS_YXDOMAIN;
1538  if (!strcasecmp(atom + 1, "xrrset"))
1539  return NS_YXRRSET;
1540  break;
1541  case 'z':
1542  if (!strcasecmp(atom + 1, "erolen"))
1543  return ZEROLEN;
1544  if (!strcasecmp(atom + 1, "one"))
1545  return ZONE;
1546  break;
1547  }
1548  return dfv;
1549 }
1550 
int line
Definition: dhcpd.h:317
Definition: dhctoken.h:146
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
Definition: conflex.c:41
Definition: data.h:205
#define ISC_FALSE
Definition: data.h:152
Definition: dhctoken.h:252
Definition: dhctoken.h:267
Definition: dhctoken.h:151
Definition: dhctoken.h:284
Definition: dhctoken.h:51
enum dhcp_token token
Definition: dhcpd.h:320
isc_boolean_t
Definition: data.h:150
#define TAILQ_INIT(head)
Definition: data.h:72
size_t buflen
Definition: dhcpd.h:329
Definition: dhctoken.h:143
Definition: dhctoken.h:153
int tlpos
Definition: dhcpd.h:318
Definition: dhctoken.h:235
char * cur_line
Definition: dhcpd.h:293
dhcp_token
Definition: dhctoken.h:34
int lpos
Definition: dhcpd.h:316
enum dhcp_token next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:380
Definition: dhctoken.h:207
Definition: dhctoken.h:137
Definition: dhctoken.h:75
Definition: dhctoken.h:229
char * tval
Definition: dhcpd.h:322
isc_result_t restore_parse_state(struct parse *cfile)
Definition: conflex.c:159
Definition: dhctoken.h:224
struct parse * saved_state
Definition: dhcpd.h:332
Definition: dhctoken.h:259
Definition: dhcpd.h:288
size_t stack_size
Definition: keama.h:111
int eol_token
Definition: dhcpd.h:295
Definition: dhctoken.h:251
Definition: dhctoken.h:159
#define ISC_TRUE
Definition: data.h:153
struct element ** stack
Definition: keama.h:110
Definition: dhctoken.h:74
Definition: dhctoken.h:349
enum dhcp_token peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:454
Definition: dhctoken.h:222
Definition: dhctoken.h:173
Definition: dhctoken.h:59
Definition: dhctoken.h:76
int tline
Definition: dhcpd.h:319
Definition: dhctoken.h:280
#define TAILQ_REMOVE(head, elm)
Definition: data.h:120
int tlen
Definition: dhcpd.h:323
isc_result_t save_parse_state(struct parse *cfile)
Definition: conflex.c:128
Definition: dhctoken.h:256
Definition: dhctoken.h:73
Definition: data.h:190
Definition: dhctoken.h:204
Definition: dhctoken.h:225
#define TAILQ_INSERT_AFTER(head, listelm, elm)
Definition: data.h:77
Definition: dhctoken.h:321
#define TAILQ_INSERT_TAIL(head, elm)
Definition: data.h:105
Definition: dhctoken.h:255
char line2[81]
Definition: dhcpd.h:315
Definition: dhctoken.h:138
char tokbuf[1500]
Definition: dhcpd.h:324
void parse_error(struct parse *cfile, const char *fmt,...)
Definition: keama.c:194
Definition: dhctoken.h:221
Definition: dhctoken.h:348
#define EOL
Definition: dhcpd.h:88
#define TAILQ_NEXT(elm)
Definition: data.h:115
Definition: dhctoken.h:101
Definition: dhctoken.h:69
size_t bufsiz
Definition: dhcpd.h:330
const char * tlname
Definition: dhcpd.h:294
isc_result_t end_parse(struct parse **cfile)
Definition: conflex.c:103
Definition: dhctoken.h:350
int lexchar
Definition: dhcpd.h:290
Definition: dhctoken.h:168
size_t bufix
Definition: dhcpd.h:329
char * inbuf
Definition: dhcpd.h:328
Definition: dhctoken.h:227
Definition: dhctoken.h:322
Definition: dhctoken.h:97
Definition: dhctoken.h:72
enum dhcp_token next_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:369
int ugflag
Definition: dhcpd.h:321
struct comments comments
Definition: keama.h:116
const char * file
Definition: dhcpd.h:3793
char * token_line
Definition: dhcpd.h:291
Definition: dhctoken.h:166
char line1[81]
Definition: dhcpd.h:314
Definition: dhctoken.h:189
enum dhcp_token do_peek_token(const char **rval, unsigned int *rlen, struct parse *cfile, isc_boolean_t raw)
Definition: conflex.c:395
Definition: dhctoken.h:196
char * prev_line
Definition: dhcpd.h:292
Definition: dhctoken.h:115
int file
Definition: dhcpd.h:327
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:443
int lexline
Definition: dhcpd.h:289
Definition: dhctoken.h:162
struct comment * createComment(const char *line)
Definition: data.c:367