]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sbin/dhclient/conflex.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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  * 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/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
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 char *prev_line;
55 char *cur_line;
56 char *tlname;
57 int eol_token;
58
59 static char line1[81];
60 static char line2[81];
61 static int lpos;
62 static int 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(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 = line2;
101                                 prev_line = line1;
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     i, c, bs = 0;
230
231         for (i = 0; i < sizeof(tokbuf); i++) {
232                 c = get_char(cfile);
233                 if (c == EOF) {
234                         parse_warn("eof in string constant");
235                         break;
236                 }
237                 if (bs) {
238                         bs = 0;
239                         i--;
240                         tokbuf[i] = c;
241                 } else if (c == '\\')
242                         bs = 1;
243                 else if (c == '"')
244                         break;
245                 else
246                         tokbuf[i] = c;
247         }
248         /*
249          * Normally, I'd feel guilty about this, but we're talking about
250          * strings that'll fit in a DHCP packet here...
251          */
252         if (i == sizeof(tokbuf)) {
253                 parse_warn("string constant larger than internal buffer");
254                 i--;
255         }
256         tokbuf[i] = 0;
257         tval = tokbuf;
258         return (STRING);
259 }
260
261 static int
262 read_number(int c, FILE *cfile)
263 {
264         int     seenx = 0, i = 0, token = NUMBER;
265
266         tokbuf[i++] = c;
267         for (; i < sizeof(tokbuf); i++) {
268                 c = get_char(cfile);
269                 if (!seenx && c == 'x')
270                         seenx = 1;
271                 else if (!isascii(c) || !isxdigit(c)) {
272                         ungetc(c, cfile);
273                         ugflag = 1;
274                         break;
275                 }
276                 tokbuf[i] = c;
277         }
278         if (i == sizeof(tokbuf)) {
279                 parse_warn("numeric token larger than internal buffer");
280                 i--;
281         }
282         tokbuf[i] = 0;
283         tval = tokbuf;
284
285         return (token);
286 }
287
288 static int
289 read_num_or_name(int c, FILE *cfile)
290 {
291         int     i = 0;
292         int     rv = NUMBER_OR_NAME;
293
294         tokbuf[i++] = c;
295         for (; i < sizeof(tokbuf); i++) {
296                 c = get_char(cfile);
297                 if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
298                         ungetc(c, cfile);
299                         ugflag = 1;
300                         break;
301                 }
302                 if (!isxdigit(c))
303                         rv = NAME;
304                 tokbuf[i] = c;
305         }
306         if (i == sizeof(tokbuf)) {
307                 parse_warn("token larger than internal buffer");
308                 i--;
309         }
310         tokbuf[i] = 0;
311         tval = tokbuf;
312
313         return (intern(tval, rv));
314 }
315
316 static int
317 intern(char *atom, int dfv)
318 {
319         if (!isascii(atom[0]))
320                 return (dfv);
321
322         switch (tolower(atom[0])) {
323         case 'a':
324                 if (!strcasecmp(atom + 1, "lways-reply-rfc1048"))
325                         return (ALWAYS_REPLY_RFC1048);
326                 if (!strcasecmp(atom + 1, "ppend"))
327                         return (APPEND);
328                 if (!strcasecmp(atom + 1, "llow"))
329                         return (ALLOW);
330                 if (!strcasecmp(atom + 1, "lias"))
331                         return (ALIAS);
332                 if (!strcasecmp(atom + 1, "bandoned"))
333                         return (ABANDONED);
334                 if (!strcasecmp(atom + 1, "uthoritative"))
335                         return (AUTHORITATIVE);
336                 break;
337         case 'b':
338                 if (!strcasecmp(atom + 1, "ackoff-cutoff"))
339                         return (BACKOFF_CUTOFF);
340                 if (!strcasecmp(atom + 1, "ootp"))
341                         return (BOOTP);
342                 if (!strcasecmp(atom + 1, "ooting"))
343                         return (BOOTING);
344                 if (!strcasecmp(atom + 1, "oot-unknown-clients"))
345                         return (BOOT_UNKNOWN_CLIENTS);
346         case 'c':
347                 if (!strcasecmp(atom + 1, "lass"))
348                         return (CLASS);
349                 if (!strcasecmp(atom + 1, "iaddr"))
350                         return (CIADDR);
351                 if (!strcasecmp(atom + 1, "lient-identifier"))
352                         return (CLIENT_IDENTIFIER);
353                 if (!strcasecmp(atom + 1, "lient-hostname"))
354                         return (CLIENT_HOSTNAME);
355                 break;
356         case 'd':
357                 if (!strcasecmp(atom + 1, "omain"))
358                         return (DOMAIN);
359                 if (!strcasecmp(atom + 1, "eny"))
360                         return (DENY);
361                 if (!strncasecmp(atom + 1, "efault", 6)) {
362                         if (!atom[7])
363                                 return (DEFAULT);
364                         if (!strcasecmp(atom + 7, "-lease-time"))
365                                 return (DEFAULT_LEASE_TIME);
366                         break;
367                 }
368                 if (!strncasecmp(atom + 1, "ynamic-bootp", 12)) {
369                         if (!atom[13])
370                                 return (DYNAMIC_BOOTP);
371                         if (!strcasecmp(atom + 13, "-lease-cutoff"))
372                                 return (DYNAMIC_BOOTP_LEASE_CUTOFF);
373                         if (!strcasecmp(atom + 13, "-lease-length"))
374                                 return (DYNAMIC_BOOTP_LEASE_LENGTH);
375                         break;
376                 }
377                 break;
378         case 'e':
379                 if (!strcasecmp(atom + 1, "thernet"))
380                         return (ETHERNET);
381                 if (!strcasecmp(atom + 1, "nds"))
382                         return (ENDS);
383                 if (!strcasecmp(atom + 1, "xpire"))
384                         return (EXPIRE);
385                 break;
386         case 'f':
387                 if (!strcasecmp(atom + 1, "ilename"))
388                         return (FILENAME);
389                 if (!strcasecmp(atom + 1, "ixed-address"))
390                         return (FIXED_ADDR);
391                 if (!strcasecmp(atom + 1, "ddi"))
392                         return (FDDI);
393                 break;
394         case 'g':
395                 if (!strcasecmp(atom + 1, "iaddr"))
396                         return (GIADDR);
397                 if (!strcasecmp(atom + 1, "roup"))
398                         return (GROUP);
399                 if (!strcasecmp(atom + 1, "et-lease-hostnames"))
400                         return (GET_LEASE_HOSTNAMES);
401                 break;
402         case 'h':
403                 if (!strcasecmp(atom + 1, "ost"))
404                         return (HOST);
405                 if (!strcasecmp(atom + 1, "ardware"))
406                         return (HARDWARE);
407                 if (!strcasecmp(atom + 1, "ostname"))
408                         return (HOSTNAME);
409                 break;
410         case 'i':
411                 if (!strcasecmp(atom + 1, "nitial-interval"))
412                         return (INITIAL_INTERVAL);
413                 if (!strcasecmp(atom + 1, "nterface"))
414                         return (INTERFACE);
415                 break;
416         case 'l':
417                 if (!strcasecmp(atom + 1, "ease"))
418                         return (LEASE);
419                 break;
420         case 'm':
421                 if (!strcasecmp(atom + 1, "ax-lease-time"))
422                         return (MAX_LEASE_TIME);
423                 if (!strncasecmp(atom + 1, "edi", 3)) {
424                         if (!strcasecmp(atom + 4, "a"))
425                                 return (MEDIA);
426                         if (!strcasecmp(atom + 4, "um"))
427                                 return (MEDIUM);
428                         break;
429                 }
430                 break;
431         case 'n':
432                 if (!strcasecmp(atom + 1, "ameserver"))
433                         return (NAMESERVER);
434                 if (!strcasecmp(atom + 1, "etmask"))
435                         return (NETMASK);
436                 if (!strcasecmp(atom + 1, "ext-server"))
437                         return (NEXT_SERVER);
438                 if (!strcasecmp(atom + 1, "ot"))
439                         return (TOKEN_NOT);
440                 break;
441         case 'o':
442                 if (!strcasecmp(atom + 1, "ption"))
443                         return (OPTION);
444                 if (!strcasecmp(atom + 1, "ne-lease-per-client"))
445                         return (ONE_LEASE_PER_CLIENT);
446                 break;
447         case 'p':
448                 if (!strcasecmp(atom + 1, "repend"))
449                         return (PREPEND);
450                 if (!strcasecmp(atom + 1, "acket"))
451                         return (PACKET);
452                 break;
453         case 'r':
454                 if (!strcasecmp(atom + 1, "ange"))
455                         return (RANGE);
456                 if (!strcasecmp(atom + 1, "equest"))
457                         return (REQUEST);
458                 if (!strcasecmp(atom + 1, "equire"))
459                         return (REQUIRE);
460                 if (!strcasecmp(atom + 1, "etry"))
461                         return (RETRY);
462                 if (!strcasecmp(atom + 1, "enew"))
463                         return (RENEW);
464                 if (!strcasecmp(atom + 1, "ebind"))
465                         return (REBIND);
466                 if (!strcasecmp(atom + 1, "eboot"))
467                         return (REBOOT);
468                 if (!strcasecmp(atom + 1, "eject"))
469                         return (REJECT);
470                 break;
471         case 's':
472                 if (!strcasecmp(atom + 1, "earch"))
473                         return (SEARCH);
474                 if (!strcasecmp(atom + 1, "tarts"))
475                         return (STARTS);
476                 if (!strcasecmp(atom + 1, "iaddr"))
477                         return (SIADDR);
478                 if (!strcasecmp(atom + 1, "ubnet"))
479                         return (SUBNET);
480                 if (!strcasecmp(atom + 1, "hared-network"))
481                         return (SHARED_NETWORK);
482                 if (!strcasecmp(atom + 1, "erver-name"))
483                         return (SERVER_NAME);
484                 if (!strcasecmp(atom + 1, "erver-identifier"))
485                         return (SERVER_IDENTIFIER);
486                 if (!strcasecmp(atom + 1, "elect-timeout"))
487                         return (SELECT_TIMEOUT);
488                 if (!strcasecmp(atom + 1, "end"))
489                         return (SEND);
490                 if (!strcasecmp(atom + 1, "cript"))
491                         return (SCRIPT);
492                 if (!strcasecmp(atom + 1, "upersede"))
493                         return (SUPERSEDE);
494                 break;
495         case 't':
496                 if (!strcasecmp(atom + 1, "imestamp"))
497                         return (TIMESTAMP);
498                 if (!strcasecmp(atom + 1, "imeout"))
499                         return (TIMEOUT);
500                 if (!strcasecmp(atom + 1, "oken-ring"))
501                         return (TOKEN_RING);
502                 break;
503         case 'u':
504                 if (!strncasecmp(atom + 1, "se", 2)) {
505                         if (!strcasecmp(atom + 3, "r-class"))
506                                 return (USER_CLASS);
507                         if (!strcasecmp(atom + 3, "-host-decl-names"))
508                                 return (USE_HOST_DECL_NAMES);
509                         if (!strcasecmp(atom + 3,
510                                          "-lease-addr-for-default-route"))
511                                 return (USE_LEASE_ADDR_FOR_DEFAULT_ROUTE);
512                         break;
513                 }
514                 if (!strcasecmp(atom + 1, "id"))
515                         return (UID);
516                 if (!strcasecmp(atom + 1, "nknown-clients"))
517                         return (UNKNOWN_CLIENTS);
518                 break;
519         case 'v':
520                 if (!strcasecmp(atom + 1, "endor-class"))
521                         return (VENDOR_CLASS);
522                 break;
523         case 'y':
524                 if (!strcasecmp(atom + 1, "iaddr"))
525                         return (YIADDR);
526                 break;
527         }
528         return (dfv);
529 }