GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/dhclient/conflex.c Lines: 0 130 0.0 %
Date: 2017-11-07 Branches: 0 80 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: conflex.c,v 1.43 2017/07/14 16:21:03 krw Exp $	*/
2
3
/* Lexical scanner for dhclient 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/queue.h>
44
#include <sys/socket.h>
45
46
#include <arpa/inet.h>
47
48
#include <net/if.h>
49
50
#include <netinet/in.h>
51
#include <netinet/if_ether.h>
52
53
#include <ctype.h>
54
#include <signal.h>
55
#include <stdio.h>
56
#include <stdlib.h>
57
#include <string.h>
58
59
#include "dhcp.h"
60
#include "dhcpd.h"
61
#include "dhctoken.h"
62
#include "log.h"
63
64
int lexline;
65
int lexchar;
66
char *token_line;
67
char *prev_line;
68
char *cur_line;
69
char *tlname;
70
71
static char line1[81];
72
static char line2[81];
73
static int lpos;
74
static int line;
75
static int tlpos;
76
static int tline;
77
static int token;
78
static int ugflag;
79
static char *tval;
80
static char tokbuf[1500];
81
82
static int get_char(FILE *);
83
static int get_token(FILE *);
84
static void skip_to_eol(FILE *);
85
static int read_string(FILE *);
86
static int read_num_or_name(int, FILE *);
87
static int intern(char *, int);
88
89
void
90
new_parse(char *name)
91
{
92
	/*
93
	 * Initialize all parsing state, as we are starting to parse a
94
	 * new file, 'name'.
95
	 */
96
97
	memset(line1, 0, sizeof(line1));
98
	memset(line2, 0, sizeof(line2));
99
	memset(tokbuf, 0, sizeof(tokbuf));
100
101
	lpos = line = 1;
102
	tlpos = tline = token = ugflag = 0;
103
	tval = NULL;
104
105
	lexline = lexchar = 0;
106
	cur_line = line1;
107
	prev_line = line2;
108
	token_line = cur_line;
109
	tlname = name;
