GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/dhcpd/conflex.c Lines: 0 123 0.0 %
Date: 2017-11-07 Branches: 0 78 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: conflex.c,v 1.19 2017/04/24 14:58:36 krw Exp $	*/
2
3
/* Lexical scanner for dhcpd config file... */
4
5
/*
6
 * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
7
 * All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 *
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. Neither the name of The Internet Software Consortium nor the names
19
 *    of its contributors may be used to endorse or promote products derived
20
 *    from this software without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23
 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
 * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
 * SUCH DAMAGE.
35
 *
36
 * This software has been written for the Internet Software Consortium
37
 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38
 * Enterprises.  To learn more about the Internet Software Consortium,
39
 * see ``http://www.vix.com/isc''.  To learn more about Vixie
40
 * Enterprises, see ``http://www.vix.com''.
41
 */
42
43
#include <sys/types.h>
44
#include <sys/socket.h>
45
46
#include <net/if.h>
47
48
#include <netinet/in.h>
49
50
#include <ctype.h>
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include <string.h>
54
55
#include "dhcp.h"
56
#include "tree.h"
57
#include "dhcpd.h"
58
#include "dhctoken.h"
59
60
int lexline;
61
int lexchar;
62
char *token_line;
63
char *prev_line;
64
char *cur_line;
65
char *tlname;
66
int eol_token;
67
68
static char line1[81];
69
static char line2[81];
70
static int lpos;
71
static int line;
72
static int tlpos;
73
static int tline;
74
static int token;
75
static int ugflag;
76
static char *tval;
77
static char tokbuf[1500];
78
79
static int get_char(FILE *);
80
static int get_token(FILE *);
81
static void skip_to_eol(FILE *);
82
static int read_string(FILE *);
83
static int read_num_or_name(int, FILE *);
84
static int intern(char *, int);
85
static int kw_cmp(const void *, const void *);
86
87
void
88
new_parse(char *name)
89
{
90
	tlname = name;
91
	lpos = line = 1;
92
	cur_line = line1;
93
	prev_line = line2;
94
	token_line = cur_line;
95
	cur_line[0] = prev_line[0] = 0;
96
	warnings_occurred = 0;
97
}
98
99
static int
100
get_char(FILE *cfile)
101
{
102
	int c = getc(cfile);
103
	if (!ugflag) {
104
		if (c == '\n') {
105
			if (cur_line == line1) {
106
				cur_line = line2;
107
				prev_line = line1;
108
			} else {
109
				cur_line = line1;
110
				prev_line = line2;
111
			}
112
			line++;
113
			lpos = 1;
114
			cur_line[0] = 0;
115
		} else if (c != EOF) {
116
			if (lpos < sizeof(line1)) {
117
				cur_line[lpos - 1] = c;
118
				cur_line[lpos] = 0;
119
			}
120
			lpos++;
121
		}
122
	} else
123
		ugflag = 0;
124
	return (c);
125
}
126
127
static int
128
get_token(FILE *cfile)
129
{
130
	int		c, ttok;
131
	static char	tb[2];
132
	int		l, p;
133
134
	do {
135
		l = line;
136
		p = lpos;
137
138
		c = get_char(cfile);
139
140
		if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
141
			continue;
142
		if (c == '#') {
143
			skip_to_eol(cfile);
144
			continue;
145
		}
146
		lexline = l;
147
		lexchar = p;
148
		if (c == '"') {
149
			ttok = read_string(cfile);
150
			break;
151
		} else if (c == '-' || (isascii(c) && isalnum(c))) {
152
			ttok = read_num_or_name(c, cfile);
153
			break;
154
		} else {
155
			tb[0] = c;
156
			tb[1] = 0;
157
			tval = tb;
158
			ttok = c;
159
			break;
160
		}
161
	} while (1);
162
	return (ttok);
163
}
164
165
int
166
next_token(char **rval, FILE *cfile)
167
{
168
	int	rv;
169
170
	if (token) {
171
		if (lexline != tline)
172
			token_line = cur_line;
173
		lexchar = tlpos;
174
		lexline = tline;
175
		rv = token;
176
		token = 0;
177
	} else {
178
		rv = get_token(cfile);
179
		token_line = cur_line;
180
	}
181
	if (rval)
182
		*rval = tval;
183
184
	return (rv);
185
}
186
187
int
188
peek_token(char **rval, FILE *cfile)
189
{
190
	int	x;
191
192
	if (!token) {
193
		tlpos = lexchar;
194
		tline = lexline;
195
		token = get_token(cfile);
196
		if (lexline != tline)
197
			token_line = prev_line;
198
		x = lexchar;
199
		lexchar = tlpos;
200
		tlpos = x;
201
		x = lexline;
202
		lexline = tline;
203
		tline = x;
204
	}
205
	if (rval)
206
		*rval = tval;
207
208
	return (token);
209
}
210
211
static void
212
skip_to_eol(FILE *cfile)
213
{
214
	int	c;
215
216
	do {
217
		c = get_char(cfile);
218
		if (c == EOF)
219
			return;
220
		if (c == '\n')
221
			return;
222
	} while (1);
223
}
224
225
static int
226
read_string(FILE *cfile)
227
{
228
	int i, c, bs;
229
230
	bs = i = 0;
231
	do {
232
		c = get_char(cfile);
233
		if (bs)
234
			bs = 0;
235
		else if (c == '\\')
236
			bs = 1;
237
238
		if (c != '"' && c != EOF && bs == 0)
239
			tokbuf[i++] = c;
240
241
	} while (i < (sizeof(tokbuf) - 1) && c != EOF && c != '"');
242
243
	if (c == EOF)
244
		parse_warn("eof in string constant");
245
	else if (c != '"')
246
		parse_warn("string constant larger than internal buffer");
247
248
	tokbuf[i] = 0;
249
	tval = tokbuf;
250
251
	return (TOK_STRING);
252
}
253
254
static int
255
read_num_or_name(int c, FILE *cfile)
256
{
257
	int i, rv, xdigits;
258
259
	xdigits = isxdigit(c) ? 1 : 0;
260
261
	tokbuf[0] = c;
262
	for (i = 1; i < sizeof(tokbuf); i++) {
263
		c = get_char(cfile);
264
		if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
265
			ungetc(c, cfile);
266
			ugflag = 1;
267
			break;
268
		}
269
		if (isxdigit(c))
270
			xdigits++;
271
		tokbuf[i] = c;
272
	}
