conflex.c 24.1 KB
Newer Older
Ted Lemon's avatar
Ted Lemon committed
1 2 3 4 5
/* conflex.c

   Lexical scanner for dhcpd config file... */

/*
Ted Lemon's avatar
Ted Lemon committed
6 7
 * Copyright (c) 1995-2000 Internet Software Consortium.
 * All rights reserved.
Ted Lemon's avatar
Ted Lemon committed
8
 *
Ted Lemon's avatar
Ted Lemon committed
9 10 11
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
Ted Lemon's avatar
Ted Lemon committed
12
 *
Ted Lemon's avatar
Ted Lemon committed
13 14 15 16 17 18 19 20
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of The Internet Software Consortium nor the names
 *    of its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
Ted Lemon's avatar
Ted Lemon committed
21
 *
Ted Lemon's avatar
Ted Lemon committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This software has been written for the Internet Software Consortium
 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
 * To learn more about the Internet Software Consortium, see
 * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
 * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 * ``http://www.nominum.com''.
Ted Lemon's avatar
Ted Lemon committed
42 43 44 45
 */

#ifndef lint
static char copyright[] =
Ted Lemon's avatar
Ted Lemon committed
46
"$Id: conflex.c,v 1.69 2000/03/17 03:59:00 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
Ted Lemon's avatar
Ted Lemon committed
47 48 49 50 51
#endif /* not lint */

#include "dhcpd.h"
#include <ctype.h>

52 53 54 55 56 57 58
static int get_char PROTO ((struct parse *));
static enum dhcp_token get_token PROTO ((struct parse *));
static void skip_to_eol PROTO ((struct parse *));
static enum dhcp_token read_string PROTO ((struct parse *));
static enum dhcp_token read_number PROTO ((int, struct parse *));
static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
Ted Lemon's avatar
Ted Lemon committed
59

60 61 62 63
isc_result_t new_parse (cfile, file, inbuf, buflen, name)
	struct parse **cfile;
	int file;
	char *inbuf;
64 65
	unsigned buflen;
	const char *name;
66 67
{
	struct parse *tmp;
68

69
	tmp = dmalloc (sizeof (struct parse), MDL);
70 71 72
	if (!tmp)
		return ISC_R_NOMEMORY;
	memset (tmp, 0, sizeof *tmp);
73

Ted Lemon's avatar
Ted Lemon committed
74
	tmp -> token = 0;
75 76 77 78 79 80 81 82
	tmp -> tlname = name;
	tmp -> lpos = tmp -> line = 1;
	tmp -> cur_line = tmp -> line1;
	tmp -> prev_line = tmp -> line2;
	tmp -> token_line = tmp -> cur_line;
	tmp -> cur_line [0] = tmp -> prev_line [0] = 0;
	tmp -> warnings_occurred = 0;
	tmp -> file = file;
Ted Lemon's avatar
Ted Lemon committed
83

84 85 86 87 88 89
	tmp -> bufix = 0;
	tmp -> buflen = buflen;
	if (inbuf) {
		tmp -> bufsiz = 0;
		tmp -> inbuf = inbuf;
	} else {
90
		tmp -> inbuf = dmalloc (8192, MDL);
91
		if (!tmp -> inbuf) {
92
			dfree (tmp, MDL);
93 94 95 96 97 98 99 100 101 102 103
			return ISC_R_NOMEMORY;
		}
		tmp -> bufsiz = 8192;
	}

	*cfile = tmp;
	return ISC_R_SUCCESS;
}

isc_result_t end_parse (cfile)
	struct parse **cfile;
104
{
105
	if ((*cfile) -> bufsiz)
106 107
		dfree ((*cfile) -> inbuf, MDL);
	dfree (*cfile, MDL);
108 109
	*cfile = (struct parse *)0;
	return ISC_R_SUCCESS;
110 111
}

Ted Lemon's avatar
Ted Lemon committed
112
static int get_char (cfile)
113
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
114
{
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
	/* My kingdom for WITH... */
	int c;

	if (cfile -> bufix == cfile -> buflen) {
		if (cfile -> file != -1) {
			cfile -> buflen =
				read (cfile -> file,
				      cfile -> inbuf, cfile -> bufsiz);
			if (cfile -> buflen == 0) {
				c = EOF;
				cfile -> bufix = 0;
			} else if (cfile -> buflen < 0) {
				c = EOF;
				cfile -> bufix = cfile -> buflen = 0;
			} else {
				c = cfile -> inbuf [0];
				cfile -> bufix = 1;
			}
		} else
			c = EOF;
	} else {
		c = cfile -> inbuf [cfile -> bufix];
		cfile -> bufix++;
	}

	if (!cfile -> ugflag) {
Ted Lemon's avatar
Ted Lemon committed
141
		if (c == EOL) {
142 143 144
			if (cfile -> cur_line == cfile -> line1) {	
				cfile -> cur_line = cfile -> line2;
				cfile -> prev_line = cfile -> line1;
145
			} else {
146 147
				cfile -> cur_line = cfile -> line1;
				cfile -> prev_line = cfile -> line2;
148
			}
149 150 151
			cfile -> line++;
			cfile -> lpos = 1;
			cfile -> cur_line [0] = 0;
152
		} else if (c != EOF) {
153 154 155
			if (cfile -> lpos <= 80) {
				cfile -> cur_line [cfile -> lpos - 1] = c;
				cfile -> cur_line [cfile -> lpos] = 0;
156
			}
157
			cfile -> lpos++;
Ted Lemon's avatar
Ted Lemon committed
158 159
		}
	} else
160
		cfile -> ugflag = 0;
Ted Lemon's avatar
Ted Lemon committed
161 162 163
	return c;		
}

