Annotation of embedaddon/dhcp/common/conflex.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>