1074 lines
27 KiB
C
1074 lines
27 KiB
C
/* conflex.c
|
|
|
|
Lexical scanner for dhcpd config file... */
|
|
|
|
/*
|
|
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
|
|
* Copyright (c) 1995-2003 by Internet Software Consortium
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Internet Systems Consortium, Inc.
|
|
* 950 Charter Street
|
|
* Redwood City, CA 94063
|
|
* <info@isc.org>
|
|
* http://www.isc.org/
|
|
*
|
|
* This software has been written for Internet Systems Consortium
|
|
* by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
|
|
* To learn more about Internet Systems 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''.
|
|
*/
|
|
|
|
#ifndef lint
|
|
static char copyright[] =
|
|
"$Id: conflex.c,v 1.92.2.7 2004/06/10 17:59:14 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
|
|
#endif /* not lint */
|
|
|
|
#include "dhcpd.h"
|
|
#include <ctype.h>
|
|
|
|
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));
|
|
|
|
isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
|
|
struct parse **cfile;
|
|
int file;
|
|
char *inbuf;
|
|
unsigned buflen;
|
|
const char *name;
|
|
int eolp;
|
|
{
|
|
struct parse *tmp;
|
|
|
|
tmp = dmalloc (sizeof (struct parse), MDL);
|
|
if (!tmp)
|
|
return ISC_R_NOMEMORY;
|
|
memset (tmp, 0, sizeof *tmp);
|
|
|
|
tmp -> token = 0;
|
|
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;
|
|
tmp -> eol_token = eolp;
|
|
|
|
tmp -> bufix = 0;
|
|
tmp -> buflen = buflen;
|
|
if (inbuf) {
|
|
tmp -> bufsiz = 0;
|
|
tmp -> inbuf = inbuf;
|
|
} else {
|
|
tmp -> inbuf = dmalloc (8192, MDL);
|
|
if (!tmp -> inbuf) {
|
|
dfree (tmp, MDL);
|
|
return ISC_R_NOMEMORY;
|
|
}
|
|
tmp -> bufsiz = 8192;
|
|
}
|
|
|
|
*cfile = tmp;
|
|
return ISC_R_SUCCESS;
|
|
}
|
|
|
|
isc_result_t end_parse (cfile)
|
|
struct parse **cfile;
|
|
{
|
|
if ((*cfile) -> bufsiz)
|
|
dfree ((*cfile) -> inbuf, MDL);
|
|
dfree (*cfile, MDL);
|
|
*cfile = (struct parse *)0;
|
|
return ISC_R_SUCCESS;
|
|
}
|
|
|
|
static int get_char (cfile)
|
|
struct parse *cfile;
|
|
{
|
|
/* 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) {
|
|
if (c == EOL) {
|
|
if (cfile -> cur_line == cfile -> line1) {
|
|
cfile -> cur_line = cfile -> line2;
|
|
cfile -> prev_line = cfile -> line1;
|
|
} else {
|
|
cfile -> cur_line = cfile -> line1;
|
|
cfile -> prev_line = cfile -> line2;
|
|
}
|
|
cfile -> line++;
|
|
cfile -> lpos = 1;
|
|
cfile -> cur_line [0] = 0;
|
|
} else if (c != EOF) {
|
|
if (cfile -> lpos <= 80) {
|
|
cfile -> cur_line [cfile -> lpos - 1] = c;
|
|
cfile -> cur_line [cfile -> lpos] = 0;
|
|
}
|
|
cfile -> lpos++;
|
|
}
|
|
} else
|
|
cfile -> ugflag = 0;
|
|
return c;
|
|
}
|
|
|
|
static enum dhcp_token get_token (cfile)
|
|
struct parse *cfile;
|
|
{
|
|
int c;
|
|
enum dhcp_token ttok;
|
|
static char tb [2];
|
|
int l, p, u;
|
|
|
|
do {
|
|
l = cfile -> line;
|
|
p = cfile -> lpos;
|
|
u = cfile -> ugflag;
|
|
|
|
c = get_char (cfile);
|
|
#ifdef OLD_LEXER
|
|
if (c == '\n' && p == 1 && !u
|
|
&& cfile -> comment_index < sizeof cfile -> comments)
|
|
cfile -> comments [cfile -> comment_index++] = '\n';
|
|
#endif
|
|
|
|
if (!(c == '\n' && cfile -> eol_token)
|
|
&& isascii (c) && isspace (c))
|
|
continue;
|
|
if (c == '#') {
|
|
#ifdef OLD_LEXER
|
|
if (cfile -> comment_index < sizeof cfile -> comments)
|
|
cfile -> comments [cfile -> comment_index++] = '#';
|
|
#endif
|
|
skip_to_eol (cfile);
|
|
continue;
|
|
}
|
|
if (c == '"') {
|
|
cfile -> lexline = l;
|
|
cfile -> lexchar = p;
|
|
ttok = read_string (cfile);
|
|
break;
|
|
}
|
|
if ((isascii (c) && isdigit (c)) || c == '-') {
|
|
cfile -> lexline = l;
|
|
cfile -> lexchar = p;
|
|
ttok = read_number (c, cfile);
|
|
break;
|
|
} else if (isascii (c) && isalpha (c)) {
|
|
cfile -> lexline = l;
|
|
cfile -> lexchar = p;
|
|
ttok = read_num_or_name (c, cfile);
|
|
break;
|
|
} else if (c == EOF) {
|
|
ttok = END_OF_FILE;
|
|
cfile -> tlen = 0;
|
|
break;
|
|
} else {
|
|
cfile -> lexline = l;
|
|
cfile -> lexchar = p;
|
|
tb [0] = c;
|
|
tb [1] = 0;
|
|
cfile -> tval = tb;
|
|
cfile -> tlen = 1;
|
|
ttok = c;
|
|
break;
|
|
}
|
|
} while (1);
|
|
return ttok;
|
|
}
|
|
|
|
enum dhcp_token next_token (rval, rlen, cfile)
|
|
const char **rval;
|
|
unsigned *rlen;
|
|
struct parse *cfile;
|
|
{
|
|
int rv;
|
|
|
|
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;
|
|
} else {
|
|
rv = get_token (cfile);
|
|
cfile -> token_line = cfile -> cur_line;
|
|
}
|
|
if (rval)
|
|
*rval = cfile -> tval;
|
|
if (rlen)
|
|
*rlen = cfile -> tlen;
|
|
#ifdef DEBUG_TOKENS
|
|
fprintf (stderr, "%s:%d ", cfile -> tval, rv);
|
|
#endif
|
|
return rv;
|
|
}
|
|
|
|
enum dhcp_token peek_token (rval, rlen, cfile)
|
|
const char **rval;
|
|
unsigned int *rlen;
|
|
struct parse *cfile;
|
|
{
|
|
int x;
|
|
|
|
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;
|
|
}
|
|
if (rval)
|
|
*rval = cfile -> tval;
|
|
if (rlen)
|
|
*rlen = cfile -> tlen;
|
|
#ifdef DEBUG_TOKENS
|
|
fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
|
|
#endif
|
|
return cfile -> token;
|
|
}
|
|
|
|
static void skip_to_eol (cfile)
|
|
struct parse *cfile;
|
|
{
|
|
int c;
|
|
do {
|
|
c = get_char (cfile);
|
|
if (c == EOF)
|
|
return;
|
|
#ifdef OLD_LEXER
|
|
if (cfile -> comment_index < sizeof (cfile -> comments))
|
|
comments [cfile -> comment_index++] = c;
|
|
#endif
|
|
if (c == EOL) {
|
|
return;
|
|
}
|
|
} while (1);
|
|
}
|
|
|
|
static enum dhcp_token read_string (cfile)
|
|
struct parse *cfile;
|
|
{
|
|
int i;
|
|
int bs = 0;
|
|
int c;
|
|
int value;
|
|
int hex;
|
|
|
|
for (i = 0; i < sizeof cfile -> tokbuf; i++) {
|
|
again:
|
|
c = get_char (cfile);
|
|
if (c == EOF) {
|
|
parse_warn (cfile, "eof in string constant");
|
|
break;
|
|
}
|
|
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;
|
|
}
|
|
bs = 0;
|
|
} 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 == '\\') {
|
|
bs = 1;
|
|
goto again;
|
|
} else if (c == '"')
|
|
break;
|
|
else
|
|
cfile -> tokbuf [i] = c;
|
|
}
|
|
/* Normally, I'd feel guilty about this, but we're talking about
|
|
strings that'll fit in a DHCP packet here... */
|
|
if (i == sizeof cfile -> tokbuf) {
|
|
parse_warn (cfile,
|
|
"string constant larger than internal buffer");
|
|
--i;
|
|
}
|
|
cfile -> tokbuf [i] = 0;
|
|
cfile -> tlen = i;
|
|
cfile -> tval = cfile -> tokbuf;
|
|
return STRING;
|
|
}
|
|
|
|
static enum dhcp_token read_number (c, cfile)
|
|
int c;
|
|
struct parse *cfile;
|
|
{
|
|
int seenx = 0;
|
|
int i = 0;
|
|
int token = NUMBER;
|
|
|
|
cfile -> tokbuf [i++] = c;
|
|
for (; i < sizeof cfile -> tokbuf; i++) {
|
|
c = get_char (cfile);
|
|
if (!seenx && c == 'x') {
|
|
seenx = 1;
|
|
#ifndef OLD_LEXER
|
|
} else if (isascii (c) && !isxdigit (c) &&
|
|
(c == '-' || c == '_' || isalpha (c))) {
|
|
token = NAME;
|
|
} else if (isascii (c) && !isdigit (c) && isxdigit (c)) {
|
|
token = NUMBER_OR_NAME;
|
|
#endif
|
|
} else if (!isascii (c) || !isxdigit (c)) {
|
|
if (c != EOF) {
|
|
cfile -> bufix--;
|
|
cfile -> ugflag = 1;
|
|
}
|
|
break;
|
|
}
|
|
cfile -> tokbuf [i] = c;
|
|
}
|
|
if (i == sizeof cfile -> tokbuf) {
|
|
parse_warn (cfile,
|
|
"numeric token larger than internal buffer");
|
|
--i;
|
|
}
|
|
cfile -> tokbuf [i] = 0;
|
|
cfile -> tlen = i;
|
|
cfile -> tval = cfile -> tokbuf;
|
|
return token;
|
|
}
|
|
|
|
static enum dhcp_token read_num_or_name (c, cfile)
|
|
int c;
|
|
struct parse *cfile;
|
|
{
|
|
int i = 0;
|
|
enum dhcp_token rv = NUMBER_OR_NAME;
|
|
cfile -> tokbuf [i++] = c;
|
|
for (; i < sizeof cfile -> tokbuf; i++) {
|
|
c = get_char (cfile);
|
|
if (!isascii (c) ||
|
|
(c != '-' && c != '_' && !isalnum (c))) {
|
|
if (c != EOF) {
|
|
cfile -> bufix--;
|
|
cfile -> ugflag = 1;
|
|
}
|
|
break;
|
|
}
|
|
if (!isxdigit (c))
|
|
rv = NAME;
|
|
cfile -> tokbuf [i] = c;
|
|
}
|
|
if (i == sizeof cfile -> tokbuf) {
|
|
parse_warn (cfile, "token larger than internal buffer");
|
|
--i;
|
|
}
|
|
cfile -> tokbuf [i] = 0;
|
|
cfile -> tlen = i;
|
|
cfile -> tval = cfile -> tokbuf;
|
|
return intern (cfile -> tval, rv);
|
|
}
|
|
|
|
static enum dhcp_token intern (atom, dfv)
|
|
char *atom;
|
|
enum dhcp_token dfv;
|
|
{
|
|
if (!isascii (atom [0]))
|
|
return dfv;
|
|
|
|
switch (tolower (atom [0])) {
|
|
case '-':
|
|
if (atom [1] == 0)
|
|
return MINUS;
|
|
break;
|
|
|
|
case 'a':
|
|
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;
|
|
break;
|
|
}
|
|
if (!strcasecmp (atom + 1, "nd"))
|
|
return AND;
|
|
if (!strcasecmp (atom + 1, "ppend"))
|
|
return APPEND;
|
|
if (!strcasecmp (atom + 1, "llow"))
|
|
return ALLOW;
|
|
if (!strcasecmp (atom + 1, "lias"))
|
|
return ALIAS;
|
|
if (!strcasecmp (atom + 1, "lgorithm"))
|
|
return ALGORITHM;
|
|
if (!strcasecmp (atom + 1, "bandoned"))
|
|
return TOKEN_ABANDONED;
|
|
if (!strcasecmp (atom + 1, "dd"))
|
|
return TOKEN_ADD;
|
|
if (!strcasecmp (atom + 1, "ll"))
|
|
return ALL;
|
|
if (!strcasecmp (atom + 1, "t"))
|
|
return AT;
|
|
if (!strcasecmp (atom + 1, "rray"))
|
|
return ARRAY;
|
|
if (!strcasecmp (atom + 1, "ddress"))
|
|
return ADDRESS;
|
|
if (!strcasecmp (atom + 1, "ctive"))
|
|
return TOKEN_ACTIVE;
|
|
break;
|
|
case 'b':
|
|
if (!strcasecmp (atom + 1, "ackup"))
|
|
return TOKEN_BACKUP;
|
|
if (!strcasecmp (atom + 1, "ootp"))
|
|
return TOKEN_BOOTP;
|
|
if (!strcasecmp (atom + 1, "inding"))
|
|
return BINDING;
|
|
if (!strcasecmp (atom + 1, "inary-to-ascii"))
|
|
return BINARY_TO_ASCII;
|
|
if (!strcasecmp (atom + 1, "ackoff-cutoff"))
|
|
return BACKOFF_CUTOFF;
|
|
if (!strcasecmp (atom + 1, "ooting"))
|
|
return BOOTING;
|
|
if (!strcasecmp (atom + 1, "oot-unknown-clients"))
|
|
return BOOT_UNKNOWN_CLIENTS;
|
|
if (!strcasecmp (atom + 1, "reak"))
|
|
return BREAK;
|
|
if (!strcasecmp (atom + 1, "illing"))
|
|
return BILLING;
|
|
if (!strcasecmp (atom + 1, "oolean"))
|
|
return BOOLEAN;
|
|
if (!strcasecmp (atom + 1, "alance"))
|
|
return BALANCE;
|
|
if (!strcasecmp (atom + 1, "ound"))
|
|
return BOUND;
|
|
break;
|
|
case 'c':
|
|
if (!strcasecmp (atom + 1, "ase"))
|
|
return CASE;
|
|
if (!strcasecmp (atom + 1, "ommit"))
|
|
return COMMIT;
|
|
if (!strcasecmp (atom + 1, "ode"))
|
|
return CODE;
|
|
if (!strcasecmp (atom + 1, "onfig-option"))
|
|
return CONFIG_OPTION;
|
|
if (!strcasecmp (atom + 1, "heck"))
|
|
return CHECK;
|
|
if (!strcasecmp (atom + 1, "lass"))
|
|
return CLASS;
|
|
if (!strcasecmp (atom + 1, "lose"))
|
|
return TOKEN_CLOSE;
|
|
if (!strcasecmp (atom + 1, "reate"))
|
|
return TOKEN_CREATE;
|
|
if (!strcasecmp (atom + 1, "iaddr"))
|
|
return CIADDR;
|
|
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, "-state"))
|
|
return CLIENT_STATE;
|
|
if (!strcasecmp (atom + 6, "-updates"))
|
|
return CLIENT_UPDATES;
|
|
if (!strcasecmp (atom + 6, "s"))
|
|
return CLIENTS;
|
|
}
|
|
if (!strcasecmp (atom + 1, "oncat"))
|
|
return CONCAT;
|
|
if (!strcasecmp (atom + 1, "onnect"))
|
|
return CONNECT;
|
|
if (!strcasecmp (atom + 1, "ommunications-interrupted"))
|
|
return COMMUNICATIONS_INTERRUPTED;
|
|
if (!strcasecmp (atom + 1, "ltt"))
|
|
return CLTT;
|
|
break;
|
|
case 'd':
|
|
if (!strcasecmp (atom + 1, "ns-update"))
|
|
return DNS_UPDATE;
|
|
if (!strcasecmp (atom + 1, "ns-delete"))
|
|
return DNS_DELETE;
|
|
if (!strcasecmp (atom + 1, "omain"))
|
|
return DOMAIN;
|
|
if (!strcasecmp (atom + 1, "omain-name"))
|
|
return DOMAIN_NAME;
|
|
if (!strcasecmp (atom + 1, "o-forward-update"))
|
|
return DO_FORWARD_UPDATE;
|
|
if (!strcasecmp (atom + 1, "ebug"))
|
|
return TOKEN_DEBUG;
|
|
if (!strcasecmp (atom + 1, "eny"))
|
|
return DENY;
|
|
if (!strcasecmp (atom + 1, "eleted"))
|
|
return TOKEN_DELETED;
|
|
if (!strcasecmp (atom + 1, "elete"))
|
|
return TOKEN_DELETE;
|
|
if (!strncasecmp (atom + 1, "efault", 6)) {
|
|
if (!atom [7])
|
|
return DEFAULT;
|
|
if (!strcasecmp (atom + 7, "-lease-time"))
|
|
return DEFAULT_LEASE_TIME;
|
|
break;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
if (!strcasecmp (atom + 1, "uplicates"))
|
|
return DUPLICATES;
|
|
if (!strcasecmp (atom + 1, "eclines"))
|
|
return DECLINES;
|
|
if (!strncasecmp (atom + 1, "efine", 5)) {
|
|
if (!strcasecmp (atom + 6, "d"))
|
|
return DEFINED;
|
|
if (!atom [6])
|
|
return DEFINE;
|
|
}
|
|
break;
|
|
case 'e':
|
|
if (isascii (atom [1]) && tolower (atom [1]) == 'x') {
|
|
if (!strcasecmp (atom + 2, "tract-int"))
|
|
return EXTRACT_INT;
|
|
if (!strcasecmp (atom + 2, "ists"))
|
|
return EXISTS;
|
|
if (!strcasecmp (atom + 2, "piry"))
|
|
return EXPIRY;
|
|
if (!strcasecmp (atom + 2, "pire"))
|
|
return EXPIRE;
|
|
if (!strcasecmp (atom + 2, "pired"))
|
|
return TOKEN_EXPIRED;
|
|
}
|
|
if (!strcasecmp (atom + 1, "ncode-int"))
|
|
return ENCODE_INT;
|
|
if (!strcasecmp (atom + 1, "thernet"))
|
|
return ETHERNET;
|
|
if (!strcasecmp (atom + 1, "nds"))
|
|
return ENDS;
|
|
if (!strncasecmp (atom + 1, "ls", 2)) {
|
|
if (!strcasecmp (atom + 3, "e"))
|
|
return ELSE;
|
|
if (!strcasecmp (atom + 3, "if"))
|
|
return ELSIF;
|
|
break;
|
|
}
|
|
if (!strcasecmp (atom + 1, "rror"))
|
|
return ERROR;
|
|
if (!strcasecmp (atom + 1, "val"))
|
|
return EVAL;
|
|
if (!strcasecmp (atom + 1, "ncapsulate"))
|
|
return ENCAPSULATE;
|
|
break;
|
|
case 'f':
|
|
if (!strcasecmp (atom + 1, "atal"))
|
|
return FATAL;
|
|
if (!strcasecmp (atom + 1, "ilename"))
|
|
return FILENAME;
|
|
if (!strcasecmp (atom + 1, "ixed-address"))
|
|
return FIXED_ADDR;
|
|
if (!strcasecmp (atom + 1, "ddi"))
|
|
return FDDI;
|
|
if (!strcasecmp (atom + 1, "ormerr"))
|
|
return NS_FORMERR;
|
|
if (!strcasecmp (atom + 1, "unction"))
|
|
return FUNCTION;
|
|
if (!strcasecmp (atom + 1, "ailover"))
|
|
return FAILOVER;
|
|
if (!strcasecmp (atom + 1, "ree"))
|
|
return TOKEN_FREE;
|
|
break;
|
|
case 'g':
|
|
if (!strcasecmp (atom + 1, "iaddr"))
|
|
return GIADDR;
|
|
if (!strcasecmp (atom + 1, "roup"))
|
|
return GROUP;
|
|
if (!strcasecmp (atom + 1, "et-lease-hostnames"))
|
|
return GET_LEASE_HOSTNAMES;
|
|
break;
|
|
case 'h':
|
|
if (!strcasecmp (atom + 1, "ba"))
|
|
return HBA;
|
|
if (!strcasecmp (atom + 1, "ost"))
|
|
return HOST;
|
|
if (!strcasecmp (atom + 1, "ost-decl-name"))
|
|
return HOST_DECL_NAME;
|
|
if (!strcasecmp (atom + 1, "ardware"))
|
|
return HARDWARE;
|
|
if (!strcasecmp (atom + 1, "ostname"))
|
|
return HOSTNAME;
|
|
if (!strcasecmp (atom + 1, "elp"))
|
|
return TOKEN_HELP;
|
|
break;
|
|
case 'i':
|
|
if (!strcasecmp (atom + 1, "nclude"))
|
|
return INCLUDE;
|
|
if (!strcasecmp (atom + 1, "nteger"))
|
|
return INTEGER;
|
|
if (!strcasecmp (atom + 1, "nfinite"))
|
|
return INFINITE;
|
|
if (!strcasecmp (atom + 1, "nfo"))
|
|
return INFO;
|
|
if (!strcasecmp (atom + 1, "p-address"))
|
|
return IP_ADDRESS;
|
|
if (!strcasecmp (atom + 1, "nitial-interval"))
|
|
return INITIAL_INTERVAL;
|
|
if (!strcasecmp (atom + 1, "nterface"))
|
|
return INTERFACE;
|
|
if (!strcasecmp (atom + 1, "dentifier"))
|
|
return IDENTIFIER;
|
|
if (!strcasecmp (atom + 1, "f"))
|
|
return IF;
|
|
if (!strcasecmp (atom + 1, "s"))
|
|
return IS;
|
|
if (!strcasecmp (atom + 1, "gnore"))
|
|
return IGNORE;
|
|
break;
|
|
case 'k':
|
|
if (!strcasecmp (atom + 1, "nown"))
|
|
return KNOWN;
|
|
if (!strcasecmp (atom + 1, "ey"))
|
|
return KEY;
|
|
break;
|
|
case 'l':
|
|
if (!strcasecmp (atom + 1, "ease"))
|
|
return LEASE;
|
|
if (!strcasecmp (atom + 1, "eased-address"))
|
|
return LEASED_ADDRESS;
|
|
if (!strcasecmp (atom + 1, "ease-time"))
|
|
return LEASE_TIME;
|
|
if (!strcasecmp (atom + 1, "imit"))
|
|
return LIMIT;
|
|
if (!strcasecmp (atom + 1, "et"))
|
|
return LET;
|
|
if (!strcasecmp (atom + 1, "oad"))
|
|
return LOAD;
|
|
if (!strcasecmp (atom + 1, "og"))
|
|
return LOG;
|
|
break;
|
|
case 'm':
|
|
if (!strncasecmp (atom + 1, "ax", 2)) {
|
|
if (!atom [3])
|
|
return TOKEN_MAX;
|
|
if (!strcasecmp (atom + 3, "-lease-time"))
|
|
return MAX_LEASE_TIME;
|
|
if (!strcasecmp (atom + 3, "-transmit-idle"))
|
|
return MAX_TRANSMIT_IDLE;
|
|
if (!strcasecmp (atom + 3, "-response-delay"))
|
|
return MAX_RESPONSE_DELAY;
|
|
if (!strcasecmp (atom + 3, "-unacked-updates"))
|
|
return MAX_UNACKED_UPDATES;
|
|
}
|
|
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;
|
|
}
|
|
if (!strncasecmp (atom + 1, "edi", 3)) {
|
|
if (!strcasecmp (atom + 4, "a"))
|
|
return MEDIA;
|
|
if (!strcasecmp (atom + 4, "um"))
|
|
return MEDIUM;
|
|
break;
|
|
}
|
|
if (!strcasecmp (atom + 1, "atch"))
|
|
return MATCH;
|
|
if (!strcasecmp (atom + 1, "embers"))
|
|
return MEMBERS;
|
|
if (!strcasecmp (atom + 1, "y"))
|
|
return MY;
|
|
if (!strcasecmp (atom + 1, "clt"))
|
|
return MCLT;
|
|
break;
|
|
case 'n':
|
|
if (!strcasecmp (atom + 1, "ormal"))
|
|
return NORMAL;
|
|
if (!strcasecmp (atom + 1, "ameserver"))
|
|
return NAMESERVER;
|
|
if (!strcasecmp (atom + 1, "etmask"))
|
|
return NETMASK;
|
|
if (!strcasecmp (atom + 1, "ever"))
|
|
return NEVER;
|
|
if (!strcasecmp (atom + 1, "ext-server"))
|
|
return NEXT_SERVER;
|
|
if (!strcasecmp (atom + 1, "ot"))
|
|
return TOKEN_NOT;
|
|
if (!strcasecmp (atom + 1, "o"))
|
|
return NO;
|
|
if (!strcasecmp (atom + 1, "s-update"))
|
|
return NS_UPDATE;
|
|
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;
|
|
if (!strcasecmp (atom + 1, "ext"))
|
|
return TOKEN_NEXT;
|
|
if (!strcasecmp (atom + 1, "ew"))
|
|
return TOKEN_NEW;
|
|
break;
|
|
case 'o':
|
|
if (!strcasecmp (atom + 1, "mapi"))
|
|
return OMAPI;
|
|
if (!strcasecmp (atom + 1, "r"))
|
|
return OR;
|
|
if (!strcasecmp (atom + 1, "n"))
|
|
return ON;
|
|
if (!strcasecmp (atom + 1, "pen"))
|
|
return TOKEN_OPEN;
|
|
if (!strcasecmp (atom + 1, "ption"))
|
|
return OPTION;
|
|
if (!strcasecmp (atom + 1, "ne-lease-per-client"))
|
|
return ONE_LEASE_PER_CLIENT;
|
|
if (!strcasecmp (atom + 1, "f"))
|
|
return OF;
|
|
if (!strcasecmp (atom + 1, "wner"))
|
|
return OWNER;
|
|
break;
|
|
case 'p':
|
|
if (!strcasecmp (atom + 1, "repend"))
|
|
return PREPEND;
|
|
if (!strcasecmp (atom + 1, "acket"))
|
|
return PACKET;
|
|
if (!strcasecmp (atom + 1, "ool"))
|
|
return POOL;
|
|
if (!strcasecmp (atom + 1, "seudo"))
|
|
return PSEUDO;
|
|
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;
|
|
if (!strcasecmp (atom + 1, "ick-first-value") ||
|
|
!strcasecmp (atom + 1, "ick"))
|
|
return PICK;
|
|
if (!strcasecmp (atom + 1, "aused"))
|
|
return PAUSED;
|
|
break;
|
|
case 'r':
|
|
if (!strcasecmp (atom + 1, "esolution-interrupted"))
|
|
return RESOLUTION_INTERRUPTED;
|
|
if (!strcasecmp (atom + 1, "ange"))
|
|
return RANGE;
|
|
if (!strcasecmp (atom + 1, "ecover"))
|
|
return RECOVER;
|
|
if (!strcasecmp (atom + 1, "ecover-done"))
|
|
return RECOVER_DONE;
|
|
if (!strcasecmp (atom + 1, "ecover-wait"))
|
|
return RECOVER_WAIT;
|
|
if (!strcasecmp (atom + 1, "econtact-interval"))
|
|
return RECONTACT_INTERVAL;
|
|
if (!strcasecmp (atom + 1, "equest"))
|
|
return REQUEST;
|
|
if (!strcasecmp (atom + 1, "equire"))
|
|
return REQUIRE;
|
|
if (!strcasecmp (atom + 1, "equire"))
|
|
return REQUIRE;
|
|
if (!strcasecmp (atom + 1, "etry"))
|
|
return RETRY;
|
|
if (!strcasecmp (atom + 1, "eturn"))
|
|
return RETURN;
|
|
if (!strcasecmp (atom + 1, "enew"))
|
|
return RENEW;
|
|
if (!strcasecmp (atom + 1, "ebind"))
|
|
return REBIND;
|
|
if (!strcasecmp (atom + 1, "eboot"))
|
|
return REBOOT;
|
|
if (!strcasecmp (atom + 1, "eject"))
|
|
return REJECT;
|
|
if (!strcasecmp (atom + 1, "everse"))
|
|
return REVERSE;
|
|
if (!strcasecmp (atom + 1, "elease"))
|
|
return RELEASE;
|
|
if (!strcasecmp (atom + 1, "efused"))
|
|
return NS_REFUSED;
|
|
if (!strcasecmp (atom + 1, "eleased"))
|
|
return TOKEN_RELEASED;
|
|
if (!strcasecmp (atom + 1, "eset"))
|
|
return TOKEN_RESET;
|
|
if (!strcasecmp (atom + 1, "eserved"))
|
|
return TOKEN_RESERVED;
|
|
if (!strcasecmp (atom + 1, "emove"))
|
|
return REMOVE;
|
|
if (!strcasecmp (atom + 1, "efresh"))
|
|
return REFRESH;
|
|
break;
|
|
case 's':
|
|
if (!strcasecmp (atom + 1, "tate"))
|
|
return STATE;
|
|
if (!strcasecmp (atom + 1, "ecret"))
|
|
return SECRET;
|
|
if (!strcasecmp (atom + 1, "ervfail"))
|
|
return NS_SERVFAIL;
|
|
if (!strcasecmp (atom + 1, "witch"))
|
|
return SWITCH;
|
|
if (!strcasecmp (atom + 1, "igned"))
|
|
return SIGNED;
|
|
if (!strcasecmp (atom + 1, "tring"))
|
|
return STRING_TOKEN;
|
|
if (!strcasecmp (atom + 1, "uffix"))
|
|
return SUFFIX;
|
|
if (!strcasecmp (atom + 1, "earch"))
|
|
return SEARCH;
|
|
if (!strcasecmp (atom + 1, "tarts"))
|
|
return STARTS;
|
|
if (!strcasecmp (atom + 1, "iaddr"))
|
|
return SIADDR;
|
|
if (!strcasecmp (atom + 1, "hared-network"))
|
|
return SHARED_NETWORK;
|
|
if (!strcasecmp (atom + 1, "econdary"))
|
|
return SECONDARY;
|
|
if (!strcasecmp (atom + 1, "erver-name"))
|
|
return SERVER_NAME;
|
|
if (!strcasecmp (atom + 1, "erver-identifier"))
|
|
return SERVER_IDENTIFIER;
|
|
if (!strcasecmp (atom + 1, "erver"))
|
|
return SERVER;
|
|
if (!strcasecmp (atom + 1, "elect-timeout"))
|
|
return SELECT_TIMEOUT;
|
|
if (!strcasecmp (atom + 1, "elect"))
|
|
return SELECT;
|
|
if (!strcasecmp (atom + 1, "end"))
|
|
return SEND;
|
|
if (!strcasecmp (atom + 1, "cript"))
|
|
return SCRIPT;
|
|
if (!strcasecmp (atom + 1, "upersede"))
|
|
return SUPERSEDE;
|
|
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;
|
|
if (!strcasecmp (atom + 1, "pace"))
|
|
return SPACE;
|
|
if (!strcasecmp (atom + 1, "tatic"))
|
|
return STATIC;
|
|
if (!strcasecmp (atom + 1, "plit"))
|
|
return SPLIT;
|
|
if (!strcasecmp (atom + 1, "et"))
|
|
return TOKEN_SET;
|
|
if (!strcasecmp (atom + 1, "econds"))
|
|
return SECONDS;
|
|
if (!strcasecmp (atom + 1, "hutdown"))
|
|
return SHUTDOWN;
|
|
if (!strcasecmp (atom + 1, "tartup"))
|
|
return STARTUP;
|
|
break;
|
|
case 't':
|
|
if (!strcasecmp (atom + 1, "imestamp"))
|
|
return TIMESTAMP;
|
|
if (!strcasecmp (atom + 1, "imeout"))
|
|
return TIMEOUT;
|
|
if (!strcasecmp (atom + 1, "oken-ring"))
|
|
return TOKEN_RING;
|
|
if (!strcasecmp (atom + 1, "ext"))
|
|
return TEXT;
|
|
if (!strcasecmp (atom + 1, "stp"))
|
|
return TSTP;
|
|
if (!strcasecmp (atom + 1, "sfp"))
|
|
return TSFP;
|
|
if (!strcasecmp (atom + 1, "ransmission"))
|
|
return TRANSMISSION;
|
|
break;
|
|
case 'u':
|
|
if (!strcasecmp (atom + 1, "nset"))
|
|
return UNSET;
|
|
if (!strcasecmp (atom + 1, "nsigned"))
|
|
return UNSIGNED;
|
|
if (!strcasecmp (atom + 1, "id"))
|
|
return UID;
|
|
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;
|
|
}
|
|
if (!strncasecmp (atom + 1, "nknown", 6)) {
|
|
if (!strcasecmp (atom + 7, "-clients"))
|
|
return UNKNOWN_CLIENTS;
|
|
if (!strcasecmp (atom + 7, "-state"))
|
|
return UNKNOWN_STATE;
|
|
if (!atom [7])
|
|
return UNKNOWN;
|
|
break;
|
|
}
|
|
if (!strcasecmp (atom + 1, "nauthenticated"))
|
|
return AUTHENTICATED;
|
|
if (!strcasecmp (atom + 1, "pdated-dns-rr"))
|
|
return UPDATED_DNS_RR;
|
|
if (!strcasecmp (atom + 1, "pdate"))
|
|
return UPDATE;
|
|
break;
|
|
case 'v':
|
|
if (!strcasecmp (atom + 1, "endor-class"))
|
|
return VENDOR_CLASS;
|
|
if (!strcasecmp (atom + 1, "endor"))
|
|
return VENDOR;
|
|
break;
|
|
case 'w':
|
|
if (!strcasecmp (atom + 1, "ith"))
|
|
return WITH;
|
|
break;
|
|
case 'y':
|
|
if (!strcasecmp (atom + 1, "iaddr"))
|
|
return YIADDR;
|
|
if (!strcasecmp (atom + 1, "xdomain"))
|
|
return NS_YXDOMAIN;
|
|
if (!strcasecmp (atom + 1, "xrrset"))
|
|
return NS_YXRRSET;
|
|
break;
|
|
case 'z':
|
|
if (!strcasecmp (atom + 1, "one"))
|
|
return ZONE;
|
|
break;
|
|
}
|
|
return dfv;
|
|
}
|