164
static enum dhcp_token get_token (cfile)
165
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
166 167
{
	int c;
168
	enum dhcp_token ttok;
169
	static char tb [2];
170
	int l, p, u;
Ted Lemon's avatar
Ted Lemon committed
171 172

	do {
173 174 175
		l = cfile -> line;
		p = cfile -> lpos;
		u = cfile -> ugflag;
176

Ted Lemon's avatar
Ted Lemon committed
177
		c = get_char (cfile);
178 179
#ifdef OLD_LEXER
		if (c == '\n' && p == 1 && !u
180 181
		    && cfile -> comment_index < sizeof cfile -> comments)
			cfile -> comments [cfile -> comment_index++] = '\n';
182 183
#endif

184 185
		if (!(c == '\n' && cfile -> eol_token)
		    && isascii (c) && isspace (c))
Ted Lemon's avatar
Ted Lemon committed
186 187
			continue;
		if (c == '#') {
188
#ifdef OLD_LEXER
189 190
			if (cfile -> comment_index < sizeof cfile -> comments)
			    cfile -> comments [cfile -> comment_index++] = '#';
191
#endif
Ted Lemon's avatar
Ted Lemon committed
192 193 194 195
			skip_to_eol (cfile);
			continue;
		}
		if (c == '"') {
196 197
			cfile -> lexline = l;
			cfile -> lexchar = p;
Ted Lemon's avatar
Ted Lemon committed
198 199 200
			ttok = read_string (cfile);
			break;
		}
Ted Lemon's avatar
Ted Lemon committed
201
		if ((isascii (c) && isdigit (c)) || c == '-') {
202 203
			cfile -> lexline = l;
			cfile -> lexchar = p;
Ted Lemon's avatar
Ted Lemon committed
204 205 206
			ttok = read_number (c, cfile);
			break;
		} else if (isascii (c) && isalpha (c)) {
207 208
			cfile -> lexline = l;
			cfile -> lexchar = p;
Ted Lemon's avatar
Ted Lemon committed
209
			ttok = read_num_or_name (c, cfile);
Ted Lemon's avatar
Ted Lemon committed
210 211
			break;
		} else {
212 213
			cfile -> lexline = l;
			cfile -> lexchar = p;
214 215
			tb [0] = c;
			tb [1] = 0;
216
			cfile -> tval = tb;
Ted Lemon's avatar
Ted Lemon committed
217 218 219 220 221 222 223
			ttok = c;
			break;
		}
	} while (1);
	return ttok;
}

224
enum dhcp_token next_token (rval, cfile)
225
	const char **rval;
226
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
227 228 229
{
	int rv;

230 231 232 233 234 235 236
	if (cfile -> token) {
		if (cfile -> lexline != cfile -> tline)
			cfile -> token_line = cfile -> cur_line;
		cfile -> lexchar = cfile -> tlpos;
		cfile -> lexline = cfile -> tline;
		rv = cfile -> token;
		cfile -> token = 0;
Ted Lemon's avatar
Ted Lemon committed
237 238
	} else {
		rv = get_token (cfile);
239
		cfile -> token_line = cfile -> cur_line;
Ted Lemon's avatar
Ted Lemon committed
240 241
	}
	if (rval)
242
		*rval = cfile -> tval;
243
#ifdef DEBUG_TOKENS
244
	fprintf (stderr, "%s:%d ", cfile -> tval, rv);
245
#endif
Ted Lemon's avatar
Ted Lemon committed
246 247 248
	return rv;
}

249
enum dhcp_token peek_token (rval, cfile)
250
	const char **rval;
251
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
252
{
253 254
	int x;

255 256 257 258 259 260 261 262 263 264 265 266 267 268
	if (!cfile -> token) {
		cfile -> tlpos = cfile -> lexchar;
		cfile -> tline = cfile -> lexline;
		cfile -> token = get_token (cfile);
		if (cfile -> lexline != cfile -> tline)
			cfile -> token_line = cfile -> prev_line;

		x = cfile -> lexchar;
		cfile -> lexchar = cfile -> tlpos;
		cfile -> tlpos = x;

		x = cfile -> lexline;
		cfile -> lexline = cfile -> tline;
		cfile -> tline = x;
269
	}
Ted Lemon's avatar
Ted Lemon committed
270
	if (rval)
271
		*rval = cfile -> tval;
272
#ifdef DEBUG_TOKENS
273
	fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
274
#endif
275
	return cfile -> token;
Ted Lemon's avatar
Ted Lemon committed
276 277 278
}

static void skip_to_eol (cfile)
279
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
280 281 282 283 284 285
{
	int c;
	do {
		c = get_char (cfile);
		if (c == EOF)
			return;
286
#ifdef OLD_LEXER
287 288
		if (cfile -> comment_index < sizeof (cfile -> comments))
			comments [cfile -> comment_index++] = c;
289
#endif
Ted Lemon's avatar
Ted Lemon committed
290 291 292 293 294 295
		if (c == EOL) {
			return;
		}
	} while (1);
}

