3 Lexical scanner for dhcpd config file... */
6 * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
38 static int get_char
PROTO ((struct parse
*));
39 static void unget_char(struct parse
*, int);
40 static void skip_to_eol
PROTO ((struct parse
*));
41 static enum dhcp_token
read_whitespace(int c
, struct parse
*cfile
);
42 static enum dhcp_token read_string
PROTO ((struct parse
*));
43 static enum dhcp_token read_number
PROTO ((int, struct parse
*));
44 static enum dhcp_token read_num_or_name
PROTO ((int, struct parse
*));
45 static enum dhcp_token intern
PROTO ((char *, enum dhcp_token
));
47 isc_result_t
new_parse (cfile
, file
, inbuf
, buflen
, name
, eolp
)
55 isc_result_t status
= ISC_R_SUCCESS
;
58 tmp
= dmalloc(sizeof(struct parse
), MDL
);
60 return (ISC_R_NOMEMORY
);
64 * We don't need to initialize things to zero here, since
65 * dmalloc() returns memory that is set to zero.
68 tmp
->lpos
= tmp
-> line
= 1;
69 tmp
->cur_line
= tmp
->line1
;
70 tmp
->prev_line
= tmp
->line2
;
71 tmp
->token_line
= tmp
->cur_line
;
72 tmp
->cur_line
[0] = tmp
->prev_line
[0] = 0;
74 tmp
->eol_token
= eolp
;
83 if (fstat(file
, &sb
) < 0) {
84 status
= ISC_R_IOERROR
;
91 tmp
->bufsiz
= tmp
->buflen
= (size_t) sb
.st_size
;
92 tmp
->inbuf
= mmap(NULL
, tmp
->bufsiz
, PROT_READ
, MAP_SHARED
,
95 if (tmp
->inbuf
== MAP_FAILED
) {
96 status
= ISC_R_IOERROR
;
102 return (ISC_R_SUCCESS
);
109 isc_result_t
end_parse (cfile
)
110 struct parse
**cfile
;
112 /* "Memory" config files have no file. */
113 if ((*cfile
)->file
!= -1) {
114 munmap((*cfile
)->inbuf
, (*cfile
)->bufsiz
);
115 close((*cfile
)->file
);
118 if ((*cfile
)->saved_state
!= NULL
) {
119 dfree((*cfile
)->saved_state
, MDL
);
124 return ISC_R_SUCCESS
;
128 * Save the current state of the parser.
130 * Only one state may be saved. Any previous saved state is
134 save_parse_state(struct parse
*cfile
) {
136 * Free any previous saved state.
138 if (cfile
->saved_state
!= NULL
) {
139 dfree(cfile
->saved_state
, MDL
);
143 * Save our current state.
145 cfile
->saved_state
= dmalloc(sizeof(struct parse
), MDL
);
146 if (cfile
->saved_state
== NULL
) {
147 return ISC_R_NOMEMORY
;
149 memcpy(cfile
->saved_state
, cfile
, sizeof(*cfile
));
150 return ISC_R_SUCCESS
;
154 * Return the parser to the previous saved state.
156 * You must call save_parse_state() before calling
157 * restore_parse_state(), but you can call restore_parse_state() any
158 * number of times after that.
161 restore_parse_state(struct parse
*cfile
) {
162 struct parse
*saved_state
;
164 if (cfile
->saved_state
== NULL
) {
165 return DHCP_R_NOTYET
;
168 saved_state
= cfile
->saved_state
;
169 memcpy(cfile
, saved_state
, sizeof(*cfile
));
170 cfile
->saved_state
= saved_state
;
171 return ISC_R_SUCCESS
;
174 static int get_char (cfile
)
177 /* My kingdom for WITH... */
180 if (cfile
->bufix
== cfile
->buflen
) {
181 #if !defined(LDAP_CONFIGURATION)
183 #else /* defined(LDAP_CONFIGURATION) */
184 if (cfile
->read_function
!= NULL
)
185 c
= cfile
->read_function(cfile
);
190 c
= cfile
->inbuf
[cfile
->bufix
];
194 if (!cfile
->ugflag
) {
196 if (cfile
->cur_line
== cfile
->line1
) {
197 cfile
->cur_line
= cfile
->line2
;
198 cfile
->prev_line
= cfile
->line1
;
200 cfile
->cur_line
= cfile
->line1
;
201 cfile
->prev_line
= cfile
->line2
;
205 cfile
->cur_line
[0] = 0;
206 } else if (c
!= EOF
) {
207 if (cfile
->lpos
<= 80) {
208 cfile
->cur_line
[cfile
->lpos
- 1] = c
;
209 cfile
->cur_line
[cfile
->lpos
] = 0;
219 * Return a character to our input buffer.
222 unget_char(struct parse
*cfile
, int c
) {
225 cfile
->ugflag
= 1; /* do not put characters into
226 our error buffer on the next
227 call to get_char() */
232 * GENERAL NOTE ABOUT TOKENS
234 * We normally only want non-whitespace tokens. There are some
235 * circumstances where we *do* want to see whitespace (for example
236 * when parsing IPv6 addresses).
238 * Generally we use the next_token() function to read tokens. This
239 * in turn calls get_next_token, which does *not* return tokens for
240 * whitespace. Rather, it skips these.
242 * When we need to see whitespace, we us next_raw_token(), which also
243 * returns the WHITESPACE token.
245 * The peek_token() and peek_raw_token() functions work as expected.
247 * Warning: if you invoke peek_token(), then if there is a whitespace
248 * token, it will be lost, and subsequent use of next_raw_token() or
249 * peek_raw_token() will NOT see it.
252 static enum dhcp_token
253 get_raw_token(struct parse
*cfile
) {
255 enum dhcp_token ttok
;
263 c
= get_char (cfile
);
264 if (!((c
== '\n') && cfile
->eol_token
) &&
265 isascii(c
) && isspace(c
)) {
266 ttok
= read_whitespace(c
, cfile
);
274 cfile
-> lexline
= l
;
275 cfile
-> lexchar
= p
;
276 ttok
= read_string (cfile
);
279 if ((isascii (c
) && isdigit (c
)) || c
== '-') {
280 cfile
-> lexline
= l
;
281 cfile
-> lexchar
= p
;
282 ttok
= read_number (c
, cfile
);
284 } else if (isascii (c
) && isalpha (c
)) {
285 cfile
-> lexline
= l
;
286 cfile
-> lexchar
= p
;
287 ttok
= read_num_or_name (c
, cfile
);
289 } else if (c
== EOF
) {
294 cfile
-> lexline
= l
;
295 cfile
-> lexchar
= p
;
308 * The get_next_token() function consumes the next token and
309 * returns it to the caller.
311 * Since the code is almost the same for "normal" and "raw"
312 * input, we pass a flag to alter the way it works.
315 static enum dhcp_token
316 get_next_token(const char **rval
, unsigned *rlen
,
317 struct parse
*cfile
, isc_boolean_t raw
) {
320 if (cfile
-> token
) {
321 if (cfile
-> lexline
!= cfile
-> tline
)
322 cfile
-> token_line
= cfile
-> cur_line
;
323 cfile
-> lexchar
= cfile
-> tlpos
;
324 cfile
-> lexline
= cfile
-> tline
;
328 rv
= get_raw_token(cfile
);
329 cfile
-> token_line
= cfile
-> cur_line
;
333 while (rv
== WHITESPACE
) {
334 rv
= get_raw_token(cfile
);
335 cfile
->token_line
= cfile
->cur_line
;
340 *rval
= cfile
-> tval
;
342 *rlen
= cfile
-> tlen
;
344 fprintf (stderr
, "%s:%d ", cfile
-> tval
, rv
);
351 * Get the next token from cfile and return it.
353 * If rval is non-NULL, set the pointer it contains to
354 * the contents of the token.
356 * If rlen is non-NULL, set the integer it contains to
357 * the length of the token.
361 next_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
362 return get_next_token(rval
, rlen
, cfile
, ISC_FALSE
);
367 * The same as the next_token() function above, but will return space
368 * as the WHITESPACE token.
372 next_raw_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
373 return get_next_token(rval
, rlen
, cfile
, ISC_TRUE
);
378 * The do_peek_token() function checks the next token without
379 * consuming it, and returns it to the caller.
381 * Since the code is almost the same for "normal" and "raw"
382 * input, we pass a flag to alter the way it works. (See the
383 * warning in the GENERAL NOTES ABOUT TOKENS above though.)
387 do_peek_token(const char **rval
, unsigned int *rlen
,
388 struct parse
*cfile
, isc_boolean_t raw
) {
391 if (!cfile
->token
|| (!raw
&& (cfile
->token
== WHITESPACE
))) {
392 cfile
-> tlpos
= cfile
-> lexchar
;
393 cfile
-> tline
= cfile
-> lexline
;
396 cfile
->token
= get_raw_token(cfile
);
397 } while (!raw
&& (cfile
->token
== WHITESPACE
));
399 if (cfile
-> lexline
!= cfile
-> tline
)
400 cfile
-> token_line
= cfile
-> prev_line
;
402 x
= cfile
-> lexchar
;
403 cfile
-> lexchar
= cfile
-> tlpos
;
406 x
= cfile
-> lexline
;
407 cfile
-> lexline
= cfile
-> tline
;
411 *rval
= cfile
-> tval
;
413 *rlen
= cfile
-> tlen
;
415 fprintf (stderr
, "(%s:%d) ", cfile
-> tval
, cfile
-> token
);
417 return cfile
-> token
;
422 * Get the next token from cfile and return it, leaving it for a
423 * subsequent call to next_token().
425 * Note that it WILL consume whitespace tokens.
427 * If rval is non-NULL, set the pointer it contains to
428 * the contents of the token.
430 * If rlen is non-NULL, set the integer it contains to
431 * the length of the token.
435 peek_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
436 return do_peek_token(rval
, rlen
, cfile
, ISC_FALSE
);
441 * The same as the peek_token() function above, but will return space
442 * as the WHITESPACE token.
446 peek_raw_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
447 return do_peek_token(rval
, rlen
, cfile
, ISC_TRUE
);
450 static void skip_to_eol (cfile
)
455 c
= get_char (cfile
);
464 static enum dhcp_token
465 read_whitespace(int c
, struct parse
*cfile
) {
469 * Read as much whitespace as we have available.
473 cfile
->tokbuf
[ofs
++] = c
;
475 } while (!((c
== '\n') && cfile
->eol_token
) &&
476 isascii(c
) && isspace(c
));
479 * Put the last (non-whitespace) character back.
481 unget_char(cfile
, c
);
486 cfile
->tokbuf
[ofs
] = '\0';
488 cfile
->tval
= cfile
->tokbuf
;
492 static enum dhcp_token
read_string (cfile
)
501 for (i
= 0; i
< sizeof cfile
-> tokbuf
; i
++) {
503 c
= get_char (cfile
);
505 parse_warn (cfile
, "eof in string constant");
511 cfile
-> tokbuf
[i
] = '\t';
514 cfile
-> tokbuf
[i
] = '\r';
517 cfile
-> tokbuf
[i
] = '\n';
520 cfile
-> tokbuf
[i
] = '\b';
536 cfile
-> tokbuf
[i
] = c
;
543 if (c
>= '0' && c
<= '9') {
544 value
= value
* 16 + (c
- '0');
545 } else if (c
>= 'a' && c
<= 'f') {
546 value
= value
* 16 + (c
- 'a' + 10);
547 } else if (c
>= 'A' && c
<= 'F') {
548 value
= value
* 16 + (c
- 'A' + 10);
551 "invalid hex digit: %x",
557 cfile
-> tokbuf
[i
] = value
;
562 if (c
>= '0' && c
<= '7') {
563 value
= value
* 8 + (c
- '0');
567 "invalid octal digit %x",
571 cfile
-> tokbuf
[i
] = 0;
575 cfile
-> tokbuf
[i
] = value
;
580 } else if (c
== '\\') {
586 cfile
-> tokbuf
[i
] = c
;
588 /* Normally, I'd feel guilty about this, but we're talking about
589 strings that'll fit in a DHCP packet here... */
590 if (i
== sizeof cfile
-> tokbuf
) {
592 "string constant larger than internal buffer");
595 cfile
-> tokbuf
[i
] = 0;
597 cfile
-> tval
= cfile
-> tokbuf
;
601 static enum dhcp_token
read_number (c
, cfile
)
608 cfile
-> tokbuf
[i
++] = c
;
609 for (; i
< sizeof cfile
-> tokbuf
; i
++) {
610 c
= get_char (cfile
);
612 /* Promote NUMBER -> NUMBER_OR_NAME -> NAME, never demote.
613 * Except in the case of '0x' syntax hex, which gets called
614 * a NAME at '0x', and returned to NUMBER_OR_NAME once it's
615 * verified to be at least 0xf or less.
617 switch(isascii(c
) ? token
: BREAK
) {
624 token
= NUMBER_OR_NAME
;
629 if((i
== 2) && isxdigit(c
) &&
630 (cfile
->tokbuf
[0] == '0') &&
631 ((cfile
->tokbuf
[1] == 'x') ||
632 (cfile
->tokbuf
[1] == 'X'))) {
633 token
= NUMBER_OR_NAME
;
635 } else if(((c
== '-') || (c
== '_') || isalnum(c
))) {
641 /* At this point c is either EOF or part of the next
642 * token. If not EOF, rewind the file one byte so
643 * the next token is read from there.
645 unget_char(cfile
, c
);
649 log_fatal("read_number():%s:%d: impossible case", MDL
);
652 cfile
-> tokbuf
[i
] = c
;
655 if (i
== sizeof cfile
-> tokbuf
) {
657 "numeric token larger than internal buffer");
662 cfile
-> tokbuf
[i
] = 0;
664 cfile
-> tval
= cfile
-> tokbuf
;
667 * If this entire token from start to finish was "-", such as
668 * the middle parameter in "42 - 7", return just the MINUS token.
670 if ((i
== 1) && (cfile
->tokbuf
[i
] == '-'))
676 static enum dhcp_token
read_num_or_name (c
, cfile
)
681 enum dhcp_token rv
= NUMBER_OR_NAME
;
682 cfile
-> tokbuf
[i
++] = c
;
683 for (; i
< sizeof cfile
-> tokbuf
; i
++) {
684 c
= get_char (cfile
);
686 (c
!= '-' && c
!= '_' && !isalnum (c
))) {
687 unget_char(cfile
, c
);
692 cfile
-> tokbuf
[i
] = c
;
694 if (i
== sizeof cfile
-> tokbuf
) {
695 parse_warn (cfile
, "token larger than internal buffer");
698 cfile
-> tokbuf
[i
] = 0;
700 cfile
-> tval
= cfile
-> tokbuf
;
701 return intern(cfile
->tval
, rv
);
704 static enum dhcp_token
705 intern(char *atom
, enum dhcp_token dfv
) {
706 if (!isascii(atom
[0]))
709 switch (tolower((unsigned char)atom
[0])) {
716 if (!strcasecmp(atom
+ 1, "bandoned"))
717 return TOKEN_ABANDONED
;
718 if (!strcasecmp(atom
+ 1, "ctive"))
720 if (!strncasecmp(atom
+ 1, "dd", 2)) {
723 else if (!strcasecmp(atom
+ 3, "ress"))
727 if (!strcasecmp(atom
+ 1, "fter"))
729 if (isascii(atom
[1]) &&
730 (tolower((unsigned char)atom
[1]) == 'l')) {
731 if (!strcasecmp(atom
+ 2, "gorithm"))
733 if (!strcasecmp(atom
+ 2, "ias"))
735 if (isascii(atom
[2]) &&
736 (tolower((unsigned char)atom
[2]) == 'l')) {
739 else if (!strcasecmp(atom
+ 3, "ow"))
743 if (!strcasecmp(atom
+ 2, "so"))
747 if (isascii(atom
[1]) &&
748 (tolower((unsigned char)atom
[1]) == 'n')) {
749 if (!strcasecmp(atom
+ 2, "d"))
751 if (!strcasecmp(atom
+ 2, "ycast-mac"))
755 if (!strcasecmp(atom
+ 1, "ppend"))
757 if (!strcasecmp(atom
+ 1, "rray"))
759 if (isascii(atom
[1]) &&
760 (tolower((unsigned char)atom
[1]) == 't')) {
763 if (!strcasecmp(atom
+ 2, "sfp"))
767 if (!strncasecmp(atom
+ 1, "ut", 2)) {
768 if (isascii(atom
[3]) &&
769 (tolower((unsigned char)atom
[3]) == 'h')) {
770 if (!strncasecmp(atom
+ 4, "enticat", 7)) {
771 if (!strcasecmp(atom
+ 11, "ed"))
772 return AUTHENTICATED
;
773 if (!strcasecmp(atom
+ 11, "ion"))
774 return AUTHENTICATION
;
777 if (!strcasecmp(atom
+ 4, "oritative"))
778 return AUTHORITATIVE
;
781 if (!strcasecmp(atom
+ 3, "o-partner-down"))
782 return AUTO_PARTNER_DOWN
;
787 if (!strcasecmp (atom
+ 1, "ackup"))
789 if (!strcasecmp (atom
+ 1, "ootp"))
791 if (!strcasecmp (atom
+ 1, "inding"))
793 if (!strcasecmp (atom
+ 1, "inary-to-ascii"))
794 return BINARY_TO_ASCII
;
795 if (!strcasecmp (atom
+ 1, "ackoff-cutoff"))
796 return BACKOFF_CUTOFF
;
797 if (!strcasecmp (atom
+ 1, "ooting"))
799 if (!strcasecmp (atom
+ 1, "oot-unknown-clients"))
800 return BOOT_UNKNOWN_CLIENTS
;
801 if (!strcasecmp (atom
+ 1, "reak"))
803 if (!strcasecmp (atom
+ 1, "illing"))
805 if (!strcasecmp (atom
+ 1, "oolean"))
807 if (!strcasecmp (atom
+ 1, "alance"))
809 if (!strcasecmp (atom
+ 1, "ound"))
813 if (!strcasecmp(atom
+ 1, "ase"))
815 if (!strcasecmp(atom
+ 1, "heck"))
817 if (!strcasecmp(atom
+ 1, "iaddr"))
819 if (isascii(atom
[1]) &&
820 tolower((unsigned char)atom
[1]) == 'l') {
821 if (!strcasecmp(atom
+ 2, "ass"))
823 if (!strncasecmp(atom
+ 2, "ient", 4)) {
824 if (!strcasecmp(atom
+ 6, "s"))
826 if (atom
[6] == '-') {
827 if (!strcasecmp(atom
+ 7, "hostname"))
828 return CLIENT_HOSTNAME
;
829 if (!strcasecmp(atom
+ 7, "identifier"))
830 return CLIENT_IDENTIFIER
;
831 if (!strcasecmp(atom
+ 7, "state"))
833 if (!strcasecmp(atom
+ 7, "updates"))
834 return CLIENT_UPDATES
;
839 if (!strcasecmp(atom
+ 2, "ose"))
841 if (!strcasecmp(atom
+ 2, "tt"))
845 if (isascii(atom
[1]) &&
846 tolower((unsigned char)atom
[1]) == 'o') {
847 if (!strcasecmp(atom
+ 2, "de"))
849 if (isascii(atom
[2]) &&
850 tolower((unsigned char)atom
[2]) == 'm') {
851 if (!strcasecmp(atom
+ 3, "mit"))
853 if (!strcasecmp(atom
+ 3,
854 "munications-interrupted"))
855 return COMMUNICATIONS_INTERRUPTED
;
856 if (!strcasecmp(atom
+ 3, "pressed"))
860 if (isascii(atom
[2]) &&
861 tolower((unsigned char)atom
[2]) == 'n') {
862 if (!strcasecmp(atom
+ 3, "cat"))
864 if (!strcasecmp(atom
+ 3, "fig-option"))
865 return CONFIG_OPTION
;
866 if (!strcasecmp(atom
+ 3, "flict-done"))
867 return CONFLICT_DONE
;
868 if (!strcasecmp(atom
+ 3, "nect"))
874 if (!strcasecmp(atom
+ 1, "reate"))
878 if (!strcasecmp(atom
+ 1, "b-time-format"))
879 return DB_TIME_FORMAT
;
880 if (!strcasecmp (atom
+ 1, "ns-update"))
882 if (!strcasecmp (atom
+ 1, "ns-delete"))
884 if (!strcasecmp (atom
+ 1, "omain"))
886 if (!strncasecmp (atom
+ 1, "omain-", 6)) {
887 if (!strcasecmp(atom
+ 7, "name"))
889 if (!strcasecmp(atom
+ 7, "list"))
892 if (!strcasecmp (atom
+ 1, "o-forward-update"))
893 return DO_FORWARD_UPDATE
;
894 if (!strcasecmp (atom
+ 1, "ebug"))
896 if (!strcasecmp (atom
+ 1, "eny"))
898 if (!strcasecmp (atom
+ 1, "eleted"))
899 return TOKEN_DELETED
;
900 if (!strcasecmp (atom
+ 1, "elete"))
902 if (!strncasecmp (atom
+ 1, "efault", 6)) {
905 if (!strcasecmp(atom
+ 7, "-duid"))
907 if (!strcasecmp (atom
+ 7, "-lease-time"))
908 return DEFAULT_LEASE_TIME
;
911 if (!strncasecmp (atom
+ 1, "ynamic", 6)) {
914 if (!strncasecmp (atom
+ 7, "-bootp", 6)) {
916 return DYNAMIC_BOOTP
;
917 if (!strcasecmp (atom
+ 13, "-lease-cutoff"))
918 return DYNAMIC_BOOTP_LEASE_CUTOFF
;
919 if (!strcasecmp (atom
+ 13, "-lease-length"))
920 return DYNAMIC_BOOTP_LEASE_LENGTH
;
924 if (!strcasecmp (atom
+ 1, "uplicates"))
926 if (!strcasecmp (atom
+ 1, "eclines"))
928 if (!strncasecmp (atom
+ 1, "efine", 5)) {
929 if (!strcasecmp (atom
+ 6, "d"))
936 if (isascii (atom
[1]) &&
937 tolower((unsigned char)atom
[1]) == 'x') {
938 if (!strcasecmp (atom
+ 2, "tract-int"))
940 if (!strcasecmp (atom
+ 2, "ists"))
942 if (!strcasecmp (atom
+ 2, "piry"))
944 if (!strcasecmp (atom
+ 2, "pire"))
946 if (!strcasecmp (atom
+ 2, "pired"))
947 return TOKEN_EXPIRED
;
949 if (!strcasecmp (atom
+ 1, "ncode-int"))
951 if (!strcasecmp(atom
+ 1, "poch"))
953 if (!strcasecmp (atom
+ 1, "thernet"))
955 if (!strcasecmp (atom
+ 1, "nds"))
957 if (!strncasecmp (atom
+ 1, "ls", 2)) {
958 if (!strcasecmp (atom
+ 3, "e"))
960 if (!strcasecmp (atom
+ 3, "if"))
964 if (!strcasecmp (atom
+ 1, "rror"))
966 if (!strcasecmp (atom
+ 1, "val"))
968 if (!strcasecmp (atom
+ 1, "ncapsulate"))
970 if (!strcasecmp(atom
+ 1, "xecute"))
972 if (!strcasecmp(atom
+1, "n")) {
977 if (!strcasecmp (atom
+ 1, "atal"))
979 if (!strcasecmp (atom
+ 1, "ilename"))
981 if (!strcasecmp (atom
+ 1, "ixed-address"))
983 if (!strcasecmp (atom
+ 1, "ixed-address6"))
985 if (!strcasecmp (atom
+ 1, "ixed-prefix6"))
986 return FIXED_PREFIX6
;
987 if (!strcasecmp (atom
+ 1, "ddi"))
989 if (!strcasecmp (atom
+ 1, "ormerr"))
991 if (!strcasecmp (atom
+ 1, "unction"))
993 if (!strcasecmp (atom
+ 1, "ailover"))
995 if (!strcasecmp (atom
+ 1, "ree"))
999 if (!strncasecmp(atom
+ 1, "et", 2)) {
1000 if (!strcasecmp(atom
+ 3, "-lease-hostnames"))
1001 return GET_LEASE_HOSTNAMES
;
1002 if (!strcasecmp(atom
+ 3, "hostbyname"))
1003 return GETHOSTBYNAME
;
1004 if (!strcasecmp(atom
+ 3, "hostname"))
1008 if (!strcasecmp (atom
+ 1, "iaddr"))
1010 if (!strcasecmp (atom
+ 1, "roup"))
1014 if (!strcasecmp(atom
+ 1, "ash"))
1016 if (!strcasecmp (atom
+ 1, "ba"))
1018 if (!strcasecmp (atom
+ 1, "ost"))
1020 if (!strcasecmp (atom
+ 1, "ost-decl-name"))
1021 return HOST_DECL_NAME
;
1022 if (!strcasecmp(atom
+ 1, "ost-identifier"))
1023 return HOST_IDENTIFIER
;
1024 if (!strcasecmp (atom
+ 1, "ardware"))
1026 if (!strcasecmp (atom
+ 1, "ostname"))
1028 if (!strcasecmp (atom
+ 1, "elp"))
1032 if (!strcasecmp(atom
+1, "a-na"))
1034 if (!strcasecmp(atom
+1, "a-ta"))
1036 if (!strcasecmp(atom
+1, "a-pd"))
1038 if (!strcasecmp(atom
+1, "aaddr"))
1040 if (!strcasecmp(atom
+1, "aprefix"))
1042 if (!strcasecmp (atom
+ 1, "nclude"))
1044 if (!strcasecmp (atom
+ 1, "nteger"))
1046 if (!strcasecmp (atom
+ 1, "nfinite"))
1048 if (!strcasecmp (atom
+ 1, "nfo"))
1050 if (!strcasecmp (atom
+ 1, "p-address"))
1052 if (!strcasecmp (atom
+ 1, "p6-address"))
1054 if (!strcasecmp (atom
+ 1, "nitial-interval"))
1055 return INITIAL_INTERVAL
;
1056 if (!strcasecmp (atom
+ 1, "nitial-delay"))
1057 return INITIAL_DELAY
;
1058 if (!strcasecmp (atom
+ 1, "nterface"))
1060 if (!strcasecmp (atom
+ 1, "dentifier"))
1062 if (!strcasecmp (atom
+ 1, "f"))
1064 if (!strcasecmp (atom
+ 1, "s"))
1066 if (!strcasecmp (atom
+ 1, "gnore"))
1070 if (!strncasecmp (atom
+ 1, "nown", 4)) {
1071 if (!strcasecmp (atom
+ 5, "-clients"))
1072 return KNOWN_CLIENTS
;
1077 if (!strcasecmp (atom
+ 1, "ey"))
1081 if (!strcasecmp (atom
+ 1, "case"))
1083 if (!strcasecmp (atom
+ 1, "ease"))
1085 if (!strcasecmp(atom
+ 1, "ease6"))
1087 if (!strcasecmp (atom
+ 1, "eased-address"))
1088 return LEASED_ADDRESS
;
1089 if (!strcasecmp (atom
+ 1, "ease-time"))
1091 if (!strcasecmp(atom
+ 1, "easequery"))
1093 if (!strcasecmp(atom
+ 1, "ength"))
1095 if (!strcasecmp (atom
+ 1, "imit"))
1097 if (!strcasecmp (atom
+ 1, "et"))
1099 if (!strcasecmp (atom
+ 1, "oad"))
1101 if (!strcasecmp(atom
+ 1, "ocal"))
1103 if (!strcasecmp (atom
+ 1, "og"))
1105 if (!strcasecmp(atom
+1, "lt")) {
1108 if (!strcasecmp(atom
+1, "l")) {
1113 if (!strncasecmp (atom
+ 1, "ax", 2)) {
1116 if (!strcasecmp (atom
+ 3, "-balance"))
1118 if (!strncasecmp (atom
+ 3, "-lease-", 7)) {
1119 if (!strcasecmp(atom
+ 10, "misbalance"))
1120 return MAX_LEASE_MISBALANCE
;
1121 if (!strcasecmp(atom
+ 10, "ownership"))
1122 return MAX_LEASE_OWNERSHIP
;
1123 if (!strcasecmp(atom
+ 10, "time"))
1124 return MAX_LEASE_TIME
;
1126 if (!strcasecmp(atom
+ 3, "-life"))
1128 if (!strcasecmp (atom
+ 3, "-transmit-idle"))
1129 return MAX_TRANSMIT_IDLE
;
1130 if (!strcasecmp (atom
+ 3, "-response-delay"))
1131 return MAX_RESPONSE_DELAY
;
1132 if (!strcasecmp (atom
+ 3, "-unacked-updates"))
1133 return MAX_UNACKED_UPDATES
;
1135 if (!strncasecmp (atom
+ 1, "in-", 3)) {
1136 if (!strcasecmp (atom
+ 4, "balance"))
1138 if (!strcasecmp (atom
+ 4, "lease-time"))
1139 return MIN_LEASE_TIME
;
1140 if (!strcasecmp (atom
+ 4, "secs"))
1144 if (!strncasecmp (atom
+ 1, "edi", 3)) {
1145 if (!strcasecmp (atom
+ 4, "a"))
1147 if (!strcasecmp (atom
+ 4, "um"))
1151 if (!strcasecmp (atom
+ 1, "atch"))
1153 if (!strcasecmp (atom
+ 1, "embers"))
1155 if (!strcasecmp (atom
+ 1, "y"))
1157 if (!strcasecmp (atom
+ 1, "clt"))
1161 if (!strcasecmp (atom
+ 1, "ormal"))
1163 if (!strcasecmp (atom
+ 1, "ameserver"))
1165 if (!strcasecmp (atom
+ 1, "etmask"))
1167 if (!strcasecmp (atom
+ 1, "ever"))
1169 if (!strcasecmp (atom
+ 1, "ext-server"))
1171 if (!strcasecmp (atom
+ 1, "ot"))
1173 if (!strcasecmp (atom
+ 1, "o"))
1175 if (!strcasecmp (atom
+ 1, "s-update"))
1177 if (!strcasecmp (atom
+ 1, "oerror"))
1179 if (!strcasecmp (atom
+ 1, "otauth"))
1181 if (!strcasecmp (atom
+ 1, "otimp"))
1183 if (!strcasecmp (atom
+ 1, "otzone"))
1185 if (!strcasecmp (atom
+ 1, "xdomain"))
1187 if (!strcasecmp (atom
+ 1, "xrrset"))
1189 if (!strcasecmp (atom
+ 1, "ull"))
1191 if (!strcasecmp (atom
+ 1, "ext"))
1193 if (!strcasecmp (atom
+ 1, "ew"))
1197 if (!strcasecmp (atom
+ 1, "mapi"))
1199 if (!strcasecmp (atom
+ 1, "r"))
1201 if (!strcasecmp (atom
+ 1, "n"))
1203 if (!strcasecmp (atom
+ 1, "pen"))
1205 if (!strcasecmp (atom
+ 1, "ption"))
1207 if (!strcasecmp (atom
+ 1, "ne-lease-per-client"))
1208 return ONE_LEASE_PER_CLIENT
;
1209 if (!strcasecmp (atom
+ 1, "f"))
1211 if (!strcasecmp (atom
+ 1, "wner"))
1215 if (!strcasecmp (atom
+ 1, "repend"))
1217 if (!strcasecmp(atom
+ 1, "referred-life"))
1218 return PREFERRED_LIFE
;
1219 if (!strcasecmp (atom
+ 1, "acket"))
1221 if (!strcasecmp (atom
+ 1, "ool"))
1223 if (!strcasecmp (atom
+ 1, "refix6"))
1225 if (!strcasecmp (atom
+ 1, "seudo"))
1227 if (!strcasecmp (atom
+ 1, "eer"))
1229 if (!strcasecmp (atom
+ 1, "rimary"))
1231 if (!strncasecmp (atom
+ 1, "artner", 6)) {
1234 if (!strcasecmp (atom
+ 7, "-down"))
1235 return PARTNER_DOWN
;
1237 if (!strcasecmp (atom
+ 1, "ort"))
1239 if (!strcasecmp (atom
+ 1, "otential-conflict"))
1240 return POTENTIAL_CONFLICT
;
1241 if (!strcasecmp (atom
+ 1, "ick-first-value") ||
1242 !strcasecmp (atom
+ 1, "ick"))
1244 if (!strcasecmp (atom
+ 1, "aused"))
1248 if (!strcasecmp(atom
+ 1, "ange"))
1250 if (!strcasecmp(atom
+ 1, "ange6"))
1252 if (isascii(atom
[1]) &&
1253 (tolower((unsigned char)atom
[1]) == 'e')) {
1254 if (!strcasecmp(atom
+ 2, "bind"))
1256 if (!strcasecmp(atom
+ 2, "boot"))
1258 if (!strcasecmp(atom
+ 2, "contact-interval"))
1259 return RECONTACT_INTERVAL
;
1260 if (!strncasecmp(atom
+ 2, "cover", 5)) {
1261 if (atom
[7] == '\0')
1263 if (!strcasecmp(atom
+ 7, "-done"))
1264 return RECOVER_DONE
;
1265 if (!strcasecmp(atom
+ 7, "-wait"))
1266 return RECOVER_WAIT
;
1269 if (!strcasecmp(atom
+ 2, "fresh"))
1271 if (!strcasecmp(atom
+ 2, "fused"))
1273 if (!strcasecmp(atom
+ 2, "ject"))
1275 if (!strcasecmp(atom
+ 2, "lease"))
1277 if (!strcasecmp(atom
+ 2, "leased"))
1278 return TOKEN_RELEASED
;
1279 if (!strcasecmp(atom
+ 2, "move"))
1281 if (!strcasecmp(atom
+ 2, "new"))
1283 if (!strcasecmp(atom
+ 2, "quest"))
1285 if (!strcasecmp(atom
+ 2, "quire"))
1287 if (isascii(atom
[2]) &&
1288 (tolower((unsigned char)atom
[2]) == 's')) {
1289 if (!strcasecmp(atom
+ 3, "erved"))
1290 return TOKEN_RESERVED
;
1291 if (!strcasecmp(atom
+ 3, "et"))
1293 if (!strcasecmp(atom
+ 3,
1294 "olution-interrupted"))
1295 return RESOLUTION_INTERRUPTED
;
1298 if (!strcasecmp(atom
+ 2, "try"))
1300 if (!strcasecmp(atom
+ 2, "turn"))
1302 if (!strcasecmp(atom
+ 2, "verse"))
1304 if (!strcasecmp(atom
+ 2, "wind"))
1310 if (!strcasecmp(atom
+ 1, "cript"))
1312 if (isascii(atom
[1]) &&
1313 tolower((unsigned char)atom
[1]) == 'e') {
1314 if (!strcasecmp(atom
+ 2, "arch"))
1316 if (isascii(atom
[2]) &&
1317 tolower((unsigned char)atom
[2]) == 'c') {
1318 if (!strncasecmp(atom
+ 3, "ond", 3)) {
1319 if (!strcasecmp(atom
+ 6, "ary"))
1321 if (!strcasecmp(atom
+ 6, "s"))
1325 if (!strcasecmp(atom
+ 3, "ret"))
1329 if (!strncasecmp(atom
+ 2, "lect", 4)) {
1330 if (atom
[6] == '\0')
1332 if (!strcasecmp(atom
+ 6, "-timeout"))
1333 return SELECT_TIMEOUT
;
1336 if (!strcasecmp(atom
+ 2, "nd"))
1338 if (!strncasecmp(atom
+ 2, "rv", 2)) {
1339 if (!strncasecmp(atom
+ 4, "er", 2)) {
1340 if (atom
[6] == '\0')
1341 return TOKEN_SERVER
;
1342 if (atom
[6] == '-') {
1343 if (!strcasecmp(atom
+ 7,
1346 if (!strcasecmp(atom
+ 7,
1349 if (!strcasecmp(atom
+ 7,
1351 return SERVER_IDENTIFIER
;
1356 if (!strcasecmp(atom
+ 4, "fail"))
1360 if (!strcasecmp(atom
+ 2, "t"))
1364 if (isascii(atom
[1]) &&
1365 tolower((unsigned char)atom
[1]) == 'h') {
1366 if (!strcasecmp(atom
+ 2, "ared-network"))
1367 return SHARED_NETWORK
;
1368 if (!strcasecmp(atom
+ 2, "utdown"))
1372 if (isascii(atom
[1]) &&
1373 tolower((unsigned char)atom
[1]) == 'i') {
1374 if (!strcasecmp(atom
+ 2, "addr"))
1376 if (!strcasecmp(atom
+ 2, "gned"))
1378 if (!strcasecmp(atom
+ 2, "ze"))
1382 if (isascii(atom
[1]) &&
1383 tolower((unsigned char)atom
[1]) == 'p') {
1384 if (isascii(atom
[2]) &&
1385 tolower((unsigned char)atom
[2]) == 'a') {
1386 if (!strcasecmp(atom
+ 3, "ce"))
1388 if (!strcasecmp(atom
+ 3, "wn"))
1392 if (!strcasecmp(atom
+ 2, "lit"))
1396 if (isascii(atom
[1]) &&
1397 tolower((unsigned char)atom
[1]) == 't') {
1398 if (isascii(atom
[2]) &&
1399 tolower((unsigned char)atom
[2]) == 'a') {
1400 if(!strncasecmp(atom
+ 3, "rt", 2)) {
1401 if (!strcasecmp(atom
+ 5, "s"))
1403 if (!strcasecmp(atom
+ 5, "up"))
1407 if (isascii(atom
[3]) &&
1408 tolower((unsigned char)atom
[3]) == 't') {
1409 if (!strcasecmp(atom
+ 4, "e"))
1411 if (!strcasecmp(atom
+ 4, "ic"))
1416 if (!strcasecmp(atom
+ 2, "ring"))
1417 return STRING_TOKEN
;
1420 if (!strncasecmp(atom
+ 1, "ub", 2)) {
1421 if (!strcasecmp(atom
+ 3, "class"))
1423 if (!strcasecmp(atom
+ 3, "net"))
1425 if (!strcasecmp(atom
+ 3, "net6"))
1427 if (!strcasecmp(atom
+ 3, "string"))
1431 if (isascii(atom
[1]) &&
1432 tolower((unsigned char)atom
[1]) == 'u') {
1433 if (!strcasecmp(atom
+ 2, "ffix"))
1435 if (!strcasecmp(atom
+ 2, "persede"))
1438 if (!strcasecmp(atom
+ 1, "witch"))
1442 if (!strcasecmp (atom
+ 1, "imestamp"))
1444 if (!strcasecmp (atom
+ 1, "imeout"))
1446 if (!strcasecmp (atom
+ 1, "oken-ring"))
1448 if (!strcasecmp (atom
+ 1, "ext"))
1450 if (!strcasecmp (atom
+ 1, "stp"))
1452 if (!strcasecmp (atom
+ 1, "sfp"))
1454 if (!strcasecmp (atom
+ 1, "ransmission"))
1455 return TRANSMISSION
;
1456 if (!strcasecmp(atom
+ 1, "emporary"))
1460 if (!strcasecmp (atom
+ 1, "case"))
1462 if (!strcasecmp (atom
+ 1, "nset"))
1464 if (!strcasecmp (atom
+ 1, "nsigned"))
1466 if (!strcasecmp (atom
+ 1, "id"))
1468 if (!strncasecmp (atom
+ 1, "se", 2)) {
1469 if (!strcasecmp (atom
+ 3, "r-class"))
1471 if (!strcasecmp (atom
+ 3, "-host-decl-names"))
1472 return USE_HOST_DECL_NAMES
;
1473 if (!strcasecmp (atom
+ 3,
1474 "-lease-addr-for-default-route"))
1475 return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE
;
1478 if (!strncasecmp (atom
+ 1, "nknown", 6)) {
1479 if (!strcasecmp (atom
+ 7, "-clients"))
1480 return UNKNOWN_CLIENTS
;
1481 if (!strcasecmp (atom
+ 7, "-state"))
1482 return UNKNOWN_STATE
;
1487 if (!strcasecmp (atom
+ 1, "nauthenticated"))
1488 return UNAUTHENTICATED
;
1489 if (!strcasecmp (atom
+ 1, "pdated-dns-rr"))
1490 return UPDATED_DNS_RR
;
1491 if (!strcasecmp (atom
+ 1, "pdate"))
1495 if (!strcasecmp (atom
+ 1, "endor-class"))
1496 return VENDOR_CLASS
;
1497 if (!strcasecmp (atom
+ 1, "endor"))
1501 if (!strcasecmp (atom
+ 1, "ith"))
1503 if (!strcasecmp(atom
+ 1, "idth"))
1507 if (!strcasecmp (atom
+ 1, "iaddr"))
1509 if (!strcasecmp (atom
+ 1, "xdomain"))
1511 if (!strcasecmp (atom
+ 1, "xrrset"))
1515 if (!strcasecmp (atom
+ 1, "erolen"))
1517 if (!strcasecmp (atom
+ 1, "one"))