110
}
111
112
static int
113
get_char(FILE *cfile)
114
{
115
	int c = getc(cfile);
116
	if (ugflag == 0) {
117
		if (c == '\n') {
118
			if (cur_line == line1) {
119
				cur_line = line2;
120
				prev_line = line1;
121
			} else {
122
				cur_line = line1;
123
				prev_line = line2;
124
			}
125
			line++;
126
			lpos = 1;
127
			cur_line[0] = 0;
128
		} else if (c != EOF) {
129
			if ((unsigned int)lpos < sizeof(line1)) {
130
				cur_line[lpos - 1] = c;
131
				cur_line[lpos] = 0;
132
			}
133
			lpos++;
134
		}
135
	} else
136
		ugflag = 0;
137
	return c;
138
}
139
140
static int
141
get_token(FILE *cfile)
142
{
143
	static char	tb[2];
144
	int		c, ttok;
145
	int		l, p, u;
146
147
	u = ugflag;
148
149
	do {
150
		l = line;
151
		p = lpos - u;
152
		u = 0;
153
154
		c = get_char(cfile);
155
156
		if (isascii(c) != 0 && isspace(c) != 0)
157
			continue;
158
		if (c == '#') {
159
			skip_to_eol(cfile);
160
			continue;
161
		}
162
		lexline = l;
163
		lexchar = p;
164
		if (c == '"') {
165
			ttok = read_string(cfile);
166
			break;
167
		} else if (c == '-' || (isascii(c) != 0 && isalnum(c) != 0)) {
168
			ttok = read_num_or_name(c, cfile);
169
			break;
170
		} else {
171
			tb[0] = c;
172
			tb[1] = 0;
173
			tval = tb;
174
			ttok = c;
175
			break;
176
		}
177
	} while (1);
178
	return ttok;
179
}
180
181
int
182
next_token(char **rval, FILE *cfile)
183
{
184
	int	rv;
185
186
	if (token != 0) {
187
		if (lexline != tline)
188
			token_line = cur_line;
189
		lexchar = tlpos;
190
		lexline = tline;
191
		rv = token;
192
		token = 0;
193
	} else {
194
		rv = get_token(cfile);
195
		token_line = cur_line;
196
	}
197
	if (rval != 0)
198
		*rval = tval;
199
200
	return rv;
201
}
202
203
int
204
peek_token(char **rval, FILE *cfile)
205
{
206
	int	 x;
207
208
	if (token == 0) {
209
		tlpos = lexchar;
210
		tline = lexline;
211
		token = get_token(cfile);
212
		if (lexline != tline)
213
			token_line = prev_line;
214
		x = lexchar;
215
		lexchar = tlpos;
216
		tlpos = x;
217
		x = lexline;
218
		lexline = tline;
219
		tline = x;
220
	}
221
	if (rval != 0)
222
		*rval = tval;
223
224
	return token;
225
}
226
227
static void
228
skip_to_eol(FILE *cfile)
229
{
230
	int	 c;
231
232
	do {
233
		c = get_char(cfile);
234
		if (c == EOF)
235
			return;
236
		if (c == '\n')
237
			return;
238
	} while (1);
239
}
240
241
static int
242
read_string(FILE *cfile)
243
{
244
	int	 i, c, bs;
245
246
	/*
247
	 * Read in characters until an un-escaped '"' is encountered.
248
	 */
249
	bs = i = 0;
250
	while ((c = get_char(cfile)) != EOF) {
251
		if (c == '"' && bs == 0)
252
			break;
253
254
		tokbuf[i++] = c;
255
		if (bs != 0)
256
			bs = 0;
257
		else if (c == '\\')
258
			bs = 1;
259
260
		if (i == sizeof(tokbuf) - 1)
261
			break;
262
	}
263
	if (bs == 1)
264
		i--;
265
266
	if (c == EOF)
267
		parse_warn("eof in string constant");
268
	else if (c != '"')
269
		parse_warn("string constant too long");
270
271
	tokbuf[i] = '\0';
272
	tval = tokbuf;
273
274
	return TOK_STRING;
275
}
276
277
static int
278
read_num_or_name(int c, FILE *cfile)
279
{
280
	unsigned int	 i, xdigits;
281
	int		 rv;
282
283
	xdigits = (isxdigit(c) != 0) ? 1 : 0;
284
285
	tokbuf[0] = c;
286
	for (i = 1; i < sizeof(tokbuf); i++) {
287
		c = get_char(cfile);
288
		if (isascii(c) == 0 || (c != '-' && c != '_' &&
289
		    isalnum(c) == 0)) {
290
			ungetc(c, cfile);
291
			ugflag = 1;
292
			break;
293
		}
294
		if (isxdigit(c) != 0)
295
			xdigits++;
296
		tokbuf[i] = c;
297
	}
298
	if (i == sizeof(tokbuf)) {
299
		parse_warn("token larger than internal buffer");
300
		i--;
301
		c = tokbuf[i];
302
		if (isxdigit(c) != 0)
303
			xdigits--;
304
	}
305
	tokbuf[i] = 0;
306
	tval = tokbuf;
307
308
	c = (unsigned int)tokbuf[0];
309
310
	if (c == '-')
311
		rv = TOK_NUMBER;
312
	else
313
		rv = intern(tval, TOK_NUMBER_OR_NAME);
314
315
	if (rv == TOK_NUMBER_OR_NAME && xdigits != i)
316
		rv = TOK_NAME;
317
318
	return rv;
319
}
320
321
static const struct keywords {
322
	const char	*k_name;
323
	int		 k_val;
324
} keywords[] = {
325
	{ "append",				TOK_APPEND },
326
	{ "backoff-cutoff",			TOK_BACKOFF_CUTOFF },
327
	{ "bootp",				TOK_BOOTP },
328
	{ "default",				TOK_DEFAULT },
329
	{ "deny",				TOK_DENY },
330
	{ "expire",				TOK_EXPIRE },
331
	{ "filename",				TOK_FILENAME },
332
	{ "fixed-address",			TOK_FIXED_ADDR },
333
	{ "ignore",				TOK_IGNORE },
334
	{ "initial-interval",			TOK_INITIAL_INTERVAL },
335
	{ "interface",				TOK_INTERFACE },
336
	{ "lease",				TOK_LEASE },
337
	{ "link-timeout",			TOK_LINK_TIMEOUT },
338
	{ "next-server",			TOK_NEXT_SERVER },
339
	{ "option",				TOK_OPTION },
340
	{ "prepend",				TOK_PREPEND },
341
	{ "rebind",				TOK_REBIND },
342
	{ "reboot",				TOK_REBOOT },
343
	{ "reject",				TOK_REJECT },
344
	{ "renew",				TOK_RENEW },
345
	{ "request",				TOK_REQUEST },
346
	{ "require",				TOK_REQUIRE },
347
	{ "retry",				TOK_RETRY },
348
	{ "select-timeout",			TOK_SELECT_TIMEOUT },
349
	{ "send",				TOK_SEND },
350
	{ "server-name",			TOK_SERVER_NAME },
351
	{ "ssid",				TOK_SSID },
352
	{ "supersede",				TOK_SUPERSEDE },
353
	{ "timeout",				TOK_TIMEOUT }
354
};
355
356
int	kw_cmp(const void *k, const void *e);
357
358
int
359
kw_cmp(const void *k, const void *e)
360
{
361
	return strcasecmp(k, ((const struct keywords *)e)->k_name);
362
}
363
364
static int
365
intern(char *atom, int dfv)
366
{
367
	const struct keywords	*p;
368
369
	p = bsearch(atom, keywords, sizeof(keywords)/sizeof(keywords[0]),
370
	    sizeof(keywords[0]), kw_cmp);
371
	if (p != NULL)
372
		return p->k_val;
373
	return dfv;
374
}