]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/dhclient/conflex.c
kern: cpuset: allow jails to modify child jails' roots
[FreeBSD/FreeBSD.git] / sbin / dhclient / conflex.c
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 <mellon@fugue.com> 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 __FBSDID("$FreeBSD$");
47
48 #include <ctype.h>
49
50 #include "dhcpd.h"
51 #include "dhctoken.h"
52
53 int lexline;
54 int lexchar;
55 char *token_line;
56 static char *prev_line;
57 static char *cur_line;
58 const char *tlname;
59 int eol_token;
60
61 static char line1[81];
62 static char line2[81];
63 static unsigned lpos;
64 static unsigned line;
65 static int tlpos;
66 static int tline;
67 static int token;
68 static int ugflag;
69 static char *tval;
70 static char tokbuf[1500];
71
72 static int get_char(FILE *);
73 static int get_token(FILE *);
74 static void skip_to_eol(FILE *);
75 static int read_string(FILE *);
76 static int read_number(int, FILE *);
77 static int read_num_or_name(int, FILE *);
78 static int intern(char *, int);
79
80 void
81 new_parse(const char *name)
82 {
83         tlname = name;
84         lpos = line = 1;
85         cur_line = line1;
86         prev_line = line2;
87         token_line = cur_line;
88         cur_line[0] = prev_line[0] = 0;
89         warnings_occurred = 0;
90 }
91
92 static int
93 get_char(FILE *cfile)
94 {
95         int c = getc(cfile);
96         if (!ugflag) {
97                 if (c == '\n') {
98                         if (cur_line == line1) {
99                                 cur_line = line2;
100                                 prev_line = line1;
101                         } else {
102                                 cur_line = line1;
103                                 prev_line = line2;
104                         }
105                         line++;
106                         lpos = 1;
107                         cur_line[0] = 0;
108                 } else if (c != EOF) {
109                         if (lpos < sizeof(line1)) {
110                                 cur_line[lpos - 1] = c;
111                                 cur_line[lpos] = 0;
112                         }
113                         lpos++;
114                 }
115         } else
116                 ugflag = 0;
117         return (c);
118 }
119
120 static int
121 get_token(FILE *cfile)
122 {
123         int             c, ttok;
124         static char     tb[2];
125         int             l, p;
126
127         do {
128                 l = line;
129                 p = lpos;
130
131                 c = get_char(cfile);
132
133                 if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
134                         continue;
135                 if (c == '#') {
136                         skip_to_eol(cfile);
137                         continue;
138                 }
139                 if (c == '"') {
140                         lexline = l;
141                         lexchar = p;
142                         ttok = read_string(cfile);
143                         break;
144                 }
145                 if ((isascii(c) && isdigit(c)) || c == '-') {
146                         lexline = l;
147                         lexchar = p;
148                         ttok = read_number(c, cfile);
149                         break;
150                 } else if (isascii(c) && isalpha(c)) {
151                         lexline = l;
152                         lexchar = p;
153                         ttok = read_num_or_name(c, cfile);
154                         break;
155                 } else {
156                         lexline = l;
157                         lexchar = p;
158                         tb[0] = c;
159                         tb[1] = 0;
160                         tval = tb;
161                         ttok = c;
162                         break;
163                 }
164         } while (1);
165         return (ttok);
166 }
167
168 int
169 next_token(char **rval, FILE *cfile)
170 {
171         int     rv;
172
173         if (token) {
174                 if (lexline != tline)
175                         token_line = cur_line;
176                 lexchar = tlpos;
177                 lexline = tline;
178                 rv = token;
179                 token = 0;
180         } else {
181                 rv = get_token(cfile);
182                 token_line = cur_line;
183         }
184         if (rval)
185                 *rval = tval;
186
187         return (rv);
188 }
189
190 int
191 peek_token(char **rval, FILE *cfile)
192 {
193         int     x;
194
195         if (!token) {
196                 tlpos = lexchar;
197                 tline = lexline;
198                 token = get_token(cfile);
199                 if (lexline != tline)
200                         token_line = prev_line;
201                 x = lexchar;
202                 lexchar = tlpos;
203                 tlpos = x;
204                 x = lexline;
205                 lexline = tline;
206                 tline = x;
207         }
208         if (rval)
209                 *rval = tval;
210
211         return (token);
212 }
213
214 static void
215 skip_to_eol(FILE *cfile)
216 {
217         int     c;
218
219         do {
220                 c = get_char(cfile);
221                 if (c == EOF)
222                         return;
223                 if (c == '\n')
224                         return;
225         } while (1);
226 }
227
228 static int
229 read_string(FILE *cfile)
230 {
231         int     c, bs = 0;
232         unsigned i;
233
234         for (i = 0; i < sizeof(tokbuf); i++) {
235                 c = get_char(cfile);
236                 if (c == EOF) {
237                         parse_warn("eof in string constant");
238                         break;
239                 }
240                 if (bs) {
241                         bs = 0;
242                         i--;
243                         tokbuf[i] = c;
244                 } else if (c == '\\')
245                         bs = 1;
246                 else if (c == '"')
247                         break;
248                 else
249                         tokbuf[i] = c;
250         }
251         /*
252          * Normally, I'd feel guilty about this, but we're talking about
253          * strings that'll fit in a DHCP packet here...
254          */
255         if (i == sizeof(tokbuf)) {
256                 parse_warn("string constant larger than internal buffer");
257                 i--;
258         }
259         tokbuf[i] = 0;
260         tval = tokbuf;
261         return (STRING);
262 }
263
264 static int
265 read_number(int c, FILE *cfile)
266 {
267         int     seenx = 0, _token = NUMBER;
268         unsigned i = 0;
269
270         tokbuf[i++] = c;
271         for (; i < sizeof(tokbuf); i++) {
272                 c = get_char(cfile);
273                 if (!seenx && c == 'x')
274                         seenx = 1;
275                 else if (!isascii(c) || !isxdigit(c)) {
276                         ungetc(c, cfile);
277                         ugflag = 1;
278                         break;
279                 }
280                 tokbuf[i] = c;
281         }
282         if (i == sizeof(tokbuf)) {
283                 parse_warn("numeric token larger than internal buffer");
284                 i--;
285         }
286         tokbuf[i] = 0;
287         tval = tokbuf;
288
289         return (_token);
290 }
291
292 static int
293 read_num_or_name(int c, FILE *cfile)
294 {
295         unsigned i = 0;
296         int     rv = NUMBER_OR_NAME;
297
298         tokbuf[i++] = c;
299         for (; i < sizeof(tokbuf); i++) {
300                 c = get_char(cfile);
301                 if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
302                         ungetc(c, cfile);
303                         ugflag = 1;
304                         break;
305                 }
306                 if (!isxdigit(c))
307                         rv = NAME;
308                 tokbuf[i] = c;
309         }
310         if (i == sizeof(tokbuf)) {
311                 parse_warn("token larger than internal buffer");
312                 i--;
313         }
314         tokbuf[i] = 0;
315         tval = tokbuf;
316
317         return (intern(tval, rv));
318 }
319
320 static int
321 intern(char *atom, int dfv)
322 {
323         if (!isascii(atom[0]))
324                 return (dfv);
325
326         switch (tolower(atom[0])) {
327         case 'a':
328                 if (!strcasecmp(atom + 1, "lways-reply-rfc1048"))
329                         return (ALWAYS_REPLY_RFC1048);
330                 if (!strcasecmp(atom + 1, "ppend"))
331                         return (APPEND);
332                 if (!strcasecmp(atom + 1, "llow"))
333                         return (ALLOW);
334                 if (!strcasecmp(atom + 1, "lias"))
335                         return (ALIAS);
336                 if (!strcasecmp(atom + 1, "bandoned"))
337                         return (ABANDONED);
338                 if (!strcasecmp(atom + 1, "uthoritative"))
339                         return (AUTHORITATIVE);
340                 break;
341         case 'b':
342                 if (!strcasecmp(atom + 1, "ackoff-cutoff"))
343                         return (BACKOFF_CUTOFF);
344                 if (!strcasecmp(atom + 1, "ootp"))
345                         return (BOOTP);
346                 if (!strcasecmp(atom + 1, "ooting"))
347                         return (BOOTING);
348                 if (!strcasecmp(atom + 1, "oot-unknown-clients"))
349                         return (BOOT_UNKNOWN_CLIENTS);
350                 break;
351         case 'c':
352                 if (!strcasecmp(atom + 1, "lass"))
353                         return (CLASS);
354                 if (!strcasecmp(atom + 1, "iaddr"))
355                         return (CIADDR);
356                 if (!strcasecmp(atom + 1, "lient-identifier"))
357                         return (CLIENT_IDENTIFIER);
358                 if (!strcasecmp(atom + 1, "lient-hostname"))
359                         return (CLIENT_HOSTNAME);
360                 break;
361         case 'd':
362                 if (!strcasecmp(atom + 1, "omain"))
363                         return (DOMAIN);
364                 if (!strcasecmp(atom + 1, "eny"))
365                         return (DENY);
366                 if (!strncasecmp(atom + 1, "efault", 6)) {
367                         if (!atom[7])
368                                 return (DEFAULT);
369                         if (!strcasecmp(atom + 7, "-lease-time"))
370                                 return (DEFAULT_LEASE_TIME);
371                         break;
372                 }
373                 if (!strncasecmp(atom + 1, "ynamic-bootp", 12)) {
374                         if (!atom[13])
375                                 return (DYNAMIC_BOOTP);
376                         if (!strcasecmp(atom + 13, "-lease-cutoff"))
377                                 return (DYNAMIC_BOOTP_LEASE_CUTOFF);
378                         if (!strcasecmp(atom + 13, "-lease-length"))
379                                 return (DYNAMIC_BOOTP_LEASE_LENGTH);
380                         break;
381                 }
382                 break;
383         case 'e':
384                 if (!strcasecmp(atom + 1, "thernet"))
385                         return (ETHERNET);
386                 if (!strcasecmp(atom + 1, "nds"))
387                         return (ENDS);
388                 if (!strcasecmp(atom + 1, "xpire"))
389                         return (EXPIRE);
390                 break;
391         case 'f':
392                 if (!strcasecmp(atom + 1, "ilename"))
393                         return (FILENAME);
394                 if (!strcasecmp(atom + 1, "ixed-address"))
395                         return (FIXED_ADDR);
396                 if (!strcasecmp(atom + 1, "ddi"))
397                         return (FDDI);
398                 break;
399         case 'g':
400                 if (!strcasecmp(atom + 1, "iaddr"))
401                         return (GIADDR);
402                 if (!strcasecmp(atom + 1, "roup"))
403                         return (GROUP);
404                 if (!strcasecmp(atom + 1, "et-lease-hostnames"))
405                         return (GET_LEASE_HOSTNAMES);
406                 break;
407         case 'h':
408                 if (!strcasecmp(atom + 1, "ost"))
409                         return (HOST);
410                 if (!strcasecmp(atom + 1, "ardware"))
411                         return (HARDWARE);
412                 if (!strcasecmp(atom + 1, "ostname"))
413                         return (HOSTNAME);
414                 break;
415         case 'i':
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                 break;
528         case 'y':
529                 if (!strcasecmp(atom + 1, "iaddr"))
530                         return (YIADDR);
531                 break;
532         }
533         return (dfv);
534 }