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