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