3 Lexical scanner for dhcpd config file... */
6 * Copyright (c) 2004-2014 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/
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
);
41 isc_result_t
new_parse (cfile
, file
, inbuf
, buflen
, name
, eolp
)
49 isc_result_t status
= ISC_R_SUCCESS
;
52 tmp
= dmalloc(sizeof(struct parse
), MDL
);
54 return (ISC_R_NOMEMORY
);
58 * We don't need to initialize things to zero here, since
59 * dmalloc() returns memory that is set to zero.
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;
68 tmp
->eol_token
= eolp
;
77 if (fstat(file
, &sb
) < 0) {
78 status
= ISC_R_IOERROR
;
85 tmp
->bufsiz
= tmp
->buflen
= (size_t) sb
.st_size
;
86 tmp
->inbuf
= mmap(NULL
, tmp
->bufsiz
, PROT_READ
, MAP_SHARED
,
89 if (tmp
->inbuf
== MAP_FAILED
) {
90 status
= ISC_R_IOERROR
;
96 return (ISC_R_SUCCESS
);
103 isc_result_t
end_parse (cfile
)
104 struct parse
**cfile
;
106 /* "Memory" config files have no file. */
107 if ((*cfile
)->file
!= -1) {
108 munmap((*cfile
)->inbuf
, (*cfile
)->bufsiz
);
109 close((*cfile
)->file
);
112 if ((*cfile
)->saved_state
!= NULL
) {
113 dfree((*cfile
)->saved_state
, MDL
);
118 return ISC_R_SUCCESS
;
122 * Save the current state of the parser.
124 * Only one state may be saved. Any previous saved state is
128 save_parse_state(struct parse
*cfile
) {
130 * Free any previous saved state.
132 if (cfile
->saved_state
!= NULL
) {
133 dfree(cfile
->saved_state
, MDL
);
137 * Save our current state.
139 cfile
->saved_state
= dmalloc(sizeof(struct parse
), MDL
);
140 if (cfile
->saved_state
== NULL
) {
141 return ISC_R_NOMEMORY
;
143 memcpy(cfile
->saved_state
, cfile
, sizeof(*cfile
));
144 return ISC_R_SUCCESS
;
148 * Return the parser to the previous saved state.
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.
155 restore_parse_state(struct parse
*cfile
) {
156 struct parse
*saved_state
;
158 if (cfile
->saved_state
== NULL
) {
159 return DHCP_R_NOTYET
;
162 saved_state
= cfile
->saved_state
;
163 memcpy(cfile
, saved_state
, sizeof(*cfile
));
164 cfile
->saved_state
= saved_state
;
165 return ISC_R_SUCCESS
;
168 static int get_char (cfile
)
171 /* My kingdom for WITH... */
174 if (cfile
->bufix
== cfile
->buflen
) {
175 #if !defined(LDAP_CONFIGURATION)
177 #else /* defined(LDAP_CONFIGURATION) */
178 if (cfile
->read_function
!= NULL
)
179 c
= cfile
->read_function(cfile
);
184 c
= cfile
->inbuf
[cfile
->bufix
];
188 if (!cfile
->ugflag
) {
190 if (cfile
->cur_line
== cfile
->line1
) {
191 cfile
->cur_line
= cfile
->line2
;
192 cfile
->prev_line
= cfile
->line1
;
194 cfile
->cur_line
= cfile
->line1
;
195 cfile
->prev_line
= cfile
->line2
;
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;
213 * Return a character to our input buffer.
216 unget_char(struct parse
*cfile
, int c
) {
219 cfile
->ugflag
= 1; /* do not put characters into
220 our error buffer on the next
221 call to get_char() */
226 * GENERAL NOTE ABOUT TOKENS
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).
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.
236 * When we need to see whitespace, we us next_raw_token(), which also
237 * returns the WHITESPACE token.
239 * The peek_token() and peek_raw_token() functions work as expected.
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.
246 static enum dhcp_token
247 get_raw_token(struct parse
*cfile
) {
249 enum dhcp_token ttok
;
257 c
= get_char (cfile
);
258 if (!((c
== '\n') && cfile
->eol_token
) &&
259 isascii(c
) && isspace(c
)) {
260 ttok
= read_whitespace(c
, cfile
);
268 cfile
-> lexline
= l
;
269 cfile
-> lexchar
= p
;
270 ttok
= read_string (cfile
);
273 if ((isascii (c
) && isdigit (c
)) || c
== '-') {
274 cfile
-> lexline
= l
;
275 cfile
-> lexchar
= p
;
276 ttok
= read_number (c
, cfile
);
278 } else if (isascii (c
) && isalpha (c
)) {
279 cfile
-> lexline
= l
;
280 cfile
-> lexchar
= p
;
281 ttok
= read_num_or_name (c
, cfile
);
283 } else if (c
== EOF
) {
288 cfile
-> lexline
= l
;
289 cfile
-> lexchar
= p
;
302 * The get_next_token() function consumes the next token and
303 * returns it to the caller.
305 * Since the code is almost the same for "normal" and "raw"
306 * input, we pass a flag to alter the way it works.
309 static enum dhcp_token
310 get_next_token(const char **rval
, unsigned *rlen
,
311 struct parse
*cfile
, isc_boolean_t raw
) {
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
;
322 rv
= get_raw_token(cfile
);
323 cfile
-> token_line
= cfile
-> cur_line
;
327 while (rv
== WHITESPACE
) {
328 rv
= get_raw_token(cfile
);
329 cfile
->token_line
= cfile
->cur_line
;
334 *rval
= cfile
-> tval
;
336 *rlen
= cfile
-> tlen
;
338 fprintf (stderr
, "%s:%d ", cfile
-> tval
, rv
);
345 * Get the next token from cfile and return it.
347 * If rval is non-NULL, set the pointer it contains to
348 * the contents of the token.
350 * If rlen is non-NULL, set the integer it contains to
351 * the length of the token.
355 next_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
356 return get_next_token(rval
, rlen
, cfile
, ISC_FALSE
);
361 * The same as the next_token() function above, but will return space
362 * as the WHITESPACE token.
366 next_raw_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
367 return get_next_token(rval
, rlen
, cfile
, ISC_TRUE
);
372 * The do_peek_token() function checks the next token without
373 * consuming it, and returns it to the caller.
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.)
381 do_peek_token(const char **rval
, unsigned int *rlen
,
382 struct parse
*cfile
, isc_boolean_t raw
) {
385 if (!cfile
->token
|| (!raw
&& (cfile
->token
== WHITESPACE
))) {
386 cfile
-> tlpos
= cfile
-> lexchar
;
387 cfile
-> tline
= cfile
-> lexline
;
390 cfile
->token
= get_raw_token(cfile
);
391 } while (!raw
&& (cfile
->token
== WHITESPACE
));
393 if (cfile
-> lexline
!= cfile
-> tline
)
394 cfile
-> token_line
= cfile
-> prev_line
;
396 x
= cfile
-> lexchar
;
397 cfile
-> lexchar
= cfile
-> tlpos
;
400 x
= cfile
-> lexline
;
401 cfile
-> lexline
= cfile
-> tline
;
405 *rval
= cfile
-> tval
;
407 *rlen
= cfile
-> tlen
;
409 fprintf (stderr
, "(%s:%d) ", cfile
-> tval
, cfile
-> token
);
411 return cfile
-> token
;
416 * Get the next token from cfile and return it, leaving it for a
417 * subsequent call to next_token().
419 * Note that it WILL consume whitespace tokens.
421 * If rval is non-NULL, set the pointer it contains to
422 * the contents of the token.
424 * If rlen is non-NULL, set the integer it contains to
425 * the length of the token.
429 peek_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
430 return do_peek_token(rval
, rlen
, cfile
, ISC_FALSE
);
435 * The same as the peek_token() function above, but will return space
436 * as the WHITESPACE token.
440 peek_raw_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
441 return do_peek_token(rval
, rlen
, cfile
, ISC_TRUE
);
444 static void skip_to_eol (cfile
)
449 c
= get_char (cfile
);
458 static enum dhcp_token
459 read_whitespace(int c
, struct parse
*cfile
) {
463 * Read as much whitespace as we have available.
467 if (ofs
>= sizeof(cfile
->tokbuf
)) {
469 * As the file includes a huge amount of whitespace,
470 * it's probably broken.
471 * Print out a warning and bail out.
474 "whitespace too long, buffer overflow.");
475 log_fatal("Exiting");
477 cfile
->tokbuf
[ofs
++] = c
;
479 } while (!((c
== '\n') && cfile
->eol_token
) &&
480 isascii(c
) && isspace(c
));
483 * Put the last (non-whitespace) character back.
485 unget_char(cfile
, c
);
490 cfile
->tokbuf
[ofs
] = '\0';
492 cfile
->tval
= cfile
->tokbuf
;
496 static enum dhcp_token
read_string (cfile
)
505 for (i
= 0; i
< sizeof cfile
-> tokbuf
; i
++) {
507 c
= get_char (cfile
);
509 parse_warn (cfile
, "eof in string constant");
515 cfile
-> tokbuf
[i
] = '\t';
518 cfile
-> tokbuf
[i
] = '\r';
521 cfile
-> tokbuf
[i
] = '\n';
524 cfile
-> tokbuf
[i
] = '\b';
540 cfile
-> tokbuf
[i
] = c
;
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);
554 "invalid hex digit: %x",
560 cfile
-> tokbuf
[i
] = value
;
565 if (c
>= '0' && c
<= '7') {
566 value
= value
* 8 + (c
- '0');
570 "invalid octal digit %x",
574 cfile
-> tokbuf
[i
] = 0;
578 cfile
-> tokbuf
[i
] = value
;
583 } else if (c
== '\\') {
589 cfile
-> tokbuf
[i
] = c
;
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
) {
595 "string constant larger than internal buffer");
598 cfile
-> tokbuf
[i
] = 0;
600 cfile
-> tval
= cfile
-> tokbuf
;
604 static enum dhcp_token
read_number (c
, cfile
)
611 cfile
-> tokbuf
[i
++] = c
;
612 for (; i
< sizeof cfile
-> tokbuf
; i
++) {
613 c
= get_char (cfile
);
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.
620 switch(isascii(c
) ? token
: BREAK
) {
627 token
= NUMBER_OR_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
;
638 } else if(((c
== '-') || (c
== '_') || isalnum(c
))) {
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.
648 unget_char(cfile
, c
);
652 log_fatal("read_number():%s:%d: impossible case", MDL
);
655 cfile
-> tokbuf
[i
] = c
;
658 if (i
== sizeof cfile
-> tokbuf
) {
660 "numeric token larger than internal buffer");
665 cfile
-> tokbuf
[i
] = 0;
667 cfile
-> tval
= cfile
-> tokbuf
;
670 * If this entire token from start to finish was "-", such as
671 * the middle parameter in "42 - 7", return just the MINUS token.
673 if ((i
== 1) && (cfile
->tokbuf
[i
] == '-'))
679 static enum dhcp_token
read_num_or_name (c
, cfile
)
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
);
689 (c
!= '-' && c
!= '_' && !isalnum (c
))) {
690 unget_char(cfile
, c
);
695 cfile
-> tokbuf
[i
] = c
;
697 if (i
== sizeof cfile
-> tokbuf
) {
698 parse_warn (cfile
, "token larger than internal buffer");
701 cfile
-> tokbuf
[i
] = 0;
703 cfile
-> tval
= cfile
-> tokbuf
;
704 return intern(cfile
->tval
, rv
);
707 static enum dhcp_token
708 intern(char *atom
, enum dhcp_token dfv
) {
709 if (!isascii(atom
[0]))
712 switch (tolower((unsigned char)atom
[0])) {
719 if (!strcasecmp(atom
+ 1, "bandoned"))
720 return TOKEN_ABANDONED
;
721 if (!strcasecmp(atom
+ 1, "ctive"))
723 if (!strncasecmp(atom
+ 1, "dd", 2)) {
726 else if (!strcasecmp(atom
+ 3, "ress"))
730 if (!strcasecmp(atom
+ 1, "fter"))
732 if (isascii(atom
[1]) &&
733 (tolower((unsigned char)atom
[1]) == 'l')) {
734 if (!strcasecmp(atom
+ 2, "gorithm"))
736 if (!strcasecmp(atom
+ 2, "ias"))
738 if (isascii(atom
[2]) &&
739 (tolower((unsigned char)atom
[2]) == 'l')) {
742 else if (!strcasecmp(atom
+ 3, "ow"))
746 if (!strcasecmp(atom
+ 2, "so"))
750 if (isascii(atom
[1]) &&
751 (tolower((unsigned char)atom
[1]) == 'n')) {
752 if (!strcasecmp(atom
+ 2, "d"))
754 if (!strcasecmp(atom
+ 2, "ycast-mac"))
758 if (!strcasecmp(atom
+ 1, "ppend"))
760 if (!strcasecmp(atom
+ 1, "rray"))
762 if (isascii(atom
[1]) &&
763 (tolower((unsigned char)atom
[1]) == 't')) {
766 if (!strcasecmp(atom
+ 2, "sfp"))
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
;
780 if (!strcasecmp(atom
+ 4, "oritative"))
781 return AUTHORITATIVE
;
784 if (!strcasecmp(atom
+ 3, "o-partner-down"))
785 return AUTO_PARTNER_DOWN
;
790 if (!strcasecmp (atom
+ 1, "ackup"))
792 if (!strcasecmp (atom
+ 1, "ootp"))
794 if (!strcasecmp (atom
+ 1, "inding"))
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"))
802 if (!strcasecmp (atom
+ 1, "oot-unknown-clients"))
803 return BOOT_UNKNOWN_CLIENTS
;
804 if (!strcasecmp (atom
+ 1, "reak"))
806 if (!strcasecmp (atom
+ 1, "illing"))
808 if (!strcasecmp (atom
+ 1, "oolean"))
810 if (!strcasecmp (atom
+ 1, "alance"))
812 if (!strcasecmp (atom
+ 1, "ound"))
816 if (!strcasecmp(atom
+ 1, "ase"))
818 if (!strcasecmp(atom
+ 1, "heck"))
820 if (!strcasecmp(atom
+ 1, "iaddr"))
822 if (isascii(atom
[1]) &&
823 tolower((unsigned char)atom
[1]) == 'l') {
824 if (!strcasecmp(atom
+ 2, "ass"))
826 if (!strncasecmp(atom
+ 2, "ient", 4)) {
827 if (!strcasecmp(atom
+ 6, "s"))
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"))
836 if (!strcasecmp(atom
+ 7, "updates"))
837 return CLIENT_UPDATES
;
842 if (!strcasecmp(atom
+ 2, "ose"))
844 if (!strcasecmp(atom
+ 2, "tt"))
848 if (isascii(atom
[1]) &&
849 tolower((unsigned char)atom
[1]) == 'o') {
850 if (!strcasecmp(atom
+ 2, "de"))
852 if (isascii(atom
[2]) &&
853 tolower((unsigned char)atom
[2]) == 'm') {
854 if (!strcasecmp(atom
+ 3, "mit"))
856 if (!strcasecmp(atom
+ 3,
857 "munications-interrupted"))
858 return COMMUNICATIONS_INTERRUPTED
;
859 if (!strcasecmp(atom
+ 3, "pressed"))
863 if (isascii(atom
[2]) &&
864 tolower((unsigned char)atom
[2]) == 'n') {
865 if (!strcasecmp(atom
+ 3, "cat"))
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"))
877 if (!strcasecmp(atom
+ 1, "reate"))
881 if (!strcasecmp(atom
+ 1, "b-time-format"))
882 return DB_TIME_FORMAT
;
883 if (!strcasecmp (atom
+ 1, "omain"))
885 if (!strncasecmp (atom
+ 1, "omain-", 6)) {
886 if (!strcasecmp(atom
+ 7, "name"))
888 if (!strcasecmp(atom
+ 7, "list"))
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"))
898 if (!strcasecmp (atom
+ 1, "eny"))
900 if (!strcasecmp (atom
+ 1, "eleted"))
901 return TOKEN_DELETED
;
902 if (!strcasecmp (atom
+ 1, "elete"))
904 if (!strncasecmp (atom
+ 1, "efault", 6)) {
907 if (!strcasecmp(atom
+ 7, "-duid"))
909 if (!strcasecmp (atom
+ 7, "-lease-time"))
910 return DEFAULT_LEASE_TIME
;
913 if (!strncasecmp (atom
+ 1, "ynamic", 6)) {
916 if (!strncasecmp (atom
+ 7, "-bootp", 6)) {
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
;
926 if (!strcasecmp (atom
+ 1, "uplicates"))
928 if (!strcasecmp (atom
+ 1, "eclines"))
930 if (!strncasecmp (atom
+ 1, "efine", 5)) {
931 if (!strcasecmp (atom
+ 6, "d"))
938 if (isascii (atom
[1]) &&
939 tolower((unsigned char)atom
[1]) == 'x') {
940 if (!strcasecmp (atom
+ 2, "tract-int"))
942 if (!strcasecmp (atom
+ 2, "ists"))
944 if (!strcasecmp (atom
+ 2, "piry"))
946 if (!strcasecmp (atom
+ 2, "pire"))
948 if (!strcasecmp (atom
+ 2, "pired"))
949 return TOKEN_EXPIRED
;
951 if (!strcasecmp (atom
+ 1, "ncode-int"))
953 if (!strcasecmp(atom
+ 1, "poch"))
955 if (!strcasecmp (atom
+ 1, "thernet"))
957 if (!strcasecmp (atom
+ 1, "nds"))
959 if (!strncasecmp (atom
+ 1, "ls", 2)) {
960 if (!strcasecmp (atom
+ 3, "e"))
962 if (!strcasecmp (atom
+ 3, "if"))
966 if (!strcasecmp (atom
+ 1, "rror"))
968 if (!strcasecmp (atom
+ 1, "val"))
970 if (!strcasecmp (atom
+ 1, "ncapsulate"))
972 if (!strcasecmp(atom
+ 1, "xecute"))
974 if (!strcasecmp(atom
+1, "n")) {
979 if (!strcasecmp (atom
+ 1, "atal"))
981 if (!strcasecmp (atom
+ 1, "ilename"))
983 if (!strcasecmp (atom
+ 1, "ixed-address"))
985 if (!strcasecmp (atom
+ 1, "ixed-address6"))
987 if (!strcasecmp (atom
+ 1, "ixed-prefix6"))
988 return FIXED_PREFIX6
;
989 if (!strcasecmp (atom
+ 1, "ddi"))
991 if (!strcasecmp (atom
+ 1, "ormerr"))
993 if (!strcasecmp (atom
+ 1, "unction"))
995 if (!strcasecmp (atom
+ 1, "ailover"))
997 if (!strcasecmp (atom
+ 1, "ree"))
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"))
1010 if (!strcasecmp (atom
+ 1, "iaddr"))
1012 if (!strcasecmp (atom
+ 1, "roup"))
1016 if (!strcasecmp(atom
+ 1, "ash"))
1018 if (!strcasecmp (atom
+ 1, "ba"))
1020 if (!strcasecmp (atom
+ 1, "ost"))
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"))
1028 if (!strcasecmp (atom
+ 1, "ostname"))
1030 if (!strcasecmp (atom
+ 1, "elp"))
1034 if (!strcasecmp(atom
+1, "a-na"))
1036 if (!strcasecmp(atom
+1, "a-ta"))
1038 if (!strcasecmp(atom
+1, "a-pd"))
1040 if (!strcasecmp(atom
+1, "aaddr"))
1042 if (!strcasecmp(atom
+1, "aprefix"))
1044 if (!strcasecmp (atom
+ 1, "nclude"))
1046 if (!strcasecmp (atom
+ 1, "nteger"))
1048 if (!strcasecmp (atom
+ 1, "nfiniband"))
1049 return TOKEN_INFINIBAND
;
1050 if (!strcasecmp (atom
+ 1, "nfinite"))
1052 if (!strcasecmp (atom
+ 1, "nfo"))
1054 if (!strcasecmp (atom
+ 1, "p-address"))
1056 if (!strcasecmp (atom
+ 1, "p6-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"))
1064 if (!strcasecmp (atom
+ 1, "dentifier"))
1066 if (!strcasecmp (atom
+ 1, "f"))
1068 if (!strcasecmp (atom
+ 1, "s"))
1070 if (!strcasecmp (atom
+ 1, "gnore"))
1074 if (!strncasecmp (atom
+ 1, "nown", 4)) {
1075 if (!strcasecmp (atom
+ 5, "-clients"))
1076 return KNOWN_CLIENTS
;
1081 if (!strcasecmp (atom
+ 1, "ey"))
1085 if (!strcasecmp (atom
+ 1, "case"))
1087 if (!strcasecmp (atom
+ 1, "ease"))
1089 if (!strcasecmp(atom
+ 1, "ease6"))
1091 if (!strcasecmp (atom
+ 1, "eased-address"))
1092 return LEASED_ADDRESS
;
1093 if (!strcasecmp (atom
+ 1, "ease-time"))
1095 if (!strcasecmp(atom
+ 1, "easequery"))
1097 if (!strcasecmp(atom
+ 1, "ength"))
1099 if (!strcasecmp (atom
+ 1, "imit"))
1101 if (!strcasecmp (atom
+ 1, "et"))
1103 if (!strcasecmp (atom
+ 1, "oad"))
1105 if (!strcasecmp(atom
+ 1, "ocal"))
1107 if (!strcasecmp (atom
+ 1, "og"))
1109 if (!strcasecmp(atom
+1, "lt")) {
1112 if (!strcasecmp(atom
+1, "l")) {
1117 if (!strncasecmp (atom
+ 1, "ax", 2)) {
1120 if (!strcasecmp (atom
+ 3, "-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
;
1130 if (!strcasecmp(atom
+ 3, "-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
;
1139 if (!strncasecmp (atom
+ 1, "in-", 3)) {
1140 if (!strcasecmp (atom
+ 4, "balance"))
1142 if (!strcasecmp (atom
+ 4, "lease-time"))
1143 return MIN_LEASE_TIME
;
1144 if (!strcasecmp (atom
+ 4, "secs"))
1148 if (!strncasecmp (atom
+ 1, "edi", 3)) {
1149 if (!strcasecmp (atom
+ 4, "a"))
1151 if (!strcasecmp (atom
+ 4, "um"))
1155 if (!strcasecmp (atom
+ 1, "atch"))
1157 if (!strcasecmp (atom
+ 1, "embers"))
1159 if (!strcasecmp (atom
+ 1, "y"))
1161 if (!strcasecmp (atom
+ 1, "clt"))
1165 if (!strcasecmp (atom
+ 1, "ormal"))
1167 if (!strcasecmp (atom
+ 1, "ameserver"))
1169 if (!strcasecmp (atom
+ 1, "etmask"))
1171 if (!strcasecmp (atom
+ 1, "ever"))
1173 if (!strcasecmp (atom
+ 1, "ext-server"))
1175 if (!strcasecmp (atom
+ 1, "ot"))
1177 if (!strcasecmp (atom
+ 1, "o"))
1179 if (!strcasecmp (atom
+ 1, "oerror"))
1181 if (!strcasecmp (atom
+ 1, "otauth"))
1183 if (!strcasecmp (atom
+ 1, "otimp"))
1185 if (!strcasecmp (atom
+ 1, "otzone"))
1187 if (!strcasecmp (atom
+ 1, "xdomain"))
1189 if (!strcasecmp (atom
+ 1, "xrrset"))
1191 if (!strcasecmp (atom
+ 1, "ull"))
1193 if (!strcasecmp (atom
+ 1, "ext"))
1195 if (!strcasecmp (atom
+ 1, "ew"))
1199 if (!strcasecmp (atom
+ 1, "mapi"))
1201 if (!strcasecmp (atom
+ 1, "r"))
1203 if (!strcasecmp (atom
+ 1, "n"))
1205 if (!strcasecmp (atom
+ 1, "pen"))
1207 if (!strcasecmp (atom
+ 1, "ption"))
1209 if (!strcasecmp (atom
+ 1, "ne-lease-per-client"))
1210 return ONE_LEASE_PER_CLIENT
;
1211 if (!strcasecmp (atom
+ 1, "f"))
1213 if (!strcasecmp (atom
+ 1, "wner"))
1217 if (!strcasecmp (atom
+ 1, "repend"))
1219 if (!strcasecmp(atom
+ 1, "referred-life"))
1220 return PREFERRED_LIFE
;
1221 if (!strcasecmp (atom
+ 1, "acket"))
1223 if (!strcasecmp (atom
+ 1, "ool"))
1225 if (!strcasecmp (atom
+ 1, "ool6"))
1227 if (!strcasecmp (atom
+ 1, "refix6"))
1229 if (!strcasecmp (atom
+ 1, "seudo"))
1231 if (!strcasecmp (atom
+ 1, "eer"))
1233 if (!strcasecmp (atom
+ 1, "rimary"))
1235 if (!strcasecmp (atom
+ 1, "rimary6"))
1237 if (!strncasecmp (atom
+ 1, "artner", 6)) {
1240 if (!strcasecmp (atom
+ 7, "-down"))
1241 return PARTNER_DOWN
;
1243 if (!strcasecmp (atom
+ 1, "ort"))
1245 if (!strcasecmp (atom
+ 1, "otential-conflict"))
1246 return POTENTIAL_CONFLICT
;
1247 if (!strcasecmp (atom
+ 1, "ick-first-value") ||
1248 !strcasecmp (atom
+ 1, "ick"))
1250 if (!strcasecmp (atom
+ 1, "aused"))
1254 if (!strcasecmp(atom
+ 1, "ange"))
1256 if (!strcasecmp(atom
+ 1, "ange6"))
1258 if (isascii(atom
[1]) &&
1259 (tolower((unsigned char)atom
[1]) == 'e')) {
1260 if (!strcasecmp(atom
+ 2, "bind"))
1262 if (!strcasecmp(atom
+ 2, "boot"))
1264 if (!strcasecmp(atom
+ 2, "contact-interval"))
1265 return RECONTACT_INTERVAL
;
1266 if (!strncasecmp(atom
+ 2, "cover", 5)) {
1267 if (atom
[7] == '\0')
1269 if (!strcasecmp(atom
+ 7, "-done"))
1270 return RECOVER_DONE
;
1271 if (!strcasecmp(atom
+ 7, "-wait"))
1272 return RECOVER_WAIT
;
1275 if (!strcasecmp(atom
+ 2, "fresh"))
1277 if (!strcasecmp(atom
+ 2, "fused"))
1279 if (!strcasecmp(atom
+ 2, "ject"))
1281 if (!strcasecmp(atom
+ 2, "lease"))
1283 if (!strcasecmp(atom
+ 2, "leased"))
1284 return TOKEN_RELEASED
;
1285 if (!strcasecmp(atom
+ 2, "move"))
1287 if (!strcasecmp(atom
+ 2, "new"))
1289 if (!strcasecmp(atom
+ 2, "quest"))
1291 if (!strcasecmp(atom
+ 2, "quire"))
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"))
1299 if (!strcasecmp(atom
+ 3,
1300 "olution-interrupted"))
1301 return RESOLUTION_INTERRUPTED
;
1304 if (!strcasecmp(atom
+ 2, "try"))
1306 if (!strcasecmp(atom
+ 2, "turn"))
1308 if (!strcasecmp(atom
+ 2, "verse"))
1310 if (!strcasecmp(atom
+ 2, "wind"))
1316 if (!strcasecmp(atom
+ 1, "cript"))
1318 if (isascii(atom
[1]) &&
1319 tolower((unsigned char)atom
[1]) == 'e') {
1320 if (!strcasecmp(atom
+ 2, "arch"))
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"))
1327 if (!strcasecmp(atom
+ 6, "ary6"))
1329 if (!strcasecmp(atom
+ 6, "s"))
1333 if (!strcasecmp(atom
+ 3, "ret"))
1337 if (!strncasecmp(atom
+ 2, "lect", 4)) {
1338 if (atom
[6] == '\0')
1340 if (!strcasecmp(atom
+ 6, "-timeout"))
1341 return SELECT_TIMEOUT
;
1344 if (!strcasecmp(atom
+ 2, "nd"))
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,
1354 if (!strcasecmp(atom
+ 7,
1357 if (!strcasecmp(atom
+ 7,
1359 return SERVER_IDENTIFIER
;
1364 if (!strcasecmp(atom
+ 4, "fail"))
1368 if (!strcasecmp(atom
+ 2, "t"))
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"))
1380 if (isascii(atom
[1]) &&
1381 tolower((unsigned char)atom
[1]) == 'i') {
1382 if (!strcasecmp(atom
+ 2, "addr"))
1384 if (!strcasecmp(atom
+ 2, "gned"))
1386 if (!strcasecmp(atom
+ 2, "ze"))
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"))
1396 if (!strcasecmp(atom
+ 3, "wn"))
1400 if (!strcasecmp(atom
+ 2, "lit"))
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"))
1411 if (!strcasecmp(atom
+ 5, "up"))
1415 if (isascii(atom
[3]) &&
1416 tolower((unsigned char)atom
[3]) == 't') {
1417 if (!strcasecmp(atom
+ 4, "e"))
1419 if (!strcasecmp(atom
+ 4, "ic"))
1424 if (!strcasecmp(atom
+ 2, "ring"))
1425 return STRING_TOKEN
;
1428 if (!strncasecmp(atom
+ 1, "ub", 2)) {
1429 if (!strcasecmp(atom
+ 3, "class"))
1431 if (!strcasecmp(atom
+ 3, "net"))
1433 if (!strcasecmp(atom
+ 3, "net6"))
1435 if (!strcasecmp(atom
+ 3, "string"))
1439 if (isascii(atom
[1]) &&
1440 tolower((unsigned char)atom
[1]) == 'u') {
1441 if (!strcasecmp(atom
+ 2, "ffix"))
1443 if (!strcasecmp(atom
+ 2, "persede"))
1446 if (!strcasecmp(atom
+ 1, "witch"))
1450 if (!strcasecmp (atom
+ 1, "imestamp"))
1452 if (!strcasecmp (atom
+ 1, "imeout"))
1454 if (!strcasecmp (atom
+ 1, "oken-ring"))
1456 if (!strcasecmp (atom
+ 1, "ext"))
1458 if (!strcasecmp (atom
+ 1, "stp"))
1460 if (!strcasecmp (atom
+ 1, "sfp"))
1462 if (!strcasecmp (atom
+ 1, "ransmission"))
1463 return TRANSMISSION
;
1464 if (!strcasecmp(atom
+ 1, "emporary"))
1468 if (!strcasecmp (atom
+ 1, "case"))
1470 if (!strcasecmp (atom
+ 1, "nset"))
1472 if (!strcasecmp (atom
+ 1, "nsigned"))
1474 if (!strcasecmp (atom
+ 1, "id"))
1476 if (!strncasecmp (atom
+ 1, "se", 2)) {
1477 if (!strcasecmp (atom
+ 3, "r-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
;
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
;
1495 if (!strcasecmp (atom
+ 1, "nauthenticated"))
1496 return UNAUTHENTICATED
;
1497 if (!strcasecmp (atom
+ 1, "pdate"))
1501 if (!strcasecmp (atom
+ 1, "6relay"))
1503 if (!strcasecmp (atom
+ 1, "6relopt"))
1505 if (!strcasecmp (atom
+ 1, "endor-class"))
1506 return VENDOR_CLASS
;
1507 if (!strcasecmp (atom
+ 1, "endor"))
1511 if (!strcasecmp (atom
+ 1, "ith"))
1513 if (!strcasecmp(atom
+ 1, "idth"))
1517 if (!strcasecmp (atom
+ 1, "iaddr"))
1519 if (!strcasecmp (atom
+ 1, "xdomain"))
1521 if (!strcasecmp (atom
+ 1, "xrrset"))
1525 if (!strcasecmp (atom
+ 1, "erolen"))
1527 if (!strcasecmp (atom
+ 1, "one"))