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