Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/dhclient/conflex.c
39475 views
1
/* $OpenBSD: conflex.c,v 1.7 2004/09/15 19:02:38 deraadt Exp $ */
2
3
/* Lexical scanner for dhcpd config file... */
4
5
/*-
6
* SPDX-License-Identifier: BSD-3-Clause
7
*
8
* Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
*
15
* 1. Redistributions of source code must retain the above copyright
16
* notice, this list of conditions and the following disclaimer.
17
* 2. Redistributions in binary form must reproduce the above copyright
18
* notice, this list of conditions and the following disclaimer in the
19
* documentation and/or other materials provided with the distribution.
20
* 3. Neither the name of The Internet Software Consortium nor the names
21
* of its contributors may be used to endorse or promote products derived
22
* from this software without specific prior written permission.
23
*
24
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
25
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
26
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
29
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
32
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
35
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
* SUCH DAMAGE.
37
*
38
* This software has been written for the Internet Software Consortium
39
* by Ted Lemon <[email protected]> in cooperation with Vixie
40
* Enterprises. To learn more about the Internet Software Consortium,
41
* see ``http://www.vix.com/isc''. To learn more about Vixie
42
* Enterprises, see ``http://www.vix.com''.
43
*/
44
45
#include <sys/cdefs.h>
46
#include <ctype.h>
47
48
#include "dhcpd.h"
49
#include "dhctoken.h"
50
51
int lexline;
52
int lexchar;
53
char *token_line;
54
static char *prev_line;
55
static char *cur_line;
56
const char *tlname;
57
int eol_token;
58
59
static char line1[81];
60
static char line2[81];
61
static unsigned lpos;
62
static unsigned line;
63
static int tlpos;
64
static int tline;
65
static int token;
66
static int ugflag;
67
static char *tval;
68
static char tokbuf[1500];
69
70
static int get_char(FILE *);
71
static int get_token(FILE *);
72
static void skip_to_eol(FILE *);
73
static int read_string(FILE *);
74
static int read_number(int, FILE *);
75
static int read_num_or_name(int, FILE *);
76
static int intern(char *, int);
77
78
void
79
new_parse(const char *name)
80
{
81
tlname = name;
82
lpos = line = 1;
83
cur_line = line1;
84
prev_line = line2;
85
token_line = cur_line;
86
cur_line[0] = prev_line[0] = 0;
87
warnings_occurred = 0;
88
}
89
90
static int
91
get_char(FILE *cfile)
92
{
93
int c = getc(cfile);
94
if (!ugflag) {
95
if (c == '\n') {
96
if (cur_line == line1) {
97
cur_line = line2;
98
prev_line = line1;
99
} else {
100
cur_line = line1;
101
prev_line = line2;
102
}
103
line++;
104
lpos = 1;
105
cur_line[0] = 0;
106
} else if (c != EOF) {
107
if (lpos < sizeof(line1)) {
108
cur_line[lpos - 1] = c;
109
cur_line[lpos] = 0;
110
}
111
lpos++;
112
}
113
} else
114
ugflag = 0;
115
return (c);
116
}
117
118
static int
119
get_token(FILE *cfile)
120
{
121
int c, ttok;
122
static char tb[2];
123
int l, p;
124
125
do {
126
l = line;
127
p = lpos;
128
129
c = get_char(cfile);
130
131
if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
132
continue;
133
if (c == '#') {
134
skip_to_eol(cfile);
135
continue;
136
}
137
if (c == '"') {
138
lexline = l;
139
lexchar = p;
140
ttok = read_string(cfile);
141
break;
142
}
143
if ((isascii(c) && isdigit(c)) || c == '-') {
144
lexline = l;
145
lexchar = p;
146
ttok = read_number(c, cfile);
147
break;
148
} else if (isascii(c) && isalpha(c)) {
149
lexline = l;
150
lexchar = p;
151
ttok = read_num_or_name(c, cfile);
152
break;
153
} else {
154
lexline = l;
155
lexchar = p;
156
tb[0] = c;
157
tb[1] = 0;
158
tval = tb;
159
ttok = c;
160
break;
161
}
162
} while (1);
163
return (ttok);
164
}
165
166
int
167
next_token(char **rval, FILE *cfile)
168
{
169
int rv;
170
171
if (token) {
172
if (lexline != tline)
173
token_line = cur_line;
174
lexchar = tlpos;
175
lexline = tline;
176
rv = token;
177
token = 0;
178
} else {
179
rv = get_token(cfile);
180
token_line = cur_line;
181
}
182
if (rval)
183
*rval = tval;
184
185
return (rv);
186
}
187
188
int
189
peek_token(char **rval, FILE *cfile)
190
{
191
int x;
192
193
if (!token) {
194
tlpos = lexchar;
195
tline = lexline;
196
token = get_token(cfile);
197
if (lexline != tline)
198
token_line = prev_line;
199
x = lexchar;
200
lexchar = tlpos;
201
tlpos = x;
202
x = lexline;
203
lexline = tline;
204
tline = x;
205
}
206
if (rval)
207
*rval = tval;
208
209
return (token);
210
}
211
212
static void
213
skip_to_eol(FILE *cfile)
214
{
215
int c;
216
217
do {
218
c = get_char(cfile);
219
if (c == EOF)
220
return;
221
if (c == '\n')
222
return;
223
} while (1);
224
}
225
226
static int
227
read_string(FILE *cfile)
228
{
229
int c, bs = 0;
230
unsigned i;
231
232
for (i = 0; i < sizeof(tokbuf); i++) {
233
c = get_char(cfile);
234
if (c == EOF) {
235
parse_warn("eof in string constant");
236
break;
237
}
238
if (bs) {
239
bs = 0;
240
i--;
241
tokbuf[i] = c;
242
} else if (c == '\\')
243
bs = 1;
244
else if (c == '"')
245
break;
246
else
247
tokbuf[i] = c;
248
}
249
/*
250
* Normally, I'd feel guilty about this, but we're talking about
251
* strings that'll fit in a DHCP packet here...
252
*/
253
if (i == sizeof(tokbuf)) {
254
parse_warn("string constant larger than internal buffer");
255
i--;
256
}
257
tokbuf[i] = 0;
258
tval = tokbuf;
259
return (STRING);
260
}
261
262
static int
263
read_number(int c, FILE *cfile)
264
{
265
int seenx = 0, _token = NUMBER;
266
unsigned i = 0;
267
268
tokbuf[i++] = c;
269
for (; i < sizeof(tokbuf); i++) {
270
c = get_char(cfile);
271
if (!seenx && c == 'x')
272
seenx = 1;
273
else if (!isascii(c) || !isxdigit(c)) {
274
ungetc(c, cfile);
275
ugflag = 1;
276
break;
277
}
278
tokbuf[i] = c;
279
}
280
if (i == sizeof(tokbuf)) {
281
parse_warn("numeric token larger than internal buffer");
282
i--;
283
}
284
tokbuf[i] = 0;
285
tval = tokbuf;
286
287
return (_token);
288
}
289
290
static int
291
read_num_or_name(int c, FILE *cfile)
292
{
293
unsigned i = 0;
294
int rv = NUMBER_OR_NAME;
295
296
tokbuf[i++] = c;
297
for (; i < sizeof(tokbuf); i++) {
298
c = get_char(cfile);
299
if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
300
ungetc(c, cfile);
301
ugflag = 1;
302
break;
303
}
304
if (!isxdigit(c))
305
rv = NAME;
306
tokbuf[i] = c;
307
}
308
if (i == sizeof(tokbuf)) {
309
parse_warn("token larger than internal buffer");
310
i--;
311
}
312
tokbuf[i] = 0;
313
tval = tokbuf;
314
315
return (intern(tval, rv));
316
}
317
318
static int
319
intern(char *atom, int dfv)
320
{
321
if (!isascii(atom[0]))
322
return (dfv);
323
324
switch (tolower(atom[0])) {
325
case 'a':
326
if (!strcasecmp(atom + 1, "lways-reply-rfc1048"))
327
return (ALWAYS_REPLY_RFC1048);
328
if (!strcasecmp(atom + 1, "ppend"))
329
return (APPEND);
330
if (!strcasecmp(atom + 1, "llow"))
331
return (ALLOW);
332
if (!strcasecmp(atom + 1, "lias"))
333
return (ALIAS);
334
if (!strcasecmp(atom + 1, "bandoned"))
335
return (ABANDONED);
336
if (!strcasecmp(atom + 1, "uthoritative"))
337
return (AUTHORITATIVE);
338
break;
339
case 'b':
340
if (!strcasecmp(atom + 1, "ackoff-cutoff"))
341
return (BACKOFF_CUTOFF);
342
if (!strcasecmp(atom + 1, "ootp"))
343
return (BOOTP);
344
if (!strcasecmp(atom + 1, "ooting"))
345
return (BOOTING);
346
if (!strcasecmp(atom + 1, "oot-unknown-clients"))
347
return (BOOT_UNKNOWN_CLIENTS);
348
break;
349
case 'c':
350
if (!strcasecmp(atom + 1, "lass"))
351
return (CLASS);
352
if (!strcasecmp(atom + 1, "iaddr"))
353
return (CIADDR);
354
if (!strcasecmp(atom + 1, "lient-identifier"))
355
return (CLIENT_IDENTIFIER);
356
if (!strcasecmp(atom + 1, "lient-hostname"))
357
return (CLIENT_HOSTNAME);
358
break;
359
case 'd':
360
if (!strcasecmp(atom + 1, "omain"))
361
return (DOMAIN);
362
if (!strcasecmp(atom + 1, "eny"))
363
return (DENY);
364
if (!strncasecmp(atom + 1, "efault", 6)) {
365
if (!atom[7])
366
return (DEFAULT);
367
if (!strcasecmp(atom + 7, "-lease-time"))
368
return (DEFAULT_LEASE_TIME);
369
break;
370
}
371
if (!strncasecmp(atom + 1, "ynamic-bootp", 12)) {
372
if (!atom[13])
373
return (DYNAMIC_BOOTP);
374
if (!strcasecmp(atom + 13, "-lease-cutoff"))
375
return (DYNAMIC_BOOTP_LEASE_CUTOFF);
376
if (!strcasecmp(atom + 13, "-lease-length"))
377
return (DYNAMIC_BOOTP_LEASE_LENGTH);
378
break;
379
}
380
break;
381
case 'e':
382
if (!strcasecmp(atom + 1, "thernet"))
383
return (ETHERNET);
384
if (!strcasecmp(atom + 1, "nds"))
385
return (ENDS);
386
if (!strcasecmp(atom + 1, "xpire"))
387
return (EXPIRE);
388
break;
389
case 'f':
390
if (!strcasecmp(atom + 1, "ilename"))
391
return (FILENAME);
392
if (!strcasecmp(atom + 1, "ixed-address"))
393
return (FIXED_ADDR);
394
if (!strcasecmp(atom + 1, "ddi"))
395
return (FDDI);
396
break;
397
case 'g':
398
if (!strcasecmp(atom + 1, "iaddr"))
399
return (GIADDR);
400
if (!strcasecmp(atom + 1, "roup"))
401
return (GROUP);
402
if (!strcasecmp(atom + 1, "et-lease-hostnames"))
403
return (GET_LEASE_HOSTNAMES);
404
break;
405
case 'h':
406
if (!strcasecmp(atom + 1, "ost"))
407
return (HOST);
408
if (!strcasecmp(atom + 1, "ardware"))
409
return (HARDWARE);
410
if (!strcasecmp(atom + 1, "ostname"))
411
return (HOSTNAME);
412
break;
413
case 'i':
414
if (!strcasecmp(atom + 1, "gnore"))
415
return (IGNORE);
416
if (!strcasecmp(atom + 1, "nitial-interval"))
417
return (INITIAL_INTERVAL);
418
if (!strcasecmp(atom + 1, "nterface"))
419
return (INTERFACE);
420
break;
421
case 'l':
422
if (!strcasecmp(atom + 1, "ease"))
423
return (LEASE);
424
break;
425
case 'm':
426
if (!strcasecmp(atom + 1, "ax-lease-time"))
427
return (MAX_LEASE_TIME);
428
if (!strncasecmp(atom + 1, "edi", 3)) {
429
if (!strcasecmp(atom + 4, "a"))
430
return (MEDIA);
431
if (!strcasecmp(atom + 4, "um"))
432
return (MEDIUM);
433
break;
434
}
435
break;
436
case 'n':
437
if (!strcasecmp(atom + 1, "ameserver"))
438
return (NAMESERVER);
439
if (!strcasecmp(atom + 1, "etmask"))
440
return (NETMASK);
441
if (!strcasecmp(atom + 1, "ext-server"))
442
return (NEXT_SERVER);
443
if (!strcasecmp(atom + 1, "ot"))
444
return (TOKEN_NOT);
445
break;
446
case 'o':
447
if (!strcasecmp(atom + 1, "ption"))
448
return (OPTION);
449
if (!strcasecmp(atom + 1, "ne-lease-per-client"))
450
return (ONE_LEASE_PER_CLIENT);
451
break;
452
case 'p':
453
if (!strcasecmp(atom + 1, "repend"))
454
return (PREPEND);
455
if (!strcasecmp(atom + 1, "acket"))
456
return (PACKET);
457
break;
458
case 'r':
459
if (!strcasecmp(atom + 1, "ange"))
460
return (RANGE);
461
if (!strcasecmp(atom + 1, "equest"))
462
return (REQUEST);
463
if (!strcasecmp(atom + 1, "equire"))
464
return (REQUIRE);
465
if (!strcasecmp(atom + 1, "etry"))
466
return (RETRY);
467
if (!strcasecmp(atom + 1, "enew"))
468
return (RENEW);
469
if (!strcasecmp(atom + 1, "ebind"))
470
return (REBIND);
471
if (!strcasecmp(atom + 1, "eboot"))
472
return (REBOOT);
473
if (!strcasecmp(atom + 1, "eject"))
474
return (REJECT);
475
break;
476
case 's':
477
if (!strcasecmp(atom + 1, "earch"))
478
return (SEARCH);
479
if (!strcasecmp(atom + 1, "tarts"))
480
return (STARTS);
481
if (!strcasecmp(atom + 1, "iaddr"))
482
return (SIADDR);
483
if (!strcasecmp(atom + 1, "ubnet"))
484
return (SUBNET);
485
if (!strcasecmp(atom + 1, "hared-network"))
486
return (SHARED_NETWORK);
487
if (!strcasecmp(atom + 1, "erver-name"))
488
return (SERVER_NAME);
489
if (!strcasecmp(atom + 1, "erver-identifier"))
490
return (SERVER_IDENTIFIER);
491
if (!strcasecmp(atom + 1, "elect-timeout"))
492
return (SELECT_TIMEOUT);
493
if (!strcasecmp(atom + 1, "end"))
494
return (SEND);
495
if (!strcasecmp(atom + 1, "cript"))
496
return (SCRIPT);
497
if (!strcasecmp(atom + 1, "upersede"))
498
return (SUPERSEDE);
499
break;
500
case 't':
501
if (!strcasecmp(atom + 1, "imestamp"))
502
return (TIMESTAMP);
503
if (!strcasecmp(atom + 1, "imeout"))
504
return (TIMEOUT);
505
if (!strcasecmp(atom + 1, "oken-ring"))
506
return (TOKEN_RING);
507
break;
508
case 'u':
509
if (!strncasecmp(atom + 1, "se", 2)) {
510
if (!strcasecmp(atom + 3, "r-class"))
511
return (USER_CLASS);
512
if (!strcasecmp(atom + 3, "-host-decl-names"))
513
return (USE_HOST_DECL_NAMES);
514
if (!strcasecmp(atom + 3,
515
"-lease-addr-for-default-route"))
516
return (USE_LEASE_ADDR_FOR_DEFAULT_ROUTE);
517
break;
518
}
519
if (!strcasecmp(atom + 1, "id"))
520
return (UID);
521
if (!strcasecmp(atom + 1, "nknown-clients"))
522
return (UNKNOWN_CLIENTS);
523
break;
524
case 'v':
525
if (!strcasecmp(atom + 1, "endor-class"))
526
return (VENDOR_CLASS);
527
if (!strcasecmp(atom + 1, "lan-pcp"))
528
return (VLAN_PCP);
529
break;
530
case 'y':
531
if (!strcasecmp(atom + 1, "iaddr"))
532
return (YIADDR);
533
break;
534
}
535
return (dfv);
536
}
537
538