1*a51e9872Skrw /* $OpenBSD: conflex.c,v 1.19 2017/04/24 14:58:36 krw Exp $ */
2e853bc5dShenning
33c41e82cShenning /* Lexical scanner for dhcpd config file... */
4e853bc5dShenning
5e853bc5dShenning /*
6e853bc5dShenning * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
7e853bc5dShenning * All rights reserved.
8e853bc5dShenning *
9e853bc5dShenning * Redistribution and use in source and binary forms, with or without
10e853bc5dShenning * modification, are permitted provided that the following conditions
11e853bc5dShenning * are met:
12e853bc5dShenning *
13e853bc5dShenning * 1. Redistributions of source code must retain the above copyright
14e853bc5dShenning * notice, this list of conditions and the following disclaimer.
15e853bc5dShenning * 2. Redistributions in binary form must reproduce the above copyright
16e853bc5dShenning * notice, this list of conditions and the following disclaimer in the
17e853bc5dShenning * documentation and/or other materials provided with the distribution.
18e853bc5dShenning * 3. Neither the name of The Internet Software Consortium nor the names
19e853bc5dShenning * of its contributors may be used to endorse or promote products derived
20e853bc5dShenning * from this software without specific prior written permission.
21e853bc5dShenning *
22e853bc5dShenning * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23e853bc5dShenning * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24e853bc5dShenning * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25e853bc5dShenning * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26e853bc5dShenning * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27e853bc5dShenning * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28e853bc5dShenning * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29e853bc5dShenning * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30e853bc5dShenning * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31e853bc5dShenning * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32e853bc5dShenning * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33e853bc5dShenning * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34e853bc5dShenning * SUCH DAMAGE.
35e853bc5dShenning *
36e853bc5dShenning * This software has been written for the Internet Software Consortium
37e853bc5dShenning * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38e853bc5dShenning * Enterprises. To learn more about the Internet Software Consortium,
39e853bc5dShenning * see ``http://www.vix.com/isc''. To learn more about Vixie
40e853bc5dShenning * Enterprises, see ``http://www.vix.com''.
41e853bc5dShenning */
42e853bc5dShenning
43837cddffSkrw #include <sys/types.h>
44837cddffSkrw #include <sys/socket.h>
453c41e82cShenning
46837cddffSkrw #include <net/if.h>
47837cddffSkrw
48837cddffSkrw #include <netinet/in.h>
49837cddffSkrw
50837cddffSkrw #include <ctype.h>
51837cddffSkrw #include <stdio.h>
52837cddffSkrw #include <stdlib.h>
53837cddffSkrw #include <string.h>
54837cddffSkrw
55837cddffSkrw #include "dhcp.h"
56837cddffSkrw #include "tree.h"
57e853bc5dShenning #include "dhcpd.h"
58e853bc5dShenning #include "dhctoken.h"
59e853bc5dShenning
60e853bc5dShenning int lexline;
61e853bc5dShenning int lexchar;
62e853bc5dShenning char *token_line;
63e853bc5dShenning char *prev_line;
64e853bc5dShenning char *cur_line;
65e853bc5dShenning char *tlname;
66e853bc5dShenning int eol_token;
67e853bc5dShenning
68e853bc5dShenning static char line1[81];
69e853bc5dShenning static char line2[81];
70e853bc5dShenning static int lpos;
71e853bc5dShenning static int line;
72e853bc5dShenning static int tlpos;
73e853bc5dShenning static int tline;
74e853bc5dShenning static int token;
75e853bc5dShenning static int ugflag;
76e853bc5dShenning static char *tval;
77e853bc5dShenning static char tokbuf[1500];
78e853bc5dShenning
793c41e82cShenning static int get_char(FILE *);
803c41e82cShenning static int get_token(FILE *);
813c41e82cShenning static void skip_to_eol(FILE *);
823c41e82cShenning static int read_string(FILE *);
833c41e82cShenning static int read_num_or_name(int, FILE *);
843c41e82cShenning static int intern(char *, int);
853b0fbcd4Skrw static int kw_cmp(const void *, const void *);
86e853bc5dShenning
873c41e82cShenning void
new_parse(char * name)883c41e82cShenning new_parse(char *name)
89e853bc5dShenning {
90e853bc5dShenning tlname = name;
91e853bc5dShenning lpos = line = 1;
92e853bc5dShenning cur_line = line1;
93e853bc5dShenning prev_line = line2;
94e853bc5dShenning token_line = cur_line;
95e853bc5dShenning cur_line[0] = prev_line[0] = 0;
96e853bc5dShenning warnings_occurred = 0;
97e853bc5dShenning }
98e853bc5dShenning
993c41e82cShenning static int
get_char(FILE * cfile)1003c41e82cShenning get_char(FILE *cfile)
101e853bc5dShenning {
102e853bc5dShenning int c = getc(cfile);
103e853bc5dShenning if (!ugflag) {
104fbc5e94dShenning if (c == '\n') {
105e853bc5dShenning if (cur_line == line1) {
106e853bc5dShenning cur_line = line2;
107e853bc5dShenning prev_line = line1;
108e853bc5dShenning } else {
109bc61fb54Skrw cur_line = line1;
110bc61fb54Skrw prev_line = line2;
111e853bc5dShenning }
112e853bc5dShenning line++;
113e853bc5dShenning lpos = 1;
114e853bc5dShenning cur_line[0] = 0;
115e853bc5dShenning } else if (c != EOF) {
116e95a4b59Skrw if (lpos < sizeof(line1)) {
117e853bc5dShenning cur_line[lpos - 1] = c;
118e853bc5dShenning cur_line[lpos] = 0;
119e853bc5dShenning }
120e853bc5dShenning lpos++;
121e853bc5dShenning }
122e853bc5dShenning } else
123e853bc5dShenning ugflag = 0;
1243c41e82cShenning return (c);
125e853bc5dShenning }
126e853bc5dShenning
1273c41e82cShenning static int
get_token(FILE * cfile)1283c41e82cShenning get_token(FILE *cfile)
129e853bc5dShenning {
1303c41e82cShenning int c, ttok;
131e853bc5dShenning static char tb[2];
1320795b389Sderaadt int l, p;
133e853bc5dShenning
134e853bc5dShenning do {
135e853bc5dShenning l = line;
136e853bc5dShenning p = lpos;
137e853bc5dShenning
138e853bc5dShenning c = get_char(cfile);
139e853bc5dShenning
140e853bc5dShenning if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
141e853bc5dShenning continue;
142e853bc5dShenning if (c == '#') {
143e853bc5dShenning skip_to_eol(cfile);
144e853bc5dShenning continue;
145e853bc5dShenning }
146e853bc5dShenning lexline = l;
147e853bc5dShenning lexchar = p;
148d37427b0Skrw if (c == '"') {
149e853bc5dShenning ttok = read_string(cfile);
150e853bc5dShenning break;
15111b1f78aSkrw } else if (c == '-' || (isascii(c) && isalnum(c))) {
152e853bc5dShenning ttok = read_num_or_name(c, cfile);
153e853bc5dShenning break;
154e853bc5dShenning } else {
155e853bc5dShenning tb[0] = c;
156e853bc5dShenning tb[1] = 0;
157e853bc5dShenning tval = tb;
158e853bc5dShenning ttok = c;
159e853bc5dShenning break;
160e853bc5dShenning }
161e853bc5dShenning } while (1);
1623c41e82cShenning return (ttok);
163e853bc5dShenning }
164e853bc5dShenning
1653c41e82cShenning int
next_token(char ** rval,FILE * cfile)1663c41e82cShenning next_token(char **rval, FILE *cfile)
167e853bc5dShenning {
168e853bc5dShenning int rv;
169e853bc5dShenning
170e853bc5dShenning if (token) {
171e853bc5dShenning if (lexline != tline)
172e853bc5dShenning token_line = cur_line;
173e853bc5dShenning lexchar = tlpos;
174e853bc5dShenning lexline = tline;
175e853bc5dShenning rv = token;
176e853bc5dShenning token = 0;
177e853bc5dShenning } else {
178e853bc5dShenning rv = get_token(cfile);
179e853bc5dShenning token_line = cur_line;
180e853bc5dShenning }
181e853bc5dShenning if (rval)
182e853bc5dShenning *rval = tval;
1833c41e82cShenning
1843c41e82cShenning return (rv);
185e853bc5dShenning }
186e853bc5dShenning
1873c41e82cShenning int
peek_token(char ** rval,FILE * cfile)1883c41e82cShenning peek_token(char **rval, FILE *cfile)
189e853bc5dShenning {
190e853bc5dShenning int x;
191e853bc5dShenning
192e853bc5dShenning if (!token) {
193e853bc5dShenning tlpos = lexchar;
194e853bc5dShenning tline = lexline;
195e853bc5dShenning token = get_token(cfile);
196e853bc5dShenning if (lexline != tline)
197e853bc5dShenning token_line = prev_line;
1983c41e82cShenning x = lexchar;
1993c41e82cShenning lexchar = tlpos;
2003c41e82cShenning tlpos = x;
2013c41e82cShenning x = lexline;
2023c41e82cShenning lexline = tline;
2033c41e82cShenning tline = x;
204e853bc5dShenning }
205e853bc5dShenning if (rval)
206e853bc5dShenning *rval = tval;
2073c41e82cShenning
2083c41e82cShenning return (token);
209e853bc5dShenning }
210e853bc5dShenning
2113c41e82cShenning static void
skip_to_eol(FILE * cfile)2123c41e82cShenning skip_to_eol(FILE *cfile)
213e853bc5dShenning {
214e853bc5dShenning int c;
2153c41e82cShenning
216e853bc5dShenning do {
217e853bc5dShenning c = get_char(cfile);
218e853bc5dShenning if (c == EOF)
219e853bc5dShenning return;
220fbc5e94dShenning if (c == '\n')
221e853bc5dShenning return;
222e853bc5dShenning } while (1);
223e853bc5dShenning }
224e853bc5dShenning
2253c41e82cShenning static int
read_string(FILE * cfile)2263c41e82cShenning read_string(FILE *cfile)
227e853bc5dShenning {
2280a2eae23Skrw int i, c, bs;
229e853bc5dShenning
2300a2eae23Skrw bs = i = 0;
2310a2eae23Skrw do {
232e853bc5dShenning c = get_char(cfile);
2330a2eae23Skrw if (bs)
234e853bc5dShenning bs = 0;
2350a2eae23Skrw else if (c == '\\')
236e853bc5dShenning bs = 1;
2370a2eae23Skrw
2380a2eae23Skrw if (c != '"' && c != EOF && bs == 0)
2390a2eae23Skrw tokbuf[i++] = c;
2400a2eae23Skrw
2410a2eae23Skrw } while (i < (sizeof(tokbuf) - 1) && c != EOF && c != '"');
2420a2eae23Skrw
2430a2eae23Skrw if (c == EOF)
2440a2eae23Skrw parse_warn("eof in string constant");
2450a2eae23Skrw else if (c != '"')
246e853bc5dShenning parse_warn("string constant larger than internal buffer");
2470a2eae23Skrw
248e853bc5dShenning tokbuf[i] = 0;
249e853bc5dShenning tval = tokbuf;
2500a2eae23Skrw
251f3ec5800Sderaadt return (TOK_STRING);
252e853bc5dShenning }
253e853bc5dShenning
2543c41e82cShenning static int
read_num_or_name(int c,FILE * cfile)2553c41e82cShenning read_num_or_name(int c, FILE *cfile)
256e853bc5dShenning {
25711b1f78aSkrw int i, rv, xdigits;
2583c41e82cShenning
25911b1f78aSkrw xdigits = isxdigit(c) ? 1 : 0;
26011b1f78aSkrw
26111b1f78aSkrw tokbuf[0] = c;
26211b1f78aSkrw for (i = 1; i < sizeof(tokbuf); i++) {
263e853bc5dShenning c = get_char(cfile);
2643c41e82cShenning if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
265e853bc5dShenning ungetc(c, cfile);
266e853bc5dShenning ugflag = 1;
267e853bc5dShenning break;
268e853bc5dShenning }
26911b1f78aSkrw if (isxdigit(c))
27011b1f78aSkrw xdigits++;
271e853bc5dShenning tokbuf[i] = c;
272e853bc5dShenning }
2733c41e82cShenning if (i == sizeof(tokbuf)) {
274e853bc5dShenning parse_warn("token larger than internal buffer");
2753c41e82cShenning i--;
27611b1f78aSkrw c = tokbuf[i];
27711b1f78aSkrw if (isxdigit(c))
27811b1f78aSkrw xdigits--;
279e853bc5dShenning }
280e853bc5dShenning tokbuf[i] = 0;
281e853bc5dShenning tval = tokbuf;
2823c41e82cShenning
28311b1f78aSkrw c = (unsigned int)tokbuf[0];
28411b1f78aSkrw
28511b1f78aSkrw if (c == '-')
28611b1f78aSkrw rv = TOK_NUMBER;
28711b1f78aSkrw else
28811b1f78aSkrw rv = intern(tval, TOK_NUMBER_OR_NAME);
28911b1f78aSkrw
29011b1f78aSkrw if (rv == TOK_NUMBER_OR_NAME && xdigits != i)
29111b1f78aSkrw rv = TOK_NAME;
29211b1f78aSkrw
29311b1f78aSkrw return (rv);
294e853bc5dShenning }
295e853bc5dShenning
296f3ec5800Sderaadt static const struct keywords {
297f3ec5800Sderaadt const char *k_name;
298f3ec5800Sderaadt int k_val;
299f3ec5800Sderaadt } keywords[] = {
300f3ec5800Sderaadt { "abandoned", TOK_ABANDONED },
301f3ec5800Sderaadt { "allow", TOK_ALLOW },
302f3ec5800Sderaadt { "always-reply-rfc1048", TOK_ALWAYS_REPLY_RFC1048 },
303f3ec5800Sderaadt { "authoritative", TOK_AUTHORITATIVE },
304f3ec5800Sderaadt { "booting", TOK_BOOTING },
305f3ec5800Sderaadt { "bootp", TOK_BOOTP },
306f3ec5800Sderaadt { "class", TOK_CLASS },
307f3ec5800Sderaadt { "client-hostname", TOK_CLIENT_HOSTNAME },
308f3ec5800Sderaadt { "default-lease-time", TOK_DEFAULT_LEASE_TIME },
309f3ec5800Sderaadt { "deny", TOK_DENY },
310f3ec5800Sderaadt { "domain", TOK_DOMAIN },
311f3ec5800Sderaadt { "dynamic-bootp", TOK_DYNAMIC_BOOTP },
312f3ec5800Sderaadt { "dynamic-bootp-lease-cutoff", TOK_DYNAMIC_BOOTP_LEASE_CUTOFF },
313f3ec5800Sderaadt { "dynamic-bootp-lease-length", TOK_DYNAMIC_BOOTP_LEASE_LENGTH },
314*a51e9872Skrw { "echo-client-id", TOK_ECHO_CLIENT_ID },
315f3ec5800Sderaadt { "ends", TOK_ENDS },
316f3ec5800Sderaadt { "ethernet", TOK_ETHERNET },
317f3ec5800Sderaadt { "filename", TOK_FILENAME },
318f3ec5800Sderaadt { "fixed-address", TOK_FIXED_ADDR },
319f3ec5800Sderaadt { "get-lease-hostnames", TOK_GET_LEASE_HOSTNAMES },
320f3ec5800Sderaadt { "group", TOK_GROUP },
321f3ec5800Sderaadt { "hardware", TOK_HARDWARE },
322f3ec5800Sderaadt { "host", TOK_HOST },
323f3ec5800Sderaadt { "hostname", TOK_HOSTNAME },
3245b44f46dSreyk { "ipsec-tunnel", TOK_IPSEC_TUNNEL },
325f3ec5800Sderaadt { "lease", TOK_LEASE },
326f3ec5800Sderaadt { "max-lease-time", TOK_MAX_LEASE_TIME },
327f3ec5800Sderaadt { "netmask", TOK_NETMASK },
328f3ec5800Sderaadt { "next-server", TOK_NEXT_SERVER },
329f3ec5800Sderaadt { "not", TOK_TOKEN_NOT },
330f3ec5800Sderaadt { "option", TOK_OPTION },
331f3ec5800Sderaadt { "range", TOK_RANGE },
332f3ec5800Sderaadt { "server-identifier", TOK_SERVER_IDENTIFIER },
333f3ec5800Sderaadt { "server-name", TOK_SERVER_NAME },
334f3ec5800Sderaadt { "shared-network", TOK_SHARED_NETWORK },
335f3ec5800Sderaadt { "starts", TOK_STARTS },
336f3ec5800Sderaadt { "subnet", TOK_SUBNET },
337f3ec5800Sderaadt { "timeout", TOK_TIMEOUT },
338f3ec5800Sderaadt { "timestamp", TOK_TIMESTAMP },
339f3ec5800Sderaadt { "uid", TOK_UID },
340f3ec5800Sderaadt { "unknown-clients", TOK_UNKNOWN_CLIENTS },
341f3ec5800Sderaadt { "use-host-decl-names", TOK_USE_HOST_DECL_NAMES },
34235318e8fSkrw { "use-lease-addr-for-default-route",
34335318e8fSkrw TOK_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE },
344e4599d01Sderaadt { "user-class", TOK_USER_CLASS },
345f3ec5800Sderaadt { "vendor-class", TOK_VENDOR_CLASS }
346f3ec5800Sderaadt };
347f3ec5800Sderaadt
3483b0fbcd4Skrw static int
kw_cmp(const void * k,const void * e)349f3ec5800Sderaadt kw_cmp(const void *k, const void *e)
350f3ec5800Sderaadt {
351f3ec5800Sderaadt return (strcasecmp(k, ((const struct keywords *)e)->k_name));
352f3ec5800Sderaadt }
353f3ec5800Sderaadt
3543c41e82cShenning static int
intern(char * atom,int dfv)3553c41e82cShenning intern(char *atom, int dfv)
356e853bc5dShenning {
357f3ec5800Sderaadt const struct keywords *p;
358e853bc5dShenning
359f3ec5800Sderaadt p = bsearch(atom, keywords, sizeof(keywords)/sizeof(keywords[0]),
360f3ec5800Sderaadt sizeof(keywords[0]), kw_cmp);
361f3ec5800Sderaadt if (p)
362f3ec5800Sderaadt return (p->k_val);
3633c41e82cShenning return (dfv);
364e853bc5dShenning }
365