~ubuntu-branches/ubuntu/oneiric/isc-dhcp/oneiric-security

« back to all changes in this revision

Viewing changes to common/conflex.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Pollock
  • Date: 2009-09-02 22:34:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090902223425-nypo7bkftxffq41m
Tags: upstream-4.1.0
ImportĀ upstreamĀ versionĀ 4.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* conflex.c
 
2
 
 
3
   Lexical scanner for dhcpd config file... */
 
4
 
 
5
/*
 
6
 * Copyright (c) 2004-2008 by Internet Systems Consortium, Inc. ("ISC")
 
7
 * Copyright (c) 1995-2003 by Internet Software Consortium
 
8
 *
 
9
 * Permission to use, copy, modify, and distribute this software for any
 
10
 * purpose with or without fee is hereby granted, provided that the above
 
11
 * copyright notice and this permission notice appear in all copies.
 
12
 *
 
13
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 
14
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
15
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 
16
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
17
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
18
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 
19
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
20
 *
 
21
 *   Internet Systems Consortium, Inc.
 
22
 *   950 Charter Street
 
23
 *   Redwood City, CA 94063
 
24
 *   <info@isc.org>
 
25
 *   http://www.isc.org/
 
26
 *
 
27
 * This software has been written for Internet Systems Consortium
 
28
 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
 
29
 * To learn more about Internet Systems Consortium, see
 
30
 * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
 
31
 * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
 
32
 * ``http://www.nominum.com''.
 
33
 */
 
34
 
 
35
#include "dhcpd.h"
 
36
#include <ctype.h>
 
37
 
 
38
static int get_char PROTO ((struct parse *));
 
39
static void unget_char(struct parse *, int);
 
40
static void skip_to_eol PROTO ((struct parse *));
 
41
static enum dhcp_token read_whitespace(int c, struct parse *cfile);
 
42
static enum dhcp_token read_string PROTO ((struct parse *));
 
43
static enum dhcp_token read_number PROTO ((int, struct parse *));
 
44
static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
 
45
static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
 
46
 
 
47
isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
 
48
        struct parse **cfile;
 
49
        int file;
 
50
        char *inbuf;
 
51
        unsigned buflen;
 
52
        const char *name;
 
53
        int eolp;
 
54
{
 
55
        isc_result_t status = ISC_R_SUCCESS;
 
56
        struct parse *tmp;
 
57
 
 
58
        tmp = dmalloc(sizeof(struct parse), MDL);
 
59
        if (tmp == NULL) {
 
60
                return (ISC_R_NOMEMORY);
 
61
        }
 
62
 
 
63
        /*
 
64
         * We don't need to initialize things to zero here, since 
 
65
         * dmalloc() returns memory that is set to zero.
 
66
         */
 
67
        tmp->tlname = name;
 
68
        tmp->lpos = tmp -> line = 1;
 
69
        tmp->cur_line = tmp->line1;
 
70
        tmp->prev_line = tmp->line2;
 
71
        tmp->token_line = tmp->cur_line;
 
72
        tmp->cur_line[0] = tmp->prev_line[0] = 0;
 
73
        tmp->file = file;
 
74
        tmp->eol_token = eolp;
 
75
 
 
76
        if (inbuf != NULL) {
 
77
                tmp->inbuf = inbuf;
 
78
                tmp->buflen = buflen;
 
79
                tmp->bufsiz = 0;
 
80
        } else {
 
81
                struct stat sb;
 
82
 
 
83
                if (fstat(file, &sb) < 0) {
 
84
                        status = ISC_R_IOERROR;
 
85
                        goto cleanup;
 
86
                }
 
87
 
 
88
                if (sb.st_size == 0)
 
89
                        goto cleanup;
 
90
 
 
91
                tmp->bufsiz = tmp->buflen = (size_t) sb.st_size;
 
92
                tmp->inbuf = mmap(NULL, tmp->bufsiz, PROT_READ, MAP_SHARED,
 
93
                                  file, 0);
 
94
 
 
95
                if (tmp->inbuf == MAP_FAILED) {
 
96
                        status = ISC_R_IOERROR;
 
97
                        goto cleanup;
 
98
                }
 
99
        }
 
100
 
 
101
        *cfile = tmp;
 
102
        return (ISC_R_SUCCESS);
 
103
 
 
104
cleanup:
 
105
        dfree(tmp, MDL);
 
106
        return (status);
 
107
}
 
108
 
 
109
isc_result_t end_parse (cfile)
 
110
        struct parse **cfile;
 
111
{
 
112
        /* "Memory" config files have no file. */
 
113
        if ((*cfile)->file != -1) {
 
114
                munmap((*cfile)->inbuf, (*cfile)->bufsiz);
 
115
                close((*cfile)->file);
 
116
        }
 
117
 
 
118
        if ((*cfile)->saved_state != NULL) {
 
119
                dfree((*cfile)->saved_state, MDL);
 
120
        }
 
121
                
 
122
        dfree(*cfile, MDL);
 
123
        *cfile = NULL;
 
124
        return ISC_R_SUCCESS;
 
125
}
 
126
 
 
127
/*
 
128
 * Save the current state of the parser.
 
129
 *
 
130
 * Only one state may be saved. Any previous saved state is
 
131
 * lost.
 
132
 */
 
133
isc_result_t
 
134
save_parse_state(struct parse *cfile) {
 
135
        /*
 
136
         * Free any previous saved state.
 
137
         */
 
138
        if (cfile->saved_state != NULL) {
 
139
                dfree(cfile->saved_state, MDL);
 
140
        }
 
141
 
 
142
        /*
 
143
         * Save our current state.
 
144
         */
 
145
        cfile->saved_state = dmalloc(sizeof(struct parse), MDL);
 
146
        if (cfile->saved_state == NULL) {
 
147
                return ISC_R_NOMEMORY;
 
148
        }
 
149
        memcpy(cfile->saved_state, cfile, sizeof(*cfile));
 
150
        return ISC_R_SUCCESS;
 
151
}
 
152
 
 
153
/*
 
154
 * Return the parser to the previous saved state.
 
155
 *
 
156
 * You must call save_parse_state() before calling 
 
157
 * restore_parse_state(), but you can call restore_parse_state() any
 
158
 * number of times after that.
 
159
 */
 
160
isc_result_t
 
161
restore_parse_state(struct parse *cfile) {
 
162
        struct parse *saved_state;
 
163
 
 
164
        if (cfile->saved_state == NULL) {
 
165
                return ISC_R_NOTYET;
 
166
        }
 
167
 
 
168
        saved_state = cfile->saved_state;
 
169
        memcpy(cfile, saved_state, sizeof(*cfile));
 
170
        cfile->saved_state = saved_state;
 
171
        return ISC_R_SUCCESS;
 
172
}
 
173
 
 
174
static int get_char (cfile)
 
175
        struct parse *cfile;
 
176
{
 
177
        /* My kingdom for WITH... */
 
178
        int c;
 
179
 
 
180
        if (cfile->bufix == cfile->buflen)
 
181
                c = EOF;
 
182
        else {
 
183
                c = cfile->inbuf [cfile->bufix];
 
184
                cfile->bufix++;
 
185
        }
 
186
 
 
187
        if (!cfile->ugflag) {
 
188
                if (c == EOL) {
 
189
                        if (cfile->cur_line == cfile->line1) {  
 
190
                                cfile->cur_line = cfile->line2;
 
191
                                cfile->prev_line = cfile->line1;
 
192
                        } else {
 
193
                                cfile->cur_line = cfile->line1;
 
194
                                cfile->prev_line = cfile->line2;
 
195
                        }
 
196
                        cfile->line++;
 
197
                        cfile->lpos = 1;
 
198
                        cfile->cur_line [0] = 0;
 
199
                } else if (c != EOF) {
 
200
                        if (cfile->lpos <= 80) {
 
201
                                cfile->cur_line [cfile->lpos - 1] = c;
 
202
                                cfile->cur_line [cfile->lpos] = 0;
 
203
                        }
 
204
                        cfile->lpos++;
 
205
                }
 
206
        } else
 
207
                cfile->ugflag = 0;
 
208
        return c;               
 
209
}
 