296
static enum dhcp_token read_string (cfile)
297
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
298 299 300 301
{
	int i;
	int bs = 0;
	int c;
302 303
	int value;
	int hex;
Ted Lemon's avatar
Ted Lemon committed
304

305
	for (i = 0; i < sizeof cfile -> tokbuf; i++) {
306
	      again:
Ted Lemon's avatar
Ted Lemon committed
307 308
		c = get_char (cfile);
		if (c == EOF) {
309
			parse_warn (cfile, "eof in string constant");
Ted Lemon's avatar
Ted Lemon committed
310 311
			break;
		}
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
		if (bs == 1) {
			switch (c) {
			      case 't':
				cfile -> tokbuf [i] = '\t';
				break;
			      case 'r':
				cfile -> tokbuf [i] = '\r';
				break;
			      case 'n':
				cfile -> tokbuf [i] = '\n';
				break;
			      case 'b':
				cfile -> tokbuf [i] = '\b';
				break;
			      case '0':
			      case '1':
			      case '2':
			      case '3':
				hex = 0;
				value = c - '0';
				++bs;
				goto again;
			      case 'x':
				hex = 1;
				value = 0;
				++bs;
				goto again;
			      default:
				cfile -> tokbuf [i] = c;
				bs = 0;
				break;
			}
Ted Lemon's avatar
Ted Lemon committed
344
			bs = 0;
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
		} else if (bs > 1) {
			if (hex) {
				if (c >= '0' && c <= '9') {
					value = value * 16 + (c - '0');
				} else if (c >= 'a' && c <= 'f') {
					value = value * 16 + (c - 'a' + 10);
				} else if (c >= 'A' && c <= 'F') {
					value = value * 16 + (c - 'A' + 10);
				} else {
					parse_warn (cfile,
						    "invalid hex digit: %x",
						    c);
					bs = 0;
					continue;
				}
				if (++bs == 4) {
					cfile -> tokbuf [i] = value;
					bs = 0;
				} else
					goto again;
			} else {
				if (c >= '0' && c <= '9') {
					value = value * 8 + (c - '0');
				} else {
				    if (value != 0) {
					parse_warn (cfile,
						    "invalid octal digit %x",
						    c);
					continue;
				    } else
					cfile -> tokbuf [i] = 0;
				    bs = 0;
				}
				if (++bs == 4) {
					cfile -> tokbuf [i] = value;
					bs = 0;
				} else
					goto again;
			}
		} else if (c == '\\') {
Ted Lemon's avatar
Ted Lemon committed
385
			bs = 1;
386 387
			goto again;
		} else if (c == '"')
Ted Lemon's avatar
Ted Lemon committed
388 389
			break;
		else
390
			cfile -> tokbuf [i] = c;
Ted Lemon's avatar
Ted Lemon committed
391 392 393
	}
	/* Normally, I'd feel guilty about this, but we're talking about
	   strings that'll fit in a DHCP packet here... */
394 395 396
	if (i == sizeof cfile -> tokbuf) {
		parse_warn (cfile,
			    "string constant larger than internal buffer");
Ted Lemon's avatar
Ted Lemon committed
397 398
		--i;
	}
399 400
	cfile -> tokbuf [i] = 0;
	cfile -> tval = cfile -> tokbuf;
Ted Lemon's avatar
Ted Lemon committed
401 402 403
	return STRING;
}

404
static enum dhcp_token read_number (c, cfile)
Ted Lemon's avatar
Ted Lemon committed
405
	int c;
406
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
407 408 409
{
	int seenx = 0;
	int i = 0;
410 411
	int token = NUMBER;

412 413
	cfile -> tokbuf [i++] = c;
	for (; i < sizeof cfile -> tokbuf; i++) {
Ted Lemon's avatar
Ted Lemon committed
414
		c = get_char (cfile);
415
		if (!seenx && c == 'x') {
Ted Lemon's avatar
Ted Lemon committed
416
			seenx = 1;
417 418 419
#ifndef OLD_LEXER
		} else if (isascii (c) && !isxdigit (c) &&
			   (c == '-' || c == '_' || isalpha (c))) {
Ted Lemon's avatar
Ted Lemon committed
420
			token = NAME;
421
		} else if (isascii (c) && !isdigit (c) && isxdigit (c)) {
Ted Lemon's avatar
Ted Lemon committed
422
			token = NUMBER_OR_NAME;
423 424
#endif
		} else if (!isascii (c) || !isxdigit (c)) {
425 426
			cfile -> bufix--;
			cfile -> ugflag = 1;
Ted Lemon's avatar
Ted Lemon committed
427 428
			break;
		}
429
		cfile -> tokbuf [i] = c;
Ted Lemon's avatar
Ted Lemon committed
430
	}
431 432 433
	if (i == sizeof cfile -> tokbuf) {
		parse_warn (cfile,
			    "numeric token larger than internal buffer");
Ted Lemon's avatar
Ted Lemon committed
434 435
		--i;
	}
436 437
	cfile -> tokbuf [i] = 0;
	cfile -> tval = cfile -> tokbuf;
438
	return token;
Ted Lemon's avatar
Ted Lemon committed
439 440
}