273
	if (i == sizeof(tokbuf)) {
274
		parse_warn("token larger than internal buffer");
275
		i--;
276
		c = tokbuf[i];
277
		if (isxdigit(c))
278
			xdigits--;
279
	}
280
	tokbuf[i] = 0;
281
	tval = tokbuf;
282
283
	c = (unsigned int)tokbuf[0];
284
285
	if (c == '-')
286
		rv = TOK_NUMBER;
287
	else
288
		rv = intern(tval, TOK_NUMBER_OR_NAME);
289
290
	if (rv == TOK_NUMBER_OR_NAME && xdigits != i)
291
		rv = TOK_NAME;
292
293
	return (rv);
294
}
295
296
static const struct keywords {
297
	const char	*k_name;
298
	int		k_val;
299
} keywords[] = {
300
	{ "abandoned",			TOK_ABANDONED },
301
	{ "allow",			TOK_ALLOW },
302
	{ "always-reply-rfc1048",	TOK_ALWAYS_REPLY_RFC1048 },
303
	{ "authoritative",		TOK_AUTHORITATIVE },
304
	{ "booting",			TOK_BOOTING },
305
	{ "bootp",			TOK_BOOTP },
306
	{ "class",			TOK_CLASS },
307
	{ "client-hostname",		TOK_CLIENT_HOSTNAME },
308
	{ "default-lease-time",		TOK_DEFAULT_LEASE_TIME },
309
	{ "deny",			TOK_DENY },
310
	{ "domain",			TOK_DOMAIN },
311
	{ "dynamic-bootp",		TOK_DYNAMIC_BOOTP },
312
	{ "dynamic-bootp-lease-cutoff",	TOK_DYNAMIC_BOOTP_LEASE_CUTOFF },
313
	{ "dynamic-bootp-lease-length",	TOK_DYNAMIC_BOOTP_LEASE_LENGTH },
314
	{ "echo-client-id",		TOK_ECHO_CLIENT_ID },
315
	{ "ends",			TOK_ENDS },
316
	{ "ethernet",			TOK_ETHERNET },
317
	{ "filename",			TOK_FILENAME },
318
	{ "fixed-address",		TOK_FIXED_ADDR },
319
	{ "get-lease-hostnames",	TOK_GET_LEASE_HOSTNAMES },
320
	{ "group",			TOK_GROUP },
321
	{ "hardware",			TOK_HARDWARE },
322
	{ "host",			TOK_HOST },
323
	{ "hostname",			TOK_HOSTNAME },
324
	{ "ipsec-tunnel",		TOK_IPSEC_TUNNEL },
325
	{ "lease",			TOK_LEASE },
326
	{ "max-lease-time",		TOK_MAX_LEASE_TIME },
327
	{ "netmask",			TOK_NETMASK },
328
	{ "next-server",		TOK_NEXT_SERVER },
329
	{ "not",			TOK_TOKEN_NOT },
330
	{ "option",			TOK_OPTION },
331
	{ "range",			TOK_RANGE },
332
	{ "server-identifier",		TOK_SERVER_IDENTIFIER },
333
	{ "server-name",		TOK_SERVER_NAME },
334
	{ "shared-network",		TOK_SHARED_NETWORK },
335
	{ "starts",			TOK_STARTS },
336
	{ "subnet",			TOK_SUBNET },
337
	{ "timeout",			TOK_TIMEOUT },
338
	{ "timestamp",			TOK_TIMESTAMP },
339
	{ "uid",			TOK_UID },
340
	{ "unknown-clients",		TOK_UNKNOWN_CLIENTS },
341
	{ "use-host-decl-names",	TOK_USE_HOST_DECL_NAMES },
342
	{ "use-lease-addr-for-default-route",
343
					TOK_USE_LEASE_ADDR_FOR_DEFAULT_ROUTE },
344
	{ "user-class",			TOK_USER_CLASS },
345
	{ "vendor-class",		TOK_VENDOR_CLASS }
346
};
347
348
static int
349
kw_cmp(const void *k, const void *e)
350
{
351
	return (strcasecmp(k, ((const struct keywords *)e)->k_name));
352
}
353
354
static int
355
intern(char *atom, int dfv)
356
{
357
	const struct keywords *p;
358
359
	p = bsearch(atom, keywords, sizeof(keywords)/sizeof(keywords[0]),
360
	    sizeof(keywords[0]), kw_cmp);
361
	if (p)
362
		return (p->k_val);
363
	return (dfv);
364
}