210
 
 
211
/*
 
212
 * Return a character to our input buffer.
 
213
 */
 
214
static void
 
215
unget_char(struct parse *cfile, int c) {
 
216
        if (c != EOF) {
 
217
                cfile->bufix--;
 
218
                cfile->ugflag = 1;      /* do not put characters into
 
219
                                           our error buffer on the next
 
220
                                           call to get_char() */
 
221
        }
 
222
}
 
223
 
 
224
/*
 
225
 * GENERAL NOTE ABOUT TOKENS
 
226
 *
 
227
 * We normally only want non-whitespace tokens. There are some 
 
228
 * circumstances where we *do* want to see whitespace (for example
 
229
 * when parsing IPv6 addresses).
 
230
 *
 
231
 * Generally we use the next_token() function to read tokens. This 
 
232
 * in turn calls get_next_token, which does *not* return tokens for
 
233
 * whitespace. Rather, it skips these.
 
234
 *
 
235
 * When we need to see whitespace, we us next_raw_token(), which also
 
236
 * returns the WHITESPACE token.
 
237
 *
 
238
 * The peek_token() and peek_raw_token() functions work as expected.
 
239
 *
 
240
 * Warning: if you invoke peek_token(), then if there is a whitespace
 
241
 * token, it will be lost, and subsequent use of next_raw_token() or
 
242
 * peek_raw_token() will NOT see it.
 
243
 */
 
244
 
 
245
static enum dhcp_token
 
246
get_raw_token(struct parse *cfile) {
 
247
        int c;
 
248
        enum dhcp_token ttok;
 
249
        static char tb [2];
 
250
        int l, p;
 
251
 
 
252
        do {
 
253
                l = cfile -> line;
 
254
                p = cfile -> lpos;
 
255
 
 
256
                c = get_char (cfile);
 
257
                if (!((c == '\n') && cfile->eol_token) && 
 
258
                    isascii(c) && isspace(c)) {
 
259
                        ttok = read_whitespace(c, cfile);
 
260
                        break;
 
261
                }
 
262
                if (c == '#') {
 
263
                        skip_to_eol (cfile);
 
264
                        continue;
 
265
                }
 
266
                if (c == '"') {
 
267
                        cfile -> lexline = l;
 
268
                        cfile -> lexchar = p;
 
269
                        ttok = read_string (cfile);
 
270
                        break;
 
271
                }
 
272
                if ((isascii (c) && isdigit (c)) || c == '-') {
 
273
                        cfile -> lexline = l;
 
274
                        cfile -> lexchar = p;
 
275
                        ttok = read_number (c, cfile);
 
276
                        break;
 
277
                } else if (isascii (c) && isalpha (c)) {
 
278
                        cfile -> lexline = l;
 
279
                        cfile -> lexchar = p;
 
280
                        ttok = read_num_or_name (c, cfile);
 
281
                        break;
 
282
                } else if (c == EOF) {
 
283
                        ttok = END_OF_FILE;
 
284
                        cfile -> tlen = 0;
 
285
                        break;
 
286
                } else {
 
287
                        cfile -> lexline = l;
 
288
                        cfile -> lexchar = p;
 
289
                        tb [0] = c;
 
290
                        tb [1] = 0;
 
291
                        cfile -> tval = tb;
 
292
                        cfile -> tlen = 1;
 
293
                        ttok = c;
 
294
                        break;
 
295
                }
 
296
        } while (1);
 
297
        return ttok;
 
298
}
 
299
 
 
300
/*
 
301
 * The get_next_token() function consumes the next token and
 
302
 * returns it to the caller.
 
303
 *
 
304
 * Since the code is almost the same for "normal" and "raw" 
 
305
 * input, we pass a flag to alter the way it works.
 
306
 */
 
307
 
 
308
static enum dhcp_token 
 
309
get_next_token(const char **rval, unsigned *rlen, 
 
310
               struct parse *cfile, isc_boolean_t raw) {
 
311
        int rv;
 
312
 
 
313
        if (cfile -> token) {
 
314
                if (cfile -> lexline != cfile -> tline)
 
315
                        cfile -> token_line = cfile -> cur_line;
 
316
                cfile -> lexchar = cfile -> tlpos;
 
317
                cfile -> lexline = cfile -> tline;
 
318
                rv = cfile -> token;
 
319
                cfile -> token = 0;
 
320
        } else {
 
321
                rv = get_raw_token(cfile);
 
322
                cfile -> token_line = cfile -> cur_line;
 
323
        }
 
324
 
 
325
        if (!raw) {
 
326
                while (rv == WHITESPACE) {
 
327
                        rv = get_raw_token(cfile);
 
328
                        cfile->token_line = cfile->cur_line;
 
329
                }
 
330
        }
 
331
        
 
332
        if (rval)
 
333
                *rval = cfile -> tval;
 
334
        if (rlen)
 
335
                *rlen = cfile -> tlen;
 
336
#ifdef DEBUG_TOKENS
 
337
        fprintf (stderr, "%s:%d ", cfile -> tval, rv);
 
338
#endif
 
339
        return rv;
 
340
}
 
341
 
 
342
 
 
343
/*
 
344
 * Get the next token from cfile and return it.
 
345
 *
 
346
 * If rval is non-NULL, set the pointer it contains to 
 
347
 * the contents of the token.
 
348
 *
 
349
 * If rlen is non-NULL, set the integer it contains to 
 
350
 * the length of the token.
 
351
 */
 
352
 
 
353
enum dhcp_token
 
354
next_token(const char **rval, unsigned *rlen, struct parse *cfile) {
 
355
        return get_next_token(rval, rlen, cfile, ISC_FALSE);
 
356
}
 
357
 
 
358
 
 
359
/*
 
360
 * The same as the next_token() function above, but will return space
 
361
 * as the WHITESPACE token.
 
362
 */
 
363
 
 
364
enum dhcp_token
 
365
next_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
 
366
        return get_next_token(rval, rlen, cfile, ISC_TRUE);
 
367
}
 
368
 
 
369
 
 
370
/*
 
371
 * The do_peek_token() function checks the next token without
 
372
 * consuming it, and returns it to the caller.
 
373
 *
 
374
 * Since the code is almost the same for "normal" and "raw" 
 
375
 * input, we pass a flag to alter the way it works. (See the 
 
376
 * warning in the GENERAL NOTES ABOUT TOKENS above though.)
 
377
 */
 
378
 
 
379
enum dhcp_token
 
380
do_peek_token(const char **rval, unsigned int *rlen,
 
381
              struct parse *cfile, isc_boolean_t raw) {
 
382
        int x;
 
383
 
 
384
        if (!cfile->token || (!raw && (cfile->token == WHITESPACE))) {
 
385
                cfile -> tlpos = cfile -> lexchar;
 
386
                cfile -> tline = cfile -> lexline;
 
387
 
 
388
                do {
 
389
                        cfile->token = get_raw_token(cfile);
 
390
                } while (!raw && (cfile->token == WHITESPACE));
 
391
 
 
392
                if (cfile -> lexline != cfile -> tline)
 
393
                        cfile -> token_line = cfile -> prev_line;
 
394
 
 
395
                x = cfile -> lexchar;
 
396
                cfile -> lexchar = cfile -> tlpos;
 
397
                cfile -> tlpos = x;
 
398
 
 
399
                x = cfile -> lexline;
 
400
                cfile -> lexline = cfile -> tline;
 
401
                cfile -> tline = x;
 
402
        }
 
403
        if (rval)
 
404
                *rval = cfile -> tval;
 
405
        if (rlen)
 
406
                *rlen = cfile -> tlen;
 
407
#ifdef DEBUG_TOKENS
 
408
        fprintf (stderr, "(%s:%d) ", cfile -> tval, cfile -> token);
 
409
#endif
 
410
        return cfile -> token;
 
411
}
 
412
 
 
413
 
 
414
/*
 
415
 * Get the next token from cfile and return it, leaving it for a 
 
416
 * subsequent call to next_token().
 
417
 *
 
418
 * Note that it WILL consume whitespace tokens.
 
419
 *
 
420
 * If rval is non-NULL, set the pointer it contains to 
 
421
 * the contents of the token.
 
422
 *
 
423
 * If rlen is non-NULL, set the integer it contains to 
 
424
 * the length of the token.
 
425
 */
 
