]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/dhclient/conflex.c
This commit was generated by cvs2svn to compensate for changes in r147899,
[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  * 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 <ctype.h>
44
45 #include "dhcpd.h"
46 #include "dhctoken.h"
47
48 int lexline;
49 int lexchar;
50 char *token_line;
51 char *prev_line;
52 char *cur_line;
53 char *tlname;
54 int eol_token;
55
56 static char line1[81];
57 static char line2[81];
58 static int lpos;
59 static int line;
60 static int tlpos;
61 static int tline;
62 static int token;
63 static int ugflag;
64 static char *tval;
65 static char tokbuf[1500];
66
67 static int get_char(FILE *);
68 static int get_token(FILE *);
69 static void skip_to_eol(FILE *);
70 static int read_string(FILE *);
71 static int read_number(int, FILE *);
72 static int read_num_or_name(int, FILE *);
73 static int intern(char *, int);
74
75 void
76 new_parse(char *name)
77 {
78         tlname = name;
79         lpos = line = 1;
80         cur_line = line1;
81         prev_line = line2;
82         token_line = cur_line;
83         cur_line[0] = prev_line[0] = 0;
84         warnings_occurred = 0;
85 }
86
87 static int
88 get_char(FILE *cfile)
89 {
90         int c = getc(cfile);
91         if (!ugflag) {
92                 if (c == '\n') {
93                         if (cur_line == line1) {
94                                 cur_line = line2;
95                                 prev_line = line1;
96                         } else {
97                                 cur_line = line2;
98                                 prev_line = line1;
99                         }
100                         line++;
101                         lpos = 1;
102                         cur_line[0] = 0;
103                 } else if (c != EOF) {
104                         if (lpos <= 81) {
105                                 cur_line[lpos - 1] = c;
106                                 cur_line[lpos] = 0;
107                         }
108                         lpos++;
109                 }
110         } else
111                 ugflag = 0;
112         return (c);
113 }
114
115 static int
116 get_token(FILE *cfile)
117 {
118         int             c, ttok;
119         static char     tb[2];
120         int             l, p;
121
122         do {
123                 l = line;
124                 p = lpos;
125
126                 c = get_char(cfile);
127
128                 if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
129                         continue;
130                 if (c == '#') {
131                         skip_to_eol(cfile);
132                         continue;
133                 }
134                 if (c == '"') {
135                         lexline = l;
136                         lexchar = p;
137                         ttok = read_string(cfile);
138                         break;
139                 }
140                 if ((isascii(c) && isdigit(c)) || c == '-') {
141                         lexline = l;
142                         lexchar = p;
143                         ttok = read_number(c, cfile);
144                         break;
145                 } else if (isascii(c) && isalpha(c)) {
146                         lexline = l;
147                         lexchar = p;
148                         ttok = read_num_or_name(c, cfile);
149                         break;
150                 } else {
151                         lexline = l;
152                         lexchar = p;
153                         tb[0] = c;
154                         tb[1] = 0;
155                         tval = tb;
156                         ttok = c;
157                         break;
158                 }
159         } while (1);
160         return (ttok);
161 }
162
163 int
164 next_token(char **rval, FILE *cfile)
165 {
166         int     rv;
167
168         if (token) {
169                 if (lexline != tline)
170                         token_line = cur_line;
171                 lexchar = tlpos;
172                 lexline = tline;
173                 rv = token;
174                 token = 0;
175         } else {
176                 rv = get_token(cfile);
177                 token_line = cur_line;
178         }
179         if (rval)
180                 *rval = tval;
181
182         return (rv);
183 }
184
185 int
186 peek_token(char **rval, FILE *cfile)
187 {
188         int     x;
189
190         if (!token) {
191                 tlpos = lexchar;
192                 tline = lexline;
193                 token = get_token(cfile);
194                 if (lexline != tline)
195                         token_line = prev_line;
196                 x = lexchar;
197                 lexchar = tlpos;
198                 tlpos = x;
199                 x = lexline;
200                 lexline = tline;
201                 tline = x;
202         }
203         if (rval)
204                 *rval = tval;
205
206         return (token);
207 }
208
209 static void
210 skip_to_eol(FILE *cfile)
211 {
212         int     c;
213
214         do {
215                 c = get_char(cfile);
216                 if (c == EOF)
217                         return;
218                 if (c == '\n')
219                         return;
220         } while (1);
221 }
222
223 static int
224 read_string(FILE *cfile)
225 {
226         int     i, c, bs = 0;
227
228         for (i = 0; i < sizeof(tokbuf); i++) {
229                 c = get_char(cfile);
230                 if (c == EOF) {
231                         parse_warn("eof in string constant");
232                         break;
233                 }
234                 if (bs) {
235                         bs = 0;
236                         tokbuf[i] = c;
237                 } else if (c == '\\')
238                         bs = 1;
239                 else if (c == '"')
240                         break;
241                 else
242                         tokbuf[i] = c;
243         }
244         /*
245          * Normally, I'd feel guilty about this, but we're talking about
246          * strings that'll fit in a DHCP packet here...
247          */
248         if (i == sizeof(tokbuf)) {
249                 parse_warn("string constant larger than internal buffer");
250                 i--;
251         }
252         tokbuf[i] = 0;
253         tval = tokbuf;
254         return (STRING);
255 }
256
257 static int
258 read_number(int c, FILE *cfile)
259 {
260         int     seenx = 0, i = 0, token = NUMBER;
261
262         tokbuf[i++] = c;
263         for (; i < sizeof(tokbuf); i++) {
264                 c = get_char(cfile);
265                 if (!seenx && c == 'x')
266                         seenx = 1;
267                 else if (!isascii(c) || !isxdigit(c)) {
268                         ungetc(c, cfile);
269                         ugflag = 1;
270                         break;
271                 }
272                 tokbuf[i] = c;
273         }
274         if (i == sizeof(tokbuf)) {
275                 parse_warn("numeric token larger than internal buffer");
276                 i--;
277         }
278         tokbuf[i] = 0;
279         tval = tokbuf;
280
281         return (token);
282 }
283
284 static int
285 read_num_or_name(int c, FILE *cfile)
286 {
287         int     i = 0;
288         int     rv = NUMBER_OR_NAME;
289
290         tokbuf[i++] = c;
291         for (; i < sizeof(tokbuf); i++) {
292                 c = get_char(cfile);
293                 if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
294                         ungetc(c, cfile);
295                         ugflag = 1;
296                         break;
297                 }
298                 if (!isxdigit(c))
299                         rv = NAME;
300                 tokbuf[i] = c;
301         }
302         if (i == sizeof(tokbuf)) {
303                 parse_warn("token larger than internal buffer");
304                 i--;
305         }
306         tokbuf[i] = 0;
307         tval = tokbuf;
308
309         return (intern(tval, rv));
310 }
311
312 static int
313 intern(char *atom, int dfv)
314 {
315         if (!isascii(atom[0]))
316                 return (dfv);
317
318         switch (tolower(atom[0])) {
319         case 'a':
320                 if (!strcasecmp(atom + 1, "lways-reply-rfc1048"))
321                         return (ALWAYS_REPLY_RFC1048);
322                 if (!strcasecmp(atom + 1, "ppend"))
323                         return (APPEND);
324                 if (!strcasecmp(atom + 1, "llow"))
325                         return (ALLOW);
326                 if (!strcasecmp(atom + 1, "lias"))
327                         return (ALIAS);
328                 if (!strcasecmp(atom + 1, "bandoned"))
329                         return (ABANDONED);
330                 if (!strcasecmp(atom + 1, "uthoritative"))
331                         return (AUTHORITATIVE);
332                 break;
333         case 'b':
334                 if (!strcasecmp(atom + 1, "ackoff-cutoff"))
335                         return (BACKOFF_CUTOFF);
336                 if (!strcasecmp(atom + 1, "ootp"))
337                         return (BOOTP);
338                 if (!strcasecmp(atom + 1, "ooting"))
339                         return (BOOTING);
340                 if (!strcasecmp(atom + 1, "oot-unknown-clients"))
341                         return (BOOT_UNKNOWN_CLIENTS);
342         case 'c':
343                 if (!strcasecmp(atom + 1, "lass"))
344                         return (CLASS);
345                 if (!strcasecmp(atom + 1, "iaddr"))
346                         return (CIADDR);
347                 if (!strcasecmp(atom + 1, "lient-identifier"))
348                         return (CLIENT_IDENTIFIER);
349                 if (!strcasecmp(atom + 1, "lient-hostname"))
350                         return (CLIENT_HOSTNAME);
351                 break;
352         case 'd':
353                 if (!strcasecmp(atom + 1, "omain"))
354                         return (DOMAIN);
355                 if (!strcasecmp(atom + 1, "eny"))
356                         return (DENY);
357                 if (!strncasecmp(atom + 1, "efault", 6)) {
358                         if (!atom[7])
359                                 return (DEFAULT);
360                         if (!strcasecmp(atom + 7, "-lease-time"))
361                                 return (DEFAULT_LEASE_TIME);
362                         break;
363                 }
364                 if (!strncasecmp(atom + 1, "ynamic-bootp", 12)) {
365                         if (!atom[13])
366                                 return (DYNAMIC_BOOTP);
367                         if (!strcasecmp(atom + 13, "-lease-cutoff"))
368                                 return (DYNAMIC_BOOTP_LEASE_CUTOFF);
369                         if (!strcasecmp(atom + 13, "-lease-length"))
370                                 return (DYNAMIC_BOOTP_LEASE_LENGTH);
371                         break;
372                 }
373                 break;
374         case 'e':
375                 if (!strcasecmp(atom + 1, "thernet"))
376                         return (ETHERNET);
377                 if (!strcasecmp(atom + 1, "nds"))
378                         return (ENDS);
379                 if (!strcasecmp(atom + 1, "xpire"))
380                         return (EXPIRE);
381                 break;
382         case 'f':
383                 if (!strcasecmp(atom + 1, "ilename"))
384                         return (FILENAME);
385                 if (!strcasecmp(atom + 1, "ixed-address"))
386                         return (FIXED_ADDR);
387                 if (!strcasecmp(atom + 1, "ddi"))
388                         return (FDDI);
389                 break;
390         case 'g':
391                 if (!strcasecmp(atom + 1, "iaddr"))
392                         return (GIADDR);
393                 if (!strcasecmp(atom + 1, "roup"))
394                         return (GROUP);
395                 if (!strcasecmp(atom + 1, "et-lease-hostnames"))
396                         return (GET_LEASE_HOSTNAMES);
397                 break;
398         case 'h':
399                 if (!strcasecmp(atom + 1, "ost"))
400                         return (HOST);
401                 if (!strcasecmp(atom + 1, "ardware"))
402                         return (HARDWARE);
403                 if (!strcasecmp(atom + 1, "ostname"))
404                         return (HOSTNAME);
405                 break;
406         case 'i':
407                 if (!strcasecmp(atom + 1, "nitial-interval"))
408                         return (INITIAL_INTERVAL);
409                 if (!strcasecmp(atom + 1, "nterface"))
410                         return (INTERFACE);
411                 break;
412         case 'l':
413                 if (!strcasecmp(atom + 1, "ease"))
414                         return (LEASE);
415                 break;
416         case 'm':
417                 if (!strcasecmp(atom + 1, "ax-lease-time"))
418                         return (MAX_LEASE_TIME);
419                 if (!strncasecmp(atom + 1, "edi", 3)) {
420                         if (!strcasecmp(atom + 4, "a"))
421                                 return (MEDIA);
422                         if (!strcasecmp(atom + 4, "um"))
423                                 return (MEDIUM);
424                         break;
425                 }
426                 break;
427         case 'n':
428                 if (!strcasecmp(atom + 1, "ameserver"))
429                         return (NAMESERVER);
430                 if (!strcasecmp(atom + 1, "etmask"))
431                         return (NETMASK);
432                 if (!strcasecmp(atom + 1, "ext-server"))
433                         return (NEXT_SERVER);
434                 if (!strcasecmp(atom + 1, "ot"))
435                         return (TOKEN_NOT);
436                 break;
437         case 'o':
438                 if (!strcasecmp(atom + 1, "ption"))
439                         return (OPTION);
440                 if (!strcasecmp(atom + 1, "ne-lease-per-client"))
441                         return (ONE_LEASE_PER_CLIENT);
442                 break;
443         case 'p':
444                 if (!strcasecmp(atom + 1, "repend"))
445                         return (PREPEND);
446                 if (!strcasecmp(atom + 1, "acket"))
447                         return (PACKET);
448                 break;
449         case 'r':
450                 if (!strcasecmp(atom + 1, "ange"))
451                         return (RANGE);
452                 if (!strcasecmp(atom + 1, "equest"))
453                         return (REQUEST);
454                 if (!strcasecmp(atom + 1, "equire"))
455                         return (REQUIRE);
456                 if (!strcasecmp(atom + 1, "etry"))
457                         return (RETRY);
458                 if (!strcasecmp(atom + 1, "enew"))
459                         return (RENEW);
460                 if (!strcasecmp(atom + 1, "ebind"))
461                         return (REBIND);
462                 if (!strcasecmp(atom + 1, "eboot"))
463                         return (REBOOT);
464                 if (!strcasecmp(atom + 1, "eject"))
465                         return (REJECT);
466                 break;
467         case 's':
468                 if (!strcasecmp(atom + 1, "earch"))
469                         return (SEARCH);
470                 if (!strcasecmp(atom + 1, "tarts"))
471                         return (STARTS);
472                 if (!strcasecmp(atom + 1, "iaddr"))
473                         return (SIADDR);
474                 if (!strcasecmp(atom + 1, "ubnet"))
475                         return (SUBNET);
476                 if (!strcasecmp(atom + 1, "hared-network"))
477                         return (SHARED_NETWORK);
478                 if (!strcasecmp(atom + 1, "erver-name"))
479                         return (SERVER_NAME);
480                 if (!strcasecmp(atom + 1, "erver-identifier"))
481                         return (SERVER_IDENTIFIER);
482                 if (!strcasecmp(atom + 1, "elect-timeout"))
483                         return (SELECT_TIMEOUT);
484                 if (!strcasecmp(atom + 1, "end"))
485                         return (SEND);
486                 if (!strcasecmp(atom + 1, "cript"))
487                         return (SCRIPT);
488                 if (!strcasecmp(atom + 1, "upersede"))
489                         return (SUPERSEDE);
490                 break;
491         case 't':
492                 if (!strcasecmp(atom + 1, "imestamp"))
493                         return (TIMESTAMP);
494                 if (!strcasecmp(atom + 1, "imeout"))
495                         return (TIMEOUT);
496                 if (!strcasecmp(atom + 1, "oken-ring"))
497                         return (TOKEN_RING);
498                 break;
499         case 'u':
500                 if (!strncasecmp(atom + 1, "se", 2)) {
501                         if (!strcasecmp(atom + 3, "r-class"))
502                                 return (USER_CLASS);
503                         if (!strcasecmp(atom + 3, "-host-decl-names"))
504                                 return (USE_HOST_DECL_NAMES);
505                         if (!strcasecmp(atom + 3,
506                                          "-lease-addr-for-default-route"))
507                                 return (USE_LEASE_ADDR_FOR_DEFAULT_ROUTE);
508                         break;
509                 }
510                 if (!strcasecmp(atom + 1, "id"))
511                         return (UID);
512                 if (!strcasecmp(atom + 1, "nknown-clients"))
513                         return (UNKNOWN_CLIENTS);
514                 break;
515         case 'v':
516                 if (!strcasecmp(atom + 1, "endor-class"))
517                         return (VENDOR_CLASS);
518                 break;
519         case 'y':
520                 if (!strcasecmp(atom + 1, "iaddr"))
521                         return (YIADDR);
522                 break;
523         }
524         return (dfv);
525 }