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