1 /* $NetBSD: conflex.c,v 1.4 2014/07/12 12:09:37 spz Exp $ */
4 Lexical scanner for dhcpd config file... */
7 * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1995-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: conflex.c,v 1.4 2014/07/12 12:09:37 spz Exp $");
36 static int get_char (struct parse
*);
37 static void unget_char(struct parse
*, int);
38 static void skip_to_eol (struct parse
*);
39 static enum dhcp_token
read_whitespace(int c
, struct parse
*cfile
);
40 static enum dhcp_token
read_string (struct parse
*);
41 static enum dhcp_token
read_number (int, struct parse
*);
42 static enum dhcp_token
read_num_or_name (int, struct parse
*);
43 static enum dhcp_token
intern (char *, enum dhcp_token
);
45 isc_result_t
new_parse (cfile
, file
, inbuf
, buflen
, name
, eolp
)
53 isc_result_t status
= ISC_R_SUCCESS
;
56 tmp
= dmalloc(sizeof(struct parse
), MDL
);
58 return (ISC_R_NOMEMORY
);
62 * We don't need to initialize things to zero here, since
63 * dmalloc() returns memory that is set to zero.
66 tmp
->lpos
= tmp
-> line
= 1;
67 tmp
->cur_line
= tmp
->line1
;
68 tmp
->prev_line
= tmp
->line2
;
69 tmp
->token_line
= tmp
->cur_line
;
70 tmp
->cur_line
[0] = tmp
->prev_line
[0] = 0;
72 tmp
->eol_token
= eolp
;
81 if (fstat(file
, &sb
) < 0) {
82 status
= ISC_R_IOERROR
;
89 tmp
->bufsiz
= tmp
->buflen
= (size_t) sb
.st_size
;
90 tmp
->inbuf
= mmap(NULL
, tmp
->bufsiz
, PROT_READ
, MAP_SHARED
,
93 if (tmp
->inbuf
== MAP_FAILED
) {
94 status
= ISC_R_IOERROR
;
100 return (ISC_R_SUCCESS
);
107 isc_result_t
end_parse (cfile
)
108 struct parse
**cfile
;
110 /* "Memory" config files have no file. */
111 if ((*cfile
)->file
!= -1) {
112 munmap((*cfile
)->inbuf
, (*cfile
)->bufsiz
);
113 close((*cfile
)->file
);
116 if ((*cfile
)->saved_state
!= NULL
) {
117 dfree((*cfile
)->saved_state
, MDL
);
122 return ISC_R_SUCCESS
;
126 * Save the current state of the parser.
128 * Only one state may be saved. Any previous saved state is
132 save_parse_state(struct parse
*cfile
) {
134 * Free any previous saved state.
136 if (cfile
->saved_state
!= NULL
) {
137 dfree(cfile
->saved_state
, MDL
);
141 * Save our current state.
143 cfile
->saved_state
= dmalloc(sizeof(struct parse
), MDL
);
144 if (cfile
->saved_state
== NULL
) {
145 return ISC_R_NOMEMORY
;
147 memcpy(cfile
->saved_state
, cfile
, sizeof(*cfile
));
148 return ISC_R_SUCCESS
;
152 * Return the parser to the previous saved state.
154 * You must call save_parse_state() before calling
155 * restore_parse_state(), but you can call restore_parse_state() any
156 * number of times after that.
159 restore_parse_state(struct parse
*cfile
) {
160 struct parse
*saved_state
;
162 if (cfile
->saved_state
== NULL
) {
163 return DHCP_R_NOTYET
;
166 saved_state
= cfile
->saved_state
;
167 memcpy(cfile
, saved_state
, sizeof(*cfile
));
168 cfile
->saved_state
= saved_state
;
169 return ISC_R_SUCCESS
;
172 static int get_char (cfile
)
175 /* My kingdom for WITH... */
178 if (cfile
->bufix
== cfile
->buflen
) {
179 #if !defined(LDAP_CONFIGURATION)
181 #else /* defined(LDAP_CONFIGURATION) */
182 if (cfile
->read_function
!= NULL
)
183 c
= cfile
->read_function(cfile
);
188 c
= cfile
->inbuf
[cfile
->bufix
];
192 if (!cfile
->ugflag
) {
194 if (cfile
->cur_line
== cfile
->line1
) {
195 cfile
->cur_line
= cfile
->line2
;
196 cfile
->prev_line
= cfile
->line1
;
198 cfile
->cur_line
= cfile
->line1
;
199 cfile
->prev_line
= cfile
->line2
;
203 cfile
->cur_line
[0] = 0;
204 } else if (c
!= EOF
) {
205 if (cfile
->lpos
<= 80) {
206 cfile
->cur_line
[cfile
->lpos
- 1] = c
;
207 cfile
->cur_line
[cfile
->lpos
] = 0;
217 * Return a character to our input buffer.
220 unget_char(struct parse
*cfile
, int c
) {
223 cfile
->ugflag
= 1; /* do not put characters into
224 our error buffer on the next
225 call to get_char() */
230 * GENERAL NOTE ABOUT TOKENS
232 * We normally only want non-whitespace tokens. There are some
233 * circumstances where we *do* want to see whitespace (for example
234 * when parsing IPv6 addresses).
236 * Generally we use the next_token() function to read tokens. This
237 * in turn calls get_next_token, which does *not* return tokens for
238 * whitespace. Rather, it skips these.
240 * When we need to see whitespace, we us next_raw_token(), which also
241 * returns the WHITESPACE token.
243 * The peek_token() and peek_raw_token() functions work as expected.
245 * Warning: if you invoke peek_token(), then if there is a whitespace
246 * token, it will be lost, and subsequent use of next_raw_token() or
247 * peek_raw_token() will NOT see it.
250 static enum dhcp_token
251 get_raw_token(struct parse
*cfile
) {
253 enum dhcp_token ttok
;
261 c
= get_char (cfile
);
262 if (!((c
== '\n') && cfile
->eol_token
) &&
263 isascii(c
) && isspace(c
)) {
264 ttok
= read_whitespace(c
, cfile
);
272 cfile
-> lexline
= l
;
273 cfile
-> lexchar
= p
;
274 ttok
= read_string (cfile
);
277 if ((isascii (c
) && isdigit (c
)) || c
== '-') {
278 cfile
-> lexline
= l
;
279 cfile
-> lexchar
= p
;
280 ttok
= read_number (c
, cfile
);
282 } else if (isascii (c
) && isalpha (c
)) {
283 cfile
-> lexline
= l
;
284 cfile
-> lexchar
= p
;
285 ttok
= read_num_or_name (c
, cfile
);
287 } else if (c
== EOF
) {
292 cfile
-> lexline
= l
;
293 cfile
-> lexchar
= p
;
306 * The get_next_token() function consumes the next token and
307 * returns it to the caller.
309 * Since the code is almost the same for "normal" and "raw"
310 * input, we pass a flag to alter the way it works.
313 static enum dhcp_token
314 get_next_token(const char **rval
, unsigned *rlen
,
315 struct parse
*cfile
, isc_boolean_t raw
) {
318 if (cfile
-> token
) {
319 if (cfile
-> lexline
!= cfile
-> tline
)
320 cfile
-> token_line
= cfile
-> cur_line
;
321 cfile
-> lexchar
= cfile
-> tlpos
;
322 cfile
-> lexline
= cfile
-> tline
;
326 rv
= get_raw_token(cfile
);
327 cfile
-> token_line
= cfile
-> cur_line
;
331 while (rv
== WHITESPACE
) {
332 rv
= get_raw_token(cfile
);
333 cfile
->token_line
= cfile
->cur_line
;
338 *rval
= cfile
-> tval
;
340 *rlen
= cfile
-> tlen
;
342 fprintf (stderr
, "%s:%d ", cfile
-> tval
, rv
);
349 * Get the next token from cfile and return it.
351 * If rval is non-NULL, set the pointer it contains to
352 * the contents of the token.
354 * If rlen is non-NULL, set the integer it contains to
355 * the length of the token.
359 next_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
360 return get_next_token(rval
, rlen
, cfile
, ISC_FALSE
);
365 * The same as the next_token() function above, but will return space
366 * as the WHITESPACE token.
370 next_raw_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
371 return get_next_token(rval
, rlen
, cfile
, ISC_TRUE
);
376 * The do_peek_token() function checks the next token without
377 * consuming it, and returns it to the caller.
379 * Since the code is almost the same for "normal" and "raw"
380 * input, we pass a flag to alter the way it works. (See the
381 * warning in the GENERAL NOTES ABOUT TOKENS above though.)
384 static enum dhcp_token
385 do_peek_token(const char **rval
, unsigned int *rlen
,
386 struct parse
*cfile
, isc_boolean_t raw
) {
389 if (!cfile
->token
|| (!raw
&& (cfile
->token
== WHITESPACE
))) {
390 cfile
-> tlpos
= cfile
-> lexchar
;
391 cfile
-> tline
= cfile
-> lexline
;
394 cfile
->token
= get_raw_token(cfile
);
395 } while (!raw
&& (cfile
->token
== WHITESPACE
));
397 if (cfile
-> lexline
!= cfile
-> tline
)
398 cfile
-> token_line
= cfile
-> prev_line
;
400 x
= cfile
-> lexchar
;
401 cfile
-> lexchar
= cfile
-> tlpos
;
404 x
= cfile
-> lexline
;
405 cfile
-> lexline
= cfile
-> tline
;
409 *rval
= cfile
-> tval
;
411 *rlen
= cfile
-> tlen
;
413 fprintf (stderr
, "(%s:%d) ", cfile
-> tval
, cfile
-> token
);
415 return cfile
-> token
;
420 * Get the next token from cfile and return it, leaving it for a
421 * subsequent call to next_token().
423 * Note that it WILL consume whitespace tokens.
425 * If rval is non-NULL, set the pointer it contains to
426 * the contents of the token.
428 * If rlen is non-NULL, set the integer it contains to
429 * the length of the token.
433 peek_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
434 return do_peek_token(rval
, rlen
, cfile
, ISC_FALSE
);
439 * The same as the peek_token() function above, but will return space
440 * as the WHITESPACE token.
444 peek_raw_token(const char **rval
, unsigned *rlen
, struct parse
*cfile
) {
445 return do_peek_token(rval
, rlen
, cfile
, ISC_TRUE
);
448 static void skip_to_eol (cfile
)
453 c
= get_char (cfile
);
462 static enum dhcp_token
463 read_whitespace(int c
, struct parse
*cfile
) {
467 * Read as much whitespace as we have available.
471 if (ofs
>= sizeof(cfile
->tokbuf
)) {
473 * As the file includes a huge amount of whitespace,
474 * it's probably broken.
475 * Print out a warning and bail out.
478 "whitespace too long, buffer overflow.");
479 log_fatal("Exiting");
481 cfile
->tokbuf
[ofs
++] = c
;
483 } while (!((c
== '\n') && cfile
->eol_token
) &&
484 isascii(c
) && isspace(c
));
487 * Put the last (non-whitespace) character back.
489 unget_char(cfile
, c
);
494 cfile
->tokbuf
[ofs
] = '\0';
496 cfile
->tval
= cfile
->tokbuf
;
500 static enum dhcp_token
read_string (cfile
)
509 for (i
= 0; i
< sizeof cfile
-> tokbuf
; i
++) {
511 c
= get_char (cfile
);
513 parse_warn (cfile
, "eof in string constant");
519 cfile
-> tokbuf
[i
] = '\t';
522 cfile
-> tokbuf
[i
] = '\r';
525 cfile
-> tokbuf
[i
] = '\n';
528 cfile
-> tokbuf
[i
] = '\b';
544 cfile
-> tokbuf
[i
] = c
;
550 if (c
>= '0' && c
<= '9') {
551 value
= value
* 16 + (c
- '0');
552 } else if (c
>= 'a' && c
<= 'f') {
553 value
= value
* 16 + (c
- 'a' + 10);
554 } else if (c
>= 'A' && c
<= 'F') {
555 value
= value
* 16 + (c
- 'A' + 10);
558 "invalid hex digit: %x",
564 cfile
-> tokbuf
[i
] = value
;
569 if (c
>= '0' && c
<= '7') {
570 value
= value
* 8 + (c
- '0');
574 "invalid octal digit %x",
578 cfile
-> tokbuf
[i
] = 0;
582 cfile
-> tokbuf
[i
] = value
;
587 } else if (c
== '\\') {
593 cfile
-> tokbuf
[i
] = c
;
595 /* Normally, I'd feel guilty about this, but we're talking about
596 strings that'll fit in a DHCP packet here... */
597 if (i
== sizeof cfile
-> tokbuf
) {
599 "string constant larger than internal buffer");
602 cfile
-> tokbuf
[i
] = 0;
604 cfile
-> tval
= cfile
-> tokbuf
;
608 static enum dhcp_token
read_number (c
, cfile
)
615 cfile
-> tokbuf
[i
++] = c
;
616 for (; i
< sizeof cfile
-> tokbuf
; i
++) {
617 c
= get_char (cfile
);
619 /* Promote NUMBER -> NUMBER_OR_NAME -> NAME, never demote.
620 * Except in the case of '0x' syntax hex, which gets called
621 * a NAME at '0x', and returned to NUMBER_OR_NAME once it's
622 * verified to be at least 0xf or less.
624 switch(isascii(c
) ? token
: BREAK
) {
631 token
= NUMBER_OR_NAME
;
636 if((i
== 2) && isxdigit(c
) &&
637 (cfile
->tokbuf
[0] == '0') &&
638 ((cfile
->tokbuf
[1] == 'x') ||
639 (cfile
->tokbuf
[1] == 'X'))) {
640 token
= NUMBER_OR_NAME
;
642 } else if(((c
== '-') || (c
== '_') || isalnum(c
))) {
648 /* At this point c is either EOF or part of the next
649 * token. If not EOF, rewind the file one byte so
650 * the next token is read from there.
652 unget_char(cfile
, c
);
656 log_fatal("read_number():%s:%d: impossible case", MDL
);
659 cfile
-> tokbuf
[i
] = c
;
662 if (i
== sizeof cfile
-> tokbuf
) {
664 "numeric token larger than internal buffer");
669 cfile
-> tokbuf
[i
] = 0;
671 cfile
-> tval
= cfile
-> tokbuf
;
674 * If this entire token from start to finish was "-", such as
675 * the middle parameter in "42 - 7", return just the MINUS token.
677 if ((i
== 1) && (cfile
->tokbuf
[i
] == '-'))
683 static enum dhcp_token
read_num_or_name (c
, cfile
)
688 enum dhcp_token rv
= NUMBER_OR_NAME
;
689 cfile
-> tokbuf
[i
++] = c
;
690 for (; i
< sizeof cfile
-> tokbuf
; i
++) {
691 c
= get_char (cfile
);
693 (c
!= '-' && c
!= '_' && !isalnum (c
))) {
694 unget_char(cfile
, c
);
699 cfile
-> tokbuf
[i
] = c
;
701 if (i
== sizeof cfile
-> tokbuf
) {
702 parse_warn (cfile
, "token larger than internal buffer");
705 cfile
-> tokbuf
[i
] = 0;
707 cfile
-> tval
= cfile
-> tokbuf
;
708 return intern(cfile
->tval
, rv
);
711 static enum dhcp_token
712 intern(char *atom
, enum dhcp_token dfv
) {
713 if (!isascii(atom
[0]))
716 switch (tolower((unsigned char)atom
[0])) {
723 if (!strcasecmp(atom
+ 1, "bandoned"))
724 return TOKEN_ABANDONED
;
725 if (!strcasecmp(atom
+ 1, "ctive"))
727 if (!strncasecmp(atom
+ 1, "dd", 2)) {
730 else if (!strcasecmp(atom
+ 3, "ress"))
734 if (!strcasecmp(atom
+ 1, "fter"))
736 if (isascii(atom
[1]) &&
737 (tolower((unsigned char)atom
[1]) == 'l')) {
738 if (!strcasecmp(atom
+ 2, "gorithm"))
740 if (!strcasecmp(atom
+ 2, "ias"))
742 if (isascii(atom
[2]) &&
743 (tolower((unsigned char)atom
[2]) == 'l')) {
746 else if (!strcasecmp(atom
+ 3, "ow"))
750 if (!strcasecmp(atom
+ 2, "so"))
754 if (isascii(atom
[1]) &&
755 (tolower((unsigned char)atom
[1]) == 'n')) {
756 if (!strcasecmp(atom
+ 2, "d"))
758 if (!strcasecmp(atom
+ 2, "ycast-mac"))
762 if (!strcasecmp(atom
+ 1, "ppend"))
764 if (!strcasecmp(atom
+ 1, "rray"))
766 if (isascii(atom
[1]) &&
767 (tolower((unsigned char)atom
[1]) == 't')) {
770 if (!strcasecmp(atom
+ 2, "sfp"))
774 if (!strncasecmp(atom
+ 1, "ut", 2)) {
775 if (isascii(atom
[3]) &&
776 (tolower((unsigned char)atom
[3]) == 'h')) {
777 if (!strncasecmp(atom
+ 4, "enticat", 7)) {
778 if (!strcasecmp(atom
+ 11, "ed"))
779 return AUTHENTICATED
;
780 if (!strcasecmp(atom
+ 11, "ion"))
781 return AUTHENTICATION
;
784 if (!strcasecmp(atom
+ 4, "oritative"))
785 return AUTHORITATIVE
;
788 if (!strcasecmp(atom
+ 3, "o-partner-down"))
789 return AUTO_PARTNER_DOWN
;
794 if (!strcasecmp (atom
+ 1, "ackup"))
796 if (!strcasecmp (atom
+ 1, "ootp"))
798 if (!strcasecmp (atom
+ 1, "inding"))
800 if (!strcasecmp (atom
+ 1, "inary-to-ascii"))
801 return BINARY_TO_ASCII
;
802 if (!strcasecmp (atom
+ 1, "ackoff-cutoff"))
803 return BACKOFF_CUTOFF
;
804 if (!strcasecmp (atom
+ 1, "ooting"))
806 if (!strcasecmp (atom
+ 1, "oot-unknown-clients"))
807 return BOOT_UNKNOWN_CLIENTS
;
808 if (!strcasecmp (atom
+ 1, "reak"))
810 if (!strcasecmp (atom
+ 1, "illing"))
812 if (!strcasecmp (atom
+ 1, "oolean"))
814 if (!strcasecmp (atom
+ 1, "alance"))
816 if (!strcasecmp (atom
+ 1, "ound"))
820 if (!strcasecmp(atom
+ 1, "ase"))
822 if (!strcasecmp(atom
+ 1, "heck"))
824 if (!strcasecmp(atom
+ 1, "iaddr"))
826 if (isascii(atom
[1]) &&
827 tolower((unsigned char)atom
[1]) == 'l') {
828 if (!strcasecmp(atom
+ 2, "ass"))
830 if (!strncasecmp(atom
+ 2, "ient", 4)) {
831 if (!strcasecmp(atom
+ 6, "s"))
833 if (atom
[6] == '-') {
834 if (!strcasecmp(atom
+ 7, "hostname"))
835 return CLIENT_HOSTNAME
;
836 if (!strcasecmp(atom
+ 7, "identifier"))
837 return CLIENT_IDENTIFIER
;
838 if (!strcasecmp(atom
+ 7, "state"))
840 if (!strcasecmp(atom
+ 7, "updates"))
841 return CLIENT_UPDATES
;
846 if (!strcasecmp(atom
+ 2, "ose"))
848 if (!strcasecmp(atom
+ 2, "tt"))
852 if (isascii(atom
[1]) &&
853 tolower((unsigned char)atom
[1]) == 'o') {
854 if (!strcasecmp(atom
+ 2, "de"))
856 if (isascii(atom
[2]) &&
857 tolower((unsigned char)atom
[2]) == 'm') {
858 if (!strcasecmp(atom
+ 3, "mit"))
860 if (!strcasecmp(atom
+ 3,
861 "munications-interrupted"))
862 return COMMUNICATIONS_INTERRUPTED
;
863 if (!strcasecmp(atom
+ 3, "pressed"))
867 if (isascii(atom
[2]) &&
868 tolower((unsigned char)atom
[2]) == 'n') {
869 if (!strcasecmp(atom
+ 3, "cat"))
871 if (!strcasecmp(atom
+ 3, "fig-option"))
872 return CONFIG_OPTION
;
873 if (!strcasecmp(atom
+ 3, "flict-done"))
874 return CONFLICT_DONE
;
875 if (!strcasecmp(atom
+ 3, "nect"))
881 if (!strcasecmp(atom
+ 1, "reate"))
885 if (!strcasecmp(atom
+ 1, "b-time-format"))
886 return DB_TIME_FORMAT
;
887 if (!strcasecmp (atom
+ 1, "omain"))
889 if (!strncasecmp (atom
+ 1, "omain-", 6)) {
890 if (!strcasecmp(atom
+ 7, "name"))
892 if (!strcasecmp(atom
+ 7, "list"))
895 if (!strcasecmp (atom
+ 1, "o-forward-update"))
896 return DO_FORWARD_UPDATE
;
897 if (!strcasecmp (atom
+ 1, "ebug"))
899 if (!strcasecmp (atom
+ 1, "eny"))
901 if (!strcasecmp (atom
+ 1, "eleted"))
902 return TOKEN_DELETED
;
903 if (!strcasecmp (atom
+ 1, "elete"))
905 if (!strncasecmp (atom
+ 1, "efault", 6)) {
908 if (!strcasecmp(atom
+ 7, "-duid"))
910 if (!strcasecmp (atom
+ 7, "-lease-time"))
911 return DEFAULT_LEASE_TIME
;
914 if (!strncasecmp (atom
+ 1, "ynamic", 6)) {
917 if (!strncasecmp (atom
+ 7, "-bootp", 6)) {
919 return DYNAMIC_BOOTP
;
920 if (!strcasecmp (atom
+ 13, "-lease-cutoff"))
921 return DYNAMIC_BOOTP_LEASE_CUTOFF
;
922 if (!strcasecmp (atom
+ 13, "-lease-length"))
923 return DYNAMIC_BOOTP_LEASE_LENGTH
;
927 if (!strcasecmp (atom
+ 1, "uplicates"))
929 if (!strcasecmp (atom
+ 1, "eclines"))
931 if (!strncasecmp (atom
+ 1, "efine", 5)) {
932 if (!strcasecmp (atom
+ 6, "d"))
939 if (isascii (atom
[1]) &&
940 tolower((unsigned char)atom
[1]) == 'x') {
941 if (!strcasecmp (atom
+ 2, "tract-int"))
943 if (!strcasecmp (atom
+ 2, "ists"))
945 if (!strcasecmp (atom
+ 2, "piry"))
947 if (!strcasecmp (atom
+ 2, "pire"))
949 if (!strcasecmp (atom
+ 2, "pired"))
950 return TOKEN_EXPIRED
;
952 if (!strcasecmp (atom
+ 1, "ncode-int"))
954 if (!strcasecmp(atom
+ 1, "poch"))
956 if (!strcasecmp (atom
+ 1, "thernet"))
958 if (!strcasecmp (atom
+ 1, "nds"))
960 if (!strncasecmp (atom
+ 1, "ls", 2)) {
961 if (!strcasecmp (atom
+ 3, "e"))
963 if (!strcasecmp (atom
+ 3, "if"))
967 if (!strcasecmp (atom
+ 1, "rror"))
969 if (!strcasecmp (atom
+ 1, "val"))
971 if (!strcasecmp (atom
+ 1, "ncapsulate"))
973 if (!strcasecmp(atom
+ 1, "xecute"))
975 if (!strcasecmp(atom
+1, "n")) {
980 if (!strcasecmp (atom
+ 1, "atal"))
982 if (!strcasecmp (atom
+ 1, "ilename"))
984 if (!strcasecmp (atom
+ 1, "ixed-address"))
986 if (!strcasecmp (atom
+ 1, "ixed-address6"))
988 if (!strcasecmp (atom
+ 1, "ixed-prefix6"))
989 return FIXED_PREFIX6
;
990 if (!strcasecmp (atom
+ 1, "ddi"))
992 if (!strcasecmp (atom
+ 1, "ormerr"))
994 if (!strcasecmp (atom
+ 1, "unction"))
996 if (!strcasecmp (atom
+ 1, "ailover"))
998 if (!strcasecmp (atom
+ 1, "ree"))
1002 if (!strncasecmp(atom
+ 1, "et", 2)) {
1003 if (!strcasecmp(atom
+ 3, "-lease-hostnames"))
1004 return GET_LEASE_HOSTNAMES
;
1005 if (!strcasecmp(atom
+ 3, "hostbyname"))
1006 return GETHOSTBYNAME
;
1007 if (!strcasecmp(atom
+ 3, "hostname"))
1011 if (!strcasecmp (atom
+ 1, "iaddr"))
1013 if (!strcasecmp (atom
+ 1, "roup"))
1017 if (!strcasecmp(atom
+ 1, "ash"))
1019 if (!strcasecmp (atom
+ 1, "ba"))
1021 if (!strcasecmp (atom
+ 1, "ost"))
1023 if (!strcasecmp (atom
+ 1, "ost-decl-name"))
1024 return HOST_DECL_NAME
;
1025 if (!strcasecmp(atom
+ 1, "ost-identifier"))
1026 return HOST_IDENTIFIER
;
1027 if (!strcasecmp (atom
+ 1, "ardware"))
1029 if (!strcasecmp (atom
+ 1, "ostname"))
1031 if (!strcasecmp (atom
+ 1, "elp"))
1035 if (!strcasecmp(atom
+1, "a-na"))
1037 if (!strcasecmp(atom
+1, "a-ta"))
1039 if (!strcasecmp(atom
+1, "a-pd"))
1041 if (!strcasecmp(atom
+1, "aaddr"))
1043 if (!strcasecmp(atom
+1, "aprefix"))
1045 if (!strcasecmp (atom
+ 1, "nclude"))
1047 if (!strcasecmp (atom
+ 1, "nteger"))
1049 if (!strcasecmp (atom
+ 1, "nfiniband"))
1050 return TOKEN_INFINIBAND
;
1051 if (!strcasecmp (atom
+ 1, "nfinite"))
1053 if (!strcasecmp (atom
+ 1, "nfo"))
1055 if (!strcasecmp (atom
+ 1, "p-address"))
1057 if (!strcasecmp (atom
+ 1, "p6-address"))
1059 if (!strcasecmp (atom
+ 1, "nitial-interval"))
1060 return INITIAL_INTERVAL
;
1061 if (!strcasecmp (atom
+ 1, "nitial-delay"))
1062 return INITIAL_DELAY
;
1063 if (!strcasecmp (atom
+ 1, "nterface"))
1065 if (!strcasecmp (atom
+ 1, "dentifier"))
1067 if (!strcasecmp (atom
+ 1, "f"))
1069 if (!strcasecmp (atom
+ 1, "s"))
1071 if (!strcasecmp (atom
+ 1, "gnore"))
1075 if (!strncasecmp (atom
+ 1, "nown", 4)) {
1076 if (!strcasecmp (atom
+ 5, "-clients"))
1077 return KNOWN_CLIENTS
;
1082 if (!strcasecmp (atom
+ 1, "ey"))
1086 if (!strcasecmp (atom
+ 1, "case"))
1088 if (!strcasecmp (atom
+ 1, "ease"))
1090 if (!strcasecmp(atom
+ 1, "ease6"))
1092 if (!strcasecmp (atom
+ 1, "eased-address"))
1093 return LEASED_ADDRESS
;
1094 if (!strcasecmp (atom
+ 1, "ease-time"))
1096 if (!strcasecmp(atom
+ 1, "easequery"))
1098 if (!strcasecmp(atom
+ 1, "ength"))
1100 if (!strcasecmp (atom
+ 1, "imit"))
1102 if (!strcasecmp (atom
+ 1, "et"))
1104 if (!strcasecmp (atom
+ 1, "oad"))
1106 if (!strcasecmp(atom
+ 1, "ocal"))
1108 if (!strcasecmp (atom
+ 1, "og"))
1110 if (!strcasecmp(atom
+1, "lt")) {
1113 if (!strcasecmp(atom
+1, "l")) {
1118 if (!strncasecmp (atom
+ 1, "ax", 2)) {
1121 if (!strcasecmp (atom
+ 3, "-balance"))
1123 if (!strncasecmp (atom
+ 3, "-lease-", 7)) {
1124 if (!strcasecmp(atom
+ 10, "misbalance"))
1125 return MAX_LEASE_MISBALANCE
;
1126 if (!strcasecmp(atom
+ 10, "ownership"))
1127 return MAX_LEASE_OWNERSHIP
;
1128 if (!strcasecmp(atom
+ 10, "time"))
1129 return MAX_LEASE_TIME
;
1131 if (!strcasecmp(atom
+ 3, "-life"))
1133 if (!strcasecmp (atom
+ 3, "-transmit-idle"))
1134 return MAX_TRANSMIT_IDLE
;
1135 if (!strcasecmp (atom
+ 3, "-response-delay"))
1136 return MAX_RESPONSE_DELAY
;
1137 if (!strcasecmp (atom
+ 3, "-unacked-updates"))
1138 return MAX_UNACKED_UPDATES
;
1140 if (!strncasecmp (atom
+ 1, "in-", 3)) {
1141 if (!strcasecmp (atom
+ 4, "balance"))
1143 if (!strcasecmp (atom
+ 4, "lease-time"))
1144 return MIN_LEASE_TIME
;
1145 if (!strcasecmp (atom
+ 4, "secs"))
1149 if (!strncasecmp (atom
+ 1, "edi", 3)) {
1150 if (!strcasecmp (atom
+ 4, "a"))
1152 if (!strcasecmp (atom
+ 4, "um"))
1156 if (!strcasecmp (atom
+ 1, "atch"))
1158 if (!strcasecmp (atom
+ 1, "embers"))
1160 if (!strcasecmp (atom
+ 1, "y"))
1162 if (!strcasecmp (atom
+ 1, "clt"))
1166 if (!strcasecmp (atom
+ 1, "ormal"))
1168 if (!strcasecmp (atom
+ 1, "ameserver"))
1170 if (!strcasecmp (atom
+ 1, "etmask"))
1172 if (!strcasecmp (atom
+ 1, "ever"))
1174 if (!strcasecmp (atom
+ 1, "ext-server"))
1176 if (!strcasecmp (atom
+ 1, "ot"))
1178 if (!strcasecmp (atom
+ 1, "o"))
1180 if (!strcasecmp (atom
+ 1, "oerror"))
1182 if (!strcasecmp (atom
+ 1, "otauth"))
1184 if (!strcasecmp (atom
+ 1, "otimp"))
1186 if (!strcasecmp (atom
+ 1, "otzone"))
1188 if (!strcasecmp (atom
+ 1, "xdomain"))
1190 if (!strcasecmp (atom
+ 1, "xrrset"))
1192 if (!strcasecmp (atom
+ 1, "ull"))
1194 if (!strcasecmp (atom
+ 1, "ext"))
1196 if (!strcasecmp (atom
+ 1, "ew"))
1200 if (!strcasecmp (atom
+ 1, "mapi"))
1202 if (!strcasecmp (atom
+ 1, "r"))
1204 if (!strcasecmp (atom
+ 1, "n"))
1206 if (!strcasecmp (atom
+ 1, "pen"))
1208 if (!strcasecmp (atom
+ 1, "ption"))
1210 if (!strcasecmp (atom
+ 1, "ne-lease-per-client"))
1211 return ONE_LEASE_PER_CLIENT
;
1212 if (!strcasecmp (atom
+ 1, "f"))
1214 if (!strcasecmp (atom
+ 1, "wner"))
1218 if (!strcasecmp (atom
+ 1, "repend"))
1220 if (!strcasecmp(atom
+ 1, "referred-life"))
1221 return PREFERRED_LIFE
;
1222 if (!strcasecmp (atom
+ 1, "acket"))
1224 if (!strcasecmp (atom
+ 1, "ool"))
1226 if (!strcasecmp (atom
+ 1, "ool6"))
1228 if (!strcasecmp (atom
+ 1, "refix6"))
1230 if (!strcasecmp (atom
+ 1, "seudo"))
1232 if (!strcasecmp (atom
+ 1, "eer"))
1234 if (!strcasecmp (atom
+ 1, "rimary"))
1236 if (!strcasecmp (atom
+ 1, "rimary6"))
1238 if (!strncasecmp (atom
+ 1, "artner", 6)) {
1241 if (!strcasecmp (atom
+ 7, "-down"))
1242 return PARTNER_DOWN
;
1244 if (!strcasecmp (atom
+ 1, "ort"))
1246 if (!strcasecmp (atom
+ 1, "otential-conflict"))
1247 return POTENTIAL_CONFLICT
;
1248 if (!strcasecmp (atom
+ 1, "ick-first-value") ||
1249 !strcasecmp (atom
+ 1, "ick"))
1251 if (!strcasecmp (atom
+ 1, "aused"))
1255 if (!strcasecmp(atom
+ 1, "ange"))
1257 if (!strcasecmp(atom
+ 1, "ange6"))
1259 if (isascii(atom
[1]) &&
1260 (tolower((unsigned char)atom
[1]) == 'e')) {
1261 if (!strcasecmp(atom
+ 2, "bind"))
1263 if (!strcasecmp(atom
+ 2, "boot"))
1265 if (!strcasecmp(atom
+ 2, "contact-interval"))
1266 return RECONTACT_INTERVAL
;
1267 if (!strncasecmp(atom
+ 2, "cover", 5)) {
1268 if (atom
[7] == '\0')
1270 if (!strcasecmp(atom
+ 7, "-done"))
1271 return RECOVER_DONE
;
1272 if (!strcasecmp(atom
+ 7, "-wait"))
1273 return RECOVER_WAIT
;
1276 if (!strcasecmp(atom
+ 2, "fresh"))
1278 if (!strcasecmp(atom
+ 2, "fused"))
1280 if (!strcasecmp(atom
+ 2, "ject"))
1282 if (!strcasecmp(atom
+ 2, "lease"))
1284 if (!strcasecmp(atom
+ 2, "leased"))
1285 return TOKEN_RELEASED
;
1286 if (!strcasecmp(atom
+ 2, "move"))
1288 if (!strcasecmp(atom
+ 2, "new"))
1290 if (!strcasecmp(atom
+ 2, "quest"))
1292 if (!strcasecmp(atom
+ 2, "quire"))
1294 if (isascii(atom
[2]) &&
1295 (tolower((unsigned char)atom
[2]) == 's')) {
1296 if (!strcasecmp(atom
+ 3, "erved"))
1297 return TOKEN_RESERVED
;
1298 if (!strcasecmp(atom
+ 3, "et"))
1300 if (!strcasecmp(atom
+ 3,
1301 "olution-interrupted"))
1302 return RESOLUTION_INTERRUPTED
;
1305 if (!strcasecmp(atom
+ 2, "try"))
1307 if (!strcasecmp(atom
+ 2, "turn"))
1309 if (!strcasecmp(atom
+ 2, "verse"))
1311 if (!strcasecmp(atom
+ 2, "wind"))
1317 if (!strcasecmp(atom
+ 1, "cript"))
1319 if (isascii(atom
[1]) &&
1320 tolower((unsigned char)atom
[1]) == 'e') {
1321 if (!strcasecmp(atom
+ 2, "arch"))
1323 if (isascii(atom
[2]) &&
1324 tolower((unsigned char)atom
[2]) == 'c') {
1325 if (!strncasecmp(atom
+ 3, "ond", 3)) {
1326 if (!strcasecmp(atom
+ 6, "ary"))
1328 if (!strcasecmp(atom
+ 6, "ary6"))
1330 if (!strcasecmp(atom
+ 6, "s"))
1334 if (!strcasecmp(atom
+ 3, "ret"))
1338 if (!strncasecmp(atom
+ 2, "lect", 4)) {
1339 if (atom
[6] == '\0')
1341 if (!strcasecmp(atom
+ 6, "-timeout"))
1342 return SELECT_TIMEOUT
;
1345 if (!strcasecmp(atom
+ 2, "nd"))
1347 if (!strncasecmp(atom
+ 2, "rv", 2)) {
1348 if (!strncasecmp(atom
+ 4, "er", 2)) {
1349 if (atom
[6] == '\0')
1350 return TOKEN_SERVER
;
1351 if (atom
[6] == '-') {
1352 if (!strcasecmp(atom
+ 7,
1355 if (!strcasecmp(atom
+ 7,
1358 if (!strcasecmp(atom
+ 7,
1360 return SERVER_IDENTIFIER
;
1365 if (!strcasecmp(atom
+ 4, "fail"))
1369 if (!strcasecmp(atom
+ 2, "t"))
1373 if (isascii(atom
[1]) &&
1374 tolower((unsigned char)atom
[1]) == 'h') {
1375 if (!strcasecmp(atom
+ 2, "ared-network"))
1376 return SHARED_NETWORK
;
1377 if (!strcasecmp(atom
+ 2, "utdown"))
1381 if (isascii(atom
[1]) &&
1382 tolower((unsigned char)atom
[1]) == 'i') {
1383 if (!strcasecmp(atom
+ 2, "addr"))
1385 if (!strcasecmp(atom
+ 2, "gned"))
1387 if (!strcasecmp(atom
+ 2, "ze"))
1391 if (isascii(atom
[1]) &&
1392 tolower((unsigned char)atom
[1]) == 'p') {
1393 if (isascii(atom
[2]) &&
1394 tolower((unsigned char)atom
[2]) == 'a') {
1395 if (!strcasecmp(atom
+ 3, "ce"))
1397 if (!strcasecmp(atom
+ 3, "wn"))
1401 if (!strcasecmp(atom
+ 2, "lit"))
1405 if (isascii(atom
[1]) &&
1406 tolower((unsigned char)atom
[1]) == 't') {
1407 if (isascii(atom
[2]) &&
1408 tolower((unsigned char)atom
[2]) == 'a') {
1409 if(!strncasecmp(atom
+ 3, "rt", 2)) {
1410 if (!strcasecmp(atom
+ 5, "s"))
1412 if (!strcasecmp(atom
+ 5, "up"))
1416 if (isascii(atom
[3]) &&
1417 tolower((unsigned char)atom
[3]) == 't') {
1418 if (!strcasecmp(atom
+ 4, "e"))
1420 if (!strcasecmp(atom
+ 4, "ic"))
1425 if (!strcasecmp(atom
+ 2, "ring"))
1426 return STRING_TOKEN
;
1429 if (!strncasecmp(atom
+ 1, "ub", 2)) {
1430 if (!strcasecmp(atom
+ 3, "class"))
1432 if (!strcasecmp(atom
+ 3, "net"))
1434 if (!strcasecmp(atom
+ 3, "net6"))
1436 if (!strcasecmp(atom
+ 3, "string"))
1440 if (isascii(atom
[1]) &&
1441 tolower((unsigned char)atom
[1]) == 'u') {
1442 if (!strcasecmp(atom
+ 2, "ffix"))
1444 if (!strcasecmp(atom
+ 2, "persede"))
1447 if (!strcasecmp(atom
+ 1, "witch"))
1451 if (!strcasecmp (atom
+ 1, "imestamp"))
1453 if (!strcasecmp (atom
+ 1, "imeout"))
1455 if (!strcasecmp (atom
+ 1, "oken-ring"))
1457 if (!strcasecmp (atom
+ 1, "ext"))
1459 if (!strcasecmp (atom
+ 1, "stp"))
1461 if (!strcasecmp (atom
+ 1, "sfp"))
1463 if (!strcasecmp (atom
+ 1, "ransmission"))
1464 return TRANSMISSION
;
1465 if (!strcasecmp(atom
+ 1, "emporary"))
1469 if (!strcasecmp (atom
+ 1, "case"))
1471 if (!strcasecmp (atom
+ 1, "nset"))
1473 if (!strcasecmp (atom
+ 1, "nsigned"))
1475 if (!strcasecmp (atom
+ 1, "id"))
1477 if (!strncasecmp (atom
+ 1, "se", 2)) {
1478 if (!strcasecmp (atom
+ 3, "r-class"))
1480 if (!strcasecmp (atom
+ 3, "-host-decl-names"))
1481 return USE_HOST_DECL_NAMES
;
1482 if (!strcasecmp (atom
+ 3,
1483 "-lease-addr-for-default-route"))
1484 return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE
;
1487 if (!strncasecmp (atom
+ 1, "nknown", 6)) {
1488 if (!strcasecmp (atom
+ 7, "-clients"))
1489 return UNKNOWN_CLIENTS
;
1490 if (!strcasecmp (atom
+ 7, "-state"))
1491 return UNKNOWN_STATE
;
1496 if (!strcasecmp (atom
+ 1, "nauthenticated"))
1497 return UNAUTHENTICATED
;
1498 if (!strcasecmp (atom
+ 1, "pdate"))
1502 if (!strcasecmp (atom
+ 1, "6relay"))
1504 if (!strcasecmp (atom
+ 1, "6relopt"))
1506 if (!strcasecmp (atom
+ 1, "endor-class"))
1507 return VENDOR_CLASS
;
1508 if (!strcasecmp (atom
+ 1, "endor"))
1512 if (!strcasecmp (atom
+ 1, "ith"))
1514 if (!strcasecmp(atom
+ 1, "idth"))
1518 if (!strcasecmp (atom
+ 1, "iaddr"))
1520 if (!strcasecmp (atom
+ 1, "xdomain"))
1522 if (!strcasecmp (atom
+ 1, "xrrset"))
1526 if (!strcasecmp (atom
+ 1, "erolen"))
1528 if (!strcasecmp (atom
+ 1, "one"))