441
static enum dhcp_token read_num_or_name (c, cfile)
Ted Lemon's avatar
Ted Lemon committed
442
	int c;
443
	struct parse *cfile;
Ted Lemon's avatar
Ted Lemon committed
444 445
{
	int i = 0;
446
	enum dhcp_token rv = NUMBER_OR_NAME;
447 448
	cfile -> tokbuf [i++] = c;
	for (; i < sizeof cfile -> tokbuf; i++) {
Ted Lemon's avatar
Ted Lemon committed
449 450 451
		c = get_char (cfile);
		if (!isascii (c) ||
		    (c != '-' && c != '_' && !isalnum (c))) {
452 453
			cfile -> bufix--;
			cfile -> ugflag = 1;
Ted Lemon's avatar
Ted Lemon committed
454 455 456
			break;
		}
		if (!isxdigit (c))
Ted Lemon's avatar
Ted Lemon committed
457
			rv = NAME;
458
		cfile -> tokbuf [i] = c;
Ted Lemon's avatar
Ted Lemon committed
459
	}
460 461
	if (i == sizeof cfile -> tokbuf) {
		parse_warn (cfile, "token larger than internal buffer");
Ted Lemon's avatar
Ted Lemon committed
462 463
		--i;
	}
464 465 466
	cfile -> tokbuf [i] = 0;
	cfile -> tval = cfile -> tokbuf;
	return intern (cfile -> tval, rv);
Ted Lemon's avatar
Ted Lemon committed
467 468
}

469
static enum dhcp_token intern (atom, dfv)
Ted Lemon's avatar
Ted Lemon committed
470
	char *atom;
471
	enum dhcp_token dfv;
