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