xref: /openbsd-src/usr.sbin/dhcpd/conflex.c (revision a51e987248c39601466de9e183d3901b5b7303cf)
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