diff options
Diffstat (limited to 'sbin/dhclient/conflex.c')
-rw-r--r-- | sbin/dhclient/conflex.c | 525 |
1 files changed, 525 insertions, 0 deletions
diff --git a/sbin/dhclient/conflex.c b/sbin/dhclient/conflex.c new file mode 100644 index 0000000..ee96bfe --- /dev/null +++ b/sbin/dhclient/conflex.c @@ -0,0 +1,525 @@ +/* $OpenBSD: conflex.c,v 1.7 2004/09/15 19:02:38 deraadt Exp $ */ + +/* Lexical scanner for dhcpd config file... */ + +/* + * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 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. + * + * 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 <mellon@fugue.com> in cooperation with Vixie + * Enterprises. To learn more about the Internet Software Consortium, + * see ``http://www.vix.com/isc''. To learn more about Vixie + * Enterprises, see ``http://www.vix.com''. + */ + +#include <ctype.h> + +#include "dhcpd.h" +#include "dhctoken.h" + +int lexline; +int lexchar; +char *token_line; +char *prev_line; +char *cur_line; +char *tlname; +int eol_token; + +static char line1[81]; +static char line2[81]; +static int lpos; +static int line; +static int tlpos; +static int tline; +static int token; +static int ugflag; +static char *tval; +static char tokbuf[1500]; + +static int get_char(FILE *); +static int get_token(FILE *); +static void skip_to_eol(FILE *); +static int read_string(FILE *); +static int read_number(int, FILE *); +static int read_num_or_name(int, FILE *); +static int intern(char *, int); + +void +new_parse(char *name) +{ + tlname = name; + lpos = line = 1; + cur_line = line1; + prev_line = line2; + token_line = cur_line; + cur_line[0] = prev_line[0] = 0; + warnings_occurred = 0; +} + +static int +get_char(FILE *cfile) +{ + int c = getc(cfile); + if (!ugflag) { + if (c == '\n') { + if (cur_line == line1) { + cur_line = line2; + prev_line = line1; + } else { + cur_line = line2; + prev_line = line1; + } + line++; + lpos = 1; + cur_line[0] = 0; + } else if (c != EOF) { + if (lpos <= 81) { + cur_line[lpos - 1] = c; + cur_line[lpos] = 0; + } + lpos++; + } + } else + ugflag = 0; + return (c); +} + +static int +get_token(FILE *cfile) +{ + int c, ttok; + static char tb[2]; + int l, p; + + do { + l = line; + p = lpos; + + c = get_char(cfile); + + if (!(c == '\n' && eol_token) && isascii(c) && isspace(c)) + continue; + if (c == '#') { + skip_to_eol(cfile); + continue; + } + if (c == '"') { + lexline = l; + lexchar = p; + ttok = read_string(cfile); + break; + } + if ((isascii(c) && isdigit(c)) || c == '-') { + lexline = l; + lexchar = p; + ttok = read_number(c, cfile); + break; + } else if (isascii(c) && isalpha(c)) { + lexline = l; + lexchar = p; + ttok = read_num_or_name(c, cfile); + break; + } else { + lexline = l; + lexchar = p; + tb[0] = c; + tb[1] = 0; + tval = tb; + ttok = c; + break; + } + } while (1); + return (ttok); +} + +int +next_token(char **rval, FILE *cfile) +{ + int rv; + + if (token) { + if (lexline != tline) + token_line = cur_line; + lexchar = tlpos; + lexline = tline; + rv = token; + token = 0; + } else { + rv = get_token(cfile); + token_line = cur_line; + } + if (rval) + *rval = tval; + + return (rv); +} + +int +peek_token(char **rval, FILE *cfile) +{ + int x; + + if (!token) { + tlpos = lexchar; + tline = lexline; + token = get_token(cfile); + if (lexline != tline) + token_line = prev_line; + x = lexchar; + lexchar = tlpos; + tlpos = x; + x = lexline; + lexline = tline; + tline = x; + } + if (rval) + *rval = tval; + + return (token); +} + +static void +skip_to_eol(FILE *cfile) +{ + int c; + + do { + c = get_char(cfile); + if (c == EOF) + return; + if (c == '\n') + return; + } while (1); +} + +static int +read_string(FILE *cfile) +{ + int i, c, bs = 0; + + for (i = 0; i < sizeof(tokbuf); i++) { + c = get_char(cfile); + if (c == EOF) { + parse_warn("eof in string constant"); + break; + } + if (bs) { + bs = 0; + tokbuf[i] = c; + } else if (c == '\\') + bs = 1; + else if (c == '"') + break; + else + 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(tokbuf)) { + parse_warn("string constant larger than internal buffer"); + i--; + } + tokbuf[i] = 0; + tval = tokbuf; + return (STRING); +} + +static int +read_number(int c, FILE *cfile) +{ + int seenx = 0, i = 0, token = NUMBER; + + tokbuf[i++] = c; + for (; i < sizeof(tokbuf); i++) { + c = get_char(cfile); + if (!seenx && c == 'x') + seenx = 1; + else if (!isascii(c) || !isxdigit(c)) { + ungetc(c, cfile); + ugflag = 1; + break; + } + tokbuf[i] = c; + } + if (i == sizeof(tokbuf)) { + parse_warn("numeric token larger than internal buffer"); + i--; + } + tokbuf[i] = 0; + tval = tokbuf; + + return (token); +} + +static int +read_num_or_name(int c, FILE *cfile) +{ + int i = 0; + int rv = NUMBER_OR_NAME; + + tokbuf[i++] = c; + for (; i < sizeof(tokbuf); i++) { + c = get_char(cfile); + if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) { + ungetc(c, cfile); + ugflag = 1; + break; + } + if (!isxdigit(c)) + rv = NAME; + tokbuf[i] = c; + } + if (i == sizeof(tokbuf)) { + parse_warn("token larger than internal buffer"); + i--; + } + tokbuf[i] = 0; + tval = tokbuf; + + return (intern(tval, rv)); +} + +static int +intern(char *atom, int dfv) +{ + if (!isascii(atom[0])) + return (dfv); + + switch (tolower(atom[0])) { + case 'a': + if (!strcasecmp(atom + 1, "lways-reply-rfc1048")) + return (ALWAYS_REPLY_RFC1048); + 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, "bandoned")) + return (ABANDONED); + if (!strcasecmp(atom + 1, "uthoritative")) + return (AUTHORITATIVE); + break; + case 'b': + if (!strcasecmp(atom + 1, "ackoff-cutoff")) + return (BACKOFF_CUTOFF); + if (!strcasecmp(atom + 1, "ootp")) + return (BOOTP); + if (!strcasecmp(atom + 1, "ooting")) + return (BOOTING); + if (!strcasecmp(atom + 1, "oot-unknown-clients")) + return (BOOT_UNKNOWN_CLIENTS); + case 'c': + if (!strcasecmp(atom + 1, "lass")) + return (CLASS); + if (!strcasecmp(atom + 1, "iaddr")) + return (CIADDR); + if (!strcasecmp(atom + 1, "lient-identifier")) + return (CLIENT_IDENTIFIER); + if (!strcasecmp(atom + 1, "lient-hostname")) + return (CLIENT_HOSTNAME); + break; + case 'd': + if (!strcasecmp(atom + 1, "omain")) + return (DOMAIN); + if (!strcasecmp(atom + 1, "eny")) + return (DENY); + 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-bootp", 12)) { + 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; + } + break; + case 'e': + if (!strcasecmp(atom + 1, "thernet")) + return (ETHERNET); + if (!strcasecmp(atom + 1, "nds")) + return (ENDS); + if (!strcasecmp(atom + 1, "xpire")) + return (EXPIRE); + break; + case 'f': + if (!strcasecmp(atom + 1, "ilename")) + return (FILENAME); + if (!strcasecmp(atom + 1, "ixed-address")) + return (FIXED_ADDR); + if (!strcasecmp(atom + 1, "ddi")) + return (FDDI); + 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, "ost")) + return (HOST); + if (!strcasecmp(atom + 1, "ardware")) + return (HARDWARE); + if (!strcasecmp(atom + 1, "ostname")) + return (HOSTNAME); + break; + case 'i': + if (!strcasecmp(atom + 1, "nitial-interval")) + return (INITIAL_INTERVAL); + if (!strcasecmp(atom + 1, "nterface")) + return (INTERFACE); + break; + case 'l': + if (!strcasecmp(atom + 1, "ease")) + return (LEASE); + break; + case 'm': + if (!strcasecmp(atom + 1, "ax-lease-time")) + return (MAX_LEASE_TIME); + if (!strncasecmp(atom + 1, "edi", 3)) { + if (!strcasecmp(atom + 4, "a")) + return (MEDIA); + if (!strcasecmp(atom + 4, "um")) + return (MEDIUM); + break; + } + break; + case 'n': + if (!strcasecmp(atom + 1, "ameserver")) + return (NAMESERVER); + if (!strcasecmp(atom + 1, "etmask")) + return (NETMASK); + if (!strcasecmp(atom + 1, "ext-server")) + return (NEXT_SERVER); + if (!strcasecmp(atom + 1, "ot")) + return (TOKEN_NOT); + break; + case 'o': + if (!strcasecmp(atom + 1, "ption")) + return (OPTION); + if (!strcasecmp(atom + 1, "ne-lease-per-client")) + return (ONE_LEASE_PER_CLIENT); + break; + case 'p': + if (!strcasecmp(atom + 1, "repend")) + return (PREPEND); + if (!strcasecmp(atom + 1, "acket")) + return (PACKET); + break; + case 'r': + if (!strcasecmp(atom + 1, "ange")) + return (RANGE); + if (!strcasecmp(atom + 1, "equest")) + return (REQUEST); + if (!strcasecmp(atom + 1, "equire")) + return (REQUIRE); + if (!strcasecmp(atom + 1, "etry")) + return (RETRY); + 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); + break; + case 's': + 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, "ubnet")) + return (SUBNET); + if (!strcasecmp(atom + 1, "hared-network")) + return (SHARED_NETWORK); + if (!strcasecmp(atom + 1, "erver-name")) + return (SERVER_NAME); + if (!strcasecmp(atom + 1, "erver-identifier")) + return (SERVER_IDENTIFIER); + if (!strcasecmp(atom + 1, "elect-timeout")) + return (SELECT_TIMEOUT); + if (!strcasecmp(atom + 1, "end")) + return (SEND); + if (!strcasecmp(atom + 1, "cript")) + return (SCRIPT); + if (!strcasecmp(atom + 1, "upersede")) + return (SUPERSEDE); + 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); + break; + case 'u': + 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 (!strcasecmp(atom + 1, "id")) + return (UID); + if (!strcasecmp(atom + 1, "nknown-clients")) + return (UNKNOWN_CLIENTS); + break; + case 'v': + if (!strcasecmp(atom + 1, "endor-class")) + return (VENDOR_CLASS); + break; + case 'y': + if (!strcasecmp(atom + 1, "iaddr")) + return (YIADDR); + break; + } + return (dfv); +} |