426
 
 
427
enum dhcp_token
 
428
peek_token(const char **rval, unsigned *rlen, struct parse *cfile) {
 
429
        return do_peek_token(rval, rlen, cfile, ISC_FALSE);
 
430
}
 
431
 
 
432
 
 
433
/*
 
434
 * The same as the peek_token() function above, but will return space
 
435
 * as the WHITESPACE token.
 
436
 */
 
437
 
 
438
enum dhcp_token
 
439
peek_raw_token(const char **rval, unsigned *rlen, struct parse *cfile) {
 
440
        return do_peek_token(rval, rlen, cfile, ISC_TRUE);
 
441
}
 
442
 
 
443
static void skip_to_eol (cfile)
 
444
        struct parse *cfile;
 
445
{
 
446
        int c;
 
447
        do {
 
448
                c = get_char (cfile);
 
449
                if (c == EOF)
 
450
                        return;
 
451
                if (c == EOL) {
 
452
                        return;
 
453
                }
 
454
        } while (1);
 
455
}
 
456
 
 
457
static enum dhcp_token
 
458
read_whitespace(int c, struct parse *cfile) {
 
459
        int ofs;
 
460
 
 
461
        /*
 
462
         * Read as much whitespace as we have available.
 
463
         */
 
464
        ofs = 0;
 
465
        do {
 
466
                cfile->tokbuf[ofs++] = c;
 
467
                c = get_char(cfile);
 
468
        } while (!((c == '\n') && cfile->eol_token) && 
 
469
                 isascii(c) && isspace(c));
 
470
 
 
471
        /*
 
472
         * Put the last (non-whitespace) character back.
 
473
         */
 
474
        unget_char(cfile, c);
 
475
 
 
476
        /*
 
477
         * Return our token.
 
478
         */
 
479
        cfile->tokbuf[ofs] = '\0';
 
480
        cfile->tlen = ofs;
 
481
        cfile->tval = cfile->tokbuf;
 
482
        return WHITESPACE;
 
483
}
 
484
 
 
485
static enum dhcp_token read_string (cfile)
 
486
        struct parse *cfile;
 
487
{
 
488
        int i;
 
489
        int bs = 0;
 
490
        int c;
 
491
        int value = 0;
 
492
        int hex = 0;
 
493
 
 
494
        for (i = 0; i < sizeof cfile -> tokbuf; i++) {
 
495
              again:
 
496
                c = get_char (cfile);
 
497
                if (c == EOF) {
 
498
                        parse_warn (cfile, "eof in string constant");
 
499
                        break;
 
500
                }
 
501
                if (bs == 1) {
 
502
                        switch (c) {
 
503
                              case 't':
 
504
                                cfile -> tokbuf [i] = '\t';
 
505
                                break;
 
506
                              case 'r':
 
507
                                cfile -> tokbuf [i] = '\r';
 
508
                                break;
 
509
                              case 'n':
 
510
                                cfile -> tokbuf [i] = '\n';
 
511
                                break;
 
512
                              case 'b':
 
513
                                cfile -> tokbuf [i] = '\b';
 
514
                                break;
 
515
                              case '0':
 
516
                              case '1':
 
517
                              case '2':
 
518
                              case '3':
 
519
                                hex = 0;
 
520
                                value = c - '0';
 
521
                                ++bs;
 
522
                                goto again;
 
523
                              case 'x':
 
524
                                hex = 1;
 
525
                                value = 0;
 
526
                                ++bs;
 
527
                                goto again;
 
528
                              default:
 
529
                                cfile -> tokbuf [i] = c;
 
530
                                bs = 0;
 
531
                                break;
 
532
                        }
 
533
                        bs = 0;
 
534
                } else if (bs > 1) {
 
535
                        if (hex) {
 
536
                                if (c >= '0' && c <= '9') {
 
537
                                        value = value * 16 + (c - '0');
 
538
                                } else if (c >= 'a' && c <= 'f') {
 
539
                                        value = value * 16 + (c - 'a' + 10);
 
540
                                } else if (c >= 'A' && c <= 'F') {
 
541
                                        value = value * 16 + (c - 'A' + 10);
 
542
                                } else {
 
543
                                        parse_warn (cfile,
 
544
                                                    "invalid hex digit: %x",
 
545
                                                    c);
 
546
                                        bs = 0;
 
547
                                        continue;
 
548
                                }
 
549
                                if (++bs == 4) {
 
550
                                        cfile -> tokbuf [i] = value;
 
551
                                        bs = 0;
 
552
                                } else
 
553
                                        goto again;
 
554
                        } else {
 
555
                                if (c >= '0' && c <= '7') {
 
556
                                        value = value * 8 + (c - '0');
 
557
                                } else {
 
558
                                    if (value != 0) {
 
559
                                        parse_warn (cfile,
 
560
                                                    "invalid octal digit %x",
 
561
                                                    c);
 
562
                                        continue;
 
563
                                    } else
 
564
                                        cfile -> tokbuf [i] = 0;
 
565
                                    bs = 0;
 
566
                                }
 
567
                                if (++bs == 4) {
 
568
                                        cfile -> tokbuf [i] = value;
 
569
                                        bs = 0;
 
570
                                } else
 
571
                                        goto again;
 
572
                        }
 
573
                } else if (c == '\\') {
 
574
                        bs = 1;
 
575
                        goto again;
 
576
                } else if (c == '"')
 
577
                        break;
 
578
                else
 
579
                        cfile -> tokbuf [i] = c;
 
580
        }
 
581
        /* Normally, I'd feel guilty about this, but we're talking about
 
582
           strings that'll fit in a DHCP packet here... */
 
583
        if (i == sizeof cfile -> tokbuf) {
 
584
                parse_warn (cfile,
 
585
                            "string constant larger than internal buffer");
 
586
                --i;
 
587
        }
 
588
        cfile -> tokbuf [i] = 0;
 
589
        cfile -> tlen = i;
 
590
        cfile -> tval = cfile -> tokbuf;
 
591
        return STRING;
 
592
}
 
593
 
 
594
static enum dhcp_token read_number (c, cfile)
 
595
        int c;
 
596
        struct parse *cfile;
 
597
{
 
598
        int i = 0;
 
599
        int token = NUMBER;
 
600
 
 
601
        cfile -> tokbuf [i++] = c;
 
602
        for (; i < sizeof cfile -> tokbuf; i++) {
 
603
                c = get_char (cfile);
 
604
 
 
605
                /* Promote NUMBER -> NUMBER_OR_NAME -> NAME, never demote.
 
606
                 * Except in the case of '0x' syntax hex, which gets called
 
607
                 * a NAME at '0x', and returned to NUMBER_OR_NAME once it's
 
608
                 * verified to be at least 0xf or less.
 
609
                 */
 
610
                switch(isascii(c) ? token : BREAK) {
 
611
                    case NUMBER:
 
612
                        if(isdigit(c))
 
613
                                break;
 
614
                        /* FALLTHROUGH */
 
615
                    case NUMBER_OR_NAME:
 
616
                        if(isxdigit(c)) {
 
617
                                token = NUMBER_OR_NAME;
 
618
                                break;
 
619
                        }
 
620
                        /* FALLTHROUGH */
 
621
                    case NAME:
 
622
                        if((i == 2) && isxdigit(c) &&
 
623
                                (cfile->tokbuf[0] == '0') &&
 
624
                                ((cfile->tokbuf[1] == 'x') ||
 
625
                                 (cfile->tokbuf[1] == 'X'))) {
 
626
                                token = NUMBER_OR_NAME;
 
627
                                break;
 
628
                        } else if(((c == '-') || (c == '_') || isalnum(c))) {
 
629
                                token = NAME;
 
630
                                break;
 
631
                        }
 
632
                        /* FALLTHROUGH */
 
633
                    case BREAK:
 
634
                        /* At this point c is either EOF or part of the next
 
635
                         * token.  If not EOF, rewind the file one byte so
 
636
                         * the next token is read from there.
 
637
                         */
 
638
                        unget_char(cfile, c);
 
639
                        goto end_read;
 
640
 
 
641
                    default:
 
642
                        log_fatal("read_number():%s:%d: impossible case", MDL);
 
643
                }
 
644
 
 
645
                cfile -> tokbuf [i] = c;
 
646
        }
 
647
 
 
648
        if (i == sizeof cfile -> tokbuf) {
 
649
                parse_warn (cfile,
 
650
                            "numeric token larger than internal buffer");
 
651
                --i;
 
652
        }
 
653
 
 
654
  end_read:
 
655
        cfile -> tokbuf [i] = 0;
 
656
        cfile -> tlen = i;
 
657
        cfile -> tval = cfile -> tokbuf;
 
658
 
 
659
        /*
 
660
         * If this entire token from start to finish was "-", such as
 
661
         * the middle parameter in "42 - 7", return just the MINUS token.
 
662
         */
 
663
        if ((i == 1) && (cfile->tokbuf[i] == '-'))
 
664
                return MINUS;
 
665
        else
 
666
                return token;
 
667
}
 