Ted Lemon's avatar
Ted Lemon committed
472
{
Ted Lemon's avatar
Ted Lemon committed
473 474 475 476
	if (!isascii (atom [0]))
		return dfv;

	switch (tolower (atom [0])) {
477 478 479 480 481
	      case '-':
		if (atom [1] == 0)
			return MINUS;
		break;

Ted Lemon's avatar
Ted Lemon committed
482
	      case 'a':
483 484 485 486 487 488 489 490 491 492 493 494 495 496
		if (!strncasecmp (atom + 1, "uth", 3)) {
			if (!strncasecmp (atom + 3, "uthenticat", 10)) {
				if (!strcasecmp (atom + 13, "ed"))
					return AUTHENTICATED;
				if (!strcasecmp (atom + 13, "ion"))
					return AUTHENTICATION;
				break;
			}
			if (!strcasecmp (atom + 1, "uthoritative"))
				return AUTHORITATIVE;
			if (!strcasecmp (atom + 1, "uth-key"))
				return AUTH_KEY;
			break;
		}
497 498
		if (!strcasecmp (atom + 1, "nd"))
			return AND;
499 500
		if (!strcasecmp (atom + 1, "ppend"))
			return APPEND;
Ted Lemon's avatar
Ted Lemon committed
501 502
		if (!strcasecmp (atom + 1, "llow"))
			return ALLOW;
Ted Lemon's avatar
Ted Lemon committed
503 504
		if (!strcasecmp (atom + 1, "lias"))
			return ALIAS;
Ted Lemon's avatar
Ted Lemon committed
505 506
		if (!strcasecmp (atom + 1, "bandoned"))
			return ABANDONED;
507
		if (!strcasecmp (atom + 1, "dd"))
508
			return TOKEN_ADD;
509 510
		if (!strcasecmp (atom + 1, "ll"))
			return ALL;
511 512
		if (!strcasecmp (atom + 1, "t"))
			return AT;
513 514
		if (!strcasecmp (atom + 1, "rray"))
			return ARRAY;
Ted Lemon's avatar
Ted Lemon committed
515
		break;
516
	      case 'b':
517 518
		if (!strcasecmp (atom + 1, "inary-to-ascii"))
			return BINARY_TO_ASCII;
519 520
		if (!strcasecmp (atom + 1, "ackoff-cutoff"))
			return BACKOFF_CUTOFF;
Ted Lemon's avatar
Ted Lemon committed
521 522 523 524
		if (!strcasecmp (atom + 1, "ootp"))
			return BOOTP;
		if (!strcasecmp (atom + 1, "ooting"))
			return BOOTING;
525 526
		if (!strcasecmp (atom + 1, "oot-unknown-clients"))
			return BOOT_UNKNOWN_CLIENTS;
527 528
		if (!strcasecmp (atom + 1, "reak"))
			return BREAK;
Ted Lemon's avatar
Ted Lemon committed
529 530
		if (!strcasecmp (atom + 1, "illing"))
			return BILLING;
531 532
		if (!strcasecmp (atom + 1, "oolean"))
			return BOOLEAN;
533
		break;
534
	      case 'c':
535 536
		if (!strcasecmp (atom + 1, "ase"))
			return CASE;
537 538
		if (!strcasecmp (atom + 1, "ommit"))
			return COMMIT;
539 540
		if (!strcasecmp (atom + 1, "ode"))
			return CODE;
541 542
		if (!strcasecmp (atom + 1, "onfig-option"))
			return CONFIG_OPTION;
543 544
		if (!strcasecmp (atom + 1, "heck"))
			return CHECK;
545 546
		if (!strcasecmp (atom + 1, "lass"))
			return CLASS;
547 548
		if (!strcasecmp (atom + 1, "iaddr"))
			return CIADDR;
549 550 551 552 553 554 555 556
		if (!strncasecmp (atom + 1, "lient", 5)) {
			if (!strcasecmp (atom + 6, "-identifier"))
				return CLIENT_IDENTIFIER;
			if (!strcasecmp (atom + 6, "-hostname"))
				return CLIENT_HOSTNAME;
			if (!strcasecmp (atom + 6, "s"))
				return CLIENTS;
		}
Ted Lemon's avatar
Ted Lemon committed
557 558
		if (!strncasecmp (atom + 1, "oncat", 5))
			return CONCAT;
559 560
		if (!strcasecmp (atom + 1, "ommunications-interrupted"))
			return COMMUNICATIONS_INTERRUPTED;
561
		break;
562
	      case 'd':
563 564
		if (!strcasecmp (atom + 1, "ns-update"))
			return DNS_UPDATE;
565 566
		if (!strcasecmp (atom + 1, "ns-delete"))
			return DNS_DELETE;
567 568
		if (!strcasecmp (atom + 1, "omain"))
			return DOMAIN;
Ted Lemon's avatar
Ted Lemon committed
569 570
		if (!strcasecmp (atom + 1, "eny"))
			return DENY;
Ted Lemon's avatar
Ted Lemon committed
571 572
		if (!strcasecmp (atom + 1, "eleted"))
			return DELETED;
573 574
		if (!strcasecmp (atom + 1, "elete"))
			return TOKEN_DELETE;
Ted Lemon's avatar
Ted Lemon committed
575 576 577 578 579 580 581
		if (!strncasecmp (atom + 1, "efault", 6)) {
			if (!atom [7])
				return DEFAULT;
			if (!strcasecmp (atom + 7, "-lease-time"))
				return DEFAULT_LEASE_TIME;
			break;
		}
582 583 584 585 586 587 588 589 590 591 592 593
		if (!strncasecmp (atom + 1, "ynamic", 6)) {
			if (!atom [7])
				return DYNAMIC;
			if (!strncasecmp (atom + 7, "-bootp", 6)) {
				if (!atom [13])
					return DYNAMIC_BOOTP;
				if (!strcasecmp (atom + 13, "-lease-cutoff"))
					return DYNAMIC_BOOTP_LEASE_CUTOFF;
				if (!strcasecmp (atom + 13, "-lease-length"))
					return DYNAMIC_BOOTP_LEASE_LENGTH;
				break;
			}
594
		}
Ted Lemon's avatar
Ted Lemon committed
595 596
		if (!strcasecmp (atom + 1, "uplicates"))
			return DUPLICATES;
Ted Lemon's avatar
Ted Lemon committed
597 598
		if (!strcasecmp (atom + 1, "eclines"))
			return DECLINES;
599 600 601 602 603 604
		if (!strncasecmp (atom + 1, "efine", 5)) {
			if (!strcasecmp (atom + 6, "d"))
				return DEFINED;
			if (!atom [6])
				return DEFINE;
		}
605
		break;
606
	      case 'e':
Ted Lemon's avatar
Ted Lemon committed
607 608 609 610 611
		if (isascii (atom [1]) && tolower (atom [1]) == 'x') {
			if (!strcasecmp (atom + 2, "tract-int"))
				return EXTRACT_INT;
			if (!strcasecmp (atom + 2, "ists"))
				return EXISTS;
Ted Lemon's avatar
Ted Lemon committed
612 613 614 615
			if (!strcasecmp (atom + 2, "piry"))
				return EXPIRY;
			if (!strcasecmp (atom + 2, "pire"))
				return EXPIRE;
Ted Lemon's avatar
Ted Lemon committed
616
		}
Ted Lemon's avatar
Ted Lemon committed
617
		if (!strcasecmp (atom + 1, "ncode-int"))
Ted Lemon's avatar
Ted Lemon committed
618
			return ENCODE_INT;
619 620 621 622
		if (!strcasecmp (atom + 1, "thernet"))
			return ETHERNET;
		if (!strcasecmp (atom + 1, "nds"))
			return ENDS;
623 624 625 626 627 628 629
		if (!strncasecmp (atom + 1, "ls", 2)) {
			if (!strcasecmp (atom + 3, "e"))
				return ELSE;
			if (!strcasecmp (atom + 3, "if"))
				return ELSIF;
			break;
		}
Ted Lemon's avatar
Ted Lemon committed
630 631
		if (!strcasecmp (atom + 1, "val"))
			return EVAL;
Ted Lemon's avatar
Ted Lemon committed
632 633 634 635 636 637
		break;
	      case 'f':
		if (!strcasecmp (atom + 1, "ilename"))
			return FILENAME;
		if (!strcasecmp (atom + 1, "ixed-address"))
			return FIXED_ADDR;
638 639
		if (!strcasecmp (atom + 1, "ddi"))
			return FDDI;
640 641
		if (!strcasecmp (atom + 1, "ormerr"))
			return NS_FORMERR;
642 643
		if (!strcasecmp (atom + 1, "unction"))
			return FUNCTION;
Ted Lemon's avatar
Ted Lemon committed
644
		break;
645 646 647
	      case 'g':
		if (!strcasecmp (atom + 1, "iaddr"))
			return GIADDR;
648 649
		if (!strcasecmp (atom + 1, "roup"))
			return GROUP;
Ted Lemon's avatar
Ted Lemon committed
650 651
		if (!strcasecmp (atom + 1, "et-lease-hostnames"))
			return GET_LEASE_HOSTNAMES;
652
		break;
653
	      case 'h':
654 655
		if (!strcasecmp (atom + 1, "ba"))
			return HBA;
656 657
		if (!strcasecmp (atom + 1, "ost"))
			return HOST;
658 659
		if (!strcasecmp (atom + 1, "ost-decl-name"))
			return HOST_DECL_NAME;
660 661
		if (!strcasecmp (atom + 1, "ardware"))
			return HARDWARE;
Ted Lemon's avatar
Ted Lemon committed
662 663
		if (!strcasecmp (atom + 1, "ostname"))
			return HOSTNAME;
664
		break;
Ted Lemon's avatar
Ted Lemon committed
665
	      case 'i':
666 667
		if (!strcasecmp (atom + 1, "nteger"))
			return INTEGER;
668 669
		if (!strcasecmp (atom + 1, "nfinite"))
			return INFINITE;
670 671
		if (!strcasecmp (atom + 1, "p-address"))
			return IP_ADDRESS;
672 673
		if (!strcasecmp (atom + 1, "nitial-interval"))
			return INITIAL_INTERVAL;
Ted Lemon's avatar
Ted Lemon committed
674 675
		if (!strcasecmp (atom + 1, "nterface"))
			return INTERFACE;
676 677
		if (!strcasecmp (atom + 1, "dentifier"))
			return IDENTIFIER;
678 679
		if (!strcasecmp (atom + 1, "f"))
			return IF;
680 681
		if (!strcasecmp (atom + 1, "s"))
			return IS;
Ted Lemon's avatar
Ted Lemon committed
682 683
		if (!strcasecmp (atom + 1, "gnore"))
			return IGNORE;
Ted Lemon's avatar
Ted Lemon committed
684
		break;
685 686 687 688
	      case 'k':
		if (!strcasecmp (atom + 1, "nown"))
			return KNOWN;
		break;
689 690 691
	      case 'l':
		if (!strcasecmp (atom + 1, "ease"))
			return LEASE;
692 693
		if (!strcasecmp (atom + 1, "eased-address"))
			return LEASED_ADDRESS;
Ted Lemon's avatar
Ted Lemon committed
694
		if (!strcasecmp (atom + 1, "ease-time"))
695
			return LEASE_TIME;
Ted Lemon's avatar
Ted Lemon committed
696 697
		if (!strcasecmp (atom + 1, "imit"))
			return LIMIT;
Ted Lemon's avatar
Ted Lemon committed
698 699
		if (!strcasecmp (atom + 1, "et"))
			return LET;
Ted Lemon's avatar
Ted Lemon committed
700
		break;
701
	      case 'm':
702 703 704 705 706 707 708
		if (!strncasecmp (atom + 1, "ax-", 3)) {
			if (!strcasecmp (atom + 4, "lease-time"))
				return MAX_LEASE_TIME;
			if (!strcasecmp (atom + 4, "transmit-idle"))
				return MAX_TRANSMIT_IDLE;
			if (!strcasecmp (atom + 4, "response-delay"))
				return MAX_RESPONSE_DELAY;
709 710
			if (!strcasecmp (atom + 5, "unacked-updates"))
				return MAX_UNACKED_UPDATES;
711
		}
712 713 714 715 716 717 718
		if (!strncasecmp (atom + 1, "in-", 3)) {
			if (!strcasecmp (atom + 4, "lease-time"))
				return MIN_LEASE_TIME;
			if (!strcasecmp (atom + 4, "secs"))
				return MIN_SECS;
			break;
		}
Ted Lemon's avatar
Ted Lemon committed
719 720 721 722 723 724 725
		if (!strncasecmp (atom + 1, "edi", 3)) {
			if (!strcasecmp (atom + 4, "a"))
				return MEDIA;
			if (!strcasecmp (atom + 4, "um"))
				return MEDIUM;
			break;
		}
726 727
		if (!strcasecmp (atom + 1, "atch"))
			return MATCH;
728 729
		if (!strcasecmp (atom + 1, "embers"))
			return MEMBERS;
730 731
		if (!strcasecmp (atom + 1, "y"))
			return MY;
732 733
		if (!strcasecmp (atom + 1, "clt"))
			return MCLT;
734 735
		break;
	      case 'n':
736 737
		if (!strcasecmp (atom + 1, "ormal"))
			return NORMAL;
738 739
		if (!strcasecmp (atom + 1, "ameserver"))
			return NAMESERVER;
740 741
		if (!strcasecmp (atom + 1, "etmask"))
			return NETMASK;
742 743
		if (!strcasecmp (atom + 1, "ever"))
			return NEVER;
744 745
		if (!strcasecmp (atom + 1, "ext-server"))
			return NEXT_SERVER;
746 747
		if (!strcasecmp (atom + 1, "ot"))
			return TOKEN_NOT;
748 749 750 751
		if (!strcasecmp (atom + 1, "o"))
			return NO;
		if (!strcasecmp (atom + 1, "s-update"))
			return NS_UPDATE;
752 753 754 755 756 757 758 759 760 761 762 763 764 765
		if (!strcasecmp (atom + 1, "oerror"))
			return NS_NOERROR;
		if (!strcasecmp (atom + 1, "otauth"))
			return NS_NOTAUTH;
		if (!strcasecmp (atom + 1, "otimp"))
			return NS_NOTIMP;
		if (!strcasecmp (atom + 1, "otzone"))
			return NS_NOTZONE;
		if (!strcasecmp (atom + 1, "xdomain"))
			return NS_NXDOMAIN;
		if (!strcasecmp (atom + 1, "xrrset"))
			return NS_NXRRSET;
		if (!strcasecmp (atom + 1, "ull"))
			return TOKEN_NULL;
766
		break;
Ted Lemon's avatar
Ted Lemon committed
767
	      case 'o':
768 769
		if (!strcasecmp (atom + 1, "r"))
			return OR;
770 771
		if (!strcasecmp (atom + 1, "n"))
			return ON;
Ted Lemon's avatar
Ted Lemon committed
772 773
		if (!strcasecmp (atom + 1, "ption"))
			return OPTION;
774 775
		if (!strcasecmp (atom + 1, "ne-lease-per-client"))
			return ONE_LEASE_PER_CLIENT;
776 777
		if (!strcasecmp (atom + 1, "f"))
			return OF;
778 779
		if (!strcasecmp (atom + 1, "wner"))
			return OWNER;
780 781
		break;
	      case 'p':
782 783
		if (!strcasecmp (atom + 1, "repend"))
			return PREPEND;
784 785
		if (!strcasecmp (atom + 1, "acket"))
			return PACKET;
786 787 788 789
		if (!strcasecmp (atom + 1, "ool"))
			return POOL;
		if (!strcasecmp (atom + 1, "seudo"))
			return PSEUDO;
790 791 792 793 794 795 796 797 798 799 800 801 802 803
		if (!strcasecmp (atom + 1, "eer"))
			return PEER;
		if (!strcasecmp (atom + 1, "rimary"))
			return PRIMARY;
		if (!strncasecmp (atom + 1, "artner", 6)) {
			if (!atom [7])
				return PARTNER;
			if (!strcasecmp (atom + 7, "-down"))
				return PARTNER_DOWN;
		}
		if (!strcasecmp (atom + 1, "ort"))
			return PORT;
		if (!strcasecmp (atom + 1, "otential-conflict"))
			return POTENTIAL_CONFLICT;
Ted Lemon's avatar
Ted Lemon committed
804 805 806
		if (!strcasecmp (atom + 1, "ick-first-value") ||
		    !strcasecmp (atom + 1, "ick"))
			return PICK;
Ted Lemon's avatar
Ted Lemon committed
807
		break;
808 809 810
	      case 'r':
		if (!strcasecmp (atom + 1, "ange"))
			return RANGE;
811 812
		if (!strcasecmp (atom + 1, "ecover"))
			return RECOVER;
Ted Lemon's avatar
Ted Lemon committed
813 814 815 816
		if (!strcasecmp (atom + 1, "equest"))
			return REQUEST;
		if (!strcasecmp (atom + 1, "equire"))
			return REQUIRE;
817 818
		if (!strcasecmp (atom + 1, "equire"))
			return REQUIRE;
Ted Lemon's avatar
Ted Lemon committed
819 820 821 822 823 824
		if (!strcasecmp (atom + 1, "etry"))
			return RETRY;
		if (!strcasecmp (atom + 1, "enew"))
			return RENEW;
		if (!strcasecmp (atom + 1, "ebind"))
			return REBIND;
Ted Lemon's avatar
Ted Lemon committed
825 826
		if (!strcasecmp (atom + 1, "eboot"))
			return REBOOT;
Ted Lemon's avatar
Ted Lemon committed
827 828
		if (!strcasecmp (atom + 1, "eject"))
			return REJECT;
829 830
		if (!strcasecmp (atom + 1, "everse"))
			return REVERSE;
831 832
		if (!strcasecmp (atom + 1, "elease"))
			return RELEASE;
833 834
		if (!strcasecmp (atom + 1, "efused"))
			return NS_REFUSED;
835 836
		break;
	      case 's':
837 838 839 840
		if (!strcasecmp (atom + 1, "ervfail"))
			return NS_SERVFAIL;
		if (!strcasecmp (atom + 1, "witch"))
			return SWITCH;
841 842 843 844
		if (!strcasecmp (atom + 1, "igned"))
			return SIGNED;
		if (!strcasecmp (atom + 1, "tring"))
			return STRING;
845 846
		if (!strcasecmp (atom + 1, "uffix"))
			return SUFFIX;
847 848
		if (!strcasecmp (atom + 1, "earch"))
			return SEARCH;
849 850
		if (!strcasecmp (atom + 1, "tarts"))
			return STARTS;
851 852
		if (!strcasecmp (atom + 1, "iaddr"))
			return SIADDR;
Ted Lemon's avatar
Ted Lemon committed
853 854
		if (!strcasecmp (atom + 1, "hared-network"))
			return SHARED_NETWORK;
855 856
		if (!strcasecmp (atom + 1, "econdary"))
			return SECONDARY;
Ted Lemon's avatar
Ted Lemon committed
857 858 859 860
		if (!strcasecmp (atom + 1, "erver-name"))
			return SERVER_NAME;
		if (!strcasecmp (atom + 1, "erver-identifier"))
			return SERVER_IDENTIFIER;
Ted Lemon's avatar
Ted Lemon committed
861 862
		if (!strcasecmp (atom + 1, "elect-timeout"))
			return SELECT_TIMEOUT;
Ted Lemon's avatar
Ted Lemon committed
863 864
		if (!strcasecmp (atom + 1, "end"))
			return SEND;
Ted Lemon's avatar
Ted Lemon committed
865 866
		if (!strcasecmp (atom + 1, "cript"))
			return SCRIPT;
867 868
		if (!strcasecmp (atom + 1, "upersede"))
			return SUPERSEDE;
869 870 871 872 873 874 875 876 877 878 879
		if (!strncasecmp (atom + 1, "ub", 2)) {
			if (!strcasecmp (atom + 3, "string"))
				return SUBSTRING;
			if (!strcasecmp (atom + 3, "net"))
				return SUBNET;
			if (!strcasecmp (atom + 3, "class"))
				return SUBCLASS;
			break;
		}
		if (!strcasecmp (atom + 1, "pawn"))
			return SPAWN;
Ted Lemon's avatar
Ted Lemon committed
880 881
		if (!strcasecmp (atom + 1, "pace"))
			return SPACE;
882 883
		if (!strcasecmp (atom + 1, "tatic"))
			return STATIC;
884
		if (!strcasecmp (atom + 1, "plit"))
885 886 887
			return SPLIT;
		if (!strcasecmp (atom + 1, "et"))
			return TOKEN_SET;
888 889
		break;
	      case 't':
890 891
		if (!strcasecmp (atom + 1, "sig-key"))
			return TSIG_KEY;
Ted Lemon's avatar
Ted Lemon committed
892
		if (!strcasecmp (atom + 1, "imestamp"))
893
			return TIMESTAMP;
Ted Lemon's avatar
Ted Lemon committed
894 895
		if (!strcasecmp (atom + 1, "imeout"))
			return TIMEOUT;
896 897
		if (!strcasecmp (atom + 1, "oken-ring"))
			return TOKEN_RING;
898 899
		if (!strcasecmp (atom + 1, "ext"))
			return TEXT;
900 901 902 903
		if (!strcasecmp (atom + 1, "stp"))
			return TSTP;
		if (!strcasecmp (atom + 1, "sfp"))
			return TSFP;
904 905
		break;
	      case 'u':
Ted Lemon's avatar
Ted Lemon committed
906 907
		if (!strcasecmp (atom + 1, "nset"))
			return UNSET;
908 909
		if (!strcasecmp (atom + 1, "nsigned"))
			return UNSIGNED;
910 911
		if (!strcasecmp (atom + 1, "id"))
			return UID;
912 913 914 915 916 917 918 919 920 921
		if (!strncasecmp (atom + 1, "se", 2)) {
			if (!strcasecmp (atom + 3, "r-class"))
				return USER_CLASS;
			if (!strcasecmp (atom + 3, "-host-decl-names"))
				return USE_HOST_DECL_NAMES;
			if (!strcasecmp (atom + 3,
					 "-lease-addr-for-default-route"))
				return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE;
			break;
		}
922 923 924 925 926 927 928 929 930
		if (!strncasecmp (atom + 1, "nknown", 6)) {
			if (!strcasecmp (atom + 7, "-clients"))
				return UNKNOWN_CLIENTS;
			if (!atom [7])
				return UNKNOWN;
			break;
		}
		if (!strcasecmp (atom + 1, "nauthenticated"))
			return AUTHENTICATED;
931 932
		if (!strcasecmp (atom + 1, "pdated-dns-rr"))
			return UPDATED_DNS_RR;
933 934
		if (!strcasecmp (atom + 1, "pdate"))
			return UPDATE;
Ted Lemon's avatar
Ted Lemon committed
935 936 937 938
		break;
	      case 'v':
		if (!strcasecmp (atom + 1, "endor-class"))
			return VENDOR_CLASS;
939
		break;
940 941 942 943
	      case 'w':
		if (!strcasecmp (atom + 1, "ith"))
			return WITH;
		break;
944 945 946
	      case 'y':
		if (!strcasecmp (atom + 1, "iaddr"))
			return YIADDR;
947 948 949 950
		if (!strcasecmp (atom + 1, "xdomain"))
			return NS_YXDOMAIN;
		if (!strcasecmp (atom + 1, "xrrset"))
			return NS_YXRRSET;
951
		break;
Ted Lemon's avatar
Ted Lemon committed
952 953 954 955
	      case 'z':
		if (!strcasecmp (atom + 1, "one"))
			return ZONE;
		break;
Ted Lemon's avatar
Ted Lemon committed
956 957 958
	}
	return dfv;
}