668
 
 
669
static enum dhcp_token read_num_or_name (c, cfile)
 
670
        int c;
 
671
        struct parse *cfile;
 
672
{
 
673
        int i = 0;
 
674
        enum dhcp_token rv = NUMBER_OR_NAME;
 
675
        cfile -> tokbuf [i++] = c;
 
676
        for (; i < sizeof cfile -> tokbuf; i++) {
 
677
                c = get_char (cfile);
 
678
                if (!isascii (c) ||
 
679
                    (c != '-' && c != '_' && !isalnum (c))) {
 
680
                        unget_char(cfile, c);
 
681
                        break;
 
682
                }
 
683
                if (!isxdigit (c))
 
684
                        rv = NAME;
 
685
                cfile -> tokbuf [i] = c;
 
686
        }
 
687
        if (i == sizeof cfile -> tokbuf) {
 
688
                parse_warn (cfile, "token larger than internal buffer");
 
689
                --i;
 
690
        }
 
691
        cfile -> tokbuf [i] = 0;
 
692
        cfile -> tlen = i;
 
693
        cfile -> tval = cfile -> tokbuf;
 
694
        return intern(cfile->tval, rv);
 
695
}
 
696
 
 
697
static enum dhcp_token
 
698
intern(char *atom, enum dhcp_token dfv) {
 
699
        if (!isascii(atom[0]))
 
700
                return dfv;
 
701
 
 
702
        switch (tolower((unsigned char)atom[0])) {
 
703
              case '-':
 
704
                if (atom [1] == 0)
 
705
                        return MINUS;
 
706
                break;
 
707
 
 
708
              case 'a':
 
709
                if (!strncasecmp (atom + 1, "uth", 3)) {
 
710
                        if (!strncasecmp (atom + 3, "uthenticat", 10)) {
 
711
                                if (!strcasecmp (atom + 13, "ed"))
 
712
                                        return AUTHENTICATED;
 
713
                                if (!strcasecmp (atom + 13, "ion"))
 
714
                                        return AUTHENTICATION;
 
715
                                break;
 
716
                        }
 
717
                        if (!strcasecmp (atom + 1, "uthoritative"))
 
718
                                return AUTHORITATIVE;
 
719
                        break;
 
720
                }
 
721
                if (!strcasecmp (atom + 1, "nd"))
 
722
                        return AND;
 
723
                if (!strcasecmp (atom + 1, "ppend"))
 
724
                        return APPEND;
 
725
                if (!strcasecmp (atom + 1, "llow"))
 
726
                        return ALLOW;
 
727
                if (!strcasecmp (atom + 1, "lias"))
 
728
                        return ALIAS;
 
729
                if (!strcasecmp (atom + 1, "lgorithm"))
 
730
                        return ALGORITHM;
 
731
                if (!strcasecmp (atom + 1, "lso"))
 
732
                        return TOKEN_ALSO;
 
733
                if (!strcasecmp (atom + 1, "bandoned"))
 
734
                        return TOKEN_ABANDONED;
 
735
                if (!strcasecmp (atom + 1, "dd"))
 
736
                        return TOKEN_ADD;
 
737
                if (!strcasecmp (atom + 1, "ll"))
 
738
                        return ALL;
 
739
                if (!strcasecmp (atom + 1, "t"))
 
740
                        return AT;
 
741
                if (!strcasecmp (atom + 1, "rray"))
 
742
                        return ARRAY;
 
743
                if (!strcasecmp (atom + 1, "ddress"))
 
744
                        return ADDRESS;
 
745
                if (!strcasecmp (atom + 1, "ctive"))
 
746
                        return TOKEN_ACTIVE;
 
747
                if (!strcasecmp (atom + 1, "tsfp"))
 
748
                        return ATSFP;
 
749
                if (!strcasecmp (atom + 1, "fter"))
 
750
                        return AFTER;
 
751
                break;
 
752
              case 'b':
 
753
                if (!strcasecmp (atom + 1, "ackup"))
 
754
                        return TOKEN_BACKUP;
 
755
                if (!strcasecmp (atom + 1, "ootp"))
 
756
                        return TOKEN_BOOTP;
 
757
                if (!strcasecmp (atom + 1, "inding"))
 
758
                        return BINDING;
 
759
                if (!strcasecmp (atom + 1, "inary-to-ascii"))
 
760
                        return BINARY_TO_ASCII;
 
761
                if (!strcasecmp (atom + 1, "ackoff-cutoff"))
 
762
                        return BACKOFF_CUTOFF;
 
763
                if (!strcasecmp (atom + 1, "ooting"))
 
764
                        return BOOTING;
 
765
                if (!strcasecmp (atom + 1, "oot-unknown-clients"))
 
766
                        return BOOT_UNKNOWN_CLIENTS;
 
767
                if (!strcasecmp (atom + 1, "reak"))
 
768
                        return BREAK;
 
769
                if (!strcasecmp (atom + 1, "illing"))
 
770
                        return BILLING;
 
771
                if (!strcasecmp (atom + 1, "oolean"))
 
772
                        return BOOLEAN;
 
773
                if (!strcasecmp (atom + 1, "alance"))
 
774
                        return BALANCE;
 
775
                if (!strcasecmp (atom + 1, "ound"))
 
776
                        return BOUND;
 
777
                break;
 
778
              case 'c':
 
779
                if (!strcasecmp (atom + 1, "ase"))
 
780
                        return CASE;
 
781
                if (!strcasecmp (atom + 1, "ommit"))
 
782
                        return COMMIT;
 
783
                if (!strcasecmp (atom + 1, "ode"))
 
784
                        return CODE;
 
785
                if (!strcasecmp (atom + 1, "onfig-option"))
 
786
                        return CONFIG_OPTION;
 
787
                if (!strcasecmp (atom + 1, "heck"))
 
788
                        return CHECK;
 
789
                if (!strcasecmp (atom + 1, "lass"))
 
790
                        return CLASS;
 
791
                if (!strcasecmp (atom + 1, "lose"))
 
792
                        return TOKEN_CLOSE;
 
793
                if (!strcasecmp(atom + 1, "ompressed"))
 
794
                        return COMPRESSED;
 
795
                if (!strcasecmp (atom + 1, "reate"))
 
796
                        return TOKEN_CREATE;
 
797
                if (!strcasecmp (atom + 1, "iaddr"))
 
798
                        return CIADDR;
 
799
                if (!strncasecmp (atom + 1, "lient", 5)) {
 
800
                        if (!strcasecmp (atom + 6, "-identifier"))
 
801
                                return CLIENT_IDENTIFIER;
 
802
                        if (!strcasecmp (atom + 6, "-hostname"))
 
803
                                return CLIENT_HOSTNAME;
 
804
                        if (!strcasecmp (atom + 6, "-state"))
 
805
                                return CLIENT_STATE;
 
806
                        if (!strcasecmp (atom + 6, "-updates"))
 
807
                                return CLIENT_UPDATES;
 
808
                        if (!strcasecmp (atom + 6, "s"))
 
809
                                return CLIENTS;
 
810
                }
 
811
                if (!strcasecmp (atom + 1, "oncat"))
 
812
                        return CONCAT;
 
813
                if (!strcasecmp (atom + 1, "onnect"))
 
814
                        return CONNECT;
 
815
                if (!strcasecmp (atom + 1, "ommunications-interrupted"))
 
816
                        return COMMUNICATIONS_INTERRUPTED;
 
817
                if (!strcasecmp (atom + 1, "ltt"))
 
818
                        return CLTT;
 
819
                break;
 
820
              case 'd':
 
821
                if (!strcasecmp(atom + 1, "b-time-format"))
 
822
                        return DB_TIME_FORMAT;
 
823
                if (!strcasecmp (atom + 1, "ns-update"))
 
824
                        return DNS_UPDATE;
 
825
                if (!strcasecmp (atom + 1, "ns-delete"))
 
826
                        return DNS_DELETE;
 
827
                if (!strcasecmp (atom + 1, "omain"))
 
828
                        return DOMAIN;
 
829
                if (!strncasecmp (atom + 1, "omain-", 6)) {
 
830
                        if (!strcasecmp(atom + 7, "name"))
 
831
                                return DOMAIN_NAME;
 
832
                        if (!strcasecmp(atom + 7, "list"))
 
833
                                return DOMAIN_LIST;
 
834
                }
 
835
                if (!strcasecmp (atom + 1, "o-forward-update"))
 
836
                        return DO_FORWARD_UPDATE;
 
837
                if (!strcasecmp (atom + 1, "ebug"))
 
838
                        return TOKEN_DEBUG;
 
839
                if (!strcasecmp (atom + 1, "eny"))
 
840
                        return DENY;
 
841
                if (!strcasecmp (atom + 1, "eleted"))
 
842
                        return TOKEN_DELETED;
 
843
                if (!strcasecmp (atom + 1, "elete"))
 
844
                        return TOKEN_DELETE;
 
845
                if (!strncasecmp (atom + 1, "efault", 6)) {
 
846
                        if (!atom [7])
 
847
                                return DEFAULT;
 
848
                        if (!strcasecmp(atom + 7, "-duid"))
 
849
                                return DEFAULT_DUID;
 
850
                        if (!strcasecmp (atom + 7, "-lease-time"))
 
851
                                return DEFAULT_LEASE_TIME;
 
852
                        break;
 
853
                }
 
854
                if (!strncasecmp (atom + 1, "ynamic", 6)) {
 
855
                        if (!atom [7])
 
856
                                return DYNAMIC;
 
857
                        if (!strncasecmp (atom + 7, "-bootp", 6)) {
 
858
                                if (!atom [13])
 
859
                                        return DYNAMIC_BOOTP;
 
860
                                if (!strcasecmp (atom + 13, "-lease-cutoff"))
 
861
                                        return DYNAMIC_BOOTP_LEASE_CUTOFF;
 
862
                                if (!strcasecmp (atom + 13, "-lease-length"))
 
863
                                        return DYNAMIC_BOOTP_LEASE_LENGTH;
 
864
                                break;
 
865
                        }
 
866
                }
 
867
                if (!strcasecmp (atom + 1, "uplicates"))
 
868
                        return DUPLICATES;
 
869
                if (!strcasecmp (atom + 1, "eclines"))
 
870
                        return DECLINES;
 
871
                if (!strncasecmp (atom + 1, "efine", 5)) {
 
872
                        if (!strcasecmp (atom + 6, "d"))
 
873
                                return DEFINED;
 
874
                        if (!atom [6])
 
875
                                return DEFINE;
 
876
                }
 
877
                break;
 
878
              case 'e':
 
879
                if (isascii (atom [1]) && 
 
880
                    tolower((unsigned char)atom[1]) == 'x') {
 
881
                        if (!strcasecmp (atom + 2, "tract-int"))
 
882
                                return EXTRACT_INT;
 
883
                        if (!strcasecmp (atom + 2, "ists"))
 
884
                                return EXISTS;
 
885
                        if (!strcasecmp (atom + 2, "piry"))
 
886
                                return EXPIRY;
 
887
                        if (!strcasecmp (atom + 2, "pire"))
 
888
                                return EXPIRE;
 
889
                        if (!strcasecmp (atom + 2, "pired"))
 
890
                                return TOKEN_EXPIRED;
 
891
                }
 
892
                if (!strcasecmp (atom + 1, "ncode-int"))
 
893
                        return ENCODE_INT;
 
894
                if (!strcasecmp(atom + 1, "poch"))
 
895
                        return EPOCH;
 
896
                if (!strcasecmp (atom + 1, "thernet"))
 
897
                        return ETHERNET;
 
898
                if (!strcasecmp (atom + 1, "nds"))
 
899
                        return ENDS;
 
900
                if (!strncasecmp (atom + 1, "ls", 2)) {
 
901
                        if (!strcasecmp (atom + 3, "e"))
 
902
                                return ELSE;
 
903
                        if (!strcasecmp (atom + 3, "if"))
 
904
                                return ELSIF;
 
905
                        break;
 
906
                }
 
907
                if (!strcasecmp (atom + 1, "rror"))
 
908
                        return ERROR;
 
909
                if (!strcasecmp (atom + 1, "val"))
 
910
                        return EVAL;
 
911
                if (!strcasecmp (atom + 1, "ncapsulate"))
 
912
                        return ENCAPSULATE;
 
913
                if (!strcasecmp(atom + 1, "xecute"))
 
914
                        return EXECUTE;
 
915
                if (!strcasecmp(atom+1, "n")) {
 
916
                        return EN;
 
917
                }
 
918
                break;
 
919
              case 'f':
 
920
                if (!strcasecmp (atom + 1, "atal"))
 
921
                        return FATAL;
 
922
                if (!strcasecmp (atom + 1, "ilename"))
 
923
                        return FILENAME;
 
924
                if (!strcasecmp (atom + 1, "ixed-address"))
 
925
                        return FIXED_ADDR;
 
926
                if (!strcasecmp (atom + 1, "ixed-address6"))
 
927
                        return FIXED_ADDR6;
 
928
                if (!strcasecmp (atom + 1, "ixed-prefix6"))
 
929
                        return FIXED_PREFIX6;
 
930
                if (!strcasecmp (atom + 1, "ddi"))
 
931
                        return TOKEN_FDDI;
 
932
                if (!strcasecmp (atom + 1, "ormerr"))
 
933
                        return NS_FORMERR;
 
934
                if (!strcasecmp (atom + 1, "unction"))
 
935
                        return FUNCTION;
 
936
                if (!strcasecmp (atom + 1, "ailover"))
 
937
                        return FAILOVER;
 
938
                if (!strcasecmp (atom + 1, "ree"))
 
939
                        return TOKEN_FREE;
 
940
                break;
 
941
              case 'g':
 
942
                if (!strcasecmp (atom + 1, "iaddr"))
 
943
                        return GIADDR;
 
944
                if (!strcasecmp (atom + 1, "roup"))
 
945
                        return GROUP;
 
946
                if (!strcasecmp (atom + 1, "et-lease-hostnames"))
 
947
                        return GET_LEASE_HOSTNAMES;
 
948
                break;
 
949
              case 'h':
 
950
                if (!strcasecmp(atom + 1, "ash"))
 
951
                        return HASH;
 
952
                if (!strcasecmp (atom + 1, "ba"))
 
953
                        return HBA;
 
954
                if (!strcasecmp (atom + 1, "ost"))
 
955
                        return HOST;
 
956
                if (!strcasecmp (atom + 1, "ost-decl-name"))
 
957
                        return HOST_DECL_NAME;
 
958
                if (!strcasecmp(atom + 1, "ost-identifier"))
 
959
                        return HOST_IDENTIFIER;
 
960
                if (!strcasecmp (atom + 1, "ardware"))
 
961
                        return HARDWARE;
 
962
                if (!strcasecmp (atom + 1, "ostname"))
 
963
                        return HOSTNAME;
 
964
                if (!strcasecmp (atom + 1, "elp"))
 
965
                        return TOKEN_HELP;
 
966
                break;
 
967
              case 'i':
 
968
                if (!strcasecmp(atom+1, "a-na")) 
 
969
                        return IA_NA;
 
970
                if (!strcasecmp(atom+1, "a-ta")) 
 
971
                        return IA_TA;
 
972
                if (!strcasecmp(atom+1, "a-pd")) 
 
973
                        return IA_PD;
 
974
                if (!strcasecmp(atom+1, "aaddr")) 
 
975
                        return IAADDR;
 
976
                if (!strcasecmp(atom+1, "aprefix")) 
 
977
                        return IAPREFIX;
 
978
                if (!strcasecmp (atom + 1, "nclude"))
 
979
                        return INCLUDE;
 
980
                if (!strcasecmp (atom + 1, "nteger"))
 
981
                        return INTEGER;
 
982
                if (!strcasecmp (atom + 1, "nfinite"))
 
983
                        return INFINITE;
 
984
                if (!strcasecmp (atom + 1, "nfo"))
 
985
                        return INFO;
 
986
                if (!strcasecmp (atom + 1, "p-address"))
 
987
                        return IP_ADDRESS;
 
988
                if (!strcasecmp (atom + 1, "p6-address"))
 
989
                        return IP6_ADDRESS;
 
990
                if (!strcasecmp (atom + 1, "nitial-interval"))
 
991
                        return INITIAL_INTERVAL;
 
992
                if (!strcasecmp (atom + 1, "nterface"))
 
993
                        return INTERFACE;
 
994
                if (!strcasecmp (atom + 1, "dentifier"))
 
995
                        return IDENTIFIER;
 
996
                if (!strcasecmp (atom + 1, "f"))
 
997
                        return IF;
 
998
                if (!strcasecmp (atom + 1, "s"))
 
999
                        return IS;
 
1000
                if (!strcasecmp (atom + 1, "gnore"))
 
1001
                        return IGNORE;
 
1002
                break;
 
1003
              case 'k':
 
1004
                if (!strncasecmp (atom + 1, "nown", 4)) {
 
1005
                        if (!strcasecmp (atom + 5, "-clients"))
 
1006
                                return KNOWN_CLIENTS;
 
1007
                        if (!atom[5])
 
1008
                                return KNOWN;
 
1009
                        break;
 
1010
                }
 
1011
                if (!strcasecmp (atom + 1, "ey"))
 
1012
                        return KEY;
 
1013
                break;
 
1014
              case 'l':
 
1015
                if (!strcasecmp (atom + 1, "case"))
 
1016
                        return LCASE;
 
1017
                if (!strcasecmp (atom + 1, "ease"))
 
1018
                        return LEASE;
 
1019
                if (!strcasecmp(atom + 1, "ease6"))
 
1020
                        return LEASE6;
 
1021
                if (!strcasecmp (atom + 1, "eased-address"))
 
1022
                        return LEASED_ADDRESS;
 
1023
                if (!strcasecmp (atom + 1, "ease-time"))
 
1024
                        return LEASE_TIME;
 
1025
                if (!strcasecmp(atom + 1, "easequery"))
 
1026
                        return LEASEQUERY;
 
1027
                if (!strcasecmp(atom + 1, "ength"))
 
1028
                        return LENGTH;
 
1029
                if (!strcasecmp (atom + 1, "imit"))
 
1030
                        return LIMIT;
 
1031
                if (!strcasecmp (atom + 1, "et"))
 
1032
                        return LET;
 
1033
                if (!strcasecmp (atom + 1, "oad"))
 
1034
                        return LOAD;
 
1035
                if (!strcasecmp(atom + 1, "ocal"))
 
1036
                        return LOCAL;
 
1037
                if (!strcasecmp (atom + 1, "og"))
 
1038
                        return LOG;
 
1039
                if (!strcasecmp(atom+1, "lt")) {
 
1040
                        return LLT;
 
1041
                }
 
1042
                if (!strcasecmp(atom+1, "l")) {
 
1043
                        return LL;
 
1044
                }
 
1045
                break;
 
1046
              case 'm':
 
1047
                if (!strncasecmp (atom + 1, "ax", 2)) {
 
1048
                        if (!atom [3])
 
1049
                                return TOKEN_MAX;
 
1050
                        if (!strcasecmp (atom + 3, "-balance"))
 
1051
                                return MAX_BALANCE;
 
1052
                        if (!strncasecmp (atom + 3, "-lease-", 7)) {
 
1053
                                if (!strcasecmp(atom + 10, "misbalance"))
 
1054
                                        return MAX_LEASE_MISBALANCE;
 
1055
                                if (!strcasecmp(atom + 10, "ownership"))
 
1056
                                        return MAX_LEASE_OWNERSHIP;
 
1057
                                if (!strcasecmp(atom + 10, "time"))
 
1058
                                        return MAX_LEASE_TIME;
 
1059
                        }
 
1060
                        if (!strcasecmp(atom + 3, "-life"))
 
1061
                                return MAX_LIFE;
 
1062
                        if (!strcasecmp (atom + 3, "-transmit-idle"))
 
1063
                                return MAX_TRANSMIT_IDLE;
 
1064
                        if (!strcasecmp (atom + 3, "-response-delay"))
 
1065
                                return MAX_RESPONSE_DELAY;
 
1066
                        if (!strcasecmp (atom + 3, "-unacked-updates"))
 
1067
                                return MAX_UNACKED_UPDATES;
 
1068
                }
 
1069
                if (!strncasecmp (atom + 1, "in-", 3)) {
 
1070
                        if (!strcasecmp (atom + 4, "balance"))
 
1071
                                return MIN_BALANCE;
 
1072
                        if (!strcasecmp (atom + 4, "lease-time"))
 
1073
                                return MIN_LEASE_TIME;
 
1074
                        if (!strcasecmp (atom + 4, "secs"))
 
1075
                                return MIN_SECS;
 
1076
                        break;
 
1077
                }
 
1078
                if (!strncasecmp (atom + 1, "edi", 3)) {
 
1079
                        if (!strcasecmp (atom + 4, "a"))
 
1080
                                return MEDIA;
 
1081
                        if (!strcasecmp (atom + 4, "um"))
 
1082
                                return MEDIUM;
 
1083
                        break;
 
1084
                }
 
1085
                if (!strcasecmp (atom + 1, "atch"))
 
1086
                        return MATCH;
 
1087
                if (!strcasecmp (atom + 1, "embers"))
 
1088
                        return MEMBERS;
 
1089
                if (!strcasecmp (atom + 1, "y"))
 
1090
                        return MY;
 
1091
                if (!strcasecmp (atom + 1, "clt"))
 
1092
                        return MCLT;
 
1093
                break;
 
1094
              case 'n':
 
1095
                if (!strcasecmp (atom + 1, "ormal"))
 
1096
                        return NORMAL;
 
1097
                if (!strcasecmp (atom + 1, "ameserver"))
 
1098
                        return NAMESERVER;
 
1099
                if (!strcasecmp (atom + 1, "etmask"))
 
1100
                        return NETMASK;
 
1101
                if (!strcasecmp (atom + 1, "ever"))
 
1102
                        return NEVER;
 
1103
                if (!strcasecmp (atom + 1, "ext-server"))
 
1104
                        return NEXT_SERVER;
 
1105
                if (!strcasecmp (atom + 1, "ot"))
 
1106
                        return TOKEN_NOT;
 
1107
                if (!strcasecmp (atom + 1, "o"))
 
1108
                        return TOKEN_NO;
 
1109
                if (!strcasecmp (atom + 1, "s-update"))
 
1110
                        return NS_UPDATE;
 
1111
                if (!strcasecmp (atom + 1, "oerror"))
 
1112
                        return NS_NOERROR;
 
1113
                if (!strcasecmp (atom + 1, "otauth"))
 
1114
                        return NS_NOTAUTH;
 
1115
                if (!strcasecmp (atom + 1, "otimp"))
 
1116
                        return NS_NOTIMP;
 
1117
                if (!strcasecmp (atom + 1, "otzone"))
 
1118
                        return NS_NOTZONE;
 
1119
                if (!strcasecmp (atom + 1, "xdomain"))
 
1120
                        return NS_NXDOMAIN;
 
1121
                if (!strcasecmp (atom + 1, "xrrset"))
 
1122
                        return NS_NXRRSET;
 
1123
                if (!strcasecmp (atom + 1, "ull"))
 
1124
                        return TOKEN_NULL;
 
1125
                if (!strcasecmp (atom + 1, "ext"))
 
1126
                        return TOKEN_NEXT;
 
1127
                if (!strcasecmp (atom + 1, "ew"))
 
1128
                        return TOKEN_NEW;
 
1129
                break;
 
1130
              case 'o':
 
1131
                if (!strcasecmp (atom + 1, "mapi"))
 
1132
                        return OMAPI;
 
1133
                if (!strcasecmp (atom + 1, "r"))
 
1134
                        return OR;
 
1135
                if (!strcasecmp (atom + 1, "n"))
 
1136
                        return ON;
 
1137
                if (!strcasecmp (atom + 1, "pen"))
 
1138
                        return TOKEN_OPEN;
 
1139
                if (!strcasecmp (atom + 1, "ption"))
 
1140
                        return OPTION;
 
1141
                if (!strcasecmp (atom + 1, "ne-lease-per-client"))
 
1142
                        return ONE_LEASE_PER_CLIENT;
 
1143
                if (!strcasecmp (atom + 1, "f"))
 
1144
                        return OF;
 
1145
                if (!strcasecmp (atom + 1, "wner"))
 
1146
                        return OWNER;
 
1147
                break;
 
1148
              case 'p':
 
1149
                if (!strcasecmp (atom + 1, "repend"))
 
1150
                        return PREPEND;
 
1151
                if (!strcasecmp(atom + 1, "referred-life"))
 
1152
                        return PREFERRED_LIFE;
 
1153
                if (!strcasecmp (atom + 1, "acket"))
 
1154
                        return PACKET;
 
1155
                if (!strcasecmp (atom + 1, "ool"))
 
1156
                        return POOL;
 
1157
                if (!strcasecmp (atom + 1, "refix6"))
 
1158
                        return PREFIX6;
 
1159
                if (!strcasecmp (atom + 1, "seudo"))
 
1160
                        return PSEUDO;
 
1161
                if (!strcasecmp (atom + 1, "eer"))
 
1162
                        return PEER;
 
1163
                if (!strcasecmp (atom + 1, "rimary"))
 
1164
                        return PRIMARY;
 
1165
                if (!strncasecmp (atom + 1, "artner", 6)) {
 
1166
                        if (!atom [7])
 
1167
                                return PARTNER;
 
1168
                        if (!strcasecmp (atom + 7, "-down"))
 
1169
                                return PARTNER_DOWN;
 
1170
                }
 
1171
                if (!strcasecmp (atom + 1, "ort"))
 
1172
                        return PORT;
 
1173
                if (!strcasecmp (atom + 1, "otential-conflict"))
 
1174
                        return POTENTIAL_CONFLICT;
 
1175
                if (!strcasecmp (atom + 1, "ick-first-value") ||
 
1176
                    !strcasecmp (atom + 1, "ick"))
 
1177
                        return PICK;
 
1178
                if (!strcasecmp (atom + 1, "aused"))
 
1179
                        return PAUSED;
 
1180
                break;
 
1181
              case 'r':
 
1182
                if (!strcasecmp (atom + 1, "esolution-interrupted"))
 
1183
                        return RESOLUTION_INTERRUPTED;
 
1184
                if (!strcasecmp (atom + 1, "ange"))
 
1185
                        return RANGE;
 
1186
                if (!strcasecmp(atom + 1, "ange6")) {
 
1187
                        return RANGE6;
 
1188
                }
 
1189
                if (!strcasecmp (atom + 1, "ecover"))
 
1190
                        return RECOVER;
 
1191
                if (!strcasecmp (atom + 1, "ecover-done"))
 
1192
                        return RECOVER_DONE;
 
1193
                if (!strcasecmp (atom + 1, "ecover-wait"))
 
1194
                        return RECOVER_WAIT;
 
1195
                if (!strcasecmp (atom + 1, "econtact-interval"))
 
1196
                        return RECONTACT_INTERVAL;
 
1197
                if (!strcasecmp (atom + 1, "equest"))
 
1198
                        return REQUEST;
 
1199
                if (!strcasecmp (atom + 1, "equire"))
 
1200
                        return REQUIRE;
 
1201
                if (!strcasecmp (atom + 1, "equire"))
 
1202
                        return REQUIRE;
 
1203
                if (!strcasecmp (atom + 1, "etry"))
 
1204
                        return RETRY;
 
1205
                if (!strcasecmp (atom + 1, "eturn"))
 
1206
                        return RETURN;
 
1207
                if (!strcasecmp (atom + 1, "enew"))
 
1208
                        return RENEW;
 
1209
                if (!strcasecmp (atom + 1, "ebind"))
 
1210
                        return REBIND;
 
1211
                if (!strcasecmp (atom + 1, "eboot"))
 
1212
                        return REBOOT;
 
1213
                if (!strcasecmp (atom + 1, "eject"))
 
1214
                        return REJECT;
 
1215
                if (!strcasecmp (atom + 1, "everse"))
 
1216
                        return REVERSE;
 
1217
                if (!strcasecmp (atom + 1, "elease"))
 
1218
                        return RELEASE;
 
1219
                if (!strcasecmp (atom + 1, "efused"))
 
1220
                        return NS_REFUSED;
 
1221
                if (!strcasecmp (atom + 1, "eleased"))
 
1222
                        return TOKEN_RELEASED;
 
1223
                if (!strcasecmp (atom + 1, "eset"))
 
1224
                        return TOKEN_RESET;
 
1225
                if (!strcasecmp (atom + 1, "eserved"))
 
1226
                        return TOKEN_RESERVED;
 
1227
                if (!strcasecmp (atom + 1, "emove"))
 
1228
                        return REMOVE;
 
1229
                if (!strcasecmp (atom + 1, "efresh"))
 
1230
                        return REFRESH;
 
1231
                break;
 
1232
              case 's':
 
1233
                if (!strcasecmp(atom + 1, "cript"))
 
1234
                        return SCRIPT;
 
1235
                if (isascii(atom[1]) && 
 
1236
                    tolower((unsigned char)atom[1]) == 'e') {
 
1237
                        if (!strcasecmp(atom + 2, "arch"))
 
1238
                                return SEARCH;
 
1239
                        if (isascii(atom[2]) && 
 
1240
                            tolower((unsigned char)atom[2]) == 'c') {
 
1241
                                if (!strncasecmp(atom + 3, "ond", 3)) {
 
1242
                                        if (!strcasecmp(atom + 6, "ary"))
 
1243
                                                return SECONDARY;
 
1244
                                        if (!strcasecmp(atom + 6, "s"))
 
1245
                                                return SECONDS;
 
1246
                                        break;
 
1247
                                }
 
1248
                                if (!strcasecmp(atom + 3, "ret"))
 
1249
                                        return SECRET;
 
1250
                                break;
 
1251
                        }
 
1252
                        if (!strncasecmp(atom + 2, "lect", 4)) {
 
1253
                                if (atom[6] == '\0')
 
1254
                                        return SELECT;
 
1255
                                if (!strcasecmp(atom + 6, "-timeout"))
 
1256
                                        return SELECT_TIMEOUT;
 
1257
                                break;
 
1258
                        }
 
1259
                        if (!strcasecmp(atom + 2, "nd"))
 
1260
                                return SEND;
 
1261
                        if (!strncasecmp(atom + 2, "rv", 2)) {
 
1262
                                if (!strncasecmp(atom + 4, "er", 2)) {
 
1263
                                        if (atom[6] == '\0')
 
1264
                                                return TOKEN_SERVER;
 
1265
                                        if (atom[6] == '-') {
 
1266
                                                if (!strcasecmp(atom + 7,
 
1267
                                                                "duid")) 
 
1268
                                                        return SERVER_DUID;
 
1269
                                                if (!strcasecmp(atom + 7,
 
1270
                                                                "name"))
 
1271
                                                        return SERVER_NAME;
 
1272
                                                if (!strcasecmp(atom + 7,
 
1273
                                                                "identifier"))
 
1274
                                                      return SERVER_IDENTIFIER;
 
1275
                                                break;
 
1276
                                        }
 
1277
                                        break;
 
1278
                                }
 
1279
                                if (!strcasecmp(atom + 4, "fail"))
 
1280
                                        return NS_SERVFAIL;
 
1281
                                break;
 
1282
                        }
 
1283
                        if (!strcasecmp(atom + 2, "t"))
 
1284
                                return TOKEN_SET;
 
1285
                        break;
 
1286
                }
 
1287
                if (isascii(atom[1]) && 
 
1288
                    tolower((unsigned char)atom[1]) == 'h') {
 
1289
                        if (!strcasecmp(atom + 2, "ared-network"))
 
1290
                                return SHARED_NETWORK;
 
1291
                        if (!strcasecmp(atom + 2, "utdown"))
 
1292
                                return SHUTDOWN;
 
1293
                        break;
 
1294
                }
 
1295
                if (isascii(atom[1]) && 
 
1296
                    tolower((unsigned char)atom[1]) == 'i') {
 
1297
                        if (!strcasecmp(atom + 2, "addr"))
 
1298
                                return SIADDR;
 
1299
                        if (!strcasecmp(atom + 2, "gned"))
 
1300
                                return SIGNED;
 
1301
                        if (!strcasecmp(atom + 2, "ze"))
 
1302
                                return SIZE;
 
1303
                        break;
 
1304
                }
 
1305
                if (isascii(atom[1]) && 
 
1306
                    tolower((unsigned char)atom[1]) == 'p') {
 
1307
                        if (isascii(atom[2]) && 
 
1308
                            tolower((unsigned char)atom[2]) == 'a') {
 
1309
                                if (!strcasecmp(atom + 3, "ce"))
 
1310
                                        return SPACE;
 
1311
                                if (!strcasecmp(atom + 3, "wn"))
 
1312
                                        return SPAWN;
 
1313
                                break;
 
1314
                        }
 
1315
                        if (!strcasecmp(atom + 2, "lit"))
 
1316
                                return SPLIT;
 
1317
                        break;
 
1318
                }
 
1319
                if (isascii(atom[1]) && 
 
1320
                    tolower((unsigned char)atom[1]) == 't') {
 
1321
                        if (isascii(atom[2]) && 
 
1322
                            tolower((unsigned char)atom[2]) == 'a') {
 
1323
                                if(!strncasecmp(atom + 3, "rt", 2)) {
 
1324
                                         if (!strcasecmp(atom + 5, "s"))
 
1325
                                                 return STARTS;
 
1326
                                         if (!strcasecmp(atom + 5, "up"))
 
1327
                                                 return STARTUP;
 
1328
                                        break;
 
1329
                                }
 
1330
                                if (isascii(atom[3]) &&
 
1331
                                    tolower((unsigned char)atom[3]) == 't') {
 
1332
                                        if (!strcasecmp(atom + 4, "e"))
 
1333
                                                return STATE;
 
1334
                                        if (!strcasecmp(atom + 4, "ic"))
 
1335
                                                return STATIC;
 
1336
                                        break;
 
1337
                                }
 
1338
                        }
 
1339
                        if (!strcasecmp(atom + 2, "ring"))
 
1340
                                return STRING_TOKEN;
 
1341
                        break;
 
1342
                }
 
1343
                if (!strncasecmp(atom + 1, "ub", 2)) {
 
1344
                        if (!strcasecmp(atom + 3, "class"))
 
1345
                                return SUBCLASS;
 
1346
                        if (!strcasecmp(atom + 3, "net"))
 
1347
                                return SUBNET;
 
1348
                        if (!strcasecmp(atom + 3, "net6"))
 
1349
                                return SUBNET6;
 
1350
                        if (!strcasecmp(atom + 3, "string"))
 
1351
                                return SUBSTRING;
 
1352
                        break;
 
1353
                }
 
1354
                if (isascii(atom[1]) && 
 
1355
                    tolower((unsigned char)atom[1]) == 'u') {
 
1356
                        if (!strcasecmp(atom + 2, "ffix"))
 
1357
                                return SUFFIX;
 
1358
                        if (!strcasecmp(atom + 2, "persede"))
 
1359
                                return SUPERSEDE;
 
1360
                }
 
1361
                if (!strcasecmp(atom + 1, "witch"))
 
1362
                        return SWITCH;
 
1363
                break;
 
1364
              case 't':
 
1365
                if (!strcasecmp (atom + 1, "imestamp"))
 
1366
                        return TIMESTAMP;
 
1367
                if (!strcasecmp (atom + 1, "imeout"))
 
1368
                        return TIMEOUT;
 
1369
                if (!strcasecmp (atom + 1, "oken-ring"))
 
1370
                        return TOKEN_RING;
 
1371
                if (!strcasecmp (atom + 1, "ext"))
 
1372
                        return TEXT;
 
1373
                if (!strcasecmp (atom + 1, "stp"))
 
1374
                        return TSTP;
 
1375
                if (!strcasecmp (atom + 1, "sfp"))
 
1376
                        return TSFP;
 
1377
                if (!strcasecmp (atom + 1, "ransmission"))
 
1378
                        return TRANSMISSION;
 
1379
                if (!strcasecmp(atom + 1, "emporary"))
 
1380
                        return TEMPORARY;
 
1381
                break;
 
1382
              case 'u':
 
1383
                if (!strcasecmp (atom + 1, "case"))
 
1384
                        return UCASE;
 
1385
                if (!strcasecmp (atom + 1, "nset"))
 
1386
                        return UNSET;
 
1387
                if (!strcasecmp (atom + 1, "nsigned"))
 
1388
                        return UNSIGNED;
 
1389
                if (!strcasecmp (atom + 1, "id"))
 
1390
                        return UID;
 
1391
                if (!strncasecmp (atom + 1, "se", 2)) {
 
1392
                        if (!strcasecmp (atom + 3, "r-class"))
 
1393
                                return USER_CLASS;
 
1394
                        if (!strcasecmp (atom + 3, "-host-decl-names"))
 
1395
                                return USE_HOST_DECL_NAMES;
 
1396
                        if (!strcasecmp (atom + 3,
 
1397
                                         "-lease-addr-for-default-route"))
 
1398
                                return USE_LEASE_ADDR_FOR_DEFAULT_ROUTE;
 
1399
                        break;
 
1400
                }
 
1401
                if (!strncasecmp (atom + 1, "nknown", 6)) {
 
1402
                        if (!strcasecmp (atom + 7, "-clients"))
 
1403
                                return UNKNOWN_CLIENTS;
 
1404
                        if (!strcasecmp (atom + 7, "-state"))
 
1405
                                return UNKNOWN_STATE;
 
1406
                        if (!atom [7])
 
1407
                                return UNKNOWN;
 
1408
                        break;
 
1409
                }
 
1410
                if (!strcasecmp (atom + 1, "nauthenticated"))
 
1411
                        return UNAUTHENTICATED;
 
1412
                if (!strcasecmp (atom + 1, "pdated-dns-rr"))
 
1413
                        return UPDATED_DNS_RR;
 
1414
                if (!strcasecmp (atom + 1, "pdate"))
 
1415
                        return UPDATE;
 
1416
                break;
 
1417
              case 'v':
 
1418
                if (!strcasecmp (atom + 1, "endor-class"))
 
1419
                        return VENDOR_CLASS;
 
1420
                if (!strcasecmp (atom + 1, "endor"))
 
1421
                        return VENDOR;
 
1422
                break;
 
1423
              case 'w':
 
1424
                if (!strcasecmp (atom + 1, "ith"))
 
1425
                        return WITH;
 
1426
                if (!strcasecmp(atom + 1, "idth"))
 
1427
                        return WIDTH;
 
1428
                break;
 
1429
              case 'y':
 
1430
                if (!strcasecmp (atom + 1, "iaddr"))
 
1431
                        return YIADDR;
 
1432
                if (!strcasecmp (atom + 1, "xdomain"))
 
1433
                        return NS_YXDOMAIN;
 
1434
                if (!strcasecmp (atom + 1, "xrrset"))
 
1435
                        return NS_YXRRSET;
 
1436
                break;
 
1437
              case 'z':
 
1438
                if (!strcasecmp (atom + 1, "erolen"))
 
1439
                        return ZEROLEN;
 
1440
                if (!strcasecmp (atom + 1, "one"))
 
1441
                        return ZONE;
 
1442
                break;
 
1443
        }
 
1444
        return dfv;
 
1445
}